← Files Token WeatherARCHIVED FILE
cloudflare/scripts/preflight.mjs
3.43 KB · Nov 9, 2026 · 01:28 UTC
import { readFile } from 'node:fs/promises';
import { resolve } from 'node:path';
import { pathToFileURL } from 'node:url';
export function inspectConfig(config) {
const allowed = ['$schema', 'name', 'account_id', 'main', 'compatibility_date',
'compatibility_flags', 'workers_dev', 'preview_urls', 'observability', 'vars', 'ratelimits', 'dev'];
if (Object.keys(config).some(key => !allowed.includes(key))) {
throw new Error('Unexpected deployment options or resource bindings. Review them before deployment.');
}
if (!/^[0-9a-f]{32}$/.test(config.account_id ?? '')) throw new Error('Select the target Cloudflare account first.');
const origin = config.vars?.PUBLIC_ORIGIN;
if (typeof origin !== 'string') throw new Error('Set the confirmed production origin.');
const url = new URL(origin);
if (origin !== url.origin || url.protocol !== 'https:' || url.username || url.password ||
url.port || !/^[a-z0-9-]+\.[a-z0-9-]+\.workers\.dev$/.test(url.hostname) ||
url.hostname.split('.')[0] !== config.name) throw new Error('Worker name and confirmed workers.dev origin must match.');
if (config.main !== 'src/index.ts' || config.workers_dev !== true || config.preview_urls !== false ||
config.observability?.enabled !== false || Object.keys(config.observability).length !== 1 ||
JSON.stringify(config.compatibility_flags) !== JSON.stringify(['nodejs_compat']) ||
!/^\d{4}-\d{2}-\d{2}$/.test(config.compatibility_date ?? '') ||
Object.keys(config.vars).length !== 1) throw new Error('Source, routing, metadata logging or variable settings differ from this profile.');
const limiters = config.ratelimits;
if (!Array.isArray(limiters) || limiters.length !== 2) throw new Error('Both request limiters are required.');
const names = ['MCP_IP_LIMITER', 'MCP_SERVICE_LIMITER'];
for (let index = 0; index < 2; index++) {
const entry = limiters[index];
if (entry.name !== names[index] || !/^[1-9]\d*$/.test(entry.namespace_id ?? '') ||
entry.simple?.period !== 60 || entry.simple?.limit !== [120, 1200][index] ||
Object.keys(entry).some(key => !['name', 'namespace_id', 'simple'].includes(key)) ||
Object.keys(entry.simple).some(key => !['limit', 'period'].includes(key))) {
throw new Error('Request limiter configuration differs from the reviewed profile.');
}
}
if (limiters[0].namespace_id === limiters[1].namespace_id) throw new Error('Use distinct rate limit namespaces.');
return { worker: config.name, endpoint: `${origin}/mcp`, account_selected: true,
preview_urls: false, body_limit_bytes: 16384,
per_ip_per_location_per_minute: 120, per_service_per_location_per_minute: 1200,
cloud_account_accessed: false, free_plan_verified: false, deployed: false,
remaining: ['Verify the selected account is on Workers Free',
'Check for an existing Worker and unused limiter namespaces',
'Verify ownership, domain challenge and production CPU after deployment'] };
}
async function main() {
const args = process.argv.slice(2);
if (args.length !== 2 || args[0] !== '--config') throw new Error('Use --config <prepared-config.json>. This command is local and never deploys.');
const config = JSON.parse(await readFile(args[1], 'utf8'));
console.log(JSON.stringify(inspectConfig(config), null, 2));
}
if (process.argv[1] && import.meta.url === pathToFileURL(resolve(process.argv[1])).href) {
main().catch(error => { console.error(error.message); process.exitCode = 1; });
}
SHA-256: c82f93054a10478fdfed1e8fc70d1465e0ded980a4b1d28c6a42cafdeb74ec49