From 8b63fdd30e45ffea999bec21cfd74ba107733519 Mon Sep 17 00:00:00 2001 From: ematipico Date: Wed, 4 Nov 2026 11:23:24 +0000 Subject: [PATCH] fix: render cf CLI samples from the cf CLI's command metadata MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The cf CLI sample of an operation was guessed from its path parameters: every path parameter became a positional, including `account_id`, and operations with a request body or a required query parameter got no sample at all. So `cf agent-memory recall` had no sample, and `cf agent-memory get-memory` showed ` ` instead of ` --namespace-name … --profile-name …`. The sample now comes from `dist/_meta/commands.json` in the cf package, the metadata `cf --help` is built from: the command that sends the operation, its required positionals, then its required options. Hand-written commands are left out, as the site documents them separately. cf is bumped to 1.0.0-beta.27, whose metadata the tests check against. --- packages/cloudflare-api-site/package.json | 2 +- .../cloudflare-api-site/src/cli-arguments.ts | 79 +++++++++++ .../src/cloudflare.test.ts | 58 ++++++-- .../cloudflare-api-site/src/cloudflare.ts | 18 ++- pnpm-lock.yaml | 125 +++++++++++------- 5 files changed, 220 insertions(+), 62 deletions(-) create mode 100644 packages/cloudflare-api-site/src/cli-arguments.ts diff --git a/packages/cloudflare-api-site/package.json b/packages/cloudflare-api-site/package.json index 6fa706588..0fc7a4566 100644 --- a/packages/cloudflare-api-site/package.json +++ b/packages/cloudflare-api-site/package.json @@ -23,7 +23,7 @@ "@iconify-json/simple-icons": "^1.2.99", "astro": "^7.4.1", "astro-fern": "workspace:*", - "cf": "1.0.0-beta.19", + "cf": "1.0.0-beta.27", "clsx": "^2.1.1", "fern-forge": "workspace:*", "hast-util-sanitize": "^5.0.2", diff --git a/packages/cloudflare-api-site/src/cli-arguments.ts b/packages/cloudflare-api-site/src/cli-arguments.ts new file mode 100644 index 000000000..1f2ec7f92 --- /dev/null +++ b/packages/cloudflare-api-site/src/cli-arguments.ts @@ -0,0 +1,79 @@ +import { readFileSync } from 'node:fs'; +import { createRequire } from 'node:module'; +import { dirname, join } from 'node:path'; + +/** A positional or an option of a cf command. */ +export interface CliArgument { + name: string; + /** The position of a positional. */ + position?: number; + type: 'string' | 'number' | 'boolean'; + required: boolean; +} + +/** A command of the cf CLI, as its metadata describes it. */ +export interface CliCommand { + /** The command, such as `cf agent-memory recall`. */ + command: string; + /** The words after `cf`, such as `["agent-memory", "recall"]`. */ + fullPath: string[]; + /** The HTTP method of the operation it sends, in uppercase. */ + httpMethod?: string; + /** The path template of the operation it sends. */ + apiPath?: string; + /** The positionals. */ + arguments?: CliArgument[]; + options?: CliArgument[]; +} + +interface CliMetadata { + commands: CliCommand[]; +} + +// The cf package doesn't export its metadata, so it is read from the +// package's directory: `dist/_meta/commands.json` lists every command with the +// positionals and options `cf --help` shows. +function readCliMetadata(file: string): CliMetadata { + const packageJson = createRequire(import.meta.url).resolve('cf/package.json'); + return JSON.parse(readFileSync(join(dirname(packageJson), 'dist', '_meta', file), 'utf8')) as CliMetadata; +} + +const operationKey = (method: string, path: string): string => `${method.toUpperCase()} ${path}`; + +let byOperation: Map | undefined; + +/** + * The commands cf generates from the API, by the operation they send. + * Hand-written commands are left out: the site documents them separately. + */ +function commandsByOperation(): Map { + if (byOperation) return byOperation; + const handWritten = new Set(readCliMetadata('hand-written-commands.json').commands.map((c) => c.command)); + byOperation = new Map(); + for (const command of readCliMetadata('commands.json').commands) { + if (!command.httpMethod || !command.apiPath || handWritten.has(command.command)) continue; + const key = operationKey(command.httpMethod, command.apiPath); + byOperation.set(key, [...(byOperation.get(key) ?? []), command]); + } + return byOperation; +} + +// The site's accessor paths and method names are the operation's SDK names, +// which cf turns into kebab-case. +const comparable = (words: readonly string[]): string => + words + .join('') + .replace(/[^A-Za-z0-9]/g, '') + .toLowerCase(); + +/** + * Returns the cf command that sends the operation `method` `path`, or + * `undefined` when cf generates none. When several commands send the + * operation, returns the one named `words`, or else the first. + */ +export function cliCommandFor(method: string, path: string, words: readonly string[]): CliCommand | undefined { + const commands = commandsByOperation().get(operationKey(method, path)); + if (!commands) return undefined; + const wanted = comparable(words); + return commands.find((command) => comparable(command.fullPath) === wanted) ?? commands[0]; +} diff --git a/packages/cloudflare-api-site/src/cloudflare.test.ts b/packages/cloudflare-api-site/src/cloudflare.test.ts index e0ffbf216..1e83889b2 100644 --- a/packages/cloudflare-api-site/src/cloudflare.test.ts +++ b/packages/cloudflare-api-site/src/cloudflare.test.ts @@ -229,10 +229,8 @@ test('optional request bodies remain present in examples when the endpoint decla }; const snippets = cloudflareSnippetsByTarget(optionalInput); const curl = snippets.get('curl'); - const cf = snippets.get('cf'); const ts = snippets.get('typescript'); assert.ok(curl && ts); - assert.equal(cf, null); assert.match(curl, /Content-Type: application\/json/); assert.match(curl, /-d /); assert.match(ts, /name: ""/); @@ -295,7 +293,7 @@ test('curl uses file input for raw bodies and does not fabricate required multip const rawSnippets = cloudflareSnippetsByTarget(raw); assert.match(rawSnippets.get('curl') ?? '', /Content-Type: application\/octet-stream/); assert.match(rawSnippets.get('curl') ?? '', /--data-binary @request-body/); - for (const target of ['cf', 'typescript', 'python', 'ruby']) assert.equal(rawSnippets.get(target), null); + for (const target of ['typescript', 'python', 'ruby']) assert.equal(rawSnippets.get(target), null); assert.equal(cloudflareSnippetsByTarget(multipart).get('curl'), null); }); @@ -435,13 +433,57 @@ test('typescript: normalizes hyphenated Fern group and method names to lower cam assert.match(ts ?? '', /client\.dns\.zoneTransfers\.primaryZones\.forceNotify\(/); }); -test('cf: positionals are the path params', () => { - assert.equal(cloudflareSnippetsByTarget(listInput).get('cf'), 'cf dns records list '); +// The cf samples come from the metadata of the cf package the site depends on. + +test('cf: renders the command with the positionals and options it requires', () => { + const recall: SnippetInput = { + op: op({ + path: '/accounts/{account_id}/agent-memory/namespaces/{namespace_name}/profiles/{profile_name}/recall', + method: 'post', + }), + accessorPath: ['agent-memory'], + methodName: 'recall', + }; + assert.equal( + cloudflareSnippetsByTarget(recall).get('cf'), + ['cf agent-memory recall ', '--namespace-name ', '--query '].join(' \\\n '), + ); + // The zone is passed with the global --zone option, which samples leave out. + assert.equal(cloudflareSnippetsByTarget(listInput).get('cf'), 'cf dns records list'); +}); + +test('cf: renders required boolean options without a value', () => { + const edit: SnippetInput = { + op: op({ path: '/zones/{zone_id}/acm/total_tls', method: 'post' }), + accessorPath: ['acm', 'total-tls'], + methodName: 'edit', + }; + assert.equal(cloudflareSnippetsByTarget(edit).get('cf'), 'cf acm total-tls edit \\\n --enabled'); +}); + +test('cf: renders nothing for operations without a generated cf command', () => { + const unknown: SnippetInput = { ...listInput, op: op({ path: '/zones/{zone_id}/unknown' }) }; + assert.equal(cloudflareSnippetsByTarget(unknown).get('cf'), null); + // `cf ai run` is hand-written: the site documents hand-written commands separately. + const aiRun: SnippetInput = { + op: op({ path: '/accounts/{account_id}/ai/run', method: 'post' }), + accessorPath: ['ai'], + methodName: 'run', + }; + assert.equal(cloudflareSnippetsByTarget(aiRun).get('cf'), null); }); -test('cf: omits commands that require unsupported flags or request bodies', () => { - assert.equal(cloudflareSnippetsByTarget(queryInput).get('cf'), null); - assert.equal(cloudflareSnippetsByTarget(createInput).get('cf'), null); +test('cf: renders the command named like the operation when several send it', () => { + const status = (methodName: string): SnippetInput => ({ + op: op({ + path: '/accounts/{account_id}/workflows/{workflow_name}/instances/{instance_id}/status', + method: 'patch', + }), + accessorPath: ['workflows', 'instances'], + methodName, + }); + assert.match(cloudflareSnippetsByTarget(status('terminate')).get('cf') ?? '', /^cf workflows instances terminate /); + assert.match(cloudflareSnippetsByTarget(status('pause')).get('cf') ?? '', /^cf workflows instances pause /); }); test('python: snake_cased accessor with keyword args', () => { diff --git a/packages/cloudflare-api-site/src/cloudflare.ts b/packages/cloudflare-api-site/src/cloudflare.ts index 100ad3dd8..caeded74f 100644 --- a/packages/cloudflare-api-site/src/cloudflare.ts +++ b/packages/cloudflare-api-site/src/cloudflare.ts @@ -10,6 +10,7 @@ * This module has no Astro/runtime dependencies, so its behaviour is unit-tested * with `node --experimental-strip-types --test` (see `cloudflare.test.ts`). */ +import { cliCommandFor } from './cli-arguments.ts'; import { createSnippetProvider, type FernOperationRoutingPreferenceContext, @@ -233,10 +234,21 @@ const renderCurl: SnippetRenderer = ({ op }) => { return args.join(' \\\n '); }; +// The sample is the cf command that sends the operation, with the positionals +// and options it requires, as the cf CLI's own metadata lists them. const renderCf: SnippetRenderer = ({ accessorPath, methodName, op }) => { - if (op.requestBody || op.queryParams.some((param) => param.required)) return null; - const positionals = op.pathParams.map((param) => `<${param.name}>`).join(' '); - return ['cf', ...accessorPath, methodName, positionals].filter(Boolean).join(' '); + const command = cliCommandFor(op.method, op.path, [...accessorPath, methodName]); + if (!command) return null; + const head = [command.command]; + for (const positional of [...(command.arguments ?? [])].sort((a, b) => (a.position ?? 0) - (b.position ?? 0))) { + if (positional.required) head.push(`<${positional.name}>`); + } + const lines = [head.join(' ')]; + for (const option of command.options ?? []) { + if (option.required) + lines.push(option.type === 'boolean' ? `--${option.name}` : `--${option.name} <${option.name}>`); + } + return lines.join(' \\\n '); }; const renderTypeScript: SnippetRenderer = ({ op, accessorPath, methodName }) => { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1b3a6887c..9f76a5f3a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -204,7 +204,7 @@ importers: dependencies: '@astrojs/cloudflare': specifier: ^15.0.0-beta.2 - version: 15.0.0-beta.2(@types/node@26.0.1)(astro@7.4.1(@types/node@26.0.1)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.1))(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.22.4)(workerd@1.20261019.1)(yaml@2.9.1) + version: 15.0.0-beta.2(@types/node@26.0.1)(astro@7.4.1(@types/node@26.0.1)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.1))(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.22.4)(workerd@1.20261101.1)(yaml@2.9.1) '@astrojs/prism': specifier: ^4.0.2 version: 4.0.2 @@ -230,8 +230,8 @@ importers: specifier: workspace:* version: link:../astro-fern cf: - specifier: 1.0.0-beta.19 - version: 1.0.0-beta.19(@types/node@26.0.1) + specifier: 1.0.0-beta.27 + version: 1.0.0-beta.27(@types/node@26.0.1) clsx: specifier: ^2.1.1 version: 2.1.1 @@ -811,9 +811,15 @@ packages: '@cloudflare/build-output-utils@0.9.3': resolution: {integrity: sha512-0MgvIq6UxbRWLwB2QJU7qjLqpPkfygOebN3UiENhdp+z6zpRKrNnwkms2ynadmxCOh3sL2v+SI0/pNXxgXdteA==} + '@cloudflare/build-output-utils@0.9.7': + resolution: {integrity: sha512-bp2uexgnQp4W5w57oBdDfjzgyGvJAiKbfl6/73uiKVPMv0xHI0be98vfYUCKOBlXMNZ1PwWbNza1Ghbg9M6Bpw==} + '@cloudflare/config@0.27.0': resolution: {integrity: sha512-wNnL0z4lj5Gm2fze5qXTOvRPbUOi4jlMmwPk7ArCUakI5oVxgjfl3Rhnfd/Mmzo3g86x/ofH75yPIhsa5msqdQ==} + '@cloudflare/config@0.29.1': + resolution: {integrity: sha512-3wWliifIE9yLDp+56Y5iLT1a6fIjBVjkHpJ5Q48UpJwcGOrQ23cNppLlvjVSjxV4+S5gZEZwElLC1fwQ2hmOEQ==} + '@cloudflare/nimbus-docs@0.18.0': resolution: {integrity: sha512-rZXLcUM3Ule0sh6pppVKtclZpmFablyegzZ9SPaXtWIA+K0RjbYWkxRGzLzjilqOkLV3w51LsWSekP5ygYckeQ==} engines: {node: '>=22.12.0'} @@ -840,8 +846,8 @@ packages: '@cloudflare/runtime-types@0.1.12': resolution: {integrity: sha512-eYF5teHQ+Jss4sbSVINM5tNPHxo/kJ2gKcMs7omyy7gO9PEkgUbGPZCYl06SxbBWTcJFF2vrX4epB775QTE4BQ==} - '@cloudflare/runtime-types@0.1.13': - resolution: {integrity: sha512-k9UQ/ZPxvL0JQRFfXpnI2O5A+3O/m17+LckI3hRhMZRUrf7n4I7+a2JqN2WX4gGjVk+JeXS0msmtmoGhUDV1rg==} + '@cloudflare/runtime-types@0.1.20': + resolution: {integrity: sha512-m0m/MHEIiGAm9+RgKiSG/KDgTh8wJHNBYRFCBqtBUrnpirTdA3LwDuajOMZgu+sPcg5btccoecpXtVKQzcbsuQ==} '@cloudflare/unenv-preset@2.16.2': resolution: {integrity: sha512-JBP1+Z7ZSNG/d4mRP+y8VC5dka3tZVMLEZRvS+rzQ4DGV1EoxRFQckcJTTkXbHSQiTj0DtNI01Zwb/V2fX0mvQ==} @@ -864,8 +870,8 @@ packages: cpu: [x64] os: [darwin] - '@cloudflare/workerd-darwin-64@1.20261019.1': - resolution: {integrity: sha512-5ZILbAta/fBQvhmAYeCE7dKMMYIr7N9wJEX50fEGLKSIwGtvT0HzSfHNIK/O7cBQ4gHQ2WfIiPClvwcye6E0fA==} + '@cloudflare/workerd-darwin-64@1.20261101.1': + resolution: {integrity: sha512-9ByDS2X/lN1csRkU2qTsnogwVA/ghYGHybznujH/EStiv9qU+01XPKagm3Zrk8AN3yQrFTmjMy6BrZWzoa+B5Q==} engines: {node: '>=16'} cpu: [x64] os: [darwin] @@ -876,8 +882,8 @@ packages: cpu: [arm64] os: [darwin] - '@cloudflare/workerd-darwin-arm64@1.20261019.1': - resolution: {integrity: sha512-cww2Ab6lVMxpTiEEjKmPI58p5EMo0vYTZSH+3WkqXJdQgc3ES66GuL247+U2B2YWajhhu2tqj7jySrXneU749g==} + '@cloudflare/workerd-darwin-arm64@1.20261101.1': + resolution: {integrity: sha512-XNgl773dDMFecMG0mOtDgw15AIeRVn3yqbbUAqMVH6vgEf64F/J6Ej3FugQyogt+1NSjOx3pgEofbX7Cd9m0ug==} engines: {node: '>=16'} cpu: [arm64] os: [darwin] @@ -888,8 +894,8 @@ packages: cpu: [x64] os: [linux] - '@cloudflare/workerd-linux-64@1.20261019.1': - resolution: {integrity: sha512-4++VRi9vkQROYqrpZYOixIJuVDmujkwrT4kszsxNFlvcmsX6Mr2GumvxIN3gIixS3vJUh3Umdtkthqj5X0S3Xw==} + '@cloudflare/workerd-linux-64@1.20261101.1': + resolution: {integrity: sha512-8C9vM51UVrmpavIC7z6anMsKPu8tjvJcwA2tCvzlwfL7odoX61ngBpN7pkYrmrwv5iS9aJ4xEzQc8QkZJKIulw==} engines: {node: '>=16'} cpu: [x64] os: [linux] @@ -900,8 +906,8 @@ packages: cpu: [arm64] os: [linux] - '@cloudflare/workerd-linux-arm64@1.20261019.1': - resolution: {integrity: sha512-75PVtJOwfjScQ53sbLtQXI7D8yP1c21t+WEUPaYbqkzaz4ZqfR5wAd+zuWs8G5Q7kOj2SQIvEfY5Sn8Y+UVrnA==} + '@cloudflare/workerd-linux-arm64@1.20261101.1': + resolution: {integrity: sha512-7NdTrbzPubhEBNiC8ftD0U3J3M8fNR/ATD3Deon6C9Z5SFTmOhQbT3jJPMGPoUzvicdTaaD/YNCwRh+JEoWaeQ==} engines: {node: '>=16'} cpu: [arm64] os: [linux] @@ -912,8 +918,8 @@ packages: cpu: [x64] os: [win32] - '@cloudflare/workerd-windows-64@1.20261019.1': - resolution: {integrity: sha512-z49fvKTETMCnG6wnMcQwxx9CpryFceiKz04FRjq26EkhCyzRNJ6c3UXhyZz3r5f1CXnnBZc5DcU8ZouPkUJCqw==} + '@cloudflare/workerd-windows-64@1.20261101.1': + resolution: {integrity: sha512-nDRpV9VRhzdrNpJOJNfe6rjOTq5LXFGC6WFCeGR/LA+cNnou1fwF0AQm//zmSDOELPNoQFi6SqjUcloZvy1sKw==} engines: {node: '>=16'} cpu: [x64] os: [win32] @@ -2805,9 +2811,9 @@ packages: ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} - cf@1.0.0-beta.19: - resolution: {integrity: sha512-hFnYP15f7dRhmAXjy9+3DekbcR3Dr7vjRWA2W18nYpokEGmIUZdEHRjertzeFHphZgQkCi+ZImlFgP4JpNifYA==} - engines: {node: '>=22'} + cf@1.0.0-beta.27: + resolution: {integrity: sha512-RLE6vCsDwq64AKoUwNH6cQLbvbAf/9xChYf7By61cqFL9kHWrYAf4Er3L1vN4vPchCM3pgn2is3eabs/3d40tQ==} + engines: {node: ^22.23.0 || ^24.22.0 || ^26.12.0} hasBin: true character-entities-html4@2.1.0: @@ -3521,8 +3527,8 @@ packages: resolution: {integrity: sha512-8Canhy6g9+vAhqMc0o80YphqYIwpiA3aAp8aX+uDXU7J/qbUeoZzcII9c2V1P4uT/eHD4SB93qet1o1bRY3BuQ==} engines: {node: '>=22.0.0'} - miniflare@5.20261019.0-beta: - resolution: {integrity: sha512-NmE6Yz7MSdjrfr3lMaMAVO55rIm3+6YXllOkJOMy6pPQITDuDeo0PYRedp7pju2olNWmrAlf1i1LIWYfGQvvuw==} + miniflare@5.20261101.0-beta: + resolution: {integrity: sha512-31uZmP8PGue7S3fYMIRXNXxFGh5/SEmd4OGna/80RXcE1nngVub21h9GbcWajQ7625mEYBnexpI2ogGo9NUa6Q==} engines: {node: '>=22.0.0'} minimatch@10.2.6: @@ -4093,6 +4099,10 @@ packages: resolution: {integrity: sha512-RYONW2MeafgYlkVOKYKkA/Ag7BmXqgIWCa8t1m0JcxrQg9pI9lEqRhAOruOBCbAohOa/gkCF+iPi9hrgvTzu6Q==} engines: {node: '>=20.18.1'} + undici@7.30.1: + resolution: {integrity: sha512-03KrMbjIFDWQR5RNPrSw3bd1r12JpyFQl9/yxjUbJtqkjmllqC5lFjZh6ujeuJCKr8EOQvRW872Oy/az+nLYxg==} + engines: {node: '>=20.18.1'} + undici@8.10.0: resolution: {integrity: sha512-HvltHd7avK13QIw/oLe4qoOLyoVSoafqJ2jYOrtMRBkbYT31eiBQ8O0ehRKZiEZCMEyLFQNIADpgCWC5fALvYQ==} engines: {node: '>=22.19.0'} @@ -4456,8 +4466,8 @@ packages: engines: {node: '>=16'} hasBin: true - workerd@1.20261019.1: - resolution: {integrity: sha512-UUYRUq/7DmeCl11YriNbcVbjUZVLtt8uuCXFu+nz77hGFf8d4DEVXoCYtnA+MlBatE4+wxoj47DVqzK3xGBAiw==} + workerd@1.20261101.1: + resolution: {integrity: sha512-qHUIS4cmvhpAE7k2TW0ZktXj9KGDeoUvvLuqi5cSalCM6el5Q6IPuaup9XAC6zQq/xJUPHMG29ML93HuSDY2RQ==} engines: {node: '>=16'} hasBin: true @@ -4526,6 +4536,9 @@ packages: zod@4.6.5: resolution: {integrity: sha512-v5l/aFXZQeai4awLbOpSoHecE9UiMrnfx75tEXLjNonXVARxQ5mOeipTjROUchszUNCqnE+hqAMujRsRHsut2Q==} + zod@4.6.6: + resolution: {integrity: sha512-4UmzQUF5fxvfcYHlbjBmejU+w+hbDnWFx4aS8kBx7nPBHcO2SqPbpAG8snbdg+Xse4pRefR98hgjFgIMCI/UhA==} + zod@4.6.7: resolution: {integrity: sha512-g8W2D2kU6a8untc053fX1uVBKzM7yqAxW/3zwk83+6RyF2+SKOuV+c0wBDhUwzV1PaGapmZH+rmcUzPf+3CGwg==} @@ -4574,11 +4587,11 @@ snapshots: - prettier - prettier-plugin-astro - '@astrojs/cloudflare@15.0.0-beta.2(@types/node@26.0.1)(astro@7.4.1(@types/node@26.0.1)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.1))(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.22.4)(workerd@1.20261019.1)(yaml@2.9.1)': + '@astrojs/cloudflare@15.0.0-beta.2(@types/node@26.0.1)(astro@7.4.1(@types/node@26.0.1)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.1))(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.22.4)(workerd@1.20261101.1)(yaml@2.9.1)': dependencies: '@astrojs/internal-helpers': 0.13.0 '@astrojs/underscore-redirects': 1.0.4 - '@cloudflare/vite-plugin': 2.0.0-beta.v.1(@types/node@26.0.1)(vite@8.3.4(@types/node@26.0.1)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.1))(workerd@1.20261019.1) + '@cloudflare/vite-plugin': 2.0.0-beta.v.1(@types/node@26.0.1)(vite@8.3.4(@types/node@26.0.1)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.1))(workerd@1.20261101.1) astro: 7.4.1(@types/node@26.0.1)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.1) piccolore: 0.1.3 prismjs: 1.30.0 @@ -5065,10 +5078,18 @@ snapshots: dependencies: '@cloudflare/config': 0.27.0 + '@cloudflare/build-output-utils@0.9.7': + dependencies: + '@cloudflare/config': 0.29.1 + '@cloudflare/config@0.27.0': dependencies: zod: 4.6.5 + '@cloudflare/config@0.29.1': + dependencies: + zod: 4.6.6 + '@cloudflare/nimbus-docs@0.18.0(@types/node@26.0.1)(astro@7.4.1(@types/node@26.0.1)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.1))(esbuild@0.28.2)(jiti@2.7.0)(supports-color@10.2.2)(tsx@4.22.4)': dependencies: '@astrojs/markdown-satteri': 0.4.3 @@ -5140,27 +5161,27 @@ snapshots: - bufferutil - utf-8-validate - '@cloudflare/runtime-types@0.1.13(@types/node@26.0.1)': + '@cloudflare/runtime-types@0.1.20(@types/node@26.0.1)': dependencies: - miniflare: 5.20261019.0-beta(@types/node@26.0.1) - workerd: 1.20261019.1 + miniflare: 5.20261101.0-beta(@types/node@26.0.1) + workerd: 1.20261101.1 transitivePeerDependencies: - '@types/node' - bufferutil - utf-8-validate - '@cloudflare/unenv-preset@2.16.2(unenv@2.0.0-rc.24)(workerd@1.20261019.1)': + '@cloudflare/unenv-preset@2.16.2(unenv@2.0.0-rc.24)(workerd@1.20261101.1)': dependencies: unenv: 2.0.0-rc.24 optionalDependencies: - workerd: 1.20261019.1 + workerd: 1.20261101.1 - '@cloudflare/vite-plugin@2.0.0-beta.v.1(@types/node@26.0.1)(vite@8.3.4(@types/node@26.0.1)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.1))(workerd@1.20261019.1)': + '@cloudflare/vite-plugin@2.0.0-beta.v.1(@types/node@26.0.1)(vite@8.3.4(@types/node@26.0.1)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.1))(workerd@1.20261101.1)': dependencies: '@cloudflare/build-output-utils': 0.9.3 '@cloudflare/config': 0.27.0 '@cloudflare/runtime-types': 0.1.12(@types/node@26.0.1) - '@cloudflare/unenv-preset': 2.16.2(unenv@2.0.0-rc.24)(workerd@1.20261019.1) + '@cloudflare/unenv-preset': 2.16.2(unenv@2.0.0-rc.24)(workerd@1.20261101.1) miniflare: 5.20261012.1-beta(@types/node@26.0.1) unenv: 2.0.0-rc.24 vite: 8.3.4(@types/node@26.0.1)(esbuild@0.28.2)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.1) @@ -5174,31 +5195,31 @@ snapshots: '@cloudflare/workerd-darwin-64@1.20261012.1': optional: true - '@cloudflare/workerd-darwin-64@1.20261019.1': + '@cloudflare/workerd-darwin-64@1.20261101.1': optional: true '@cloudflare/workerd-darwin-arm64@1.20261012.1': optional: true - '@cloudflare/workerd-darwin-arm64@1.20261019.1': + '@cloudflare/workerd-darwin-arm64@1.20261101.1': optional: true '@cloudflare/workerd-linux-64@1.20261012.1': optional: true - '@cloudflare/workerd-linux-64@1.20261019.1': + '@cloudflare/workerd-linux-64@1.20261101.1': optional: true '@cloudflare/workerd-linux-arm64@1.20261012.1': optional: true - '@cloudflare/workerd-linux-arm64@1.20261019.1': + '@cloudflare/workerd-linux-arm64@1.20261101.1': optional: true '@cloudflare/workerd-windows-64@1.20261012.1': optional: true - '@cloudflare/workerd-windows-64@1.20261019.1': + '@cloudflare/workerd-windows-64@1.20261101.1': optional: true '@cspotcode/source-map-support@0.8.1': @@ -6658,13 +6679,13 @@ snapshots: ccount@2.0.1: {} - cf@1.0.0-beta.19(@types/node@26.0.1): + cf@1.0.0-beta.27(@types/node@26.0.1): dependencies: - '@cloudflare/build-output-utils': 0.9.3 - '@cloudflare/config': 0.27.0 - '@cloudflare/runtime-types': 0.1.13(@types/node@26.0.1) + '@cloudflare/build-output-utils': 0.9.7 + '@cloudflare/config': 0.29.1 + '@cloudflare/runtime-types': 0.1.20(@types/node@26.0.1) blake3-wasm: 2.1.5 - miniflare: 5.20261019.0-beta(@types/node@26.0.1) + miniflare: 5.20261101.0-beta(@types/node@26.0.1) transitivePeerDependencies: - '@types/node' - bufferutil @@ -7606,12 +7627,12 @@ snapshots: - bufferutil - utf-8-validate - miniflare@5.20261019.0-beta(@types/node@26.0.1): + miniflare@5.20261101.0-beta(@types/node@26.0.1): dependencies: '@cspotcode/source-map-support': 0.8.1 sharp: 0.35.5(@types/node@26.0.1) - undici: 7.29.1 - workerd: 1.20261019.1 + undici: 7.30.1 + workerd: 1.20261101.1 ws: 8.21.0 youch: 4.1.0-beta.10 transitivePeerDependencies: @@ -8438,6 +8459,8 @@ snapshots: undici@7.29.1: {} + undici@7.30.1: {} + undici@8.10.0: {} unenv@2.0.0-rc.24: @@ -8742,13 +8765,13 @@ snapshots: '@cloudflare/workerd-linux-arm64': 1.20261012.1 '@cloudflare/workerd-windows-64': 1.20261012.1 - workerd@1.20261019.1: + workerd@1.20261101.1: optionalDependencies: - '@cloudflare/workerd-darwin-64': 1.20261019.1 - '@cloudflare/workerd-darwin-arm64': 1.20261019.1 - '@cloudflare/workerd-linux-64': 1.20261019.1 - '@cloudflare/workerd-linux-arm64': 1.20261019.1 - '@cloudflare/workerd-windows-64': 1.20261019.1 + '@cloudflare/workerd-darwin-64': 1.20261101.1 + '@cloudflare/workerd-darwin-arm64': 1.20261101.1 + '@cloudflare/workerd-linux-64': 1.20261101.1 + '@cloudflare/workerd-linux-arm64': 1.20261101.1 + '@cloudflare/workerd-windows-64': 1.20261101.1 wrap-ansi@9.0.2: dependencies: @@ -8813,6 +8836,8 @@ snapshots: zod@4.6.5: {} + zod@4.6.6: {} + zod@4.6.7: {} zwitch@2.0.4: {}