@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
|
@@ -508,6 +508,13 @@ function startStorageServer(opts) {
|
|
|
508
508
|
stop: () => server.stop(true)
|
|
509
509
|
};
|
|
510
510
|
}
|
|
511
|
+
const nodeBuild = (opts) => ({
|
|
512
|
+
extension: "@prisma/composer/node",
|
|
513
|
+
type: "node",
|
|
514
|
+
module: opts.module,
|
|
515
|
+
entry: opts.entry,
|
|
516
|
+
...opts.dir === void 0 ? {} : { dir: opts.dir }
|
|
517
|
+
});
|
|
511
518
|
/**
|
|
512
519
|
* **Last-resort escape hatch for unsafe type assertions. Not a sanctioned tool to reach for.**
|
|
513
520
|
*
|
|
@@ -580,11 +587,6 @@ function freezeParams(params) {
|
|
|
580
587
|
for (const [name, param] of Object.entries(params)) frozen[name] = Object.freeze({ ...param });
|
|
581
588
|
return Object.freeze(frozen);
|
|
582
589
|
}
|
|
583
|
-
function freezeSecrets(secrets) {
|
|
584
|
-
const frozen = {};
|
|
585
|
-
for (const [name, need] of Object.entries(secrets)) frozen[name] = Object.freeze({ ...need });
|
|
586
|
-
return blindCast(Object.freeze(frozen));
|
|
587
|
-
}
|
|
588
590
|
/** A frozen shallow copy that keeps the caller's declared type. */
|
|
589
591
|
function frozenShallowCopy(obj) {
|
|
590
592
|
return blindCast(Object.freeze({ ...obj }));
|
|
@@ -638,7 +640,8 @@ function resource(def) {
|
|
|
638
640
|
}
|
|
639
641
|
/**
|
|
640
642
|
* Constructs a branded, frozen Service node — declarations only (inputs,
|
|
641
|
-
* params, build adapter, and the ports it exposes). Pure;
|
|
643
|
+
* params, the input schema, build adapter, and the ports it exposes). Pure;
|
|
644
|
+
* carries no runtime behavior.
|
|
642
645
|
*/
|
|
643
646
|
function service$1(def) {
|
|
644
647
|
requireName(def.name, "service");
|
|
@@ -646,8 +649,7 @@ function service$1(def) {
|
|
|
646
649
|
requireType(def.type, "service");
|
|
647
650
|
requireConfigKeySegmentNames(Object.keys(def.inputs), "input", "service");
|
|
648
651
|
requireConfigKeySegmentNames(Object.keys(def.params), "param", "service");
|
|
649
|
-
|
|
650
|
-
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.`);
|
|
652
|
+
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).");
|
|
651
653
|
return Object.freeze({
|
|
652
654
|
[NODE]: true,
|
|
653
655
|
kind: "service",
|
|
@@ -656,7 +658,7 @@ function service$1(def) {
|
|
|
656
658
|
type: def.type,
|
|
657
659
|
inputs: frozenShallowCopy(def.inputs),
|
|
658
660
|
params: freezeParams(def.params),
|
|
659
|
-
|
|
661
|
+
inputSchema: blindCast(def.input),
|
|
660
662
|
build: Object.freeze({ ...def.build }),
|
|
661
663
|
expose: def.expose !== void 0 ? frozenShallowCopy(def.expose) : void 0
|
|
662
664
|
});
|
|
@@ -689,11 +691,16 @@ function dependency(def) {
|
|
|
689
691
|
* `JSON.stringify`, and `console.log`/`util.inspect` all print `[REDACTED]`, so
|
|
690
692
|
* a secret can't leak through an accidental log or serialization.
|
|
691
693
|
*
|
|
692
|
-
*
|
|
693
|
-
*
|
|
694
|
+
* Every box carries a brand property keyed by the registered symbol
|
|
695
|
+
* `Symbol.for('prisma:secret-box')`, which is what `isSecretString` checks. A
|
|
696
|
+
* symbol key is invisible to `JSON.stringify` and `Object.keys`, so the box's
|
|
697
|
+
* public shape still matches the platform's own `secrecy` type
|
|
698
|
+
* (pdp-control-plane).
|
|
694
699
|
*/
|
|
695
700
|
const REDACTED = "[REDACTED]";
|
|
701
|
+
const SECRET_BOX = blindCast(Symbol.for("prisma:secret-box"));
|
|
696
702
|
var SecretBox = class {
|
|
703
|
+
[SECRET_BOX] = true;
|
|
697
704
|
#value;
|
|
698
705
|
constructor(value) {
|
|
699
706
|
this.#value = value;
|
|
@@ -759,31 +766,6 @@ function hydrateSync(root, config) {
|
|
|
759
766
|
}
|
|
760
767
|
return deps;
|
|
761
768
|
}
|
|
762
|
-
/**
|
|
763
|
-
* Wraps each of a service's resolved secret values in a redacting `SecretBox`
|
|
764
|
-
* — what the node's `secrets()` accessor returns (ADR-0021, sibling to
|
|
765
|
-
* `load()`/`config()`). The RESOLUTION of a secret's value (the boot
|
|
766
|
-
* double-lookup that reads the platform var the pointer names) is the target
|
|
767
|
-
* pack's job; core is handed the already-resolved strings and only boxes them,
|
|
768
|
-
* so a secret is redacted by TYPE from here on. A declared slot missing from
|
|
769
|
-
* `values` is a target contract violation, named loudly.
|
|
770
|
-
*/
|
|
771
|
-
function hydrateSecrets(root, values) {
|
|
772
|
-
const boxed = {};
|
|
773
|
-
for (const slot of Object.keys(root.secretSlots)) {
|
|
774
|
-
const value = values[slot];
|
|
775
|
-
if (value === void 0) throw new Error(`secret slot "${slot}" has no resolved value — the target must resolve every declared secret before hydrateSecrets().`);
|
|
776
|
-
boxed[slot] = new SecretBox(value);
|
|
777
|
-
}
|
|
778
|
-
return blindCast(boxed);
|
|
779
|
-
}
|
|
780
|
-
const nodeBuild = (opts) => ({
|
|
781
|
-
extension: "@prisma/composer/node",
|
|
782
|
-
type: "node",
|
|
783
|
-
module: opts.module,
|
|
784
|
-
entry: opts.entry,
|
|
785
|
-
...opts.dir === void 0 ? {} : { dir: opts.dir }
|
|
786
|
-
});
|
|
787
769
|
const liftArray = (data) => Array.isArray(data) ? data : [data];
|
|
788
770
|
/**
|
|
789
771
|
* Splits an array into two arrays based on the result of a predicate
|
|
@@ -7991,7 +7973,7 @@ function coerceEnvSourcedParam(raw, d, key) {
|
|
|
7991
7973
|
/**
|
|
7992
7974
|
* Boot: read each declared param from env by its key, reverse the param's own
|
|
7993
7975
|
* serialization (missing/invalid fails loudly), assemble the typed Config.
|
|
7994
|
-
*
|
|
7976
|
+
* The input document rides its own channel (readInput), not this one.
|
|
7995
7977
|
*/
|
|
7996
7978
|
const deserialize = (node, address) => {
|
|
7997
7979
|
const service = {};
|
|
@@ -8028,40 +8010,84 @@ const stash = (node, config) => {
|
|
|
8028
8010
|
process.env[configKey("", d)] = encode(d.owner, value);
|
|
8029
8011
|
}
|
|
8030
8012
|
};
|
|
8031
|
-
/** The
|
|
8032
|
-
const
|
|
8013
|
+
/** The input document's own row name; its full key is COMPOSER_<addr>_INPUT. */
|
|
8014
|
+
const INPUT_KEY_NAME = "INPUT";
|
|
8015
|
+
/** The input document row's key for a service address. */
|
|
8016
|
+
const inputKey = (address) => configKey(address, {
|
|
8033
8017
|
owner: "service",
|
|
8034
|
-
name:
|
|
8018
|
+
name: INPUT_KEY_NAME
|
|
8035
8019
|
});
|
|
8020
|
+
const SECRET_MARKER = "$secret";
|
|
8021
|
+
const ESCAPED_KEY = /^\$\$+secret$/;
|
|
8022
|
+
/** True for the framework's secret pointer: `{ "$secret": "<PLATFORM_VAR>" }` and nothing else. */
|
|
8023
|
+
function isSecretPointer(value) {
|
|
8024
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) && Object.keys(value).length === 1 && SECRET_MARKER in value && typeof value[SECRET_MARKER] === "string";
|
|
8025
|
+
}
|
|
8026
|
+
/** A plain data object (not an array, not a class instance) — the only object shape a binding/document may nest. */
|
|
8027
|
+
function isPlainObject(value) {
|
|
8028
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
8029
|
+
const proto = Object.getPrototypeOf(value);
|
|
8030
|
+
return proto === Object.prototype || proto === null;
|
|
8031
|
+
}
|
|
8036
8032
|
/**
|
|
8037
|
-
* Boot:
|
|
8038
|
-
*
|
|
8039
|
-
*
|
|
8040
|
-
*
|
|
8033
|
+
* Boot: read the one input document row (address-free after run()'s
|
|
8034
|
+
* re-stash), swap each `$secret` pointer for a redacting box over the named
|
|
8035
|
+
* platform var, unescape reserved keys, validate with the service's own
|
|
8036
|
+
* schema, and return the typed object. A missing row is a loud failure naming
|
|
8037
|
+
* the env var — a deployed environment always writes it; a local harness must
|
|
8038
|
+
* supply it (set the row to the serialized input document).
|
|
8041
8039
|
*/
|
|
8042
|
-
|
|
8043
|
-
const
|
|
8044
|
-
|
|
8045
|
-
|
|
8046
|
-
|
|
8047
|
-
|
|
8048
|
-
|
|
8049
|
-
|
|
8050
|
-
|
|
8051
|
-
}
|
|
8052
|
-
|
|
8053
|
-
};
|
|
8040
|
+
function readInput(node, address) {
|
|
8041
|
+
const schema = node.inputSchema;
|
|
8042
|
+
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).`);
|
|
8043
|
+
const key = inputKey(address);
|
|
8044
|
+
const raw = process.env[key];
|
|
8045
|
+
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).`);
|
|
8046
|
+
let parsed;
|
|
8047
|
+
try {
|
|
8048
|
+
parsed = JSON.parse(raw);
|
|
8049
|
+
} catch (cause) {
|
|
8050
|
+
const message = cause instanceof Error ? cause.message : String(cause);
|
|
8051
|
+
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).`);
|
|
8052
|
+
}
|
|
8053
|
+
const hydrated = hydrateInputDocument(parsed, key);
|
|
8054
|
+
try {
|
|
8055
|
+
return standardValidateSync(schema, hydrated);
|
|
8056
|
+
} catch (cause) {
|
|
8057
|
+
const message = cause instanceof Error ? cause.message : String(cause);
|
|
8058
|
+
throw new Error(`invalid input document (env ${key}): ${message}`);
|
|
8059
|
+
}
|
|
8060
|
+
}
|
|
8061
|
+
/** Reverses the document encoding: `$secret` pointers become redacting boxes over the named platform vars; escaped reserved keys drop one "$". */
|
|
8062
|
+
function hydrateInputDocument(value, key) {
|
|
8063
|
+
if (isSecretPointer(value)) {
|
|
8064
|
+
const name = value[SECRET_MARKER];
|
|
8065
|
+
const secret = process.env[name];
|
|
8066
|
+
if (secret === void 0 || secret === "") throw new Error(`secret input is not provisioned (env ${key} → ${name}): the platform var "${name}" is unset or empty.`);
|
|
8067
|
+
return new SecretBox(secret);
|
|
8068
|
+
}
|
|
8069
|
+
if (Array.isArray(value)) return value.map((member) => hydrateInputDocument(member, key));
|
|
8070
|
+
if (isPlainObject(value)) {
|
|
8071
|
+
const out = {};
|
|
8072
|
+
for (const [k, member] of Object.entries(value)) {
|
|
8073
|
+
const read = ESCAPED_KEY.test(k) ? k.slice(1) : k;
|
|
8074
|
+
out[read] = hydrateInputDocument(member, key);
|
|
8075
|
+
}
|
|
8076
|
+
return out;
|
|
8077
|
+
}
|
|
8078
|
+
return value;
|
|
8079
|
+
}
|
|
8054
8080
|
/**
|
|
8055
|
-
* run()'s setup step for
|
|
8056
|
-
* address-free key, so the address-free `
|
|
8057
|
-
*
|
|
8081
|
+
* run()'s setup step for the input document: re-emit the row under its
|
|
8082
|
+
* address-free key, so the address-free `readInput` reads identically. The
|
|
8083
|
+
* document carries pointers, never values — the values stay only in their
|
|
8084
|
+
* platform vars.
|
|
8058
8085
|
*/
|
|
8059
|
-
const
|
|
8060
|
-
|
|
8061
|
-
|
|
8062
|
-
|
|
8063
|
-
|
|
8064
|
-
}
|
|
8086
|
+
const stashInput = (node, address) => {
|
|
8087
|
+
if (node.inputSchema === void 0) return;
|
|
8088
|
+
const raw = process.env[inputKey(address)];
|
|
8089
|
+
if (raw === void 0) return;
|
|
8090
|
+
process.env[inputKey("")] = raw;
|
|
8065
8091
|
};
|
|
8066
8092
|
/**
|
|
8067
8093
|
* Boot: for each reserved provider param, read its address-scoped row through
|
|
@@ -8244,20 +8270,24 @@ Object.freeze({
|
|
|
8244
8270
|
});
|
|
8245
8271
|
const reservedParams = { port: number$1({ default: 3e3 }) };
|
|
8246
8272
|
/**
|
|
8247
|
-
* A Prisma Compute service — declarations only (deps +
|
|
8248
|
-
* ports it exposes), no descriptor. `
|
|
8249
|
-
*
|
|
8250
|
-
*
|
|
8273
|
+
* A Prisma Compute service — declarations only (deps + one input schema +
|
|
8274
|
+
* build + the ports it exposes), no descriptor. The reserved `port` param
|
|
8275
|
+
* rides its own channel (ADR-0042 leaves it untouched); a dependency named
|
|
8276
|
+
* like it fails at authoring.
|
|
8251
8277
|
*
|
|
8252
8278
|
* · run(address, boot) — the process controller: deserialize the platform
|
|
8253
8279
|
* environment (keyed off `address`, the extension's ONE env read) into a
|
|
8254
|
-
* typed Config, re-emit it under address-free
|
|
8255
|
-
* then call boot() to start the app's entry.
|
|
8256
|
-
* · load() /
|
|
8257
|
-
* load() hydrates + memoizes the deps,
|
|
8258
|
-
*
|
|
8280
|
+
* typed Config, re-emit it (and the input document row) under address-free
|
|
8281
|
+
* process-local stash keys, then call boot() to start the app's entry.
|
|
8282
|
+
* · load() / input() — called from inside the app's entry: read the stash;
|
|
8283
|
+
* load() hydrates + memoizes the deps, input() parses the input document,
|
|
8284
|
+
* replaces each `$secret` pointer with a redacting box over the named
|
|
8285
|
+
* platform var, validates with the declared schema, and memoizes (ADR-0042).
|
|
8259
8286
|
* · origin() — this service's platform-assigned public origin, read from the
|
|
8260
8287
|
* stash `run()` populates; memoized per process.
|
|
8288
|
+
* · port() — this service's resolved reserved port (the value `run()` routes
|
|
8289
|
+
* to and exports as PORT), read from that same stash via #processConfig();
|
|
8290
|
+
* defaults to 3000 when the platform binds none.
|
|
8261
8291
|
*
|
|
8262
8292
|
* The underlying node carries `extension: '@prisma/composer-prisma-cloud'` —
|
|
8263
8293
|
* the control-plane registry key `prisma-composer deploy` resolves through the
|
|
@@ -8267,8 +8297,7 @@ const reservedParams = { port: number$1({ default: 3e3 }) };
|
|
|
8267
8297
|
var ComputeService = class {
|
|
8268
8298
|
#resolved;
|
|
8269
8299
|
#loadedDeps;
|
|
8270
|
-
#
|
|
8271
|
-
#loadedSecrets;
|
|
8300
|
+
#loadedInput;
|
|
8272
8301
|
#origin;
|
|
8273
8302
|
constructor(node) {
|
|
8274
8303
|
Object.assign(this, node);
|
|
@@ -8281,7 +8310,7 @@ var ComputeService = class {
|
|
|
8281
8310
|
const config = deserialize(this, address);
|
|
8282
8311
|
stash(this, config);
|
|
8283
8312
|
stashProviderParams(RESERVED_PROVIDER_PARAMS, address);
|
|
8284
|
-
|
|
8313
|
+
stashInput(this, address);
|
|
8285
8314
|
const port = config.service["port"];
|
|
8286
8315
|
if (typeof port === "number") process.env["PORT"] = String(port);
|
|
8287
8316
|
return boot();
|
|
@@ -8290,13 +8319,9 @@ var ComputeService = class {
|
|
|
8290
8319
|
if (this.#loadedDeps === void 0) this.#loadedDeps = blindCast(hydrateSync(this, this.#processConfig()));
|
|
8291
8320
|
return this.#loadedDeps;
|
|
8292
8321
|
}
|
|
8293
|
-
|
|
8294
|
-
if (this.#
|
|
8295
|
-
return this.#
|
|
8296
|
-
}
|
|
8297
|
-
secrets() {
|
|
8298
|
-
if (this.#loadedSecrets === void 0) this.#loadedSecrets = blindCast(hydrateSecrets(this, deserializeSecrets(this, "")));
|
|
8299
|
-
return this.#loadedSecrets;
|
|
8322
|
+
input() {
|
|
8323
|
+
if (this.#loadedInput === void 0) this.#loadedInput = blindCast(readInput(this, ""));
|
|
8324
|
+
return this.#loadedInput;
|
|
8300
8325
|
}
|
|
8301
8326
|
/** This service's platform-assigned public origin — read from the stash
|
|
8302
8327
|
* run() populates and memoized per process. Throws if called before run()
|
|
@@ -8305,26 +8330,24 @@ var ComputeService = class {
|
|
|
8305
8330
|
this.#origin ??= readOrigin();
|
|
8306
8331
|
return this.#origin;
|
|
8307
8332
|
}
|
|
8333
|
+
/** This service's resolved reserved port — the value run() routes to and
|
|
8334
|
+
* exports as PORT — read the same way load() reads the stash. Defaults to
|
|
8335
|
+
* 3000 when the platform binds none. */
|
|
8336
|
+
port() {
|
|
8337
|
+
const port = this.#processConfig().service["port"];
|
|
8338
|
+
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.`);
|
|
8339
|
+
return port;
|
|
8340
|
+
}
|
|
8308
8341
|
};
|
|
8309
8342
|
const compute = (def) => {
|
|
8310
|
-
const
|
|
8311
|
-
for (const reserved of Object.keys(reservedParams)) {
|
|
8312
|
-
if (reserved in def.deps) throw new Error(`compute(): dependency "${reserved}" collides with the reserved service param of the same name — rename the dependency.`);
|
|
8313
|
-
if (reserved in userParams) throw new Error(`compute(): param "${reserved}" collides with the reserved service param of the same name — rename the param.`);
|
|
8314
|
-
}
|
|
8315
|
-
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.`);
|
|
8316
|
-
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.`);
|
|
8317
|
-
const params = blindCast({
|
|
8318
|
-
...userParams,
|
|
8319
|
-
...reservedParams
|
|
8320
|
-
});
|
|
8343
|
+
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.`);
|
|
8321
8344
|
const instance = new ComputeService(service$1({
|
|
8322
8345
|
name: def.name,
|
|
8323
8346
|
extension: "@prisma/composer-prisma-cloud",
|
|
8324
8347
|
type: "compute",
|
|
8325
8348
|
inputs: def.deps,
|
|
8326
|
-
params,
|
|
8327
|
-
...def.
|
|
8349
|
+
params: reservedParams,
|
|
8350
|
+
...def.input !== void 0 ? { input: def.input } : {},
|
|
8328
8351
|
build: def.build,
|
|
8329
8352
|
...def.expose !== void 0 ? { expose: def.expose } : {}
|
|
8330
8353
|
}));
|
|
@@ -8392,21 +8415,21 @@ function s3Credentials(opts) {
|
|
|
8392
8415
|
/**
|
|
8393
8416
|
* The storage service authoring factory — a `compute` service routed to the
|
|
8394
8417
|
* `s3-store` lowering instead of `compute`'s. It is exactly `compute`'s
|
|
8395
|
-
* runnable (run/load/
|
|
8396
|
-
* `type` overridden to `'s3-store'`: nothing at runtime keys off
|
|
8397
|
-
* serializer keys off the deployment address and each param's
|
|
8398
|
-
* `load`/`
|
|
8399
|
-
* sees the override and routes to the
|
|
8400
|
-
* return type is compute's exactly
|
|
8401
|
-
* storage module (D4b) calls this
|
|
8402
|
-
*
|
|
8418
|
+
* runnable (run/load/input, deps, input schema, build, expose) with the
|
|
8419
|
+
* routing `type` overridden to `'s3-store'`: nothing at runtime keys off
|
|
8420
|
+
* `type` (the serializer keys off the deployment address and each param's
|
|
8421
|
+
* owner/name, and `load`/`input` off deps/the input schema), so only the
|
|
8422
|
+
* deploy-time descriptor lookup sees the override and routes to the
|
|
8423
|
+
* extended-output lowering (§ 5). The return type is compute's exactly
|
|
8424
|
+
* (including the reserved `port` param). The storage module (D4b) calls this
|
|
8425
|
+
* with its `db`/`credentials` deps and `expose: { store: s3Contract }`.
|
|
8403
8426
|
*
|
|
8404
|
-
* `compute()`'s result is a `ComputeService` instance — its run/load/
|
|
8405
|
-
*
|
|
8406
|
-
*
|
|
8407
|
-
*
|
|
8408
|
-
*
|
|
8409
|
-
*
|
|
8427
|
+
* `compute()`'s result is a `ComputeService` instance — its run/load/input/
|
|
8428
|
+
* origin methods live on the class prototype, not as the instance's own
|
|
8429
|
+
* properties, so a plain object spread (`{ ...node }`) would silently drop
|
|
8430
|
+
* them. Building a fresh `ComputeService` from the same data fields (which
|
|
8431
|
+
* `{ ...node }` DOES copy — they're the node's own enumerable properties)
|
|
8432
|
+
* with `type` overridden keeps every method intact.
|
|
8410
8433
|
*/
|
|
8411
8434
|
function s3StoreService(def) {
|
|
8412
8435
|
const instance = new ComputeService({
|
|
@@ -8429,21 +8452,22 @@ const s3Contract = Object.freeze({
|
|
|
8429
8452
|
/**
|
|
8430
8453
|
* The storage service node (like cron's `scheduler.ts` + `scheduler-service.ts`
|
|
8431
8454
|
* combined): `storageService` builds the `s3-store` service — a Postgres `db`
|
|
8432
|
-
* dependency, a minted `credentials` dependency, a `bucket`
|
|
8433
|
-
*
|
|
8434
|
-
*
|
|
8435
|
-
*
|
|
8436
|
-
*
|
|
8437
|
-
* `cronScheduler(
|
|
8455
|
+
* dependency, a minted `credentials` dependency, a `bucket` input key
|
|
8456
|
+
* (bound at provision by `storage()`, ADR-0042), and the `store` port exposing
|
|
8457
|
+
* `s3Contract`. The deploy bootstrap runs the default-exported bare node
|
|
8458
|
+
* (`main.run(address, boot)`); the real bucket comes from the stashed input
|
|
8459
|
+
* document at runtime — exactly like `scheduler-service.ts` default-exports a
|
|
8460
|
+
* schedule-free `cronScheduler()`.
|
|
8438
8461
|
*/
|
|
8439
|
-
|
|
8462
|
+
const storageInputSchema = type({ bucket: "string" });
|
|
8463
|
+
function storageService() {
|
|
8440
8464
|
return s3StoreService({
|
|
8441
8465
|
name: "storage",
|
|
8442
8466
|
deps: {
|
|
8443
8467
|
db: postgres(),
|
|
8444
8468
|
credentials: s3Credentials()
|
|
8445
8469
|
},
|
|
8446
|
-
|
|
8470
|
+
input: storageInputSchema,
|
|
8447
8471
|
build: nodeBuild({
|
|
8448
8472
|
module: new URL("./storage-service.mjs", import.meta.url).href,
|
|
8449
8473
|
entry: "./storage-entrypoint.mjs"
|
|
@@ -8451,10 +8475,11 @@ function storageService(opts) {
|
|
|
8451
8475
|
expose: { store: s3Contract }
|
|
8452
8476
|
});
|
|
8453
8477
|
}
|
|
8454
|
-
storageService(
|
|
8455
|
-
const service = storageService(
|
|
8478
|
+
storageService();
|
|
8479
|
+
const service = storageService();
|
|
8456
8480
|
const { db, credentials } = service.load();
|
|
8457
|
-
const { bucket
|
|
8481
|
+
const { bucket } = service.input();
|
|
8482
|
+
const port = service.port();
|
|
8458
8483
|
startStorageServer({
|
|
8459
8484
|
store: await createPgStore(db.url),
|
|
8460
8485
|
credentials,
|