@prisma/composer-prisma-cloud 0.3.0-dev.8 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/compute-main.mjs +4 -20
- package/dist/compute-main.mjs.map +1 -1
- package/dist/control.d.mts +1 -1
- package/dist/control.mjs +17 -28
- package/dist/control.mjs.map +1 -1
- package/dist/cron/index.d.mts +26 -33
- package/dist/cron/index.d.mts.map +1 -1
- package/dist/cron/index.mjs +77 -202
- package/dist/cron/index.mjs.map +1 -1
- package/dist/cron/scheduler-entrypoint.mjs +114 -133
- package/dist/cron/scheduler-entrypoint.mjs.map +1 -1
- package/dist/cron/scheduler-service.mjs +76 -200
- package/dist/cron/scheduler-service.mjs.map +1 -1
- package/dist/email/email-entrypoint.mjs +126 -162
- package/dist/email/email-entrypoint.mjs.map +1 -1
- package/dist/email/email-service.mjs +79 -230
- package/dist/email/email-service.mjs.map +1 -1
- package/dist/email/index.d.mts +29 -33
- package/dist/email/index.d.mts.map +1 -1
- package/dist/email/index.mjs +84 -236
- package/dist/email/index.mjs.map +1 -1
- package/dist/email/testing.mjs +89 -112
- package/dist/email/testing.mjs.map +1 -1
- package/dist/index.d.mts +43 -51
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +51 -47
- package/dist/index.mjs.map +1 -1
- package/dist/local-target.mjs +1 -1
- package/dist/local-target.mjs.map +1 -1
- package/dist/{secret-BVGxqHxY-DYDfiULl.mjs → param-BTzY0ne5-CW6ojZ3E.mjs} +4 -45
- package/dist/param-BTzY0ne5-CW6ojZ3E.mjs.map +1 -0
- package/dist/{preflight-names-CpJUd9ZA-BCU-W3cT.mjs → preflight-names-BPL-qsZF-BfoRgbgb.mjs} +14 -30
- package/dist/{preflight-names-CpJUd9ZA-BCU-W3cT.mjs.map → preflight-names-BPL-qsZF-BfoRgbgb.mjs.map} +1 -1
- package/dist/{provisioned-edges-Cxy18aoh-CUnaY96r.mjs → provisioned-edges-C1wSO3cx-YC5C19f9.mjs} +3 -3
- package/dist/{provisioned-edges-Cxy18aoh-CUnaY96r.mjs.map → provisioned-edges-C1wSO3cx-YC5C19f9.mjs.map} +1 -1
- package/dist/secret-rz_ZqNeq-_xd97Jd9.mjs +47 -0
- package/dist/secret-rz_ZqNeq-_xd97Jd9.mjs.map +1 -0
- package/dist/serializer-CJiOhF2d-DJUjQj1i.mjs +251 -0
- package/dist/serializer-CJiOhF2d-DJUjQj1i.mjs.map +1 -0
- package/dist/{serializer-BD_6nkr4-DWn5NNTC.d.mts → serializer-Cx5slrV4-xJfH6EWS.d.mts} +2 -2
- package/dist/serializer-Cx5slrV4-xJfH6EWS.d.mts.map +1 -0
- package/dist/storage/index.d.mts +26 -31
- package/dist/storage/index.d.mts.map +1 -1
- package/dist/storage/index.mjs +89 -215
- package/dist/storage/index.mjs.map +1 -1
- package/dist/storage/storage-entrypoint.mjs +122 -147
- package/dist/storage/storage-entrypoint.mjs.map +1 -1
- package/dist/storage/storage-service.mjs +87 -212
- package/dist/storage/storage-service.mjs.map +1 -1
- package/dist/streams/index.d.mts +22 -29
- package/dist/streams/index.d.mts.map +1 -1
- package/dist/streams/index.mjs +88 -213
- package/dist/streams/index.mjs.map +1 -1
- package/dist/streams/streams-entrypoint.mjs +118 -139
- package/dist/streams/streams-entrypoint.mjs.map +1 -1
- package/dist/streams/streams-service.mjs +87 -212
- package/dist/streams/streams-service.mjs.map +1 -1
- package/dist/testing.d.mts +5 -19
- package/dist/testing.d.mts.map +1 -1
- package/dist/testing.mjs +3 -11
- package/dist/testing.mjs.map +1 -1
- package/package.json +18 -18
- package/dist/secret-BVGxqHxY-DYDfiULl.mjs.map +0 -1
- package/dist/serializer-BD_6nkr4-DWn5NNTC.d.mts.map +0 -1
- package/dist/serializer-sVE4UAmg-CikRngbR.mjs +0 -475
- package/dist/serializer-sVE4UAmg-CikRngbR.mjs.map +0 -1
|
@@ -1,11 +1,4 @@
|
|
|
1
1
|
//#region ../../1-prisma-cloud/2-shared-modules/cron/dist/scheduler-entrypoint.mjs
|
|
2
|
-
const nodeBuild = (opts) => ({
|
|
3
|
-
extension: "@prisma/composer/node",
|
|
4
|
-
type: "node",
|
|
5
|
-
module: opts.module,
|
|
6
|
-
entry: opts.entry,
|
|
7
|
-
...opts.dir === void 0 ? {} : { dir: opts.dir }
|
|
8
|
-
});
|
|
9
2
|
/**
|
|
10
3
|
* **Last-resort escape hatch for unsafe type assertions. Not a sanctioned tool to reach for.**
|
|
11
4
|
*
|
|
@@ -87,14 +80,18 @@ function freezeParams(params) {
|
|
|
87
80
|
for (const [name, param] of Object.entries(params)) frozen[name] = Object.freeze({ ...param });
|
|
88
81
|
return Object.freeze(frozen);
|
|
89
82
|
}
|
|
83
|
+
function freezeSecrets(secrets) {
|
|
84
|
+
const frozen = {};
|
|
85
|
+
for (const [name, need] of Object.entries(secrets)) frozen[name] = Object.freeze({ ...need });
|
|
86
|
+
return blindCast(Object.freeze(frozen));
|
|
87
|
+
}
|
|
90
88
|
/** A frozen shallow copy that keeps the caller's declared type. */
|
|
91
89
|
function frozenShallowCopy(obj) {
|
|
92
90
|
return blindCast(Object.freeze({ ...obj }));
|
|
93
91
|
}
|
|
94
92
|
/**
|
|
95
93
|
* Constructs a branded, frozen Service node — declarations only (inputs,
|
|
96
|
-
* params,
|
|
97
|
-
* carries no runtime behavior.
|
|
94
|
+
* params, build adapter, and the ports it exposes). Pure; carries no runtime behavior.
|
|
98
95
|
*/
|
|
99
96
|
function service$1(def) {
|
|
100
97
|
requireName(def.name, "service");
|
|
@@ -102,7 +99,8 @@ function service$1(def) {
|
|
|
102
99
|
requireType(def.type, "service");
|
|
103
100
|
requireConfigKeySegmentNames(Object.keys(def.inputs), "input", "service");
|
|
104
101
|
requireConfigKeySegmentNames(Object.keys(def.params), "param", "service");
|
|
105
|
-
|
|
102
|
+
requireConfigKeySegmentNames(Object.keys(def.secrets ?? {}), "secret", "service");
|
|
103
|
+
for (const slot of Object.keys(def.secrets ?? {})) if (Object.hasOwn(def.params, slot)) throw new Error(`service() secret slot "${slot}" collides with a param of the same name — a secret slot and a service param derive the same config key (COMPOSER_<addr>_${slot.toUpperCase()}); rename one.`);
|
|
106
104
|
return Object.freeze({
|
|
107
105
|
[NODE]: true,
|
|
108
106
|
kind: "service",
|
|
@@ -111,7 +109,7 @@ function service$1(def) {
|
|
|
111
109
|
type: def.type,
|
|
112
110
|
inputs: frozenShallowCopy(def.inputs),
|
|
113
111
|
params: freezeParams(def.params),
|
|
114
|
-
|
|
112
|
+
secretSlots: freezeSecrets(def.secrets ?? blindCast({})),
|
|
115
113
|
build: Object.freeze({ ...def.build }),
|
|
116
114
|
expose: def.expose !== void 0 ? frozenShallowCopy(def.expose) : void 0
|
|
117
115
|
});
|
|
@@ -144,16 +142,11 @@ function dependency(def) {
|
|
|
144
142
|
* `JSON.stringify`, and `console.log`/`util.inspect` all print `[REDACTED]`, so
|
|
145
143
|
* a secret can't leak through an accidental log or serialization.
|
|
146
144
|
*
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
* symbol key is invisible to `JSON.stringify` and `Object.keys`, so the box's
|
|
150
|
-
* public shape still matches the platform's own `secrecy` type
|
|
151
|
-
* (pdp-control-plane).
|
|
145
|
+
* Shape matches the platform's own `secrecy` type (pdp-control-plane). The class
|
|
146
|
+
* is nominal enough on its own — no phantom brand.
|
|
152
147
|
*/
|
|
153
148
|
const REDACTED = "[REDACTED]";
|
|
154
|
-
const SECRET_BOX = blindCast(Symbol.for("prisma:secret-box"));
|
|
155
149
|
var SecretBox = class {
|
|
156
|
-
[SECRET_BOX] = true;
|
|
157
150
|
#value;
|
|
158
151
|
constructor(value) {
|
|
159
152
|
this.#value = value;
|
|
@@ -203,6 +196,10 @@ function string$1(opts = {}) {
|
|
|
203
196
|
function number$1(opts = {}) {
|
|
204
197
|
return withFacets(numberSchema, opts);
|
|
205
198
|
}
|
|
199
|
+
/** A param over any caller-supplied Standard Schema — a structured `jobs`, say. */
|
|
200
|
+
function param(schema, opts = {}) {
|
|
201
|
+
return withFacets(schema, opts);
|
|
202
|
+
}
|
|
206
203
|
/**
|
|
207
204
|
* Synchronous hydrate — what the node's `load()` uses so
|
|
208
205
|
* `const { db } = service.load()` reads without `await`. Requires every
|
|
@@ -219,6 +216,31 @@ function hydrateSync(root, config) {
|
|
|
219
216
|
}
|
|
220
217
|
return deps;
|
|
221
218
|
}
|
|
219
|
+
/**
|
|
220
|
+
* Wraps each of a service's resolved secret values in a redacting `SecretBox`
|
|
221
|
+
* — what the node's `secrets()` accessor returns (ADR-0021, sibling to
|
|
222
|
+
* `load()`/`config()`). The RESOLUTION of a secret's value (the boot
|
|
223
|
+
* double-lookup that reads the platform var the pointer names) is the target
|
|
224
|
+
* pack's job; core is handed the already-resolved strings and only boxes them,
|
|
225
|
+
* so a secret is redacted by TYPE from here on. A declared slot missing from
|
|
226
|
+
* `values` is a target contract violation, named loudly.
|
|
227
|
+
*/
|
|
228
|
+
function hydrateSecrets(root, values) {
|
|
229
|
+
const boxed = {};
|
|
230
|
+
for (const slot of Object.keys(root.secretSlots)) {
|
|
231
|
+
const value = values[slot];
|
|
232
|
+
if (value === void 0) throw new Error(`secret slot "${slot}" has no resolved value — the target must resolve every declared secret before hydrateSecrets().`);
|
|
233
|
+
boxed[slot] = new SecretBox(value);
|
|
234
|
+
}
|
|
235
|
+
return blindCast(boxed);
|
|
236
|
+
}
|
|
237
|
+
const nodeBuild = (opts) => ({
|
|
238
|
+
extension: "@prisma/composer/node",
|
|
239
|
+
type: "node",
|
|
240
|
+
module: opts.module,
|
|
241
|
+
entry: opts.entry,
|
|
242
|
+
...opts.dir === void 0 ? {} : { dir: opts.dir }
|
|
243
|
+
});
|
|
222
244
|
const liftArray = (data) => Array.isArray(data) ? data : [data];
|
|
223
245
|
/**
|
|
224
246
|
* Splits an array into two arrays based on the result of a predicate
|
|
@@ -7426,7 +7448,7 @@ function coerceEnvSourcedParam(raw, d, key) {
|
|
|
7426
7448
|
/**
|
|
7427
7449
|
* Boot: read each declared param from env by its key, reverse the param's own
|
|
7428
7450
|
* serialization (missing/invalid fails loudly), assemble the typed Config.
|
|
7429
|
-
*
|
|
7451
|
+
* Secrets ride a separate channel (deserializeSecrets), not this one.
|
|
7430
7452
|
*/
|
|
7431
7453
|
const deserialize = (node, address) => {
|
|
7432
7454
|
const service = {};
|
|
@@ -7463,84 +7485,40 @@ const stash = (node, config) => {
|
|
|
7463
7485
|
process.env[configKey("", d)] = encode(d.owner, value);
|
|
7464
7486
|
}
|
|
7465
7487
|
};
|
|
7466
|
-
/** The
|
|
7467
|
-
const
|
|
7468
|
-
/** The input document row's key for a service address. */
|
|
7469
|
-
const inputKey = (address) => configKey(address, {
|
|
7488
|
+
/** The pointer-row key for a secret slot: COMPOSER_<addr>_<slot> (secrets are service-level). */
|
|
7489
|
+
const secretKey = (address, slot) => configKey(address, {
|
|
7470
7490
|
owner: "service",
|
|
7471
|
-
name:
|
|
7491
|
+
name: slot
|
|
7472
7492
|
});
|
|
7473
|
-
const SECRET_MARKER = "$secret";
|
|
7474
|
-
const ESCAPED_KEY = /^\$\$+secret$/;
|
|
7475
|
-
/** True for the framework's secret pointer: `{ "$secret": "<PLATFORM_VAR>" }` and nothing else. */
|
|
7476
|
-
function isSecretPointer(value) {
|
|
7477
|
-
return typeof value === "object" && value !== null && !Array.isArray(value) && Object.keys(value).length === 1 && SECRET_MARKER in value && typeof value[SECRET_MARKER] === "string";
|
|
7478
|
-
}
|
|
7479
|
-
/** A plain data object (not an array, not a class instance) — the only object shape a binding/document may nest. */
|
|
7480
|
-
function isPlainObject(value) {
|
|
7481
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
7482
|
-
const proto = Object.getPrototypeOf(value);
|
|
7483
|
-
return proto === Object.prototype || proto === null;
|
|
7484
|
-
}
|
|
7485
7493
|
/**
|
|
7486
|
-
* Boot:
|
|
7487
|
-
*
|
|
7488
|
-
* platform
|
|
7489
|
-
*
|
|
7490
|
-
* the env var — a deployed environment always writes it; a local harness must
|
|
7491
|
-
* supply it (set the row to the serialized input document).
|
|
7494
|
+
* Boot: resolve every secret slot to its value by double-lookup — read the
|
|
7495
|
+
* pointer key (the platform NAME), then read that platform var. A missing
|
|
7496
|
+
* pointer or a missing/empty platform value is a loud failure naming both keys.
|
|
7497
|
+
* Returns a plain Record for core's `hydrateSecrets` to box.
|
|
7492
7498
|
*/
|
|
7493
|
-
|
|
7494
|
-
const
|
|
7495
|
-
|
|
7496
|
-
|
|
7497
|
-
|
|
7498
|
-
|
|
7499
|
-
|
|
7500
|
-
|
|
7501
|
-
|
|
7502
|
-
}
|
|
7503
|
-
|
|
7504
|
-
|
|
7505
|
-
}
|
|
7506
|
-
const hydrated = hydrateInputDocument(parsed, key);
|
|
7507
|
-
try {
|
|
7508
|
-
return standardValidateSync(schema, hydrated);
|
|
7509
|
-
} catch (cause) {
|
|
7510
|
-
const message = cause instanceof Error ? cause.message : String(cause);
|
|
7511
|
-
throw new Error(`invalid input document (env ${key}): ${message}`);
|
|
7512
|
-
}
|
|
7513
|
-
}
|
|
7514
|
-
/** Reverses the document encoding: `$secret` pointers become redacting boxes over the named platform vars; escaped reserved keys drop one "$". */
|
|
7515
|
-
function hydrateInputDocument(value, key) {
|
|
7516
|
-
if (isSecretPointer(value)) {
|
|
7517
|
-
const name = value[SECRET_MARKER];
|
|
7518
|
-
const secret = process.env[name];
|
|
7519
|
-
if (secret === void 0 || secret === "") throw new Error(`secret input is not provisioned (env ${key} → ${name}): the platform var "${name}" is unset or empty.`);
|
|
7520
|
-
return new SecretBox(secret);
|
|
7521
|
-
}
|
|
7522
|
-
if (Array.isArray(value)) return value.map((member) => hydrateInputDocument(member, key));
|
|
7523
|
-
if (isPlainObject(value)) {
|
|
7524
|
-
const out = {};
|
|
7525
|
-
for (const [k, member] of Object.entries(value)) {
|
|
7526
|
-
const read = ESCAPED_KEY.test(k) ? k.slice(1) : k;
|
|
7527
|
-
out[read] = hydrateInputDocument(member, key);
|
|
7528
|
-
}
|
|
7529
|
-
return out;
|
|
7530
|
-
}
|
|
7531
|
-
return value;
|
|
7532
|
-
}
|
|
7499
|
+
const deserializeSecrets = (node, address) => {
|
|
7500
|
+
const values = {};
|
|
7501
|
+
for (const slot of Object.keys(node.secretSlots)) {
|
|
7502
|
+
const key = secretKey(address, slot);
|
|
7503
|
+
const name = process.env[key];
|
|
7504
|
+
if (name === void 0 || name === "") throw new Error(`missing secret pointer for slot "${slot}" (env ${key}) — the deploy did not write it.`);
|
|
7505
|
+
const value = process.env[name];
|
|
7506
|
+
if (value === void 0 || value === "") throw new Error(`secret "${slot}" is not provisioned (env ${key} → ${name}): the platform var "${name}" is unset or empty.`);
|
|
7507
|
+
values[slot] = value;
|
|
7508
|
+
}
|
|
7509
|
+
return values;
|
|
7510
|
+
};
|
|
7533
7511
|
/**
|
|
7534
|
-
* run()'s setup step for
|
|
7535
|
-
* address-free key, so the address-free `
|
|
7536
|
-
*
|
|
7537
|
-
* platform vars.
|
|
7512
|
+
* run()'s setup step for secrets: re-emit each slot's pointer NAME under its
|
|
7513
|
+
* address-free key, so the address-free `deserializeSecrets` double-looks-up
|
|
7514
|
+
* identically. Never the value — the value stays only in the platform var.
|
|
7538
7515
|
*/
|
|
7539
|
-
const
|
|
7540
|
-
|
|
7541
|
-
|
|
7542
|
-
|
|
7543
|
-
|
|
7516
|
+
const stashSecrets = (node, address) => {
|
|
7517
|
+
for (const slot of Object.keys(node.secretSlots)) {
|
|
7518
|
+
const name = process.env[secretKey(address, slot)];
|
|
7519
|
+
if (name === void 0) continue;
|
|
7520
|
+
process.env[secretKey("", slot)] = name;
|
|
7521
|
+
}
|
|
7544
7522
|
};
|
|
7545
7523
|
/**
|
|
7546
7524
|
* Boot: for each reserved provider param, read its address-scoped row through
|
|
@@ -7830,24 +7808,20 @@ Object.freeze({
|
|
|
7830
7808
|
});
|
|
7831
7809
|
const reservedParams = { port: number$1({ default: 3e3 }) };
|
|
7832
7810
|
/**
|
|
7833
|
-
* A Prisma Compute service — declarations only (deps +
|
|
7834
|
-
*
|
|
7835
|
-
*
|
|
7836
|
-
*
|
|
7811
|
+
* A Prisma Compute service — declarations only (deps + params + build + the
|
|
7812
|
+
* ports it exposes), no descriptor. `params` merges with the reserved
|
|
7813
|
+
* `ReservedParams` (`port`); a user param whose name collides with a reserved
|
|
7814
|
+
* one fails at authoring, the same way a colliding dependency name does.
|
|
7837
7815
|
*
|
|
7838
7816
|
* · run(address, boot) — the process controller: deserialize the platform
|
|
7839
7817
|
* environment (keyed off `address`, the extension's ONE env read) into a
|
|
7840
|
-
* typed Config, re-emit it
|
|
7841
|
-
*
|
|
7842
|
-
* · load() /
|
|
7843
|
-
* load() hydrates + memoizes the deps,
|
|
7844
|
-
*
|
|
7845
|
-
* platform var, validates with the declared schema, and memoizes (ADR-0042).
|
|
7818
|
+
* typed Config, re-emit it under address-free process-local stash keys,
|
|
7819
|
+
* then call boot() to start the app's entry.
|
|
7820
|
+
* · load() / config() — called from inside the app's entry: read the stash;
|
|
7821
|
+
* load() hydrates + memoizes the deps, config() returns the typed params.
|
|
7822
|
+
* Separate accessors so a dep and a param never share a namespace (ADR-0021).
|
|
7846
7823
|
* · origin() — this service's platform-assigned public origin, read from the
|
|
7847
7824
|
* stash `run()` populates; memoized per process.
|
|
7848
|
-
* · port() — this service's resolved reserved port (the value `run()` routes
|
|
7849
|
-
* to and exports as PORT), read from that same stash via #processConfig();
|
|
7850
|
-
* defaults to 3000 when the platform binds none.
|
|
7851
7825
|
*
|
|
7852
7826
|
* The underlying node carries `extension: '@prisma/composer-prisma-cloud'` —
|
|
7853
7827
|
* the control-plane registry key `prisma-composer deploy` resolves through the
|
|
@@ -7857,7 +7831,8 @@ const reservedParams = { port: number$1({ default: 3e3 }) };
|
|
|
7857
7831
|
var ComputeService = class {
|
|
7858
7832
|
#resolved;
|
|
7859
7833
|
#loadedDeps;
|
|
7860
|
-
#
|
|
7834
|
+
#loadedParams;
|
|
7835
|
+
#loadedSecrets;
|
|
7861
7836
|
#origin;
|
|
7862
7837
|
constructor(node) {
|
|
7863
7838
|
Object.assign(this, node);
|
|
@@ -7870,7 +7845,7 @@ var ComputeService = class {
|
|
|
7870
7845
|
const config = deserialize(this, address);
|
|
7871
7846
|
stash(this, config);
|
|
7872
7847
|
stashProviderParams(RESERVED_PROVIDER_PARAMS, address);
|
|
7873
|
-
|
|
7848
|
+
stashSecrets(this, address);
|
|
7874
7849
|
const port = config.service["port"];
|
|
7875
7850
|
if (typeof port === "number") process.env["PORT"] = String(port);
|
|
7876
7851
|
return boot();
|
|
@@ -7879,9 +7854,13 @@ var ComputeService = class {
|
|
|
7879
7854
|
if (this.#loadedDeps === void 0) this.#loadedDeps = blindCast(hydrateSync(this, this.#processConfig()));
|
|
7880
7855
|
return this.#loadedDeps;
|
|
7881
7856
|
}
|
|
7882
|
-
|
|
7883
|
-
if (this.#
|
|
7884
|
-
return this.#
|
|
7857
|
+
config() {
|
|
7858
|
+
if (this.#loadedParams === void 0) this.#loadedParams = blindCast(this.#processConfig().service);
|
|
7859
|
+
return this.#loadedParams;
|
|
7860
|
+
}
|
|
7861
|
+
secrets() {
|
|
7862
|
+
if (this.#loadedSecrets === void 0) this.#loadedSecrets = blindCast(hydrateSecrets(this, deserializeSecrets(this, "")));
|
|
7863
|
+
return this.#loadedSecrets;
|
|
7885
7864
|
}
|
|
7886
7865
|
/** This service's platform-assigned public origin — read from the stash
|
|
7887
7866
|
* run() populates and memoized per process. Throws if called before run()
|
|
@@ -7890,24 +7869,26 @@ var ComputeService = class {
|
|
|
7890
7869
|
this.#origin ??= readOrigin();
|
|
7891
7870
|
return this.#origin;
|
|
7892
7871
|
}
|
|
7893
|
-
/** This service's resolved reserved port — the value run() routes to and
|
|
7894
|
-
* exports as PORT — read the same way load() reads the stash. Defaults to
|
|
7895
|
-
* 3000 when the platform binds none. */
|
|
7896
|
-
port() {
|
|
7897
|
-
const port = this.#processConfig().service["port"];
|
|
7898
|
-
if (typeof port !== "number") throw new Error(`service "${this.name}" resolved a non-numeric port — the reserved port param is number({ default: 3000 }), so a stashed config always carries a number here.`);
|
|
7899
|
-
return port;
|
|
7900
|
-
}
|
|
7901
7872
|
};
|
|
7902
7873
|
const compute = (def) => {
|
|
7903
|
-
|
|
7874
|
+
const userParams = def.params ?? blindCast({});
|
|
7875
|
+
for (const reserved of Object.keys(reservedParams)) {
|
|
7876
|
+
if (reserved in def.deps) throw new Error(`compute(): dependency "${reserved}" collides with the reserved service param of the same name — rename the dependency.`);
|
|
7877
|
+
if (reserved in userParams) throw new Error(`compute(): param "${reserved}" collides with the reserved service param of the same name — rename the param.`);
|
|
7878
|
+
}
|
|
7879
|
+
for (const name of Object.keys(userParams)) if (name.toUpperCase() === "ORIGIN") throw new Error(`compute(): param "${name}" collides with the framework-written origin row — rename the param.`);
|
|
7880
|
+
for (const name of Object.keys(def.secrets ?? {})) if (name.toUpperCase() === "ORIGIN") throw new Error(`compute(): secret "${name}" collides with the framework-written origin row — rename the secret.`);
|
|
7881
|
+
const params = blindCast({
|
|
7882
|
+
...userParams,
|
|
7883
|
+
...reservedParams
|
|
7884
|
+
});
|
|
7904
7885
|
const instance = new ComputeService(service$1({
|
|
7905
7886
|
name: def.name,
|
|
7906
7887
|
extension: "@prisma/composer-prisma-cloud",
|
|
7907
7888
|
type: "compute",
|
|
7908
7889
|
inputs: def.deps,
|
|
7909
|
-
params
|
|
7910
|
-
...def.
|
|
7890
|
+
params,
|
|
7891
|
+
...def.secrets !== void 0 ? { secrets: def.secrets } : {},
|
|
7911
7892
|
build: def.build,
|
|
7912
7893
|
...def.expose !== void 0 ? { expose: def.expose } : {}
|
|
7913
7894
|
}));
|
|
@@ -7958,25 +7939,25 @@ function parseEvery(s) {
|
|
|
7958
7939
|
}
|
|
7959
7940
|
/**
|
|
7960
7941
|
* The reusable scheduler node and its firing logic. `cronScheduler` builds a
|
|
7961
|
-
* `compute()` whose
|
|
7962
|
-
*
|
|
7963
|
-
*
|
|
7964
|
-
*
|
|
7942
|
+
* `compute()` whose `jobs` param default is the app's schedule and whose only
|
|
7943
|
+
* dependency is `trigger(jobId)`; nothing else about it varies per app.
|
|
7944
|
+
* `runScheduler` is the pure, injectable firing loop the entrypoint (and its
|
|
7945
|
+
* tests) drive.
|
|
7965
7946
|
*/
|
|
7966
|
-
const
|
|
7947
|
+
const scheduleSchema = type({
|
|
7967
7948
|
jobId: "string",
|
|
7968
7949
|
every: "string"
|
|
7969
|
-
}).array()
|
|
7950
|
+
}).array();
|
|
7970
7951
|
/**
|
|
7971
|
-
* The always-on scheduler service.
|
|
7972
|
-
*
|
|
7973
|
-
*
|
|
7952
|
+
* The always-on scheduler service. `schedule` sets only the `jobs` param's
|
|
7953
|
+
* default — the value the deploy serializes into config; the scheduler
|
|
7954
|
+
* itself is job-agnostic.
|
|
7974
7955
|
*/
|
|
7975
|
-
function cronScheduler() {
|
|
7956
|
+
function cronScheduler(schedule) {
|
|
7976
7957
|
return compute({
|
|
7977
7958
|
name: "scheduler",
|
|
7978
7959
|
deps: { trigger: rpc(triggerContract) },
|
|
7979
|
-
|
|
7960
|
+
params: { jobs: param(scheduleSchema, { default: [...schedule.jobs] }) },
|
|
7980
7961
|
build: nodeBuild({
|
|
7981
7962
|
module: new URL("./scheduler-service.mjs", import.meta.url).href,
|
|
7982
7963
|
entry: "./scheduler-entrypoint.mjs"
|
|
@@ -7997,9 +7978,9 @@ function runScheduler(opts) {
|
|
|
7997
7978
|
});
|
|
7998
7979
|
}, parseEvery(job.every));
|
|
7999
7980
|
}
|
|
8000
|
-
const service = cronScheduler();
|
|
7981
|
+
const service = cronScheduler({ jobs: [] });
|
|
8001
7982
|
const { trigger } = service.load();
|
|
8002
|
-
const { jobs } = service.
|
|
7983
|
+
const { jobs } = service.config();
|
|
8003
7984
|
runScheduler({
|
|
8004
7985
|
jobs,
|
|
8005
7986
|
call: (jobId) => trigger.trigger({ jobId })
|