@prisma/composer-prisma-cloud 0.1.0-dev.9 → 0.2.0-dev.1

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.
Files changed (45) hide show
  1. package/dist/control.d.mts +40 -34
  2. package/dist/control.mjs +512 -105
  3. package/dist/control.mjs.map +1 -1
  4. package/dist/cron/index.d.mts +54 -4
  5. package/dist/cron/index.mjs +154 -42
  6. package/dist/cron/index.mjs.map +1 -1
  7. package/dist/cron/scheduler-entrypoint.mjs +459 -306
  8. package/dist/cron/scheduler-entrypoint.mjs.map +1 -1
  9. package/dist/cron/scheduler-service.mjs +154 -42
  10. package/dist/cron/scheduler-service.mjs.map +1 -1
  11. package/dist/index.d.mts +76 -6
  12. package/dist/index.mjs +108 -45
  13. package/dist/index.mjs.map +1 -1
  14. package/dist/{prisma-next-qPB8_Az6.mjs → prisma-next-DlU01kXJ-2sP5mQb6.mjs} +3 -3
  15. package/dist/prisma-next-DlU01kXJ-2sP5mQb6.mjs.map +1 -0
  16. package/dist/prisma-next.d.mts +1 -1
  17. package/dist/prisma-next.mjs +1 -1
  18. package/dist/{provisioned-edges-DIQAR4q4-Bn9op-JG.mjs → provisioned-edges-B_XS1Mz--NFJgcXK7.mjs} +66 -6
  19. package/dist/provisioned-edges-B_XS1Mz--NFJgcXK7.mjs.map +1 -0
  20. package/dist/{serializer-CX4VYdf_-KKGoAxfx.mjs → serializer-D8_84XWO-DA2B6YbX.mjs} +33 -3
  21. package/dist/serializer-D8_84XWO-DA2B6YbX.mjs.map +1 -0
  22. package/dist/storage/index.d.mts +62 -14
  23. package/dist/storage/index.mjs +168 -48
  24. package/dist/storage/index.mjs.map +1 -1
  25. package/dist/storage/storage-entrypoint.mjs +361 -239
  26. package/dist/storage/storage-entrypoint.mjs.map +1 -1
  27. package/dist/storage/storage-service.mjs +168 -48
  28. package/dist/storage/storage-service.mjs.map +1 -1
  29. package/dist/storage/testing.mjs.map +1 -1
  30. package/dist/streams/index.d.mts +62 -89
  31. package/dist/streams/index.mjs +169 -49
  32. package/dist/streams/index.mjs.map +1 -1
  33. package/dist/streams/streams-entrypoint.mjs +361 -239
  34. package/dist/streams/streams-entrypoint.mjs.map +1 -1
  35. package/dist/streams/streams-service.mjs +168 -48
  36. package/dist/streams/streams-service.mjs.map +1 -1
  37. package/dist/streams/testing.d.mts +1 -1
  38. package/dist/streams/testing.mjs.map +1 -1
  39. package/dist/testing.d.mts +1 -1
  40. package/dist/testing.mjs +1 -1
  41. package/dist/testing.mjs.map +1 -1
  42. package/package.json +14 -14
  43. package/dist/prisma-next-qPB8_Az6.mjs.map +0 -1
  44. package/dist/provisioned-edges-DIQAR4q4-Bn9op-JG.mjs.map +0 -1
  45. package/dist/serializer-CX4VYdf_-KKGoAxfx.mjs.map +0 -1
@@ -1,7 +1,7 @@
1
1
  import { dependency, hydrateSecrets, hydrateSync, number, provisionNeed, resource, service, string } from "@prisma/composer";
2
2
  import { blindCast } from "@prisma/composer/casts";
3
- import { RPC_PEER_KEY } from "@prisma/composer/service-rpc";
4
3
  import { type } from "arktype";
4
+ import { RPC_PEER_KEY } from "@prisma/composer/service-rpc";
5
5
  import node from "@prisma/composer/node";
6
6
  blindCast(Symbol.for("prisma:prisma-cloud-secret-source"));
7
7
  /**
@@ -191,6 +191,35 @@ function stashProviderParams(entries, address) {
191
191
  process.env[configKey("", d)] = encode("service", value);
192
192
  }
193
193
  }
194
+ /** The framework-resolved origin row: COMPOSER_<addr>_ORIGIN. Written per
195
+ * compute service at serialize — the service's own provisioned endpoint URL,
196
+ * riding the reserved-provider-param machinery (`origin-key.ts`'s
197
+ * `ORIGIN_PARAM`); never a declared param, never in config(). A harness with
198
+ * no deploy behind it supplies it by setting `COMPOSER_ORIGIN` to the
199
+ * JSON-encoded origin URL — exactly how the existing entrypoint tests supply
200
+ * their other `COMPOSER_*` rows. */
201
+ const ORIGIN_KEY_NAME = "ORIGIN";
202
+ /**
203
+ * Reads this service's origin back out of the address-free stash
204
+ * `stashProviderParams` wrote for the ORIGIN entry. `COMPOSER_ORIGIN` unset is
205
+ * a loud failure — a deployed environment always writes it, so an unset row
206
+ * means either a local harness that hasn't supplied it or a boot() called
207
+ * before run().
208
+ */
209
+ function readOrigin() {
210
+ const d = {
211
+ owner: "service",
212
+ name: ORIGIN_KEY_NAME,
213
+ param: {
214
+ schema: type("string"),
215
+ optional: true
216
+ }
217
+ };
218
+ const key = configKey("", d);
219
+ const value = coerce(process.env[key], d, key);
220
+ if (value === void 0) throw new Error("this service's origin is not available (env COMPOSER_ORIGIN is unset) — a deployed environment writes it automatically; a local harness must supply it like any other config value (set COMPOSER_ORIGIN to the JSON-encoded origin URL).");
221
+ return blindCast(value);
222
+ }
194
223
  /** Synchronous Standard Schema validation — see the matching note in core's `config.ts`. */
195
224
  function standardValidateSync(schema, value) {
196
225
  const result = schema["~standard"].validate(value);
@@ -199,7 +228,41 @@ function standardValidateSync(schema, value) {
199
228
  return result.value;
200
229
  }
201
230
  //#endregion
202
- //#region ../../1-prisma-cloud/1-extensions/target/dist/provisioned-edges-DIQAR4q4.mjs
231
+ //#region ../../1-prisma-cloud/1-extensions/target/dist/provisioned-edges-B_XS1Mz-.mjs
232
+ /**
233
+ * The service's own origin as a reserved provider param (ADR-0031): the ONE
234
+ * brand and the ONE entry — shared by control.ts (which registers the
235
+ * deploy-side value function that resolves the provisioned service's
236
+ * `endpointDomain` — see its `selfOriginValue`) and compute.ts (which
237
+ * validates and stashes the row at boot through the generic
238
+ * `stashProviderParams` loop), so writer and reader cannot drift.
239
+ *
240
+ * Unlike the key-minting brands (`service-keys.ts`, `streams-keys.ts`) this
241
+ * brand has no provisioner and no consumer edges: the value derives from the
242
+ * service's OWN provisioned attributes, so control.ts registers it as a
243
+ * service-derived provider param (`descriptors/shared.ts`'s
244
+ * `ServiceProviderParam`) and the descriptor writes it for EVERY compute
245
+ * service, exposing or not.
246
+ *
247
+ * This module is reachable from the RUNTIME/authoring side — it must never
248
+ * import `@internal/lowering` or `effect`, or those tokens leak into a user
249
+ * service's bundle (the deploy-side value function lives in control.ts, the
250
+ * control-plane-only entry).
251
+ */
252
+ /** ADR-0031's brand for the service's own origin — control.ts registers the deploy-side value function under this. */
253
+ const SELF_ORIGIN = Symbol.for("prisma:self-origin");
254
+ /**
255
+ * The reserved provider param for the origin row: the var name is `ORIGIN`,
256
+ * derived through `configKey` at both ends (`configKey(address, …)` at
257
+ * deploy, `configKey('', …)` — `COMPOSER_ORIGIN` — at boot, where
258
+ * `readOrigin` reads it back). `brand` is `SELF_ORIGIN` — control.ts looks
259
+ * its deploy-side value function up by this field.
260
+ */
261
+ const ORIGIN_PARAM = {
262
+ name: ORIGIN_KEY_NAME,
263
+ schema: type("string"),
264
+ brand: SELF_ORIGIN
265
+ };
203
266
  /**
204
267
  * RPC's reserved provider param (ADR-0030/ADR-0031): the declaration —
205
268
  * name + schema + brand — for the accepted-keys set a provider stores, shared
@@ -252,17 +315,51 @@ configKey("", {
252
315
  owner: "service",
253
316
  name: STREAMS_API_KEY_PARAM.name
254
317
  });
255
- const RESERVED_PROVIDER_PARAMS = [RPC_ACCEPTED_KEYS_PARAM, STREAMS_API_KEY_PARAM];
318
+ /**
319
+ * The list of provider-side reserved params the boot path validates and
320
+ * stashes (ADR-0031): every brand's `{name, schema, brand}` declaration,
321
+ * collected from that brand's own module (`service-keys.ts`,
322
+ * `streams-keys.ts`, `origin-key.ts`) so `compute.ts` names no brand itself.
323
+ *
324
+ * This list exists separately from `control.ts`'s deploy-side registry
325
+ * (`PROVIDER_PARAMS`) because `control.ts` is deploy-only code — it imports
326
+ * `@internal/lowering` and `effect` to mint values — and a booted service
327
+ * must never import it. This module is reachable from a user service's
328
+ * bundle through `compute.ts`, so it must never import `@internal/lowering`,
329
+ * `effect`, `alchemy`, or `control.ts`.
330
+ *
331
+ * This is the single source of which reserved provider params exist:
332
+ * control.ts builds `PROVIDER_PARAMS` by mapping over this list and looking
333
+ * up each entry's deploy-side value function (edge-derived `value(refs)` or
334
+ * service-derived `valueForService(provisioned, address)`) by its `brand`,
335
+ * throwing at module load if one is missing. Adding a brand means adding its
336
+ * entry here, plus its deploy-side value function in control.ts — a brand
337
+ * registered for deploy but absent here is no longer expressible, because
338
+ * deploy no longer names its own param set independently.
339
+ */
340
+ const RESERVED_PROVIDER_PARAMS = [
341
+ RPC_ACCEPTED_KEYS_PARAM,
342
+ STREAMS_API_KEY_PARAM,
343
+ ORIGIN_PARAM
344
+ ];
256
345
  blindCast(Symbol.for("prisma:prisma-cloud-param-source"));
257
- //#endregion
258
- //#region ../../1-prisma-cloud/1-extensions/target/dist/index.mjs
346
+ Object.freeze({
347
+ kind: "s3",
348
+ __cmp: {
349
+ url: "",
350
+ bucket: "",
351
+ accessKeyId: "",
352
+ secretAccessKey: ""
353
+ },
354
+ satisfies: (required) => required.kind === "s3"
355
+ });
259
356
  const reservedParams = { port: number({ default: 3e3 }) };
260
357
  /**
261
358
  * A Prisma Compute service — declarations only (deps + params + build + the
262
359
  * ports it exposes), no descriptor. `params` merges with the reserved
263
360
  * `ReservedParams` (`port`); a user param whose name collides with a reserved
264
361
  * one fails at authoring, the same way a colliding dependency name does.
265
- * Returns the extension's runnable/loadable node:
362
+ *
266
363
  * · run(address, boot) — the process controller: deserialize the platform
267
364
  * environment (keyed off `address`, the extension's ONE env read) into a
268
365
  * typed Config, re-emit it under address-free process-local stash keys,
@@ -270,23 +367,69 @@ const reservedParams = { port: number({ default: 3e3 }) };
270
367
  * · load() / config() — called from inside the app's entry: read the stash;
271
368
  * load() hydrates + memoizes the deps, config() returns the typed params.
272
369
  * Separate accessors so a dep and a param never share a namespace (ADR-0021).
370
+ * · origin() — this service's platform-assigned public origin, read from the
371
+ * stash `run()` populates; memoized per process.
273
372
  *
274
- * `service()`'s underlying node carries `extension: '@prisma/composer-prisma-cloud'` —
373
+ * The underlying node carries `extension: '@prisma/composer-prisma-cloud'` —
275
374
  * the control-plane registry key `prisma-composer deploy` resolves through the
276
375
  * app's `prisma-composer.config.ts` (ADR-0017). This module loads nothing at
277
- * deploy time; nodes are pure data.
376
+ * deploy time; nodes are pure data until run() or load() is called.
278
377
  */
378
+ var ComputeService = class {
379
+ #resolved;
380
+ #loadedDeps;
381
+ #loadedParams;
382
+ #loadedSecrets;
383
+ #origin;
384
+ constructor(node) {
385
+ Object.assign(this, node);
386
+ }
387
+ #processConfig() {
388
+ if (this.#resolved === void 0) this.#resolved = deserialize(this, "");
389
+ return this.#resolved;
390
+ }
391
+ async run(address, boot) {
392
+ const config = deserialize(this, address);
393
+ stash(this, config);
394
+ stashProviderParams(RESERVED_PROVIDER_PARAMS, address);
395
+ stashSecrets(this, address);
396
+ const port = config.service["port"];
397
+ if (typeof port === "number") process.env["PORT"] = String(port);
398
+ return boot();
399
+ }
400
+ load() {
401
+ if (this.#loadedDeps === void 0) this.#loadedDeps = blindCast(hydrateSync(this, this.#processConfig()));
402
+ return this.#loadedDeps;
403
+ }
404
+ config() {
405
+ if (this.#loadedParams === void 0) this.#loadedParams = blindCast(this.#processConfig().service);
406
+ return this.#loadedParams;
407
+ }
408
+ secrets() {
409
+ if (this.#loadedSecrets === void 0) this.#loadedSecrets = blindCast(hydrateSecrets(this, deserializeSecrets(this, "")));
410
+ return this.#loadedSecrets;
411
+ }
412
+ /** This service's platform-assigned public origin — read from the stash
413
+ * run() populates and memoized per process. Throws if called before run()
414
+ * has stashed it (readOrigin's pinned message). */
415
+ origin() {
416
+ this.#origin ??= readOrigin();
417
+ return this.#origin;
418
+ }
419
+ };
279
420
  const compute = (def) => {
280
421
  const userParams = def.params ?? blindCast({});
281
422
  for (const reserved of Object.keys(reservedParams)) {
282
423
  if (reserved in def.deps) throw new Error(`compute(): dependency "${reserved}" collides with the reserved service param of the same name — rename the dependency.`);
283
424
  if (reserved in userParams) throw new Error(`compute(): param "${reserved}" collides with the reserved service param of the same name — rename the param.`);
284
425
  }
426
+ 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.`);
427
+ 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.`);
285
428
  const params = blindCast({
286
429
  ...userParams,
287
430
  ...reservedParams
288
431
  });
289
- const node = service({
432
+ const instance = new ComputeService(service({
290
433
  name: def.name,
291
434
  extension: "@prisma/composer-prisma-cloud",
292
435
  type: "compute",
@@ -295,40 +438,9 @@ const compute = (def) => {
295
438
  ...def.secrets !== void 0 ? { secrets: def.secrets } : {},
296
439
  build: def.build,
297
440
  ...def.expose !== void 0 ? { expose: def.expose } : {}
298
- });
299
- let resolved;
300
- let loadedDeps;
301
- let loadedParams;
302
- let loadedSecrets;
303
- function processConfig() {
304
- if (resolved === void 0) resolved = deserialize(node, "");
305
- return resolved;
306
- }
307
- const runnable = {
308
- ...node,
309
- async run(address, boot) {
310
- const config = deserialize(node, address);
311
- stash(node, config);
312
- stashProviderParams(RESERVED_PROVIDER_PARAMS, address);
313
- stashSecrets(node, address);
314
- const port = config.service["port"];
315
- if (typeof port === "number") process.env["PORT"] = String(port);
316
- return boot();
317
- },
318
- load() {
319
- if (loadedDeps === void 0) loadedDeps = blindCast(hydrateSync(node, processConfig()));
320
- return loadedDeps;
321
- },
322
- config() {
323
- if (loadedParams === void 0) loadedParams = blindCast(processConfig().service);
324
- return loadedParams;
325
- },
326
- secrets() {
327
- if (loadedSecrets === void 0) loadedSecrets = blindCast(hydrateSecrets(node, deserializeSecrets(node, "")));
328
- return loadedSecrets;
329
- }
330
- };
331
- return Object.freeze(blindCast(runnable));
441
+ }));
442
+ Object.freeze(instance);
443
+ return instance;
332
444
  };
333
445
  /**
334
446
  * The contract a Postgres provides — and the contract its consumers require.
@@ -399,16 +511,24 @@ function s3Credentials(opts) {
399
511
  * return type is compute's exactly (including the reserved `port` param). The
400
512
  * storage module (D4b) calls this with its `db`/`credentials` deps, a `bucket`
401
513
  * param, and `expose: { store: s3Contract }`.
514
+ *
515
+ * `compute()`'s result is a `ComputeService` instance — its run/load/config/
516
+ * secrets/origin methods live on the class prototype, not as the instance's
517
+ * own properties, so a plain object spread (`{ ...node }`) would silently
518
+ * drop them. Building a fresh `ComputeService` from the same data fields
519
+ * (which `{ ...node }` DOES copy — they're the node's own enumerable
520
+ * properties) with `type` overridden keeps every method intact.
402
521
  */
403
522
  function s3StoreService(def) {
404
- const node = compute(def);
405
- return Object.freeze(blindCast({
406
- ...node,
523
+ const instance = new ComputeService({
524
+ ...compute(def),
407
525
  type: "s3-store"
408
- }));
526
+ });
527
+ Object.freeze(instance);
528
+ return instance;
409
529
  }
410
530
  //#endregion
411
- //#region ../../1-prisma-cloud/2-shared-modules/storage/dist/storage-service-BQdOiMsW.mjs
531
+ //#region ../../1-prisma-cloud/2-shared-modules/storage/dist/storage-service-DSaZsAC4.mjs
412
532
  const s3Contract = Object.freeze({
413
533
  kind: "s3",
414
534
  __cmp: {