import { useQuery } from '@tanstack/react-query'; import { useState } from 'react'; import { Notice } from '#/components/atoms/notice.jsx'; import { Panel } from '#/components/atoms/panel.jsx'; import { ErrorNotice } from '#/components/molecules/error-notice.jsx'; import { Section } from '#/components/molecules/section.jsx'; import { SelectField } from '#/components/molecules/select-field.jsx'; import { TextLink } from '#/components/molecules/text-link.jsx'; import { get, post } from '#/lib/api.js'; import { queryKeys, useApiMutation } from '#/lib/query.js'; /** * The update page for this deployment, with this server's hostname, worker * script name and release channel carried along so the page can find the * worker and install from the channel this server follows. * @param {string} updateUrl * @param {{scriptName?: string|null, channel?: string}} [version] */ export function updateHref(updateUrl, version = {}) { const url = new URL(updateUrl); url.searchParams.set('host', window.location.host); if (version.scriptName) url.searchParams.set('script', version.scriptName); if (version.channel === 'canary') url.searchParams.set('channel', 'canary'); return url.toString(); } const CHANNELS = [ ['stable', 'Stable releases'], ['canary', 'Canary builds'], ]; /** * The pds.js release this server runs, whether a newer one is published, and * which release channel the check follows. The server does the lookup and * caches it, so rendering this card costs one same-origin request. * Installing a release is a redeploy of the server: with an update page * configured the card links there, and without one it names the release and * leaves the redeploy to the operator. * @param {{data: {features: {settings: boolean}}}} props */ export function VersionCard({ data: overview }) { const { data } = useQuery({ queryKey: queryKeys.version, queryFn: () => get('/version'), }); const canStore = overview.features.settings; const { run, busy, error } = useApiMutation([queryKeys.version]); const [pending, setPending] = useState(null); const channel = pending ?? data?.channel ?? 'stable'; const changeChannel = (next) => { const previous = channel; setPending(next); run(async () => { try { await post('/settings/release-channel', { channel: next }); } catch (err) { setPending(previous); throw err; } }); }; let status; if (!data) { status = (
Checking for the latest release.
); } else if (data.updateAvailable) { status = ({data.channel === 'canary' ? 'This is the newest canary build.' : 'This is the latest release.'}
); } else { status = (The release registry could not be reached. Checking again later.
); } return ({data ? `Version ${data.current}` : ' '}
{status}Canary follows the newest build of the main branch. It changes often and gets less testing than a release.
)} {!canStore && (This server does not store settings.
)}