@prisma/composer-prisma-cloud 0.11.0-dev.3 → 0.11.0-dev.5

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.
@@ -10,15 +10,12 @@ import { createManagementApiClient } from "@prisma/management-api-sdk";
10
10
  import * as Redacted from "effect/Redacted";
11
11
  import * as Data from "effect/Data";
12
12
  import * as Option from "effect/Option";
13
- import * as Provider from "alchemy/Provider";
14
- import { Resource } from "alchemy";
15
- import * as crypto$1 from "node:crypto";
16
13
  import "node:crypto";
17
- import * as fs$1 from "node:fs";
18
14
  import "node:fs";
19
- import * as path$1 from "node:path";
20
15
  import path from "node:path";
16
+ import * as Provider from "alchemy/Provider";
21
17
  import * as Output from "alchemy/Output";
18
+ import { Resource } from "alchemy";
22
19
  import * as NodeHttpClient from "@effect/platform-node/NodeHttpClient";
23
20
  import * as Prisma from "alchemy/Prisma";
24
21
  import pg from "pg";
@@ -61,7 +58,7 @@ const normalizeBaseUrl = (value) => Effect.try({
61
58
  */
62
59
  const managementApiBaseUrl = (env) => env !== void 0 ? normalizeBaseUrl(env["PRISMA_API_URL"] || env["PRISMA_MANAGEMENT_API_URL"] || DEFAULT_BASE_URL) : Config$1.string("PRISMA_API_URL").pipe(Config$1.orElse(() => Config$1.string("PRISMA_MANAGEMENT_API_URL")), Config$1.withDefault(DEFAULT_BASE_URL), Effect.flatMap(normalizeBaseUrl));
63
60
  //#endregion
64
- //#region ../../1-prisma-cloud/0-lowering/lowering/dist/http-SXZNNmho.mjs
61
+ //#region ../../1-prisma-cloud/0-lowering/lowering/dist/database-url-claim-m_nGXIHa.mjs
65
62
  /**
66
63
  * The typed Prisma Management API client, built once from the resolved
67
64
  * credentials. Providers yield this in their outer Effect and call it inside
@@ -97,8 +94,6 @@ const fail = (r) => Effect.fail(new PrismaApiError({
97
94
  }));
98
95
  /** Unwrap `data`, failing on any API error. Preserves the SDK's response type. */
99
96
  const call = (f) => attempt(f).pipe(Effect.flatMap((r) => r.error !== void 0 || r.data === void 0 ? fail(r) : Effect.succeed(r.data)));
100
- /** Unwrap `data`, mapping a 404 to `undefined` (resource gone / not found). */
101
- const callOptional = (f) => attempt(f).pipe(Effect.flatMap((r) => r.response.status === 404 ? Effect.succeed(void 0) : r.error !== void 0 ? fail(r) : Effect.succeed(r.data)));
102
97
  /** Fire-and-forget a call, tolerating a 404 (already deleted). */
103
98
  const callVoid = (f) => attempt(f).pipe(Effect.flatMap((r) => r.response.status === 404 || r.error === void 0 ? Effect.void : fail(r)));
104
99
  /**
@@ -107,8 +102,6 @@ const callVoid = (f) => attempt(f).pipe(Effect.flatMap((r) => r.response.status
107
102
  * — whoever created it — is left exactly as it is.
108
103
  */
109
104
  const callCreateOnly = (f) => attempt(f).pipe(Effect.flatMap((r) => r.response.status === 409 || r.error === void 0 ? Effect.void : fail(r)));
110
- //#endregion
111
- //#region ../../1-prisma-cloud/0-lowering/lowering/dist/database-url-claim-BGCE1rXH.mjs
112
105
  /** Far beyond any real collection size per listing; hitting it means the API's pagination is broken. */
113
106
  const MAX_PAGES = 1e3;
114
107
  const brokenPaginationError = (description, reason) => new PrismaApiError({
@@ -330,82 +323,6 @@ const claimDatabaseUrlKeys = (projectId) => Effect.gen(function* () {
330
323
  if (Option.isNone(client)) return;
331
324
  for (const key of RESERVED_DATABASE_URL_KEYS) for (const environmentClass of ENVIRONMENT_CLASSES) yield* claim(client.value, projectId, key, environmentClass);
332
325
  });
333
- /** A Prisma **Object Store bucket** inside a project. */
334
- const Bucket = Resource("PrismaComposer.Bucket", { aliases: ["Prisma.Bucket"] });
335
- const BucketProvider = () => Provider.effect(Bucket, Effect.gen(function* () {
336
- const client = yield* ManagementClient;
337
- return {
338
- stables: ["id"],
339
- list: () => Effect.succeed([]),
340
- reconcile: Effect.fn(function* ({ news, output }) {
341
- const observed = output?.id ? yield* callOptional(() => client.GET("/v1/buckets/{bucketId}", { params: { path: { bucketId: output.id } } })) : void 0;
342
- if (observed) return {
343
- id: observed.data.id,
344
- name: observed.data.name
345
- };
346
- const created = yield* call(() => client.POST("/v1/buckets", { body: {
347
- projectId: news.projectId,
348
- name: news.name,
349
- ...news.branchId !== void 0 ? { branchId: news.branchId } : {}
350
- } }));
351
- return {
352
- id: created.data.id,
353
- name: created.data.name
354
- };
355
- }),
356
- delete: Effect.fn(function* ({ output }) {
357
- yield* callVoid(() => client.DELETE("/v1/buckets/{bucketId}", { params: { path: { bucketId: output.id } } }));
358
- }),
359
- read: Effect.fn(function* ({ output }) {
360
- if (!output?.id) return void 0;
361
- const b = yield* callOptional(() => client.GET("/v1/buckets/{bucketId}", { params: { path: { bucketId: output.id } } }));
362
- return b ? {
363
- id: b.data.id,
364
- name: b.data.name
365
- } : void 0;
366
- })
367
- };
368
- }));
369
- /** A **bucket access key** for a Prisma Object Store bucket — yields the S3 credentials. */
370
- const BucketKey = Resource("PrismaComposer.BucketKey", { aliases: ["Prisma.BucketKey"] });
371
- const BucketKeyProvider = () => Provider.effect(BucketKey, Effect.gen(function* () {
372
- const client = yield* ManagementClient;
373
- return {
374
- stables: [
375
- "id",
376
- "bucketId",
377
- "secretAccessKey",
378
- "accessKeyId",
379
- "endpoint",
380
- "bucketName"
381
- ],
382
- list: () => Effect.succeed([]),
383
- reconcile: Effect.fn(function* ({ news, output }) {
384
- if (output?.id) return output;
385
- const created = yield* call(() => client.POST("/v1/buckets/{bucketId}/keys", {
386
- params: { path: { bucketId: news.bucketId } },
387
- body: {
388
- name: news.name,
389
- role: news.role
390
- }
391
- }));
392
- return {
393
- id: created.data.id,
394
- bucketId: news.bucketId,
395
- accessKeyId: created.data.accessKeyId,
396
- secretAccessKey: Redacted.make(created.data.secretAccessKey),
397
- endpoint: created.data.endpoint,
398
- bucketName: created.data.bucketName
399
- };
400
- }),
401
- delete: Effect.fn(function* ({ output }) {
402
- yield* callVoid(() => client.DELETE("/v1/buckets/{bucketId}/keys/{keyId}", { params: { path: {
403
- bucketId: output.bucketId,
404
- keyId: output.id
405
- } } }));
406
- })
407
- };
408
- }));
409
326
  //#endregion
410
327
  //#region ../../0-framework/2-authoring/bundle-paths/dist/index.mjs
411
328
  /**
@@ -424,73 +341,6 @@ function isWithin(root, candidate) {
424
341
  //#endregion
425
342
  //#region ../../1-prisma-cloud/0-lowering/lowering/dist/compute.mjs
426
343
  /**
427
- * The environment is folded into `artifactPath`: the artifact is hard-linked
428
- * into a sibling directory named by a hash of the environment. The platform
429
- * materializes env rows into a deployment at create time and never re-reads
430
- * them (PRO-211), and nothing an `EnvironmentVariable` exposes can ride
431
- * upstream `Prisma.Deployment`'s replacement block — so a changed environment
432
- * must move `artifactPath` to ship a new deployment, and an unchanged one
433
- * must not, so the deployment is reused.
434
- *
435
- * No secret ever enters the hash: rows that are secret-free by construction
436
- * (ADR-0042 literals and pointers) contribute their text; every other row is
437
- * `withheld` and contributes only its key and what produces its value.
438
- * Platform variables a row points at (and Composer never writes) contribute
439
- * their `updatedAt`, so an out-of-band rotation redeploys. Accepted blind
440
- * spot: a value re-minted in place by the SAME resources does not move the
441
- * fingerprint — there is no leak-free signal for it at plan time.
442
- *
443
- * Replace this with upstream `Prisma.Deployment`'s `redeployOn` once the
444
- * pinned alchemy has it; the one call site is `descriptors/compute.ts`.
445
- */
446
- /**
447
- * The exact text the fingerprint hashes — exported so a test can assert what
448
- * is, and is not, in it. Entries are sorted by key so the row order the
449
- * serializer happens to produce cannot move the fingerprint.
450
- */
451
- function deployEnvFingerprintMaterial(entries, pointerUpdatedAt) {
452
- const rows = entries.map((entry) => ({
453
- key: entry.key,
454
- row: [
455
- entry.key,
456
- entry.value !== void 0 ? ["value", entry.value] : ["withheld", entry.withheld],
457
- [...entry.pointers ?? []].sort().map((name) => [name, pointerUpdatedAt(name) ?? "?"])
458
- ]
459
- })).sort((a, b) => a.key < b.key ? -1 : 1).map((r) => r.row);
460
- return JSON.stringify(rows);
461
- }
462
- /** The environment fingerprint: a sha256 hex digest of `deployEnvFingerprintMaterial`. */
463
- function deployEnvFingerprint(entries, pointerUpdatedAt) {
464
- return crypto$1.createHash("sha256").update(deployEnvFingerprintMaterial(entries, pointerUpdatedAt)).digest("hex");
465
- }
466
- /** How much of the digest names the directory — enough that two environments never collide in practice, short enough to read in a log line. */
467
- const FINGERPRINT_PATH_LENGTH = 12;
468
- /**
469
- * Hard-links `artifactPath` into a sibling `deploy-env-<fingerprint>`
470
- * directory and returns the link's path: same bytes, a path that moves if and
471
- * only if the environment moved. The canonical path is already
472
- * content-addressed, so a code change moves the parent directory and a
473
- * fingerprint change moves the child — either one is a new path, which is what
474
- * upstream plans a replace on. The empty path
475
- * (`packageComputeArtifact`'s destroy-run placeholder) passes through untouched.
476
- */
477
- function fingerprintedArtifactPath(artifactPath, fingerprint) {
478
- if (artifactPath === "") return artifactPath;
479
- const dir = path$1.join(path$1.dirname(artifactPath), `deploy-env-${fingerprint.slice(0, FINGERPRINT_PATH_LENGTH)}`);
480
- fs$1.mkdirSync(dir, { recursive: true });
481
- const linked = path$1.join(dir, path$1.basename(artifactPath));
482
- if (!fs$1.existsSync(linked)) try {
483
- fs$1.linkSync(artifactPath, linked);
484
- } catch (error) {
485
- if (!(error instanceof Error && "code" in error && error.code === "EEXIST")) {
486
- const tmp = `${linked}.tmp-${String(process.pid)}`;
487
- fs$1.copyFileSync(artifactPath, tmp);
488
- fs$1.renameSync(tmp, linked);
489
- }
490
- }
491
- return linked;
492
- }
493
- /**
494
344
  * Orders a deployment AFTER the environment rows it boots with: the platform
495
345
  * materializes rows into a deployment at create time and never re-reads them
496
346
  * (PRO-211). Alchemy schedules only on resource references inside prop
@@ -500,7 +350,8 @@ function fingerprintedArtifactPath(artifactPath, fingerprint) {
500
350
  * treats `{portMapping, skipCodeUpload, artifactPath, artifactContentType}`
501
351
  * as one block and returns "no opinion" if any is unresolved (a brand-new
502
352
  * variable always is), which would silently skip the artifact comparison.
503
- * Ordering only: shipping a CHANGED value is deploy-fingerprint.ts's job.
353
+ * Ordering only: shipping a CHANGED value is `Deployment.triggers`' job (the
354
+ * compute descriptor declares one member per environment row).
504
355
  */
505
356
  const appAfterEnvironment = (app, environment) => environment.length === 0 ? app : Output.flatMap(Output.all(app, ...environment.map((variable) => variable.environmentVariableId)), () => app);
506
357
  /**
@@ -560,15 +411,17 @@ const prismaEnvironment = () => Layer.effect(Prisma.PrismaEnvironment, Effect.ge
560
411
  }));
561
412
  /**
562
413
  * Upstream alchemy's live providers for the postgres family (Project,
563
- * Database, Connection) and the compute family (App, Deployment,
564
- * EnvironmentVariable), over upstream's management client, authenticated by
414
+ * Database, Connection), the compute family (App, Deployment,
415
+ * EnvironmentVariable), and the bucket family (Bucket, BucketAccessKey),
416
+ * over upstream's management client, authenticated by
565
417
  * {@link prismaEnvironment}.
566
418
  *
567
- * alchemy 2.0.0-beta.67 exports only the per-resource provider layers, so
568
- * they are composed by hand here. TODO: switch to upstream's
569
- * `liveProviderLayer` in the alchemy release that exports it.
419
+ * Composed from the per-resource provider layers rather than upstream's own
420
+ * `providers()` bundle: that bundle pulls in the profile store
421
+ * (`AlchemyProfile`/`CredentialsStore`), and Composer deliberately runs
422
+ * without one — no TTY prompt, no non-interactive hard-fail.
570
423
  */
571
- const upstreamPrismaProviders = () => Layer.mergeAll(Prisma.ProjectProvider(), Prisma.DatabaseProvider(), Prisma.ConnectionProvider(), Prisma.AppProvider(), Prisma.DeploymentProvider(), Prisma.EnvironmentVariableProvider()).pipe(Layer.provideMerge(Prisma.PrismaClientLive), Layer.provide(NodeHttpClient.layerNodeHttp), Layer.provideMerge(prismaEnvironment()));
424
+ const upstreamPrismaProviders = () => Layer.mergeAll(Prisma.ProjectProvider(), Prisma.DatabaseProvider(), Prisma.ConnectionProvider(), Prisma.AppProvider(), Prisma.DeploymentProvider(), Prisma.EnvironmentVariableProvider(), Prisma.BucketProvider(), Prisma.BucketAccessKeyProvider()).pipe(Layer.provideMerge(Prisma.PrismaClientLive), Layer.provide(NodeHttpClient.layerNodeHttp), Layer.provideMerge(prismaEnvironment()));
572
425
  /**
573
426
  * The Prisma provider bundle: every resource provider, the Management API
574
427
  * client, and env-based credentials. Plug into a stack with
@@ -589,9 +442,9 @@ const providers = () => Layer.effect(Providers, Provider.collection([
589
442
  Prisma.App,
590
443
  Prisma.Deployment,
591
444
  Prisma.EnvironmentVariable,
592
- Bucket,
593
- BucketKey
594
- ])).pipe(Layer.provide(Layer.mergeAll(upstreamPrismaProviders(), BucketProvider(), BucketKeyProvider())), Layer.provideMerge(NodeHttpClient.layerNodeHttp), Layer.provideMerge(layer()), Layer.provideMerge(fromEnv()), Layer.orDie);
445
+ Prisma.Bucket,
446
+ Prisma.BucketAccessKey
447
+ ])).pipe(Layer.provide(upstreamPrismaProviders()), Layer.provideMerge(NodeHttpClient.layerNodeHttp), Layer.provideMerge(layer()), Layer.provideMerge(fromEnv()), Layer.orDie);
595
448
  //#endregion
596
449
  //#region ../../1-prisma-cloud/0-lowering/s3-protocol/dist/index.mjs
597
450
  /**
@@ -1236,6 +1089,6 @@ const s3CredentialsProviderService = {
1236
1089
  /** The `S3Credentials` provider layer — merged into the extension descriptor's `providers()`. */
1237
1090
  const S3CredentialsProvider = () => Provider.effect(S3Credentials, Effect.succeed(s3CredentialsProviderService));
1238
1091
  //#endregion
1239
- export { claimDatabaseUrlKeys as A, managementApiBaseUrl as B, appAfterEnvironment as C, Bucket as D, isWithin as E, PrismaApiError as F, call as I, layer as L, drivePagesAsync as M, resolveDefaultBranchId as N, BucketKey as O, ManagementClient as P, PrismaCredentials as R, ServiceKeyProvider as S, fingerprintedArtifactPath as T, resolveTargetRef as _, PgWarmProvider as a, providers as b, PrismaCloudContainer as c, collectPreflightNames as d, containerDescriptor as f, resolvePrismaNextConfig as g, prismaCloudContainerOf as h, PgWarm as i, collectPages as j, RESERVED_DATABASE_URL_KEYS as k, S3Credentials as l, packHeadRefHashes as m, GeneratedParamProvider as n, PnMigration as o, deserialize as p, PRISMA_CLOUD_EXTENSION_ID as r, PnMigrationProvider as s, GeneratedParam as t, S3CredentialsProvider as u, mintKeyPair as v, deployEnvFingerprint as w, ServiceKey as x, Providers as y, fromEnv as z };
1092
+ export { collectPages as A, appAfterEnvironment as C, RESERVED_DATABASE_URL_KEYS as D, PrismaApiError as E, fromEnv as F, managementApiBaseUrl as I, layer as M, resolveDefaultBranchId as N, call as O, PrismaCredentials as P, ServiceKeyProvider as S, ManagementClient as T, resolveTargetRef as _, PgWarmProvider as a, providers as b, PrismaCloudContainer as c, collectPreflightNames as d, containerDescriptor as f, resolvePrismaNextConfig as g, prismaCloudContainerOf as h, PgWarm as i, drivePagesAsync as j, claimDatabaseUrlKeys as k, S3Credentials as l, packHeadRefHashes as m, GeneratedParamProvider as n, PnMigration as o, deserialize as p, PRISMA_CLOUD_EXTENSION_ID as r, PnMigrationProvider as s, GeneratedParam as t, S3CredentialsProvider as u, mintKeyPair as v, isWithin as w, ServiceKey as x, Providers as y };
1240
1093
 
1241
- //# sourceMappingURL=s3-credentials-resource-BUsjCFtj-C-nS9rK-.mjs.map
1094
+ //# sourceMappingURL=s3-credentials-resource-BUsjCFtj-BzHGBAmT.mjs.map