@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.
- package/dist/auth/pack.mjs +1 -1
- package/dist/auth/pack.mjs.map +1 -1
- package/dist/auth/testing.mjs +1 -1
- package/dist/auth/testing.mjs.map +1 -1
- package/dist/control.d.mts +0 -9
- package/dist/control.d.mts.map +1 -1
- package/dist/control.mjs +105 -88
- package/dist/control.mjs.map +1 -1
- package/dist/local-target.mjs +46 -34
- package/dist/local-target.mjs.map +1 -1
- package/dist/{s3-credentials-resource-BUsjCFtj-C-nS9rK-.mjs → s3-credentials-resource-BUsjCFtj-BzHGBAmT.mjs} +18 -165
- package/dist/{s3-credentials-resource-BUsjCFtj-C-nS9rK-.mjs.map → s3-credentials-resource-BUsjCFtj-BzHGBAmT.mjs.map} +1 -1
- package/package.json +23 -23
|
@@ -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/
|
|
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
|
|
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)
|
|
564
|
-
* EnvironmentVariable),
|
|
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
|
-
*
|
|
568
|
-
*
|
|
569
|
-
* `
|
|
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
|
-
|
|
594
|
-
])).pipe(Layer.provide(
|
|
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 {
|
|
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-
|
|
1094
|
+
//# sourceMappingURL=s3-credentials-resource-BUsjCFtj-BzHGBAmT.mjs.map
|