@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,1294 @@
|
|
|
1
|
+
import { CommandFamily } from "@prisma/cli-engine";
|
|
2
|
+
import * as Layer from "effect/Layer";
|
|
3
|
+
import { Input, StackServices } from "alchemy";
|
|
4
|
+
import * as Effect from "effect/Effect";
|
|
5
|
+
import { State } from "alchemy/State/State";
|
|
6
|
+
//#region ../../0-framework/0-foundation/foundation/dist/errors.d.mts
|
|
7
|
+
//#region src/structured-error.d.ts
|
|
8
|
+
interface StructuredError extends Error {
|
|
9
|
+
readonly code: `${string}.${string}`;
|
|
10
|
+
readonly why?: string;
|
|
11
|
+
readonly fix?: string;
|
|
12
|
+
readonly where?: {
|
|
13
|
+
readonly path?: string;
|
|
14
|
+
readonly line?: number;
|
|
15
|
+
};
|
|
16
|
+
readonly severity?: 'error' | 'warn' | 'info';
|
|
17
|
+
readonly meta?: Record<string, unknown>;
|
|
18
|
+
readonly docsUrl?: string;
|
|
19
|
+
}
|
|
20
|
+
//#endregion
|
|
21
|
+
//#region src/cli-structured-error.d.ts
|
|
22
|
+
/**
|
|
23
|
+
* CLI error envelope for output formatting.
|
|
24
|
+
* This is the serialized form of a CliStructuredError.
|
|
25
|
+
*/
|
|
26
|
+
interface CliErrorEnvelope {
|
|
27
|
+
readonly ok: false;
|
|
28
|
+
readonly code: string;
|
|
29
|
+
readonly severity: 'error' | 'warn' | 'info';
|
|
30
|
+
readonly summary: string;
|
|
31
|
+
readonly why?: string;
|
|
32
|
+
readonly fix?: string;
|
|
33
|
+
readonly where?: {
|
|
34
|
+
readonly path?: string;
|
|
35
|
+
readonly line?: number;
|
|
36
|
+
};
|
|
37
|
+
readonly meta?: Record<string, unknown>;
|
|
38
|
+
readonly docsUrl?: string;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Structured CLI error that contains all information needed for error envelopes.
|
|
42
|
+
* Call sites throw these errors with full context.
|
|
43
|
+
*
|
|
44
|
+
* A `CliStructuredError` is a `StructuredError` (see
|
|
45
|
+
* `./structured-error.ts`): `code` is a dotted
|
|
46
|
+
* `NAMESPACE.SUBCODE` string, and the namespace prefix is the error's
|
|
47
|
+
* category — there is no separate `domain` field. See ADR 239 in
|
|
48
|
+
* prisma/prisma and composer's ADR-0044 for the namespace taxonomy.
|
|
49
|
+
*/
|
|
50
|
+
declare class CliStructuredError extends Error implements StructuredError {
|
|
51
|
+
readonly code: `${string}.${string}`;
|
|
52
|
+
readonly severity: 'error' | 'warn' | 'info';
|
|
53
|
+
readonly why?: string;
|
|
54
|
+
readonly fix?: string;
|
|
55
|
+
readonly where?: {
|
|
56
|
+
readonly path?: string;
|
|
57
|
+
readonly line?: number;
|
|
58
|
+
};
|
|
59
|
+
readonly meta?: Record<string, unknown>;
|
|
60
|
+
readonly docsUrl?: string;
|
|
61
|
+
constructor(code: `${string}.${string}`, summary: string, options?: {
|
|
62
|
+
readonly severity?: 'error' | 'warn' | 'info';
|
|
63
|
+
readonly why?: string;
|
|
64
|
+
readonly fix?: string;
|
|
65
|
+
readonly where?: {
|
|
66
|
+
readonly path?: string;
|
|
67
|
+
readonly line?: number;
|
|
68
|
+
};
|
|
69
|
+
readonly meta?: Record<string, unknown>;
|
|
70
|
+
readonly docsUrl?: string;
|
|
71
|
+
readonly cause?: unknown;
|
|
72
|
+
});
|
|
73
|
+
/**
|
|
74
|
+
* Converts this error to a CLI error envelope for output formatting.
|
|
75
|
+
*/
|
|
76
|
+
toEnvelope(): CliErrorEnvelope;
|
|
77
|
+
/**
|
|
78
|
+
* Type guard to check if an error is a CliStructuredError.
|
|
79
|
+
* Uses duck-typing to work across module boundaries where instanceof may fail.
|
|
80
|
+
*/
|
|
81
|
+
static is(error: unknown): error is CliStructuredError;
|
|
82
|
+
}
|
|
83
|
+
//#endregion
|
|
84
|
+
//#region ../../../node_modules/@standard-schema/spec/dist/index.d.ts
|
|
85
|
+
/** The Standard Typed interface. This is a base type extended by other specs. */
|
|
86
|
+
interface StandardTypedV1<Input = unknown, Output = Input> {
|
|
87
|
+
/** The Standard properties. */
|
|
88
|
+
readonly "~standard": StandardTypedV1.Props<Input, Output>;
|
|
89
|
+
}
|
|
90
|
+
declare namespace StandardTypedV1 {
|
|
91
|
+
/** The Standard Typed properties interface. */
|
|
92
|
+
interface Props<Input = unknown, Output = Input> {
|
|
93
|
+
/** The version number of the standard. */
|
|
94
|
+
readonly version: 1;
|
|
95
|
+
/** The vendor name of the schema library. */
|
|
96
|
+
readonly vendor: string;
|
|
97
|
+
/** Inferred types associated with the schema. */
|
|
98
|
+
readonly types?: Types<Input, Output> | undefined;
|
|
99
|
+
}
|
|
100
|
+
/** The Standard Typed types interface. */
|
|
101
|
+
interface Types<Input = unknown, Output = Input> {
|
|
102
|
+
/** The input type of the schema. */
|
|
103
|
+
readonly input: Input;
|
|
104
|
+
/** The output type of the schema. */
|
|
105
|
+
readonly output: Output;
|
|
106
|
+
}
|
|
107
|
+
/** Infers the input type of a Standard Typed. */
|
|
108
|
+
type InferInput<Schema extends StandardTypedV1> = NonNullable<Schema["~standard"]["types"]>["input"];
|
|
109
|
+
/** Infers the output type of a Standard Typed. */
|
|
110
|
+
type InferOutput<Schema extends StandardTypedV1> = NonNullable<Schema["~standard"]["types"]>["output"];
|
|
111
|
+
}
|
|
112
|
+
/** The Standard Schema interface. */
|
|
113
|
+
interface StandardSchemaV1<Input = unknown, Output = Input> {
|
|
114
|
+
/** The Standard Schema properties. */
|
|
115
|
+
readonly "~standard": StandardSchemaV1.Props<Input, Output>;
|
|
116
|
+
}
|
|
117
|
+
declare namespace StandardSchemaV1 {
|
|
118
|
+
/** The Standard Schema properties interface. */
|
|
119
|
+
interface Props<Input = unknown, Output = Input> extends StandardTypedV1.Props<Input, Output> {
|
|
120
|
+
/** Validates unknown input values. */
|
|
121
|
+
readonly validate: (value: unknown, options?: StandardSchemaV1.Options | undefined) => Result<Output> | Promise<Result<Output>>;
|
|
122
|
+
}
|
|
123
|
+
/** The result interface of the validate function. */
|
|
124
|
+
type Result<Output> = SuccessResult<Output> | FailureResult;
|
|
125
|
+
/** The result interface if validation succeeds. */
|
|
126
|
+
interface SuccessResult<Output> {
|
|
127
|
+
/** The typed output value. */
|
|
128
|
+
readonly value: Output;
|
|
129
|
+
/** A falsy value for `issues` indicates success. */
|
|
130
|
+
readonly issues?: undefined;
|
|
131
|
+
}
|
|
132
|
+
interface Options {
|
|
133
|
+
/** Explicit support for additional vendor-specific parameters, if needed. */
|
|
134
|
+
readonly libraryOptions?: Record<string, unknown> | undefined;
|
|
135
|
+
}
|
|
136
|
+
/** The result interface if validation fails. */
|
|
137
|
+
interface FailureResult {
|
|
138
|
+
/** The issues of failed validation. */
|
|
139
|
+
readonly issues: ReadonlyArray<Issue>;
|
|
140
|
+
}
|
|
141
|
+
/** The issue interface of the failure output. */
|
|
142
|
+
interface Issue {
|
|
143
|
+
/** The error message of the issue. */
|
|
144
|
+
readonly message: string;
|
|
145
|
+
/** The path of the issue, if any. */
|
|
146
|
+
readonly path?: ReadonlyArray<PropertyKey | PathSegment> | undefined;
|
|
147
|
+
}
|
|
148
|
+
/** The path segment interface of the issue. */
|
|
149
|
+
interface PathSegment {
|
|
150
|
+
/** The key representing a path segment. */
|
|
151
|
+
readonly key: PropertyKey;
|
|
152
|
+
}
|
|
153
|
+
/** The Standard types interface. */
|
|
154
|
+
interface Types<Input = unknown, Output = Input> extends StandardTypedV1.Types<Input, Output> {}
|
|
155
|
+
/** Infers the input type of a Standard. */
|
|
156
|
+
type InferInput<Schema extends StandardTypedV1> = StandardTypedV1.InferInput<Schema>;
|
|
157
|
+
/** Infers the output type of a Standard. */
|
|
158
|
+
type InferOutput<Schema extends StandardTypedV1> = StandardTypedV1.InferOutput<Schema>;
|
|
159
|
+
}
|
|
160
|
+
//#endregion
|
|
161
|
+
//#region ../../0-framework/1-core/core/dist/graph-types-N6brq1zY.d.mts
|
|
162
|
+
//#region src/config.d.ts
|
|
163
|
+
/**
|
|
164
|
+
* A declared config param — pure data: a caller-owned Standard Schema
|
|
165
|
+
* (ADR-0018) plus a few framework facets. The framework carries the schema,
|
|
166
|
+
* infers the value type from it, and validates with it, without ever
|
|
167
|
+
* enumerating permitted shapes. Turning a value into stored config and back is
|
|
168
|
+
* the deploy target's job, not the param's (ADR-0019) — the same split RPC
|
|
169
|
+
* uses: schema on the declaration, wire owned by the mover.
|
|
170
|
+
*/
|
|
171
|
+
interface ConfigParam<S extends StandardSchemaV1 = StandardSchemaV1> {
|
|
172
|
+
readonly schema: S;
|
|
173
|
+
readonly optional?: boolean;
|
|
174
|
+
readonly default?: StandardSchemaV1.InferOutput<S>;
|
|
175
|
+
/**
|
|
176
|
+
* A framework-minted value (ADR-0031): core resolves `provision.brand`
|
|
177
|
+
* against the consumer extension's `provisions` registry and mints this
|
|
178
|
+
* param's value per dependency edge. Opaque — core forwards the need and
|
|
179
|
+
* never reads its payload.
|
|
180
|
+
*/
|
|
181
|
+
readonly provision?: ProvisionNeed;
|
|
182
|
+
}
|
|
183
|
+
type Params = Record<string, ConfigParam>;
|
|
184
|
+
/** What implementations receive — undefined only for optional params with no default. */
|
|
185
|
+
type Values<P extends Params> = { readonly [K in keyof P]: P[K]['optional'] extends true ? undefined extends P[K]['default'] ? StandardSchemaV1.InferOutput<P[K]['schema']> | undefined : StandardSchemaV1.InferOutput<P[K]['schema']> : StandardSchemaV1.InferOutput<P[K]['schema']>; };
|
|
186
|
+
/**
|
|
187
|
+
* The connection face of a dependency: declared params (data) and how
|
|
188
|
+
* validated values become a client (the hydrate behavior slot). Both P and C
|
|
189
|
+
* are INFERRED — the declaration types hydrate's input; the factory types the
|
|
190
|
+
* loaded dep.
|
|
191
|
+
*/
|
|
192
|
+
interface Connection<P extends Params = Params, C = unknown> {
|
|
193
|
+
readonly params: P;
|
|
194
|
+
hydrate(values: Values<P>): C | Promise<C>;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* The resolved, typed configuration of one service — what crosses the
|
|
198
|
+
* core→pack boundary. Core builds it at deploy (leaf values are provisioning
|
|
199
|
+
* refs, so the env writes depend on the resources/producer — the ordering
|
|
200
|
+
* edges); the pack serializes it, and at boot reconstructs the identical
|
|
201
|
+
* structure with concrete values. Both forms conform to the shape from
|
|
202
|
+
* configOf. Core never stringifies.
|
|
203
|
+
*/
|
|
204
|
+
interface Config {
|
|
205
|
+
readonly service: Readonly<Record<string, unknown>>;
|
|
206
|
+
readonly inputs: Readonly<Record<string, Readonly<Record<string, unknown>>>>;
|
|
207
|
+
}
|
|
208
|
+
//#endregion
|
|
209
|
+
//#region src/contract.d.ts
|
|
210
|
+
/**
|
|
211
|
+
* A Contract is the declared interface of a service-to-service dependency: a
|
|
212
|
+
* protocol brand (`kind`) plus an opaque comparison type (`Cmp`) the core
|
|
213
|
+
* never inspects. Wiring compatibility is plain TypeScript assignability on
|
|
214
|
+
* `Cmp`, checked at `ModuleBuilder.provision`'s call site (node.ts); `satisfies`
|
|
215
|
+
* is its runtime mirror, called at Load (graph.ts). Correctness comes from
|
|
216
|
+
* the kind's builder shaping `Cmp` so assignability means the right thing —
|
|
217
|
+
* see @prisma/composer/service-rpc's `contract()`/`rpc()`.
|
|
218
|
+
*/
|
|
219
|
+
interface Contract<Kind extends string, Cmp> {
|
|
220
|
+
readonly kind: Kind;
|
|
221
|
+
readonly __cmp: Cmp;
|
|
222
|
+
satisfies(required: Contract<Kind, unknown>): boolean;
|
|
223
|
+
}
|
|
224
|
+
//#endregion
|
|
225
|
+
//#region src/node.d.ts
|
|
226
|
+
declare const NODE: unique symbol;
|
|
227
|
+
declare const SECRET_NEED: unique symbol;
|
|
228
|
+
declare const SECRET_SOURCE: unique symbol;
|
|
229
|
+
/** A declared secret input slot — nameless; the root binds it and the topology forwards it in. */
|
|
230
|
+
interface SecretNeed {
|
|
231
|
+
readonly [SECRET_NEED]: true;
|
|
232
|
+
readonly kind: 'secret';
|
|
233
|
+
}
|
|
234
|
+
/** A module's secret-forwarding slots: name → the need it declares. */
|
|
235
|
+
type Secrets = Record<string, SecretNeed>;
|
|
236
|
+
/** The wiring value bound to a secret slot: a target-defined payload core forwards but never inspects. A target (e.g. @prisma/composer-prisma-cloud's `envSecret`) builds one via `secretSource()`. */
|
|
237
|
+
interface SecretSource<T = unknown> {
|
|
238
|
+
readonly [SECRET_SOURCE]: true;
|
|
239
|
+
/** Target-defined. Core never reads this; the target that authored the source reads it back. */
|
|
240
|
+
readonly payload: T;
|
|
241
|
+
}
|
|
242
|
+
/** What `provision(moduleChild, { secrets })` supplies: one source per declared secret slot. */
|
|
243
|
+
type SecretBindings<S extends Secrets> = { [K in keyof S]: SecretSource; };
|
|
244
|
+
declare const PROVISION_NEED: unique symbol;
|
|
245
|
+
/** A param value the framework mints. Opaque to core: it forwards the payload to the resolved provisioner and never reads it (ADR-0031). */
|
|
246
|
+
interface ProvisionNeed<T = unknown> {
|
|
247
|
+
readonly [PROVISION_NEED]: true;
|
|
248
|
+
/** Selects the provisioner in an extension's `provisions` registry. */
|
|
249
|
+
readonly brand: symbol;
|
|
250
|
+
/** Provisioner-defined; core never reads it. */
|
|
251
|
+
readonly payload: T;
|
|
252
|
+
}
|
|
253
|
+
declare const PARAM_SOURCE: unique symbol;
|
|
254
|
+
declare const PARAM_NEED: unique symbol;
|
|
255
|
+
/** The wiring value bound to a param at provision time: a target-defined payload core forwards but never inspects. A target (e.g. @prisma/composer-prisma-cloud's `envParam`) builds one via `paramSource()`. */
|
|
256
|
+
interface ParamSource<T = unknown> {
|
|
257
|
+
readonly [PARAM_SOURCE]: true;
|
|
258
|
+
/** Target-defined. Core never reads this; the target that authored the source reads it back. */
|
|
259
|
+
readonly payload: T;
|
|
260
|
+
}
|
|
261
|
+
/** A module's declared param-forwarding slot — nameless, schema-less; the root (or an ancestor module) binds a `ParamSource` and the topology forwards it into a child's real, schema-bearing param. */
|
|
262
|
+
interface ParamNeed {
|
|
263
|
+
readonly [PARAM_NEED]: true;
|
|
264
|
+
readonly kind: 'param';
|
|
265
|
+
}
|
|
266
|
+
/** A module's param-forwarding slots: name → the need it declares. */
|
|
267
|
+
type ParamNeeds = Record<string, ParamNeed>;
|
|
268
|
+
/** What `provision(service, { params })` accepts per declared param: a literal (schema-validated when config is built) or an opaque `ParamSource`, taking precedence over `param.default`. Every entry is optional — an unbound param falls back to its `default`. */
|
|
269
|
+
type ParamBindings<P extends Params> = { readonly [K in keyof P]?: StandardSchemaV1.InferOutput<P[K]['schema']> | ParamSource; };
|
|
270
|
+
/** What `provision(moduleChild, { params })` accepts per declared `ParamNeed`: a `ParamSource` only — a need carries no schema to validate a literal against. */
|
|
271
|
+
type ParamNeedBindings<PN extends ParamNeeds> = { readonly [K in keyof PN]?: ParamSource; };
|
|
272
|
+
/**
|
|
273
|
+
* What `provision(service, { input })` accepts (ADR-0042): a plain object
|
|
274
|
+
* mirroring the service's input schema, whose leaves are literals,
|
|
275
|
+
* `envParam(...)` sources, or `envSecret(...)` sources. Deliberately a
|
|
276
|
+
* best-effort structural type: the framework never introspects a Standard
|
|
277
|
+
* Schema, so the binding's exact shape cannot be derived from it — deploy-time
|
|
278
|
+
* validation of the resolved binding is the real check.
|
|
279
|
+
*/
|
|
280
|
+
type InputBinding = string | number | boolean | null | ParamSource | SecretSource | readonly InputBinding[] | {
|
|
281
|
+
readonly [key: string]: InputBinding;
|
|
282
|
+
};
|
|
283
|
+
/** Opaque `Contract<any, any>` bound shared by every node/port type that doesn't care which contract. */
|
|
284
|
+
type AnyContract = Contract<any, any>;
|
|
285
|
+
/** How a service's app becomes a runnable artifact — the build descriptor's routing key (`extension`/`type`) plus paths resolved relative to the authoring module. */
|
|
286
|
+
interface BuildAdapter {
|
|
287
|
+
/** The extension package that provides the build descriptor, e.g. "@prisma/composer/node". */
|
|
288
|
+
readonly extension: string;
|
|
289
|
+
/** The build descriptor's node ID within its extension, e.g. "node" · "nextjs". */
|
|
290
|
+
readonly type: string;
|
|
291
|
+
/** The authoring module's `import.meta.url` — every other path on this descriptor resolves relative to `dirname(module)`. */
|
|
292
|
+
readonly module: string;
|
|
293
|
+
/** The app's built runnable, resolved relative to `dirname(module)` and interpreted by the type's build descriptor (e.g. "node": a server file; "nextjs": located in the standalone tree). */
|
|
294
|
+
readonly entry: string;
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* A Resource's identity: the one place a piece of infrastructure exists.
|
|
298
|
+
* Provisioned by a module, never embedded in a service's deps. `provides`
|
|
299
|
+
* is the Contract the resource offers; `type` is derived from `provides.kind`.
|
|
300
|
+
*/
|
|
301
|
+
interface ResourceNode<C extends AnyContract = AnyContract> {
|
|
302
|
+
readonly [NODE]: true;
|
|
303
|
+
readonly kind: 'resource';
|
|
304
|
+
/** Human-readable, given at authoring — logs/diagnostics only; identity remains the deploy address (ADR-0006). */
|
|
305
|
+
readonly name: string;
|
|
306
|
+
/** The extension package that authored this node, e.g. "@prisma/composer-prisma-cloud" — the registry key at deploy. */
|
|
307
|
+
readonly extension: string;
|
|
308
|
+
readonly type: C['kind'];
|
|
309
|
+
/** The Contract this resource provides — the resource's single port. */
|
|
310
|
+
readonly provides: C;
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* A Service: inputs + its own declared params + how it is built. Inspectable,
|
|
314
|
+
* inert until run, and carries NO runtime behavior — an extension's factory
|
|
315
|
+
* wraps it into a runnable/loadable shape (see RunnableServiceNode).
|
|
316
|
+
*/
|
|
317
|
+
interface ServiceNode<D extends Deps = Deps, P extends Params = Params, E extends Expose = Expose, I extends StandardSchemaV1 | undefined = StandardSchemaV1 | undefined> {
|
|
318
|
+
readonly [NODE]: true;
|
|
319
|
+
readonly kind: 'service';
|
|
320
|
+
/** Human-readable, given at authoring — logs/diagnostics only; identity remains the deploy address (ADR-0006). */
|
|
321
|
+
readonly name: string;
|
|
322
|
+
/** The extension package that authored this node, e.g. "@prisma/composer-prisma-cloud" — the registry key at deploy. */
|
|
323
|
+
readonly extension: string;
|
|
324
|
+
readonly type: string;
|
|
325
|
+
readonly inputs: D;
|
|
326
|
+
/** Extension-reserved config declarations (e.g. compute's `port`) — never user-authored (ADR-0042). */
|
|
327
|
+
readonly params: P;
|
|
328
|
+
/** The service's whole incoming configuration as ONE Standard Schema (authored as `input`, ADR-0042), or `undefined` when it takes none. The framework never introspects it — it only calls `~standard.validate`. Named `inputSchema` on the node so the data field does not collide with the `input()` accessor. */
|
|
329
|
+
readonly inputSchema: I;
|
|
330
|
+
/** How the app's entry is built + assembled. */
|
|
331
|
+
readonly build: BuildAdapter;
|
|
332
|
+
/** Named output ports this service exposes — the Contracts a consumer's `rpc(contract)` can require. `undefined` when the service exposes nothing. */
|
|
333
|
+
readonly expose: E | undefined;
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* A service's dependency slot. At Load the enclosing module wires a
|
|
337
|
+
* producer's ref into it; at run it hydrates a client via Connection. `Req`
|
|
338
|
+
* is the required contract (`unknown` for an untyped end like `http()`).
|
|
339
|
+
*/
|
|
340
|
+
interface DependencyEnd<C = unknown, Req = unknown> {
|
|
341
|
+
readonly [NODE]: true;
|
|
342
|
+
readonly kind: 'dependency';
|
|
343
|
+
/** Human-readable, given at authoring — logs/diagnostics only. */
|
|
344
|
+
readonly name: string;
|
|
345
|
+
readonly type: string;
|
|
346
|
+
readonly connection: Connection<Params, C>;
|
|
347
|
+
/** The required contract, or `undefined` for an untyped end (e.g. `http()`). */
|
|
348
|
+
readonly required: Req | undefined;
|
|
349
|
+
}
|
|
350
|
+
/** A Module: the same Deps/Expose boundary a service has, around transparent wiring instead of a black-box body — its `body` runs at Load, not at authoring. */
|
|
351
|
+
interface ModuleNode<D extends Deps = Deps, E extends Expose = Expose, S extends Secrets = Secrets, PN extends ParamNeeds = ParamNeeds> {
|
|
352
|
+
readonly [NODE]: true;
|
|
353
|
+
readonly kind: 'module';
|
|
354
|
+
/** Human-readable, given at authoring — logs/diagnostics only. */
|
|
355
|
+
readonly name: string;
|
|
356
|
+
readonly deps: D;
|
|
357
|
+
/** Declared secret input slots (authored as `secrets`) — forwarded to internals via `ctx.secrets` (ADR-0029). */
|
|
358
|
+
readonly secretSlots: S;
|
|
359
|
+
/** Declared param-forwarding slots (authored as `params`) — forwarded to internals via `ctx.params`, the same rail secrets ride on. */
|
|
360
|
+
readonly paramSlots: PN;
|
|
361
|
+
readonly expose: E;
|
|
362
|
+
body(ctx: ModuleContext<D, S, PN>): ModuleOutputs<E> | void;
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* What a module's body receives: its declared inputs as forwardable wiring
|
|
366
|
+
* values, plus `provision` to register the owned services/modules it wires them into.
|
|
367
|
+
*/
|
|
368
|
+
interface ModuleContext<D extends Deps, S extends Secrets = Secrets, PN extends ParamNeeds = ParamNeeds> {
|
|
369
|
+
/** The module's declared inputs as wiring values — pass them into provision(). */
|
|
370
|
+
readonly inputs: { [K in keyof D]: InputRef<D[K]>; };
|
|
371
|
+
/** The module's declared secret slots as forwardable sources — pass them into a child's `secrets` (ADR-0029). */
|
|
372
|
+
readonly secrets: { readonly [K in keyof S]: SecretSource; };
|
|
373
|
+
/** The module's declared param-forwarding slots as forwardable sources — pass them into a child's `params`. */
|
|
374
|
+
readonly params: { readonly [K in keyof PN]: ParamSource; };
|
|
375
|
+
/** Registers an owned child (service or module) under a stable id. */
|
|
376
|
+
readonly provision: ModuleBuilder['provision'];
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* A module's forwarded-input value: the same ref-port shape a producer's
|
|
380
|
+
* output carries, so it flows down a nested `provision()` call indistinguishably
|
|
381
|
+
* from a sibling's exposed port.
|
|
382
|
+
*/
|
|
383
|
+
type InputRef<DE> = DE extends DependencyEnd<any, infer Req extends AnyContract> ? RefPort<Req> : never;
|
|
384
|
+
/** One ref-port per declared expose key, contract-checked against `E` (mirrors `Wiring`'s `NoInfer` use). */
|
|
385
|
+
type ModuleOutputs<E extends Expose> = { [P in keyof E]: RefPort<NoInfer<E[P]>>; };
|
|
386
|
+
/**
|
|
387
|
+
* A provisioned producer's port as a wiring-time value: its contract, tagged
|
|
388
|
+
* with which provider produced it (`__providerId`, read by Load to resolve the edge).
|
|
389
|
+
*/
|
|
390
|
+
type RefPort<C extends AnyContract> = C & {
|
|
391
|
+
readonly __providerId: string;
|
|
392
|
+
};
|
|
393
|
+
/**
|
|
394
|
+
* What `provision(id, service)` hands back: a stable id plus one ref-port per
|
|
395
|
+
* exposed contract. `provision(id, resource)` returns the same shape with the
|
|
396
|
+
* resource's one port flattened onto the ref itself.
|
|
397
|
+
*/
|
|
398
|
+
type ProvisionedRef<E extends Expose = Record<never, never>> = {
|
|
399
|
+
readonly id: string;
|
|
400
|
+
} & { readonly [P in keyof E]: RefPort<E[P]>; };
|
|
401
|
+
/** A DependencyEnd's required contract (unknown for an untyped end). */
|
|
402
|
+
type ReqOf<DE> = DE extends DependencyEnd<any, infer Req> ? Req : never;
|
|
403
|
+
/**
|
|
404
|
+
* The producers that satisfy a node's declared dependency slots — one ref per
|
|
405
|
+
* slot, checked against its required contract. A slot also accepts
|
|
406
|
+
* `InputRef<D[K]>` so a module body can forward its own `ctx.inputs` straight
|
|
407
|
+
* into a nested `provision()` call — the same value shape a producer's own
|
|
408
|
+
* exposed port carries.
|
|
409
|
+
*/
|
|
410
|
+
type DepBindings<D extends Deps> = { [K in keyof D]: NoInfer<ReqOf<D[K]>> | InputRef<D[K]>; };
|
|
411
|
+
/**
|
|
412
|
+
* A SERVICE provision's trailing options: an explicit `id` (default: the
|
|
413
|
+
* node's own `name`); `deps` required exactly when the node declares
|
|
414
|
+
* dependency slots (`[keyof D] extends [never]` is the "no slots" test);
|
|
415
|
+
* `input` required exactly when the node declares an input schema (ADR-0042).
|
|
416
|
+
* `params` is always optional — it binds only extension-reserved params (e.g.
|
|
417
|
+
* compute's `port`), which fall back to their own defaults.
|
|
418
|
+
*/
|
|
419
|
+
type ServiceProvisionArgs<D extends Deps, I extends StandardSchemaV1 | undefined, PB> = [keyof D] extends [never] ? I extends undefined ? [opts?: {
|
|
420
|
+
id?: string;
|
|
421
|
+
params?: PB;
|
|
422
|
+
}] : [opts: {
|
|
423
|
+
id?: string;
|
|
424
|
+
input: InputBinding;
|
|
425
|
+
params?: PB;
|
|
426
|
+
}] : I extends undefined ? [opts: {
|
|
427
|
+
id?: string;
|
|
428
|
+
deps: DepBindings<D>;
|
|
429
|
+
params?: PB;
|
|
430
|
+
}] : [opts: {
|
|
431
|
+
id?: string;
|
|
432
|
+
deps: DepBindings<D>;
|
|
433
|
+
input: InputBinding;
|
|
434
|
+
params?: PB;
|
|
435
|
+
}];
|
|
436
|
+
/**
|
|
437
|
+
* A child-MODULE provision's trailing options: `deps`/`secrets` required
|
|
438
|
+
* exactly when the module declares the slots; a declared param-forwarding
|
|
439
|
+
* slot may be bound to a `ParamSource`.
|
|
440
|
+
*/
|
|
441
|
+
type ModuleProvisionArgs<D extends Deps, S extends Secrets, PB> = [keyof D] extends [never] ? [keyof S] extends [never] ? [opts?: {
|
|
442
|
+
id?: string;
|
|
443
|
+
params?: PB;
|
|
444
|
+
}] : [opts: {
|
|
445
|
+
id?: string;
|
|
446
|
+
secrets: SecretBindings<S>;
|
|
447
|
+
params?: PB;
|
|
448
|
+
}] : [keyof S] extends [never] ? [opts: {
|
|
449
|
+
id?: string;
|
|
450
|
+
deps: DepBindings<D>;
|
|
451
|
+
params?: PB;
|
|
452
|
+
}] : [opts: {
|
|
453
|
+
id?: string;
|
|
454
|
+
deps: DepBindings<D>;
|
|
455
|
+
secrets: SecretBindings<S>;
|
|
456
|
+
params?: PB;
|
|
457
|
+
}];
|
|
458
|
+
interface ModuleBuilder {
|
|
459
|
+
/** Provisions an owned resource; its id defaults to the node's `name`. */
|
|
460
|
+
provision<C extends AnyContract>(resource: ResourceNode<C>, opts?: {
|
|
461
|
+
id?: string;
|
|
462
|
+
}): {
|
|
463
|
+
readonly id: string;
|
|
464
|
+
} & RefPort<C>;
|
|
465
|
+
/** Registers an owned service; its id defaults to the node's `name`; `deps`/`input` are required iff it declares them; a reserved param may be bound (literal or `ParamSource`), overriding its default. */
|
|
466
|
+
provision<D extends Deps, P extends Params, E extends Expose, I extends StandardSchemaV1 | undefined>(service: ServiceNode<D, P, E, I>, ...args: ServiceProvisionArgs<D, I, ParamBindings<P>>): ProvisionedRef<E>;
|
|
467
|
+
/**
|
|
468
|
+
* The service call with `deps`/`input` spelled out. `ServiceProvisionArgs`
|
|
469
|
+
* above cannot resolve while `D`/`I` are still unbound type parameters — a
|
|
470
|
+
* generic wrapper like `cron()` provisioning a caller-supplied service — so
|
|
471
|
+
* that call site resolves to this concrete overload instead.
|
|
472
|
+
*/
|
|
473
|
+
provision<D extends Deps, P extends Params, E extends Expose, I extends StandardSchemaV1 | undefined>(service: ServiceNode<D, P, E, I>, opts: {
|
|
474
|
+
id?: string;
|
|
475
|
+
deps: DepBindings<D>;
|
|
476
|
+
input?: InputBinding;
|
|
477
|
+
params?: ParamBindings<P>;
|
|
478
|
+
}): ProvisionedRef<E>;
|
|
479
|
+
/** Registers an owned child module; its id defaults to the node's `name`; `deps`/`secrets` are required iff it declares them; a declared param-forwarding slot may be bound to a `ParamSource`. */
|
|
480
|
+
provision<D extends Deps, E extends Expose, S extends Secrets, PN extends ParamNeeds>(child: ModuleNode<D, E, S, PN>, ...args: ModuleProvisionArgs<D, S, ParamNeedBindings<PN>>): ProvisionedRef<E>;
|
|
481
|
+
/** The child-module call with `deps`/`secrets` spelled out — the same generic-wrapper escape as the service overload above. */
|
|
482
|
+
provision<D extends Deps, E extends Expose, S extends Secrets, PN extends ParamNeeds>(child: ModuleNode<D, E, S, PN>, opts: {
|
|
483
|
+
id?: string;
|
|
484
|
+
deps: DepBindings<D>;
|
|
485
|
+
secrets?: SecretBindings<S>;
|
|
486
|
+
params?: ParamNeedBindings<PN>;
|
|
487
|
+
}): ProvisionedRef<E>;
|
|
488
|
+
}
|
|
489
|
+
/** Dependency map: name → the slot the service declares. Only declarations are admitted, never a concrete ResourceNode. */
|
|
490
|
+
type Deps = Record<string, DependencyEnd<any, any>>;
|
|
491
|
+
/** Output-port map: name → the Contract a service exposes for others to depend on. */
|
|
492
|
+
type Expose = Readonly<Record<string, AnyContract>>;
|
|
493
|
+
//#endregion
|
|
494
|
+
//#region src/graph-types.d.ts
|
|
495
|
+
/** Path-derived: root-scope children are bare ids ("auth", "db"); a nested module's own children dot-join under its address ("auth.db"). */
|
|
496
|
+
type NodeId = string;
|
|
497
|
+
interface GraphNode {
|
|
498
|
+
readonly id: NodeId;
|
|
499
|
+
readonly node: ServiceNode | ResourceNode | DependencyEnd | ModuleNode;
|
|
500
|
+
}
|
|
501
|
+
/**
|
|
502
|
+
* `input`: a service consumes its own declared dependency slot — from the
|
|
503
|
+
* slot node to the service. `dependency`: a service consumes a provisioned
|
|
504
|
+
* producer (a service or a resource — the one wiring mechanism) — from the
|
|
505
|
+
* producer to the consumer, labeled with the consumer's input name (from the
|
|
506
|
+
* module wiring).
|
|
507
|
+
*/
|
|
508
|
+
interface Edge {
|
|
509
|
+
readonly from: NodeId;
|
|
510
|
+
readonly to: NodeId;
|
|
511
|
+
readonly input: string;
|
|
512
|
+
readonly kind: 'input' | 'dependency';
|
|
513
|
+
}
|
|
514
|
+
/**
|
|
515
|
+
* A service's provision-time input binding (ADR-0042): the plain object a
|
|
516
|
+
* `provision(service, { input })` call supplied, recorded at that service's
|
|
517
|
+
* address. Core never walks it beyond usage tracking; the deploy target's
|
|
518
|
+
* recursive descent classifies its leaves (literals, `envParam`, `envSecret`).
|
|
519
|
+
*/
|
|
520
|
+
interface ServiceInputBinding {
|
|
521
|
+
/** The graph address of the service that declares the input schema. */
|
|
522
|
+
readonly serviceAddress: NodeId;
|
|
523
|
+
/** The binding object supplied at provision. */
|
|
524
|
+
readonly binding: InputBinding;
|
|
525
|
+
}
|
|
526
|
+
/**
|
|
527
|
+
* A resolved param binding: a `provision()` call bound a service's param
|
|
528
|
+
* slot to either a literal value or an opaque `ParamSource` — the non-secret
|
|
529
|
+
* sibling of `SecretBinding`. Unlike a secret, a param binding is not
|
|
530
|
+
* required for every declared param (a param may fall back to its own
|
|
531
|
+
* `default`), so this list only carries the ones a `provision()` call
|
|
532
|
+
* actually bound.
|
|
533
|
+
*/
|
|
534
|
+
interface ParamBinding {
|
|
535
|
+
/** The graph address of the service that declares the param. */
|
|
536
|
+
readonly serviceAddress: NodeId;
|
|
537
|
+
/** The param name on that service. */
|
|
538
|
+
readonly slot: string;
|
|
539
|
+
/** A literal value (schema-validated by `buildConfig`) or an opaque `ParamSource` (the deploy target reads its own payload back) — check with `isParamSource`. Core never inspects a `ParamSource`'s payload. */
|
|
540
|
+
readonly binding: unknown;
|
|
541
|
+
}
|
|
542
|
+
interface Graph {
|
|
543
|
+
readonly root: GraphNode;
|
|
544
|
+
/** Root + one per input, topo-ordered (deps first). */
|
|
545
|
+
readonly nodes: readonly GraphNode[];
|
|
546
|
+
readonly edges: readonly Edge[];
|
|
547
|
+
/** Every service input binding a `provision()` call supplied (ADR-0042). */
|
|
548
|
+
readonly inputBindings: readonly ServiceInputBinding[];
|
|
549
|
+
/** Every service param bound at provision — literal or source; unbound params are absent here and fall back to their `default` (see `buildConfig`). */
|
|
550
|
+
readonly params: readonly ParamBinding[];
|
|
551
|
+
}
|
|
552
|
+
//#endregion
|
|
553
|
+
//#region ../../0-framework/3-tooling/cli/dist/load-entry-yXw6cagY.d.mts
|
|
554
|
+
/**
|
|
555
|
+
* WHAT to converge. Deliberately not a command line: which alchemy binary to
|
|
556
|
+
* run is a question about this machine's installed tree, and answering it
|
|
557
|
+
* eagerly would make an injected adapter — a test's fake child — fail in a
|
|
558
|
+
* directory that has no alchemy installed, before the fake ever ran. The
|
|
559
|
+
* adapter resolves the binary, because the adapter is what starts a child.
|
|
560
|
+
*
|
|
561
|
+
* `env` carries only the ADDITIONS to the invoking environment — the container
|
|
562
|
+
* transport vars and the result-file pointer — never a whole environment: the
|
|
563
|
+
* engine merges additions over the invocation environment and applies its own
|
|
564
|
+
* credential vars last.
|
|
565
|
+
*/
|
|
566
|
+
interface AlchemyInvocation {
|
|
567
|
+
readonly action: 'deploy' | 'destroy';
|
|
568
|
+
readonly stackFileRelativePath: string;
|
|
569
|
+
readonly cwd: string;
|
|
570
|
+
readonly stage: string;
|
|
571
|
+
readonly env: Readonly<Record<string, string | undefined>>;
|
|
572
|
+
}
|
|
573
|
+
/**
|
|
574
|
+
* How the converge child ended, verbatim. A signal-killed child carries
|
|
575
|
+
* `signal` and a null `exitCode`; callers branch on `signal` first, because a
|
|
576
|
+
* signal-killed child is an abort, not a failure. Structurally the engine's
|
|
577
|
+
* `ChildResult`, declared here so the control surface does not depend on the
|
|
578
|
+
* engine.
|
|
579
|
+
*/
|
|
580
|
+
interface AlchemyOutcome {
|
|
581
|
+
readonly exitCode: number | null;
|
|
582
|
+
readonly signal: string | null;
|
|
583
|
+
}
|
|
584
|
+
/** Starts the converge and resolves when it ends. The CLI supplies one backed
|
|
585
|
+
* by `ctx.spawn`; hosts get `spawnAlchemy`. */
|
|
586
|
+
type RunAlchemy = (invocation: AlchemyInvocation) => Promise<AlchemyOutcome>;
|
|
587
|
+
//#endregion
|
|
588
|
+
//#region ../../0-framework/0-foundation/foundation/dist/result.d.mts
|
|
589
|
+
//#region src/result.d.ts
|
|
590
|
+
/**
|
|
591
|
+
* Represents a successful result containing a value.
|
|
592
|
+
*/
|
|
593
|
+
interface Ok<T> {
|
|
594
|
+
readonly ok: true;
|
|
595
|
+
readonly value: T;
|
|
596
|
+
assertOk(): T;
|
|
597
|
+
assertNotOk(): never;
|
|
598
|
+
}
|
|
599
|
+
/**
|
|
600
|
+
* Represents an unsuccessful result containing failure details.
|
|
601
|
+
*/
|
|
602
|
+
interface NotOk<F> {
|
|
603
|
+
readonly ok: false;
|
|
604
|
+
readonly failure: F;
|
|
605
|
+
assertOk(): never;
|
|
606
|
+
assertNotOk(): F;
|
|
607
|
+
}
|
|
608
|
+
/**
|
|
609
|
+
* A discriminated union representing either success (Ok) or failure (NotOk).
|
|
610
|
+
*
|
|
611
|
+
* @typeParam T - The success value type
|
|
612
|
+
* @typeParam F - The failure details type
|
|
613
|
+
*/
|
|
614
|
+
type Result$1<T, F> = Ok<T> | NotOk<F>;
|
|
615
|
+
//#endregion
|
|
616
|
+
//#region ../../0-framework/1-core/core/dist/app-config-aIrriqVU.d.mts
|
|
617
|
+
//#region src/container-transport.d.ts
|
|
618
|
+
/**
|
|
619
|
+
* Carries resolved containers from the CLI process into the alchemy process
|
|
620
|
+
* (ADR-0037). A deploy runs as two processes: the CLI resolves each
|
|
621
|
+
* extension's containers, then spawns `alchemy`, which re-imports the config
|
|
622
|
+
* from scratch and needs those containers back — and env vars are the only
|
|
623
|
+
* channel between the two. So the CLI writes each instance's `serialize()`
|
|
624
|
+
* output into one env var per extension, and in the alchemy process
|
|
625
|
+
* `deserializeContainers` reads each var back through the same extension's
|
|
626
|
+
* descriptor. The framework owns the vars; it never reads their contents.
|
|
627
|
+
*/
|
|
628
|
+
/** The key an extension resolves a container from: which app, which stage. */
|
|
629
|
+
interface LocateContainerInput {
|
|
630
|
+
/** The application name (root node's name, or `--name`). */
|
|
631
|
+
readonly appName: string;
|
|
632
|
+
/** The USER-FACING stage name — `--stage <name>` as the user typed it (git-ref validated), or `undefined` for the default (production) stage. Alchemy's stage is the container's `alchemyStage` when supplied, with this value as the explicit-user-stage fallback; when neither exists, the CLI fails before Alchemy runs. */
|
|
633
|
+
readonly stage: string | undefined;
|
|
634
|
+
}
|
|
635
|
+
/**
|
|
636
|
+
* One resolved container. The framework sees only this interface; the
|
|
637
|
+
* extension that produced the instance narrows it back to its own concrete
|
|
638
|
+
* type wherever the framework hands it back (ADR-0037).
|
|
639
|
+
*/
|
|
640
|
+
interface ContainerInstance {
|
|
641
|
+
readonly input: LocateContainerInput;
|
|
642
|
+
/** The exact string the CLI hands `alchemy` as its stage — the deploy-state scope. Distinct from `input.stage`, the user-facing name: for Prisma Cloud this is the resolved Branch id (stable across renames, machine-independent). Framework-visible like `input` — NOT part of the `serialize()` payload, which stays extension-owned. */
|
|
643
|
+
readonly alchemyStage?: string | undefined;
|
|
644
|
+
/** Serialize to a non-empty string for the process transport above. The format is the extension's own; only its `deserialize` reads it. */
|
|
645
|
+
serialize(): string;
|
|
646
|
+
}
|
|
647
|
+
/**
|
|
648
|
+
* What the caller has already authenticated, handed to one container
|
|
649
|
+
* lifecycle call. A caller that holds neither omits the argument, and the
|
|
650
|
+
* extension falls back to whatever credential protocol it defines for
|
|
651
|
+
* itself (for Prisma Cloud, its env vars — which is how the alchemy child
|
|
652
|
+
* process still resolves containers).
|
|
653
|
+
*
|
|
654
|
+
* `C` is the extension's own platform-client type, left as a type parameter
|
|
655
|
+
* because this shared-plane module must not import a platform SDK; the
|
|
656
|
+
* framework only carries the value, never calls it. The framework stores the
|
|
657
|
+
* erased `C = unknown` form and the extension recovers its concrete client
|
|
658
|
+
* through the same method bivariance that erases `I` below.
|
|
659
|
+
*/
|
|
660
|
+
interface ContainerCredentials<C = unknown> {
|
|
661
|
+
/** The workspace the container lives in. `undefined` when the caller has no workspace to name — the extension decides whether it can proceed. */
|
|
662
|
+
readonly workspaceId: string | undefined;
|
|
663
|
+
/** An already-authenticated platform API client. Present means the extension must not build its own from the environment. */
|
|
664
|
+
readonly client?: C | undefined;
|
|
665
|
+
}
|
|
666
|
+
/**
|
|
667
|
+
* The platform containers an app deploys into, as one lifecycle. `I` is
|
|
668
|
+
* the extension's own instance type — the same descriptor produces and
|
|
669
|
+
* consumes it, so the extension gets full typing internally while the
|
|
670
|
+
* framework stores the erased form; `C` erases the same way. METHOD SYNTAX
|
|
671
|
+
* REQUIRED on all four members: the erased assignment into
|
|
672
|
+
* ExtensionDescriptor compiles only through method bivariance;
|
|
673
|
+
* property-arrow members are checked contravariantly and the assignment
|
|
674
|
+
* fails (same rule as ServiceLowering<P, S> — ADR-0033).
|
|
675
|
+
*/
|
|
676
|
+
interface ContainerDescriptor<I extends ContainerInstance = ContainerInstance, C = unknown> {
|
|
677
|
+
/** Resolve the container for (appName, stage), creating anything absent. Called by `deploy`. */
|
|
678
|
+
ensure(input: LocateContainerInput, credentials?: ContainerCredentials<C>): Promise<I>;
|
|
679
|
+
/** Find the container for (appName, stage); `undefined` when nothing exists. Called by `destroy` — never creates. */
|
|
680
|
+
locate(input: LocateContainerInput, credentials?: ContainerCredentials<C>): Promise<I | undefined>;
|
|
681
|
+
/** Remove the container after a successful destroy, after every extension's `teardown` has run. Failure policy is the extension's. */
|
|
682
|
+
remove(instance: I, credentials?: ContainerCredentials<C>): Promise<void>;
|
|
683
|
+
/** Reconstruct an instance from its own `serialize()` output — the far end of the framework's parent→child transport. */
|
|
684
|
+
deserialize(serialized: string): I;
|
|
685
|
+
}
|
|
686
|
+
//#endregion
|
|
687
|
+
//#region src/control/deploy.d.ts
|
|
688
|
+
/** The Layer shape every Alchemy state store must satisfy — what `LowerOptions.state` and `PrismaAppConfig.state` both traffic in. */
|
|
689
|
+
type AlchemyStateLayer = Layer.Layer<State, never, StackServices>;
|
|
690
|
+
/**
|
|
691
|
+
* An extension's application-level descriptor: shared infrastructure that runs
|
|
692
|
+
* once per lowering, before any node. Its outputs reach the extension's own
|
|
693
|
+
* SPI calls via LowerContext.application.
|
|
694
|
+
*/
|
|
695
|
+
interface ApplicationDescriptor {
|
|
696
|
+
provision(ctx: LowerContext): Effect.Effect<unknown, unknown, unknown>;
|
|
697
|
+
}
|
|
698
|
+
/**
|
|
699
|
+
* One provisioned param need, resolved against the CONSUMER extension's
|
|
700
|
+
* `provisions` registry (ADR-0031). `edgeId` — `${consumerAddress}.${input}`
|
|
701
|
+
* — is the mint's stable resource key, so a provisioner's own resource ids
|
|
702
|
+
* derive from it and stay stable across redeploys.
|
|
703
|
+
*/
|
|
704
|
+
interface ProvisionEdge {
|
|
705
|
+
readonly edgeId: string;
|
|
706
|
+
readonly consumerAddress: string;
|
|
707
|
+
readonly providerAddress: string;
|
|
708
|
+
readonly input: string;
|
|
709
|
+
/** Opaque; forwarded from the param's declared need. Core never reads its payload. */
|
|
710
|
+
readonly need: ProvisionNeed;
|
|
711
|
+
}
|
|
712
|
+
/** One extension-registered provisioner, keyed by a need's brand (ADR-0031). */
|
|
713
|
+
interface ProvisionerDescriptor {
|
|
714
|
+
/** Mints one stable value for one provisioned edge; yields the platform resource, returns an opaque ref core forwards into config. */
|
|
715
|
+
provision(edge: ProvisionEdge): Effect.Effect<unknown, unknown, unknown>;
|
|
716
|
+
}
|
|
717
|
+
/**
|
|
718
|
+
* The phased service SPI. `P` and `S` are the descriptor's OWN intra-node
|
|
719
|
+
* handoff types — provision's product consumed by serialize/deploy, and
|
|
720
|
+
* serialize's product consumed by deploy. Core threads them through without
|
|
721
|
+
* inspection; only the descriptor that writes them reads them.
|
|
722
|
+
*
|
|
723
|
+
* Method syntax (not property-arrow) is required: the heterogeneous
|
|
724
|
+
* descriptor registry (`NodeDescriptor`) assigns concrete descriptors to
|
|
725
|
+
* this interface's `unknown` defaults through TypeScript's method
|
|
726
|
+
* bivariance — a property-arrow form is checked contravariantly and breaks
|
|
727
|
+
* that assignment.
|
|
728
|
+
*/
|
|
729
|
+
interface ServiceLowering<P = unknown, S = unknown> {
|
|
730
|
+
/** Makes the platform-specific thing that will host the service — identity-bearing infrastructure only, no code runs. */
|
|
731
|
+
provision(ctx: LowerContext): Effect.Effect<P, unknown, unknown>;
|
|
732
|
+
/**
|
|
733
|
+
* Encodes the typed Config into the service's runtime environment. Boot-side
|
|
734
|
+
* deserialize reverses it through the same serializer. Returns the env-var
|
|
735
|
+
* records so `deploy` can reference them.
|
|
736
|
+
*/
|
|
737
|
+
serialize(ctx: LowerContext, provisioned: P, config: Config): Effect.Effect<S, unknown, unknown>;
|
|
738
|
+
/**
|
|
739
|
+
* Prints the bootstrap and assembles the deployable artifact from the
|
|
740
|
+
* app-built bundle. Must be byte-deterministic: an unchanged service noops
|
|
741
|
+
* on redeploy.
|
|
742
|
+
*/
|
|
743
|
+
package(ctx: LowerContext, input: PackageInput): Effect.Effect<Artifact, unknown, unknown>;
|
|
744
|
+
/** Ships the packaged artifact into the provisioned thing and runs it. Returns the node's outputs for dependents, plus the entities it became on the deployment target. */
|
|
745
|
+
deploy(ctx: LowerContext, provisioned: P, artifact: Artifact, serialized: S): Effect.Effect<LoweredResult, unknown, unknown>;
|
|
746
|
+
}
|
|
747
|
+
/** Input to an extension's package() step: the built bundle and the node's graph address. */
|
|
748
|
+
interface PackageInput {
|
|
749
|
+
/** The build descriptor's normalized output: the bundle dir + the app's runnable. */
|
|
750
|
+
readonly assembled: Bundle;
|
|
751
|
+
/** The node's graph address — baked into the printed bootstrap. */
|
|
752
|
+
readonly address: string;
|
|
753
|
+
}
|
|
754
|
+
/** One node's realization. Runs inside the Alchemy stack effect. */
|
|
755
|
+
type Lowering = (ctx: LowerContext) => Effect.Effect<LoweredResult, unknown, unknown>;
|
|
756
|
+
interface LowerContext {
|
|
757
|
+
readonly id: NodeId;
|
|
758
|
+
/**
|
|
759
|
+
* The node's deployment address: its full, dot-joined hierarchical
|
|
760
|
+
* position in the graph (e.g. "auth.api"). The config-key namespace and
|
|
761
|
+
* the bootstrap parameter.
|
|
762
|
+
*/
|
|
763
|
+
readonly address: string;
|
|
764
|
+
readonly node: ServiceNode | ResourceNode;
|
|
765
|
+
readonly graph: Graph;
|
|
766
|
+
readonly opts: LowerOptions;
|
|
767
|
+
/**
|
|
768
|
+
* The owning extension's application hook product; `undefined` when the
|
|
769
|
+
* extension declares no hook. Core never reads it; the extension narrows
|
|
770
|
+
* it with its own type guard.
|
|
771
|
+
*/
|
|
772
|
+
readonly application: unknown;
|
|
773
|
+
/**
|
|
774
|
+
* The owning extension's resolved container, deserialized from the
|
|
775
|
+
* framework transport; core never reads it — the extension narrows it
|
|
776
|
+
* with its own type guard. `undefined` when the extension declares no
|
|
777
|
+
* container descriptor.
|
|
778
|
+
*/
|
|
779
|
+
readonly container: ContainerInstance | undefined;
|
|
780
|
+
/** Already-lowered deps (topo order). */
|
|
781
|
+
readonly lowered: ReadonlyMap<NodeId, Outputs>;
|
|
782
|
+
/** Every provisioned param value minted this lowering, keyed by edge id (ADR-0031). */
|
|
783
|
+
readonly provisioned: ReadonlyMap<string, unknown>;
|
|
784
|
+
}
|
|
785
|
+
/**
|
|
786
|
+
* The values a node provides to its dependents — what a consumer's declared
|
|
787
|
+
* connection params resolve against (buildConfig reads them by param name).
|
|
788
|
+
* Name-keyed and unknown-valued of necessity: core cannot know extension
|
|
789
|
+
* types, and which producer feeds which consumer is decided by the user's
|
|
790
|
+
* graph at runtime. The connection declaration is the contract.
|
|
791
|
+
*/
|
|
792
|
+
type Outputs = Readonly<Record<string, unknown>>;
|
|
793
|
+
/**
|
|
794
|
+
* One thing a node became on the deployment target, RESOLVED — what the report
|
|
795
|
+
* consumer sees. The descriptor names it; core never infers meaning from it.
|
|
796
|
+
* `url` is present ONLY when the descriptor declares the address publicly
|
|
797
|
+
* reachable — a connection string is never a `url`.
|
|
798
|
+
*
|
|
799
|
+
* A descriptor constructing one holds `svc.id` / `deployment.deployedUrl` —
|
|
800
|
+
* `Output<T>` references, not values, because the stack effect runs before
|
|
801
|
+
* Alchemy applies anything. So construction sites traffic in
|
|
802
|
+
* `Input<DeployedEntity>` (Alchemy's own idiom for "this shape, fields possibly
|
|
803
|
+
* unresolved"); apply resolves it before any reader sees it.
|
|
804
|
+
*/
|
|
805
|
+
interface DeployedEntity {
|
|
806
|
+
readonly kind: string;
|
|
807
|
+
readonly id: string;
|
|
808
|
+
readonly url?: string;
|
|
809
|
+
readonly details?: Readonly<Record<string, string>>;
|
|
810
|
+
}
|
|
811
|
+
/**
|
|
812
|
+
* What a node's final lowering phase produces: outputs for dependents,
|
|
813
|
+
* entities for reporting.
|
|
814
|
+
*
|
|
815
|
+
* `entities` is REQUIRED, not optional. "This node became nothing reportable
|
|
816
|
+
* on the deployment target" is a claim, and an optional field lets a
|
|
817
|
+
* descriptor make it by saying nothing at all — no error, no type complaint,
|
|
818
|
+
* no failing test. That is the shared bag's sin in miniature (ADR-0033): a
|
|
819
|
+
* claim made anonymously, with nothing recording that a claim was made. `[]`
|
|
820
|
+
* costs one token and puts the assertion on the record where a reviewer can
|
|
821
|
+
* see it.
|
|
822
|
+
*/
|
|
823
|
+
interface LoweredResult {
|
|
824
|
+
readonly outputs: Outputs;
|
|
825
|
+
readonly entities: readonly Input<DeployedEntity>[];
|
|
826
|
+
}
|
|
827
|
+
/** What one graph node became — in-process only (it holds the node itself, so it never crosses the stack boundary). */
|
|
828
|
+
interface DeployedNode {
|
|
829
|
+
readonly address: string;
|
|
830
|
+
readonly node: ServiceNode | ResourceNode;
|
|
831
|
+
readonly entities: readonly DeployedEntity[];
|
|
832
|
+
}
|
|
833
|
+
/** The result of the Deploy operation: the app and every node it deployed, in topo order. */
|
|
834
|
+
interface DeploymentResult {
|
|
835
|
+
readonly app: string;
|
|
836
|
+
readonly nodes: readonly DeployedNode[];
|
|
837
|
+
}
|
|
838
|
+
interface LowerOptions {
|
|
839
|
+
/** Stack + root node id. */
|
|
840
|
+
readonly name: string;
|
|
841
|
+
readonly bundles: Record<string, Bundle>;
|
|
842
|
+
readonly stage?: string;
|
|
843
|
+
/** Alchemy state store for the stack. Defaults to the config's own state layer. */
|
|
844
|
+
readonly state?: AlchemyStateLayer;
|
|
845
|
+
/** Explicit provider set for the stack. Defaults to the config's own merged `providers()` (`mergedProviders`) — the same override precedence as `state`. The dev stack module passes `localTargetProviders(...)` here (ADR-0041); `lower()` itself learns nothing about the local target. */
|
|
846
|
+
readonly providers?: Layer.Layer<never>;
|
|
847
|
+
/**
|
|
848
|
+
* Invoked once per deploy, during apply, with the Deploy operation's result
|
|
849
|
+
* — the app and every node it deployed, resolved, in topo order.
|
|
850
|
+
* Presentation belongs to the caller (the CLI wires its renderer here);
|
|
851
|
+
* core never formats. Absent means no report is assembled and no Action is
|
|
852
|
+
* declared at all.
|
|
853
|
+
*/
|
|
854
|
+
readonly report?: (result: DeploymentResult) => void;
|
|
855
|
+
}
|
|
856
|
+
/** A build descriptor's normalized output: the produced bundle dir plus the app's runnable entry within it. */
|
|
857
|
+
interface Bundle {
|
|
858
|
+
readonly dir: string;
|
|
859
|
+
readonly entry: string;
|
|
860
|
+
/**
|
|
861
|
+
* Absolute paths to the USER-BUILT inputs this bundle was assembled from
|
|
862
|
+
* (ADR-0041). `prisma-composer dev`'s watch loop watches exactly these — a
|
|
863
|
+
* file entry as a file, a directory entry recursively — and re-runs
|
|
864
|
+
* assemble on a change. Optional so a build adapter that predates this
|
|
865
|
+
* field still compiles; a bundle without it is simply not watched.
|
|
866
|
+
*/
|
|
867
|
+
readonly watch?: readonly string[];
|
|
868
|
+
}
|
|
869
|
+
/** Shared input shape for every extension's build descriptor. */
|
|
870
|
+
interface AssembleInput {
|
|
871
|
+
readonly build: BuildAdapter;
|
|
872
|
+
/** The service's graph address (e.g. "storefront.web"). Unique per service, so the assembler uses it to name this service's own working directory: `<cwd>/.prisma-composer/artifacts/<address>/`. */
|
|
873
|
+
readonly address: string;
|
|
874
|
+
/** The directory the deploy command was run from. The assembler puts its working directory under it (`<cwd>/.prisma-composer/`), the same place the CLI writes its other generated files. */
|
|
875
|
+
readonly cwd: string;
|
|
876
|
+
}
|
|
877
|
+
/** package()'s product. */
|
|
878
|
+
interface Artifact {
|
|
879
|
+
readonly path: string;
|
|
880
|
+
readonly sha256: string;
|
|
881
|
+
}
|
|
882
|
+
//#endregion
|
|
883
|
+
//#region src/control/app-config.d.ts
|
|
884
|
+
/**
|
|
885
|
+
* One extension's control-plane registry: everything the deploy pipeline may
|
|
886
|
+
* look up for a node whose `extension` field names this package. `nodes` is
|
|
887
|
+
* keyed by the node's within-extension ID (`node.type` / `build.type`).
|
|
888
|
+
*/
|
|
889
|
+
interface ExtensionDescriptor {
|
|
890
|
+
/** The extension's package name, e.g. "@prisma/composer-prisma-cloud" — what a node's `extension` field is matched against. */
|
|
891
|
+
readonly id: string;
|
|
892
|
+
/** ONE registry per extension, keyed by node ID. */
|
|
893
|
+
readonly nodes: Record<string, NodeDescriptor>;
|
|
894
|
+
/** Param provisioners this extension supplies, keyed by need brand (ADR-0031). Core resolves a param's ProvisionNeed against the CONSUMER extension's map. */
|
|
895
|
+
readonly provisions?: ReadonlyMap<symbol, ProvisionerDescriptor>;
|
|
896
|
+
/** Once-per-lowering hook — the application's shared infrastructure (e.g. prisma-cloud's Project). */
|
|
897
|
+
readonly application?: ApplicationDescriptor;
|
|
898
|
+
/** The extension's Alchemy providers — merged across all configured extensions (config order). */
|
|
899
|
+
readonly providers?: () => Layer.Layer<never>;
|
|
900
|
+
/**
|
|
901
|
+
* Deploy-time prerequisite check — the CLI runs it once, after the app's
|
|
902
|
+
* Project/Branch are resolved and BEFORE any stack file is written or Alchemy
|
|
903
|
+
* runs. A target uses it to verify platform prerequisites (e.g. that every
|
|
904
|
+
* secret env var in the provision manifest exists for the resolved stage) and
|
|
905
|
+
* throws to abort the deploy. Async: it talks to the platform (ADR-0029).
|
|
906
|
+
*
|
|
907
|
+
* METHOD SYNTAX REQUIRED, for the same reason ContainerDescriptor's members
|
|
908
|
+
* need it: the framework hands over the erased `PreflightInput<unknown>`,
|
|
909
|
+
* and an extension that types the input against its own client type only
|
|
910
|
+
* assigns here through method bivariance.
|
|
911
|
+
*/
|
|
912
|
+
preflight?(input: PreflightInput): Promise<void>;
|
|
913
|
+
/**
|
|
914
|
+
* Destroy-time cleanup — the CLI runs it once, after `alchemy destroy`
|
|
915
|
+
* succeeds and BEFORE the stage's Project/Branch are removed. A target uses
|
|
916
|
+
* it to remove infrastructure it owns outside the stack (e.g. the deploy
|
|
917
|
+
* state store, which the destroy above was still reading). Throwing aborts
|
|
918
|
+
* the destroy before the containers go; a target that would rather warn than
|
|
919
|
+
* fail the command handles that itself. Async: it talks to the platform.
|
|
920
|
+
*/
|
|
921
|
+
readonly teardown?: (input: TeardownInput) => Promise<void>;
|
|
922
|
+
/**
|
|
923
|
+
* The extension's container lifecycle, when its platform has containers
|
|
924
|
+
* (ADR-0038). The CLI resolves containers after assembly and before any
|
|
925
|
+
* stack file or Alchemy run (deploy ensures, destroy locates); the
|
|
926
|
+
* resolved instance reaches the alchemy process through the env transport
|
|
927
|
+
* in container-transport.ts.
|
|
928
|
+
*/
|
|
929
|
+
readonly container?: ContainerDescriptor;
|
|
930
|
+
/**
|
|
931
|
+
* The extension's LOCAL TARGET counterpart (ADR-0041; naming, operator
|
|
932
|
+
* 2026-07-23 — "dev" names the user-facing feature only, the seam takes
|
|
933
|
+
* the concept's real noun) — a LAZY reference: an async thunk, never the
|
|
934
|
+
* descriptor object itself. This keeps the production control entry's
|
|
935
|
+
* static import graph free of local-target implementation code (operator
|
|
936
|
+
* directive) — the thunk is one line, dynamically importing the
|
|
937
|
+
* extension's own local-target entry by bare specifier
|
|
938
|
+
* (e.g. `() => import('@prisma/composer-prisma-cloud/local-target').then((m) => m.localTargetDescriptor())`),
|
|
939
|
+
* so nothing local-target-flavored is bundled into, or loaded by, any
|
|
940
|
+
* deploy path.
|
|
941
|
+
*/
|
|
942
|
+
readonly localTarget?: () => Promise<LocalTargetDescriptor>;
|
|
943
|
+
}
|
|
944
|
+
/**
|
|
945
|
+
* The deploy's one state store. It names its owning extension so core knows
|
|
946
|
+
* whose resolved container to pass into `create` (ADR-0038).
|
|
947
|
+
*/
|
|
948
|
+
interface StateDescriptor {
|
|
949
|
+
/** The owning extension's id — matched against `ExtensionDescriptor.id`. */
|
|
950
|
+
readonly extension: string;
|
|
951
|
+
/** Build the state layer. `container` is the owning extension's resolved instance; `undefined` when it declared no container descriptor. */
|
|
952
|
+
create(container: ContainerInstance | undefined): AlchemyStateLayer;
|
|
953
|
+
}
|
|
954
|
+
/** The resolved deploy context handed to an extension's `preflight` hook. `C` erases to `unknown` at the framework boundary — see ContainerCredentials. */
|
|
955
|
+
interface PreflightInput<C = unknown> {
|
|
956
|
+
/** The loaded application graph — the manifest of prerequisites is read from it (`provisionManifest`). */
|
|
957
|
+
readonly graph: Graph;
|
|
958
|
+
/** The calling extension's own resolved container; `undefined` when it declares no container descriptor. Narrow with the extension's guard. */
|
|
959
|
+
readonly container: ContainerInstance | undefined;
|
|
960
|
+
/** The stage name (`--stage`), or `undefined` for the default stage — for diagnostics/scope. */
|
|
961
|
+
readonly stage: string | undefined;
|
|
962
|
+
/** What the caller has already authenticated, for the platform calls preflight makes. Absent means the extension falls back to its own credential protocol. */
|
|
963
|
+
readonly credentials?: ContainerCredentials<C> | undefined;
|
|
964
|
+
}
|
|
965
|
+
/** The resolved destroy context handed to an extension's `teardown` hook. */
|
|
966
|
+
interface TeardownInput {
|
|
967
|
+
/** The calling extension's own resolved container; `undefined` when it declares no container descriptor. Narrow with the extension's guard. */
|
|
968
|
+
readonly container: ContainerInstance | undefined;
|
|
969
|
+
/** The stage name (`--stage`), or `undefined` for the default stage — for diagnostics/scope. */
|
|
970
|
+
readonly stage: string | undefined;
|
|
971
|
+
}
|
|
972
|
+
/** The extension's LOCAL TARGET counterpart (ADR-0041) — the local-target variant OF ExtensionDescriptor, hence the full qualifier. An extension without one is not local-target-capable (cannot back the "dev" feature). */
|
|
973
|
+
interface LocalTargetDescriptor {
|
|
974
|
+
/** Local providers for the SAME resource types this extension's lowering emits. Receives the app identity — unlike deploy's env-arg-free `providers()`, local providers are emulator clients and must know which app they provision for. */
|
|
975
|
+
providers(input: LocalTargetProvidersInput): Layer.Layer<never>;
|
|
976
|
+
/** A stable local identity — resolved without any platform call. */
|
|
977
|
+
readonly container: ContainerDescriptor;
|
|
978
|
+
/** Value sourcing (secrets/env-params) — runs where deploy's preflight runs. */
|
|
979
|
+
preflight?(input: PreflightInput): Promise<void>;
|
|
980
|
+
/** Ensure the emulator daemons this topology's node kinds need are running (idempotent; they persist across sessions). */
|
|
981
|
+
emulators?(input: LocalTargetEmulatorsInput): Promise<void>;
|
|
982
|
+
/** The dev session's view of the running app. Core renders it and never learns an emulator's API. */
|
|
983
|
+
attach(input: LocalTargetAttachInput): Promise<LocalTargetAttachment>;
|
|
984
|
+
/** `--fresh`: remove every local trace of the dev instance — emulator instances, state, data. */
|
|
985
|
+
teardown?(input: TeardownInput): Promise<void>;
|
|
986
|
+
}
|
|
987
|
+
interface LocalTargetProvidersInput {
|
|
988
|
+
/** This extension's resolved local-target container (its `input.appName` is the emulator app namespace). */
|
|
989
|
+
readonly container: ContainerInstance | undefined;
|
|
990
|
+
/** Absolute path of the dev state directory (`<cwd>/.prisma-composer/dev`). */
|
|
991
|
+
readonly devDir: string;
|
|
992
|
+
}
|
|
993
|
+
interface LocalTargetEmulatorsInput {
|
|
994
|
+
/** The loaded application graph — inspected for which node kinds need an emulator. */
|
|
995
|
+
readonly graph: Graph;
|
|
996
|
+
readonly container: ContainerInstance | undefined;
|
|
997
|
+
/** Absolute path of the dev state directory (`<cwd>/.prisma-composer/dev`). */
|
|
998
|
+
readonly devDir: string;
|
|
999
|
+
}
|
|
1000
|
+
interface LocalTargetAttachInput {
|
|
1001
|
+
readonly container: ContainerInstance | undefined;
|
|
1002
|
+
readonly devDir: string;
|
|
1003
|
+
}
|
|
1004
|
+
interface LocalTargetAttachment {
|
|
1005
|
+
/** Start every stopped service from its last deployment (the session-resume signal — a no-op converge cannot start anything). */
|
|
1006
|
+
startServices(): Promise<void>;
|
|
1007
|
+
/** Every service's local endpoint, for the front door. */
|
|
1008
|
+
endpoints(): Promise<readonly {
|
|
1009
|
+
readonly address: string;
|
|
1010
|
+
readonly url: string;
|
|
1011
|
+
}[]>;
|
|
1012
|
+
/** Merged, line-oriented log stream across the app's services (including services that appear after later converges). `opts.tail` is how many trailing lines of existing history to emit before live output (default 0 — live only). Ends when `signal` aborts. */
|
|
1013
|
+
logs(signal: AbortSignal, opts?: {
|
|
1014
|
+
readonly tail?: number;
|
|
1015
|
+
}): AsyncIterable<{
|
|
1016
|
+
readonly service: string;
|
|
1017
|
+
readonly line: string;
|
|
1018
|
+
}>;
|
|
1019
|
+
/** Stop the app's service instances (emulators and data persist). */
|
|
1020
|
+
stopServices(): Promise<void>;
|
|
1021
|
+
}
|
|
1022
|
+
/**
|
|
1023
|
+
* What one registry entry can do. The `kind` discriminant is checked at every
|
|
1024
|
+
* lookup site against what the site needs — a resource node looked up against
|
|
1025
|
+
* a `service` descriptor is an error naming (extension, type, expected kind).
|
|
1026
|
+
*/
|
|
1027
|
+
type NodeDescriptor = ({
|
|
1028
|
+
readonly kind: 'resource';
|
|
1029
|
+
} & Lowering) | ({
|
|
1030
|
+
readonly kind: 'service';
|
|
1031
|
+
} & ServiceLowering) | {
|
|
1032
|
+
readonly kind: 'build';
|
|
1033
|
+
assemble(input: AssembleInput): Promise<Bundle>;
|
|
1034
|
+
};
|
|
1035
|
+
/**
|
|
1036
|
+
* The config file's default export. `extensions` lists every extension the
|
|
1037
|
+
* app deploys through; `state` is the ONE state store per deploy — explicit,
|
|
1038
|
+
* platform-agnostic, never defaulted by an extension.
|
|
1039
|
+
*/
|
|
1040
|
+
interface PrismaAppConfig {
|
|
1041
|
+
readonly extensions: ExtensionDescriptor[];
|
|
1042
|
+
readonly state: StateDescriptor;
|
|
1043
|
+
}
|
|
1044
|
+
//#endregion
|
|
1045
|
+
//#region ../../0-framework/3-tooling/assemble/dist/index.d.mts
|
|
1046
|
+
/** Assembles one service node — the seam tests substitute to avoid a real build. */
|
|
1047
|
+
type RunAssembler = (node: ServiceNode, address: string, cwd: string) => Promise<Bundle>;
|
|
1048
|
+
//#endregion
|
|
1049
|
+
//#region ../../0-framework/3-tooling/cli/dist/log-DRnnWupy.d.mts
|
|
1050
|
+
//#region src/deployment-summary.d.ts
|
|
1051
|
+
/** The serializable projection of DeploymentResult — what CAN cross the process
|
|
1052
|
+
* boundary. Writer (report hook) and reader (deploy operation) share this shape. */
|
|
1053
|
+
interface DeployedNodeSummary {
|
|
1054
|
+
readonly address: string;
|
|
1055
|
+
readonly entities: readonly DeployedEntity[];
|
|
1056
|
+
}
|
|
1057
|
+
interface DeploymentSummary {
|
|
1058
|
+
readonly app: string;
|
|
1059
|
+
readonly nodes: readonly DeployedNodeSummary[];
|
|
1060
|
+
}
|
|
1061
|
+
//#endregion
|
|
1062
|
+
//#region src/operations/shared.d.ts
|
|
1063
|
+
/** A running service's dotted address plus its local URL — what `dev` reports
|
|
1064
|
+
* as the front door and `log` reports as the tailable services. */
|
|
1065
|
+
interface ServiceEndpoint {
|
|
1066
|
+
readonly address: string;
|
|
1067
|
+
readonly url: string;
|
|
1068
|
+
}
|
|
1069
|
+
/**
|
|
1070
|
+
* The operations' in-package injection seam — lets the CLI's own tests drive
|
|
1071
|
+
* them without a real wrapper build, config evaluation, or alchemy process.
|
|
1072
|
+
* Threaded through the *WithDeps variants, never part of the published
|
|
1073
|
+
* surface: the fields mirror internal types.
|
|
1074
|
+
*/
|
|
1075
|
+
interface OperationDeps {
|
|
1076
|
+
readonly runAssembler?: RunAssembler | undefined;
|
|
1077
|
+
/**
|
|
1078
|
+
* Starts the converge child. The CLI passes one backed by the engine's
|
|
1079
|
+
* `ctx.spawn`, so the terminal reaches the child natively and the engine
|
|
1080
|
+
* owns signal policy; hosts get the default `spawnAlchemy`.
|
|
1081
|
+
*/
|
|
1082
|
+
readonly alchemy?: RunAlchemy | undefined;
|
|
1083
|
+
readonly config?: PrismaAppConfig | undefined;
|
|
1084
|
+
/** Names the config file explicitly instead of walking up from the entry. */
|
|
1085
|
+
readonly configPath?: string | undefined;
|
|
1086
|
+
/**
|
|
1087
|
+
* How the in-process leg authenticates: the caller's already-authenticated
|
|
1088
|
+
* API client and the workspace it acts in. Supplied by the CLI from the
|
|
1089
|
+
* engine's credential read, so no code below this point reads the
|
|
1090
|
+
* environment for token material. Absent for hosts that have not adopted
|
|
1091
|
+
* the seam — the container descriptors then fall back to the environment
|
|
1092
|
+
* protocol, as the spawned child does.
|
|
1093
|
+
*
|
|
1094
|
+
* Read by `deploy` and `destroy` only, because they are the operations that
|
|
1095
|
+
* reach a PLATFORM container. `dev` and `log` resolve local targets, whose
|
|
1096
|
+
* container is "a stable local identity — resolved without any platform
|
|
1097
|
+
* call", and both commands are credential-free by contract: there is no
|
|
1098
|
+
* authenticated call on those paths for this to reach.
|
|
1099
|
+
*/
|
|
1100
|
+
readonly credentials?: ContainerCredentials | undefined;
|
|
1101
|
+
}
|
|
1102
|
+
//#endregion
|
|
1103
|
+
//#region src/operations/deploy.d.ts
|
|
1104
|
+
interface DeployInput {
|
|
1105
|
+
/** Path to the entry module, resolved against `cwd` — same contract as `prisma-composer deploy <entry>`. */
|
|
1106
|
+
readonly entry: string;
|
|
1107
|
+
/** Override the root node's name (the `--name` flag's slot). */
|
|
1108
|
+
readonly name?: string | undefined;
|
|
1109
|
+
/** Target stage. ABSENT = production — bare deploy targets production (main.ts effectiveStage). */
|
|
1110
|
+
readonly stage?: string | undefined;
|
|
1111
|
+
/** Defaults to process.cwd(); the directory `.prisma-composer/` and `.alchemy` state live under. */
|
|
1112
|
+
readonly cwd?: string | undefined;
|
|
1113
|
+
}
|
|
1114
|
+
interface DeploySuccess {
|
|
1115
|
+
/** Parsed from the alchemy child's result file. Undefined when the child
|
|
1116
|
+
* did not write one (injected fake alchemy, or a report-less apply). */
|
|
1117
|
+
readonly summary: DeploymentSummary | undefined;
|
|
1118
|
+
}
|
|
1119
|
+
/** In-package variant threading the injection seam (the CLI's RunDeps, unit
|
|
1120
|
+
* tests). Deliberately NOT re-exported through `./control` — the seam mirrors
|
|
1121
|
+
* internal types and is not part of the published surface. */
|
|
1122
|
+
declare function deployWithDeps(input: DeployInput, deps: OperationDeps): Promise<Result$1<DeploySuccess, CliStructuredError>>;
|
|
1123
|
+
//#endregion
|
|
1124
|
+
//#region src/operations/destroy.d.ts
|
|
1125
|
+
/** Destroy must name its target explicitly — no silent default to production. Encoded, not re-derived from flags. */
|
|
1126
|
+
type DestroyTarget = {
|
|
1127
|
+
readonly kind: 'production';
|
|
1128
|
+
} | {
|
|
1129
|
+
readonly kind: 'stage';
|
|
1130
|
+
readonly stage: string;
|
|
1131
|
+
};
|
|
1132
|
+
type DestroyEvent =
|
|
1133
|
+
/** Emitted before the pipeline when `<cwd>/.alchemy` is missing/empty. */
|
|
1134
|
+
{
|
|
1135
|
+
readonly kind: 'no-local-deploy-state';
|
|
1136
|
+
readonly cwd: string;
|
|
1137
|
+
};
|
|
1138
|
+
interface DestroyInput {
|
|
1139
|
+
readonly entry: string;
|
|
1140
|
+
readonly name?: string | undefined;
|
|
1141
|
+
readonly target: DestroyTarget;
|
|
1142
|
+
readonly cwd?: string | undefined;
|
|
1143
|
+
/** Mid-operation notifications, in real time. Rendering is the host's. */
|
|
1144
|
+
readonly onEvent?: ((event: DestroyEvent) => void) | undefined;
|
|
1145
|
+
}
|
|
1146
|
+
/** In-package variant threading the injection seam (the CLI's RunDeps, unit
|
|
1147
|
+
* tests). Deliberately NOT re-exported through `./control` — the seam mirrors
|
|
1148
|
+
* internal types and is not part of the published surface. */
|
|
1149
|
+
declare function destroyWithDeps(input: DestroyInput, deps: OperationDeps): Promise<Result$1<void, CliStructuredError>>;
|
|
1150
|
+
//#endregion
|
|
1151
|
+
//#region src/operations/dev.d.ts
|
|
1152
|
+
type DevEvent =
|
|
1153
|
+
/** Initial front door + after each successful re-converge. */
|
|
1154
|
+
{
|
|
1155
|
+
readonly kind: 'ready';
|
|
1156
|
+
readonly endpoints: readonly ServiceEndpoint[];
|
|
1157
|
+
} | {
|
|
1158
|
+
readonly kind: 'unwatchable';
|
|
1159
|
+
readonly address: string;
|
|
1160
|
+
} | {
|
|
1161
|
+
readonly kind: 'rebuild-failed';
|
|
1162
|
+
readonly message: string;
|
|
1163
|
+
} |
|
|
1164
|
+
/** The file watcher itself errored (EMFILE, a vanished directory); the session keeps running. */
|
|
1165
|
+
{
|
|
1166
|
+
readonly kind: 'watch-error';
|
|
1167
|
+
readonly message: string;
|
|
1168
|
+
} |
|
|
1169
|
+
/** The app keeps running, still watching. */
|
|
1170
|
+
{
|
|
1171
|
+
readonly kind: 'converge-failed';
|
|
1172
|
+
readonly stackFilePath: string;
|
|
1173
|
+
readonly reproduceCommand: string;
|
|
1174
|
+
readonly cwd: string;
|
|
1175
|
+
} | {
|
|
1176
|
+
readonly kind: 'stopping';
|
|
1177
|
+
} |
|
|
1178
|
+
/** One service refused to stop during stop(); teardown continues and `stopped` still follows. */
|
|
1179
|
+
{
|
|
1180
|
+
readonly kind: 'stop-error';
|
|
1181
|
+
readonly message: string;
|
|
1182
|
+
} | {
|
|
1183
|
+
readonly kind: 'stopped';
|
|
1184
|
+
};
|
|
1185
|
+
interface DevInput {
|
|
1186
|
+
readonly entry: string;
|
|
1187
|
+
readonly name?: string | undefined;
|
|
1188
|
+
readonly fresh?: boolean | undefined;
|
|
1189
|
+
readonly cwd?: string | undefined;
|
|
1190
|
+
readonly onEvent?: ((event: DevEvent) => void) | undefined;
|
|
1191
|
+
}
|
|
1192
|
+
/** A running dev session. The operation NEVER touches process signal handlers —
|
|
1193
|
+
* the host owns signals (and must evict alchemy's import-time SIGINT/SIGTERM
|
|
1194
|
+
* listeners before installing its own; see run-dev.ts). */
|
|
1195
|
+
interface DevSession {
|
|
1196
|
+
/** The initial front door, already merged across attachments. */
|
|
1197
|
+
readonly endpoints: readonly ServiceEndpoint[];
|
|
1198
|
+
/** Stop the watch loop and the app's services (emulators and data stay up).
|
|
1199
|
+
* Idempotent; emits 'stopping'/'stopped'; resolves `closed`. */
|
|
1200
|
+
stop(): Promise<void>;
|
|
1201
|
+
/** Settles when the session has fully stopped (via stop()). */
|
|
1202
|
+
readonly closed: Promise<void>;
|
|
1203
|
+
}
|
|
1204
|
+
/** In-package variant threading the injection seam (the CLI's RunDeps, unit
|
|
1205
|
+
* tests). Deliberately NOT re-exported through `./control` — the seam mirrors
|
|
1206
|
+
* internal types and is not part of the published surface. */
|
|
1207
|
+
declare function devWithDeps(input: DevInput, deps: OperationDeps): Promise<Result$1<DevSession, CliStructuredError>>;
|
|
1208
|
+
//#endregion
|
|
1209
|
+
//#region src/pipeline.d.ts
|
|
1210
|
+
interface AppIdentity {
|
|
1211
|
+
readonly configPath: string;
|
|
1212
|
+
readonly config: PrismaAppConfig;
|
|
1213
|
+
readonly name: string;
|
|
1214
|
+
}
|
|
1215
|
+
//#endregion
|
|
1216
|
+
//#region src/operations/log.d.ts
|
|
1217
|
+
interface LogLine {
|
|
1218
|
+
readonly service: string;
|
|
1219
|
+
readonly line: string;
|
|
1220
|
+
}
|
|
1221
|
+
type LogEvent =
|
|
1222
|
+
/** One attachment's stream died; the others continue. */
|
|
1223
|
+
{
|
|
1224
|
+
readonly kind: 'stream-failed';
|
|
1225
|
+
readonly message: string;
|
|
1226
|
+
} |
|
|
1227
|
+
/** The consumer fell behind and the bounded merge queue overflowed:
|
|
1228
|
+
* `count` oldest lines were dropped since the last delivered line. */
|
|
1229
|
+
{
|
|
1230
|
+
readonly kind: 'lines-dropped';
|
|
1231
|
+
readonly count: number;
|
|
1232
|
+
};
|
|
1233
|
+
/** The log operation's in-package injection seam (the CLI's LogRunDeps, unit
|
|
1234
|
+
* tests) — threaded through logWithDeps, never part of the published surface. */
|
|
1235
|
+
interface LogDeps {
|
|
1236
|
+
/** Substituted for the c12 evaluation of the discovered config file (discovery still runs). */
|
|
1237
|
+
readonly config?: PrismaAppConfig | undefined;
|
|
1238
|
+
/** Overrides the identity resolution (config + name) — lets tests skip a real entry module. */
|
|
1239
|
+
readonly identity?: AppIdentity | undefined;
|
|
1240
|
+
/** Names the config file explicitly instead of walking up from the entry. */
|
|
1241
|
+
readonly configPath?: string | undefined;
|
|
1242
|
+
}
|
|
1243
|
+
interface LogInput {
|
|
1244
|
+
readonly entry: string;
|
|
1245
|
+
readonly name?: string | undefined;
|
|
1246
|
+
/** Restrict to one service's dotted address; validated against running services. */
|
|
1247
|
+
readonly address?: string | undefined;
|
|
1248
|
+
/** Trailing history lines before live output. Defaults to 0 (live only) —
|
|
1249
|
+
* the attachment contract's default; the CLI's user-facing default of 20 stays in main.ts. */
|
|
1250
|
+
readonly tail?: number | undefined;
|
|
1251
|
+
readonly cwd?: string | undefined;
|
|
1252
|
+
/** Ends the stream when aborted. The host owns SIGINT/SIGTERM → abort. */
|
|
1253
|
+
readonly signal?: AbortSignal | undefined;
|
|
1254
|
+
readonly onEvent?: ((event: LogEvent) => void) | undefined;
|
|
1255
|
+
}
|
|
1256
|
+
interface LogAttached {
|
|
1257
|
+
/** For the adapter's empty-services notice. */
|
|
1258
|
+
readonly appName: string;
|
|
1259
|
+
/** Every running service. EMPTY means nothing is running — a valid, non-failure state;
|
|
1260
|
+
* `lines` is then an already-finished iterable. */
|
|
1261
|
+
readonly services: readonly ServiceEndpoint[];
|
|
1262
|
+
/** Merged, address-filtered stream; ends on signal abort or when every source ends. */
|
|
1263
|
+
readonly lines: AsyncIterable<LogLine>;
|
|
1264
|
+
}
|
|
1265
|
+
/** In-package variant threading the injection seam (the CLI's LogRunDeps,
|
|
1266
|
+
* unit tests). Deliberately NOT re-exported through `./control` — the seam
|
|
1267
|
+
* mirrors internal types and is not part of the published surface. */
|
|
1268
|
+
declare function logWithDeps(input: LogInput, deps: LogDeps): Promise<Result$1<LogAttached, CliStructuredError>>;
|
|
1269
|
+
//#endregion
|
|
1270
|
+
//#region ../../0-framework/3-tooling/cli/dist/family-DkH0si4D.d.mts
|
|
1271
|
+
//#region src/family/family.d.ts
|
|
1272
|
+
/**
|
|
1273
|
+
* The control-plane operations the family's handlers call. These are the
|
|
1274
|
+
* deps-taking variants, not the bare ones: a handler must inject the converge
|
|
1275
|
+
* spawn adapter (so the ENGINE starts the child and owns signal policy) and
|
|
1276
|
+
* the credentials the in-process leg authenticates with. A double that
|
|
1277
|
+
* honours `deps.alchemy` therefore exercises the real settlement path
|
|
1278
|
+
* against a scripted fake child.
|
|
1279
|
+
*/
|
|
1280
|
+
interface ComposerOperations {
|
|
1281
|
+
readonly deploy: typeof deployWithDeps;
|
|
1282
|
+
readonly destroy: typeof destroyWithDeps;
|
|
1283
|
+
readonly dev: typeof devWithDeps;
|
|
1284
|
+
readonly log: typeof logWithDeps;
|
|
1285
|
+
}
|
|
1286
|
+
declare const realOperations: ComposerOperations;
|
|
1287
|
+
interface CreateComposerFamilyOptions {
|
|
1288
|
+
/** Defaults to the real control operations. */
|
|
1289
|
+
readonly operations?: ComposerOperations | undefined;
|
|
1290
|
+
}
|
|
1291
|
+
declare function createComposerFamily(options?: CreateComposerFamilyOptions): CommandFamily;
|
|
1292
|
+
//#endregion
|
|
1293
|
+
export { Result$1 as _, DeployInput as a, DestroyInput as c, LogAttached as d, LogDeps as f, ServiceEndpoint as g, OperationDeps as h, realOperations as i, DevInput as l, LogLine as m, CreateComposerFamilyOptions as n, DeploySuccess as o, LogInput as p, createComposerFamily as r, DestroyEvent as s, ComposerOperations as t, DevSession as u, CliStructuredError as v };
|
|
1294
|
+
//# sourceMappingURL=family-DkH0si4D-CN5QubKS.d.mts.map
|