@demiurgejs/core 0.2.0-beta.5 → 0.2.0-beta.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/README.md +14 -0
  2. package/bin/demiurge.mjs +6 -0
  3. package/dist/chunks/{document-shell-9GPwtcTt.js → document-shell-C0aPrkhd.js} +2 -2
  4. package/dist/chunks/{document-shell-9GPwtcTt.js.map → document-shell-C0aPrkhd.js.map} +1 -1
  5. package/dist/chunks/image-CRerJ5BY.js +145 -0
  6. package/dist/chunks/image-CRerJ5BY.js.map +1 -0
  7. package/dist/chunks/{image-codec-Dh1POFhE.js → image-codec-CQ8Cwxwb.js} +2 -2
  8. package/dist/chunks/{image-codec-Dh1POFhE.js.map → image-codec-CQ8Cwxwb.js.map} +1 -1
  9. package/dist/chunks/{images-CG7ZzayG.js → images-QgdmLyQ3.js} +11 -11
  10. package/dist/chunks/{images-CG7ZzayG.js.map → images-QgdmLyQ3.js.map} +1 -1
  11. package/dist/chunks/{index-0MNiR_wo.js → index-LYve1rQp.js} +286 -351
  12. package/dist/chunks/index-LYve1rQp.js.map +1 -0
  13. package/dist/chunks/links-iU22QkCE.js +68 -0
  14. package/dist/chunks/links-iU22QkCE.js.map +1 -0
  15. package/dist/chunks/{plugin-BZauDxRY.js → plugin-bkP6WwrS.js} +13 -12
  16. package/dist/chunks/{plugin-BZauDxRY.js.map → plugin-bkP6WwrS.js.map} +1 -1
  17. package/dist/chunks/runtime-BH519j2t.js +294 -0
  18. package/dist/chunks/runtime-BH519j2t.js.map +1 -0
  19. package/dist/chunks/streaming-BlKlC3nw.js +427 -0
  20. package/dist/chunks/streaming-BlKlC3nw.js.map +1 -0
  21. package/dist/chunks/{testing-CUwGj2ie.js → testing-BEW1nchS.js} +645 -630
  22. package/dist/chunks/testing-BEW1nchS.js.map +1 -0
  23. package/dist/chunks/{vite-QoqrGl6f.js → vite-BADZA8Fl.js} +73 -70
  24. package/dist/chunks/vite-BADZA8Fl.js.map +1 -0
  25. package/dist/cli.d.ts +8 -2
  26. package/dist/cli.d.ts.map +1 -1
  27. package/dist/cli.js +186 -122
  28. package/dist/cli.js.map +1 -1
  29. package/dist/config/index.js +2 -2
  30. package/dist/config/types.d.ts +3 -1
  31. package/dist/config/types.d.ts.map +1 -1
  32. package/dist/config/validate.d.ts.map +1 -1
  33. package/dist/data/cache.d.ts +5 -0
  34. package/dist/data/cache.d.ts.map +1 -1
  35. package/dist/data/index.d.ts +1 -1
  36. package/dist/data/index.d.ts.map +1 -1
  37. package/dist/data/testing.d.ts.map +1 -1
  38. package/dist/data/testing.js +101 -67
  39. package/dist/data/testing.js.map +1 -1
  40. package/dist/data/tiered.d.ts.map +1 -1
  41. package/dist/edge/index.js +27 -26
  42. package/dist/edge/index.js.map +1 -1
  43. package/dist/edge/stores.d.ts.map +1 -1
  44. package/dist/index.d.ts +1 -1
  45. package/dist/index.d.ts.map +1 -1
  46. package/dist/index.js +126 -125
  47. package/dist/index.js.map +1 -1
  48. package/dist/internal/testing.js +2 -2
  49. package/dist/kv/index.js +7 -6
  50. package/dist/kv/index.js.map +1 -1
  51. package/dist/kv/store.d.ts.map +1 -1
  52. package/dist/node/http.d.ts +2 -0
  53. package/dist/node/http.d.ts.map +1 -1
  54. package/dist/node/index.d.ts +1 -1
  55. package/dist/node/index.d.ts.map +1 -1
  56. package/dist/node/index.js +12 -11
  57. package/dist/node/index.js.map +1 -1
  58. package/dist/node/serve.d.ts +4 -0
  59. package/dist/node/serve.d.ts.map +1 -1
  60. package/dist/redis/index.js +29 -28
  61. package/dist/redis/index.js.map +1 -1
  62. package/dist/redis/store.d.ts.map +1 -1
  63. package/dist/route/serialization.d.ts +4 -4
  64. package/dist/route/serialization.d.ts.map +1 -1
  65. package/dist/static/index.d.ts.map +1 -1
  66. package/dist/static/index.js +255 -255
  67. package/dist/static/index.js.map +1 -1
  68. package/dist/static/testing.d.ts +26 -0
  69. package/dist/static/testing.d.ts.map +1 -0
  70. package/dist/static/testing.js +76 -0
  71. package/dist/static/testing.js.map +1 -0
  72. package/dist/testing/index.d.ts +47 -0
  73. package/dist/testing/index.d.ts.map +1 -0
  74. package/dist/testing/index.js +99 -0
  75. package/dist/testing/index.js.map +1 -0
  76. package/dist/vercel/build.d.ts +31 -0
  77. package/dist/vercel/build.d.ts.map +1 -0
  78. package/dist/vercel/config.d.ts +15 -0
  79. package/dist/vercel/config.d.ts.map +1 -0
  80. package/dist/vercel/index.d.ts +7 -0
  81. package/dist/vercel/index.d.ts.map +1 -0
  82. package/dist/vercel/index.js +11 -0
  83. package/dist/vercel/index.js.map +1 -0
  84. package/dist/vercel/runtime.d.ts +29 -0
  85. package/dist/vercel/runtime.d.ts.map +1 -0
  86. package/dist/vite/index.js +1 -1
  87. package/package.json +13 -1
  88. package/dist/chunks/index-0MNiR_wo.js.map +0 -1
  89. package/dist/chunks/streaming-GYIsVTQH.js +0 -560
  90. package/dist/chunks/streaming-GYIsVTQH.js.map +0 -1
  91. package/dist/chunks/testing-CUwGj2ie.js.map +0 -1
  92. package/dist/chunks/vite-QoqrGl6f.js.map +0 -1
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sources":["../src/inspect/types.ts","../src/inspect/report.ts","../src/inspect/command.ts","../src/cli.ts"],"sourcesContent":["import type { HttpMethod } from \"../route\";\nimport type {\n DocumentCspState,\n RouteAccessState,\n StaticPolicyFinding,\n} from \"../vite/policy-verification\";\n\n/**\n * The version of the static policy report. ADR 0019 raises this integer when\n * the framework removes a field or changes the meaning of a field.\n */\nexport const STATIC_POLICY_REPORT_VERSION = 1;\n\n/**\n * The version of the problem document that the inspect command writes when it\n * cannot produce a report.\n */\nexport const INSPECTION_PROBLEM_VERSION = 1;\n\n/**\n * The origin of one fact in a report. The value `static` states that the build\n * knows the fact. The value `request` states that only a request supplies it.\n */\nexport type InspectionResolution = \"request\" | \"static\";\n\n/** The rule that removed one value from a report. */\nexport type InspectionRedactionReason =\n /** A cookie holds the value. */\n | \"cookie-value\"\n /** An `env.secret(...)` declaration produced the value. */\n | \"environment-secret\"\n /** A session record holds the value. */\n | \"session-record\";\n\n/** One value that the serializer removed from a report. */\nexport type InspectionRedaction = {\n /** The name of the field that held the value. */\n name: string;\n /** The dotted path of the field inside the report. */\n path: string;\n /** The rule that removed the value. */\n reason: InspectionRedactionReason;\n};\n\n/** The named sections of the static policy report. */\nexport type StaticPolicyReportSection =\n | \"findings\"\n | \"redactions\"\n | \"request\"\n | \"routes\";\n\n/** The kind of route file that the static pass read. */\nexport type StaticRouteKind = \"attached\" | \"page\" | \"resource\";\n\n/**\n * The statically readable description of one route file.\n *\n * Each declared field states what the file itself declares. The framework\n * resolves the cascade of the route tree and reports the result of the\n * cascade in the `findings` section.\n */\nexport type StaticRouteReport = {\n /** The access state that the route file declares. */\n declaredAccess: RouteAccessState;\n /** The Content-Security-Policy state that the route file declares. */\n declaredDocumentCsp: DocumentCspState;\n /** `true` when the route file declares a document policy. */\n declaresDocumentPolicy: boolean;\n /** The path of the route file, relative to the route directory. */\n file: string;\n /** The kind of the route file. */\n kind: StaticRouteKind;\n /** The HTTP methods that the route file exports. */\n methods: HttpMethod[];\n /** The route pattern. An attached file has no pattern. */\n pattern?: string;\n};\n\n/**\n * The report that `demiurge inspect` writes to standard output. Each section\n * states the resolution of its facts in the `resolutions` record.\n */\nexport type StaticPolicyReport = {\n /** The static policy findings, sorted by file, export name, and code. */\n findings: StaticPolicyFinding[];\n /** The values that the serializer removed. */\n redactions: InspectionRedaction[];\n /** The names of the facts that only a request supplies. */\n request: string[];\n /** The resolution of each section of the report. */\n resolutions: Record<StaticPolicyReportSection, InspectionResolution>;\n /** Every route file under the route directory. */\n routes: StaticRouteReport[];\n /** The route directory, relative to the project root. */\n routesDir: string;\n /** The version of this report shape. */\n version: number;\n};\n\n/** The reason that the inspect command could not produce a report. */\nexport type InspectionProblemCode =\n /** The framework could not read the configuration. */\n | \"configuration-unreadable\"\n /** The command received an invalid argument. */\n | \"invalid-argument\";\n\n/**\n * The document that the inspect command writes when it cannot produce a\n * report. The command then exits with code 2.\n */\nexport type InspectionProblem = {\n /** The stable code of the condition. */\n code: InspectionProblemCode;\n /** The description of the condition. */\n detail: string;\n /** The short name of the condition. */\n title: string;\n /** The version of this problem shape. */\n version: number;\n};\n","import { relative, sep } from \"node:path\";\nimport { toRoutePattern, toRouteSegments } from \"../router\";\nimport type { EnvSchema } from \"../security\";\nimport {\n inspectRoutePolicies,\n type DemiurgeVitePluginOptions,\n} from \"../vite/plugin\";\nimport type { RouteFileInspection } from \"../vite/policy-verification\";\nimport {\n STATIC_POLICY_REPORT_VERSION,\n type StaticPolicyReport,\n type StaticRouteReport,\n} from \"./types\";\n\nexport type StaticPolicyReportOptions = {\n /** The plugin options of the application. */\n options?: DemiurgeVitePluginOptions;\n /** The absolute path of the project root. */\n root: string;\n};\n\n// A build knows the route tree and the policy cascade. It does not know a\n// header, a cookie, a session, or an authorization result, because a request\n// supplies each one. The report names these facts, so a reader learns which\n// answer needs a running application.\nconst requestFacts = [\n \"authorization-result\",\n \"cookie-values\",\n \"csrf-token\",\n \"environment-values\",\n \"rate-limit-state\",\n \"request-headers\",\n \"response-headers\",\n \"session-record\",\n];\n\n/**\n * Builds the static inspection report of an application.\n *\n * The function reads the route tree and resolves the policy cascade through\n * `inspectRoutePolicies`. It loads no route module, so it runs no data loader\n * and no mutation handler.\n */\nexport async function createStaticPolicyReport(\n input: StaticPolicyReportOptions,\n): Promise<StaticPolicyReport> {\n const options = input.options ?? {};\n const pass = await inspectRoutePolicies(input.root, options);\n const routes = pass.inspections\n .map((inspection) => toStaticRouteReport(pass.routesDir, inspection))\n .sort((left, right) => left.file.localeCompare(right.file));\n\n return {\n findings: pass.findings,\n redactions: [],\n request: requestFacts,\n resolutions: {\n findings: \"static\",\n redactions: \"static\",\n request: \"request\",\n routes: \"static\",\n },\n routes,\n routesDir: toPosixPath(relative(input.root, pass.routesDir)),\n version: STATIC_POLICY_REPORT_VERSION,\n };\n}\n\n/** Reads the names of the variables that `env.secret(...)` declared. */\nexport function findSecretEnvKeys(schema: EnvSchema | undefined) {\n return Object.entries(schema ?? {})\n .filter(([, variable]) => variable.sensitive)\n .map(([key]) => key)\n .sort();\n}\n\n/** Counts the findings that carry error severity. */\nexport function countErrorFindings(report: StaticPolicyReport) {\n return report.findings.filter((finding) => finding.severity === \"error\")\n .length;\n}\n\n/** Writes the human summary that the command sends to standard error. */\nexport function formatStaticPolicyReportSummary(report: StaticPolicyReport) {\n const errors = countErrorFindings(report);\n const warnings = report.findings.length - errors;\n\n return [\n `Demiurge inspected ${report.routes.length} route files in ${report.routesDir}.`,\n `Findings: ${errors} error, ${warnings} warning.`,\n `The report states ${report.request.length} facts that only a request supplies.`,\n ...report.findings.map((finding) =>\n ` ${finding.severity}: ${toPosixPath(finding.file)} [${finding.code}] ${finding.message}`\n ),\n ].join(\"\\n\");\n}\n\nfunction toStaticRouteReport(\n routesDir: string,\n inspection: RouteFileInspection,\n): StaticRouteReport {\n const file = toPosixPath(relative(routesDir, inspection.file));\n const fileSegments = file.replace(/\\.tsx?$/, \"\").split(\"/\");\n const attached = fileSegments.at(-1)?.startsWith(\"@\") ?? false;\n\n return {\n declaredAccess: inspection.accessState,\n declaredDocumentCsp: inspection.documentCspState,\n declaresDocumentPolicy: inspection.declaresDocumentPolicy,\n file,\n kind: attached\n ? \"attached\"\n : inspection.declaresPageRoute\n ? \"page\"\n : \"resource\",\n methods: inspection.methods,\n ...(attached\n ? {}\n : { pattern: toRoutePattern(toRouteSegments(fileSegments)) }),\n };\n}\n\nfunction toPosixPath(pathname: string) {\n return pathname.split(sep).join(\"/\");\n}\n","import type { ResolvedDemiurgeConfig } from \"../config/types\";\nimport { toPluginOptions } from \"../config/vite\";\nimport {\n countErrorFindings,\n createStaticPolicyReport,\n findSecretEnvKeys,\n formatStaticPolicyReportSummary,\n} from \"./report\";\nimport { serializeInspectionReport } from \"./redact\";\nimport {\n INSPECTION_PROBLEM_VERSION,\n type InspectionProblem,\n type InspectionProblemCode,\n} from \"./types\";\n\n/** The exit codes of the `demiurge inspect` command. */\nexport const INSPECT_EXIT_OK = 0;\nexport const INSPECT_EXIT_FINDINGS = 1;\nexport const INSPECT_EXIT_INVALID = 2;\n\nexport type InspectCommandInput = {\n /** The arguments that follow the command name. */\n arguments: readonly string[];\n /** Reads the configuration of the application. */\n loadConfig: () => Promise<ResolvedDemiurgeConfig>;\n};\n\nexport type InspectCommandResult = {\n /** The exit code of the command. */\n exitCode: number;\n /** The human summary that the command writes to standard error. */\n stderr: string;\n /** The JSON document that the command writes to standard output. */\n stdout: string;\n};\n\n/**\n * Runs the `demiurge inspect` command.\n *\n * The command reads the route tree, resolves the policy cascade, and returns\n * one JSON document. The command loads no route module, so it runs no data\n * loader and no mutation handler.\n */\nexport async function runInspectCommand(\n input: InspectCommandInput,\n): Promise<InspectCommandResult> {\n if (input.arguments.length > 0) {\n return toProblemResult(\n \"invalid-argument\",\n \"The inspect command accepts no argument.\",\n `The command received ${input.arguments.join(\" \")}.`,\n );\n }\n\n let config: ResolvedDemiurgeConfig;\n\n try {\n config = await input.loadConfig();\n } catch (error) {\n return toProblemResult(\n \"configuration-unreadable\",\n \"Demiurge could not read the configuration.\",\n error instanceof Error ? error.message : String(error),\n );\n }\n\n const report = await createStaticPolicyReport({\n options: toPluginOptions(config),\n root: config.root,\n });\n\n return {\n exitCode: countErrorFindings(report) > 0\n ? INSPECT_EXIT_FINDINGS\n : INSPECT_EXIT_OK,\n stderr: formatStaticPolicyReportSummary(report),\n stdout: serializeInspectionReport(report, {\n secretEnvKeys: findSecretEnvKeys(config.env),\n }),\n };\n}\n\nfunction toProblemResult(\n code: InspectionProblemCode,\n title: string,\n detail: string,\n): InspectCommandResult {\n const problem: InspectionProblem = {\n code,\n detail,\n title,\n version: INSPECTION_PROBLEM_VERSION,\n };\n\n return {\n exitCode: INSPECT_EXIT_INVALID,\n stderr: `${title}\\n${detail}`,\n stdout: serializeInspectionReport(problem),\n };\n}\n","import { readFile, readdir } from \"node:fs/promises\";\nimport { isAbsolute, join, relative, resolve, sep } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport type { InlineConfig } from \"vite\";\nimport { createDemiurgeViteConfig } from \"./config/vite\";\nimport type { ResolvedDemiurgeConfig } from \"./config/types\";\nimport { parseClientManifest } from \"./manifest\";\nimport type { RouteImporter } from \"./route\";\nimport {\n generateVercelStaticOutput,\n generateStaticOutput,\n type GenerateStaticOutputOptions,\n type StaticOutputManifest,\n} from \"./static\";\n\nexport { parseClientManifest } from \"./manifest\";\nexport type { ClientBuildManifest } from \"./manifest\";\nexport {\n INSPECT_EXIT_FINDINGS,\n INSPECT_EXIT_INVALID,\n INSPECT_EXIT_OK,\n runInspectCommand,\n} from \"./inspect\";\nexport type { InspectCommandResult } from \"./inspect\";\n\ntype CliEnvironment = Record<string, string | undefined>;\n\nconst cliOptionNames = new Set([\"--host\", \"--origin\", \"--out-dir\", \"--port\"]);\n\nconst CLIENT_ENTRY = \"virtual:demiurge/client-entry\";\nconst SERVER_ENTRY = \"virtual:demiurge/server-entry\";\nconst DEFAULT_CLIENT_OUT_DIR = \"dist\";\nconst DEFAULT_SERVER_OUT_DIR = \"dist/server\";\nconst FRAMEWORK_SERVER_OUT_DIR = \".demiurge/server\";\n\nexport type CliOptions = {\n command: \"build\" | \"dev\" | \"help\" | \"inspect\" | \"preview\";\n host: string;\n origin?: string;\n outDir?: string;\n port: number;\n};\n\nexport type BuildRuntime = {\n build: (config: InlineConfig) => Promise<unknown>;\n createViteConfig: (overrides: InlineConfig) => Promise<InlineConfig>;\n generate: (\n options: GenerateStaticOutputOptions,\n ) => Promise<StaticOutputManifest>;\n importModule: (specifier: string) => Promise<Record<string, unknown>>;\n now: () => number;\n readText: (file: string) => Promise<string>;\n};\n\nexport type BuildResult = {\n deploymentOutDir?: string;\n manifest?: StaticOutputManifest;\n outDir: string;\n serverOutDir?: string;\n};\n\nexport function parseCliArguments(\n arguments_: string[],\n environment: CliEnvironment = {},\n): CliOptions {\n const command = arguments_[0];\n if (!command || command === \"--help\" || command === \"-h\" || command === \"help\") {\n return {\n command: \"help\",\n host: \"localhost\",\n port: 4173,\n };\n }\n if (\n command !== \"build\" && command !== \"dev\" && command !== \"inspect\" &&\n command !== \"preview\"\n ) {\n throw new Error(`Unknown command: ${command}`);\n }\n\n const options: CliOptions = {\n command,\n host: \"localhost\",\n origin: environment.SITE_ORIGIN,\n port: command === \"dev\" ? 5173 : 4173,\n };\n\n for (let index = 1; index < arguments_.length; index += 1) {\n const argument = arguments_[index]!;\n if (argument === \"--help\" || argument === \"-h\") {\n return { command: \"help\", host: \"localhost\", port: 4173 };\n }\n const [name, inlineValue] = argument.split(\"=\", 2);\n if (!cliOptionNames.has(name!)) {\n throw new Error(`Unknown option: ${argument}`);\n }\n const value = inlineValue ?? arguments_[++index];\n if (!value || value.startsWith(\"--\")) {\n throw new Error(`Option ${name} requires a value.`);\n }\n\n if (name === \"--host\") options.host = value;\n if (name === \"--origin\") options.origin = value;\n if (name === \"--out-dir\") options.outDir = value;\n if (name === \"--port\") {\n const port = Number(value);\n if (!Number.isSafeInteger(port) || port < 0 || port > 65_535) {\n throw new Error(\"The server port must be an integer from 0 through 65535.\");\n }\n options.port = port;\n }\n }\n\n return options;\n}\n\nexport const helpText = `Usage: demiurge <command> [options]\n\nCommands:\n dev Start the development server\n build Build production output\n inspect Write the static inspection report as JSON\n preview Serve static output with its declared headers\n\nOptions:\n --host <host> Set the server host (default: localhost)\n --origin <origin> Set the build origin (default: SITE_ORIGIN)\n --out-dir <directory> Set the client output directory (default: dist)\n --port <port> Set the server port (dev: 5173, preview: 4173)\n -h, --help Show this help\n\nThe inspect command writes JSON to standard output and a summary to standard\nerror. It exits with 0 for no error finding, 1 for at least one error finding,\nand 2 for an invalid argument or an unreadable configuration.\n\nDemiurge reads demiurge.config.ts from the project root.`;\n\nexport async function runDev(\n options: CliOptions,\n config: ResolvedDemiurgeConfig,\n) {\n const { createServer } = await import(\"vite\");\n const server = await createServer(\n await createDemiurgeViteConfig({\n config,\n overrides: {\n mode: \"development\",\n server: { host: options.host, port: options.port },\n },\n }),\n );\n await server.listen();\n return server;\n}\n\nexport async function runBuild(\n options: CliOptions,\n config: ResolvedDemiurgeConfig,\n runtime?: BuildRuntime,\n): Promise<BuildResult> {\n const root = config.root;\n const build = runtime?.build ?? (await import(\"vite\")).build;\n const createViteConfig = runtime?.createViteConfig ??\n ((overrides: InlineConfig) => createDemiurgeViteConfig({ config, overrides }));\n\n const outDir = resolve(\n root,\n options.outDir ?? config.deployment?.outDir ?? DEFAULT_CLIENT_OUT_DIR,\n );\n const frameworkServerOutDir = resolve(root, FRAMEWORK_SERVER_OUT_DIR);\n\n await validateBuildOutputDirectory(\n root,\n outDir,\n join(root, \"public\"),\n frameworkServerOutDir,\n );\n\n await build(\n await createViteConfig({\n define: { \"process.env.NODE_ENV\": JSON.stringify(\"production\") },\n mode: \"production\",\n build: {\n emptyOutDir: true,\n outDir,\n rollupOptions: { input: CLIENT_ENTRY },\n },\n }),\n );\n\n const applicationServer = config.deployment?.server;\n const serverOutDir = applicationServer\n ? resolve(root, applicationServer.outDir ?? DEFAULT_SERVER_OUT_DIR)\n : undefined;\n\n if (applicationServer && serverOutDir) {\n await build(\n await createViteConfig({\n define: { \"process.env.NODE_ENV\": JSON.stringify(\"production\") },\n mode: \"production\",\n build: {\n copyPublicDir: false,\n emptyOutDir: true,\n outDir: serverOutDir,\n rollupOptions: { input: resolve(root, applicationServer.entry) },\n ssr: true,\n },\n }),\n );\n }\n\n if (!config.deployment?.static) return { outDir, serverOutDir };\n\n const staticResult = await buildStaticOutput({\n build,\n config,\n createViteConfig,\n frameworkServerOutDir,\n options,\n outDir,\n root,\n runtime,\n });\n\n return { ...staticResult, outDir, serverOutDir };\n}\n\nasync function buildStaticOutput({\n build,\n config,\n createViteConfig,\n frameworkServerOutDir,\n options,\n outDir,\n root,\n runtime,\n}: {\n build: (config: InlineConfig) => Promise<unknown>;\n config: ResolvedDemiurgeConfig;\n createViteConfig: (overrides: InlineConfig) => Promise<InlineConfig>;\n frameworkServerOutDir: string;\n options: CliOptions;\n outDir: string;\n root: string;\n runtime?: BuildRuntime;\n}) {\n await build(\n await createViteConfig({\n define: { \"process.env.NODE_ENV\": JSON.stringify(\"production\") },\n mode: \"production\",\n build: {\n copyPublicDir: false,\n emptyOutDir: true,\n outDir: frameworkServerOutDir,\n rollupOptions: {\n input: SERVER_ENTRY,\n output: { entryFileNames: \"server-entry.js\" },\n },\n ssr: true,\n },\n }),\n );\n\n const clientManifest = parseClientManifest(\n runtime\n ? await runtime.readText(resolve(outDir, \"demiurge-manifest.json\"))\n : await readFile(resolve(outDir, \"demiurge-manifest.json\"), \"utf8\"),\n );\n const serverEntryUrl = `${\n pathToFileURL(resolve(frameworkServerOutDir, \"server-entry.js\")).href\n }?build=${runtime?.now() ?? Date.now()}`;\n const serverEntry = runtime\n ? await runtime.importModule(serverEntryUrl)\n : await import(serverEntryUrl);\n if (!isRouteImporterRecord(serverEntry.routes)) {\n throw new Error(\"The framework server bundle does not export routes.\");\n }\n\n const manifest = await (runtime?.generate ?? generateStaticOutput)({\n fonts: config.assets?.fonts,\n images: config.assets?.images,\n origin: options.origin ?? config.deployment?.static?.origin,\n outDir,\n root,\n routes: serverEntry.routes,\n ssr: clientManifest,\n staticFileHeaders: config.security?.staticFileHeaders ?? [],\n });\n\n const provider = config.deployment?.static?.provider;\n const deploymentOutDir = provider\n ? await generateVercelStaticOutput({\n deployment: provider,\n manifest,\n outDir,\n projectRoot: root,\n })\n : undefined;\n\n return { deploymentOutDir, manifest };\n}\n\nexport function resolvePreviewOutputDirectory(\n root: string,\n outDir: string | undefined,\n configuredOutDir?: string,\n) {\n return resolve(root, outDir ?? configuredOutDir ?? DEFAULT_CLIENT_OUT_DIR);\n}\n\nexport async function validateBuildOutputDirectory(\n root: string,\n outDir: string,\n publicDir: false | string,\n serverOutDir: string,\n) {\n const pathFromRoot = relative(root, outDir);\n if (\n !pathFromRoot ||\n pathFromRoot === \"..\" ||\n pathFromRoot.startsWith(`..${sep}`) ||\n isAbsolute(pathFromRoot)\n ) {\n throw new Error(\"The static output directory must be inside the Vite root.\");\n }\n\n if (publicDir && pathsOverlap(outDir, publicDir)) {\n throw new Error(\"The static output directory must not overlap the Vite public directory.\");\n }\n\n if (pathsOverlap(outDir, serverOutDir)) {\n throw new Error(\"The static output directory must not overlap the framework server directory.\");\n }\n\n let entries: string[];\n try {\n entries = await readdir(outDir);\n } catch (error) {\n if (isMissingPath(error)) return;\n throw error;\n }\n\n if (\n entries.length &&\n !entries.includes(\"demiurge-manifest.json\") &&\n !entries.includes(\"demiurge-static-manifest.json\")\n ) {\n throw new Error(\n \"The static output directory contains files that a Demiurge build did not create.\",\n );\n }\n}\n\nfunction isRouteImporterRecord(\n value: unknown,\n): value is Record<string, RouteImporter> {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n return false;\n }\n\n return Object.values(value).every((load) => typeof load === \"function\");\n}\n\nfunction pathsOverlap(left: string, right: string) {\n const fromLeft = relative(left, right);\n const fromRight = relative(right, left);\n return isSameOrChildPath(fromLeft) || isSameOrChildPath(fromRight);\n}\n\nfunction isSameOrChildPath(pathname: string) {\n return !pathname ||\n (pathname !== \"..\" && !pathname.startsWith(`..${sep}`) &&\n !isAbsolute(pathname));\n}\n\nfunction isMissingPath(error: unknown) {\n return error instanceof Error && \"code\" in error && error.code === \"ENOENT\";\n}\n"],"names":["STATIC_POLICY_REPORT_VERSION","INSPECTION_PROBLEM_VERSION","requestFacts","createStaticPolicyReport","input","options","pass","inspectRoutePolicies","routes","inspection","toStaticRouteReport","left","right","toPosixPath","relative","findSecretEnvKeys","schema","variable","key","countErrorFindings","report","finding","formatStaticPolicyReportSummary","errors","warnings","routesDir","file","fileSegments","attached","toRoutePattern","toRouteSegments","pathname","sep","INSPECT_EXIT_OK","INSPECT_EXIT_FINDINGS","INSPECT_EXIT_INVALID","runInspectCommand","toProblemResult","config","error","toPluginOptions","serializeInspectionReport","code","title","detail","problem","cliOptionNames","CLIENT_ENTRY","SERVER_ENTRY","DEFAULT_CLIENT_OUT_DIR","DEFAULT_SERVER_OUT_DIR","FRAMEWORK_SERVER_OUT_DIR","parseCliArguments","arguments_","environment","command","index","argument","name","inlineValue","value","port","helpText","runDev","createServer","server","createDemiurgeViteConfig","runBuild","runtime","root","build","createViteConfig","overrides","outDir","resolve","frameworkServerOutDir","validateBuildOutputDirectory","join","applicationServer","serverOutDir","buildStaticOutput","clientManifest","parseClientManifest","readFile","serverEntryUrl","pathToFileURL","serverEntry","isRouteImporterRecord","manifest","generateStaticOutput","provider","generateVercelStaticOutput","resolvePreviewOutputDirectory","configuredOutDir","publicDir","pathFromRoot","isAbsolute","pathsOverlap","entries","readdir","isMissingPath","load","fromLeft","fromRight","isSameOrChildPath"],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sources":["../src/inspect/types.ts","../src/inspect/report.ts","../src/inspect/command.ts","../src/cli.ts"],"sourcesContent":["import type { HttpMethod } from \"../route\";\nimport type {\n DocumentCspState,\n RouteAccessState,\n StaticPolicyFinding,\n} from \"../vite/policy-verification\";\n\n/**\n * The version of the static policy report. ADR 0019 raises this integer when\n * the framework removes a field or changes the meaning of a field.\n */\nexport const STATIC_POLICY_REPORT_VERSION = 1;\n\n/**\n * The version of the problem document that the inspect command writes when it\n * cannot produce a report.\n */\nexport const INSPECTION_PROBLEM_VERSION = 1;\n\n/**\n * The origin of one fact in a report. The value `static` states that the build\n * knows the fact. The value `request` states that only a request supplies it.\n */\nexport type InspectionResolution = \"request\" | \"static\";\n\n/** The rule that removed one value from a report. */\nexport type InspectionRedactionReason =\n /** A cookie holds the value. */\n | \"cookie-value\"\n /** An `env.secret(...)` declaration produced the value. */\n | \"environment-secret\"\n /** A session record holds the value. */\n | \"session-record\";\n\n/** One value that the serializer removed from a report. */\nexport type InspectionRedaction = {\n /** The name of the field that held the value. */\n name: string;\n /** The dotted path of the field inside the report. */\n path: string;\n /** The rule that removed the value. */\n reason: InspectionRedactionReason;\n};\n\n/** The named sections of the static policy report. */\nexport type StaticPolicyReportSection =\n | \"findings\"\n | \"redactions\"\n | \"request\"\n | \"routes\";\n\n/** The kind of route file that the static pass read. */\nexport type StaticRouteKind = \"attached\" | \"page\" | \"resource\";\n\n/**\n * The statically readable description of one route file.\n *\n * Each declared field states what the file itself declares. The framework\n * resolves the cascade of the route tree and reports the result of the\n * cascade in the `findings` section.\n */\nexport type StaticRouteReport = {\n /** The access state that the route file declares. */\n declaredAccess: RouteAccessState;\n /** The Content-Security-Policy state that the route file declares. */\n declaredDocumentCsp: DocumentCspState;\n /** `true` when the route file declares a document policy. */\n declaresDocumentPolicy: boolean;\n /** The path of the route file, relative to the route directory. */\n file: string;\n /** The kind of the route file. */\n kind: StaticRouteKind;\n /** The HTTP methods that the route file exports. */\n methods: HttpMethod[];\n /** The route pattern. An attached file has no pattern. */\n pattern?: string;\n};\n\n/**\n * The report that `demiurge inspect` writes to standard output. Each section\n * states the resolution of its facts in the `resolutions` record.\n */\nexport type StaticPolicyReport = {\n /** The static policy findings, sorted by file, export name, and code. */\n findings: StaticPolicyFinding[];\n /** The values that the serializer removed. */\n redactions: InspectionRedaction[];\n /** The names of the facts that only a request supplies. */\n request: string[];\n /** The resolution of each section of the report. */\n resolutions: Record<StaticPolicyReportSection, InspectionResolution>;\n /** Every route file under the route directory. */\n routes: StaticRouteReport[];\n /** The route directory, relative to the project root. */\n routesDir: string;\n /** The version of this report shape. */\n version: number;\n};\n\n/** The reason that the inspect command could not produce a report. */\nexport type InspectionProblemCode =\n /** The framework could not read the configuration. */\n | \"configuration-unreadable\"\n /** The command received an invalid argument. */\n | \"invalid-argument\";\n\n/**\n * The document that the inspect command writes when it cannot produce a\n * report. The command then exits with code 2.\n */\nexport type InspectionProblem = {\n /** The stable code of the condition. */\n code: InspectionProblemCode;\n /** The description of the condition. */\n detail: string;\n /** The short name of the condition. */\n title: string;\n /** The version of this problem shape. */\n version: number;\n};\n","import { relative, sep } from \"node:path\";\nimport { toRoutePattern, toRouteSegments } from \"../router\";\nimport type { EnvSchema } from \"../security\";\nimport {\n inspectRoutePolicies,\n type DemiurgeVitePluginOptions,\n} from \"../vite/plugin\";\nimport type { RouteFileInspection } from \"../vite/policy-verification\";\nimport {\n STATIC_POLICY_REPORT_VERSION,\n type StaticPolicyReport,\n type StaticRouteReport,\n} from \"./types\";\n\nexport type StaticPolicyReportOptions = {\n /** The plugin options of the application. */\n options?: DemiurgeVitePluginOptions;\n /** The absolute path of the project root. */\n root: string;\n};\n\n// A build knows the route tree and the policy cascade. It does not know a\n// header, a cookie, a session, or an authorization result, because a request\n// supplies each one. The report names these facts, so a reader learns which\n// answer needs a running application.\nconst requestFacts = [\n \"authorization-result\",\n \"cookie-values\",\n \"csrf-token\",\n \"environment-values\",\n \"rate-limit-state\",\n \"request-headers\",\n \"response-headers\",\n \"session-record\",\n];\n\n/**\n * Builds the static inspection report of an application.\n *\n * The function reads the route tree and resolves the policy cascade through\n * `inspectRoutePolicies`. It loads no route module, so it runs no data loader\n * and no mutation handler.\n */\nexport async function createStaticPolicyReport(\n input: StaticPolicyReportOptions,\n): Promise<StaticPolicyReport> {\n const options = input.options ?? {};\n const pass = await inspectRoutePolicies(input.root, options);\n const routes = pass.inspections\n .map((inspection) => toStaticRouteReport(pass.routesDir, inspection))\n .sort((left, right) => left.file.localeCompare(right.file));\n\n return {\n findings: pass.findings,\n redactions: [],\n request: requestFacts,\n resolutions: {\n findings: \"static\",\n redactions: \"static\",\n request: \"request\",\n routes: \"static\",\n },\n routes,\n routesDir: toPosixPath(relative(input.root, pass.routesDir)),\n version: STATIC_POLICY_REPORT_VERSION,\n };\n}\n\n/** Reads the names of the variables that `env.secret(...)` declared. */\nexport function findSecretEnvKeys(schema: EnvSchema | undefined) {\n return Object.entries(schema ?? {})\n .filter(([, variable]) => variable.sensitive)\n .map(([key]) => key)\n .sort();\n}\n\n/** Counts the findings that carry error severity. */\nexport function countErrorFindings(report: StaticPolicyReport) {\n return report.findings.filter((finding) => finding.severity === \"error\")\n .length;\n}\n\n/** Writes the human summary that the command sends to standard error. */\nexport function formatStaticPolicyReportSummary(report: StaticPolicyReport) {\n const errors = countErrorFindings(report);\n const warnings = report.findings.length - errors;\n\n return [\n `Demiurge inspected ${report.routes.length} route files in ${report.routesDir}.`,\n `Findings: ${errors} error, ${warnings} warning.`,\n `The report states ${report.request.length} facts that only a request supplies.`,\n ...report.findings.map((finding) =>\n ` ${finding.severity}: ${toPosixPath(finding.file)} [${finding.code}] ${finding.message}`\n ),\n ].join(\"\\n\");\n}\n\nfunction toStaticRouteReport(\n routesDir: string,\n inspection: RouteFileInspection,\n): StaticRouteReport {\n const file = toPosixPath(relative(routesDir, inspection.file));\n const fileSegments = file.replace(/\\.tsx?$/, \"\").split(\"/\");\n const attached = fileSegments.at(-1)?.startsWith(\"@\") ?? false;\n\n return {\n declaredAccess: inspection.accessState,\n declaredDocumentCsp: inspection.documentCspState,\n declaresDocumentPolicy: inspection.declaresDocumentPolicy,\n file,\n kind: attached\n ? \"attached\"\n : inspection.declaresPageRoute\n ? \"page\"\n : \"resource\",\n methods: inspection.methods,\n ...(attached\n ? {}\n : { pattern: toRoutePattern(toRouteSegments(fileSegments)) }),\n };\n}\n\nfunction toPosixPath(pathname: string) {\n return pathname.split(sep).join(\"/\");\n}\n","import type { ResolvedDemiurgeConfig } from \"../config/types\";\nimport { toPluginOptions } from \"../config/vite\";\nimport {\n countErrorFindings,\n createStaticPolicyReport,\n findSecretEnvKeys,\n formatStaticPolicyReportSummary,\n} from \"./report\";\nimport { serializeInspectionReport } from \"./redact\";\nimport {\n INSPECTION_PROBLEM_VERSION,\n type InspectionProblem,\n type InspectionProblemCode,\n} from \"./types\";\n\n/** The exit codes of the `demiurge inspect` command. */\nexport const INSPECT_EXIT_OK = 0;\nexport const INSPECT_EXIT_FINDINGS = 1;\nexport const INSPECT_EXIT_INVALID = 2;\n\nexport type InspectCommandInput = {\n /** The arguments that follow the command name. */\n arguments: readonly string[];\n /** Reads the configuration of the application. */\n loadConfig: () => Promise<ResolvedDemiurgeConfig>;\n};\n\nexport type InspectCommandResult = {\n /** The exit code of the command. */\n exitCode: number;\n /** The human summary that the command writes to standard error. */\n stderr: string;\n /** The JSON document that the command writes to standard output. */\n stdout: string;\n};\n\n/**\n * Runs the `demiurge inspect` command.\n *\n * The command reads the route tree, resolves the policy cascade, and returns\n * one JSON document. The command loads no route module, so it runs no data\n * loader and no mutation handler.\n */\nexport async function runInspectCommand(\n input: InspectCommandInput,\n): Promise<InspectCommandResult> {\n if (input.arguments.length > 0) {\n return toProblemResult(\n \"invalid-argument\",\n \"The inspect command accepts no argument.\",\n `The command received ${input.arguments.join(\" \")}.`,\n );\n }\n\n let config: ResolvedDemiurgeConfig;\n\n try {\n config = await input.loadConfig();\n } catch (error) {\n return toProblemResult(\n \"configuration-unreadable\",\n \"Demiurge could not read the configuration.\",\n error instanceof Error ? error.message : String(error),\n );\n }\n\n const report = await createStaticPolicyReport({\n options: toPluginOptions(config),\n root: config.root,\n });\n\n return {\n exitCode: countErrorFindings(report) > 0\n ? INSPECT_EXIT_FINDINGS\n : INSPECT_EXIT_OK,\n stderr: formatStaticPolicyReportSummary(report),\n stdout: serializeInspectionReport(report, {\n secretEnvKeys: findSecretEnvKeys(config.env),\n }),\n };\n}\n\nfunction toProblemResult(\n code: InspectionProblemCode,\n title: string,\n detail: string,\n): InspectCommandResult {\n const problem: InspectionProblem = {\n code,\n detail,\n title,\n version: INSPECTION_PROBLEM_VERSION,\n };\n\n return {\n exitCode: INSPECT_EXIT_INVALID,\n stderr: `${title}\\n${detail}`,\n stdout: serializeInspectionReport(problem),\n };\n}\n","import { readFile, readdir } from \"node:fs/promises\";\nimport { isAbsolute, join, relative, resolve, sep } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport type { InlineConfig } from \"vite\";\nimport { createDemiurgeViteConfig } from \"./config/vite\";\nimport type { ResolvedDemiurgeConfig } from \"./config/types\";\nimport { parseClientManifest } from \"./manifest\";\nimport type { NodeBuildRuntime, ServeNodeBuildOptions } from \"./node\";\nimport type { RouteImporter } from \"./route\";\nimport {\n generateVercelStaticOutput,\n generateStaticOutput,\n type GenerateStaticOutputOptions,\n type StaticOutputManifest,\n} from \"./static\";\nimport { generateVercelNodeOutput } from \"./vercel\";\n\nexport { parseClientManifest } from \"./manifest\";\nexport type { ClientBuildManifest } from \"./manifest\";\nexport {\n INSPECT_EXIT_FINDINGS,\n INSPECT_EXIT_INVALID,\n INSPECT_EXIT_OK,\n runInspectCommand,\n} from \"./inspect\";\nexport type { InspectCommandResult } from \"./inspect\";\n\ntype CliEnvironment = Record<string, string | undefined>;\n\nconst cliOptionNames = new Set([\"--host\", \"--origin\", \"--out-dir\", \"--port\"]);\n\nconst CLIENT_ENTRY = \"virtual:demiurge/client-entry\";\nconst SERVER_ENTRY = \"virtual:demiurge/server-entry\";\nconst DEFAULT_CLIENT_OUT_DIR = \"dist\";\nconst DEFAULT_SERVER_OUT_DIR = \"dist/server\";\nconst FRAMEWORK_SERVER_OUT_DIR = \".demiurge/server\";\n\nexport type CliOptions = {\n command: \"build\" | \"dev\" | \"help\" | \"inspect\" | \"preview\" | \"start\";\n host: string;\n origin?: string;\n outDir?: string;\n port: number;\n};\n\nexport type BuildRuntime = {\n build: (config: InlineConfig) => Promise<unknown>;\n createViteConfig: (overrides: InlineConfig) => Promise<InlineConfig>;\n generate: (\n options: GenerateStaticOutputOptions,\n ) => Promise<StaticOutputManifest>;\n importModule: (specifier: string) => Promise<Record<string, unknown>>;\n now: () => number;\n readText: (file: string) => Promise<string>;\n};\n\nexport type BuildResult = {\n deploymentOutDir?: string;\n manifest?: StaticOutputManifest;\n outDir: string;\n serverOutDir?: string;\n};\n\nexport type StartRuntime = {\n importModule: (specifier: string) => Promise<Record<string, unknown>>;\n serve: (options: ServeNodeBuildOptions) => Promise<unknown>;\n};\n\nexport function parseCliArguments(\n arguments_: string[],\n environment: CliEnvironment = {},\n): CliOptions {\n const command = arguments_[0];\n if (!command || command === \"--help\" || command === \"-h\" || command === \"help\") {\n return {\n command: \"help\",\n host: \"localhost\",\n port: 4173,\n };\n }\n if (\n command !== \"build\" && command !== \"dev\" && command !== \"inspect\" &&\n command !== \"preview\" && command !== \"start\"\n ) {\n throw new Error(`Unknown command: ${command}`);\n }\n\n const options: CliOptions = {\n command,\n host: command === \"start\" ? environment.HOST ?? \"127.0.0.1\" : \"localhost\",\n origin: environment.SITE_ORIGIN,\n port: command === \"dev\" ? 5173 : 4173,\n };\n\n for (let index = 1; index < arguments_.length; index += 1) {\n const argument = arguments_[index]!;\n if (argument === \"--help\" || argument === \"-h\") {\n return { command: \"help\", host: \"localhost\", port: 4173 };\n }\n const [name, inlineValue] = argument.split(\"=\", 2);\n if (!cliOptionNames.has(name!)) {\n throw new Error(`Unknown option: ${argument}`);\n }\n const value = inlineValue ?? arguments_[++index];\n if (!value || value.startsWith(\"--\")) {\n throw new Error(`Option ${name} requires a value.`);\n }\n\n if (name === \"--host\") options.host = value;\n if (name === \"--origin\") options.origin = value;\n if (name === \"--out-dir\") options.outDir = value;\n if (name === \"--port\") {\n const port = Number(value);\n if (!Number.isSafeInteger(port) || port < 0 || port > 65_535) {\n throw new Error(\"The server port must be an integer from 0 through 65535.\");\n }\n options.port = port;\n }\n }\n\n return options;\n}\n\nexport const helpText = `Usage: demiurge <command> [options]\n\nCommands:\n dev Start the development server\n build Build production output\n start Run built Node production output\n inspect Write the static inspection report as JSON\n preview Serve static output with its declared headers\n\nOptions:\n --host <host> Set the server host (start: HOST or 127.0.0.1; otherwise: localhost)\n --origin <origin> Set the build origin (default: SITE_ORIGIN)\n --out-dir <directory> Set the client output directory (default: dist)\n --port <port> Set the server port (dev: 5173, preview: 4173)\n -h, --help Show this help\n\nThe inspect command writes JSON to standard output and a summary to standard\nerror. It exits with 0 for no error finding, 1 for at least one error finding,\nand 2 for an invalid argument or an unreadable configuration.\n\nDemiurge reads demiurge.config.ts from the project root.`;\n\nexport async function runDev(\n options: CliOptions,\n config: ResolvedDemiurgeConfig,\n) {\n const { createServer } = await import(\"vite\");\n const server = await createServer(\n await createDemiurgeViteConfig({\n config,\n overrides: {\n mode: \"development\",\n server: { host: options.host, port: options.port },\n },\n }),\n );\n await server.listen();\n return server;\n}\n\nexport async function runBuild(\n options: CliOptions,\n config: ResolvedDemiurgeConfig,\n runtime?: BuildRuntime,\n): Promise<BuildResult> {\n const root = config.root;\n const build = runtime?.build ?? (await import(\"vite\")).build;\n const createViteConfig = runtime?.createViteConfig ??\n ((overrides: InlineConfig) => createDemiurgeViteConfig({ config, overrides }));\n\n const outDir = resolve(\n root,\n options.outDir ?? config.deployment?.outDir ?? DEFAULT_CLIENT_OUT_DIR,\n );\n const frameworkServerOutDir = resolve(root, FRAMEWORK_SERVER_OUT_DIR);\n\n await validateBuildOutputDirectory(\n root,\n outDir,\n join(root, \"public\"),\n frameworkServerOutDir,\n );\n\n await build(\n await createViteConfig({\n define: { \"process.env.NODE_ENV\": JSON.stringify(\"production\") },\n mode: \"production\",\n build: {\n emptyOutDir: true,\n outDir,\n rollupOptions: { input: CLIENT_ENTRY },\n },\n }),\n );\n\n const applicationServer = config.deployment?.server;\n const serverOutDir = applicationServer\n ? resolve(root, applicationServer.outDir ?? DEFAULT_SERVER_OUT_DIR)\n : undefined;\n\n if (applicationServer && serverOutDir) {\n await build(\n await createViteConfig({\n define: { \"process.env.NODE_ENV\": JSON.stringify(\"production\") },\n mode: \"production\",\n build: {\n copyPublicDir: false,\n emptyOutDir: true,\n outDir: serverOutDir,\n rollupOptions: {\n input: applicationServer.entry\n ? resolve(root, applicationServer.entry)\n : SERVER_ENTRY,\n output: { entryFileNames: \"server-entry.js\" },\n },\n ssr: true,\n },\n ...(applicationServer.provider\n ? {\n ssr: {\n external: [\"@demiurgejs/core\", \"react\", \"react-dom\"],\n noExternal: true,\n },\n }\n : {}),\n }),\n );\n }\n\n const provider = applicationServer?.provider;\n if (provider && applicationServer && serverOutDir) {\n if (config.security?.staticFileHeaders?.length) {\n throw new Error(\n \"Vercel Node deployment does not support security.staticFileHeaders. Remove the rules or use a deployment that serves the browser output directly.\",\n );\n }\n const deploymentOutDir = await generateVercelNodeOutput({\n clientDir: outDir,\n deployment: provider,\n projectRoot: root,\n serverDir: serverOutDir,\n });\n return { deploymentOutDir, outDir, serverOutDir };\n }\n\n if (!config.deployment?.static) return { outDir, serverOutDir };\n\n const staticResult = await buildStaticOutput({\n build,\n config,\n createViteConfig,\n frameworkServerOutDir,\n options,\n outDir,\n root,\n runtime,\n });\n\n return { ...staticResult, outDir, serverOutDir };\n}\n\nexport async function runStart(\n options: CliOptions,\n config: ResolvedDemiurgeConfig,\n environment: CliEnvironment = process.env,\n runtime?: StartRuntime,\n) {\n const applicationServer = config.deployment?.server;\n if (!applicationServer) {\n throw new Error(\n \"The start command requires deployment.server in demiurge.config.ts.\",\n );\n }\n\n const allowedHosts = environment.ALLOWED_HOSTS\n ?.split(\",\")\n .map((value) => value.trim())\n .filter(Boolean);\n if (!allowedHosts?.length) {\n throw new Error(\n \"The start command requires ALLOWED_HOSTS as a comma-separated host allowlist.\",\n );\n }\n\n const root = config.root;\n const clientDir = resolve(\n root,\n options.outDir ?? config.deployment?.outDir ?? DEFAULT_CLIENT_OUT_DIR,\n );\n const serverOutDir = resolve(\n root,\n applicationServer.outDir ?? DEFAULT_SERVER_OUT_DIR,\n );\n const serverEntryUrl = pathToFileURL(join(serverOutDir, \"server-entry.js\")).href;\n const serverEntry = runtime\n ? await runtime.importModule(serverEntryUrl)\n : await import(serverEntryUrl);\n if (!isNodeBuildRuntime(serverEntry)) {\n throw new Error(\n \"The application server bundle does not export a Node build runtime.\",\n );\n }\n\n const serve = runtime?.serve ?? (await import(\"./node\")).serveNodeBuild;\n return serve({\n allowedHosts,\n base: pathToFileURL(`${root}/`).href,\n clientDir: relative(root, clientDir),\n createHandler: serverEntry.createHandler,\n env: environment,\n host: options.host,\n port: options.port,\n readyPath: \"/.well-known/ready\",\n shutdown: { signals: [\"SIGINT\", \"SIGTERM\"] },\n static: serverEntry.createStatic,\n });\n}\n\nfunction isNodeBuildRuntime(value: Record<string, unknown>): value is NodeBuildRuntime {\n return typeof value.createHandler === \"function\" &&\n (value.createStatic === undefined || typeof value.createStatic === \"function\");\n}\n\nasync function buildStaticOutput({\n build,\n config,\n createViteConfig,\n frameworkServerOutDir,\n options,\n outDir,\n root,\n runtime,\n}: {\n build: (config: InlineConfig) => Promise<unknown>;\n config: ResolvedDemiurgeConfig;\n createViteConfig: (overrides: InlineConfig) => Promise<InlineConfig>;\n frameworkServerOutDir: string;\n options: CliOptions;\n outDir: string;\n root: string;\n runtime?: BuildRuntime;\n}) {\n await build(\n await createViteConfig({\n define: { \"process.env.NODE_ENV\": JSON.stringify(\"production\") },\n mode: \"production\",\n build: {\n copyPublicDir: false,\n emptyOutDir: true,\n outDir: frameworkServerOutDir,\n rollupOptions: {\n input: SERVER_ENTRY,\n output: { entryFileNames: \"server-entry.js\" },\n },\n ssr: true,\n },\n }),\n );\n\n const clientManifest = parseClientManifest(\n runtime\n ? await runtime.readText(resolve(outDir, \"demiurge-manifest.json\"))\n : await readFile(resolve(outDir, \"demiurge-manifest.json\"), \"utf8\"),\n );\n const serverEntryUrl = `${\n pathToFileURL(resolve(frameworkServerOutDir, \"server-entry.js\")).href\n }?build=${runtime?.now() ?? Date.now()}`;\n const serverEntry = runtime\n ? await runtime.importModule(serverEntryUrl)\n : await import(serverEntryUrl);\n if (!isRouteImporterRecord(serverEntry.routes)) {\n throw new Error(\"The framework server bundle does not export routes.\");\n }\n\n const manifest = await (runtime?.generate ?? generateStaticOutput)({\n fonts: config.assets?.fonts,\n images: config.assets?.images,\n origin: options.origin ?? config.deployment?.static?.origin,\n outDir,\n root,\n routes: serverEntry.routes,\n ssr: clientManifest,\n staticFileHeaders: config.security?.staticFileHeaders ?? [],\n });\n\n const provider = config.deployment?.static?.provider;\n const deploymentOutDir = provider\n ? await generateVercelStaticOutput({\n deployment: provider,\n manifest,\n outDir,\n projectRoot: root,\n })\n : undefined;\n\n return { deploymentOutDir, manifest };\n}\n\nexport function resolvePreviewOutputDirectory(\n root: string,\n outDir: string | undefined,\n configuredOutDir?: string,\n) {\n return resolve(root, outDir ?? configuredOutDir ?? DEFAULT_CLIENT_OUT_DIR);\n}\n\nexport async function validateBuildOutputDirectory(\n root: string,\n outDir: string,\n publicDir: false | string,\n serverOutDir: string,\n) {\n const pathFromRoot = relative(root, outDir);\n if (\n !pathFromRoot ||\n pathFromRoot === \"..\" ||\n pathFromRoot.startsWith(`..${sep}`) ||\n isAbsolute(pathFromRoot)\n ) {\n throw new Error(\"The static output directory must be inside the Vite root.\");\n }\n\n if (publicDir && pathsOverlap(outDir, publicDir)) {\n throw new Error(\"The static output directory must not overlap the Vite public directory.\");\n }\n\n if (pathsOverlap(outDir, serverOutDir)) {\n throw new Error(\"The static output directory must not overlap the framework server directory.\");\n }\n\n let entries: string[];\n try {\n entries = await readdir(outDir);\n } catch (error) {\n if (isMissingPath(error)) return;\n throw error;\n }\n\n if (\n entries.length &&\n !entries.includes(\"demiurge-manifest.json\") &&\n !entries.includes(\"demiurge-static-manifest.json\")\n ) {\n throw new Error(\n \"The static output directory contains files that a Demiurge build did not create.\",\n );\n }\n}\n\nfunction isRouteImporterRecord(\n value: unknown,\n): value is Record<string, RouteImporter> {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n return false;\n }\n\n return Object.values(value).every((load) => typeof load === \"function\");\n}\n\nfunction pathsOverlap(left: string, right: string) {\n const fromLeft = relative(left, right);\n const fromRight = relative(right, left);\n return isSameOrChildPath(fromLeft) || isSameOrChildPath(fromRight);\n}\n\nfunction isSameOrChildPath(pathname: string) {\n return !pathname ||\n (pathname !== \"..\" && !pathname.startsWith(`..${sep}`) &&\n !isAbsolute(pathname));\n}\n\nfunction isMissingPath(error: unknown) {\n return error instanceof Error && \"code\" in error && error.code === \"ENOENT\";\n}\n"],"names":["STATIC_POLICY_REPORT_VERSION","INSPECTION_PROBLEM_VERSION","requestFacts","createStaticPolicyReport","input","options","pass","inspectRoutePolicies","routes","inspection","toStaticRouteReport","left","right","toPosixPath","relative","findSecretEnvKeys","schema","variable","key","countErrorFindings","report","finding","formatStaticPolicyReportSummary","errors","warnings","routesDir","file","fileSegments","attached","toRoutePattern","toRouteSegments","pathname","sep","INSPECT_EXIT_OK","INSPECT_EXIT_FINDINGS","INSPECT_EXIT_INVALID","runInspectCommand","toProblemResult","config","error","toPluginOptions","serializeInspectionReport","code","title","detail","problem","cliOptionNames","CLIENT_ENTRY","SERVER_ENTRY","DEFAULT_CLIENT_OUT_DIR","DEFAULT_SERVER_OUT_DIR","FRAMEWORK_SERVER_OUT_DIR","parseCliArguments","arguments_","environment","command","index","argument","name","inlineValue","value","port","helpText","runDev","createServer","server","createDemiurgeViteConfig","runBuild","runtime","root","build","createViteConfig","overrides","outDir","resolve","frameworkServerOutDir","validateBuildOutputDirectory","join","applicationServer","serverOutDir","provider","generateVercelNodeOutput","buildStaticOutput","runStart","allowedHosts","clientDir","serverEntryUrl","pathToFileURL","serverEntry","isNodeBuildRuntime","clientManifest","parseClientManifest","readFile","isRouteImporterRecord","manifest","generateStaticOutput","generateVercelStaticOutput","resolvePreviewOutputDirectory","configuredOutDir","publicDir","pathFromRoot","isAbsolute","pathsOverlap","entries","readdir","isMissingPath","load","fromLeft","fromRight","isSameOrChildPath"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { existsSync as f } from "node:fs";
2
2
  import { join as u, resolve as a, dirname as s } from "node:path";
3
- import { D as r, v as d } from "../chunks/vite-QoqrGl6f.js";
4
- import { c as F, t as M } from "../chunks/vite-QoqrGl6f.js";
3
+ import { D as r, v as d } from "../chunks/vite-BADZA8Fl.js";
4
+ import { c as F, t as M } from "../chunks/vite-BADZA8Fl.js";
5
5
  function x(e) {
6
6
  return e;
7
7
  }
@@ -4,6 +4,7 @@ import type { ImagePolicy } from "../platform/images";
4
4
  import type { LocaleConfiguration } from "../routing";
5
5
  import type { EnvSchema } from "../security/env";
6
6
  import type { StaticFileHeaderPatternRule, VercelStaticDeployment } from "../static";
7
+ import type { VercelNodeDeployment } from "../vercel/config";
7
8
  export type DemiurgeRoutingConfig<Locale extends string = string> = {
8
9
  locales?: LocaleConfiguration<Locale>;
9
10
  routesDir?: string;
@@ -26,8 +27,9 @@ export type DemiurgeAssetsConfig = {
26
27
  images?: ImagePolicy;
27
28
  };
28
29
  export type DemiurgeServerDeploymentConfig = {
29
- entry: string;
30
+ entry?: string;
30
31
  outDir?: string;
32
+ provider?: VercelNodeDeployment;
31
33
  };
32
34
  export type DemiurgeStaticDeploymentConfig = {
33
35
  origin?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/config/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/config/types.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/config/validate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE;CAI3D;AA2BD,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,OAAO,EACd,UAAU,EAAE,MAAM,GACjB,cAAc,CAoIhB;AA4HD,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,UAW3C"}
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/config/validate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE;CAI3D;AA2BD,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,OAAO,EACd,UAAU,EAAE,MAAM,GACjB,cAAc,CA6IhB;AA4HD,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,UAW3C"}
@@ -46,7 +46,12 @@ export type CacheStoreEntry = {
46
46
  tags: readonly string[];
47
47
  value: unknown;
48
48
  };
49
+ export type CacheStoreAtomicity = "best-effort" | "strong";
50
+ export type CacheStoreCapabilities = {
51
+ atomicity: CacheStoreAtomicity;
52
+ };
49
53
  export type CacheStore = {
54
+ capabilities: CacheStoreCapabilities;
50
55
  acquireRefreshLease?: (key: string, token: string, expiresAt: number) => MaybePromise<boolean>;
51
56
  delete: (key: string) => MaybePromise<boolean>;
52
57
  get: (key: string) => MaybePromise<CacheStoreEntry | undefined>;
@@ -1 +1 @@
1
- {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/data/cache.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/data/cache.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  export { cacheNotFound, CacheNotFoundError, createCache, createInvalidation, createMemoryCache, createMemoryCacheStore, defineTags, isCacheNotFoundError, parseCacheDuration, query, serializeCacheKey, serializeCacheNamespace, serializeCacheTag, tag, } from "./cache";
2
2
  export { createMemoryIdempotencyStore, runIdempotentMutation, } from "./idempotency";
3
3
  export { createTieredCacheStore } from "./tiered";
4
- export type { Cache, CacheDuration, CacheKey, CacheKeyPart, CacheRequest, CacheScope, CacheNamespace, CacheStore, CacheStoreEntry, CacheTag, CreateCacheOptions, Invalidation, InvalidationResult, Query, QueryDefinition, MemoryCacheOptions, MemoryCacheStoreOptions, } from "./cache";
4
+ export type { Cache, CacheDuration, CacheKey, CacheKeyPart, CacheRequest, CacheStoreAtomicity, CacheStoreCapabilities, CacheScope, CacheNamespace, CacheStore, CacheStoreEntry, CacheTag, CreateCacheOptions, Invalidation, InvalidationResult, Query, QueryDefinition, MemoryCacheOptions, MemoryCacheStoreOptions, } from "./cache";
5
5
  export type { TieredCacheStoreOptions } from "./tiered";
6
6
  export type { IdempotencyRequest, IdempotencyResult, IdempotencyStore, MemoryIdempotencyStoreOptions, } from "./idempotency";
7
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/data/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,kBAAkB,EAClB,WAAW,EACX,kBAAkB,EAClB,iBAAiB,EACjB,sBAAsB,EACtB,UAAU,EACV,oBAAoB,EACpB,kBAAkB,EAClB,KAAK,EACL,iBAAiB,EACjB,uBAAuB,EACvB,iBAAiB,EACjB,GAAG,GACJ,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,4BAA4B,EAC5B,qBAAqB,GACtB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAClD,YAAY,EACV,KAAK,EACL,aAAa,EACb,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,cAAc,EACd,UAAU,EACV,eAAe,EACf,QAAQ,EACR,kBAAkB,EAClB,YAAY,EACZ,kBAAkB,EAClB,KAAK,EACL,eAAe,EACf,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,SAAS,CAAC;AACjB,YAAY,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AACxD,YAAY,EACV,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,6BAA6B,GAC9B,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/data/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,kBAAkB,EAClB,WAAW,EACX,kBAAkB,EAClB,iBAAiB,EACjB,sBAAsB,EACtB,UAAU,EACV,oBAAoB,EACpB,kBAAkB,EAClB,KAAK,EACL,iBAAiB,EACjB,uBAAuB,EACvB,iBAAiB,EACjB,GAAG,GACJ,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,4BAA4B,EAC5B,qBAAqB,GACtB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAClD,YAAY,EACV,KAAK,EACL,aAAa,EACb,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,mBAAmB,EACnB,sBAAsB,EACtB,UAAU,EACV,cAAc,EACd,UAAU,EACV,eAAe,EACf,QAAQ,EACR,kBAAkB,EAClB,YAAY,EACZ,kBAAkB,EAClB,KAAK,EACL,eAAe,EACf,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,SAAS,CAAC;AACjB,YAAY,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AACxD,YAAY,EACV,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,6BAA6B,GAC9B,MAAM,eAAe,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../../src/data/testing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAmB,MAAM,SAAS,CAAC;AAE3D,KAAK,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;AAEtC,MAAM,MAAM,iBAAiB,GAAG,MAAM,YAAY,CAAC,UAAU,CAAC,CAAC;AAE/D,wBAAsB,wBAAwB,CAC5C,WAAW,EAAE,iBAAiB,iBA2G/B;AAED,wBAAsB,+BAA+B,CACnD,WAAW,EAAE,iBAAiB,iBAwF/B"}
1
+ {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../../src/data/testing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAmB,MAAM,SAAS,CAAC;AAE3D,KAAK,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;AAEtC,MAAM,MAAM,iBAAiB,GAAG,MAAM,YAAY,CAAC,UAAU,CAAC,CAAC;AAE/D,wBAAsB,wBAAwB,CAC5C,WAAW,EAAE,iBAAiB,iBAuI/B;AAED,wBAAsB,+BAA+B,CACnD,WAAW,EAAE,iBAAiB,iBAqG/B"}
@@ -1,156 +1,190 @@
1
- async function m(i) {
2
- const e = await i(), s = `demiurge-contract:${Date.now()}:${Math.random()}`, a = `${s}:alpha`, o = `${s}:beta`, u = `${s}:gamma`, r = `${s}:delta`, l = `${s}:tag:alpha`, g = `${s}:tag:beta`, c = `${s}:tag:delta`, n = Date.now() + 6e4, h = {
3
- expiresAt: n,
4
- staleUntil: n + 5e3,
1
+ async function $(n) {
2
+ const e = await n(), s = `demiurge-contract:${Date.now()}:${Math.random()}`, a = `${s}:alpha`, u = `${s}:beta`, r = `${s}:gamma`, g = `${s}:delta`, o = `${s}:atomic`, l = `${s}:tag:alpha`, m = `${s}:tag:beta`, w = `${s}:tag:delta`, i = Date.now() + 6e4, h = {
3
+ expiresAt: i,
4
+ staleUntil: i + 5e3,
5
5
  tags: [l],
6
6
  value: { id: "alpha", revision: 1 }
7
7
  };
8
8
  try {
9
+ if (t(
10
+ e.capabilities.atomicity === "best-effort" || e.capabilities.atomicity === "strong",
11
+ "capabilities.atomicity must be `best-effort` or `strong`"
12
+ ), e.capabilities.atomicity === "strong") {
13
+ const f = `${s}:tag:atomic`;
14
+ await e.set(o, {
15
+ expiresAt: i,
16
+ staleUntil: i,
17
+ tags: [f],
18
+ value: "atomic"
19
+ });
20
+ const y = await Promise.all([
21
+ e.invalidateTags([f]),
22
+ e.invalidateTags([f])
23
+ ]);
24
+ t(
25
+ y.reduce((p, b) => p + b, 0) === 1,
26
+ "strong atomicity must count one concurrent tag invalidation exactly once"
27
+ ), t(
28
+ await e.get(o) === void 0,
29
+ "strong atomicity must remove an entry during concurrent tag invalidation"
30
+ );
31
+ }
9
32
  t(
10
33
  await e.get(a) === void 0,
11
34
  "get() must return undefined for a missing key"
12
- ), await e.set(a, h), d(await e.get(a), h, "set() then get()");
13
- const f = {
35
+ ), await e.set(a, h), v(await e.get(a), h, "set() then get()");
36
+ const d = {
14
37
  ...h,
15
38
  value: { id: "alpha", revision: 2 }
16
39
  };
17
- await e.set(a, f), d(
40
+ await e.set(a, d), v(
18
41
  await e.get(a),
19
- f,
42
+ d,
20
43
  "set() must replace an existing key"
21
- ), await e.set(o, {
22
- expiresAt: n + 1e4,
23
- staleUntil: n + 15e3,
24
- tags: [g],
44
+ ), await e.set(u, {
45
+ expiresAt: i + 1e4,
46
+ staleUntil: i + 15e3,
47
+ tags: [m],
25
48
  value: "beta"
26
- }), await e.set(u, {
27
- expiresAt: n + 2e4,
28
- staleUntil: n + 25e3,
29
- tags: [l, g],
49
+ }), await e.set(r, {
50
+ expiresAt: i + 2e4,
51
+ staleUntil: i + 25e3,
52
+ tags: [l, m],
30
53
  value: ["gamma"]
31
54
  }), t(
32
55
  await e.invalidateTags([l]) === 2,
33
56
  "invalidateTags() must return the number of entries deleted, counting each entry once"
34
57
  ), t(
35
- await e.get(a) === void 0 && await e.get(u) === void 0,
58
+ await e.get(a) === void 0 && await e.get(r) === void 0,
36
59
  "invalidateTags() must delete every entry carrying a matching tag"
37
60
  ), t(
38
- (await e.get(o))?.value === "beta",
61
+ (await e.get(u))?.value === "beta",
39
62
  "invalidateTags() must preserve entries with no matching tag"
40
63
  ), t(
41
- await e.delete(o) === !0,
64
+ await e.delete(u) === !0,
42
65
  "delete() must report an existing key"
43
66
  ), t(
44
- await e.delete(o) === !1,
67
+ await e.delete(u) === !1,
45
68
  "delete() must report a missing key"
46
69
  );
47
- const w = {
48
- expiresAt: n,
70
+ const c = {
71
+ expiresAt: i,
49
72
  negative: !0,
50
- staleUntil: n,
51
- tags: [c],
73
+ staleUntil: i,
74
+ tags: [w],
52
75
  value: "not found"
53
76
  };
54
- await e.set(r, w), d(
55
- await e.get(r),
56
- w,
77
+ await e.set(g, c), v(
78
+ await e.get(g),
79
+ c,
57
80
  "set() then get() for a negative entry"
58
81
  ), t(
59
- await e.invalidateTags([c]) === 1,
82
+ await e.invalidateTags([w]) === 1,
60
83
  "invalidateTags() must delete a negative entry carrying a matching tag"
61
84
  ), t(
62
- await e.get(r) === void 0,
85
+ await e.get(g) === void 0,
63
86
  "invalidateTags() must remove a negative entry the same as a positive one"
64
87
  );
65
88
  } finally {
66
89
  await Promise.all([
67
90
  e.delete(a),
68
- e.delete(o),
69
91
  e.delete(u),
70
- e.delete(r)
92
+ e.delete(r),
93
+ e.delete(g),
94
+ e.delete(o)
71
95
  ]);
72
96
  }
73
97
  }
74
- async function v(i) {
75
- const e = await i(), s = `demiurge-refresh-contract:${Date.now()}:${Math.random()}`, a = `${s}:entry`, o = `${s}:tag`, u = `${s}:first`, r = `${s}:second`, l = Date.now() + 6e4;
98
+ async function R(n) {
99
+ const e = await n(), s = `demiurge-refresh-contract:${Date.now()}:${Math.random()}`, a = `${s}:entry`, u = `${s}:tag`, r = `${s}:first`, g = `${s}:second`, o = Date.now() + 6e4;
76
100
  t(
77
101
  !!(e.acquireRefreshLease && e.publishRefresh && e.releaseRefreshLease),
78
102
  "SWR support requires acquireRefreshLease(), publishRefresh(), and releaseRefreshLease()"
79
103
  );
80
- const g = e.acquireRefreshLease, c = e.publishRefresh, n = e.releaseRefreshLease, h = {
104
+ const l = e.acquireRefreshLease, m = e.publishRefresh, w = e.releaseRefreshLease, i = {
81
105
  expiresAt: Date.now() - 1,
82
106
  staleUntil: Date.now() + 12e4,
83
- tags: [o],
107
+ tags: [u],
84
108
  value: "original"
85
- }, f = {
86
- ...h,
109
+ }, h = {
110
+ ...i,
87
111
  expiresAt: Date.now() + 6e4,
88
112
  value: "refreshed"
89
113
  };
90
114
  try {
91
- await e.set(a, h), t(
92
- await g(a, u, l),
93
- "acquireRefreshLease() must acquire an unowned key"
94
- ), t(
95
- !await g(a, r, l),
96
- "acquireRefreshLease() must exclude a second owner"
97
- ), t(
98
- !await c(a, r, f),
115
+ await e.set(a, i);
116
+ let d, c;
117
+ if (e.capabilities.atomicity === "strong") {
118
+ const f = await Promise.all([
119
+ l(a, r, o),
120
+ l(a, g, o)
121
+ ]);
122
+ t(
123
+ f.filter(Boolean).length === 1,
124
+ "strong atomicity must allow exactly one concurrent refresh lease owner"
125
+ ), d = f[0] ? r : g, c = f[0] ? g : r;
126
+ } else
127
+ t(
128
+ await l(a, r, o),
129
+ "acquireRefreshLease() must acquire an unowned key"
130
+ ), d = r, c = g;
131
+ t(
132
+ !await m(a, c, h),
99
133
  "publishRefresh() must reject a non-owner token"
100
- ), await n(a, r), t(
101
- !await g(a, r, l),
134
+ ), await w(a, c), t(
135
+ !await l(a, c, o),
102
136
  "releaseRefreshLease() must not release another owner's lease"
103
137
  ), t(
104
- await c(a, u, f),
138
+ await m(a, d, h),
105
139
  "publishRefresh() must atomically publish for the current owner"
106
- ), d(
140
+ ), v(
107
141
  await e.get(a),
108
- f,
142
+ h,
109
143
  "publishRefresh() for the current owner"
110
144
  ), t(
111
- await g(a, r, l),
145
+ await l(a, c, o),
112
146
  "successful publication must release the refresh lease"
113
147
  ), t(await e.delete(a), "delete() must remove the refreshed entry"), t(
114
- !await c(a, r, h),
148
+ !await m(a, c, i),
115
149
  "delete() must cancel an in-flight refresh lease"
116
- ), await e.set(a, h), t(
117
- await g(a, u, l),
150
+ ), await e.set(a, i), t(
151
+ await l(a, r, o),
118
152
  "a lease must be reusable after deletion"
119
153
  ), t(
120
- await e.invalidateTags([o]) === 1,
154
+ await e.invalidateTags([u]) === 1,
121
155
  "invalidateTags() must remove the leased entry"
122
156
  ), t(
123
- !await c(a, u, f),
157
+ !await m(a, r, h),
124
158
  "tag invalidation must cancel an in-flight refresh lease"
125
159
  );
126
160
  } finally {
127
161
  await e.delete(a);
128
162
  }
129
163
  }
130
- function d(i, e, s) {
131
- t(!!i, `${s} must preserve the entry`), t(
132
- i?.expiresAt === e.expiresAt,
164
+ function v(n, e, s) {
165
+ t(!!n, `${s} must preserve the entry`), t(
166
+ n?.expiresAt === e.expiresAt,
133
167
  `${s} must preserve expiresAt`
134
168
  ), t(
135
- !!i?.negative == !!e.negative,
169
+ !!n?.negative == !!e.negative,
136
170
  `${s} must preserve the negative flag`
137
171
  ), t(
138
- i?.staleUntil === e.staleUntil,
172
+ n?.staleUntil === e.staleUntil,
139
173
  `${s} must preserve staleUntil`
140
174
  ), t(
141
- JSON.stringify(i?.tags) === JSON.stringify(e.tags),
175
+ JSON.stringify(n?.tags) === JSON.stringify(e.tags),
142
176
  `${s} must preserve tags`
143
177
  ), t(
144
- JSON.stringify(i?.value) === JSON.stringify(e.value),
178
+ JSON.stringify(n?.value) === JSON.stringify(e.value),
145
179
  `${s} must preserve JSON-compatible values`
146
180
  );
147
181
  }
148
- function t(i, e) {
149
- if (!i)
182
+ function t(n, e) {
183
+ if (!n)
150
184
  throw new Error(`Cache store contract failed: ${e}.`);
151
185
  }
152
186
  export {
153
- m as verifyCacheStoreContract,
154
- v as verifyCacheStoreRefreshContract
187
+ $ as verifyCacheStoreContract,
188
+ R as verifyCacheStoreRefreshContract
155
189
  };
156
190
  //# sourceMappingURL=testing.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"testing.js","sources":["../../src/data/testing.ts"],"sourcesContent":["import type { CacheStore, CacheStoreEntry } from \"./cache\";\n\ntype MaybePromise<T> = T | Promise<T>;\n\nexport type CacheStoreFactory = () => MaybePromise<CacheStore>;\n\nexport async function verifyCacheStoreContract(\n createStore: CacheStoreFactory,\n) {\n const store = await createStore();\n const prefix = `demiurge-contract:${Date.now()}:${Math.random()}`;\n const alphaKey = `${prefix}:alpha`;\n const betaKey = `${prefix}:beta`;\n const gammaKey = `${prefix}:gamma`;\n const deltaKey = `${prefix}:delta`;\n const alphaTag = `${prefix}:tag:alpha`;\n const betaTag = `${prefix}:tag:beta`;\n const deltaTag = `${prefix}:tag:delta`;\n const future = Date.now() + 60_000;\n const alpha = {\n expiresAt: future,\n staleUntil: future + 5_000,\n tags: [alphaTag],\n value: { id: \"alpha\", revision: 1 },\n } satisfies CacheStoreEntry;\n\n try {\n assert(\n await store.get(alphaKey) === undefined,\n \"get() must return undefined for a missing key\",\n );\n\n await store.set(alphaKey, alpha);\n assertEntry(await store.get(alphaKey), alpha, \"set() then get()\");\n\n const updatedAlpha = {\n ...alpha,\n value: { id: \"alpha\", revision: 2 },\n } satisfies CacheStoreEntry;\n await store.set(alphaKey, updatedAlpha);\n assertEntry(\n await store.get(alphaKey),\n updatedAlpha,\n \"set() must replace an existing key\",\n );\n\n await store.set(betaKey, {\n expiresAt: future + 10_000,\n staleUntil: future + 15_000,\n tags: [betaTag],\n value: \"beta\",\n });\n await store.set(gammaKey, {\n expiresAt: future + 20_000,\n staleUntil: future + 25_000,\n tags: [alphaTag, betaTag],\n value: [\"gamma\"],\n });\n\n assert(\n await store.invalidateTags([alphaTag]) === 2,\n \"invalidateTags() must return the number of entries deleted, counting each entry once\",\n );\n assert(\n await store.get(alphaKey) === undefined &&\n await store.get(gammaKey) === undefined,\n \"invalidateTags() must delete every entry carrying a matching tag\",\n );\n assert(\n (await store.get(betaKey))?.value === \"beta\",\n \"invalidateTags() must preserve entries with no matching tag\",\n );\n assert(\n await store.delete(betaKey) === true,\n \"delete() must report an existing key\",\n );\n assert(\n await store.delete(betaKey) === false,\n \"delete() must report a missing key\",\n );\n\n // A negative entry (a loader's `cacheNotFound()` result) round-trips\n // like any other entry, and tag invalidation clears it the same way it\n // clears a positive result.\n const delta = {\n expiresAt: future,\n negative: true,\n staleUntil: future,\n tags: [deltaTag],\n value: \"not found\",\n } satisfies CacheStoreEntry;\n\n await store.set(deltaKey, delta);\n assertEntry(\n await store.get(deltaKey),\n delta,\n \"set() then get() for a negative entry\",\n );\n assert(\n await store.invalidateTags([deltaTag]) === 1,\n \"invalidateTags() must delete a negative entry carrying a matching tag\",\n );\n assert(\n await store.get(deltaKey) === undefined,\n \"invalidateTags() must remove a negative entry the same as a positive one\",\n );\n } finally {\n await Promise.all([\n store.delete(alphaKey),\n store.delete(betaKey),\n store.delete(gammaKey),\n store.delete(deltaKey),\n ]);\n }\n}\n\nexport async function verifyCacheStoreRefreshContract(\n createStore: CacheStoreFactory,\n) {\n const store = await createStore();\n const prefix = `demiurge-refresh-contract:${Date.now()}:${Math.random()}`;\n const key = `${prefix}:entry`;\n const tag = `${prefix}:tag`;\n const firstToken = `${prefix}:first`;\n const secondToken = `${prefix}:second`;\n const leaseExpiresAt = Date.now() + 60_000;\n\n assert(\n Boolean(\n store.acquireRefreshLease &&\n store.publishRefresh &&\n store.releaseRefreshLease,\n ),\n \"SWR support requires acquireRefreshLease(), publishRefresh(), and releaseRefreshLease()\",\n );\n\n const acquireRefreshLease = store.acquireRefreshLease!;\n const publishRefresh = store.publishRefresh!;\n const releaseRefreshLease = store.releaseRefreshLease!;\n const original = {\n expiresAt: Date.now() - 1,\n staleUntil: Date.now() + 120_000,\n tags: [tag],\n value: \"original\",\n } satisfies CacheStoreEntry;\n const refreshed = {\n ...original,\n expiresAt: Date.now() + 60_000,\n value: \"refreshed\",\n } satisfies CacheStoreEntry;\n\n try {\n await store.set(key, original);\n assert(\n await acquireRefreshLease(key, firstToken, leaseExpiresAt),\n \"acquireRefreshLease() must acquire an unowned key\",\n );\n assert(\n !await acquireRefreshLease(key, secondToken, leaseExpiresAt),\n \"acquireRefreshLease() must exclude a second owner\",\n );\n assert(\n !await publishRefresh(key, secondToken, refreshed),\n \"publishRefresh() must reject a non-owner token\",\n );\n await releaseRefreshLease(key, secondToken);\n assert(\n !await acquireRefreshLease(key, secondToken, leaseExpiresAt),\n \"releaseRefreshLease() must not release another owner's lease\",\n );\n assert(\n await publishRefresh(key, firstToken, refreshed),\n \"publishRefresh() must atomically publish for the current owner\",\n );\n assertEntry(\n await store.get(key),\n refreshed,\n \"publishRefresh() for the current owner\",\n );\n assert(\n await acquireRefreshLease(key, secondToken, leaseExpiresAt),\n \"successful publication must release the refresh lease\",\n );\n assert(await store.delete(key), \"delete() must remove the refreshed entry\");\n assert(\n !await publishRefresh(key, secondToken, original),\n \"delete() must cancel an in-flight refresh lease\",\n );\n\n await store.set(key, original);\n assert(\n await acquireRefreshLease(key, firstToken, leaseExpiresAt),\n \"a lease must be reusable after deletion\",\n );\n assert(\n await store.invalidateTags([tag]) === 1,\n \"invalidateTags() must remove the leased entry\",\n );\n assert(\n !await publishRefresh(key, firstToken, refreshed),\n \"tag invalidation must cancel an in-flight refresh lease\",\n );\n } finally {\n await store.delete(key);\n }\n}\n\nfunction assertEntry(\n actual: CacheStoreEntry | undefined,\n expected: CacheStoreEntry,\n operation: string,\n) {\n assert(Boolean(actual), `${operation} must preserve the entry`);\n assert(\n actual?.expiresAt === expected.expiresAt,\n `${operation} must preserve expiresAt`,\n );\n assert(\n Boolean(actual?.negative) === Boolean(expected.negative),\n `${operation} must preserve the negative flag`,\n );\n assert(\n actual?.staleUntil === expected.staleUntil,\n `${operation} must preserve staleUntil`,\n );\n assert(\n JSON.stringify(actual?.tags) === JSON.stringify(expected.tags),\n `${operation} must preserve tags`,\n );\n assert(\n JSON.stringify(actual?.value) === JSON.stringify(expected.value),\n `${operation} must preserve JSON-compatible values`,\n );\n}\n\nfunction assert(condition: boolean, requirement: string): asserts condition {\n if (!condition) {\n throw new Error(`Cache store contract failed: ${requirement}.`);\n }\n}\n"],"names":["verifyCacheStoreContract","createStore","store","prefix","alphaKey","betaKey","gammaKey","deltaKey","alphaTag","betaTag","deltaTag","future","alpha","assert","assertEntry","updatedAlpha","delta","verifyCacheStoreRefreshContract","key","tag","firstToken","secondToken","leaseExpiresAt","acquireRefreshLease","publishRefresh","releaseRefreshLease","original","refreshed","actual","expected","operation","condition","requirement"],"mappings":"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"}
1
+ {"version":3,"file":"testing.js","sources":["../../src/data/testing.ts"],"sourcesContent":["import type { CacheStore, CacheStoreEntry } from \"./cache\";\n\ntype MaybePromise<T> = T | Promise<T>;\n\nexport type CacheStoreFactory = () => MaybePromise<CacheStore>;\n\nexport async function verifyCacheStoreContract(\n createStore: CacheStoreFactory,\n) {\n const store = await createStore();\n const prefix = `demiurge-contract:${Date.now()}:${Math.random()}`;\n const alphaKey = `${prefix}:alpha`;\n const betaKey = `${prefix}:beta`;\n const gammaKey = `${prefix}:gamma`;\n const deltaKey = `${prefix}:delta`;\n const atomicKey = `${prefix}:atomic`;\n const alphaTag = `${prefix}:tag:alpha`;\n const betaTag = `${prefix}:tag:beta`;\n const deltaTag = `${prefix}:tag:delta`;\n const future = Date.now() + 60_000;\n const alpha = {\n expiresAt: future,\n staleUntil: future + 5_000,\n tags: [alphaTag],\n value: { id: \"alpha\", revision: 1 },\n } satisfies CacheStoreEntry;\n\n try {\n assert(\n store.capabilities.atomicity === \"best-effort\" ||\n store.capabilities.atomicity === \"strong\",\n \"capabilities.atomicity must be `best-effort` or `strong`\",\n );\n if (store.capabilities.atomicity === \"strong\") {\n const atomicTag = `${prefix}:tag:atomic`;\n await store.set(atomicKey, {\n expiresAt: future,\n staleUntil: future,\n tags: [atomicTag],\n value: \"atomic\",\n });\n const invalidations = await Promise.all([\n store.invalidateTags([atomicTag]),\n store.invalidateTags([atomicTag]),\n ]);\n assert(\n invalidations.reduce((total, count) => total + count, 0) === 1,\n \"strong atomicity must count one concurrent tag invalidation exactly once\",\n );\n assert(\n await store.get(atomicKey) === undefined,\n \"strong atomicity must remove an entry during concurrent tag invalidation\",\n );\n }\n assert(\n await store.get(alphaKey) === undefined,\n \"get() must return undefined for a missing key\",\n );\n\n await store.set(alphaKey, alpha);\n assertEntry(await store.get(alphaKey), alpha, \"set() then get()\");\n\n const updatedAlpha = {\n ...alpha,\n value: { id: \"alpha\", revision: 2 },\n } satisfies CacheStoreEntry;\n await store.set(alphaKey, updatedAlpha);\n assertEntry(\n await store.get(alphaKey),\n updatedAlpha,\n \"set() must replace an existing key\",\n );\n\n await store.set(betaKey, {\n expiresAt: future + 10_000,\n staleUntil: future + 15_000,\n tags: [betaTag],\n value: \"beta\",\n });\n await store.set(gammaKey, {\n expiresAt: future + 20_000,\n staleUntil: future + 25_000,\n tags: [alphaTag, betaTag],\n value: [\"gamma\"],\n });\n\n assert(\n await store.invalidateTags([alphaTag]) === 2,\n \"invalidateTags() must return the number of entries deleted, counting each entry once\",\n );\n assert(\n await store.get(alphaKey) === undefined &&\n await store.get(gammaKey) === undefined,\n \"invalidateTags() must delete every entry carrying a matching tag\",\n );\n assert(\n (await store.get(betaKey))?.value === \"beta\",\n \"invalidateTags() must preserve entries with no matching tag\",\n );\n assert(\n await store.delete(betaKey) === true,\n \"delete() must report an existing key\",\n );\n assert(\n await store.delete(betaKey) === false,\n \"delete() must report a missing key\",\n );\n\n // A negative entry (a loader's `cacheNotFound()` result) round-trips\n // like any other entry, and tag invalidation clears it the same way it\n // clears a positive result.\n const delta = {\n expiresAt: future,\n negative: true,\n staleUntil: future,\n tags: [deltaTag],\n value: \"not found\",\n } satisfies CacheStoreEntry;\n\n await store.set(deltaKey, delta);\n assertEntry(\n await store.get(deltaKey),\n delta,\n \"set() then get() for a negative entry\",\n );\n assert(\n await store.invalidateTags([deltaTag]) === 1,\n \"invalidateTags() must delete a negative entry carrying a matching tag\",\n );\n assert(\n await store.get(deltaKey) === undefined,\n \"invalidateTags() must remove a negative entry the same as a positive one\",\n );\n } finally {\n await Promise.all([\n store.delete(alphaKey),\n store.delete(betaKey),\n store.delete(gammaKey),\n store.delete(deltaKey),\n store.delete(atomicKey),\n ]);\n }\n}\n\nexport async function verifyCacheStoreRefreshContract(\n createStore: CacheStoreFactory,\n) {\n const store = await createStore();\n const prefix = `demiurge-refresh-contract:${Date.now()}:${Math.random()}`;\n const key = `${prefix}:entry`;\n const tag = `${prefix}:tag`;\n const firstToken = `${prefix}:first`;\n const secondToken = `${prefix}:second`;\n const leaseExpiresAt = Date.now() + 60_000;\n\n assert(\n Boolean(\n store.acquireRefreshLease &&\n store.publishRefresh &&\n store.releaseRefreshLease,\n ),\n \"SWR support requires acquireRefreshLease(), publishRefresh(), and releaseRefreshLease()\",\n );\n\n const acquireRefreshLease = store.acquireRefreshLease!;\n const publishRefresh = store.publishRefresh!;\n const releaseRefreshLease = store.releaseRefreshLease!;\n const original = {\n expiresAt: Date.now() - 1,\n staleUntil: Date.now() + 120_000,\n tags: [tag],\n value: \"original\",\n } satisfies CacheStoreEntry;\n const refreshed = {\n ...original,\n expiresAt: Date.now() + 60_000,\n value: \"refreshed\",\n } satisfies CacheStoreEntry;\n\n try {\n await store.set(key, original);\n let ownerToken: string;\n let otherToken: string;\n if (store.capabilities.atomicity === \"strong\") {\n const acquired = await Promise.all([\n acquireRefreshLease(key, firstToken, leaseExpiresAt),\n acquireRefreshLease(key, secondToken, leaseExpiresAt),\n ]);\n assert(\n acquired.filter(Boolean).length === 1,\n \"strong atomicity must allow exactly one concurrent refresh lease owner\",\n );\n ownerToken = acquired[0] ? firstToken : secondToken;\n otherToken = acquired[0] ? secondToken : firstToken;\n } else {\n assert(\n await acquireRefreshLease(key, firstToken, leaseExpiresAt),\n \"acquireRefreshLease() must acquire an unowned key\",\n );\n ownerToken = firstToken;\n otherToken = secondToken;\n }\n assert(\n !await publishRefresh(key, otherToken, refreshed),\n \"publishRefresh() must reject a non-owner token\",\n );\n await releaseRefreshLease(key, otherToken);\n assert(\n !await acquireRefreshLease(key, otherToken, leaseExpiresAt),\n \"releaseRefreshLease() must not release another owner's lease\",\n );\n assert(\n await publishRefresh(key, ownerToken, refreshed),\n \"publishRefresh() must atomically publish for the current owner\",\n );\n assertEntry(\n await store.get(key),\n refreshed,\n \"publishRefresh() for the current owner\",\n );\n assert(\n await acquireRefreshLease(key, otherToken, leaseExpiresAt),\n \"successful publication must release the refresh lease\",\n );\n assert(await store.delete(key), \"delete() must remove the refreshed entry\");\n assert(\n !await publishRefresh(key, otherToken, original),\n \"delete() must cancel an in-flight refresh lease\",\n );\n\n await store.set(key, original);\n assert(\n await acquireRefreshLease(key, firstToken, leaseExpiresAt),\n \"a lease must be reusable after deletion\",\n );\n assert(\n await store.invalidateTags([tag]) === 1,\n \"invalidateTags() must remove the leased entry\",\n );\n assert(\n !await publishRefresh(key, firstToken, refreshed),\n \"tag invalidation must cancel an in-flight refresh lease\",\n );\n } finally {\n await store.delete(key);\n }\n}\n\nfunction assertEntry(\n actual: CacheStoreEntry | undefined,\n expected: CacheStoreEntry,\n operation: string,\n) {\n assert(Boolean(actual), `${operation} must preserve the entry`);\n assert(\n actual?.expiresAt === expected.expiresAt,\n `${operation} must preserve expiresAt`,\n );\n assert(\n Boolean(actual?.negative) === Boolean(expected.negative),\n `${operation} must preserve the negative flag`,\n );\n assert(\n actual?.staleUntil === expected.staleUntil,\n `${operation} must preserve staleUntil`,\n );\n assert(\n JSON.stringify(actual?.tags) === JSON.stringify(expected.tags),\n `${operation} must preserve tags`,\n );\n assert(\n JSON.stringify(actual?.value) === JSON.stringify(expected.value),\n `${operation} must preserve JSON-compatible values`,\n );\n}\n\nfunction assert(condition: boolean, requirement: string): asserts condition {\n if (!condition) {\n throw new Error(`Cache store contract failed: ${requirement}.`);\n }\n}\n"],"names":["verifyCacheStoreContract","createStore","store","prefix","alphaKey","betaKey","gammaKey","deltaKey","atomicKey","alphaTag","betaTag","deltaTag","future","alpha","assert","atomicTag","invalidations","total","count","assertEntry","updatedAlpha","delta","verifyCacheStoreRefreshContract","key","tag","firstToken","secondToken","leaseExpiresAt","acquireRefreshLease","publishRefresh","releaseRefreshLease","original","refreshed","ownerToken","otherToken","acquired","actual","expected","operation","condition","requirement"],"mappings":"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"}