@prisma/composer-prisma-cloud 0.3.0-dev.6 → 0.3.0-dev.8
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/control.d.mts +1 -1
- package/dist/control.mjs +28 -17
- package/dist/control.mjs.map +1 -1
- package/dist/cron/index.d.mts +33 -26
- package/dist/cron/index.d.mts.map +1 -1
- package/dist/cron/index.mjs +202 -77
- package/dist/cron/index.mjs.map +1 -1
- package/dist/cron/scheduler-entrypoint.mjs +133 -114
- package/dist/cron/scheduler-entrypoint.mjs.map +1 -1
- package/dist/cron/scheduler-service.mjs +200 -76
- package/dist/cron/scheduler-service.mjs.map +1 -1
- package/dist/email/email-entrypoint.mjs +162 -126
- package/dist/email/email-entrypoint.mjs.map +1 -1
- package/dist/email/email-service.mjs +230 -79
- package/dist/email/email-service.mjs.map +1 -1
- package/dist/email/index.d.mts +33 -29
- package/dist/email/index.d.mts.map +1 -1
- package/dist/email/index.mjs +236 -84
- package/dist/email/index.mjs.map +1 -1
- package/dist/email/testing.mjs +112 -89
- package/dist/email/testing.mjs.map +1 -1
- package/dist/index.d.mts +51 -43
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +47 -51
- package/dist/index.mjs.map +1 -1
- package/dist/local-target.mjs +1 -1
- package/dist/local-target.mjs.map +1 -1
- package/dist/{preflight-names-BPL-qsZF-BfoRgbgb.mjs → preflight-names-CpJUd9ZA-BCU-W3cT.mjs} +30 -14
- package/dist/{preflight-names-BPL-qsZF-BfoRgbgb.mjs.map → preflight-names-CpJUd9ZA-BCU-W3cT.mjs.map} +1 -1
- package/dist/{provisioned-edges-C1wSO3cx-YC5C19f9.mjs → provisioned-edges-Cxy18aoh-CUnaY96r.mjs} +3 -3
- package/dist/{provisioned-edges-C1wSO3cx-YC5C19f9.mjs.map → provisioned-edges-Cxy18aoh-CUnaY96r.mjs.map} +1 -1
- package/dist/{param-BTzY0ne5-CW6ojZ3E.mjs → secret-BVGxqHxY-DYDfiULl.mjs} +45 -4
- package/dist/secret-BVGxqHxY-DYDfiULl.mjs.map +1 -0
- package/dist/{serializer-Cx5slrV4-xJfH6EWS.d.mts → serializer-BD_6nkr4-DWn5NNTC.d.mts} +2 -2
- package/dist/serializer-BD_6nkr4-DWn5NNTC.d.mts.map +1 -0
- package/dist/serializer-sVE4UAmg-CikRngbR.mjs +475 -0
- package/dist/serializer-sVE4UAmg-CikRngbR.mjs.map +1 -0
- package/dist/storage/index.d.mts +31 -26
- package/dist/storage/index.d.mts.map +1 -1
- package/dist/storage/index.mjs +215 -89
- package/dist/storage/index.mjs.map +1 -1
- package/dist/storage/storage-entrypoint.mjs +147 -122
- package/dist/storage/storage-entrypoint.mjs.map +1 -1
- package/dist/storage/storage-service.mjs +212 -87
- package/dist/storage/storage-service.mjs.map +1 -1
- package/dist/streams/index.d.mts +29 -22
- package/dist/streams/index.d.mts.map +1 -1
- package/dist/streams/index.mjs +213 -88
- package/dist/streams/index.mjs.map +1 -1
- package/dist/streams/streams-entrypoint.mjs +139 -118
- package/dist/streams/streams-entrypoint.mjs.map +1 -1
- package/dist/streams/streams-service.mjs +212 -87
- package/dist/streams/streams-service.mjs.map +1 -1
- package/dist/testing.d.mts +19 -5
- package/dist/testing.d.mts.map +1 -1
- package/dist/testing.mjs +11 -3
- package/dist/testing.mjs.map +1 -1
- package/package.json +17 -17
- package/dist/param-BTzY0ne5-CW6ojZ3E.mjs.map +0 -1
- package/dist/secret-rz_ZqNeq-_xd97Jd9.mjs +0 -47
- package/dist/secret-rz_ZqNeq-_xd97Jd9.mjs.map +0 -1
- package/dist/serializer-CJiOhF2d-DJUjQj1i.mjs +0 -251
- package/dist/serializer-CJiOhF2d-DJUjQj1i.mjs.map +0 -1
- package/dist/serializer-Cx5slrV4-xJfH6EWS.d.mts.map +0 -1
|
@@ -1,4 +1,11 @@
|
|
|
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
|
+
});
|
|
2
9
|
/**
|
|
3
10
|
* **Last-resort escape hatch for unsafe type assertions. Not a sanctioned tool to reach for.**
|
|
4
11
|
*
|
|
@@ -80,18 +87,14 @@ function freezeParams(params) {
|
|
|
80
87
|
for (const [name, param] of Object.entries(params)) frozen[name] = Object.freeze({ ...param });
|
|
81
88
|
return Object.freeze(frozen);
|
|
82
89
|
}
|
|
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
|
-
}
|
|
88
90
|
/** A frozen shallow copy that keeps the caller's declared type. */
|
|
89
91
|
function frozenShallowCopy(obj) {
|
|
90
92
|
return blindCast(Object.freeze({ ...obj }));
|
|
91
93
|
}
|
|
92
94
|
/**
|
|
93
95
|
* Constructs a branded, frozen Service node — declarations only (inputs,
|
|
94
|
-
* params, build adapter, and the ports it exposes). Pure;
|
|
96
|
+
* params, the input schema, build adapter, and the ports it exposes). Pure;
|
|
97
|
+
* carries no runtime behavior.
|
|
95
98
|
*/
|
|
96
99
|
function service$1(def) {
|
|
97
100
|
requireName(def.name, "service");
|
|
@@ -99,8 +102,7 @@ function service$1(def) {
|
|
|
99
102
|
requireType(def.type, "service");
|
|
100
103
|
requireConfigKeySegmentNames(Object.keys(def.inputs), "input", "service");
|
|
101
104
|
requireConfigKeySegmentNames(Object.keys(def.params), "param", "service");
|
|
102
|
-
|
|
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.`);
|
|
105
|
+
if (def.input !== void 0 && typeof def.input["~standard"]?.validate !== "function") throw new Error("service() `input` must be a Standard Schema (an object with a \"~standard\".validate function) — see https://standardschema.dev (ADR-0042).");
|
|
104
106
|
return Object.freeze({
|
|
105
107
|
[NODE]: true,
|
|
106
108
|
kind: "service",
|
|
@@ -109,7 +111,7 @@ function service$1(def) {
|
|
|
109
111
|
type: def.type,
|
|
110
112
|
inputs: frozenShallowCopy(def.inputs),
|
|
111
113
|
params: freezeParams(def.params),
|
|
112
|
-
|
|
114
|
+
inputSchema: blindCast(def.input),
|
|
113
115
|
build: Object.freeze({ ...def.build }),
|
|
114
116
|
expose: def.expose !== void 0 ? frozenShallowCopy(def.expose) : void 0
|
|
115
117
|
});
|
|
@@ -142,11 +144,16 @@ function dependency(def) {
|
|
|
142
144
|
* `JSON.stringify`, and `console.log`/`util.inspect` all print `[REDACTED]`, so
|
|
143
145
|
* a secret can't leak through an accidental log or serialization.
|
|
144
146
|
*
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
+
* Every box carries a brand property keyed by the registered symbol
|
|
148
|
+
* `Symbol.for('prisma:secret-box')`, which is what `isSecretString` checks. A
|
|
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).
|
|
147
152
|
*/
|
|
148
153
|
const REDACTED = "[REDACTED]";
|
|
154
|
+
const SECRET_BOX = blindCast(Symbol.for("prisma:secret-box"));
|
|
149
155
|
var SecretBox = class {
|
|
156
|
+
[SECRET_BOX] = true;
|
|
150
157
|
#value;
|
|
151
158
|
constructor(value) {
|
|
152
159
|
this.#value = value;
|
|
@@ -196,10 +203,6 @@ function string$1(opts = {}) {
|
|
|
196
203
|
function number$1(opts = {}) {
|
|
197
204
|
return withFacets(numberSchema, opts);
|
|
198
205
|
}
|
|
199
|
-
/** A param over any caller-supplied Standard Schema — a structured `jobs`, say. */
|
|
200
|
-
function param(schema, opts = {}) {
|
|
201
|
-
return withFacets(schema, opts);
|
|
202
|
-
}
|
|
203
206
|
/**
|
|
204
207
|
* Synchronous hydrate — what the node's `load()` uses so
|
|
205
208
|
* `const { db } = service.load()` reads without `await`. Requires every
|
|
@@ -216,31 +219,6 @@ function hydrateSync(root, config) {
|
|
|
216
219
|
}
|
|
217
220
|
return deps;
|
|
218
221
|
}
|
|
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
|
-
});
|
|
244
222
|
const liftArray = (data) => Array.isArray(data) ? data : [data];
|
|
245
223
|
/**
|
|
246
224
|
* Splits an array into two arrays based on the result of a predicate
|
|
@@ -7448,7 +7426,7 @@ function coerceEnvSourcedParam(raw, d, key) {
|
|
|
7448
7426
|
/**
|
|
7449
7427
|
* Boot: read each declared param from env by its key, reverse the param's own
|
|
7450
7428
|
* serialization (missing/invalid fails loudly), assemble the typed Config.
|
|
7451
|
-
*
|
|
7429
|
+
* The input document rides its own channel (readInput), not this one.
|
|
7452
7430
|
*/
|
|
7453
7431
|
const deserialize = (node, address) => {
|
|
7454
7432
|
const service = {};
|
|
@@ -7485,40 +7463,84 @@ const stash = (node, config) => {
|
|
|
7485
7463
|
process.env[configKey("", d)] = encode(d.owner, value);
|
|
7486
7464
|
}
|
|
7487
7465
|
};
|
|
7488
|
-
/** The
|
|
7489
|
-
const
|
|
7466
|
+
/** The input document's own row name; its full key is COMPOSER_<addr>_INPUT. */
|
|
7467
|
+
const INPUT_KEY_NAME = "INPUT";
|
|
7468
|
+
/** The input document row's key for a service address. */
|
|
7469
|
+
const inputKey = (address) => configKey(address, {
|
|
7490
7470
|
owner: "service",
|
|
7491
|
-
name:
|
|
7471
|
+
name: INPUT_KEY_NAME
|
|
7492
7472
|
});
|
|
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
|
+
}
|
|
7493
7485
|
/**
|
|
7494
|
-
* Boot:
|
|
7495
|
-
*
|
|
7496
|
-
*
|
|
7497
|
-
*
|
|
7486
|
+
* Boot: read the one input document row (address-free after run()'s
|
|
7487
|
+
* re-stash), swap each `$secret` pointer for a redacting box over the named
|
|
7488
|
+
* platform var, unescape reserved keys, validate with the service's own
|
|
7489
|
+
* schema, and return the typed object. A missing row is a loud failure naming
|
|
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).
|
|
7498
7492
|
*/
|
|
7499
|
-
|
|
7500
|
-
const
|
|
7501
|
-
|
|
7502
|
-
|
|
7503
|
-
|
|
7504
|
-
|
|
7505
|
-
|
|
7506
|
-
|
|
7507
|
-
|
|
7508
|
-
}
|
|
7509
|
-
|
|
7510
|
-
};
|
|
7493
|
+
function readInput(node, address) {
|
|
7494
|
+
const schema = node.inputSchema;
|
|
7495
|
+
if (schema === void 0) throw new Error(`input() called on service "${node.name}", which declares no input schema — declare \`input: <schema>\` on compute() to use it (ADR-0042).`);
|
|
7496
|
+
const key = inputKey(address);
|
|
7497
|
+
const raw = process.env[key];
|
|
7498
|
+
if (raw === void 0 || raw === "") throw new Error(`this service's input is not available (env ${key} is unset) — a deployed environment writes it automatically; a local harness must supply it like any other config value (set ${key} to the serialized input document).`);
|
|
7499
|
+
let parsed;
|
|
7500
|
+
try {
|
|
7501
|
+
parsed = JSON.parse(raw);
|
|
7502
|
+
} catch (cause) {
|
|
7503
|
+
const message = cause instanceof Error ? cause.message : String(cause);
|
|
7504
|
+
throw new Error(`this service's input document is not valid JSON (env ${key}): ${message} — a deployed environment writes it automatically; a local harness must supply the serialized input document (set ${key} to it).`);
|
|
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
|
+
}
|
|
7511
7533
|
/**
|
|
7512
|
-
* run()'s setup step for
|
|
7513
|
-
* address-free key, so the address-free `
|
|
7514
|
-
*
|
|
7534
|
+
* run()'s setup step for the input document: re-emit the row under its
|
|
7535
|
+
* address-free key, so the address-free `readInput` reads identically. The
|
|
7536
|
+
* document carries pointers, never values — the values stay only in their
|
|
7537
|
+
* platform vars.
|
|
7515
7538
|
*/
|
|
7516
|
-
const
|
|
7517
|
-
|
|
7518
|
-
|
|
7519
|
-
|
|
7520
|
-
|
|
7521
|
-
}
|
|
7539
|
+
const stashInput = (node, address) => {
|
|
7540
|
+
if (node.inputSchema === void 0) return;
|
|
7541
|
+
const raw = process.env[inputKey(address)];
|
|
7542
|
+
if (raw === void 0) return;
|
|
7543
|
+
process.env[inputKey("")] = raw;
|
|
7522
7544
|
};
|
|
7523
7545
|
/**
|
|
7524
7546
|
* Boot: for each reserved provider param, read its address-scoped row through
|
|
@@ -7808,20 +7830,24 @@ Object.freeze({
|
|
|
7808
7830
|
});
|
|
7809
7831
|
const reservedParams = { port: number$1({ default: 3e3 }) };
|
|
7810
7832
|
/**
|
|
7811
|
-
* A Prisma Compute service — declarations only (deps +
|
|
7812
|
-
* ports it exposes), no descriptor. `
|
|
7813
|
-
*
|
|
7814
|
-
*
|
|
7833
|
+
* A Prisma Compute service — declarations only (deps + one input schema +
|
|
7834
|
+
* build + the ports it exposes), no descriptor. The reserved `port` param
|
|
7835
|
+
* rides its own channel (ADR-0042 leaves it untouched); a dependency named
|
|
7836
|
+
* like it fails at authoring.
|
|
7815
7837
|
*
|
|
7816
7838
|
* · run(address, boot) — the process controller: deserialize the platform
|
|
7817
7839
|
* environment (keyed off `address`, the extension's ONE env read) into a
|
|
7818
|
-
* typed Config, re-emit it under address-free
|
|
7819
|
-
* then call boot() to start the app's entry.
|
|
7820
|
-
* · load() /
|
|
7821
|
-
* load() hydrates + memoizes the deps,
|
|
7822
|
-
*
|
|
7840
|
+
* typed Config, re-emit it (and the input document row) under address-free
|
|
7841
|
+
* process-local stash keys, then call boot() to start the app's entry.
|
|
7842
|
+
* · load() / input() — called from inside the app's entry: read the stash;
|
|
7843
|
+
* load() hydrates + memoizes the deps, input() parses the input document,
|
|
7844
|
+
* replaces each `$secret` pointer with a redacting box over the named
|
|
7845
|
+
* platform var, validates with the declared schema, and memoizes (ADR-0042).
|
|
7823
7846
|
* · origin() — this service's platform-assigned public origin, read from the
|
|
7824
7847
|
* 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.
|
|
7825
7851
|
*
|
|
7826
7852
|
* The underlying node carries `extension: '@prisma/composer-prisma-cloud'` —
|
|
7827
7853
|
* the control-plane registry key `prisma-composer deploy` resolves through the
|
|
@@ -7831,8 +7857,7 @@ const reservedParams = { port: number$1({ default: 3e3 }) };
|
|
|
7831
7857
|
var ComputeService = class {
|
|
7832
7858
|
#resolved;
|
|
7833
7859
|
#loadedDeps;
|
|
7834
|
-
#
|
|
7835
|
-
#loadedSecrets;
|
|
7860
|
+
#loadedInput;
|
|
7836
7861
|
#origin;
|
|
7837
7862
|
constructor(node) {
|
|
7838
7863
|
Object.assign(this, node);
|
|
@@ -7845,7 +7870,7 @@ var ComputeService = class {
|
|
|
7845
7870
|
const config = deserialize(this, address);
|
|
7846
7871
|
stash(this, config);
|
|
7847
7872
|
stashProviderParams(RESERVED_PROVIDER_PARAMS, address);
|
|
7848
|
-
|
|
7873
|
+
stashInput(this, address);
|
|
7849
7874
|
const port = config.service["port"];
|
|
7850
7875
|
if (typeof port === "number") process.env["PORT"] = String(port);
|
|
7851
7876
|
return boot();
|
|
@@ -7854,13 +7879,9 @@ var ComputeService = class {
|
|
|
7854
7879
|
if (this.#loadedDeps === void 0) this.#loadedDeps = blindCast(hydrateSync(this, this.#processConfig()));
|
|
7855
7880
|
return this.#loadedDeps;
|
|
7856
7881
|
}
|
|
7857
|
-
|
|
7858
|
-
if (this.#
|
|
7859
|
-
return this.#
|
|
7860
|
-
}
|
|
7861
|
-
secrets() {
|
|
7862
|
-
if (this.#loadedSecrets === void 0) this.#loadedSecrets = blindCast(hydrateSecrets(this, deserializeSecrets(this, "")));
|
|
7863
|
-
return this.#loadedSecrets;
|
|
7882
|
+
input() {
|
|
7883
|
+
if (this.#loadedInput === void 0) this.#loadedInput = blindCast(readInput(this, ""));
|
|
7884
|
+
return this.#loadedInput;
|
|
7864
7885
|
}
|
|
7865
7886
|
/** This service's platform-assigned public origin — read from the stash
|
|
7866
7887
|
* run() populates and memoized per process. Throws if called before run()
|
|
@@ -7869,26 +7890,24 @@ var ComputeService = class {
|
|
|
7869
7890
|
this.#origin ??= readOrigin();
|
|
7870
7891
|
return this.#origin;
|
|
7871
7892
|
}
|
|
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
|
+
}
|
|
7872
7901
|
};
|
|
7873
7902
|
const compute = (def) => {
|
|
7874
|
-
const
|
|
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
|
-
});
|
|
7903
|
+
for (const reserved of Object.keys(reservedParams)) if (reserved in def.deps) throw new Error(`compute(): dependency "${reserved}" collides with the reserved service param of the same name — rename the dependency.`);
|
|
7885
7904
|
const instance = new ComputeService(service$1({
|
|
7886
7905
|
name: def.name,
|
|
7887
7906
|
extension: "@prisma/composer-prisma-cloud",
|
|
7888
7907
|
type: "compute",
|
|
7889
7908
|
inputs: def.deps,
|
|
7890
|
-
params,
|
|
7891
|
-
...def.
|
|
7909
|
+
params: reservedParams,
|
|
7910
|
+
...def.input !== void 0 ? { input: def.input } : {},
|
|
7892
7911
|
build: def.build,
|
|
7893
7912
|
...def.expose !== void 0 ? { expose: def.expose } : {}
|
|
7894
7913
|
}));
|
|
@@ -7939,25 +7958,25 @@ function parseEvery(s) {
|
|
|
7939
7958
|
}
|
|
7940
7959
|
/**
|
|
7941
7960
|
* The reusable scheduler node and its firing logic. `cronScheduler` builds a
|
|
7942
|
-
* `compute()` whose
|
|
7943
|
-
* dependency is `trigger(jobId)`; nothing
|
|
7944
|
-
* `runScheduler` is the pure, injectable firing
|
|
7945
|
-
* tests) drive.
|
|
7961
|
+
* `compute()` whose one input is the `jobs` schedule (bound at provision by
|
|
7962
|
+
* `cron()`, ADR-0042) and whose only dependency is `trigger(jobId)`; nothing
|
|
7963
|
+
* else about it varies per app. `runScheduler` is the pure, injectable firing
|
|
7964
|
+
* loop the entrypoint (and its tests) drive.
|
|
7946
7965
|
*/
|
|
7947
|
-
const
|
|
7966
|
+
const cronInputSchema = type({ jobs: type({
|
|
7948
7967
|
jobId: "string",
|
|
7949
7968
|
every: "string"
|
|
7950
|
-
}).array();
|
|
7969
|
+
}).array() });
|
|
7951
7970
|
/**
|
|
7952
|
-
* The always-on scheduler service.
|
|
7953
|
-
*
|
|
7954
|
-
*
|
|
7971
|
+
* The always-on scheduler service. Job-agnostic: the schedule arrives as the
|
|
7972
|
+
* `jobs` key of the input binding `cron()` supplies at provision, and the
|
|
7973
|
+
* entrypoint reads it back through `input()`.
|
|
7955
7974
|
*/
|
|
7956
|
-
function cronScheduler(
|
|
7975
|
+
function cronScheduler() {
|
|
7957
7976
|
return compute({
|
|
7958
7977
|
name: "scheduler",
|
|
7959
7978
|
deps: { trigger: rpc(triggerContract) },
|
|
7960
|
-
|
|
7979
|
+
input: cronInputSchema,
|
|
7961
7980
|
build: nodeBuild({
|
|
7962
7981
|
module: new URL("./scheduler-service.mjs", import.meta.url).href,
|
|
7963
7982
|
entry: "./scheduler-entrypoint.mjs"
|
|
@@ -7978,9 +7997,9 @@ function runScheduler(opts) {
|
|
|
7978
7997
|
});
|
|
7979
7998
|
}, parseEvery(job.every));
|
|
7980
7999
|
}
|
|
7981
|
-
const service = cronScheduler(
|
|
8000
|
+
const service = cronScheduler();
|
|
7982
8001
|
const { trigger } = service.load();
|
|
7983
|
-
const { jobs } = service.
|
|
8002
|
+
const { jobs } = service.input();
|
|
7984
8003
|
runScheduler({
|
|
7985
8004
|
jobs,
|
|
7986
8005
|
call: (jobId) => trigger.trigger({ jobId })
|