@prisma/composer 0.25.0 → 0.26.0-dev.1
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.
- package/dist/{app-config-joXc-BKm-CdcXqNMD.mjs → app-config-CGJHcFb--CIEFCG4V.mjs} +3 -3
- package/dist/{app-config-joXc-BKm-CdcXqNMD.mjs.map → app-config-CGJHcFb--CIEFCG4V.mjs.map} +1 -1
- package/dist/{app-config-jGcCcxK4-DnzGGbDS.d.mts → app-config-DyCMnkDr-CguUhanl.d.mts} +4 -4
- package/dist/{app-config-jGcCcxK4-DnzGGbDS.d.mts.map → app-config-DyCMnkDr-CguUhanl.d.mts.map} +1 -1
- package/dist/config-CdxvLFzg.mjs.map +1 -1
- package/dist/config-i9yR7YWi.d.mts +1 -0
- package/dist/config.d.mts +2 -2
- package/dist/config.mjs +1 -1
- package/dist/control.d.mts +63 -44
- package/dist/control.d.mts.map +1 -1
- package/dist/control.mjs +10 -42
- package/dist/control.mjs.map +1 -1
- package/dist/deploy-i9yR7YWi.d.mts +1 -0
- package/dist/deploy.d.mts +2 -2
- package/dist/deploy.mjs +1 -1
- package/dist/deploy.mjs.map +1 -1
- package/dist/deployment-summary-37e6WEuh-BOTJynIi.mjs +168 -0
- package/dist/deployment-summary-37e6WEuh-BOTJynIi.mjs.map +1 -0
- package/dist/deployment-summary-CU-eVvJM-c3AqO52N.d.mts +26 -0
- package/dist/deployment-summary-CU-eVvJM-c3AqO52N.d.mts.map +1 -0
- package/dist/dev-Bmq-eLnv-DsenQNJM.mjs +154 -0
- package/dist/dev-Bmq-eLnv-DsenQNJM.mjs.map +1 -0
- package/dist/{execute-deploy-destroy-CvKCwVkD-Di3Ooeip.mjs → execute-deploy-destroy-c0eko3AO-BoK0-r1U.mjs} +43 -32
- package/dist/execute-deploy-destroy-c0eko3AO-BoK0-r1U.mjs.map +1 -0
- package/dist/{execute-dev-BLCK5wF7-CJvkj5wl.mjs → execute-dev-BICPaq1g-DQccw8kr.mjs} +180 -131
- package/dist/{execute-dev-BLCK5wF7-CJvkj5wl.mjs.map → execute-dev-BICPaq1g-DQccw8kr.mjs.map} +1 -1
- package/dist/{execute-log-B_zCJ17b-CE954g1a.mjs → execute-log-DivzSDBL-CBdSN2Vv.mjs} +7 -10
- package/dist/execute-log-DivzSDBL-CBdSN2Vv.mjs.map +1 -0
- package/dist/{local-target-DnA2E8IN.mjs → local-target-B4xoiDAV.mjs} +2 -2
- package/dist/{local-target-DnA2E8IN.mjs.map → local-target-B4xoiDAV.mjs.map} +1 -1
- package/dist/local-target.d.mts +1 -1
- package/dist/local-target.mjs +2 -2
- package/dist/nextjs-control.d.mts +4 -4
- package/dist/nextjs-control.mjs +2 -2
- package/dist/nextjs-control.mjs.map +1 -1
- package/dist/node-control.d.mts +4 -4
- package/dist/node-control.mjs +2 -2
- package/dist/node-control.mjs.map +1 -1
- package/dist/{pipeline-C7gNjMzJ-CzM8DNS_.mjs → pipeline-DYvl561J-DDtnkFPh.mjs} +278 -311
- package/dist/pipeline-DYvl561J-DDtnkFPh.mjs.map +1 -0
- package/dist/report.d.mts +4 -3
- package/dist/report.d.mts.map +1 -1
- package/dist/report.mjs +2 -2
- package/dist/report.mjs.map +1 -1
- package/dist/{run-alchemy-pANK8XNX-CgCpXLkG.mjs → run-alchemy-BEvB2sYQ-Cy2fhbcu.mjs} +2 -2
- package/dist/{run-alchemy-pANK8XNX-CgCpXLkG.mjs.map → run-alchemy-BEvB2sYQ-Cy2fhbcu.mjs.map} +1 -1
- package/package.json +11 -12
- package/skills/prisma-composer-core-concepts/SKILL.md +106 -45
- package/src/exports/testing.ts +1 -1
- package/dist/config-BGtKERz-.d.mts +0 -1
- package/dist/deploy-BGtKERz-.d.mts +0 -1
- package/dist/deployment-summary-DswOl_9E-B9MhYYDt.mjs +0 -70
- package/dist/deployment-summary-DswOl_9E-B9MhYYDt.mjs.map +0 -1
- package/dist/execute-deploy-destroy-CvKCwVkD-Di3Ooeip.mjs.map +0 -1
- package/dist/execute-log-B_zCJ17b-CE954g1a.mjs.map +0 -1
- package/dist/pipeline-C7gNjMzJ-CzM8DNS_.mjs.map +0 -1
- package/dist/result-CQIOBgdW.mjs +0 -247
- package/dist/result-CQIOBgdW.mjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline-DYvl561J-DDtnkFPh.mjs","names":["fs","path","path","fs"],"sources":["../../../0-framework/3-tooling/cli/dist/composer-config-CY9fET8H.mjs","../../../0-framework/3-tooling/assemble/dist/index.mjs","../../../0-framework/3-tooling/cli/dist/pipeline-DYvl561J.mjs"],"sourcesContent":["import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n//#region src/composer-config.ts\n/**\n* What makes a `composer` section valid, shared by the CLI's section validator and the programmatic operations.\n* It imports nothing from the CLI engine, because `@prisma/composer` must not depend on it.\n*/\nconst SECTION_FIX = \"Write `composer: composer({ extensions: [...], state: ... })` in prisma.config.ts, with `import { defineConfig as composer } from '@prisma/composer/config'`.\";\nconst MOVE_TO_SECTION_FIX = `${SECTION_FIX} If the project has a prisma-composer.config.ts, move its extensions and state into that section and delete the file.`;\nconst SECTION_IS_THE_ONLY_SOURCE = \"Composer reads its configuration only from the `composer` section of prisma.config.ts.\";\nconst DESCRIPTOR_FIX = \"Use the descriptor the extension factory returns, unchanged, instead of building one by hand.\";\nconst RETIRED_FILE_NAMES = [\n\t\"ts\",\n\t\"mts\",\n\t\"mjs\",\n\t\"js\"\n].map((extension) => `prisma-composer.config.${extension}`);\nconst sectionMissing = {\n\tcode: \"CONFIG.SECTION_MISSING\",\n\tsummary: \"No loaded prisma.config.ts declares a `composer` section.\",\n\twhy: `${SECTION_IS_THE_ONLY_SOURCE} A prisma-composer.config.ts file is no longer read.`,\n\tfix: MOVE_TO_SECTION_FIX\n};\n/** What the generated stack file throws when the file it imports has no `composer` export. */\nfunction noComposerExportMessage(configFile) {\n\treturn `${configFile} declares no \\`composer\\` section. Pass the prisma.config.ts that declares it.`;\n}\nfunction configFileMissing(file) {\n\treturn {\n\t\tcode: \"CONFIG.FILE_MISSING\",\n\t\tsummary: `${file} does not exist.`,\n\t\tfix: \"Pass the path of the prisma.config.ts that declares the `composer` section.\",\n\t\twhere: file\n\t};\n}\n/** A prisma-composer.config.* beside the declaring file would otherwise be silently ignored. */\n/** The path with symlinks resolved; the path itself when it cannot be resolved, so the check never throws. */\nfunction realPath(file) {\n\ttry {\n\t\treturn fs.realpathSync(file);\n\t} catch {\n\t\treturn file;\n\t}\n}\nfunction retiredFileFinding(configFile) {\n\tconst directory = path.dirname(realPath(configFile));\n\tconst found = RETIRED_FILE_NAMES.map((name) => path.join(directory, name)).find((file) => fs.existsSync(file));\n\tif (found === void 0) return void 0;\n\treturn {\n\t\tcode: \"CONFIG.FILE_RETIRED\",\n\t\tsummary: `${found} is no longer read.`,\n\t\twhy: SECTION_IS_THE_ONLY_SOURCE,\n\t\tfix: MOVE_TO_SECTION_FIX,\n\t\twhere: found\n\t};\n}\nfunction isObject(value) {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\nfunction isExtensionDescriptor(value) {\n\treturn isObject(value) && typeof value[\"id\"] === \"string\" && value[\"id\"].length > 0 && isObject(value[\"nodes\"]);\n}\nfunction isStateDescriptor(value) {\n\treturn isObject(value) && typeof value[\"extension\"] === \"string\" && typeof value[\"create\"] === \"function\";\n}\nconst stateInvalid = {\n\tcode: \"CONFIG.FIELD_INVALID\",\n\tsummary: \"`composer.state` must be a state descriptor with a string `extension` and a `create` function.\",\n\tfix: \"Set `state` to the state descriptor an extension provides, e.g. `state: prismaState()`.\",\n\tfield: \"state\"\n};\nfunction unknownField(key) {\n\treturn {\n\t\tcode: \"CONFIG.FIELD_UNKNOWN\",\n\t\tsummary: `The \\`composer\\` section has no field \\`${key}\\`.`,\n\t\tfix: key === \"composer\" ? \"Pass the `composer` property of the prisma.config.ts export, not the whole export. The section takes only `extensions` and `state`.\" : `Remove \\`${key}\\`. The section takes only \\`extensions\\` and \\`state\\`.`,\n\t\tfield: key\n\t};\n}\nfunction checkExtensions(value) {\n\tif (!Array.isArray(value)) return {\n\t\textensions: [],\n\t\tfindings: [{\n\t\t\tcode: \"CONFIG.FIELD_INVALID\",\n\t\t\tsummary: \"`composer.extensions` must be an array of extension descriptors.\",\n\t\t\tfix: \"Set `extensions` to the descriptors your extensions provide, e.g. `extensions: [nodeBuild()]`.\",\n\t\t\tfield: \"extensions\"\n\t\t}]\n\t};\n\tconst findings = [];\n\tconst extensions = [];\n\tconst seen = /* @__PURE__ */ new Set();\n\tfor (const [index, entry] of value.entries()) {\n\t\tconst field = `extensions[${index}]`;\n\t\tif (!isObject(entry)) {\n\t\t\tfindings.push({\n\t\t\t\tcode: \"CONFIG.FIELD_INVALID\",\n\t\t\t\tsummary: `\\`composer.${field}\\` must be an extension descriptor object.`,\n\t\t\t\tfix: \"Put the descriptor an extension factory returns here, e.g. `nodeBuild()`, not the factory itself.\",\n\t\t\t\tfield\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tconst id = entry[\"id\"];\n\t\tif (typeof id !== \"string\" || id.length === 0) findings.push({\n\t\t\tcode: \"CONFIG.FIELD_INVALID\",\n\t\t\tsummary: `\\`composer.${field}.id\\` must be a non-empty string (the extension package name).`,\n\t\t\tfix: DESCRIPTOR_FIX,\n\t\t\tfield: `${field}.id`\n\t\t});\n\t\telse if (seen.has(id)) findings.push({\n\t\t\tcode: \"CONFIG.EXTENSION_DUPLICATE\",\n\t\t\tsummary: `Extension \"${id}\" is listed more than once in \\`composer.extensions\\`.`,\n\t\t\tfix: `Remove the repeated \"${id}\" entry from \\`extensions\\`.`,\n\t\t\tfield: `${field}.id`\n\t\t});\n\t\telse seen.add(id);\n\t\tif (!isObject(entry[\"nodes\"])) findings.push({\n\t\t\tcode: \"CONFIG.FIELD_INVALID\",\n\t\t\tsummary: `\\`composer.${field}.nodes\\` must be an object (the node-ID → control registry).`,\n\t\t\tfix: DESCRIPTOR_FIX,\n\t\t\tfield: `${field}.nodes`\n\t\t});\n\t\tif (isExtensionDescriptor(entry)) extensions.push(entry);\n\t}\n\treturn {\n\t\tfindings,\n\t\textensions\n\t};\n}\nfunction checkFields(section) {\n\tif (Object.hasOwn(section, \"configPath\")) return {\n\t\tok: false,\n\t\tfindings: [{\n\t\t\tcode: \"CONFIG.FIELD_RETIRED\",\n\t\t\tsummary: \"`composer.configPath` is no longer supported: prisma-composer.config.ts is no longer read.\",\n\t\t\twhy: SECTION_IS_THE_ONLY_SOURCE,\n\t\t\tfix: `Replace \\`configPath\\` with the section itself. ${MOVE_TO_SECTION_FIX}`,\n\t\t\tfield: \"configPath\"\n\t\t}]\n\t};\n\tif (Object.hasOwn(section, \"composer\")) return {\n\t\tok: false,\n\t\tfindings: [unknownField(\"composer\")]\n\t};\n\tconst findings = Object.keys(section).filter((key) => key !== \"extensions\" && key !== \"state\").map(unknownField);\n\tconst checked = checkExtensions(section[\"extensions\"]);\n\tfindings.push(...checked.findings);\n\tconst state = section[\"state\"];\n\tif (!isStateDescriptor(state)) findings.push(stateInvalid);\n\tconst [first, ...rest] = findings;\n\tif (first === void 0 && isStateDescriptor(state)) return {\n\t\tok: true,\n\t\tvalue: {\n\t\t\textensions: checked.extensions,\n\t\t\tstate\n\t\t}\n\t};\n\treturn {\n\t\tok: false,\n\t\tfindings: [first ?? stateInvalid, ...rest]\n\t};\n}\n/**\n* Checks the fields that identify each descriptor and returns the descriptors as the config file's own objects.\n* Never throws: a section's values are user code, and a throwing getter or Proxy trap becomes a finding.\n*/\nfunction checkComposerSection(raw) {\n\tif (!isObject(raw)) return {\n\t\tok: false,\n\t\tfindings: [{\n\t\t\tcode: \"CONFIG.FIELD_INVALID\",\n\t\t\tsummary: \"The `composer` section of prisma.config.ts must be an object.\",\n\t\t\tfix: SECTION_FIX\n\t\t}]\n\t};\n\ttry {\n\t\treturn checkFields({ ...raw });\n\t} catch (cause) {\n\t\treturn {\n\t\t\tok: false,\n\t\t\tfindings: [{\n\t\t\t\tcode: \"CONFIG.FIELD_INVALID\",\n\t\t\t\tsummary: \"The `composer` section of prisma.config.ts could not be read.\",\n\t\t\t\twhy: `Reading it threw: ${cause instanceof Error ? cause.message : String(cause)}`,\n\t\t\t\tfix: SECTION_FIX\n\t\t\t}]\n\t\t};\n\t}\n}\n/**\n* The whole check, shared by the section validator and the programmatic operations so both report the same findings in the same order: the retired file beside the declaring `configFile` (resolved through symlinks), then every field finding.\n*/\nfunction checkComposerConfig(raw, configFile) {\n\tconst retired = retiredFileFinding(configFile);\n\tconst checked = checkComposerSection(raw);\n\tif (retired === void 0) return checked;\n\treturn {\n\t\tok: false,\n\t\tfindings: checked.ok ? [retired] : [retired, ...checked.findings]\n\t};\n}\n//#endregion\nexport { sectionMissing as i, configFileMissing as n, noComposerExportMessage as r, checkComposerConfig as t };\n\n//# sourceMappingURL=composer-config-CY9fET8H.mjs.map","import { CliStructuredError } from \"@internal/foundation/errors\";\n//#region src/assemble-error.ts\n/**\n* A user-facing assembly failure, structured at origin (base-type rule 6):\n* a `CliStructuredError` whose code names which way assembly went wrong.\n* This package's second consumer is the programmatic deploy API, not just\n* the CLI — hosts branch on `error.code`, the CLI renders the envelope.\n*/\nvar AssembleError = class extends CliStructuredError {\n\tconstructor(code, summary, options) {\n\t\tsuper(code, summary, options);\n\t}\n};\n//#endregion\n//#region src/assemble-services.ts\n/**\n* The registry route for one service's build: extension by\n* `build.extension`, node descriptor by `build.type`, kind must be \"build\".\n* The CLI's coverage validation reports the same misses earlier with the\n* config fix; these errors are the backstop for programmatic callers.\n*/\nfunction buildDescriptorAssemble(config, node, address, cwd) {\n\tconst { extension, type } = node.build;\n\tconst extensionDescriptor = config.extensions.find((candidate) => candidate.id === extension);\n\tif (extensionDescriptor === void 0) throw new AssembleError(\"ASSEMBLE.EXTENSION_MISSING\", `No extension \"${extension}\" is configured (needed by service \"${node.name}\"'s build).`, { fix: \"Add it to `extensions` in the `composer` section of prisma.config.ts.\" });\n\tconst nodeDescriptor = extensionDescriptor.nodes[type];\n\tif (nodeDescriptor === void 0) throw new AssembleError(\"ASSEMBLE.DESCRIPTOR_MISSING\", `Extension \"${extension}\" has no descriptor for build type \"${type}\".`, { why: `Known types: ${Object.keys(extensionDescriptor.nodes).join(\", \")}.` });\n\tif (nodeDescriptor.kind !== \"build\") throw new AssembleError(\"ASSEMBLE.DESCRIPTOR_KIND_MISMATCH\", `Extension \"${extension}\"'s descriptor for type \"${type}\" is a \"${nodeDescriptor.kind}\" descriptor.`, { why: \"Assembling a service build needs a \\\"build\\\" descriptor.\" });\n\treturn nodeDescriptor.assemble({\n\t\tbuild: node.build,\n\t\taddress,\n\t\tcwd\n\t});\n}\nasync function assembleServices(graph, config, cwd, run) {\n\tconst runAssembler = run ?? ((node, address, nodeCwd) => buildDescriptorAssemble(config, node, address, nodeCwd));\n\tconst serviceNodes = graph.nodes.filter((n) => n.node.kind === \"service\");\n\tif (serviceNodes.length === 0) throw new AssembleError(\"ASSEMBLE.SERVICE_MISSING\", \"The loaded graph has no service to assemble.\");\n\tconst bundles = {};\n\tfor (const { id, node } of serviceNodes) try {\n\t\tbundles[id] = await runAssembler(node, id, cwd);\n\t} catch (error) {\n\t\tif (CliStructuredError.is(error)) throw error;\n\t\tthrow new AssembleError(\"ASSEMBLE.BUILD_FAILED\", error instanceof Error ? error.message : String(error), {\n\t\t\tmeta: { address: id },\n\t\t\tcause: error\n\t\t});\n\t}\n\treturn { bundles };\n}\n//#endregion\nexport { AssembleError, assembleServices };\n\n//# sourceMappingURL=index.mjs.map","import { n as configFileMissing, t as checkComposerConfig } from \"./composer-config-CY9fET8H.mjs\";\nimport * as mod from \"node:module\";\nimport * as fs from \"node:fs\";\nimport { existsSync } from \"node:fs\";\nimport { blindCast } from \"@internal/foundation/casts\";\nimport { CliStructuredError } from \"@internal/foundation/errors\";\nimport * as path from \"node:path\";\nimport { assembleServices } from \"@internal/assemble\";\nimport { Load, isNode } from \"@internal/core\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\n//#region src/entry-resolution.ts\n/**\n* Synchronous Node resolve hook so that entry modules may import relative\n* files using the specifier forms TypeScript accepts by default —\n* extensionless `./service` and `./service.js` for a `.ts` source file —\n* without requiring `allowImportingTsExtensions` in every consumer's tsconfig.\n*\n* Resolution only; uses TypeScript's own documented mapping: for a specifier\n* Node could not resolve, strip any JS-family extension and probe the\n* corresponding TypeScript source; first candidate that exists on disk wins.\n* Format-specific rules: `.mjs` → `.mts`; `.cjs` → `.cts`; `.js` and\n* extensionless → `.ts`, `.mts`, `.tsx`, then `./index.ts`. Bare and package\n* specifiers are never touched. Existing `./x.ts` imports keep working —\n* Node resolves them before the hook fires (ADR-0005: no transform, no\n* guessing, deterministic TypeScript rule).\n*\n* Bun resolves `./x.js` and `./x` to `x.ts` natively, so the hook is a\n* no-op under Bun. Nothing is registered there.\n*/\nlet registered = false;\n/**\n* Registers the resolve hook once (idempotent). Call at the start of\n* `loadEntry` so every module in the entry graph benefits, including those\n* imported lazily after the entry itself loads.\n*/\nfunction registerEntryResolution() {\n\tif (registered || typeof process.versions.bun === \"string\") return;\n\tif (typeof mod.registerHooks !== \"function\") return;\n\tregistered = true;\n\tmod.registerHooks({ resolve(specifier, context, nextResolve) {\n\t\ttry {\n\t\t\treturn nextResolve(specifier, context);\n\t\t} catch (error) {\n\t\t\tif (!isRelativeSpecifier(specifier) || context.parentURL === void 0 || !isModuleNotFoundError(error)) throw error;\n\t\t\tfor (const candidate of sourceCandidates(new URL(specifier, context.parentURL))) if (existsSync(fileURLToPath(candidate))) return nextResolve(candidate.href, context);\n\t\t\tthrow error;\n\t\t}\n\t} });\n}\n/**\n* TypeScript's extension mapping: for a JS-family or extensionless URL,\n* produce the source candidates to probe. Format-specific: `.mjs` maps only\n* to `.mts`; `.cjs` maps only to `.cts`; `.js` and extensionless probe\n* `.ts`, `.mts`, `.tsx` (keeping `.tsx` so the JSX diagnostic fires), then\n* `./index.ts`.\n*/\nfunction sourceCandidates(resolved) {\n\tconst href = resolved.href;\n\tif (href.endsWith(\".mjs\")) {\n\t\tconst base = href.slice(0, -4);\n\t\treturn [new URL(`${base}.mts`)];\n\t}\n\tif (href.endsWith(\".cjs\")) {\n\t\tconst base = href.slice(0, -4);\n\t\treturn [new URL(`${base}.cts`)];\n\t}\n\tconst base = href.endsWith(\".js\") ? href.slice(0, -3) : href;\n\treturn [\n\t\tnew URL(`${base}.ts`),\n\t\tnew URL(`${base}.mts`),\n\t\tnew URL(`${base}.tsx`),\n\t\tnew URL(`${base}/index.ts`)\n\t];\n}\nfunction isRelativeSpecifier(specifier) {\n\treturn specifier.startsWith(\"./\") || specifier.startsWith(\"../\");\n}\nfunction isModuleNotFoundError(error) {\n\tif (!(error instanceof Error)) return false;\n\tif (!(\"code\" in error)) return false;\n\treturn error.code === \"ERR_MODULE_NOT_FOUND\";\n}\n//#endregion\n//#region src/jsx-load-error.ts\n/**\n* `loadEntry` imports a user's topology with the host runtime's own module\n* loader — under node (the CLI's shebang runtime), that loader strips\n* TypeScript types but has no JSX transform (ADR-0005: the framework\n* doesn't bundle or transform the app's code; deploy loading is no\n* exception). A `.tsx`/`.jsx` file anywhere in the topology's import graph\n* dies with node's raw `ERR_UNKNOWN_FILE_EXTENSION`, which names the file\n* but not the cause or the fix. This turns that one case into structured\n* error parts (summary/why/fix) that do — every other load failure (syntax\n* errors, missing files, non-JSX unknown extensions) is untouched.\n*/\nconst UNKNOWN_EXTENSION_CODE = \"ERR_UNKNOWN_FILE_EXTENSION\";\nconst JSX_EXTENSIONS = [\".tsx\", \".jsx\"];\nfunction errorCode(error) {\n\treturn \"code\" in error && typeof error.code === \"string\" ? error.code : void 0;\n}\nfunction unknownExtensionPath(error) {\n\tif (!(error instanceof Error)) return void 0;\n\tif (errorCode(error) !== UNKNOWN_EXTENSION_CODE) return void 0;\n\treturn /Unknown file extension \"\\.\\w+\" for (.+)$/.exec(error.message)?.[1];\n}\n/**\n* Returns structured error parts when `error` is node's\n* `ERR_UNKNOWN_FILE_EXTENSION` for a `.tsx`/`.jsx` file — `undefined` for\n* every other error (including unknown-extension failures for some other\n* extension), so the caller can fall through to its normal rethrow.\n*/\nfunction explainJsxLoadError(error, entryPath) {\n\tconst offendingPath = unknownExtensionPath(error);\n\tif (offendingPath === void 0) return void 0;\n\tif (!JSX_EXTENSIONS.some((ext) => offendingPath.endsWith(ext))) return void 0;\n\treturn {\n\t\tsummary: `\"${offendingPath}\" can't be loaded.`,\n\t\twhy: `deploy loads \"${entryPath}\"'s topology with node's own module loader, which strips TypeScript types but has no JSX transform — so a .tsx/.jsx file can't sit anywhere in that import graph.`,\n\t\tfix: \"Precompile that file in your own build (transform the JSX away, keep the real npm packages external) and import the compiled output instead of the raw .tsx/.jsx — see examples/email/scripts/build.ts in the prisma/composer repo for a worked example.\"\n\t};\n}\n//#endregion\n//#region src/load-entry.ts\n/**\n* Pipeline step 1 (deploy-cli.md § The pipeline): import the entry module\n* (resolved against cwd) and require its default export to be a node — a\n* service or module, branded by core's factories. Whatever this module exports\n* IS the application; nothing else marks a root (ADR-0003).\n*/\nasync function loadEntry(entryArg, cwd) {\n\tregisterEntryResolution();\n\tconst resolvedPath = path.resolve(cwd, entryArg);\n\tlet mod;\n\ttry {\n\t\tmod = await import(pathToFileURL(resolvedPath).href);\n\t} catch (error) {\n\t\tconst explained = explainJsxLoadError(error, resolvedPath);\n\t\tif (explained !== void 0) throw new CliStructuredError(\"COMPOSE.ENTRY_UNLOADABLE\", explained.summary, {\n\t\t\twhy: explained.why,\n\t\t\tfix: explained.fix,\n\t\t\twhere: { path: resolvedPath },\n\t\t\tcause: error\n\t\t});\n\t\tthrow new CliStructuredError(\"COMPOSE.ENTRY_UNLOADABLE\", `Failed to import entry module \"${resolvedPath}\": ${error instanceof Error ? error.message : String(error)}`, {\n\t\t\twhere: { path: resolvedPath },\n\t\t\tcause: error\n\t\t});\n\t}\n\tconst root = blindCast(mod).default;\n\tif (!isNode(root) || root.kind === \"dependency\" || root.kind === \"resource\") throw new CliStructuredError(\"COMPOSE.ENTRY_EXPORT_INVALID\", `Entry module \"${resolvedPath}\" must default-export a node (a service or a module).`, {\n\t\tfix: \"Construct it with service() or module() from @prisma/composer.\",\n\t\twhere: { path: resolvedPath }\n\t});\n\treturn {\n\t\tpath: resolvedPath,\n\t\troot: blindCast(root)\n\t};\n}\n//#endregion\n//#region src/validate-coverage.ts\nfunction lookup(extensions, extension, type, expectedKind, what) {\n\tconst ext = extensions.get(extension);\n\tif (ext === void 0) throw new CliStructuredError(\"CONFIG.EXTENSION_MISSING\", `No extension \"${extension}\" is configured (needed by ${what}).`, {\n\t\tfix: \"Add it to `extensions` in the `composer` section of prisma.config.ts (import its /control entry and list its descriptor).\",\n\t\tmeta: {\n\t\t\textension,\n\t\t\ttype\n\t\t}\n\t});\n\tconst descriptor = ext.nodes[type];\n\tif (descriptor === void 0) throw new CliStructuredError(\"CONFIG.DESCRIPTOR_MISSING\", `Extension \"${extension}\" has no descriptor for node type \"${type}\" (needed by ${what}).`, {\n\t\twhy: `Known types: ${Object.keys(ext.nodes).join(\", \")}.`,\n\t\tmeta: {\n\t\t\textension,\n\t\t\ttype\n\t\t}\n\t});\n\tif (descriptor.kind !== expectedKind) throw new CliStructuredError(\"CONFIG.DESCRIPTOR_KIND_MISMATCH\", `Extension \"${extension}\"'s descriptor for node type \"${type}\" is a \"${descriptor.kind}\" descriptor — ${what} needs a \"${expectedKind}\" descriptor.`, { meta: {\n\t\textension,\n\t\ttype,\n\t\tkind: descriptor.kind\n\t} });\n}\n/** Throws a structured CONFIG.* error on the first uncovered `(extension, type)`; silent when the config covers the whole graph. */\nfunction validateRegistryCoverage(graph, config) {\n\tconst extensions = new Map(config.extensions.map((descriptor) => [descriptor.id, descriptor]));\n\tfor (const { id, node } of graph.nodes) {\n\t\tif (node.kind === \"resource\") {\n\t\t\tlookup(extensions, node.extension, node.type, \"resource\", `resource node \"${id}\"`);\n\t\t\tcontinue;\n\t\t}\n\t\tif (node.kind !== \"service\") continue;\n\t\tlookup(extensions, node.extension, node.type, \"service\", `service node \"${id}\"`);\n\t\tlookup(extensions, node.build.extension, node.build.type, \"build\", `service node \"${id}\"'s build descriptor`);\n\t}\n}\n//#endregion\n//#region src/pipeline.ts\n/**\n* The shared prefix of `deploy`/`destroy`/`dev` (deploy-cli.md § The\n* pipeline; local-dev spec § 6): entry load, Load,\n* registry coverage validation, name resolution, assemble. Deploy and dev\n* diverge after this — deploy resolves containers/preflight/stack file\n* against the hosted providers, dev against the local ones — so everything\n* up to and including assemble lives here once, consumed verbatim by both\n* `run()` (main.ts) and `runDev()` (dev/run-dev.ts), so the two pipelines\n* cannot drift.\n*/\nfunction configError(findings, file) {\n\tconst [first] = findings;\n\treturn new CliStructuredError(first.code, first.summary, {\n\t\t...first.why === void 0 ? {} : { why: first.why },\n\t\tfix: first.fix,\n\t\twhere: { path: first.where ?? file },\n\t\tmeta: {\n\t\t\t...first.field === void 0 ? {} : { field: first.field },\n\t\t\tfindings\n\t\t}\n\t});\n}\n/**\n* Refuses a caller's config with the same findings, in the same order, as the CLI's section validator.\n* The error is the first finding and carries all of them in `meta.findings`. Returns the config with `file` resolved against `cwd`.\n*/\nfunction checkConfigSource(source, cwd) {\n\tconst file = path.resolve(cwd, source.file);\n\tif (!fs.existsSync(file)) throw configError([configFileMissing(file)], file);\n\tconst checked = checkComposerConfig(source.value, file);\n\tif (!checked.ok) throw configError(checked.findings, file);\n\treturn {\n\t\tvalue: checked.value,\n\t\tfile\n\t};\n}\n/**\n* The pipeline's front — entry load and name resolution —\n* WITHOUT Load, coverage, or assemble. `log` needs only who the app is (its\n* config and resolved name) to reach the already-running local instance; it\n* neither builds nor provisions, so it must not require the user's built\n* output the way the full pipeline does.\n*/\nasync function resolveAppIdentity(entry, overrideName, cwd, config) {\n\tconst { value } = checkConfigSource(config, cwd);\n\tconst entryModule = await loadEntry(entry, cwd);\n\tconst name = overrideName ?? entryModule.root.name;\n\tif (name.length === 0) throw new CliStructuredError(\"COMPOSE.NAME_MISSING\", \"The root node has no name.\", { fix: \"Name it at authoring, or pass --name.\" });\n\treturn {\n\t\tconfig: value,\n\t\tname\n\t};\n}\n/**\n* Runs entry load, Load, registry coverage, name resolution, and assemble — steps 1–5 of `run()`. `onAssembleError`, when\n* given, lets a caller decorate an assemble failure with command-specific\n* guidance (destroy's \"build first\" hint) without this shared step knowing\n* about any one command.\n*/\nasync function runPipeline(entry, overrideName, cwd, source, deps = {}, onAssembleError) {\n\tconst configSource = checkConfigSource(source, cwd);\n\tconst config = configSource.value;\n\tconst entryModule = await loadEntry(entry, cwd);\n\tconst graph = Load(entryModule.root);\n\tif (graph.root.node.kind !== \"module\") throw new CliStructuredError(\"COMPOSE.ROOT_NOT_MODULE\", \"The deploy root must be a module.\", { fix: \"Wrap your service, e.g. export default module('name', ({ provision }) => { provision(service); }).\" });\n\tvalidateRegistryCoverage(graph, config);\n\tconst name = overrideName ?? entryModule.root.name;\n\tif (name.length === 0) throw new CliStructuredError(\"COMPOSE.NAME_MISSING\", \"The root node has no name.\", { fix: \"Name it at authoring, or pass --name.\" });\n\tlet assembled;\n\ttry {\n\t\tassembled = await assembleServices(graph, config, cwd, deps.runAssembler);\n\t} catch (error) {\n\t\tif (onAssembleError !== void 0 && error instanceof Error) throw onAssembleError(error);\n\t\tthrow error;\n\t}\n\treturn {\n\t\tconfigSource,\n\t\tentryModule,\n\t\tgraph,\n\t\tname,\n\t\tassembled\n\t};\n}\n//#endregion\nexport { runPipeline as n, resolveAppIdentity as t };\n\n//# sourceMappingURL=pipeline-DYvl561J.mjs.map"],"mappings":"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"}
|
package/dist/report.d.mts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { f as DeploymentResult } from "./app-config-
|
|
2
|
-
import "./deploy-
|
|
1
|
+
import { f as DeploymentResult } from "./app-config-DyCMnkDr-CguUhanl.mjs";
|
|
2
|
+
import "./deploy-i9yR7YWi.mjs";
|
|
3
|
+
import { r as captureEngineFailure } from "./deployment-summary-CU-eVvJM-c3AqO52N.mjs";
|
|
3
4
|
//#region ../../0-framework/3-tooling/cli/dist/report.d.mts
|
|
4
5
|
//#region src/render-deployment.d.ts
|
|
5
6
|
/**
|
|
@@ -14,5 +15,5 @@ declare function renderDeployment(result: DeploymentResult): string;
|
|
|
14
15
|
*/
|
|
15
16
|
declare function deploymentReport(result: DeploymentResult): void;
|
|
16
17
|
//#endregion
|
|
17
|
-
export { deploymentReport, renderDeployment };
|
|
18
|
+
export { captureEngineFailure, deploymentReport, renderDeployment };
|
|
18
19
|
//# sourceMappingURL=report.d.mts.map
|
package/dist/report.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"report.d.mts","names":[],"sources":["../../../0-framework/3-tooling/cli/dist/report.d.mts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"report.d.mts","names":[],"sources":["../../../0-framework/3-tooling/cli/dist/report.d.mts"],"mappings":";;;;;;;;;iBAOiB,iBAAiB,QAAQ;;;;;;iBAMzB,iBAAiB,QAAQ"}
|
package/dist/report.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { n as captureEngineFailure, o as writeDeploymentSummaryFile } from "./deployment-summary-37e6WEuh-BOTJynIi.mjs";
|
|
2
2
|
//#region ../../0-framework/3-tooling/cli/dist/report.mjs
|
|
3
3
|
/** Gap between the deepest tree label and the entity column. */
|
|
4
4
|
const LABEL_GAP = 3;
|
|
@@ -81,6 +81,6 @@ function deploymentReport(result) {
|
|
|
81
81
|
writeDeploymentSummaryFile(result);
|
|
82
82
|
}
|
|
83
83
|
//#endregion
|
|
84
|
-
export { deploymentReport, renderDeployment };
|
|
84
|
+
export { captureEngineFailure, deploymentReport, renderDeployment };
|
|
85
85
|
|
|
86
86
|
//# sourceMappingURL=report.mjs.map
|
package/dist/report.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"report.mjs","names":[],"sources":["../../../0-framework/3-tooling/cli/dist/report.mjs"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"report.mjs","names":[],"sources":["../../../0-framework/3-tooling/cli/dist/report.mjs"],"sourcesContent":["import { n as captureEngineFailure, o as writeDeploymentSummaryFile } from \"./deployment-summary-37e6WEuh.mjs\";\n//#region src/render-deployment.ts\n/** Gap between the deepest tree label and the entity column. */\nconst LABEL_GAP = 3;\nconst emptyNode = (segment) => ({\n\tsegment,\n\tchildren: /* @__PURE__ */ new Map()\n});\n/** Builds the address tree, splitting each dot-address into its segments. */\nfunction buildTree(nodes) {\n\tconst root = emptyNode(\"\");\n\tfor (const deployed of nodes) {\n\t\tlet node = root;\n\t\tfor (const segment of deployed.address.split(\".\")) {\n\t\t\tlet child = node.children.get(segment);\n\t\t\tif (child === void 0) {\n\t\t\t\tchild = emptyNode(segment);\n\t\t\t\tnode.children.set(segment, child);\n\t\t\t}\n\t\t\tnode = child;\n\t\t}\n\t\tnode.deployed = deployed;\n\t}\n\treturn root;\n}\n/** Flattens the tree to rows in address order, drawing the box guides. */\nfunction toRows(node, guides, rows) {\n\tconst children = Array.from(node.children.values());\n\tchildren.forEach((child, index) => {\n\t\tconst isLast = index === children.length - 1;\n\t\trows.push({\n\t\t\tlabel: `${guides}${isLast ? \"└─ \" : \"├─ \"}${child.segment}`,\n\t\t\tcontinuation: `${guides}${isLast ? \" \" : \"│ \"}`,\n\t\t\tdeployed: child.deployed\n\t\t});\n\t\ttoRows(child, `${guides}${isLast ? \" \" : \"│ \"}`, rows);\n\t});\n}\n/** `kind id` — the one line an entity gets. */\nconst entityLine = (entity) => `${entity.kind} ${entity.id}`;\n/** Pads `prefix` out to `width`, so every entity starts in the same column. */\nconst pad = (prefix, width) => prefix.padEnd(width, \" \");\n/**\n* Renders a deploy's result as the app's own topology. Pure — returns the\n* string; the caller prints.\n*/\nfunction renderDeployment(result) {\n\tconst rows = [];\n\ttoRows(buildTree(result.nodes), \"\", rows);\n\tconst column = Math.max(0, ...rows.map((row) => row.label.length)) + LABEL_GAP;\n\tconst lines = [result.app];\n\tfor (const row of rows) {\n\t\tif (row.deployed === void 0) {\n\t\t\tlines.push(row.label);\n\t\t\tcontinue;\n\t\t}\n\t\tif (row.deployed.entities.length === 0) {\n\t\t\tlines.push(`${pad(row.label, column)}(no entities reported)`);\n\t\t\tcontinue;\n\t\t}\n\t\trow.deployed.entities.forEach((entity, index) => {\n\t\t\tconst prefix = index === 0 ? row.label : row.continuation;\n\t\t\tlines.push(`${pad(prefix, column)}${entityLine(entity)}`);\n\t\t\tif (entity.url !== void 0) lines.push(`${pad(row.continuation, column)}${entity.url}`);\n\t\t\tfor (const [key, value] of Object.entries(entity.details ?? {})) {\n\t\t\t\tif (value === \"\") continue;\n\t\t\t\tfor (const line of value.split(\"\\n\")) lines.push(`${pad(row.continuation, column)}${key} ${line}`);\n\t\t\t}\n\t\t});\n\t}\n\treturn lines.join(\"\\n\");\n}\n/**\n* The report hook the generated stack file wires into `LowerOptions`. Prints a\n* leading blank line so the summary separates from alchemy's own apply output,\n* then hands the result to the cross-process writer (deployment-summary.ts).\n*/\nfunction deploymentReport(result) {\n\tconsole.log(\"\");\n\tconsole.log(renderDeployment(result));\n\twriteDeploymentSummaryFile(result);\n}\n//#endregion\nexport { captureEngineFailure, deploymentReport, renderDeployment };\n\n//# sourceMappingURL=report.mjs.map"],"mappings":";;;AAGA,MAAM,YAAY;AAClB,MAAM,aAAa,aAAa;CAC/B;CACA,0BAA0B,IAAI,IAAI;AACnC;;AAEA,SAAS,UAAU,OAAO;CACzB,MAAM,OAAO,UAAU,EAAE;CACzB,KAAK,MAAM,YAAY,OAAO;EAC7B,IAAI,OAAO;EACX,KAAK,MAAM,WAAW,SAAS,QAAQ,MAAM,GAAG,GAAG;GAClD,IAAI,QAAQ,KAAK,SAAS,IAAI,OAAO;GACrC,IAAI,UAAU,KAAK,GAAG;IACrB,QAAQ,UAAU,OAAO;IACzB,KAAK,SAAS,IAAI,SAAS,KAAK;GACjC;GACA,OAAO;EACR;EACA,KAAK,WAAW;CACjB;CACA,OAAO;AACR;;AAEA,SAAS,OAAO,MAAM,QAAQ,MAAM;CACnC,MAAM,WAAW,MAAM,KAAK,KAAK,SAAS,OAAO,CAAC;CAClD,SAAS,SAAS,OAAO,UAAU;EAClC,MAAM,SAAS,UAAU,SAAS,SAAS;EAC3C,KAAK,KAAK;GACT,OAAO,GAAG,SAAS,SAAS,QAAQ,QAAQ,MAAM;GAClD,cAAc,GAAG,SAAS,SAAS,QAAQ;GAC3C,UAAU,MAAM;EACjB,CAAC;EACD,OAAO,OAAO,GAAG,SAAS,SAAS,QAAQ,SAAS,IAAI;CACzD,CAAC;AACF;;AAEA,MAAM,cAAc,WAAW,GAAG,OAAO,KAAK,GAAG,OAAO;;AAExD,MAAM,OAAO,QAAQ,UAAU,OAAO,OAAO,OAAO,GAAG;;;;;AAKvD,SAAS,iBAAiB,QAAQ;CACjC,MAAM,OAAO,CAAC;CACd,OAAO,UAAU,OAAO,KAAK,GAAG,IAAI,IAAI;CACxC,MAAM,SAAS,KAAK,IAAI,GAAG,GAAG,KAAK,KAAK,QAAQ,IAAI,MAAM,MAAM,CAAC,IAAI;CACrE,MAAM,QAAQ,CAAC,OAAO,GAAG;CACzB,KAAK,MAAM,OAAO,MAAM;EACvB,IAAI,IAAI,aAAa,KAAK,GAAG;GAC5B,MAAM,KAAK,IAAI,KAAK;GACpB;EACD;EACA,IAAI,IAAI,SAAS,SAAS,WAAW,GAAG;GACvC,MAAM,KAAK,GAAG,IAAI,IAAI,OAAO,MAAM,EAAE,uBAAuB;GAC5D;EACD;EACA,IAAI,SAAS,SAAS,SAAS,QAAQ,UAAU;GAChD,MAAM,SAAS,UAAU,IAAI,IAAI,QAAQ,IAAI;GAC7C,MAAM,KAAK,GAAG,IAAI,QAAQ,MAAM,IAAI,WAAW,MAAM,GAAG;GACxD,IAAI,OAAO,QAAQ,KAAK,GAAG,MAAM,KAAK,GAAG,IAAI,IAAI,cAAc,MAAM,IAAI,OAAO,KAAK;GACrF,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,OAAO,WAAW,CAAC,CAAC,GAAG;IAChE,IAAI,UAAU,IAAI;IAClB,KAAK,MAAM,QAAQ,MAAM,MAAM,IAAI,GAAG,MAAM,KAAK,GAAG,IAAI,IAAI,cAAc,MAAM,IAAI,IAAI,GAAG,MAAM;GAClG;EACD,CAAC;CACF;CACA,OAAO,MAAM,KAAK,IAAI;AACvB;;;;;;AAMA,SAAS,iBAAiB,QAAQ;CACjC,QAAQ,IAAI,EAAE;CACd,QAAQ,IAAI,iBAAiB,MAAM,CAAC;CACpC,2BAA2B,MAAM;AAClC"}
|
|
@@ -2,7 +2,7 @@ import { t as CliStructuredError } from "./errors-0e8IVwzi.mjs";
|
|
|
2
2
|
import * as fs$1 from "node:fs";
|
|
3
3
|
import * as path$1 from "node:path";
|
|
4
4
|
import spawn from "cross-spawn";
|
|
5
|
-
//#region ../../0-framework/3-tooling/cli/dist/run-alchemy-
|
|
5
|
+
//#region ../../0-framework/3-tooling/cli/dist/run-alchemy-BEvB2sYQ.mjs
|
|
6
6
|
/**
|
|
7
7
|
* Pipeline step 7 (deploy-cli.md § The pipeline; design-notes.md's "Driving
|
|
8
8
|
* Alchemy" call): hand the terminal to the generated stack file.
|
|
@@ -96,4 +96,4 @@ const spawnAlchemy = async (invocation) => {
|
|
|
96
96
|
//#endregion
|
|
97
97
|
export { spawnAlchemy as n, alchemyInvocation as t };
|
|
98
98
|
|
|
99
|
-
//# sourceMappingURL=run-alchemy-
|
|
99
|
+
//# sourceMappingURL=run-alchemy-BEvB2sYQ-Cy2fhbcu.mjs.map
|
package/dist/{run-alchemy-pANK8XNX-CgCpXLkG.mjs.map → run-alchemy-BEvB2sYQ-Cy2fhbcu.mjs.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-alchemy-
|
|
1
|
+
{"version":3,"file":"run-alchemy-BEvB2sYQ-Cy2fhbcu.mjs","names":["path","fs"],"sources":["../../../0-framework/3-tooling/cli/dist/run-alchemy-BEvB2sYQ.mjs"],"sourcesContent":["import * as fs from \"node:fs\";\nimport { CliStructuredError } from \"@internal/foundation/errors\";\nimport * as path from \"node:path\";\nimport spawn from \"cross-spawn\";\n//#region src/run-alchemy.ts\n/**\n* Pipeline step 7 (deploy-cli.md § The pipeline; design-notes.md's \"Driving\n* Alchemy\" call): hand the terminal to the generated stack file.\n*\n* Resolves the installed `alchemy` bin and launches package-manager shims with\n* cross-spawn.\n*\n* This module composes the invocation; it does not decide how the child is\n* started. Under the CLI the engine starts it (`ctx.spawn`), which is what\n* makes Ctrl-C reach the child natively and keeps signal policy in one place.\n* `spawnAlchemy` is the default for programmatic hosts driving\n* `@prisma/composer/control`, which have no engine to borrow.\n*/\n/** Walks up from `startDir` looking for the installed Alchemy executable. */\nfunction resolveAlchemyBin(startDir) {\n\tconst names = process.platform === \"win32\" ? [\n\t\t\"alchemy.exe\",\n\t\t\"alchemy.cmd\",\n\t\t\"alchemy\"\n\t] : [\"alchemy\"];\n\tlet dir = startDir;\n\twhile (true) {\n\t\tfor (const name of names) {\n\t\t\tconst candidate = path.join(dir, \"node_modules\", \".bin\", name);\n\t\t\tif (fs.existsSync(candidate)) return candidate;\n\t\t}\n\t\tconst parent = path.dirname(dir);\n\t\tif (parent === dir) throw new CliStructuredError(\"DEPLOY.ALCHEMY_BIN_MISSING\", `Could not find an installed \\`alchemy\\` bin above \"${startDir}\".`, { fix: \"Add \\\"alchemy\\\" as a dependency of your app.\" });\n\t\tdir = parent;\n\t}\n}\n/**\n* Resolves the invocation against this machine — the step every adapter takes\n* and no caller should. Raises DEPLOY.ALCHEMY_BIN_MISSING when the app has no\n* alchemy installed.\n*/\nfunction alchemyCommandLine(invocation) {\n\treturn {\n\t\tcommand: resolveAlchemyBin(invocation.cwd),\n\t\targs: [\n\t\t\tinvocation.action,\n\t\t\tinvocation.stackFileRelativePath,\n\t\t\t\"--yes\",\n\t\t\t\"--stage\",\n\t\t\tinvocation.stage\n\t\t],\n\t\tcwd: invocation.cwd,\n\t\tenv: invocation.env\n\t};\n}\n/** What becomes `alchemy deploy|destroy <stack file> --yes --stage <stage>`. */\nfunction alchemyInvocation(input) {\n\treturn {\n\t\taction: input.command,\n\t\tstackFileRelativePath: input.stackFileRelativePath,\n\t\tcwd: input.cwd,\n\t\tstage: input.stage,\n\t\tenv: {\n\t\t\t...input.containerEnv,\n\t\t\t...input.preflightEnv,\n\t\t\t...input.env\n\t\t}\n\t};\n}\n/**\n* The default runner for hosts with no engine: inherited stdio, the caller's\n* own process group, and the child's status returned verbatim. It does not\n* collapse a signal into an exit code — that collapse is what made a\n* Ctrl-C'd deploy report itself as a failure.\n*/\nconst spawnAlchemy = async (invocation) => {\n\tconst line = alchemyCommandLine(invocation);\n\treturn new Promise((resolve, reject) => {\n\t\tconst child = spawn(line.command, [...line.args], {\n\t\t\tcwd: line.cwd,\n\t\t\tstdio: \"inherit\",\n\t\t\tenv: {\n\t\t\t\t...process.env,\n\t\t\t\t...line.env\n\t\t\t}\n\t\t});\n\t\tchild.on(\"error\", reject);\n\t\tchild.on(\"close\", (exitCode, signal) => {\n\t\t\tresolve({\n\t\t\t\texitCode,\n\t\t\t\tsignal\n\t\t\t});\n\t\t});\n\t});\n};\n//#endregion\nexport { alchemyInvocation as n, spawnAlchemy as r, alchemyCommandLine as t };\n\n//# sourceMappingURL=run-alchemy-BEvB2sYQ.mjs.map"],"mappings":";;;;;;;;;;;;;;;;;;;AAmBA,SAAS,kBAAkB,UAAU;CACpC,MAAM,QAAQ,QAAQ,aAAa,UAAU;EAC5C;EACA;EACA;CACD,IAAI,CAAC,SAAS;CACd,IAAI,MAAM;CACV,OAAO,MAAM;EACZ,KAAK,MAAM,QAAQ,OAAO;GACzB,MAAM,YAAYA,OAAK,KAAK,KAAK,gBAAgB,QAAQ,IAAI;GAC7D,IAAIC,KAAG,WAAW,SAAS,GAAG,OAAO;EACtC;EACA,MAAM,SAASD,OAAK,QAAQ,GAAG;EAC/B,IAAI,WAAW,KAAK,MAAM,IAAI,mBAAmB,8BAA8B,sDAAsD,SAAS,KAAK,EAAE,KAAK,+CAA+C,CAAC;EAC1M,MAAM;CACP;AACD;;;;;;AAMA,SAAS,mBAAmB,YAAY;CACvC,OAAO;EACN,SAAS,kBAAkB,WAAW,GAAG;EACzC,MAAM;GACL,WAAW;GACX,WAAW;GACX;GACA;GACA,WAAW;EACZ;EACA,KAAK,WAAW;EAChB,KAAK,WAAW;CACjB;AACD;;AAEA,SAAS,kBAAkB,OAAO;CACjC,OAAO;EACN,QAAQ,MAAM;EACd,uBAAuB,MAAM;EAC7B,KAAK,MAAM;EACX,OAAO,MAAM;EACb,KAAK;GACJ,GAAG,MAAM;GACT,GAAG,MAAM;GACT,GAAG,MAAM;EACV;CACD;AACD;;;;;;;AAOA,MAAM,eAAe,OAAO,eAAe;CAC1C,MAAM,OAAO,mBAAmB,UAAU;CAC1C,OAAO,IAAI,SAAS,SAAS,WAAW;EACvC,MAAM,QAAQ,MAAM,KAAK,SAAS,CAAC,GAAG,KAAK,IAAI,GAAG;GACjD,KAAK,KAAK;GACV,OAAO;GACP,KAAK;IACJ,GAAG,QAAQ;IACX,GAAG,KAAK;GACT;EACD,CAAC;EACD,MAAM,GAAG,SAAS,MAAM;EACxB,MAAM,GAAG,UAAU,UAAU,WAAW;GACvC,QAAQ;IACP;IACA;GACD,CAAC;EACF,CAAC;CACF,CAAC;AACF"}
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma/composer",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.26.0-dev.1",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "Prisma Composer — build a Prisma App by composing Modules. Core authoring, deploy pipeline, and the service-rpc/node/nextjs authoring surfaces. The `prisma
|
|
5
|
+
"description": "Prisma Composer — build a Prisma App by composing Modules. Core authoring, deploy pipeline, and the service-rpc/node/nextjs authoring surfaces. The command family the `prisma` CLI mounts lives in @prisma/composer-cli.",
|
|
6
6
|
"exports": {
|
|
7
7
|
".": "./dist/index.mjs",
|
|
8
8
|
"./config": "./dist/config.mjs",
|
|
@@ -33,22 +33,21 @@
|
|
|
33
33
|
"@standard-schema/spec": "^1.1.0",
|
|
34
34
|
"alchemy": "2.0.0-beta.78",
|
|
35
35
|
"arktype": "^2.2.3",
|
|
36
|
-
"c12": "^3.3.4",
|
|
37
36
|
"cross-spawn": "^7.0.6",
|
|
38
37
|
"effect": "4.0.0-rc.115",
|
|
39
38
|
"esbuild": "^0.28.1",
|
|
40
39
|
"@prisma/management-api-sdk": "^1.80.0"
|
|
41
40
|
},
|
|
42
41
|
"devDependencies": {
|
|
43
|
-
"@internal/assemble": "0.
|
|
44
|
-
"@internal/cli": "0.
|
|
45
|
-
"@internal/core": "0.
|
|
46
|
-
"@internal/foundation": "0.
|
|
47
|
-
"@internal/lowering": "0.
|
|
48
|
-
"@internal/nextjs": "0.
|
|
49
|
-
"@internal/node": "0.
|
|
50
|
-
"@internal/service-rpc": "0.
|
|
51
|
-
"@internal/tsdown-config": "0.
|
|
42
|
+
"@internal/assemble": "0.26.0-dev.1",
|
|
43
|
+
"@internal/cli": "0.26.0-dev.1",
|
|
44
|
+
"@internal/core": "0.26.0-dev.1",
|
|
45
|
+
"@internal/foundation": "0.26.0-dev.1",
|
|
46
|
+
"@internal/lowering": "0.26.0-dev.1",
|
|
47
|
+
"@internal/nextjs": "0.26.0-dev.1",
|
|
48
|
+
"@internal/node": "0.26.0-dev.1",
|
|
49
|
+
"@internal/service-rpc": "0.26.0-dev.1",
|
|
50
|
+
"@internal/tsdown-config": "0.26.0-dev.1",
|
|
52
51
|
"@types/node": "^26.0.1",
|
|
53
52
|
"tsdown": "^0.22.7",
|
|
54
53
|
"typescript": "^6.0.3"
|
|
@@ -2,27 +2,27 @@
|
|
|
2
2
|
name: prisma-composer-core-concepts
|
|
3
3
|
metadata:
|
|
4
4
|
library: "@prisma/composer"
|
|
5
|
-
library_version: "0.
|
|
5
|
+
library_version: "0.26.0-dev.1"
|
|
6
6
|
version: 2026.9.1
|
|
7
7
|
description: >-
|
|
8
8
|
Use when deploying or managing an app that uses Prisma Composer
|
|
9
9
|
(`@prisma/composer`): wiring its services and Modules, running it locally,
|
|
10
10
|
testing composed services, or standing up / tearing down an environment.
|
|
11
|
-
Triggers on "prisma composer", "@prisma/composer", "prisma app",
|
|
12
|
-
`prisma
|
|
11
|
+
Triggers on "prisma composer", "@prisma/composer", "prisma app",
|
|
12
|
+
`prisma deploy`, `prisma dev`, `compute()`, `module()`, `contract()`,
|
|
13
13
|
`service.load()`, `mockService`, `bootstrapService`.
|
|
14
14
|
---
|
|
15
15
|
|
|
16
16
|
# Prisma Composer core concepts
|
|
17
17
|
|
|
18
18
|
A **Prisma App** is a tree of typed declarations composed in TypeScript and
|
|
19
|
-
handed to the `prisma
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
than inferring
|
|
19
|
+
handed to the `prisma` CLI, which has two Composer commands: `prisma deploy`
|
|
20
|
+
and `prisma dev`. Teardown and logs are not commands; they are the `destroy`
|
|
21
|
+
and `log` operations of `@prisma/composer/control`, called from a script.
|
|
22
|
+
This file covers structures, hierarchies, relationships, and workflows: the
|
|
23
|
+
concepts you cannot observe from the code or the CLI's help output. It is not
|
|
24
|
+
a CLI reference; discover each command's flags with `prisma <command> --help`
|
|
25
|
+
rather than inferring them. The Prisma platform moves fast, so treat this file as the
|
|
26
26
|
stable conceptual core and find current, fuller documentation at
|
|
27
27
|
<https://www.prisma.io/docs>. For working code, read `examples/` in the
|
|
28
28
|
prisma/composer repo.
|
|
@@ -87,8 +87,8 @@ is a couple of lines.
|
|
|
87
87
|
Within the entry graph (everything reachable from `module.ts`), write
|
|
88
88
|
relative imports with explicit `.ts` extensions (`./service.ts`, with
|
|
89
89
|
`allowImportingTsExtensions` in tsconfig): that form resolves everywhere.
|
|
90
|
-
|
|
91
|
-
`./service` to the `.ts` source, but other
|
|
90
|
+
`prisma deploy` and `prisma dev` also map `./service.js` and extensionless
|
|
91
|
+
`./service` to the `.ts` source, but other tools may not.
|
|
92
92
|
|
|
93
93
|
## The service node is the only doorway
|
|
94
94
|
|
|
@@ -216,13 +216,37 @@ deploy. Rules that bite:
|
|
|
216
216
|
runtime env for prerendered routes.
|
|
217
217
|
4. **Always build before `deploy` or `dev`.** Neither builds for you.
|
|
218
218
|
|
|
219
|
-
Deploy configuration
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
219
|
+
Deploy configuration is the `composer` section of `prisma.config.ts`, and
|
|
220
|
+
nothing else. It registers extensions (`prismaCloud()`, `nodeBuild()`,
|
|
221
|
+
`nextjsBuild()` when the app has a Next.js service) and the deploy-state
|
|
222
|
+
backend (`prismaState()`):
|
|
223
|
+
|
|
224
|
+
```ts
|
|
225
|
+
// prisma.config.ts
|
|
226
|
+
import { defineConfig as composer } from '@prisma/composer/config';
|
|
227
|
+
import { nodeBuild } from '@prisma/composer/node/control';
|
|
228
|
+
import { prismaCloud, prismaState } from '@prisma/composer-prisma-cloud/control';
|
|
229
|
+
import { definePrismaConfig } from 'prisma/config';
|
|
230
|
+
|
|
231
|
+
export default definePrismaConfig({
|
|
232
|
+
composer: composer({ extensions: [prismaCloud(), nodeBuild()], state: prismaState() }),
|
|
233
|
+
});
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
The commands find `prisma.config.ts` from the directory they run in, walking up
|
|
237
|
+
to the repository root; the nearest file that declares `composer` wins, and its
|
|
238
|
+
section is used whole, never merged key by key. Only `extensions` and `state`
|
|
239
|
+
are allowed; any other key is an error. App code never imports the file.
|
|
240
|
+
|
|
241
|
+
A separate `prisma-composer.config.ts` is no longer read, and the old setup is
|
|
242
|
+
refused, never silently ignored: `CONFIG.SECTION_MISSING` when no loaded
|
|
243
|
+
`prisma.config.ts` declares a `composer` section, `CONFIG.FIELD_RETIRED` when
|
|
244
|
+
the section still has `configPath`, `CONFIG.FILE_RETIRED` when a
|
|
245
|
+
`prisma-composer.config.*` sits next to the declaring `prisma.config.ts`; all
|
|
246
|
+
three under the CLI's `CLI.CONFIG_SECTION_INVALID`. The fix for all three is to move the old
|
|
247
|
+
file's `extensions` and `state` into the section and delete the old file.
|
|
248
|
+
`@prisma/composer-cli/family` no longer exports `ComposerSection`; the
|
|
249
|
+
section's type is `PrismaAppConfig` from `@prisma/composer/config`.
|
|
226
250
|
|
|
227
251
|
## Databases and migrations
|
|
228
252
|
|
|
@@ -252,6 +276,11 @@ including the first schema of a new database, follows one loop:
|
|
|
252
276
|
4. Commit `migrations/` with the change, then deploy. A fresh database
|
|
253
277
|
replays the whole path from empty.
|
|
254
278
|
|
|
279
|
+
Every service that uses the database deploys only after its migration
|
|
280
|
+
completes: a failed migration means the new code does not ship. The old
|
|
281
|
+
code serves against the new schema until the new deployment is live, so
|
|
282
|
+
keep each migration compatible with the code it replaces.
|
|
283
|
+
|
|
255
284
|
If no authored path reaches the target contract, deploy (and `dev` against a
|
|
256
285
|
stale local database) refuses with `MIGRATION_PATH_NOT_FOUND`; its message
|
|
257
286
|
lists the two ways out: author the missing migration, or, when iterating
|
|
@@ -267,9 +296,14 @@ complete pattern.
|
|
|
267
296
|
|
|
268
297
|
Deploy compares the declared topology against recorded deploy state and
|
|
269
298
|
applies only the difference. Re-deploying with nothing changed is a no-op;
|
|
270
|
-
removing a node removes its deployed resource.
|
|
271
|
-
|
|
272
|
-
`
|
|
299
|
+
removing a node removes its deployed resource. `prisma deploy` needs a signed-in
|
|
300
|
+
identity: `prisma auth login` stores a session on a developer machine, and
|
|
301
|
+
`PRISMA_SERVICE_TOKEN` overrides it in CI. The `/control` operations, and so
|
|
302
|
+
a destroy script, never use that session: `deploy` and `destroy` read
|
|
303
|
+
`PRISMA_SERVICE_TOKEN` and `PRISMA_WORKSPACE_ID` from the environment (both
|
|
304
|
+
in the workspace's Console settings); `dev` and `log` read neither. The
|
|
305
|
+
`prisma` bin starts under Node; when the modules `module.ts` imports use Bun
|
|
306
|
+
APIs, run it under Bun (`bun node_modules/.bin/prisma deploy module.ts`).
|
|
273
307
|
|
|
274
308
|
**Stages.** A stage is an environment name chosen on the command line at
|
|
275
309
|
deploy time, never written in the topology. The identical graph deploys
|
|
@@ -278,8 +312,14 @@ stage is a Branch of it, with its own running services, its own empty
|
|
|
278
312
|
database, its own configuration. A stage name must be a valid git ref name;
|
|
279
313
|
an invalid name is a hard error.
|
|
280
314
|
|
|
281
|
-
**Destroy**
|
|
282
|
-
|
|
315
|
+
**Destroy** is the `destroy` operation, and its `target` is required:
|
|
316
|
+
`{ kind: 'stage', stage }` or `{ kind: 'production' }`, never a default:
|
|
317
|
+
|
|
318
|
+
```ts
|
|
319
|
+
await destroy({ entry: 'module.ts', target: { kind: 'stage', stage: 'pr-42' }, config });
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
Destroying a stage
|
|
283
323
|
deletes its Branch after removing its resources. Destroying production
|
|
284
324
|
removes only the resources inside the production Branch, never the Branch
|
|
285
325
|
itself directly; once the Project is empty it is deleted too, and that
|
|
@@ -295,7 +335,7 @@ ancestor directories. Windows resolves `alchemy.exe`, then `alchemy.cmd`,
|
|
|
295
335
|
then the extensionless shim; POSIX resolves `alchemy`. No global Alchemy
|
|
296
336
|
installation is needed.
|
|
297
337
|
|
|
298
|
-
1.
|
|
338
|
+
1. The deploy and destroy operations write the pipeline's results to a generated, gitignored
|
|
299
339
|
stack file at `.prisma-composer/alchemy.run.ts`, then run the alchemy CLI
|
|
300
340
|
against it as a child process; `dev` does the same at
|
|
301
341
|
`.prisma-composer/dev/alchemy.run.ts` with local providers. The file
|
|
@@ -306,8 +346,9 @@ installation is needed.
|
|
|
306
346
|
path; running `alchemy deploy .prisma-composer/alchemy.run.ts` directly
|
|
307
347
|
separates "the framework computed the wrong thing" from "the engine or
|
|
308
348
|
platform rejected the right thing". An engine failure surfaces as
|
|
309
|
-
`DEPLOY.ENGINE_FAILED` carrying the exit code
|
|
310
|
-
|
|
349
|
+
`DEPLOY.ENGINE_FAILED` carrying the exit code, the engine's own error
|
|
350
|
+
lines (credentials redacted, capped at 1000 characters) and that reproduce
|
|
351
|
+
command; the child's live output streams to the terminal either way.
|
|
311
352
|
3. Destroy evaluates the same stack program as deploy, and evaluating it
|
|
312
353
|
packages the assembled bundles, so **an app must be built before it can
|
|
313
354
|
be torn down**.
|
|
@@ -336,17 +377,27 @@ and crash the consumer at boot). Fix whichever end is wrong; don't mark the
|
|
|
336
377
|
param `optional` unless absent really is legal. Only reachable if you
|
|
337
378
|
authored the connection or an extension on one side.
|
|
338
379
|
|
|
339
|
-
**Driving deploys from code.**
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
`
|
|
380
|
+
**Driving deploys from code.** A script imports only
|
|
381
|
+
`@prisma/composer/control`; the extensions' `/control` entries are imported
|
|
382
|
+
only by `prisma.config.ts` (ADR-0017). `@prisma/composer/control` exposes typed
|
|
383
|
+
`deploy`, `destroy`, `dev`, and `log` returning structured results;
|
|
384
|
+
`prisma deploy` and `prisma dev` render `deploy` and `dev`. Each takes
|
|
385
|
+
a required `config: { value, file }` (`ComposerConfigSource`): the `composer`
|
|
386
|
+
export of your `prisma.config.ts` and that file's path; a relative `file`
|
|
387
|
+
resolves against `cwd`, so build it from `import.meta.url`. The operations
|
|
388
|
+
never look for a config file, but refuse what the CLI refuses before any work
|
|
389
|
+
starts (`CONFIG.FIELD_UNKNOWN` for the whole export instead of its `composer`
|
|
390
|
+
property, `CONFIG.FILE_RETIRED`, `CONFIG.FILE_MISSING`); the deploy re-imports
|
|
391
|
+
`file`, so `value` must be its `composer` export. Failures come back as
|
|
392
|
+
`{ ok: false, failure }` with a dotted `failure.code` from a closed registry
|
|
393
|
+
(e.g. `ASSEMBLE.BUILD_FAILED`, `DEPLOY.ENGINE_FAILED`,
|
|
394
|
+
`DEPS.EXECUTOR_UNLOADABLE`); branch on the code, not the message. A
|
|
344
395
|
non-structured rejection out of an operation is a bug in composer, not an
|
|
345
396
|
expected failure.
|
|
346
397
|
|
|
347
398
|
## Local development
|
|
348
399
|
|
|
349
|
-
|
|
400
|
+
`prisma dev` runs the whole app on this machine, wired as it deploys,
|
|
350
401
|
against local emulators. No cloud credentials are needed or read. Concepts
|
|
351
402
|
that surprise:
|
|
352
403
|
|
|
@@ -356,13 +407,20 @@ that surprise:
|
|
|
356
407
|
2. Ctrl-C stops the app's processes but leaves local databases, buckets, and
|
|
357
408
|
their data up: the next `dev` is a warm start. Starting clean, wiping
|
|
358
409
|
this app's local instances and data first, is an explicit opt-in flag.
|
|
359
|
-
3. `dev` does not print service logs
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
410
|
+
3. `dev` does not print service logs. The `log` operation follows the
|
|
411
|
+
already-running app's merged logs; it never builds, provisions, starts, or
|
|
412
|
+
stops anything:
|
|
413
|
+
|
|
414
|
+
```ts
|
|
415
|
+
const attached = await log({ entry: 'module.ts', config, tail: 20, signal });
|
|
416
|
+
if (attached.ok) for await (const { service, line } of attached.value.lines) console.log(service, line);
|
|
417
|
+
```
|
|
418
|
+
4. `dev` reads `prisma.config.ts` once, at start, and watches it: after an
|
|
419
|
+
edit it says so and pauses rebuilds until you restart `dev`.
|
|
420
|
+
5. An unset secret doesn't block a local run: it becomes a placeholder plus a
|
|
363
421
|
warning, and only the code path that spends it fails, at the external
|
|
364
422
|
service it calls.
|
|
365
|
-
|
|
423
|
+
6. Windows isn't supported yet.
|
|
366
424
|
|
|
367
425
|
Local Postgres runs on `@prisma/dev`, which `@prisma/composer-prisma-cloud`
|
|
368
426
|
declares as its own dependency (`^0.25.2`) and resolves from its own package.
|
|
@@ -432,10 +490,12 @@ today the blocks above plus your own Modules are the whole set, so verify a
|
|
|
432
490
|
|
|
433
491
|
## Failure modes quick reference
|
|
434
492
|
|
|
435
|
-
1.
|
|
436
|
-
version conflict** (`
|
|
437
|
-
|
|
438
|
-
|
|
493
|
+
1. **`prisma deploy` and `prisma dev` stop with `CLI.CONFIG_UNREADABLE` on an
|
|
494
|
+
`effect` version conflict** (`prisma.config.ts could not be evaluated:`
|
|
495
|
+
followed by a module error from inside alchemy, such as
|
|
496
|
+
`Schema.TaggedError is not a function`). The extensions in the `composer`
|
|
497
|
+
section import alchemy, and the app, or one of its dependencies, pins a
|
|
498
|
+
different `effect` that the package manager hoisted over Composer's pin. Match the app's own
|
|
439
499
|
`effect` to `@prisma/composer`'s exact pin, or force it with
|
|
440
500
|
`"overrides": { "effect": "<pin>" }` in the app's `package.json` (yarn:
|
|
441
501
|
`resolutions`; pnpm: `pnpm.overrides`), then reinstall. A plain Composer
|
|
@@ -486,9 +546,10 @@ today the blocks above plus your own Modules are the whole set, so verify a
|
|
|
486
546
|
|
|
487
547
|
Name the gap instead of inventing an API:
|
|
488
548
|
|
|
489
|
-
1. **No
|
|
490
|
-
|
|
491
|
-
`
|
|
549
|
+
1. **No `prisma` command for teardown or logs.** Use the `destroy` and `log`
|
|
550
|
+
operations of `@prisma/composer/control` from a script. A destroy script
|
|
551
|
+
cannot use the `prisma auth login` session; it needs `PRISMA_SERVICE_TOKEN`
|
|
552
|
+
and `PRISMA_WORKSPACE_ID` in the environment.
|
|
492
553
|
2. **No in-memory contract bindings.** A dependency can't yet be wired to a
|
|
493
554
|
co-located handler without HTTP; use `bootstrapService` with a loopback
|
|
494
555
|
fake.
|
package/src/exports/testing.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Public surface (the `./testing` subpath): `mockService`, the application
|
|
3
|
-
* unit-test seam for composed services. The command family's
|
|
3
|
+
* unit-test seam for composed services. The command family's operations double
|
|
4
4
|
* lives in `@prisma/composer-cli/testing`.
|
|
5
5
|
*/
|
|
6
6
|
export * from '@internal/core/testing';
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import "./app-config-jGcCcxK4-DnzGGbDS.mjs";
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import "./app-config-jGcCcxK4-DnzGGbDS.mjs";
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { t as blindCast } from "./casts-DpaahrlC-C5XMnP9S.mjs";
|
|
2
|
-
import * as fs$1 from "node:fs";
|
|
3
|
-
//#region ../../0-framework/3-tooling/cli/dist/deployment-summary-DswOl_9E.mjs
|
|
4
|
-
/**
|
|
5
|
-
* The deploy result's cross-process protocol, whole in one place: the
|
|
6
|
-
* serializable shape, the env var that names the carrier file, the writer the
|
|
7
|
-
* report hook calls from inside the alchemy child, and the reader the deploy
|
|
8
|
-
* operation runs after the child exits. `DeploymentResult` itself cannot
|
|
9
|
-
* cross the boundary — its `DeployedNode` entries hold live graph-node
|
|
10
|
-
* references (ADR-0033) — so the writer projects it down to what CAN.
|
|
11
|
-
*
|
|
12
|
-
* The summary is best-effort by contract: the writer never fails the child
|
|
13
|
-
* over it, and the reader maps absent or malformed to `undefined`.
|
|
14
|
-
*/
|
|
15
|
-
/** Env var the deploy operation sets on the alchemy child: when present,
|
|
16
|
-
* the report hook also writes the JSON DeploymentSummary there. */
|
|
17
|
-
const DEPLOYMENT_RESULT_FILE_ENV = "PRISMA_COMPOSER_DEPLOYMENT_RESULT_FILE";
|
|
18
|
-
/** Pure projection: keeps app + each node's address/entities, drops the in-process `node`. */
|
|
19
|
-
function toDeploymentSummary(result) {
|
|
20
|
-
return {
|
|
21
|
-
app: result.app,
|
|
22
|
-
nodes: result.nodes.map((node) => ({
|
|
23
|
-
address: node.address,
|
|
24
|
-
entities: node.entities
|
|
25
|
-
}))
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Writer half, called by the report hook inside the alchemy child: when the
|
|
30
|
-
* env var names a file, write the summary there. Best-effort — a write
|
|
31
|
-
* failure must not fail a deploy that already converged, so it is swallowed.
|
|
32
|
-
*/
|
|
33
|
-
function writeDeploymentSummaryFile(result) {
|
|
34
|
-
const file = process.env[DEPLOYMENT_RESULT_FILE_ENV];
|
|
35
|
-
if (file === void 0 || file.length === 0) return;
|
|
36
|
-
try {
|
|
37
|
-
fs$1.writeFileSync(file, JSON.stringify(toDeploymentSummary(result)));
|
|
38
|
-
} catch {}
|
|
39
|
-
}
|
|
40
|
-
function isRecord(value) {
|
|
41
|
-
return typeof value === "object" && value !== null;
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Reader half, run by the deploy operation after the child exits. Absent or
|
|
45
|
-
* malformed → undefined — the summary is best-effort, never a deploy failure.
|
|
46
|
-
*/
|
|
47
|
-
function readDeploymentSummary(resultFilePath) {
|
|
48
|
-
let raw;
|
|
49
|
-
try {
|
|
50
|
-
raw = fs$1.readFileSync(resultFilePath, "utf8");
|
|
51
|
-
} catch {
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
let parsed;
|
|
55
|
-
try {
|
|
56
|
-
parsed = JSON.parse(raw);
|
|
57
|
-
} catch {
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
if (!isRecord(parsed) || typeof parsed["app"] !== "string" || !Array.isArray(parsed["nodes"])) return;
|
|
61
|
-
for (const node of parsed["nodes"]) {
|
|
62
|
-
if (!isRecord(node) || typeof node["address"] !== "string" || !Array.isArray(node["entities"])) return;
|
|
63
|
-
for (const entity of node["entities"]) if (!isRecord(entity) || typeof entity["kind"] !== "string" || typeof entity["id"] !== "string") return;
|
|
64
|
-
}
|
|
65
|
-
return blindCast(parsed);
|
|
66
|
-
}
|
|
67
|
-
//#endregion
|
|
68
|
-
export { readDeploymentSummary as n, writeDeploymentSummaryFile as r, DEPLOYMENT_RESULT_FILE_ENV as t };
|
|
69
|
-
|
|
70
|
-
//# sourceMappingURL=deployment-summary-DswOl_9E-B9MhYYDt.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"deployment-summary-DswOl_9E-B9MhYYDt.mjs","names":["fs"],"sources":["../../../0-framework/3-tooling/cli/dist/deployment-summary-DswOl_9E.mjs"],"sourcesContent":["import * as fs from \"node:fs\";\nimport { blindCast } from \"@internal/foundation/casts\";\n//#region src/deployment-summary.ts\n/**\n* The deploy result's cross-process protocol, whole in one place: the\n* serializable shape, the env var that names the carrier file, the writer the\n* report hook calls from inside the alchemy child, and the reader the deploy\n* operation runs after the child exits. `DeploymentResult` itself cannot\n* cross the boundary — its `DeployedNode` entries hold live graph-node\n* references (ADR-0033) — so the writer projects it down to what CAN.\n*\n* The summary is best-effort by contract: the writer never fails the child\n* over it, and the reader maps absent or malformed to `undefined`.\n*/\n/** Env var the deploy operation sets on the alchemy child: when present,\n* the report hook also writes the JSON DeploymentSummary there. */\nconst DEPLOYMENT_RESULT_FILE_ENV = \"PRISMA_COMPOSER_DEPLOYMENT_RESULT_FILE\";\n/** Pure projection: keeps app + each node's address/entities, drops the in-process `node`. */\nfunction toDeploymentSummary(result) {\n\treturn {\n\t\tapp: result.app,\n\t\tnodes: result.nodes.map((node) => ({\n\t\t\taddress: node.address,\n\t\t\tentities: node.entities\n\t\t}))\n\t};\n}\n/**\n* Writer half, called by the report hook inside the alchemy child: when the\n* env var names a file, write the summary there. Best-effort — a write\n* failure must not fail a deploy that already converged, so it is swallowed.\n*/\nfunction writeDeploymentSummaryFile(result) {\n\tconst file = process.env[DEPLOYMENT_RESULT_FILE_ENV];\n\tif (file === void 0 || file.length === 0) return;\n\ttry {\n\t\tfs.writeFileSync(file, JSON.stringify(toDeploymentSummary(result)));\n\t} catch {}\n}\nfunction isRecord(value) {\n\treturn typeof value === \"object\" && value !== null;\n}\n/**\n* Reader half, run by the deploy operation after the child exits. Absent or\n* malformed → undefined — the summary is best-effort, never a deploy failure.\n*/\nfunction readDeploymentSummary(resultFilePath) {\n\tlet raw;\n\ttry {\n\t\traw = fs.readFileSync(resultFilePath, \"utf8\");\n\t} catch {\n\t\treturn;\n\t}\n\tlet parsed;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch {\n\t\treturn;\n\t}\n\tif (!isRecord(parsed) || typeof parsed[\"app\"] !== \"string\" || !Array.isArray(parsed[\"nodes\"])) return;\n\tfor (const node of parsed[\"nodes\"]) {\n\t\tif (!isRecord(node) || typeof node[\"address\"] !== \"string\" || !Array.isArray(node[\"entities\"])) return;\n\t\tfor (const entity of node[\"entities\"]) if (!isRecord(entity) || typeof entity[\"kind\"] !== \"string\" || typeof entity[\"id\"] !== \"string\") return;\n\t}\n\treturn blindCast(parsed);\n}\n//#endregion\nexport { readDeploymentSummary as n, writeDeploymentSummaryFile as r, DEPLOYMENT_RESULT_FILE_ENV as t };\n\n//# sourceMappingURL=deployment-summary-DswOl_9E.mjs.map"],"mappings":";;;;;;;;;;;;;;;;AAgBA,MAAM,6BAA6B;;AAEnC,SAAS,oBAAoB,QAAQ;CACpC,OAAO;EACN,KAAK,OAAO;EACZ,OAAO,OAAO,MAAM,KAAK,UAAU;GAClC,SAAS,KAAK;GACd,UAAU,KAAK;EAChB,EAAE;CACH;AACD;;;;;;AAMA,SAAS,2BAA2B,QAAQ;CAC3C,MAAM,OAAO,QAAQ,IAAI;CACzB,IAAI,SAAS,KAAK,KAAK,KAAK,WAAW,GAAG;CAC1C,IAAI;EACH,KAAG,cAAc,MAAM,KAAK,UAAU,oBAAoB,MAAM,CAAC,CAAC;CACnE,QAAQ,CAAC;AACV;AACA,SAAS,SAAS,OAAO;CACxB,OAAO,OAAO,UAAU,YAAY,UAAU;AAC/C;;;;;AAKA,SAAS,sBAAsB,gBAAgB;CAC9C,IAAI;CACJ,IAAI;EACH,MAAMA,KAAG,aAAa,gBAAgB,MAAM;CAC7C,QAAQ;EACP;CACD;CACA,IAAI;CACJ,IAAI;EACH,SAAS,KAAK,MAAM,GAAG;CACxB,QAAQ;EACP;CACD;CACA,IAAI,CAAC,SAAS,MAAM,KAAK,OAAO,OAAO,WAAW,YAAY,CAAC,MAAM,QAAQ,OAAO,QAAQ,GAAG;CAC/F,KAAK,MAAM,QAAQ,OAAO,UAAU;EACnC,IAAI,CAAC,SAAS,IAAI,KAAK,OAAO,KAAK,eAAe,YAAY,CAAC,MAAM,QAAQ,KAAK,WAAW,GAAG;EAChG,KAAK,MAAM,UAAU,KAAK,aAAa,IAAI,CAAC,SAAS,MAAM,KAAK,OAAO,OAAO,YAAY,YAAY,OAAO,OAAO,UAAU,UAAU;CACzI;CACA,OAAO,UAAU,MAAM;AACxB"}
|