@prisma/composer-cli 0.6.0-dev.21
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/LICENSE +201 -0
- package/dist/bin.mjs +987 -0
- package/dist/bin.mjs.map +1 -0
- package/dist/container-transport-DKmKg5JQ-CoY4XPma.mjs +30 -0
- package/dist/container-transport-DKmKg5JQ-CoY4XPma.mjs.map +1 -0
- package/dist/execute-deploy-destroy-DfVJUICu-D-kARRtf.mjs +317 -0
- package/dist/execute-deploy-destroy-DfVJUICu-D-kARRtf.mjs.map +1 -0
- package/dist/execute-deploy-destroy-DfVJUICu-quUQ08T8.mjs +316 -0
- package/dist/execute-deploy-destroy-DfVJUICu-quUQ08T8.mjs.map +1 -0
- package/dist/execute-dev-BMTFWfFc-B1whS-Rr.mjs +2011 -0
- package/dist/execute-dev-BMTFWfFc-B1whS-Rr.mjs.map +1 -0
- package/dist/execute-dev-BMTFWfFc-D0niyhe3.mjs +2012 -0
- package/dist/execute-dev-BMTFWfFc-D0niyhe3.mjs.map +1 -0
- package/dist/execute-log-Cay9hlKW-DJMh35AZ.mjs +158 -0
- package/dist/execute-log-Cay9hlKW-DJMh35AZ.mjs.map +1 -0
- package/dist/execute-log-Cay9hlKW-DrMeVOXq.mjs +157 -0
- package/dist/execute-log-Cay9hlKW-DrMeVOXq.mjs.map +1 -0
- package/dist/family-DkH0si4D-CN5QubKS.d.mts +1294 -0
- package/dist/family-DkH0si4D-CN5QubKS.d.mts.map +1 -0
- package/dist/family.d.mts +52 -0
- package/dist/family.d.mts.map +1 -0
- package/dist/family.mjs +923 -0
- package/dist/family.mjs.map +1 -0
- package/dist/local-target-CBZyaBy0.mjs +68 -0
- package/dist/local-target-CBZyaBy0.mjs.map +1 -0
- package/dist/local-target-H0IWu_FM.mjs +68 -0
- package/dist/local-target-H0IWu_FM.mjs.map +1 -0
- package/dist/pipeline-AoW8zq4I-C6Qe0VaZ.mjs +976 -0
- package/dist/pipeline-AoW8zq4I-C6Qe0VaZ.mjs.map +1 -0
- package/dist/pipeline-AoW8zq4I-DYNbf-ad.mjs +977 -0
- package/dist/pipeline-AoW8zq4I-DYNbf-ad.mjs.map +1 -0
- package/dist/result-B4XjxVK6.mjs +384 -0
- package/dist/result-B4XjxVK6.mjs.map +1 -0
- package/dist/result-D4d-xy4I.mjs +230 -0
- package/dist/result-D4d-xy4I.mjs.map +1 -0
- package/dist/run-alchemy-D44OZlyB-DA7s331N.mjs +93 -0
- package/dist/run-alchemy-D44OZlyB-DA7s331N.mjs.map +1 -0
- package/dist/run-alchemy-D44OZlyB-wmf8mHRE.mjs +93 -0
- package/dist/run-alchemy-D44OZlyB-wmf8mHRE.mjs.map +1 -0
- package/dist/shared-BTnATsqm-CDCqKwCF.mjs +158 -0
- package/dist/shared-BTnATsqm-CDCqKwCF.mjs.map +1 -0
- package/dist/testing.d.mts +53 -0
- package/dist/testing.d.mts.map +1 -0
- package/dist/testing.mjs +151 -0
- package/dist/testing.mjs.map +1 -0
- package/package.json +53 -0
- package/src/exports/family.ts +14 -0
- package/src/exports/testing.ts +6 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { i as CliStructuredError, s as blindCast } from "./result-D4d-xy4I.mjs";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import * as fs from "node:fs";
|
|
4
|
+
import * as path from "node:path";
|
|
5
|
+
//#region ../../0-framework/3-tooling/cli/dist/shared-BTnATsqm.mjs
|
|
6
|
+
/**
|
|
7
|
+
* Deploy preflight (TML-3158): verify that alchemy resolves the exact `effect`
|
|
8
|
+
* version @prisma/composer pins. Package managers cannot be made to enforce
|
|
9
|
+
* this — alchemy's own peer range accepts newer effect betas, and npm resolves
|
|
10
|
+
* transitive peer conflicts with a warning, not a failure — so a floating
|
|
11
|
+
* `@effect/*` range anywhere in the consumer's tree can hoist a newer effect
|
|
12
|
+
* to the root, where alchemy picks it up and crashes mid-deploy
|
|
13
|
+
* (`TypeError: Schedule.either is not a function`). This check turns that
|
|
14
|
+
* silent break into a start-up error naming the fix.
|
|
15
|
+
*/
|
|
16
|
+
/** Walks up from `startDir` looking for `node_modules/alchemy` (mirrors resolveAlchemyBin). Undefined when absent — the check skips rather than second-guessing later, clearer failures. */
|
|
17
|
+
function findAlchemyPackageDir(startDir) {
|
|
18
|
+
let dir = startDir;
|
|
19
|
+
while (true) {
|
|
20
|
+
const candidate = path.join(dir, "node_modules", "alchemy");
|
|
21
|
+
if (fs.existsSync(path.join(candidate, "package.json"))) return candidate;
|
|
22
|
+
const parent = path.dirname(dir);
|
|
23
|
+
if (parent === dir) return void 0;
|
|
24
|
+
dir = parent;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The `effect` version Node gives `packageDir`'s code, resolved exactly as
|
|
29
|
+
* Node would: from the package's real path (so pnpm symlink layouts resolve
|
|
30
|
+
* from the package's own store position, like at runtime). Undefined when
|
|
31
|
+
* `effect` is not resolvable from there.
|
|
32
|
+
*/
|
|
33
|
+
function resolveEffectVersionFrom(packageDir) {
|
|
34
|
+
let entry;
|
|
35
|
+
try {
|
|
36
|
+
entry = createRequire(path.join(fs.realpathSync(packageDir), "noop.js")).resolve("effect");
|
|
37
|
+
} catch {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
let dir = path.dirname(entry);
|
|
41
|
+
while (!fs.existsSync(path.join(dir, "package.json"))) {
|
|
42
|
+
const parent = path.dirname(dir);
|
|
43
|
+
if (parent === dir) return void 0;
|
|
44
|
+
dir = parent;
|
|
45
|
+
}
|
|
46
|
+
const version = JSON.parse(fs.readFileSync(path.join(dir, "package.json"), "utf-8")).version;
|
|
47
|
+
return typeof version === "string" ? version : void 0;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* The `effect` version @prisma/composer pins, read from its own installed
|
|
51
|
+
* package.json — the single source of truth; never hardcoded here. Undefined
|
|
52
|
+
* when @prisma/composer is not resolvable from `startDir` (e.g. the CLI is
|
|
53
|
+
* driven some other way), in which case the check skips.
|
|
54
|
+
*
|
|
55
|
+
* Assumes the pin is an exact version — effectMismatchError compares with
|
|
56
|
+
* `===`, which scripts/check-npm-effect-resolution.mjs enforces in CI;
|
|
57
|
+
* relaxing the pin to a range means revisiting that comparison.
|
|
58
|
+
*/
|
|
59
|
+
function requiredEffectVersion(startDir) {
|
|
60
|
+
let manifestPath;
|
|
61
|
+
try {
|
|
62
|
+
manifestPath = createRequire(path.join(startDir, "noop.js")).resolve("@prisma/composer/package.json");
|
|
63
|
+
} catch {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
|
|
67
|
+
if (typeof manifest !== "object" || manifest === null || !("dependencies" in manifest)) return;
|
|
68
|
+
const dependencies = manifest.dependencies;
|
|
69
|
+
if (typeof dependencies !== "object" || dependencies === null || !("effect" in dependencies)) return;
|
|
70
|
+
const version = dependencies.effect;
|
|
71
|
+
return typeof version === "string" ? version : void 0;
|
|
72
|
+
}
|
|
73
|
+
/** Pure comparison + parts rendering, separated so tests cover the rule without a filesystem. Returns the structured error parts, or undefined when the tree is healthy or either side is unknown. */
|
|
74
|
+
function effectMismatchError(found, required) {
|
|
75
|
+
if (found === void 0 || required === void 0 || found === required) return void 0;
|
|
76
|
+
return {
|
|
77
|
+
summary: `Dependency conflict: alchemy resolves effect@${found}, but @prisma/composer requires effect@${required}.`,
|
|
78
|
+
why: "Your package manager installed a second effect that alchemy picks up; deploying with it would crash inside alchemy.",
|
|
79
|
+
fix: `Add this to your app's package.json, then reinstall:
|
|
80
|
+
|
|
81
|
+
"overrides": { "effect": "${required}" }\n\n(npm uses "overrides"; yarn calls it "resolutions", pnpm "pnpm.overrides".)`,
|
|
82
|
+
meta: {
|
|
83
|
+
found,
|
|
84
|
+
required
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Runs the preflight from the app's directory and RETURNS the
|
|
90
|
+
* DEPS.EFFECT_VERSION_CONFLICT error for a mismatched tree; undefined when the
|
|
91
|
+
* tree is healthy or alchemy is not installed.
|
|
92
|
+
*
|
|
93
|
+
* This is the form the config-load machinery uses. The check belongs on the
|
|
94
|
+
* config-load path rather than at import time because that is the first moment
|
|
95
|
+
* anything actually loads alchemy's provider tree — the break it explains —
|
|
96
|
+
* and because a check that runs at import time takes out commands that never
|
|
97
|
+
* touch alchemy at all, help among them.
|
|
98
|
+
*/
|
|
99
|
+
function effectResolutionDiagnostic(cwd) {
|
|
100
|
+
const alchemyDir = findAlchemyPackageDir(cwd);
|
|
101
|
+
if (alchemyDir === void 0) return void 0;
|
|
102
|
+
const parts = effectMismatchError(resolveEffectVersionFrom(alchemyDir), requiredEffectVersion(cwd));
|
|
103
|
+
if (parts === void 0) return void 0;
|
|
104
|
+
return new CliStructuredError("DEPS.EFFECT_VERSION_CONFLICT", parts.summary, {
|
|
105
|
+
why: parts.why,
|
|
106
|
+
fix: parts.fix,
|
|
107
|
+
meta: parts.meta
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
/** The throwing form, used by the executor-load diagnosis — the one caller left now that the bin runs no start-up preflight of its own. */
|
|
111
|
+
function checkEffectResolution(cwd) {
|
|
112
|
+
const diagnostic = effectResolutionDiagnostic(cwd);
|
|
113
|
+
if (diagnostic !== void 0) throw diagnostic;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Reads the execution diagnostics an engine-failure error carries in
|
|
117
|
+
* `meta.diagnostics`; undefined for every other failure.
|
|
118
|
+
*/
|
|
119
|
+
function executionDiagnostics(f) {
|
|
120
|
+
const diagnostics = f.meta?.["diagnostics"];
|
|
121
|
+
if (typeof diagnostics !== "object" || diagnostics === null) return void 0;
|
|
122
|
+
const candidate = blindCast(diagnostics);
|
|
123
|
+
if (candidate["exitCode"] !== void 0 && typeof candidate["exitCode"] !== "number" || candidate["signal"] !== void 0 && typeof candidate["signal"] !== "string" || typeof candidate["stackFilePath"] !== "string" || typeof candidate["reproduceCommand"] !== "string" || typeof candidate["cwd"] !== "string") return;
|
|
124
|
+
return blindCast(diagnostics);
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Site-specific wrap for foreign extension/environment causes — passthrough
|
|
128
|
+
* when already structured; never a boundary fallback (base-type rule 6(ii)).
|
|
129
|
+
*/
|
|
130
|
+
function toStructured(code, error) {
|
|
131
|
+
return CliStructuredError.is(error) ? error : new CliStructuredError(code, error instanceof Error ? error.message : String(error), { cause: error });
|
|
132
|
+
}
|
|
133
|
+
/** Diagnoses a failed executor import: when the app's tree resolves a
|
|
134
|
+
* mismatched `effect` (the known way that import breaks), the failure is the
|
|
135
|
+
* fix-naming DEPS.EFFECT_VERSION_CONFLICT from checkEffectResolution with the
|
|
136
|
+
* import error riding as cause; otherwise DEPS.EXECUTOR_UNLOADABLE — an
|
|
137
|
+
* environmental failure of the consumer's installed tree, not a bug here. */
|
|
138
|
+
function executorLoadFailure(operation, error, cwd) {
|
|
139
|
+
try {
|
|
140
|
+
checkEffectResolution(cwd);
|
|
141
|
+
} catch (diagnostic) {
|
|
142
|
+
if (CliStructuredError.is(diagnostic)) return new CliStructuredError(diagnostic.code, diagnostic.message, {
|
|
143
|
+
...diagnostic.why !== void 0 ? { why: diagnostic.why } : {},
|
|
144
|
+
...diagnostic.fix !== void 0 ? { fix: diagnostic.fix } : {},
|
|
145
|
+
...diagnostic.meta !== void 0 ? { meta: diagnostic.meta } : {},
|
|
146
|
+
cause: error
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
return new CliStructuredError("DEPS.EXECUTOR_UNLOADABLE", `Could not load the ${operation} executor: ${error instanceof Error ? error.message : String(error)}`, {
|
|
150
|
+
why: `The ${operation} operation's executor imports the deploy engine's provider tree from your app's installed dependencies, and that import failed.`,
|
|
151
|
+
fix: "Reinstall your dependencies, and check that `alchemy` is installed and loadable from your app.",
|
|
152
|
+
cause: error
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
//#endregion
|
|
156
|
+
export { toStructured as i, executionDiagnostics as n, executorLoadFailure as r, effectResolutionDiagnostic as t };
|
|
157
|
+
|
|
158
|
+
//# sourceMappingURL=shared-BTnATsqm-CDCqKwCF.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared-BTnATsqm-CDCqKwCF.mjs","names":[],"sources":["../../../0-framework/3-tooling/cli/dist/shared-BTnATsqm.mjs"],"sourcesContent":["import { createRequire } from \"node:module\";\nimport { CliStructuredError } from \"@internal/foundation/errors\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { blindCast } from \"@internal/foundation/casts\";\n//#region src/check-effect-resolution.ts\n/**\n* Deploy preflight (TML-3158): verify that alchemy resolves the exact `effect`\n* version @prisma/composer pins. Package managers cannot be made to enforce\n* this — alchemy's own peer range accepts newer effect betas, and npm resolves\n* transitive peer conflicts with a warning, not a failure — so a floating\n* `@effect/*` range anywhere in the consumer's tree can hoist a newer effect\n* to the root, where alchemy picks it up and crashes mid-deploy\n* (`TypeError: Schedule.either is not a function`). This check turns that\n* silent break into a start-up error naming the fix.\n*/\n/** Walks up from `startDir` looking for `node_modules/alchemy` (mirrors resolveAlchemyBin). Undefined when absent — the check skips rather than second-guessing later, clearer failures. */\nfunction findAlchemyPackageDir(startDir) {\n\tlet dir = startDir;\n\twhile (true) {\n\t\tconst candidate = path.join(dir, \"node_modules\", \"alchemy\");\n\t\tif (fs.existsSync(path.join(candidate, \"package.json\"))) return candidate;\n\t\tconst parent = path.dirname(dir);\n\t\tif (parent === dir) return void 0;\n\t\tdir = parent;\n\t}\n}\n/**\n* The `effect` version Node gives `packageDir`'s code, resolved exactly as\n* Node would: from the package's real path (so pnpm symlink layouts resolve\n* from the package's own store position, like at runtime). Undefined when\n* `effect` is not resolvable from there.\n*/\nfunction resolveEffectVersionFrom(packageDir) {\n\tlet entry;\n\ttry {\n\t\tentry = createRequire(path.join(fs.realpathSync(packageDir), \"noop.js\")).resolve(\"effect\");\n\t} catch {\n\t\treturn;\n\t}\n\tlet dir = path.dirname(entry);\n\twhile (!fs.existsSync(path.join(dir, \"package.json\"))) {\n\t\tconst parent = path.dirname(dir);\n\t\tif (parent === dir) return void 0;\n\t\tdir = parent;\n\t}\n\tconst version = JSON.parse(fs.readFileSync(path.join(dir, \"package.json\"), \"utf-8\")).version;\n\treturn typeof version === \"string\" ? version : void 0;\n}\n/**\n* The `effect` version @prisma/composer pins, read from its own installed\n* package.json — the single source of truth; never hardcoded here. Undefined\n* when @prisma/composer is not resolvable from `startDir` (e.g. the CLI is\n* driven some other way), in which case the check skips.\n*\n* Assumes the pin is an exact version — effectMismatchError compares with\n* `===`, which scripts/check-npm-effect-resolution.mjs enforces in CI;\n* relaxing the pin to a range means revisiting that comparison.\n*/\nfunction requiredEffectVersion(startDir) {\n\tlet manifestPath;\n\ttry {\n\t\tmanifestPath = createRequire(path.join(startDir, \"noop.js\")).resolve(\"@prisma/composer/package.json\");\n\t} catch {\n\t\treturn;\n\t}\n\tconst manifest = JSON.parse(fs.readFileSync(manifestPath, \"utf-8\"));\n\tif (typeof manifest !== \"object\" || manifest === null || !(\"dependencies\" in manifest)) return;\n\tconst dependencies = manifest.dependencies;\n\tif (typeof dependencies !== \"object\" || dependencies === null || !(\"effect\" in dependencies)) return;\n\tconst version = dependencies.effect;\n\treturn typeof version === \"string\" ? version : void 0;\n}\n/** Pure comparison + parts rendering, separated so tests cover the rule without a filesystem. Returns the structured error parts, or undefined when the tree is healthy or either side is unknown. */\nfunction effectMismatchError(found, required) {\n\tif (found === void 0 || required === void 0 || found === required) return void 0;\n\treturn {\n\t\tsummary: `Dependency conflict: alchemy resolves effect@${found}, but @prisma/composer requires effect@${required}.`,\n\t\twhy: \"Your package manager installed a second effect that alchemy picks up; deploying with it would crash inside alchemy.\",\n\t\tfix: `Add this to your app's package.json, then reinstall:\n\n \"overrides\": { \"effect\": \"${required}\" }\\n\\n(npm uses \"overrides\"; yarn calls it \"resolutions\", pnpm \"pnpm.overrides\".)`,\n\t\tmeta: {\n\t\t\tfound,\n\t\t\trequired\n\t\t}\n\t};\n}\n/**\n* Runs the preflight from the app's directory and RETURNS the\n* DEPS.EFFECT_VERSION_CONFLICT error for a mismatched tree; undefined when the\n* tree is healthy or alchemy is not installed.\n*\n* This is the form the config-load machinery uses. The check belongs on the\n* config-load path rather than at import time because that is the first moment\n* anything actually loads alchemy's provider tree — the break it explains —\n* and because a check that runs at import time takes out commands that never\n* touch alchemy at all, help among them.\n*/\nfunction effectResolutionDiagnostic(cwd) {\n\tconst alchemyDir = findAlchemyPackageDir(cwd);\n\tif (alchemyDir === void 0) return void 0;\n\tconst parts = effectMismatchError(resolveEffectVersionFrom(alchemyDir), requiredEffectVersion(cwd));\n\tif (parts === void 0) return void 0;\n\treturn new CliStructuredError(\"DEPS.EFFECT_VERSION_CONFLICT\", parts.summary, {\n\t\twhy: parts.why,\n\t\tfix: parts.fix,\n\t\tmeta: parts.meta\n\t});\n}\n/** The throwing form, used by the executor-load diagnosis — the one caller left now that the bin runs no start-up preflight of its own. */\nfunction checkEffectResolution(cwd) {\n\tconst diagnostic = effectResolutionDiagnostic(cwd);\n\tif (diagnostic !== void 0) throw diagnostic;\n}\n//#endregion\n//#region src/operations/shared.ts\n/**\n* Reads the execution diagnostics an engine-failure error carries in\n* `meta.diagnostics`; undefined for every other failure.\n*/\nfunction executionDiagnostics(f) {\n\tconst diagnostics = f.meta?.[\"diagnostics\"];\n\tif (typeof diagnostics !== \"object\" || diagnostics === null) return void 0;\n\tconst candidate = blindCast(diagnostics);\n\tif (candidate[\"exitCode\"] !== void 0 && typeof candidate[\"exitCode\"] !== \"number\" || candidate[\"signal\"] !== void 0 && typeof candidate[\"signal\"] !== \"string\" || typeof candidate[\"stackFilePath\"] !== \"string\" || typeof candidate[\"reproduceCommand\"] !== \"string\" || typeof candidate[\"cwd\"] !== \"string\") return;\n\treturn blindCast(diagnostics);\n}\n/**\n* Site-specific wrap for foreign extension/environment causes — passthrough\n* when already structured; never a boundary fallback (base-type rule 6(ii)).\n*/\nfunction toStructured(code, error) {\n\treturn CliStructuredError.is(error) ? error : new CliStructuredError(code, error instanceof Error ? error.message : String(error), { cause: error });\n}\n/** Diagnoses a failed executor import: when the app's tree resolves a\n* mismatched `effect` (the known way that import breaks), the failure is the\n* fix-naming DEPS.EFFECT_VERSION_CONFLICT from checkEffectResolution with the\n* import error riding as cause; otherwise DEPS.EXECUTOR_UNLOADABLE — an\n* environmental failure of the consumer's installed tree, not a bug here. */\nfunction executorLoadFailure(operation, error, cwd) {\n\ttry {\n\t\tcheckEffectResolution(cwd);\n\t} catch (diagnostic) {\n\t\tif (CliStructuredError.is(diagnostic)) return new CliStructuredError(diagnostic.code, diagnostic.message, {\n\t\t\t...diagnostic.why !== void 0 ? { why: diagnostic.why } : {},\n\t\t\t...diagnostic.fix !== void 0 ? { fix: diagnostic.fix } : {},\n\t\t\t...diagnostic.meta !== void 0 ? { meta: diagnostic.meta } : {},\n\t\t\tcause: error\n\t\t});\n\t}\n\treturn new CliStructuredError(\"DEPS.EXECUTOR_UNLOADABLE\", `Could not load the ${operation} executor: ${error instanceof Error ? error.message : String(error)}`, {\n\t\twhy: `The ${operation} operation's executor imports the deploy engine's provider tree from your app's installed dependencies, and that import failed.`,\n\t\tfix: \"Reinstall your dependencies, and check that `alchemy` is installed and loadable from your app.\",\n\t\tcause: error\n\t});\n}\n//#endregion\nexport { effectResolutionDiagnostic as i, executorLoadFailure as n, toStructured as r, executionDiagnostics as t };\n\n//# sourceMappingURL=shared-BTnATsqm.mjs.map"],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { _ as Result, a as DeployInput, c as DestroyInput, d as LogAttached, f as LogDeps, g as ServiceEndpoint, h as OperationDeps, l as DevInput, m as LogLine, o as DeploySuccess, p as LogInput, s as DestroyEvent, t as ComposerOperations, u as DevSession, v as CliStructuredError } from "./family-DkH0si4D-CN5QubKS.mjs";
|
|
2
|
+
//#region ../../0-framework/3-tooling/cli/dist/testing.d.mts
|
|
3
|
+
//#region src/testing/control-double.d.ts
|
|
4
|
+
interface ControlDoubleFixtures {
|
|
5
|
+
/** Returned as-is; pass notOk(error) for a failing deploy. Default: ok with no summary. */
|
|
6
|
+
readonly deploy?: Result<DeploySuccess, CliStructuredError> | undefined;
|
|
7
|
+
/** Returned as-is. Default: ok. */
|
|
8
|
+
readonly destroy?: Result<void, CliStructuredError> | undefined;
|
|
9
|
+
/** Delivered to the caller's onEvent, in order, before destroy resolves. */
|
|
10
|
+
readonly destroyEvents?: readonly DestroyEvent[] | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* A failing dev: returned as-is, no session starts. When absent, dev
|
|
13
|
+
* succeeds with a working DevSession double over `devEndpoints`.
|
|
14
|
+
*/
|
|
15
|
+
readonly dev?: Result<DevSession, CliStructuredError> | undefined;
|
|
16
|
+
/** The session's front door; emitted as the initial 'ready' event, like the real operation's. */
|
|
17
|
+
readonly devEndpoints?: readonly ServiceEndpoint[] | undefined;
|
|
18
|
+
/** A failing log: returned as-is. When absent, log attaches over the fixtures below. */
|
|
19
|
+
readonly log?: Result<LogAttached, CliStructuredError> | undefined;
|
|
20
|
+
readonly logAppName?: string | undefined;
|
|
21
|
+
readonly logServices?: readonly ServiceEndpoint[] | undefined;
|
|
22
|
+
/** Replayed through the attachment's stream, then the stream ends (or ends early on signal abort). */
|
|
23
|
+
readonly logLines?: readonly LogLine[] | undefined;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The deps each call carried, in the same order as the inputs beside them.
|
|
27
|
+
* These are the operation's SECOND argument — the seam the config path, the
|
|
28
|
+
* converge spawn adapter and the credentials ride in on — so a host that
|
|
29
|
+
* drops one of those is caught here rather than by its absence downstream.
|
|
30
|
+
*/
|
|
31
|
+
interface ControlDoubleDeps {
|
|
32
|
+
readonly deploy: readonly OperationDeps[];
|
|
33
|
+
readonly destroy: readonly OperationDeps[];
|
|
34
|
+
readonly dev: readonly OperationDeps[];
|
|
35
|
+
readonly log: readonly LogDeps[];
|
|
36
|
+
}
|
|
37
|
+
/** Every input each operation received, in call order — the assertion surface. */
|
|
38
|
+
interface ControlDoubleCalls {
|
|
39
|
+
readonly deploy: readonly DeployInput[];
|
|
40
|
+
readonly destroy: readonly DestroyInput[];
|
|
41
|
+
readonly dev: readonly DevInput[];
|
|
42
|
+
readonly log: readonly LogInput[];
|
|
43
|
+
readonly deps: ControlDoubleDeps;
|
|
44
|
+
}
|
|
45
|
+
interface ControlDouble {
|
|
46
|
+
/** Drop-in for the real operations: hand to createComposerFamily({ operations }). */
|
|
47
|
+
readonly operations: ComposerOperations;
|
|
48
|
+
readonly calls: ControlDoubleCalls;
|
|
49
|
+
}
|
|
50
|
+
declare function createControlDouble(fixtures?: ControlDoubleFixtures): ControlDouble;
|
|
51
|
+
//#endregion
|
|
52
|
+
export { type ControlDouble, type ControlDoubleCalls, type ControlDoubleFixtures, createControlDouble };
|
|
53
|
+
//# sourceMappingURL=testing.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testing.d.mts","names":[],"sources":["../../../0-framework/3-tooling/cli/dist/testing.d.mts"],"mappings":";;;UAKU;;WAEC,SAAS,OAAO,eAAe;;WAE/B,UAAU,aAAa;;WAEvB,yBAAyB;;;;;WAKzB,MAAM,OAAO,YAAY;;WAEzB,wBAAwB;;WAExB,MAAM,OAAO,aAAa;WAC1B;WACA,uBAAuB;;WAEvB,oBAAoB;;;;;;;;UAQrB;WACC,iBAAiB;WACjB,kBAAkB;WAClB,cAAc;WACd,cAAc;;;UAGf;WACC,iBAAiB;WACjB,kBAAkB;WAClB,cAAc;WACd,cAAc;WACd,MAAM;;UAEP;;WAEC,YAAY;WACZ,OAAO;;iBAED,oBAAoB,WAAW,wBAAwB"}
|
package/dist/testing.mjs
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { i as CliStructuredError, n as ok, r as okVoid, t as notOk } from "./result-D4d-xy4I.mjs";
|
|
2
|
+
//#region ../../0-framework/3-tooling/cli/dist/testing.mjs
|
|
3
|
+
/**
|
|
4
|
+
* The published control-API double (`@prisma/composer/testing`): the four
|
|
5
|
+
* control operations with their real signatures and Result shapes, backed by
|
|
6
|
+
* fixtures instead of alchemy, containers, or a network.
|
|
7
|
+
*
|
|
8
|
+
* Hosts that mount composer's command family — prisma-cli above all — test
|
|
9
|
+
* against this instead of the real operations, so their suites never spawn a
|
|
10
|
+
* converge and their typecheck never needs the alchemy/effect constellation.
|
|
11
|
+
* The conformance guarantee is carried by the types: `ComposerOperations` is
|
|
12
|
+
* defined as `typeof deployWithDeps` (etc.) of the REAL operations, and the
|
|
13
|
+
* double is declared against it, so a drift in any real signature fails
|
|
14
|
+
* `tsc --noEmit` right here. Every import of implementation modules is
|
|
15
|
+
* type-only and erases
|
|
16
|
+
* at build — the built `testing` chunk must contain no path to the real
|
|
17
|
+
* control implementation, which scripts/check-family-static-graph.mjs proves
|
|
18
|
+
* against the packed tarball.
|
|
19
|
+
*/
|
|
20
|
+
function devSessionDouble(input, endpoints) {
|
|
21
|
+
let resolveClosed;
|
|
22
|
+
const closed = new Promise((resolve) => {
|
|
23
|
+
resolveClosed = resolve;
|
|
24
|
+
});
|
|
25
|
+
let stopped = false;
|
|
26
|
+
input.onEvent?.({
|
|
27
|
+
kind: "ready",
|
|
28
|
+
endpoints
|
|
29
|
+
});
|
|
30
|
+
return {
|
|
31
|
+
endpoints,
|
|
32
|
+
closed,
|
|
33
|
+
stop: async () => {
|
|
34
|
+
if (stopped) return;
|
|
35
|
+
stopped = true;
|
|
36
|
+
input.onEvent?.({ kind: "stopping" });
|
|
37
|
+
input.onEvent?.({ kind: "stopped" });
|
|
38
|
+
resolveClosed();
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
async function* replayLines(lines, address, signal) {
|
|
43
|
+
for (const line of lines) {
|
|
44
|
+
if (signal?.aborted === true) return;
|
|
45
|
+
if (address !== void 0 && line.service !== address) continue;
|
|
46
|
+
yield line;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Runs the caller's converge adapter, when it supplied one, against a
|
|
51
|
+
* synthetic invocation — no alchemy bin is resolved and no real child is
|
|
52
|
+
* started; the adapter decides what the child does.
|
|
53
|
+
*
|
|
54
|
+
* This is what makes a host's tests cover the settlement rules rather than
|
|
55
|
+
* just the grammar: a scripted fake child that exits non-zero, or is killed
|
|
56
|
+
* by a signal, produces the same failure shape the real executor produces, so
|
|
57
|
+
* the handler's settlement — and the engine's own child-status settlement
|
|
58
|
+
* behind it — is genuinely exercised. Returns undefined when no adapter was
|
|
59
|
+
* injected, leaving the fixture result untouched.
|
|
60
|
+
*/
|
|
61
|
+
async function runConverge(action, deps, cwd) {
|
|
62
|
+
if (deps.alchemy === void 0) return void 0;
|
|
63
|
+
const stackFilePath = ".prisma-composer/alchemy.run.ts";
|
|
64
|
+
const reproduceCommand = `alchemy ${action} ${stackFilePath} --yes --stage test`;
|
|
65
|
+
const workingDirectory = cwd ?? ".";
|
|
66
|
+
const outcome = await deps.alchemy({
|
|
67
|
+
action,
|
|
68
|
+
stackFileRelativePath: stackFilePath,
|
|
69
|
+
cwd: workingDirectory,
|
|
70
|
+
stage: "test",
|
|
71
|
+
env: {}
|
|
72
|
+
});
|
|
73
|
+
if (outcome.signal !== null) return notOk(new CliStructuredError("DEPLOY.ENGINE_FAILED", `alchemy ${action} was interrupted by ${outcome.signal}.`, { meta: {
|
|
74
|
+
signal: outcome.signal,
|
|
75
|
+
diagnostics: {
|
|
76
|
+
exitCode: void 0,
|
|
77
|
+
signal: outcome.signal,
|
|
78
|
+
stackFilePath,
|
|
79
|
+
reproduceCommand,
|
|
80
|
+
cwd: workingDirectory
|
|
81
|
+
}
|
|
82
|
+
} }));
|
|
83
|
+
const status = outcome.exitCode ?? 1;
|
|
84
|
+
if (status === 0) return void 0;
|
|
85
|
+
return notOk(new CliStructuredError("DEPLOY.ENGINE_FAILED", `alchemy ${action} exited with status ${status}.`, { meta: {
|
|
86
|
+
exitCode: status,
|
|
87
|
+
diagnostics: {
|
|
88
|
+
exitCode: status,
|
|
89
|
+
stackFilePath,
|
|
90
|
+
reproduceCommand,
|
|
91
|
+
cwd: workingDirectory
|
|
92
|
+
}
|
|
93
|
+
} }));
|
|
94
|
+
}
|
|
95
|
+
function createControlDouble(fixtures = {}) {
|
|
96
|
+
const deployCalls = [];
|
|
97
|
+
const destroyCalls = [];
|
|
98
|
+
const devCalls = [];
|
|
99
|
+
const logCalls = [];
|
|
100
|
+
const deps = {
|
|
101
|
+
deploy: [],
|
|
102
|
+
destroy: [],
|
|
103
|
+
dev: [],
|
|
104
|
+
log: []
|
|
105
|
+
};
|
|
106
|
+
const calls = {
|
|
107
|
+
deploy: deployCalls,
|
|
108
|
+
destroy: destroyCalls,
|
|
109
|
+
dev: devCalls,
|
|
110
|
+
log: logCalls,
|
|
111
|
+
deps
|
|
112
|
+
};
|
|
113
|
+
return {
|
|
114
|
+
operations: {
|
|
115
|
+
deploy: async (input, operationDeps) => {
|
|
116
|
+
calls.deploy.push(input);
|
|
117
|
+
deps.deploy.push(operationDeps);
|
|
118
|
+
const converge = await runConverge("deploy", operationDeps, input.cwd);
|
|
119
|
+
if (converge !== void 0) return converge;
|
|
120
|
+
return fixtures.deploy ?? ok({ summary: void 0 });
|
|
121
|
+
},
|
|
122
|
+
destroy: async (input, operationDeps) => {
|
|
123
|
+
calls.destroy.push(input);
|
|
124
|
+
deps.destroy.push(operationDeps);
|
|
125
|
+
for (const event of fixtures.destroyEvents ?? []) input.onEvent?.(event);
|
|
126
|
+
const converge = await runConverge("destroy", operationDeps, input.cwd);
|
|
127
|
+
if (converge !== void 0) return converge;
|
|
128
|
+
return fixtures.destroy ?? okVoid();
|
|
129
|
+
},
|
|
130
|
+
dev: async (input, operationDeps) => {
|
|
131
|
+
calls.dev.push(input);
|
|
132
|
+
deps.dev.push(operationDeps);
|
|
133
|
+
return fixtures.dev ?? ok(devSessionDouble(input, fixtures.devEndpoints ?? []));
|
|
134
|
+
},
|
|
135
|
+
log: async (input, logDeps) => {
|
|
136
|
+
calls.log.push(input);
|
|
137
|
+
deps.log.push(logDeps);
|
|
138
|
+
return fixtures.log ?? ok({
|
|
139
|
+
appName: fixtures.logAppName ?? "app",
|
|
140
|
+
services: fixtures.logServices ?? [],
|
|
141
|
+
lines: replayLines(fixtures.logLines ?? [], input.address, input.signal)
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
calls
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
//#endregion
|
|
149
|
+
export { createControlDouble };
|
|
150
|
+
|
|
151
|
+
//# sourceMappingURL=testing.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testing.mjs","names":[],"sources":["../../../0-framework/3-tooling/cli/dist/testing.mjs"],"sourcesContent":["import { CliStructuredError } from \"@internal/foundation/errors\";\nimport { notOk, ok, okVoid } from \"@internal/foundation/result\";\n//#region src/testing/control-double.ts\n/**\n* The published control-API double (`@prisma/composer/testing`): the four\n* control operations with their real signatures and Result shapes, backed by\n* fixtures instead of alchemy, containers, or a network.\n*\n* Hosts that mount composer's command family — prisma-cli above all — test\n* against this instead of the real operations, so their suites never spawn a\n* converge and their typecheck never needs the alchemy/effect constellation.\n* The conformance guarantee is carried by the types: `ComposerOperations` is\n* defined as `typeof deployWithDeps` (etc.) of the REAL operations, and the\n* double is declared against it, so a drift in any real signature fails\n* `tsc --noEmit` right here. Every import of implementation modules is\n* type-only and erases\n* at build — the built `testing` chunk must contain no path to the real\n* control implementation, which scripts/check-family-static-graph.mjs proves\n* against the packed tarball.\n*/\nfunction devSessionDouble(input, endpoints) {\n\tlet resolveClosed;\n\tconst closed = new Promise((resolve) => {\n\t\tresolveClosed = resolve;\n\t});\n\tlet stopped = false;\n\tinput.onEvent?.({\n\t\tkind: \"ready\",\n\t\tendpoints\n\t});\n\treturn {\n\t\tendpoints,\n\t\tclosed,\n\t\tstop: async () => {\n\t\t\tif (stopped) return;\n\t\t\tstopped = true;\n\t\t\tinput.onEvent?.({ kind: \"stopping\" });\n\t\t\tinput.onEvent?.({ kind: \"stopped\" });\n\t\t\tresolveClosed();\n\t\t}\n\t};\n}\nasync function* replayLines(lines, address, signal) {\n\tfor (const line of lines) {\n\t\tif (signal?.aborted === true) return;\n\t\tif (address !== void 0 && line.service !== address) continue;\n\t\tyield line;\n\t}\n}\n/**\n* Runs the caller's converge adapter, when it supplied one, against a\n* synthetic invocation — no alchemy bin is resolved and no real child is\n* started; the adapter decides what the child does.\n*\n* This is what makes a host's tests cover the settlement rules rather than\n* just the grammar: a scripted fake child that exits non-zero, or is killed\n* by a signal, produces the same failure shape the real executor produces, so\n* the handler's settlement — and the engine's own child-status settlement\n* behind it — is genuinely exercised. Returns undefined when no adapter was\n* injected, leaving the fixture result untouched.\n*/\nasync function runConverge(action, deps, cwd) {\n\tif (deps.alchemy === void 0) return void 0;\n\tconst stackFilePath = \".prisma-composer/alchemy.run.ts\";\n\tconst reproduceCommand = `alchemy ${action} ${stackFilePath} --yes --stage test`;\n\tconst workingDirectory = cwd ?? \".\";\n\tconst outcome = await deps.alchemy({\n\t\taction,\n\t\tstackFileRelativePath: stackFilePath,\n\t\tcwd: workingDirectory,\n\t\tstage: \"test\",\n\t\tenv: {}\n\t});\n\tif (outcome.signal !== null) return notOk(new CliStructuredError(\"DEPLOY.ENGINE_FAILED\", `alchemy ${action} was interrupted by ${outcome.signal}.`, { meta: {\n\t\tsignal: outcome.signal,\n\t\tdiagnostics: {\n\t\t\texitCode: void 0,\n\t\t\tsignal: outcome.signal,\n\t\t\tstackFilePath,\n\t\t\treproduceCommand,\n\t\t\tcwd: workingDirectory\n\t\t}\n\t} }));\n\tconst status = outcome.exitCode ?? 1;\n\tif (status === 0) return void 0;\n\treturn notOk(new CliStructuredError(\"DEPLOY.ENGINE_FAILED\", `alchemy ${action} exited with status ${status}.`, { meta: {\n\t\texitCode: status,\n\t\tdiagnostics: {\n\t\t\texitCode: status,\n\t\t\tstackFilePath,\n\t\t\treproduceCommand,\n\t\t\tcwd: workingDirectory\n\t\t}\n\t} }));\n}\nfunction createControlDouble(fixtures = {}) {\n\tconst deployCalls = [];\n\tconst destroyCalls = [];\n\tconst devCalls = [];\n\tconst logCalls = [];\n\tconst deps = {\n\t\tdeploy: [],\n\t\tdestroy: [],\n\t\tdev: [],\n\t\tlog: []\n\t};\n\tconst calls = {\n\t\tdeploy: deployCalls,\n\t\tdestroy: destroyCalls,\n\t\tdev: devCalls,\n\t\tlog: logCalls,\n\t\tdeps\n\t};\n\treturn {\n\t\toperations: {\n\t\t\tdeploy: async (input, operationDeps) => {\n\t\t\t\tcalls.deploy.push(input);\n\t\t\t\tdeps.deploy.push(operationDeps);\n\t\t\t\tconst converge = await runConverge(\"deploy\", operationDeps, input.cwd);\n\t\t\t\tif (converge !== void 0) return converge;\n\t\t\t\treturn fixtures.deploy ?? ok({ summary: void 0 });\n\t\t\t},\n\t\t\tdestroy: async (input, operationDeps) => {\n\t\t\t\tcalls.destroy.push(input);\n\t\t\t\tdeps.destroy.push(operationDeps);\n\t\t\t\tfor (const event of fixtures.destroyEvents ?? []) input.onEvent?.(event);\n\t\t\t\tconst converge = await runConverge(\"destroy\", operationDeps, input.cwd);\n\t\t\t\tif (converge !== void 0) return converge;\n\t\t\t\treturn fixtures.destroy ?? okVoid();\n\t\t\t},\n\t\t\tdev: async (input, operationDeps) => {\n\t\t\t\tcalls.dev.push(input);\n\t\t\t\tdeps.dev.push(operationDeps);\n\t\t\t\treturn fixtures.dev ?? ok(devSessionDouble(input, fixtures.devEndpoints ?? []));\n\t\t\t},\n\t\t\tlog: async (input, logDeps) => {\n\t\t\t\tcalls.log.push(input);\n\t\t\t\tdeps.log.push(logDeps);\n\t\t\t\treturn fixtures.log ?? ok({\n\t\t\t\t\tappName: fixtures.logAppName ?? \"app\",\n\t\t\t\t\tservices: fixtures.logServices ?? [],\n\t\t\t\t\tlines: replayLines(fixtures.logLines ?? [], input.address, input.signal)\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t\tcalls\n\t};\n}\n//#endregion\nexport { createControlDouble };\n\n//# sourceMappingURL=testing.mjs.map"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@prisma/composer-cli",
|
|
3
|
+
"version": "0.6.0-dev.21",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Prisma Composer's command family and the `prisma-composer` CLI.",
|
|
6
|
+
"bin": {
|
|
7
|
+
"prisma-composer": "./dist/bin.mjs"
|
|
8
|
+
},
|
|
9
|
+
"exports": {
|
|
10
|
+
"./family": "./dist/family.mjs",
|
|
11
|
+
"./testing": "./dist/testing.mjs",
|
|
12
|
+
"./package.json": "./package.json"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"src"
|
|
17
|
+
],
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@prisma/composer": "0.6.0-dev.21",
|
|
20
|
+
"alchemy": "2.0.0-beta.67",
|
|
21
|
+
"c12": "^3.3.4",
|
|
22
|
+
"effect": "4.0.0-beta.103",
|
|
23
|
+
"esbuild": "^0.28.1"
|
|
24
|
+
},
|
|
25
|
+
"peerDependencies": {
|
|
26
|
+
"@prisma/cli-engine": "0.1.1"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@internal/cli": "0.6.0-dev.21",
|
|
30
|
+
"@internal/tsdown-config": "0.6.0-dev.21",
|
|
31
|
+
"@prisma/cli-engine": "0.1.1",
|
|
32
|
+
"@types/node": "^26.0.1",
|
|
33
|
+
"tsdown": "^0.22.7",
|
|
34
|
+
"typescript": "^6.0.3"
|
|
35
|
+
},
|
|
36
|
+
"license": "Apache-2.0",
|
|
37
|
+
"repository": {
|
|
38
|
+
"type": "git",
|
|
39
|
+
"url": "https://github.com/prisma/composer.git",
|
|
40
|
+
"directory": "packages/9-public/composer-cli"
|
|
41
|
+
},
|
|
42
|
+
"engines": {
|
|
43
|
+
"node": ">=22.18.0"
|
|
44
|
+
},
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public"
|
|
47
|
+
},
|
|
48
|
+
"scripts": {
|
|
49
|
+
"build": "tsdown",
|
|
50
|
+
"clean": "rm -rf dist",
|
|
51
|
+
"typecheck": "tsc --noEmit"
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public surface (the `./family` subpath): composer's engine `CommandFamily`,
|
|
3
|
+
* for hosts that mount composer's commands into their own CLI — the `prisma`
|
|
4
|
+
* bin does exactly this.
|
|
5
|
+
*
|
|
6
|
+
* Kept apart from `@prisma/composer`'s `./control` on purpose. `./control` is
|
|
7
|
+
* the programmatic deploy pipeline; this is the command surface: grammar, help
|
|
8
|
+
* and arg validation belong to the engine, and the handlers behind them are
|
|
9
|
+
* the same operations `./control` exposes.
|
|
10
|
+
*
|
|
11
|
+
* Its static graph is alchemy-free and effect-free, so importing it costs a
|
|
12
|
+
* host nothing until a composer command actually runs.
|
|
13
|
+
*/
|
|
14
|
+
export * from '@internal/cli/family';
|