@prisma/composer-prisma-cloud 0.9.0 → 0.10.0-dev.2
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 +1496 -982
- package/dist/auth/testing.mjs.map +1 -1
- package/dist/control.mjs +1 -1
- package/dist/control.mjs.map +1 -1
- package/dist/local-target.mjs +1 -1
- package/dist/local-target.mjs.map +1 -1
- package/dist/{s3-credentials-resource-BltGd-gG-BJIY99QX.mjs → s3-credentials-resource-vElUxfYi-Bb7ILl1X.mjs} +6 -4
- package/dist/{s3-credentials-resource-BltGd-gG-BJIY99QX.mjs.map → s3-credentials-resource-vElUxfYi-Bb7ILl1X.mjs.map} +1 -1
- package/package.json +21 -21
package/dist/auth/testing.mjs
CHANGED
|
@@ -23667,10 +23667,7 @@ function _defu(baseObject, defaults, namespace = ".", merger) {
|
|
|
23667
23667
|
function createDefu(merger) {
|
|
23668
23668
|
return (...arguments_) => arguments_.reduce((p, c) => _defu(p, c, "", merger), {});
|
|
23669
23669
|
}
|
|
23670
|
-
|
|
23671
|
-
var init_defu = __esmMin((() => {
|
|
23672
|
-
defu = createDefu();
|
|
23673
|
-
}));
|
|
23670
|
+
const defu = createDefu();
|
|
23674
23671
|
/**
|
|
23675
23672
|
* Cloud provider instance metadata service FQDNs. These resolve to link-local
|
|
23676
23673
|
* IPs (usually `169.254.169.254`) inside their respective clouds and are
|
|
@@ -23914,7 +23911,6 @@ function isLoopbackHost(host) {
|
|
|
23914
23911
|
}
|
|
23915
23912
|
init_env();
|
|
23916
23913
|
init_error();
|
|
23917
|
-
init_defu();
|
|
23918
23914
|
async function runPluginInit(context) {
|
|
23919
23915
|
let options = context.options;
|
|
23920
23916
|
const plugins = options.plugins || [];
|
|
@@ -30586,7 +30582,6 @@ const changeEmail = createAuthEndpoint("/change-email", {
|
|
|
30586
30582
|
});
|
|
30587
30583
|
init_env();
|
|
30588
30584
|
init_error();
|
|
30589
|
-
init_defu();
|
|
30590
30585
|
init_instrumentation();
|
|
30591
30586
|
const defuReplaceArrays = createDefu((obj, key, value) => {
|
|
30592
30587
|
if (Array.isArray(obj[key]) && Array.isArray(value)) {
|
|
@@ -32348,7 +32343,7 @@ function rowChanged(baseRow, cloneRow) {
|
|
|
32348
32343
|
return JSON.stringify(baseRow) !== JSON.stringify(cloneRow);
|
|
32349
32344
|
}
|
|
32350
32345
|
var memoryAdapter;
|
|
32351
|
-
var init_dist$
|
|
32346
|
+
var init_dist$2 = __esmMin((() => {
|
|
32352
32347
|
init_adapter();
|
|
32353
32348
|
init_env();
|
|
32354
32349
|
memoryAdapter = (db, config) => {
|
|
@@ -32609,7 +32604,7 @@ async function getBaseAdapter(options, handleDirectDatabase) {
|
|
|
32609
32604
|
acc[key] = [];
|
|
32610
32605
|
return acc;
|
|
32611
32606
|
}, {});
|
|
32612
|
-
const { memoryAdapter } = await Promise.resolve().then(() => (init_dist$
|
|
32607
|
+
const { memoryAdapter } = await Promise.resolve().then(() => (init_dist$2(), dist_exports));
|
|
32613
32608
|
adapter = memoryAdapter(memoryDB)(options);
|
|
32614
32609
|
} else if (typeof options.database === "function") adapter = options.database(options);
|
|
32615
32610
|
else adapter = await handleDirectDatabase(options);
|
|
@@ -49496,7 +49491,7 @@ var init_handle_empty_in_lists = __esmMin((() => {}));
|
|
|
49496
49491
|
var init_safe_null_comparison_plugin = __esmMin((() => {}));
|
|
49497
49492
|
var init_constraint_node = __esmMin((() => {}));
|
|
49498
49493
|
var init_simple_reference_expression_node = __esmMin((() => {}));
|
|
49499
|
-
var init_dist$
|
|
49494
|
+
var init_dist$1 = __esmMin((() => {
|
|
49500
49495
|
init_kysely();
|
|
49501
49496
|
init_query_creator();
|
|
49502
49497
|
init_query_finalizer();
|
|
@@ -49713,7 +49708,7 @@ var BunSqliteQueryCompiler;
|
|
|
49713
49708
|
var BunSqliteDialect;
|
|
49714
49709
|
var init_bun_sqlite_dialect_DTyyejk1 = __esmMin((() => {
|
|
49715
49710
|
init_kysely_migration_tables_B2_rTeXm();
|
|
49716
|
-
init_dist$
|
|
49711
|
+
init_dist$1();
|
|
49717
49712
|
BunSqliteAdapter = class {
|
|
49718
49713
|
get supportsCreateIfNotExists() {
|
|
49719
49714
|
return true;
|
|
@@ -49882,7 +49877,7 @@ var NodeSqliteQueryCompiler;
|
|
|
49882
49877
|
var NodeSqliteDialect;
|
|
49883
49878
|
var init_node_sqlite_dialect = __esmMin((() => {
|
|
49884
49879
|
init_kysely_migration_tables_B2_rTeXm();
|
|
49885
|
-
init_dist$
|
|
49880
|
+
init_dist$1();
|
|
49886
49881
|
NodeSqliteAdapter = class {
|
|
49887
49882
|
get supportsCreateIfNotExists() {
|
|
49888
49883
|
return true;
|
|
@@ -50050,7 +50045,7 @@ var D1SqliteQueryCompiler;
|
|
|
50050
50045
|
var D1SqliteDialect;
|
|
50051
50046
|
var init_d1_sqlite_dialect_CDCl_qH4 = __esmMin((() => {
|
|
50052
50047
|
init_kysely_migration_tables_B2_rTeXm();
|
|
50053
|
-
init_dist$
|
|
50048
|
+
init_dist$1();
|
|
50054
50049
|
D1SqliteAdapter = class extends SqliteAdapter {};
|
|
50055
50050
|
D1SqliteDriver = class {
|
|
50056
50051
|
#config;
|
|
@@ -50223,8 +50218,8 @@ function insensitiveNe(columnRef, value) {
|
|
|
50223
50218
|
}
|
|
50224
50219
|
var createKyselyAdapter;
|
|
50225
50220
|
var kyselyAdapter;
|
|
50226
|
-
var init_dist
|
|
50227
|
-
init_dist$
|
|
50221
|
+
var init_dist = __esmMin((() => {
|
|
50222
|
+
init_dist$1();
|
|
50228
50223
|
init_adapter();
|
|
50229
50224
|
init_env();
|
|
50230
50225
|
init_string();
|
|
@@ -50740,7 +50735,7 @@ var kysely_adapter_exports = /* @__PURE__ */ __exportAll({
|
|
|
50740
50735
|
kyselyAdapter: () => kyselyAdapter
|
|
50741
50736
|
});
|
|
50742
50737
|
var init_kysely_adapter = __esmMin((() => {
|
|
50743
|
-
init_dist
|
|
50738
|
+
init_dist();
|
|
50744
50739
|
}));
|
|
50745
50740
|
init_error();
|
|
50746
50741
|
async function getAdapter(options) {
|
|
@@ -50793,9 +50788,9 @@ function getSchema(config) {
|
|
|
50793
50788
|
}
|
|
50794
50789
|
init_get_tables();
|
|
50795
50790
|
init_env();
|
|
50796
|
-
init_dist
|
|
50791
|
+
init_dist();
|
|
50797
50792
|
init_adapter();
|
|
50798
|
-
init_dist$
|
|
50793
|
+
init_dist$1();
|
|
50799
50794
|
const map = {
|
|
50800
50795
|
postgres: {
|
|
50801
50796
|
string: [
|
|
@@ -51643,7 +51638,6 @@ init_get_tables();
|
|
|
51643
51638
|
init_env();
|
|
51644
51639
|
init_error();
|
|
51645
51640
|
init_id();
|
|
51646
|
-
init_defu();
|
|
51647
51641
|
/**
|
|
51648
51642
|
* Estimates the entropy of a string in bits.
|
|
51649
51643
|
* This is a simple approximation that helps detect low-entropy secrets.
|
|
@@ -51854,7 +51848,7 @@ Most of the features of Better Auth will not work correctly.`);
|
|
|
51854
51848
|
return ctx;
|
|
51855
51849
|
}
|
|
51856
51850
|
init_error();
|
|
51857
|
-
init_dist
|
|
51851
|
+
init_dist();
|
|
51858
51852
|
const init = async (options) => {
|
|
51859
51853
|
const adapter = await getAdapter(options);
|
|
51860
51854
|
const getDatabaseType = (database) => getKyselyDatabaseType(database) || "unknown";
|
|
@@ -59502,8 +59496,12 @@ function ifDefined(key, value) {
|
|
|
59502
59496
|
return value !== void 0 ? blindCast({ [key]: value }) : {};
|
|
59503
59497
|
}
|
|
59504
59498
|
const STRUCTURED_CODE_RE = /^[A-Z][A-Z0-9]*\.[A-Z][A-Z0-9_]*$/;
|
|
59499
|
+
/** Whether a bare string is a published `NAMESPACE.SUBCODE` code. */
|
|
59500
|
+
function isStructuredErrorCode(code) {
|
|
59501
|
+
return STRUCTURED_CODE_RE.test(code);
|
|
59502
|
+
}
|
|
59505
59503
|
function isStructuredError(e) {
|
|
59506
|
-
return typeof e === "object" && e !== null && "code" in e && typeof e.code === "string" &&
|
|
59504
|
+
return typeof e === "object" && e !== null && "code" in e && typeof e.code === "string" && isStructuredErrorCode(e.code) && "message" in e && typeof e.message === "string";
|
|
59507
59505
|
}
|
|
59508
59506
|
function structuredError(code, message, options) {
|
|
59509
59507
|
const error = options?.cause !== void 0 ? new Error(message, { cause: options.cause }) : new Error(message);
|
|
@@ -59515,6 +59513,7 @@ function structuredError(code, message, options) {
|
|
|
59515
59513
|
code,
|
|
59516
59514
|
...ifDefined("why", options?.why),
|
|
59517
59515
|
...ifDefined("fix", options?.fix),
|
|
59516
|
+
...ifDefined("nextActions", options?.nextActions),
|
|
59518
59517
|
...ifDefined("where", options?.where),
|
|
59519
59518
|
...ifDefined("severity", options?.severity),
|
|
59520
59519
|
...ifDefined("meta", options?.meta),
|
|
@@ -59540,7 +59539,7 @@ var CliStructuredError = class extends Error {
|
|
|
59540
59539
|
code;
|
|
59541
59540
|
severity;
|
|
59542
59541
|
constructor(code, summary, options) {
|
|
59543
|
-
super(summary);
|
|
59542
|
+
super(summary, options?.cause !== void 0 ? { cause: options.cause } : void 0);
|
|
59544
59543
|
this.name = "CliStructuredError";
|
|
59545
59544
|
this.code = code;
|
|
59546
59545
|
this.severity = options?.severity ?? "error";
|
|
@@ -59552,6 +59551,7 @@ var CliStructuredError = class extends Error {
|
|
|
59552
59551
|
Object.assign(this, {
|
|
59553
59552
|
...ifDefined("why", options?.why),
|
|
59554
59553
|
...ifDefined("fix", fix),
|
|
59554
|
+
...ifDefined("nextActions", options?.nextActions),
|
|
59555
59555
|
...ifDefined("where", where),
|
|
59556
59556
|
...ifDefined("meta", options?.meta),
|
|
59557
59557
|
...ifDefined("docsUrl", options?.docsUrl)
|
|
@@ -59559,6 +59559,9 @@ var CliStructuredError = class extends Error {
|
|
|
59559
59559
|
}
|
|
59560
59560
|
/**
|
|
59561
59561
|
* Converts this error to a CLI error envelope for output formatting.
|
|
59562
|
+
*
|
|
59563
|
+
* This is the boundary that emits the envelope, so it is where a missing
|
|
59564
|
+
* `nextActions` becomes `[]`.
|
|
59562
59565
|
*/
|
|
59563
59566
|
toEnvelope() {
|
|
59564
59567
|
return {
|
|
@@ -59568,6 +59571,7 @@ var CliStructuredError = class extends Error {
|
|
|
59568
59571
|
summary: this.message,
|
|
59569
59572
|
...ifDefined("why", this.why),
|
|
59570
59573
|
...ifDefined("fix", this.fix),
|
|
59574
|
+
nextActions: this.nextActions ?? [],
|
|
59571
59575
|
...ifDefined("where", this.where),
|
|
59572
59576
|
...ifDefined("meta", this.meta),
|
|
59573
59577
|
...ifDefined("docsUrl", this.docsUrl)
|
|
@@ -59589,8 +59593,12 @@ var CliStructuredError = class extends Error {
|
|
|
59589
59593
|
function errorConfigValidation(field, options) {
|
|
59590
59594
|
return new CliStructuredError("CONFIG.VALIDATION_FAILED", "Config validation error", {
|
|
59591
59595
|
why: options?.why ?? `Config must have a "${field}" field`,
|
|
59592
|
-
fix: "Check your prisma
|
|
59593
|
-
docsUrl: docsUrlFor("CONFIG.VALIDATION_FAILED")
|
|
59596
|
+
fix: "Check your prisma.config.ts and ensure all required fields are provided",
|
|
59597
|
+
docsUrl: docsUrlFor("CONFIG.VALIDATION_FAILED"),
|
|
59598
|
+
meta: {
|
|
59599
|
+
field,
|
|
59600
|
+
...options?.section !== void 0 ? { section: options.section } : {}
|
|
59601
|
+
}
|
|
59594
59602
|
});
|
|
59595
59603
|
}
|
|
59596
59604
|
function postgresError(code, message, options) {
|
|
@@ -59601,7 +59609,7 @@ function postgresError(code, message, options) {
|
|
|
59601
59609
|
* — named by `operation` (e.g. `createTable`, `dropColumn`, `dataTransform`) —
|
|
59602
59610
|
* was invoked, but the migration was constructed without a `ControlStack`.
|
|
59603
59611
|
* Concrete authoring usage always goes through the migration CLI entrypoint,
|
|
59604
|
-
* which assembles a stack from the loaded `prisma
|
|
59612
|
+
* which assembles a stack from the loaded `prisma.config.ts`; reaching this
|
|
59605
59613
|
* error means a test fixture or ad-hoc consumer instantiated `PostgresMigration`
|
|
59606
59614
|
* with the no-arg form (legal for `operations` / `describe` introspection only).
|
|
59607
59615
|
*
|
|
@@ -59621,7 +59629,7 @@ function postgresError(code, message, options) {
|
|
|
59621
59629
|
function errorPostgresMigrationStackMissing(operation) {
|
|
59622
59630
|
return new CliStructuredError("MIGRATION.POSTGRES_CONTROL_STACK_MISSING", `PostgresMigration.${operation} requires a control adapter`, {
|
|
59623
59631
|
why: `PostgresMigration.${operation} was invoked on an instance constructed without a ControlStack, so the stored controlAdapter is undefined and the operation cannot lower its plan.`,
|
|
59624
|
-
fix: "Construct the migration via the migration CLI entrypoint (which assembles a ControlStack from the loaded prisma
|
|
59632
|
+
fix: "Construct the migration via the migration CLI entrypoint (which assembles a ControlStack from the loaded prisma.config.ts), or pass a ControlStack containing a Postgres adapter to the migration constructor in test fixtures.",
|
|
59625
59633
|
meta: { operation }
|
|
59626
59634
|
});
|
|
59627
59635
|
}
|
|
@@ -59984,6 +59992,22 @@ function normalizeSchemaNativeType(nativeType) {
|
|
|
59984
59992
|
if (trimmed.includes(" without time zone")) return trimmed.replace(" without time zone", "");
|
|
59985
59993
|
return trimmed;
|
|
59986
59994
|
}
|
|
59995
|
+
/**
|
|
59996
|
+
* A bug in Prisma Next, not a user error. Never catch this except at the
|
|
59997
|
+
* outermost boundary for crash reporting — an InternalError means an invariant
|
|
59998
|
+
* broke and the process cannot reliably continue. User-facing failures use
|
|
59999
|
+
* `structuredError` with a dotted code instead.
|
|
60000
|
+
*/
|
|
60001
|
+
var InternalError = class extends Error {
|
|
60002
|
+
isPrismaInternalError = true;
|
|
60003
|
+
constructor(message, options) {
|
|
60004
|
+
super(message, options?.cause !== void 0 ? { cause: options.cause } : void 0);
|
|
60005
|
+
this.name = "InternalError";
|
|
60006
|
+
}
|
|
60007
|
+
};
|
|
60008
|
+
function assertNever(value, message) {
|
|
60009
|
+
throw new InternalError(message ?? `Unreachable: unexpected value ${String(value)}`);
|
|
60010
|
+
}
|
|
59987
60011
|
function isJsonArray(value) {
|
|
59988
60012
|
return Array.isArray(value);
|
|
59989
60013
|
}
|
|
@@ -60002,170 +60026,6 @@ function frozenCodecRef(codec) {
|
|
|
60002
60026
|
...ifDefined("many", codec.many)
|
|
60003
60027
|
});
|
|
60004
60028
|
}
|
|
60005
|
-
function asNamespaceId(value) {
|
|
60006
|
-
return blindCast(value);
|
|
60007
|
-
}
|
|
60008
|
-
/**
|
|
60009
|
-
* Resolves the effective control policy for a storage-plane node.
|
|
60010
|
-
*
|
|
60011
|
-
* Precedence: node-level value → contract default → `'managed'`.
|
|
60012
|
-
*
|
|
60013
|
-
* Both parameters are optional raw values so this function stays node-type-agnostic
|
|
60014
|
-
* and can be called by any consumer (verifier, planner, etc.) without importing IR classes.
|
|
60015
|
-
*/
|
|
60016
|
-
function effectiveControlPolicy(nodeControl, defaultControlPolicy) {
|
|
60017
|
-
return nodeControl ?? defaultControlPolicy ?? "managed";
|
|
60018
|
-
}
|
|
60019
|
-
const CrossReferenceSchema = /* @__PURE__ */ blindCast(/* @__PURE__ */ type({
|
|
60020
|
-
"+": "reject",
|
|
60021
|
-
namespace: "string",
|
|
60022
|
-
model: "string",
|
|
60023
|
-
"space?": "string"
|
|
60024
|
-
}));
|
|
60025
|
-
/**
|
|
60026
|
-
* Runtime predicate for `ColumnDefaultLiteralInputValue`. Authoring layers
|
|
60027
|
-
* resolve template values from caller-supplied args (typed `unknown` at the
|
|
60028
|
-
* boundary) and need to validate before constructing a `ColumnDefault`.
|
|
60029
|
-
* Accepts JSON primitives, plain arrays/objects of JSON values, and `Date`
|
|
60030
|
-
* instances. Rejects functions, class instances (other than `Date`),
|
|
60031
|
-
* `undefined`, `bigint`, `symbol`, and arrays/objects containing those.
|
|
60032
|
-
*/
|
|
60033
|
-
function isColumnDefaultLiteralInputValue(value) {
|
|
60034
|
-
if (value === null) return true;
|
|
60035
|
-
const t = typeof value;
|
|
60036
|
-
if (t === "string" || t === "number" || t === "boolean") return true;
|
|
60037
|
-
if (value instanceof Date) return true;
|
|
60038
|
-
if (Array.isArray(value)) return value.every(isColumnDefaultLiteralInputValue);
|
|
60039
|
-
if (t === "object" && Object.getPrototypeOf(value) === Object.prototype) return Object.values(value).every(isColumnDefaultLiteralInputValue);
|
|
60040
|
-
return false;
|
|
60041
|
-
}
|
|
60042
|
-
function isColumnDefault(value) {
|
|
60043
|
-
if (typeof value !== "object" || value === null) return false;
|
|
60044
|
-
const kind = value.kind;
|
|
60045
|
-
if (kind === "literal") return "value" in value;
|
|
60046
|
-
if (kind === "function") return typeof value.expression === "string";
|
|
60047
|
-
return false;
|
|
60048
|
-
}
|
|
60049
|
-
var DdlColumnDefault = class {
|
|
60050
|
-
freeze() {
|
|
60051
|
-
Object.freeze(this);
|
|
60052
|
-
}
|
|
60053
|
-
};
|
|
60054
|
-
var LiteralColumnDefault = class extends DdlColumnDefault {
|
|
60055
|
-
kind = "literal";
|
|
60056
|
-
value;
|
|
60057
|
-
constructor(value) {
|
|
60058
|
-
super();
|
|
60059
|
-
if (!isColumnDefaultLiteralInputValue(value)) throw structuredError("CONTRACT.DEFAULT_INVALID", "Invalid column default literal value");
|
|
60060
|
-
this.value = value;
|
|
60061
|
-
this.freeze();
|
|
60062
|
-
}
|
|
60063
|
-
accept(visitor, ctx) {
|
|
60064
|
-
return visitor.literal(this, ctx);
|
|
60065
|
-
}
|
|
60066
|
-
};
|
|
60067
|
-
var FunctionColumnDefault = class extends DdlColumnDefault {
|
|
60068
|
-
kind = "function";
|
|
60069
|
-
expression;
|
|
60070
|
-
constructor(expression) {
|
|
60071
|
-
super();
|
|
60072
|
-
this.expression = expression;
|
|
60073
|
-
this.freeze();
|
|
60074
|
-
}
|
|
60075
|
-
accept(visitor, ctx) {
|
|
60076
|
-
return visitor.function(this, ctx);
|
|
60077
|
-
}
|
|
60078
|
-
};
|
|
60079
|
-
var DdlColumn = class {
|
|
60080
|
-
name;
|
|
60081
|
-
type;
|
|
60082
|
-
notNull;
|
|
60083
|
-
primaryKey;
|
|
60084
|
-
default;
|
|
60085
|
-
/** Codec identity for this column. When present, the DDL walker resolves the codec via `codecLookup.get(codecRef.codecId)` and calls `codec.encode(default.value, {})` to obtain the wire value before inlining the literal default into the DDL string. When absent, literal defaults follow RawSqlLiteral wire-scalar semantics (string / number / boolean / bigint / null / Uint8Array / Date inlined directly). */
|
|
60086
|
-
codecRef;
|
|
60087
|
-
constructor(options) {
|
|
60088
|
-
this.name = options.name;
|
|
60089
|
-
this.type = options.type;
|
|
60090
|
-
this.notNull = options.notNull;
|
|
60091
|
-
this.primaryKey = options.primaryKey;
|
|
60092
|
-
this.default = options.default;
|
|
60093
|
-
this.codecRef = options.codecRef;
|
|
60094
|
-
Object.freeze(this);
|
|
60095
|
-
}
|
|
60096
|
-
};
|
|
60097
|
-
var DdlNode = class {
|
|
60098
|
-
/**
|
|
60099
|
-
* Structural brand: every DDL node answers `true`. Lets {@link isDdlNode}
|
|
60100
|
-
* recognise any `DdlNode` subclass — including target-contributed kinds —
|
|
60101
|
-
* without a central kind registry that subclasses would have to register
|
|
60102
|
-
* into.
|
|
60103
|
-
*/
|
|
60104
|
-
isDdlNode() {
|
|
60105
|
-
return true;
|
|
60106
|
-
}
|
|
60107
|
-
freeze() {
|
|
60108
|
-
Object.freeze(this);
|
|
60109
|
-
}
|
|
60110
|
-
collectParamRefs() {
|
|
60111
|
-
return [];
|
|
60112
|
-
}
|
|
60113
|
-
};
|
|
60114
|
-
function isDdlNode(value) {
|
|
60115
|
-
return typeof value === "object" && value !== null && "isDdlNode" in value && typeof value.isDdlNode === "function";
|
|
60116
|
-
}
|
|
60117
|
-
/**
|
|
60118
|
-
* A composite (or single-column) PRIMARY KEY constraint on a `CreateTable`
|
|
60119
|
-
* node. When `name` is set, the adapter renders `CONSTRAINT <name> PRIMARY KEY
|
|
60120
|
-
* (…)`; otherwise it renders an anonymous `PRIMARY KEY (…)`.
|
|
60121
|
-
*
|
|
60122
|
-
* Frozen on construction — immutable after creation.
|
|
60123
|
-
*/
|
|
60124
|
-
var PrimaryKeyConstraint = class {
|
|
60125
|
-
kind = "primary-key";
|
|
60126
|
-
columns;
|
|
60127
|
-
name;
|
|
60128
|
-
constructor(options) {
|
|
60129
|
-
this.columns = Object.freeze([...options.columns]);
|
|
60130
|
-
this.name = options.name;
|
|
60131
|
-
Object.freeze(this);
|
|
60132
|
-
}
|
|
60133
|
-
};
|
|
60134
|
-
/**
|
|
60135
|
-
* A table-level CHECK constraint carrying a raw SQL predicate expression. Used
|
|
60136
|
-
* for checks that are not enum value-set restrictions — e.g. the element-non-null
|
|
60137
|
-
* constraint on a scalar-array column (`array_position(col, NULL) IS NULL`).
|
|
60138
|
-
* The `expression` is emitted verbatim, so callers must supply safe,
|
|
60139
|
-
* pre-validated SQL.
|
|
60140
|
-
*
|
|
60141
|
-
* Frozen on construction — immutable after creation.
|
|
60142
|
-
*/
|
|
60143
|
-
var CheckExpressionConstraint = class {
|
|
60144
|
-
kind = "check-expression";
|
|
60145
|
-
name;
|
|
60146
|
-
expression;
|
|
60147
|
-
constructor(options) {
|
|
60148
|
-
this.name = options.name;
|
|
60149
|
-
this.expression = options.expression;
|
|
60150
|
-
Object.freeze(this);
|
|
60151
|
-
}
|
|
60152
|
-
};
|
|
60153
|
-
/**
|
|
60154
|
-
* A bug in Prisma Next, not a user error. Never catch this except at the
|
|
60155
|
-
* outermost boundary for crash reporting — an InternalError means an invariant
|
|
60156
|
-
* broke and the process cannot reliably continue. User-facing failures use
|
|
60157
|
-
* `structuredError` with a dotted code instead.
|
|
60158
|
-
*/
|
|
60159
|
-
var InternalError = class extends Error {
|
|
60160
|
-
isPrismaInternalError = true;
|
|
60161
|
-
constructor(message, options) {
|
|
60162
|
-
super(message, options?.cause !== void 0 ? { cause: options.cause } : void 0);
|
|
60163
|
-
this.name = "InternalError";
|
|
60164
|
-
}
|
|
60165
|
-
};
|
|
60166
|
-
function assertNever(value, message) {
|
|
60167
|
-
throw new InternalError(message ?? `Unreachable: unexpected value ${String(value)}`);
|
|
60168
|
-
}
|
|
60169
60029
|
const toAnyExpressionVisitor = {
|
|
60170
60030
|
columnRef: (expr) => expr,
|
|
60171
60031
|
identifierRef: (expr) => expr,
|
|
@@ -60378,7 +60238,7 @@ var FunctionSource = class FunctionSource extends FromSource {
|
|
|
60378
60238
|
ordinality;
|
|
60379
60239
|
constructor(fn, args, alias, ordinality = false) {
|
|
60380
60240
|
super();
|
|
60381
|
-
if (alias?.columnAliases?.length === 0) throw structuredError("
|
|
60241
|
+
if (alias?.columnAliases?.length === 0) throw structuredError("RUNTIME.AST_INVALID", "FunctionSource column aliases must not be empty", { meta: {
|
|
60382
60242
|
kind: "function-source",
|
|
60383
60243
|
field: "columnAliases"
|
|
60384
60244
|
} });
|
|
@@ -60676,7 +60536,7 @@ var CaseExpr = class CaseExpr extends Expression {
|
|
|
60676
60536
|
elseExpr;
|
|
60677
60537
|
constructor(branches, elseExpr) {
|
|
60678
60538
|
super();
|
|
60679
|
-
if (branches.length === 0) throw structuredError("
|
|
60539
|
+
if (branches.length === 0) throw structuredError("RUNTIME.AST_INVALID", "CaseExpr requires at least one branch", { meta: {
|
|
60680
60540
|
kind: "case",
|
|
60681
60541
|
field: "branches"
|
|
60682
60542
|
} });
|
|
@@ -61329,6 +61189,154 @@ var UpdateAst = class UpdateAst extends QueryAst {
|
|
|
61329
61189
|
return this;
|
|
61330
61190
|
}
|
|
61331
61191
|
};
|
|
61192
|
+
function asNamespaceId(value) {
|
|
61193
|
+
return blindCast(value);
|
|
61194
|
+
}
|
|
61195
|
+
/**
|
|
61196
|
+
* Resolves the effective control policy for a storage-plane node.
|
|
61197
|
+
*
|
|
61198
|
+
* Precedence: node-level value → contract default → `'managed'`.
|
|
61199
|
+
*
|
|
61200
|
+
* Both parameters are optional raw values so this function stays node-type-agnostic
|
|
61201
|
+
* and can be called by any consumer (verifier, planner, etc.) without importing IR classes.
|
|
61202
|
+
*/
|
|
61203
|
+
function effectiveControlPolicy(nodeControl, defaultControlPolicy) {
|
|
61204
|
+
return nodeControl ?? defaultControlPolicy ?? "managed";
|
|
61205
|
+
}
|
|
61206
|
+
const CrossReferenceSchema = /* @__PURE__ */ blindCast(/* @__PURE__ */ type({
|
|
61207
|
+
"+": "reject",
|
|
61208
|
+
namespace: "string",
|
|
61209
|
+
model: "string",
|
|
61210
|
+
"space?": "string"
|
|
61211
|
+
}));
|
|
61212
|
+
/**
|
|
61213
|
+
* Runtime predicate for `ColumnDefaultLiteralInputValue`. Authoring layers
|
|
61214
|
+
* resolve template values from caller-supplied args (typed `unknown` at the
|
|
61215
|
+
* boundary) and need to validate before constructing a `ColumnDefault`.
|
|
61216
|
+
* Accepts JSON primitives, plain arrays/objects of JSON values, and `Date`
|
|
61217
|
+
* instances. Rejects functions, class instances (other than `Date`),
|
|
61218
|
+
* `undefined`, `bigint`, `symbol`, and arrays/objects containing those.
|
|
61219
|
+
*/
|
|
61220
|
+
function isColumnDefaultLiteralInputValue(value) {
|
|
61221
|
+
if (value === null) return true;
|
|
61222
|
+
const t = typeof value;
|
|
61223
|
+
if (t === "string" || t === "number" || t === "boolean") return true;
|
|
61224
|
+
if (value instanceof Date) return true;
|
|
61225
|
+
if (Array.isArray(value)) return value.every(isColumnDefaultLiteralInputValue);
|
|
61226
|
+
if (t === "object" && Object.getPrototypeOf(value) === Object.prototype) return Object.values(value).every(isColumnDefaultLiteralInputValue);
|
|
61227
|
+
return false;
|
|
61228
|
+
}
|
|
61229
|
+
function isColumnDefault(value) {
|
|
61230
|
+
if (typeof value !== "object" || value === null) return false;
|
|
61231
|
+
const kind = value.kind;
|
|
61232
|
+
if (kind === "literal") return "value" in value;
|
|
61233
|
+
if (kind === "function") return typeof value.expression === "string";
|
|
61234
|
+
return false;
|
|
61235
|
+
}
|
|
61236
|
+
var DdlColumnDefault = class {
|
|
61237
|
+
freeze() {
|
|
61238
|
+
Object.freeze(this);
|
|
61239
|
+
}
|
|
61240
|
+
};
|
|
61241
|
+
var LiteralColumnDefault = class extends DdlColumnDefault {
|
|
61242
|
+
kind = "literal";
|
|
61243
|
+
value;
|
|
61244
|
+
constructor(value) {
|
|
61245
|
+
super();
|
|
61246
|
+
if (!isColumnDefaultLiteralInputValue(value)) throw structuredError("CONTRACT.DEFAULT_INVALID", "Invalid column default literal value");
|
|
61247
|
+
this.value = value;
|
|
61248
|
+
this.freeze();
|
|
61249
|
+
}
|
|
61250
|
+
accept(visitor, ctx) {
|
|
61251
|
+
return visitor.literal(this, ctx);
|
|
61252
|
+
}
|
|
61253
|
+
};
|
|
61254
|
+
var FunctionColumnDefault = class extends DdlColumnDefault {
|
|
61255
|
+
kind = "function";
|
|
61256
|
+
expression;
|
|
61257
|
+
constructor(expression) {
|
|
61258
|
+
super();
|
|
61259
|
+
this.expression = expression;
|
|
61260
|
+
this.freeze();
|
|
61261
|
+
}
|
|
61262
|
+
accept(visitor, ctx) {
|
|
61263
|
+
return visitor.function(this, ctx);
|
|
61264
|
+
}
|
|
61265
|
+
};
|
|
61266
|
+
var DdlColumn = class {
|
|
61267
|
+
name;
|
|
61268
|
+
type;
|
|
61269
|
+
notNull;
|
|
61270
|
+
primaryKey;
|
|
61271
|
+
default;
|
|
61272
|
+
/** Codec identity for this column. When present, the DDL walker resolves the codec via `codecLookup.get(codecRef.codecId)` and runs the literal default through both declared conversions in order — `codec.encode(codec.decodeJson(default.value), {})` — to obtain the wire value it inlines into the DDL string. The read-back is what makes the pair sound: a contract stores a literal default in the codec's canonical JSON, which is not always the application value `encode` takes (`pg/int8@1` stores decimal text for a `bigint`). A `Date` is the one authored value JSON has no notation for, so it arrives as itself and skips `decodeJson`. When absent, literal defaults follow RawSqlLiteral wire-scalar semantics (string / number / boolean / bigint / null / Uint8Array / Date inlined directly). */
|
|
61273
|
+
codecRef;
|
|
61274
|
+
constructor(options) {
|
|
61275
|
+
this.name = options.name;
|
|
61276
|
+
this.type = options.type;
|
|
61277
|
+
this.notNull = options.notNull;
|
|
61278
|
+
this.primaryKey = options.primaryKey;
|
|
61279
|
+
this.default = options.default;
|
|
61280
|
+
this.codecRef = options.codecRef;
|
|
61281
|
+
Object.freeze(this);
|
|
61282
|
+
}
|
|
61283
|
+
};
|
|
61284
|
+
var DdlNode = class {
|
|
61285
|
+
/**
|
|
61286
|
+
* Structural brand: every DDL node answers `true`. Lets {@link isDdlNode}
|
|
61287
|
+
* recognise any `DdlNode` subclass — including target-contributed kinds —
|
|
61288
|
+
* without a central kind registry that subclasses would have to register
|
|
61289
|
+
* into.
|
|
61290
|
+
*/
|
|
61291
|
+
isDdlNode() {
|
|
61292
|
+
return true;
|
|
61293
|
+
}
|
|
61294
|
+
freeze() {
|
|
61295
|
+
Object.freeze(this);
|
|
61296
|
+
}
|
|
61297
|
+
collectParamRefs() {
|
|
61298
|
+
return [];
|
|
61299
|
+
}
|
|
61300
|
+
};
|
|
61301
|
+
function isDdlNode(value) {
|
|
61302
|
+
return typeof value === "object" && value !== null && "isDdlNode" in value && typeof value.isDdlNode === "function";
|
|
61303
|
+
}
|
|
61304
|
+
/**
|
|
61305
|
+
* A composite (or single-column) PRIMARY KEY constraint on a `CreateTable`
|
|
61306
|
+
* node. When `name` is set, the adapter renders `CONSTRAINT <name> PRIMARY KEY
|
|
61307
|
+
* (…)`; otherwise it renders an anonymous `PRIMARY KEY (…)`.
|
|
61308
|
+
*
|
|
61309
|
+
* Frozen on construction — immutable after creation.
|
|
61310
|
+
*/
|
|
61311
|
+
var PrimaryKeyConstraint = class {
|
|
61312
|
+
kind = "primary-key";
|
|
61313
|
+
columns;
|
|
61314
|
+
name;
|
|
61315
|
+
constructor(options) {
|
|
61316
|
+
this.columns = Object.freeze([...options.columns]);
|
|
61317
|
+
this.name = options.name;
|
|
61318
|
+
Object.freeze(this);
|
|
61319
|
+
}
|
|
61320
|
+
};
|
|
61321
|
+
/**
|
|
61322
|
+
* A table-level CHECK constraint carrying a raw SQL predicate expression. Used
|
|
61323
|
+
* for checks that are not enum value-set restrictions — e.g. the element-non-null
|
|
61324
|
+
* constraint on a scalar-array column (`array_position(col, NULL) IS NULL`).
|
|
61325
|
+
* The `expression` is emitted verbatim, so callers must supply safe,
|
|
61326
|
+
* pre-validated SQL.
|
|
61327
|
+
*
|
|
61328
|
+
* Frozen on construction — immutable after creation.
|
|
61329
|
+
*/
|
|
61330
|
+
var CheckExpressionConstraint = class {
|
|
61331
|
+
kind = "check-expression";
|
|
61332
|
+
name;
|
|
61333
|
+
expression;
|
|
61334
|
+
constructor(options) {
|
|
61335
|
+
this.name = options.name;
|
|
61336
|
+
this.expression = options.expression;
|
|
61337
|
+
Object.freeze(this);
|
|
61338
|
+
}
|
|
61339
|
+
};
|
|
61332
61340
|
/**
|
|
61333
61341
|
* Walks an AST's parameter references in first-encounter order and dedupes
|
|
61334
61342
|
* by ParamRef identity. The single canonical helper used by every consumer
|
|
@@ -62026,10 +62034,12 @@ const PG_INT_CODEC_ID = "pg/int@1";
|
|
|
62026
62034
|
const PG_INT2_CODEC_ID = "pg/int2@1";
|
|
62027
62035
|
const PG_INT4_CODEC_ID = "pg/int4@1";
|
|
62028
62036
|
const PG_INT8_CODEC_ID = "pg/int8@1";
|
|
62037
|
+
const PG_INT8_NUMBER_CODEC_ID = "pg/int8number@1";
|
|
62029
62038
|
const PG_FLOAT_CODEC_ID = "pg/float@1";
|
|
62030
62039
|
const PG_FLOAT4_CODEC_ID = "pg/float4@1";
|
|
62031
62040
|
const PG_FLOAT8_CODEC_ID = "pg/float8@1";
|
|
62032
62041
|
const PG_NUMERIC_CODEC_ID = "pg/numeric@1";
|
|
62042
|
+
const PG_UNBOUNDED_INT_CODEC_ID = "pg/unboundedint@1";
|
|
62033
62043
|
const PG_BOOL_CODEC_ID = "pg/bool@1";
|
|
62034
62044
|
const PG_BIT_CODEC_ID = "pg/bit@1";
|
|
62035
62045
|
const PG_VARBIT_CODEC_ID = "pg/varbit@1";
|
|
@@ -62152,16 +62162,19 @@ function buildPostgresCodecDescriptorRegistry(descriptors) {
|
|
|
62152
62162
|
for (const descriptor of descriptors) {
|
|
62153
62163
|
if (!isPostgresCodecDescriptor(descriptor)) {
|
|
62154
62164
|
const codecId = candidateCodecId(descriptor);
|
|
62155
|
-
throw structuredError("
|
|
62165
|
+
throw structuredError("RUNTIME.CODEC_DESCRIPTOR_INVALID", `Codec descriptor '${codecId}' is not a valid PostgreSQL codec descriptor.`, {
|
|
62156
62166
|
why: "PostgreSQL codec registries require the postgres-codec discriminant and complete target descriptor methods.",
|
|
62157
62167
|
fix: "Extend PostgresCodecDescriptor or adapt a generic descriptor with postgresCodec().",
|
|
62158
62168
|
meta: { codecId }
|
|
62159
62169
|
});
|
|
62160
62170
|
}
|
|
62161
|
-
if (byId.has(descriptor.codecId)) throw structuredError("
|
|
62171
|
+
if (byId.has(descriptor.codecId)) throw structuredError("RUNTIME.DUPLICATE_CODEC", `Duplicate PostgreSQL codec descriptor id '${descriptor.codecId}'.`, {
|
|
62162
62172
|
why: "Each codecId must resolve to exactly one PostgreSQL descriptor during registry composition.",
|
|
62163
62173
|
fix: "Remove the duplicate target, adapter, or extension contribution.",
|
|
62164
|
-
meta: {
|
|
62174
|
+
meta: {
|
|
62175
|
+
codecId: descriptor.codecId,
|
|
62176
|
+
target: "postgres"
|
|
62177
|
+
}
|
|
62165
62178
|
});
|
|
62166
62179
|
byId.set(descriptor.codecId, descriptor);
|
|
62167
62180
|
}
|
|
@@ -62461,6 +62474,40 @@ function normalizeSqlBody(sql) {
|
|
|
62461
62474
|
}
|
|
62462
62475
|
/**
|
|
62463
62476
|
* Returns the first 8 lowercase hex characters of the SHA-256 digest over the
|
|
62477
|
+
* canonical content tuple for a check constraint:
|
|
62478
|
+
*
|
|
62479
|
+
* [normalizeSqlBody(expression)]
|
|
62480
|
+
*
|
|
62481
|
+
* The predicate is the whole of a check's content — the constraint name,
|
|
62482
|
+
* schema, and table are orthogonal to its equivalence. The one-element tuple
|
|
62483
|
+
* keeps the encoding in the same shape as the index and RLS tuples so a member
|
|
62484
|
+
* can be added later without re-reading which encoding a kind uses.
|
|
62485
|
+
*
|
|
62486
|
+
* The tuple order and encoding are a stability commitment: any change
|
|
62487
|
+
* re-suffixes every wire name.
|
|
62488
|
+
*/
|
|
62489
|
+
function computeCheckContentHash(expression) {
|
|
62490
|
+
const tuple = JSON.stringify([normalizeSqlBody(expression)]);
|
|
62491
|
+
return createHash("sha256").update(tuple).digest("hex").slice(0, 8);
|
|
62492
|
+
}
|
|
62493
|
+
/** The trailing segment a check's wire-name prefix carries, per kind. */
|
|
62494
|
+
const CHECK_KIND_SUFFIX = {
|
|
62495
|
+
membership: "check",
|
|
62496
|
+
elementNotNull: "elem_not_null"
|
|
62497
|
+
};
|
|
62498
|
+
/**
|
|
62499
|
+
* Composes the wire-name prefix of a derived CHECK constraint:
|
|
62500
|
+
* `${table}_${column}_${kindSuffix}`, capped at the wire-name byte budget.
|
|
62501
|
+
* Shared by contract authoring (naming emitted checks) and `contract infer`
|
|
62502
|
+
* (recomputing the name a derived check would carry), so truncated and
|
|
62503
|
+
* multibyte prefixes match by construction.
|
|
62504
|
+
*/
|
|
62505
|
+
function composeCheckWirePrefix(tableName, columnName, kind) {
|
|
62506
|
+
return truncateToWireNamePrefixBytes(`${tableName}_${columnName}_${CHECK_KIND_SUFFIX[kind]}`);
|
|
62507
|
+
}
|
|
62508
|
+
Object.keys(CHECK_KIND_SUFFIX).filter((kind) => kind in CHECK_KIND_SUFFIX);
|
|
62509
|
+
/**
|
|
62510
|
+
* Returns the first 8 lowercase hex characters of the SHA-256 digest over the
|
|
62464
62511
|
* canonical content tuple for an index:
|
|
62465
62512
|
*
|
|
62466
62513
|
* [normalizeSqlBody(expression), normalizeSqlBody(where), columns, unique, type, sortedOptions]
|
|
@@ -62501,17 +62548,40 @@ function computeIndexContentHash(parts) {
|
|
|
62501
62548
|
]);
|
|
62502
62549
|
return createHash("sha256").update(tuple).digest("hex").slice(0, 8);
|
|
62503
62550
|
}
|
|
62551
|
+
const utf8 = new TextEncoder();
|
|
62552
|
+
/** UTF-8 byte length — the unit Postgres measures identifiers in. */
|
|
62553
|
+
function byteLength(value) {
|
|
62554
|
+
return utf8.encode(value).length;
|
|
62555
|
+
}
|
|
62504
62556
|
/**
|
|
62505
|
-
* Rejects a wire-name prefix over {@link
|
|
62557
|
+
* Rejects a wire-name prefix over {@link WIRE_NAME_PREFIX_MAX_BYTES}.
|
|
62506
62558
|
* `subject` opens the error message (e.g. `defineContract: policy prefix`).
|
|
62507
62559
|
*/
|
|
62508
62560
|
function assertWireNamePrefixLength(prefix, subject) {
|
|
62509
|
-
if (prefix
|
|
62561
|
+
if (byteLength(prefix) > 54) throw structuredError("CONTRACT.WIRE_NAME_PREFIX_TOO_LONG", `${subject} "${prefix}" exceeds the 54-byte maximum (Postgres identifiers cap at 63 bytes and the wire name appends a 9-byte hash suffix).`, { meta: {
|
|
62510
62562
|
prefix,
|
|
62511
|
-
|
|
62563
|
+
maxBytes: 54
|
|
62512
62564
|
} });
|
|
62513
62565
|
}
|
|
62514
62566
|
/**
|
|
62567
|
+
* Shortens a DERIVED wire-name prefix to {@link WIRE_NAME_PREFIX_MAX_BYTES},
|
|
62568
|
+
* cutting on a code-point boundary so a multibyte character is never split.
|
|
62569
|
+
* Only derived prefixes truncate — an authored one throws
|
|
62570
|
+
* ({@link assertWireNamePrefixLength}), because its author can shorten it.
|
|
62571
|
+
*/
|
|
62572
|
+
function truncateToWireNamePrefixBytes(prefix) {
|
|
62573
|
+
if (byteLength(prefix) <= 54) return prefix;
|
|
62574
|
+
let out = "";
|
|
62575
|
+
let bytes = 0;
|
|
62576
|
+
for (const character of prefix) {
|
|
62577
|
+
const size = byteLength(character);
|
|
62578
|
+
if (bytes + size > 54) break;
|
|
62579
|
+
out += character;
|
|
62580
|
+
bytes += size;
|
|
62581
|
+
}
|
|
62582
|
+
return out;
|
|
62583
|
+
}
|
|
62584
|
+
/**
|
|
62515
62585
|
* SQL family IR node base. Carries the family-level `kind` discriminator
|
|
62516
62586
|
* `'sql'` and inherits the framework's `freezeNode` affordance.
|
|
62517
62587
|
*
|
|
@@ -62556,6 +62626,41 @@ var SqlNode = class extends IRNodeBase {
|
|
|
62556
62626
|
}
|
|
62557
62627
|
};
|
|
62558
62628
|
/**
|
|
62629
|
+
* SQL Contract IR node for a table-level check constraint, name-identified:
|
|
62630
|
+
* `name` is the full physical name; a present `prefix` marks the constraint as
|
|
62631
|
+
* wire-named (`name` is `formatWireName(prefix, <8hex>)` over the expression's
|
|
62632
|
+
* content hash), an absent `prefix` marks it exact (the name is adopted
|
|
62633
|
+
* verbatim). This is the convention indexes and RLS policies already use — see
|
|
62634
|
+
* ADR 234, "Content-addressed wire names for Postgres-normalized objects".
|
|
62635
|
+
*
|
|
62636
|
+
* The predicate is opaque: one SQL string, never parsed and never rendered
|
|
62637
|
+
* from structured parts. A database reprints predicates in its own normalized
|
|
62638
|
+
* form, so a wire-named check is compared by name — the hash already commits
|
|
62639
|
+
* to the expression the contract declared.
|
|
62640
|
+
*/
|
|
62641
|
+
var CheckConstraint = class CheckConstraint extends SqlNode {
|
|
62642
|
+
name;
|
|
62643
|
+
expression;
|
|
62644
|
+
constructor(input) {
|
|
62645
|
+
super();
|
|
62646
|
+
const name = nameOf(input.naming);
|
|
62647
|
+
if (name.length === 0) throw new ContractValidationError("CheckConstraint: every check constraint carries a full physical name.", "storage");
|
|
62648
|
+
this.name = name;
|
|
62649
|
+
if (input.naming.kind === "wire") this.prefix = input.naming.prefix;
|
|
62650
|
+
this.expression = input.expression;
|
|
62651
|
+
freezeNode(this);
|
|
62652
|
+
}
|
|
62653
|
+
/**
|
|
62654
|
+
* Normalizes either shape into an instance: an existing `CheckConstraint`
|
|
62655
|
+
* passes through, canonical input is constructed. Callers that accept
|
|
62656
|
+
* "instance or input" go through this, so the constructor keeps one
|
|
62657
|
+
* canonical shape instead of widening to a union.
|
|
62658
|
+
*/
|
|
62659
|
+
static from(value) {
|
|
62660
|
+
return value instanceof CheckConstraint ? value : new CheckConstraint(value);
|
|
62661
|
+
}
|
|
62662
|
+
};
|
|
62663
|
+
/**
|
|
62559
62664
|
* SQL Contract IR node for a table-level secondary index, name-identified:
|
|
62560
62665
|
* `name` is the full physical name; a present `prefix` marks the index as
|
|
62561
62666
|
* wire-named (`name` is `formatWireName(prefix, <8hex>)`), an absent `prefix`
|
|
@@ -62573,7 +62678,7 @@ var SqlNode = class extends IRNodeBase {
|
|
|
62573
62678
|
* alias one (e.g.
|
|
62574
62679
|
* `import { Index as SqlIndexNode } from '@internal/sql-contract/types'`).
|
|
62575
62680
|
*/
|
|
62576
|
-
var Index = class extends SqlNode {
|
|
62681
|
+
var Index = class Index extends SqlNode {
|
|
62577
62682
|
name;
|
|
62578
62683
|
unique;
|
|
62579
62684
|
constructor(input) {
|
|
@@ -62591,31 +62696,8 @@ var Index = class extends SqlNode {
|
|
|
62591
62696
|
if (input.options !== void 0) this.options = input.options;
|
|
62592
62697
|
freezeNode(this);
|
|
62593
62698
|
}
|
|
62594
|
-
|
|
62595
|
-
|
|
62596
|
-
* SQL Contract IR node for a table-level check constraint that restricts
|
|
62597
|
-
* a column to the permitted values of a value-set.
|
|
62598
|
-
*
|
|
62599
|
-
* The constraint is **structured** (names a column and a value-set
|
|
62600
|
-
* reference), not a raw SQL expression. Each target renders its own DDL
|
|
62601
|
-
* from the structured form, keeping the contract target-agnostic.
|
|
62602
|
-
*
|
|
62603
|
-
* Construction is idempotent: passing an existing `CheckConstraint`
|
|
62604
|
-
* instance as input produces a new instance with identical fields.
|
|
62605
|
-
* The constructor does not use `instanceof` for input discrimination —
|
|
62606
|
-
* it reads plain named properties, which is sufficient since
|
|
62607
|
-
* `CheckConstraintInput` is a structural type.
|
|
62608
|
-
*/
|
|
62609
|
-
var CheckConstraint = class extends SqlNode {
|
|
62610
|
-
name;
|
|
62611
|
-
column;
|
|
62612
|
-
valueSet;
|
|
62613
|
-
constructor(input) {
|
|
62614
|
-
super();
|
|
62615
|
-
this.name = input.name;
|
|
62616
|
-
this.column = input.column;
|
|
62617
|
-
this.valueSet = input.valueSet;
|
|
62618
|
-
freezeNode(this);
|
|
62699
|
+
static from(value) {
|
|
62700
|
+
return value instanceof Index ? value : new Index(value);
|
|
62619
62701
|
}
|
|
62620
62702
|
};
|
|
62621
62703
|
/**
|
|
@@ -62634,7 +62716,7 @@ var CheckConstraint = class extends SqlNode {
|
|
|
62634
62716
|
* Use `UNBOUND_NAMESPACE_ID` from `@internal/framework-components/ir`
|
|
62635
62717
|
* as the sentinel `namespaceId` for single-namespace (unbound) references.
|
|
62636
62718
|
*/
|
|
62637
|
-
var ForeignKeyReference = class extends SqlNode {
|
|
62719
|
+
var ForeignKeyReference = class ForeignKeyReference extends SqlNode {
|
|
62638
62720
|
namespaceId;
|
|
62639
62721
|
tableName;
|
|
62640
62722
|
columns;
|
|
@@ -62646,6 +62728,9 @@ var ForeignKeyReference = class extends SqlNode {
|
|
|
62646
62728
|
if (input.spaceId !== void 0) this.spaceId = input.spaceId;
|
|
62647
62729
|
freezeNode(this);
|
|
62648
62730
|
}
|
|
62731
|
+
static from(value) {
|
|
62732
|
+
return value instanceof ForeignKeyReference ? value : new ForeignKeyReference(value);
|
|
62733
|
+
}
|
|
62649
62734
|
};
|
|
62650
62735
|
/**
|
|
62651
62736
|
* SQL Contract IR node for a table-level foreign-key declaration — the
|
|
@@ -62667,23 +62752,26 @@ var ForeignKeyReference = class extends SqlNode {
|
|
|
62667
62752
|
* regardless of whether the input was a JSON literal or an already-constructed
|
|
62668
62753
|
* class instance.
|
|
62669
62754
|
*/
|
|
62670
|
-
var ForeignKey = class extends SqlNode {
|
|
62755
|
+
var ForeignKey = class ForeignKey extends SqlNode {
|
|
62671
62756
|
source;
|
|
62672
62757
|
target;
|
|
62673
62758
|
constructor(input) {
|
|
62674
62759
|
super();
|
|
62675
|
-
this.source =
|
|
62676
|
-
this.target =
|
|
62760
|
+
this.source = ForeignKeyReference.from(input.source);
|
|
62761
|
+
this.target = ForeignKeyReference.from(input.target);
|
|
62677
62762
|
if (input.name !== void 0) this.name = input.name;
|
|
62678
62763
|
if (input.onDelete !== void 0) this.onDelete = input.onDelete;
|
|
62679
62764
|
if (input.onUpdate !== void 0) this.onUpdate = input.onUpdate;
|
|
62680
62765
|
freezeNode(this);
|
|
62681
62766
|
}
|
|
62767
|
+
static from(value) {
|
|
62768
|
+
return value instanceof ForeignKey ? value : new ForeignKey(value);
|
|
62769
|
+
}
|
|
62682
62770
|
};
|
|
62683
62771
|
/**
|
|
62684
62772
|
* SQL Contract IR node for a table's primary-key constraint.
|
|
62685
62773
|
*/
|
|
62686
|
-
var PrimaryKey$1 = class extends SqlNode {
|
|
62774
|
+
var PrimaryKey$1 = class PrimaryKey extends SqlNode {
|
|
62687
62775
|
columns;
|
|
62688
62776
|
constructor(input) {
|
|
62689
62777
|
super();
|
|
@@ -62691,6 +62779,9 @@ var PrimaryKey$1 = class extends SqlNode {
|
|
|
62691
62779
|
if (input.name !== void 0) this.name = input.name;
|
|
62692
62780
|
freezeNode(this);
|
|
62693
62781
|
}
|
|
62782
|
+
static from(value) {
|
|
62783
|
+
return value instanceof PrimaryKey ? value : new PrimaryKey(value);
|
|
62784
|
+
}
|
|
62694
62785
|
};
|
|
62695
62786
|
/**
|
|
62696
62787
|
* SQL Contract IR node for a single column entry in `StorageTable.columns`.
|
|
@@ -62705,7 +62796,7 @@ var PrimaryKey$1 = class extends SqlNode {
|
|
|
62705
62796
|
* in the parent `StorageTable.columns: Record<string, StorageColumn>`
|
|
62706
62797
|
* map, so a `name` field would be redundant with the key.
|
|
62707
62798
|
*/
|
|
62708
|
-
var StorageColumn = class extends SqlNode {
|
|
62799
|
+
var StorageColumn = class StorageColumn extends SqlNode {
|
|
62709
62800
|
nativeType;
|
|
62710
62801
|
codecId;
|
|
62711
62802
|
nullable;
|
|
@@ -62715,6 +62806,7 @@ var StorageColumn = class extends SqlNode {
|
|
|
62715
62806
|
this.codecId = input.codecId;
|
|
62716
62807
|
this.nullable = input.nullable;
|
|
62717
62808
|
if (input.many !== void 0) this.many = input.many;
|
|
62809
|
+
if (input.noCheck !== void 0) this.noCheck = input.noCheck;
|
|
62718
62810
|
if (input.typeParams !== void 0) this.typeParams = input.typeParams;
|
|
62719
62811
|
if (input.typeRef !== void 0) this.typeRef = input.typeRef;
|
|
62720
62812
|
if (input.default !== void 0) this.default = input.default;
|
|
@@ -62722,11 +62814,14 @@ var StorageColumn = class extends SqlNode {
|
|
|
62722
62814
|
if (input.valueSet !== void 0) this.valueSet = input.valueSet;
|
|
62723
62815
|
freezeNode(this);
|
|
62724
62816
|
}
|
|
62817
|
+
static from(value) {
|
|
62818
|
+
return value instanceof StorageColumn ? value : new StorageColumn(value);
|
|
62819
|
+
}
|
|
62725
62820
|
};
|
|
62726
62821
|
/**
|
|
62727
62822
|
* SQL Contract IR node for a table-level unique constraint.
|
|
62728
62823
|
*/
|
|
62729
|
-
var UniqueConstraint = class extends SqlNode {
|
|
62824
|
+
var UniqueConstraint = class UniqueConstraint extends SqlNode {
|
|
62730
62825
|
columns;
|
|
62731
62826
|
constructor(input) {
|
|
62732
62827
|
super();
|
|
@@ -62734,6 +62829,9 @@ var UniqueConstraint = class extends SqlNode {
|
|
|
62734
62829
|
if (input.name !== void 0) this.name = input.name;
|
|
62735
62830
|
freezeNode(this);
|
|
62736
62831
|
}
|
|
62832
|
+
static from(value) {
|
|
62833
|
+
return value instanceof UniqueConstraint ? value : new UniqueConstraint(value);
|
|
62834
|
+
}
|
|
62737
62835
|
};
|
|
62738
62836
|
/**
|
|
62739
62837
|
* SQL Contract IR node for a single table entry in a namespace's
|
|
@@ -62754,13 +62852,13 @@ var StorageTable = class StorageTable extends SqlNode {
|
|
|
62754
62852
|
foreignKeys;
|
|
62755
62853
|
constructor(input) {
|
|
62756
62854
|
super();
|
|
62757
|
-
this.columns = Object.freeze(Object.fromEntries(Object.entries(input.columns).map(([name, col]) => [name,
|
|
62758
|
-
if (input.primaryKey !== void 0) this.primaryKey =
|
|
62759
|
-
this.uniques = Object.freeze(input.uniques.map(
|
|
62760
|
-
this.indexes = Object.freeze(input.indexes.map(
|
|
62761
|
-
this.foreignKeys = Object.freeze(input.foreignKeys.map(
|
|
62855
|
+
this.columns = Object.freeze(Object.fromEntries(Object.entries(input.columns).map(([name, col]) => [name, StorageColumn.from(col)])));
|
|
62856
|
+
if (input.primaryKey !== void 0) this.primaryKey = PrimaryKey$1.from(input.primaryKey);
|
|
62857
|
+
this.uniques = Object.freeze(input.uniques.map(UniqueConstraint.from));
|
|
62858
|
+
this.indexes = Object.freeze(input.indexes.map(Index.from));
|
|
62859
|
+
this.foreignKeys = Object.freeze(input.foreignKeys.map(ForeignKey.from));
|
|
62762
62860
|
if (input.control !== void 0) this.control = input.control;
|
|
62763
|
-
if (input.checks !== void 0 && input.checks.length > 0) this.checks = Object.freeze(input.checks.map(
|
|
62861
|
+
if (input.checks !== void 0 && input.checks.length > 0) this.checks = Object.freeze(input.checks.map(CheckConstraint.from));
|
|
62764
62862
|
freezeNode(this);
|
|
62765
62863
|
}
|
|
62766
62864
|
/**
|
|
@@ -62806,6 +62904,16 @@ var StorageValueSet = class extends SqlNode {
|
|
|
62806
62904
|
}
|
|
62807
62905
|
};
|
|
62808
62906
|
/**
|
|
62907
|
+
* Hydrates one stored check constraint into constructor input. `parseNaming`
|
|
62908
|
+
* is what rejects a hand-edited file whose `prefix` and `name` disagree.
|
|
62909
|
+
*/
|
|
62910
|
+
function checkConstraintInputFromSerialized(flat) {
|
|
62911
|
+
return {
|
|
62912
|
+
naming: parseNaming(flat.name, flat.prefix),
|
|
62913
|
+
expression: flat.expression
|
|
62914
|
+
};
|
|
62915
|
+
}
|
|
62916
|
+
/**
|
|
62809
62917
|
* Hydrates one stored index into constructor input. The parameter is typed
|
|
62810
62918
|
* but the values are whatever the file held, so each field the union depends
|
|
62811
62919
|
* on is checked here rather than downstream — by the time `Index` sees the
|
|
@@ -62978,22 +63086,119 @@ const pgNumericDecode = (wire) => {
|
|
|
62978
63086
|
return wire;
|
|
62979
63087
|
};
|
|
62980
63088
|
const DECIMAL_INTEGER = /^-?\d+$/;
|
|
62981
|
-
/**
|
|
62982
|
-
|
|
63089
|
+
/**
|
|
63090
|
+
* Requires an application value to be of the JS type the codec reads.
|
|
63091
|
+
*
|
|
63092
|
+
* A range check reads a value of the wrong type as a value out of range, and
|
|
63093
|
+
* reports a number plainly inside the range as outside it — so the type is
|
|
63094
|
+
* established first and answered for on its own terms, naming what a caller
|
|
63095
|
+
* has to change.
|
|
63096
|
+
*/
|
|
63097
|
+
const requireJsType = (codecId, expected, value) => {
|
|
63098
|
+
if (typeof value === expected) return;
|
|
63099
|
+
throw postgresError("RUNTIME.ENCODE_FAILED", `${codecId} value must be a ${expected}, got ${typeof value} ${String(value)}`, { meta: {
|
|
63100
|
+
codecId,
|
|
63101
|
+
received: typeof value
|
|
63102
|
+
} });
|
|
63103
|
+
};
|
|
63104
|
+
/** Writes a `bigint` application value as the decimal text the wire form of the exact integer codecs carries. */
|
|
63105
|
+
const pgBigintEncode = (codecId, value) => {
|
|
63106
|
+
requireJsType(codecId, "bigint", value);
|
|
63107
|
+
return value.toString();
|
|
63108
|
+
};
|
|
63109
|
+
/**
|
|
63110
|
+
* Writes an application value as the decimal text these codecs carry as their
|
|
63111
|
+
* canonical JSON.
|
|
63112
|
+
*
|
|
63113
|
+
* A schema-written literal default (`BigInt @default(0)`) arrives here as a
|
|
63114
|
+
* `number`, since a number literal is the only integer a schema language
|
|
63115
|
+
* writes, and one that is a safe integer names its value exactly. Past that
|
|
63116
|
+
* range the literal was rounded before any of this ran, so the value written is
|
|
63117
|
+
* not the value meant — which this refuses rather than minting an exact-looking
|
|
63118
|
+
* total from it. A non-integral number is refused on the same terms.
|
|
63119
|
+
*/
|
|
63120
|
+
const pgBigintEncodeJson = (codecId, value) => {
|
|
63121
|
+
if (typeof value !== "number") return pgBigintEncode(codecId, value);
|
|
63122
|
+
if (!Number.isSafeInteger(value)) throw postgresError("RUNTIME.ENCODE_FAILED", `${codecId} number literal must be an integer within the safe integer range, got ${String(value)}`, { meta: {
|
|
63123
|
+
codecId,
|
|
63124
|
+
received: String(value)
|
|
63125
|
+
} });
|
|
63126
|
+
return BigInt(value).toString();
|
|
63127
|
+
};
|
|
63128
|
+
/**
|
|
63129
|
+
* Reads a wire or JSON value as a `bigint`, rejecting anything `BigInt()` would
|
|
63130
|
+
* misread. A number-typed wire value must also be a safe integer: past
|
|
63131
|
+
* ±(2^53 − 1) the driver's `number` has already rounded, so stringifying it
|
|
63132
|
+
* would mint a spuriously-exact `bigint` that need not equal the stored value.
|
|
63133
|
+
*/
|
|
63134
|
+
const decimalIntegerDecode = (codecId, wire) => {
|
|
62983
63135
|
if (typeof wire === "bigint") return wire;
|
|
62984
63136
|
const text = String(wire);
|
|
62985
|
-
if (!DECIMAL_INTEGER.test(text)) throw postgresError("RUNTIME.DECODE_FAILED",
|
|
62986
|
-
codecId
|
|
63137
|
+
if (!DECIMAL_INTEGER.test(text)) throw postgresError("RUNTIME.DECODE_FAILED", `${codecId} value must be a decimal integer`, { meta: {
|
|
63138
|
+
codecId,
|
|
63139
|
+
received: text
|
|
63140
|
+
} });
|
|
63141
|
+
if (typeof wire === "number" && !Number.isSafeInteger(wire)) throw postgresError("RUNTIME.DECODE_FAILED", `${codecId} wire number must be an integer within the safe integer range, got ${text}`, { meta: {
|
|
63142
|
+
codecId,
|
|
62987
63143
|
received: text
|
|
62988
63144
|
} });
|
|
62989
63145
|
return BigInt(text);
|
|
62990
63146
|
};
|
|
63147
|
+
/** Reads an `int8` wire or JSON value as a `bigint`, rejecting anything `BigInt()` would misread. */
|
|
63148
|
+
const pgInt8Decode = (wire) => decimalIntegerDecode("pg/int8@1", wire);
|
|
62991
63149
|
/**
|
|
62992
|
-
*
|
|
62993
|
-
*
|
|
63150
|
+
* Reads an unconstrained-`numeric` wire or JSON value as a `bigint`, rejecting
|
|
63151
|
+
* non-integral values — including `NaN` and the infinities, which are `numeric`
|
|
63152
|
+
* values but not integers.
|
|
63153
|
+
*/
|
|
63154
|
+
const pgUnboundedIntDecode = (wire) => decimalIntegerDecode("pg/unboundedint@1", wire);
|
|
63155
|
+
const MIN_SAFE_INTEGER_BIGINT = BigInt(Number.MIN_SAFE_INTEGER);
|
|
63156
|
+
const MAX_SAFE_INTEGER_BIGINT = BigInt(Number.MAX_SAFE_INTEGER);
|
|
63157
|
+
/**
|
|
63158
|
+
* Requires an integer within ±(2^53 − 1), the range a JS `number` holds
|
|
63159
|
+
* exactly. The guard throws rather than rounding: past the boundary a `number`
|
|
63160
|
+
* silently loses digits, which is the failure mode this codec exists to refuse.
|
|
63161
|
+
*/
|
|
63162
|
+
const pgInt8NumberGuard = (code, value) => {
|
|
63163
|
+
if (!Number.isSafeInteger(value)) throw postgresError(code, `pg/int8number@1 value must be an integer within the safe integer range, got ${String(value)}`, { meta: {
|
|
63164
|
+
codecId: "pg/int8number@1",
|
|
63165
|
+
received: String(value)
|
|
63166
|
+
} });
|
|
63167
|
+
return value;
|
|
63168
|
+
};
|
|
63169
|
+
const pgInt8NumberEncodeJson = (value) => {
|
|
63170
|
+
requireJsType("pg/int8number@1", "number", value);
|
|
63171
|
+
return pgInt8NumberGuard("RUNTIME.ENCODE_FAILED", value);
|
|
63172
|
+
};
|
|
63173
|
+
const pgInt8NumberEncode = (value) => String(pgInt8NumberEncodeJson(value));
|
|
63174
|
+
/**
|
|
63175
|
+
* Reads an `int8` wire value as a `number`, throwing outside ±(2^53 − 1) and on
|
|
63176
|
+
* non-integral input. Decimal text goes through `BigInt` before the range check
|
|
63177
|
+
* so an out-of-range value is compared exactly rather than after rounding.
|
|
63178
|
+
*/
|
|
63179
|
+
const pgInt8NumberDecode = (wire) => {
|
|
63180
|
+
if (typeof wire === "number") return pgInt8NumberGuard("RUNTIME.DECODE_FAILED", wire);
|
|
63181
|
+
const value = decimalIntegerDecode("pg/int8number@1", wire);
|
|
63182
|
+
if (value < MIN_SAFE_INTEGER_BIGINT || value > MAX_SAFE_INTEGER_BIGINT) throw postgresError("RUNTIME.DECODE_FAILED", `pg/int8number@1 value must be an integer within the safe integer range, got ${value}`, { meta: {
|
|
63183
|
+
codecId: "pg/int8number@1",
|
|
63184
|
+
received: value.toString()
|
|
63185
|
+
} });
|
|
63186
|
+
return Number(value);
|
|
63187
|
+
};
|
|
63188
|
+
const pgInt8NumberDecodeJson = (json) => {
|
|
63189
|
+
if (typeof json !== "number") throw postgresError("RUNTIME.DECODE_FAILED", "pg/int8number@1 database JSON value must be a number", { meta: {
|
|
63190
|
+
codecId: "pg/int8number@1",
|
|
63191
|
+
received: typeof json
|
|
63192
|
+
} });
|
|
63193
|
+
return pgInt8NumberGuard("RUNTIME.DECODE_FAILED", json);
|
|
63194
|
+
};
|
|
63195
|
+
/**
|
|
63196
|
+
* Renders a decimal-text default as a `bigint` literal, for the codecs whose
|
|
63197
|
+
* canonical JSON is decimal text while the application type is `bigint`
|
|
63198
|
+
* (`pg/int8@1`, `pg/unboundedint@1`) — a plain string literal would not
|
|
62994
63199
|
* typecheck against the emitted column type.
|
|
62995
63200
|
*/
|
|
62996
|
-
const
|
|
63201
|
+
const decimalTextBigintLiteral = (value) => typeof value === "string" && DECIMAL_INTEGER.test(value) ? `${value}n` : void 0;
|
|
62997
63202
|
const pgNumericRenderOutputType = (typeParams) => {
|
|
62998
63203
|
const precision = typeParams.precision;
|
|
62999
63204
|
if (precision === void 0) return void 0;
|
|
@@ -63653,13 +63858,13 @@ const pgInt2Descriptor = new PgInt2Descriptor();
|
|
|
63653
63858
|
*/
|
|
63654
63859
|
var PgInt8Codec = class extends CodecImpl {
|
|
63655
63860
|
async encode(value, _ctx) {
|
|
63656
|
-
return value
|
|
63861
|
+
return pgBigintEncode(PG_INT8_CODEC_ID, value);
|
|
63657
63862
|
}
|
|
63658
63863
|
async decode(wire, _ctx) {
|
|
63659
63864
|
return pgInt8Decode(wire);
|
|
63660
63865
|
}
|
|
63661
63866
|
encodeJson(value) {
|
|
63662
|
-
return value
|
|
63867
|
+
return pgBigintEncodeJson(PG_INT8_CODEC_ID, value);
|
|
63663
63868
|
}
|
|
63664
63869
|
decodeJson(json) {
|
|
63665
63870
|
if (typeof json !== "string") throw postgresError("RUNTIME.DECODE_FAILED", "pg/int8@1 database JSON value must be a decimal string", { meta: {
|
|
@@ -63685,13 +63890,59 @@ var PgInt8Descriptor = class extends PostgresCodecDescriptor {
|
|
|
63685
63890
|
targetTypes = ["int8"];
|
|
63686
63891
|
paramsSchema = voidParamsSchema;
|
|
63687
63892
|
renderValueLiteral(value) {
|
|
63688
|
-
return
|
|
63893
|
+
return decimalTextBigintLiteral(value);
|
|
63689
63894
|
}
|
|
63690
63895
|
factory() {
|
|
63691
63896
|
return () => new PgInt8Codec(this);
|
|
63692
63897
|
}
|
|
63693
63898
|
};
|
|
63694
63899
|
const pgInt8Descriptor = new PgInt8Descriptor();
|
|
63900
|
+
/**
|
|
63901
|
+
* A Postgres `int8` decoded as a JS `number`, for columns whose values stay
|
|
63902
|
+
* within the safe integer range ±(2^53 − 1). Both directions guard rather than
|
|
63903
|
+
* round: decode (wire and JSON) and encode throw a structured error on
|
|
63904
|
+
* out-of-range or non-integral input. The canonical JSON is a JSON number —
|
|
63905
|
+
* the deliberate exception to the decimal-text rule for 64-bit integers, and
|
|
63906
|
+
* the codec's purpose. The descriptor claims no target type, so `int8` in type
|
|
63907
|
+
* position stays `pg/int8@1`.
|
|
63908
|
+
*/
|
|
63909
|
+
var PgInt8NumberCodec = class extends CodecImpl {
|
|
63910
|
+
async encode(value, _ctx) {
|
|
63911
|
+
return pgInt8NumberEncode(value);
|
|
63912
|
+
}
|
|
63913
|
+
async decode(wire, _ctx) {
|
|
63914
|
+
return pgInt8NumberDecode(wire);
|
|
63915
|
+
}
|
|
63916
|
+
encodeJson(value) {
|
|
63917
|
+
return pgInt8NumberEncodeJson(value);
|
|
63918
|
+
}
|
|
63919
|
+
decodeJson(json) {
|
|
63920
|
+
return pgInt8NumberDecodeJson(json);
|
|
63921
|
+
}
|
|
63922
|
+
};
|
|
63923
|
+
var PgInt8NumberDescriptor = class extends PostgresCodecDescriptor {
|
|
63924
|
+
nativeType() {
|
|
63925
|
+
return PG_INT8_NATIVE_TYPE;
|
|
63926
|
+
}
|
|
63927
|
+
jsonProjection(expression) {
|
|
63928
|
+
return expression;
|
|
63929
|
+
}
|
|
63930
|
+
codecId = PG_INT8_NUMBER_CODEC_ID;
|
|
63931
|
+
traits = [
|
|
63932
|
+
"equality",
|
|
63933
|
+
"order",
|
|
63934
|
+
"numeric"
|
|
63935
|
+
];
|
|
63936
|
+
targetTypes = [];
|
|
63937
|
+
paramsSchema = voidParamsSchema;
|
|
63938
|
+
renderValueLiteral(value) {
|
|
63939
|
+
return renderTsLiteral(value);
|
|
63940
|
+
}
|
|
63941
|
+
factory() {
|
|
63942
|
+
return () => new PgInt8NumberCodec(this);
|
|
63943
|
+
}
|
|
63944
|
+
};
|
|
63945
|
+
const pgInt8NumberDescriptor = new PgInt8NumberDescriptor();
|
|
63695
63946
|
var PgFloat4Codec = class extends CodecImpl {
|
|
63696
63947
|
async encode(value, _ctx) {
|
|
63697
63948
|
return value;
|
|
@@ -63845,6 +64096,53 @@ var PgNumericDescriptor = class extends PostgresCodecDescriptor {
|
|
|
63845
64096
|
};
|
|
63846
64097
|
const pgNumericDescriptor = new PgNumericDescriptor();
|
|
63847
64098
|
/**
|
|
64099
|
+
* A genuinely unbounded integer over unconstrained Postgres `numeric` storage.
|
|
64100
|
+
* Application values are `bigint` and the canonical JSON is decimal text, like
|
|
64101
|
+
* `pg/int8@1`; decode rejects non-integral values. The descriptor claims no
|
|
64102
|
+
* target type, so `numeric` and `decimal` in type position stay `pg/numeric@1`.
|
|
64103
|
+
*/
|
|
64104
|
+
var PgUnboundedIntCodec = class extends CodecImpl {
|
|
64105
|
+
async encode(value, _ctx) {
|
|
64106
|
+
return pgBigintEncode(PG_UNBOUNDED_INT_CODEC_ID, value);
|
|
64107
|
+
}
|
|
64108
|
+
async decode(wire, _ctx) {
|
|
64109
|
+
return pgUnboundedIntDecode(wire);
|
|
64110
|
+
}
|
|
64111
|
+
encodeJson(value) {
|
|
64112
|
+
return pgBigintEncodeJson(PG_UNBOUNDED_INT_CODEC_ID, value);
|
|
64113
|
+
}
|
|
64114
|
+
decodeJson(json) {
|
|
64115
|
+
if (typeof json !== "string") throw postgresError("RUNTIME.DECODE_FAILED", "pg/unboundedint@1 database JSON value must be a decimal string", { meta: {
|
|
64116
|
+
codecId: PG_UNBOUNDED_INT_CODEC_ID,
|
|
64117
|
+
received: typeof json
|
|
64118
|
+
} });
|
|
64119
|
+
return pgUnboundedIntDecode(json);
|
|
64120
|
+
}
|
|
64121
|
+
};
|
|
64122
|
+
var PgUnboundedIntDescriptor = class extends PostgresCodecDescriptor {
|
|
64123
|
+
nativeType() {
|
|
64124
|
+
return PG_NUMERIC_NATIVE_TYPE;
|
|
64125
|
+
}
|
|
64126
|
+
jsonProjection(expression) {
|
|
64127
|
+
return decimalTextJsonProjection(expression);
|
|
64128
|
+
}
|
|
64129
|
+
codecId = PG_UNBOUNDED_INT_CODEC_ID;
|
|
64130
|
+
traits = [
|
|
64131
|
+
"equality",
|
|
64132
|
+
"order",
|
|
64133
|
+
"numeric"
|
|
64134
|
+
];
|
|
64135
|
+
targetTypes = [];
|
|
64136
|
+
paramsSchema = voidParamsSchema;
|
|
64137
|
+
renderValueLiteral(value) {
|
|
64138
|
+
return decimalTextBigintLiteral(value);
|
|
64139
|
+
}
|
|
64140
|
+
factory() {
|
|
64141
|
+
return () => new PgUnboundedIntCodec(this);
|
|
64142
|
+
}
|
|
64143
|
+
};
|
|
64144
|
+
const pgUnboundedIntDescriptor = new PgUnboundedIntDescriptor();
|
|
64145
|
+
/**
|
|
63848
64146
|
* A Postgres `date` has no time-of-day or timezone component. This codec
|
|
63849
64147
|
* canonicalizes its JS-level value as a `Date` at UTC midnight, so its
|
|
63850
64148
|
* round-trip is independent of the process's local timezone — see
|
|
@@ -64381,9 +64679,11 @@ const codecDescriptors = definePostgresCodecs([
|
|
|
64381
64679
|
pgInt4Descriptor,
|
|
64382
64680
|
pgInt2Descriptor,
|
|
64383
64681
|
pgInt8Descriptor,
|
|
64682
|
+
pgInt8NumberDescriptor,
|
|
64384
64683
|
pgFloat4Descriptor,
|
|
64385
64684
|
pgFloat8Descriptor,
|
|
64386
64685
|
pgNumericDescriptor,
|
|
64686
|
+
pgUnboundedIntDescriptor,
|
|
64387
64687
|
pgDateDescriptor,
|
|
64388
64688
|
pgTimestampDescriptor,
|
|
64389
64689
|
pgTimestamptzDescriptor,
|
|
@@ -64577,14 +64877,6 @@ const ColumnDefaultFunctionSchema = type.declare().type({
|
|
|
64577
64877
|
kind: functionKindSchema,
|
|
64578
64878
|
expression: "string"
|
|
64579
64879
|
});
|
|
64580
|
-
const ColumnDefaultSchema = ColumnDefaultLiteralSchema.or(ColumnDefaultFunctionSchema);
|
|
64581
|
-
const StorageValueSetRefSchema = type({
|
|
64582
|
-
plane: "'storage'",
|
|
64583
|
-
namespaceId: "string",
|
|
64584
|
-
entityKind: "'valueSet'",
|
|
64585
|
-
entityName: "string",
|
|
64586
|
-
"spaceId?": "string"
|
|
64587
|
-
});
|
|
64588
64880
|
const StorageColumnSchema = type({
|
|
64589
64881
|
"+": "reject",
|
|
64590
64882
|
nativeType: "string",
|
|
@@ -64593,11 +64885,26 @@ const StorageColumnSchema = type({
|
|
|
64593
64885
|
"many?": "boolean",
|
|
64594
64886
|
"typeParams?": "Record<string, unknown>",
|
|
64595
64887
|
"typeRef?": "string",
|
|
64596
|
-
"default?":
|
|
64888
|
+
"default?": ColumnDefaultLiteralSchema.or(ColumnDefaultFunctionSchema),
|
|
64597
64889
|
"control?": ControlPolicySchema$1,
|
|
64598
|
-
"valueSet?":
|
|
64890
|
+
"valueSet?": type({
|
|
64891
|
+
plane: "'storage'",
|
|
64892
|
+
namespaceId: "string",
|
|
64893
|
+
entityKind: "'valueSet'",
|
|
64894
|
+
entityName: "string",
|
|
64895
|
+
"spaceId?": "string"
|
|
64896
|
+
}),
|
|
64897
|
+
"noCheck?": "(\"membership\" | \"elementNotNull\")[]"
|
|
64599
64898
|
}).narrow((col, ctx) => {
|
|
64600
64899
|
if (col.typeParams !== void 0 && col.typeRef !== void 0) return ctx.mustBe("a column with either typeParams or typeRef, not both");
|
|
64900
|
+
if (col.noCheck !== void 0) {
|
|
64901
|
+
if (col.noCheck.length === 0) return ctx.mustBe("a column whose noCheck array is non-empty (omit the key when enforced)");
|
|
64902
|
+
for (let i = 1; i < col.noCheck.length; i += 1) {
|
|
64903
|
+
const previous = col.noCheck[i - 1];
|
|
64904
|
+
const current = col.noCheck[i];
|
|
64905
|
+
if (previous !== void 0 && current !== void 0 && previous >= current) return ctx.mustBe("a column whose noCheck kinds are unique and sorted ascending lexicographically");
|
|
64906
|
+
}
|
|
64907
|
+
}
|
|
64601
64908
|
return true;
|
|
64602
64909
|
});
|
|
64603
64910
|
/**
|
|
@@ -64651,8 +64958,8 @@ const ForeignKeySchema = type.declare().type({
|
|
|
64651
64958
|
const CheckConstraintSchema = type({
|
|
64652
64959
|
"+": "reject",
|
|
64653
64960
|
name: "string",
|
|
64654
|
-
|
|
64655
|
-
|
|
64961
|
+
"prefix?": "string",
|
|
64962
|
+
expression: "string"
|
|
64656
64963
|
});
|
|
64657
64964
|
const tableEntityKind = {
|
|
64658
64965
|
kind: "table",
|
|
@@ -64668,7 +64975,8 @@ const tableEntityKind = {
|
|
|
64668
64975
|
}),
|
|
64669
64976
|
construct: (input) => new StorageTable({
|
|
64670
64977
|
...input,
|
|
64671
|
-
indexes: input.indexes.map((i) => i instanceof Index ? i : indexInputFromSerialized(i))
|
|
64978
|
+
indexes: input.indexes.map((i) => i instanceof Index ? i : indexInputFromSerialized(i)),
|
|
64979
|
+
...ifDefined("checks", input.checks?.map((c) => c instanceof CheckConstraint ? c : checkConstraintInputFromSerialized(c)))
|
|
64672
64980
|
})
|
|
64673
64981
|
};
|
|
64674
64982
|
const valueSetEntityKind = {
|
|
@@ -66682,6 +66990,7 @@ function isAggregateDescriptor(value) {
|
|
|
66682
66990
|
if (!isObjectLike(value)) return false;
|
|
66683
66991
|
if (!("operation" in value) || !isNonEmptyString(value.operation)) return false;
|
|
66684
66992
|
if (!("nullable" in value) || typeof value.nullable !== "boolean") return false;
|
|
66993
|
+
if (value.nullable === false && (!("emptyResultJson" in value) || value.emptyResultJson === void 0)) return false;
|
|
66685
66994
|
if (!("input" in value) || !isAggregateInputMatch(value.input)) return false;
|
|
66686
66995
|
if (!("output" in value) || !isAggregateOutputCodec(value.output)) return false;
|
|
66687
66996
|
return value.input.kind === "codec" || value.input.kind === "trait" || value.output.kind === "codec";
|
|
@@ -66930,7 +67239,7 @@ function collectAggregateDescriptors(descriptors) {
|
|
|
66930
67239
|
for (const descriptor of descriptors) {
|
|
66931
67240
|
const descriptorId = descriptor.id ?? "<unknown>";
|
|
66932
67241
|
for (const contributed of descriptor.types?.aggregateDescriptors ?? []) {
|
|
66933
|
-
if (!isAggregateDescriptor(contributed)) throw runtimeError("CONTRACT.AGGREGATE_DESCRIPTOR_INVALID", `Malformed aggregate descriptor contributed by "${descriptorId}". A descriptor declares a non-empty \`operation\`, an \`input\` match of kind \`none\`/\`any\`/\`codec\`/\`trait\`, an \`output\` of kind \`self\`/\`codec\`, and a boolean \`nullable
|
|
67242
|
+
if (!isAggregateDescriptor(contributed)) throw runtimeError("CONTRACT.AGGREGATE_DESCRIPTOR_INVALID", `Malformed aggregate descriptor contributed by "${descriptorId}". A descriptor declares a non-empty \`operation\`, an \`input\` match of kind \`none\`/\`any\`/\`codec\`/\`trait\`, an \`output\` of kind \`self\`/\`codec\`, and a boolean \`nullable\` — plus \`emptyResultJson\`, in the result codec's canonical JSON, where \`nullable\` is false; a \`self\` output needs an input to reuse.`, {
|
|
66934
67243
|
contributedBy: descriptorId,
|
|
66935
67244
|
descriptor: contributed
|
|
66936
67245
|
});
|
|
@@ -67737,6 +68046,9 @@ var PrimaryKey = class PrimaryKey extends SqlSchemaIRNode {
|
|
|
67737
68046
|
children() {
|
|
67738
68047
|
return [];
|
|
67739
68048
|
}
|
|
68049
|
+
static from(value) {
|
|
68050
|
+
return value instanceof PrimaryKey ? value : new PrimaryKey(value);
|
|
68051
|
+
}
|
|
67740
68052
|
static is(node) {
|
|
67741
68053
|
return node.nodeKind === RelationalSchemaNodeKind.primaryKey;
|
|
67742
68054
|
}
|
|
@@ -67747,27 +68059,28 @@ var PrimaryKey = class PrimaryKey extends SqlSchemaIRNode {
|
|
|
67747
68059
|
}
|
|
67748
68060
|
};
|
|
67749
68061
|
/**
|
|
67750
|
-
* Schema IR node for a table-level check constraint
|
|
67751
|
-
*
|
|
67752
|
-
*
|
|
67753
|
-
* Carries the **resolved values** rather than a raw SQL predicate so
|
|
67754
|
-
* callers can compare value-sets without parsing SQL.
|
|
68062
|
+
* Schema IR node for a table-level check constraint, carried as an opaque
|
|
68063
|
+
* predicate. The expression is never parsed — a database reprints predicates
|
|
68064
|
+
* in its own normalized form, so any structured reading of it would drift.
|
|
67755
68065
|
*
|
|
67756
|
-
* Implements `DiffableNode` so a check
|
|
67757
|
-
*
|
|
67758
|
-
* `
|
|
67759
|
-
*
|
|
68066
|
+
* Implements `DiffableNode` so a check is directly a table's diff-tree child;
|
|
68067
|
+
* `id` is `check:<name>`. `isEqualTo` is mode-selected by the receiver's
|
|
68068
|
+
* `prefix` (the differ always calls `expected.isEqualTo(actual)`): a
|
|
68069
|
+
* wire-named receiver compares ids only — the wire name's hash already
|
|
68070
|
+
* commits to the predicate — while an exact-named receiver byte-compares the
|
|
68071
|
+
* expression, which is reliable precisely when both sides came from the same
|
|
68072
|
+
* reprint.
|
|
67760
68073
|
*/
|
|
67761
68074
|
var SqlCheckConstraintIR = class SqlCheckConstraintIR extends SqlSchemaIRNode {
|
|
67762
68075
|
nodeKind = RelationalSchemaNodeKind.check;
|
|
67763
68076
|
name;
|
|
67764
|
-
|
|
67765
|
-
permittedValues;
|
|
68077
|
+
expression;
|
|
67766
68078
|
constructor(input) {
|
|
67767
68079
|
super();
|
|
67768
|
-
this.name = input.
|
|
67769
|
-
this.
|
|
67770
|
-
this.
|
|
68080
|
+
this.name = nameOf(input.naming);
|
|
68081
|
+
if (input.naming.kind === "wire") this.prefix = input.naming.prefix;
|
|
68082
|
+
this.expression = input.expression;
|
|
68083
|
+
defineNonEnumerable(this, "dependsOn", input.dependsOn);
|
|
67771
68084
|
freezeNode(this);
|
|
67772
68085
|
}
|
|
67773
68086
|
get id() {
|
|
@@ -67776,23 +68089,17 @@ var SqlCheckConstraintIR = class SqlCheckConstraintIR extends SqlSchemaIRNode {
|
|
|
67776
68089
|
children() {
|
|
67777
68090
|
return [];
|
|
67778
68091
|
}
|
|
68092
|
+
static from(value) {
|
|
68093
|
+
return value instanceof SqlCheckConstraintIR ? value : new SqlCheckConstraintIR(value);
|
|
68094
|
+
}
|
|
67779
68095
|
static is(node) {
|
|
67780
68096
|
return node.nodeKind === RelationalSchemaNodeKind.check;
|
|
67781
68097
|
}
|
|
67782
|
-
/**
|
|
67783
|
-
* Compares the permitted-value sets only (unordered), matching the
|
|
67784
|
-
* relational walk's `verifyCheckConstraints`: two checks pairing by name
|
|
67785
|
-
* compare their value sets — the `column` field is descriptive, not part
|
|
67786
|
-
* of the comparison, so a name-paired check with equal values verifies
|
|
67787
|
-
* regardless of which column carries it.
|
|
67788
|
-
*/
|
|
67789
68098
|
isEqualTo(other) {
|
|
67790
68099
|
const node = blindCast(other);
|
|
67791
68100
|
assertNode(node, "SqlCheckConstraintIR", SqlCheckConstraintIR.is);
|
|
67792
|
-
|
|
67793
|
-
|
|
67794
|
-
if (thisValues.size !== otherValues.size) return false;
|
|
67795
|
-
return [...thisValues].every((v) => otherValues.has(v));
|
|
68101
|
+
if (this.prefix !== void 0) return this.id === node.id;
|
|
68102
|
+
return this.expression === node.expression;
|
|
67796
68103
|
}
|
|
67797
68104
|
};
|
|
67798
68105
|
/**
|
|
@@ -68081,6 +68388,9 @@ var SqlIndexIR = class SqlIndexIR extends SqlSchemaIRNode {
|
|
|
68081
68388
|
children() {
|
|
68082
68389
|
return [];
|
|
68083
68390
|
}
|
|
68391
|
+
static from(value) {
|
|
68392
|
+
return value instanceof SqlIndexIR ? value : new SqlIndexIR(value);
|
|
68393
|
+
}
|
|
68084
68394
|
static is(node) {
|
|
68085
68395
|
return node.nodeKind === RelationalSchemaNodeKind.index;
|
|
68086
68396
|
}
|
|
@@ -68229,10 +68539,10 @@ var SqlTableIR = class extends SqlSchemaIRNode {
|
|
|
68229
68539
|
this.columns = Object.freeze(Object.fromEntries(Object.entries(input.columns).map(([key, col]) => [key, col instanceof SqlColumnIR ? col : new SqlColumnIR(col)])));
|
|
68230
68540
|
this.foreignKeys = Object.freeze(input.foreignKeys.map((fk) => fk instanceof SqlForeignKeyIR ? fk : new SqlForeignKeyIR(fk)));
|
|
68231
68541
|
this.uniques = Object.freeze(input.uniques.map((u) => u instanceof SqlUniqueIR ? u : new SqlUniqueIR(u)));
|
|
68232
|
-
this.indexes = Object.freeze(input.indexes.map(
|
|
68233
|
-
if (input.primaryKey !== void 0) this.primaryKey =
|
|
68542
|
+
this.indexes = Object.freeze(input.indexes.map(SqlIndexIR.from));
|
|
68543
|
+
if (input.primaryKey !== void 0) this.primaryKey = PrimaryKey.from(input.primaryKey);
|
|
68234
68544
|
if (input.annotations !== void 0) this.annotations = input.annotations;
|
|
68235
|
-
if (input.checks !== void 0 && input.checks.length > 0) this.checks = Object.freeze(input.checks.map(
|
|
68545
|
+
if (input.checks !== void 0 && input.checks.length > 0) this.checks = Object.freeze(input.checks.map(SqlCheckConstraintIR.from));
|
|
68236
68546
|
freezeNode(this);
|
|
68237
68547
|
}
|
|
68238
68548
|
get id() {
|
|
@@ -68693,15 +69003,16 @@ var PostgresRoleSchemaNode = class PostgresRoleSchemaNode extends SqlSchemaIRNod
|
|
|
68693
69003
|
* - `'decode'` — abort fired during `decodeRow` / `decodeField`.
|
|
68694
69004
|
* - `'stream'` — abort fired between rows or before any codec call
|
|
68695
69005
|
* (already-aborted at entry).
|
|
68696
|
-
* - `'
|
|
68697
|
-
* on entry to or during
|
|
69006
|
+
* - `'beforeQuery'` / `'beforeExecute'` / `'afterQuery'` /
|
|
69007
|
+
* `'afterExecute'` / `'onRow'` — abort fired on entry to or during
|
|
69008
|
+
* the corresponding middleware phase
|
|
68698
69009
|
* (cooperative cancellation per the param-transform seam).
|
|
68699
69010
|
*/
|
|
68700
69011
|
const RUNTIME_ABORTED = "RUNTIME.ABORTED";
|
|
68701
69012
|
/**
|
|
68702
69013
|
* Construct a `RUNTIME.ABORTED` envelope. Phase distinguishes where the
|
|
68703
69014
|
* abort was observed — codec call sites (`encode` / `decode` / `stream`)
|
|
68704
|
-
* or middleware seams
|
|
69015
|
+
* or operation-specific middleware seams, as
|
|
68705
69016
|
* enumerated on {@link RuntimeAbortedPhase}. Cause carries
|
|
68706
69017
|
* `signal.reason` verbatim from the platform — native abort produces a
|
|
68707
69018
|
* `DOMException`, explicit `controller.abort(reason)` produces whatever
|
|
@@ -68866,8 +69177,8 @@ function renderLoweredSql(ast, contract, codecDescriptorRegistry) {
|
|
|
68866
69177
|
case "delete":
|
|
68867
69178
|
sql = renderDelete(node, contract, pim);
|
|
68868
69179
|
break;
|
|
68869
|
-
case "raw-
|
|
68870
|
-
sql =
|
|
69180
|
+
case "raw-query":
|
|
69181
|
+
sql = renderParts(node.parts, contract, pim);
|
|
68871
69182
|
break;
|
|
68872
69183
|
// v8 ignore next 4
|
|
68873
69184
|
default: assertNever(node, `Unsupported AST node kind: ${unreachableKind(node)}`);
|
|
@@ -68918,7 +69229,7 @@ function collectTableSources(ast) {
|
|
|
68918
69229
|
/**
|
|
68919
69230
|
* Ordered, codec-encoded values of the value-set a storage column restricts to, or `undefined` when the referenced column carries no value-set (the common, non-enum case). Resolves the column's storage coordinate from the SELECT's table sources, then the column's `valueSet` ref to the value-set's `values`.
|
|
68920
69231
|
*/
|
|
68921
|
-
function allStrings
|
|
69232
|
+
function allStrings(values) {
|
|
68922
69233
|
return values.every((value) => typeof value === "string");
|
|
68923
69234
|
}
|
|
68924
69235
|
function resolveEnumOrderValues(ref, sourcesByRef, contract) {
|
|
@@ -68956,11 +69267,11 @@ function resolveEnumOrderValuesForIdentifier(name, sourcesByRef, contract) {
|
|
|
68956
69267
|
function renderOrderByExpr(expr, sourcesByRef, contract, pim) {
|
|
68957
69268
|
if (expr.kind === "column-ref") {
|
|
68958
69269
|
const orderValues = resolveEnumOrderValues(expr, sourcesByRef, contract);
|
|
68959
|
-
if (orderValues !== void 0 && allStrings
|
|
69270
|
+
if (orderValues !== void 0 && allStrings(orderValues)) return `array_position(ARRAY[${orderValues.map((value) => `'${escapeLiteral(value)}'`).join(", ")}]::text[], ${renderColumn(expr)})`;
|
|
68960
69271
|
}
|
|
68961
69272
|
if (expr.kind === "identifier-ref") {
|
|
68962
69273
|
const orderValues = resolveEnumOrderValuesForIdentifier(expr.name, sourcesByRef, contract);
|
|
68963
|
-
if (orderValues !== void 0 && allStrings
|
|
69274
|
+
if (orderValues !== void 0 && allStrings(orderValues)) return `array_position(ARRAY[${orderValues.map((value) => `'${escapeLiteral(value)}'`).join(", ")}]::text[], ${quoteIdentifier(expr.name)})`;
|
|
68964
69275
|
}
|
|
68965
69276
|
return renderExpr(expr, contract, pim);
|
|
68966
69277
|
}
|
|
@@ -69332,19 +69643,11 @@ function renderUpdate(ast, contract, pim) {
|
|
|
69332
69643
|
function renderDelete(ast, contract, pim) {
|
|
69333
69644
|
return `DELETE FROM ${qualifyTableFromNamespaceCoordinate(ast.table, contract)}${ast.where ? ` WHERE ${renderWhere(ast.where, contract, pim)}` : ""}${ast.returning?.length ? ` RETURNING ${renderReturning(ast.returning, contract, pim)}` : ""}`;
|
|
69334
69645
|
}
|
|
69335
|
-
function
|
|
69336
|
-
|
|
69337
|
-
for (let i = 0; i < ast.fragments.length; i++) {
|
|
69338
|
-
out.push(ast.fragments[i] ?? "");
|
|
69339
|
-
if (i < ast.args.length) {
|
|
69340
|
-
const arg = ast.args[i];
|
|
69341
|
-
if (arg !== void 0) out.push(renderExpr(arg, contract, pim));
|
|
69342
|
-
}
|
|
69343
|
-
}
|
|
69344
|
-
return out.join("");
|
|
69646
|
+
function renderParts(parts, contract, pim) {
|
|
69647
|
+
return parts.map((part) => typeof part === "string" ? part : renderExpr(part, contract, pim)).join("");
|
|
69345
69648
|
}
|
|
69346
69649
|
function renderRawExpr(node, contract, pim) {
|
|
69347
|
-
return node.parts
|
|
69650
|
+
return renderParts(node.parts, contract, pim);
|
|
69348
69651
|
}
|
|
69349
69652
|
/**
|
|
69350
69653
|
* Maps each `ReferentialAction` value to the SQL keyword used in ON DELETE /
|
|
@@ -69364,8 +69667,15 @@ const REFERENTIAL_ACTION_SQL = {
|
|
|
69364
69667
|
function errorMarkerRowCorrupt(options) {
|
|
69365
69668
|
return new CliStructuredError("CONTRACT.MARKER_ROW_CORRUPT", "Marker row is corrupt or incompatible", {
|
|
69366
69669
|
why: options.why,
|
|
69367
|
-
fix: `The ${options.markerLocation} row for space "${options.space}" contains invalid data. Delete the row, then run \`prisma
|
|
69368
|
-
|
|
69670
|
+
fix: `The ${options.markerLocation} row for space "${options.space}" contains invalid data. Delete the row, then run \`prisma db sign --db <url>\` to write a fresh marker.`,
|
|
69671
|
+
nextActions: [{
|
|
69672
|
+
kind: "run-command",
|
|
69673
|
+
label: "Write a fresh marker",
|
|
69674
|
+
command: "{bin} db sign --db <url>",
|
|
69675
|
+
reason: `Delete the invalid ${options.markerLocation} row for space "${options.space}" first — this command then writes a valid one.`
|
|
69676
|
+
}],
|
|
69677
|
+
meta: { space: options.space },
|
|
69678
|
+
...ifDefined("cause", options.cause)
|
|
69369
69679
|
});
|
|
69370
69680
|
}
|
|
69371
69681
|
/**
|
|
@@ -69375,7 +69685,8 @@ function errorMarkerReadFailed(options) {
|
|
|
69375
69685
|
return new CliStructuredError("CONTRACT.MARKER_READ_FAILED", "Database error while reading contract marker", {
|
|
69376
69686
|
why: options.why,
|
|
69377
69687
|
fix: `Could not read marker at ${options.markerLocation} for space "${options.space}". Verify read permissions, connectivity, and locks, then retry.`,
|
|
69378
|
-
meta: { space: options.space }
|
|
69688
|
+
meta: { space: options.space },
|
|
69689
|
+
...ifDefined("cause", options.cause)
|
|
69379
69690
|
});
|
|
69380
69691
|
}
|
|
69381
69692
|
function isMarkerRowParseError(err) {
|
|
@@ -69386,10 +69697,17 @@ function isLegacyMarkerShapeReadError(message) {
|
|
|
69386
69697
|
return normalized.includes("column \"space\" does not exist") || normalized.includes("no such column: space");
|
|
69387
69698
|
}
|
|
69388
69699
|
function errorLegacyMarkerShape(options) {
|
|
69389
|
-
return errorRunnerFailed(`Legacy marker-table shape detected on ${options.markerLocation} (no \`space\` column). Prisma Next is in pre-1.0; the previous transitional auto-migration to the per-space-row schema has been removed. Drop \`${options.markerLocation}\` and re-run \`prisma
|
|
69700
|
+
return errorRunnerFailed(`Legacy marker-table shape detected on ${options.markerLocation} (no \`space\` column). Prisma Next is in pre-1.0; the previous transitional auto-migration to the per-space-row schema has been removed. Drop \`${options.markerLocation}\` and re-run \`prisma db init\` to reinitialise from a clean baseline.`, {
|
|
69390
69701
|
why: options.why,
|
|
69391
|
-
fix: "Legacy marker-table shape detected. Drop `prisma_contract.marker` (Postgres) or `_prisma_marker` (SQLite) and re-run `prisma
|
|
69392
|
-
|
|
69702
|
+
fix: "Legacy marker-table shape detected. Drop `prisma_contract.marker` (Postgres) or `_prisma_marker` (SQLite) and re-run `prisma db init` to recreate it with the current per-space schema.",
|
|
69703
|
+
nextActions: [{
|
|
69704
|
+
kind: "run-command",
|
|
69705
|
+
label: "Reinitialise the marker table from a clean baseline",
|
|
69706
|
+
command: "{bin} db init",
|
|
69707
|
+
reason: `Drop \`${options.markerLocation}\` first — it has the legacy shape (no \`space\` column) and this command recreates it with the current per-space schema.`
|
|
69708
|
+
}],
|
|
69709
|
+
meta: { runnerErrorCode: "MIGRATION.LEGACY_MARKER_SHAPE" },
|
|
69710
|
+
...ifDefined("cause", options.cause)
|
|
69393
69711
|
});
|
|
69394
69712
|
}
|
|
69395
69713
|
function rethrowMarkerReadError(err, context) {
|
|
@@ -69397,17 +69715,20 @@ function rethrowMarkerReadError(err, context) {
|
|
|
69397
69715
|
if (isMarkerRowParseError(err)) throw errorMarkerRowCorrupt({
|
|
69398
69716
|
why: err.message,
|
|
69399
69717
|
space: context.space,
|
|
69400
|
-
markerLocation: context.markerLocation
|
|
69718
|
+
markerLocation: context.markerLocation,
|
|
69719
|
+
cause: err
|
|
69401
69720
|
});
|
|
69402
69721
|
const message = err instanceof Error ? err.message : String(err);
|
|
69403
69722
|
if (isLegacyMarkerShapeReadError(message)) throw errorLegacyMarkerShape({
|
|
69404
69723
|
why: message,
|
|
69405
|
-
markerLocation: context.markerLocation
|
|
69724
|
+
markerLocation: context.markerLocation,
|
|
69725
|
+
cause: err
|
|
69406
69726
|
});
|
|
69407
69727
|
throw errorMarkerReadFailed({
|
|
69408
69728
|
why: message,
|
|
69409
69729
|
space: context.space,
|
|
69410
|
-
markerLocation: context.markerLocation
|
|
69730
|
+
markerLocation: context.markerLocation,
|
|
69731
|
+
cause: err
|
|
69411
69732
|
});
|
|
69412
69733
|
}
|
|
69413
69734
|
async function withMarkerReadErrorHandling(operation, context) {
|
|
@@ -69431,17 +69752,20 @@ function errorRunnerFailed(summary, options) {
|
|
|
69431
69752
|
return new CliStructuredError("MIGRATION.RUNNER_FAILED", summary, {
|
|
69432
69753
|
why: options?.why ?? "Migration runner failed",
|
|
69433
69754
|
fix: options?.fix ?? "Inspect the reported conflict and reconcile schema drift",
|
|
69434
|
-
...options?.
|
|
69755
|
+
...ifDefined("nextActions", options?.nextActions),
|
|
69756
|
+
...options?.meta ? { meta: options.meta } : {},
|
|
69757
|
+
...ifDefined("cause", options?.cause)
|
|
69435
69758
|
});
|
|
69436
69759
|
}
|
|
69437
69760
|
/**
|
|
69438
|
-
* Generic runtime error.
|
|
69761
|
+
* Generic runtime error carrying a caller-provided dotted code.
|
|
69439
69762
|
*/
|
|
69440
|
-
function errorRuntime(summary, options) {
|
|
69441
|
-
return new CliStructuredError(
|
|
69442
|
-
...
|
|
69443
|
-
...
|
|
69444
|
-
...
|
|
69763
|
+
function errorRuntime(code, summary, options) {
|
|
69764
|
+
return new CliStructuredError(code, summary, {
|
|
69765
|
+
...ifDefined("why", options?.why),
|
|
69766
|
+
...ifDefined("fix", options?.fix),
|
|
69767
|
+
...ifDefined("meta", options?.meta),
|
|
69768
|
+
...ifDefined("cause", options?.cause)
|
|
69445
69769
|
});
|
|
69446
69770
|
}
|
|
69447
69771
|
function sqlFamilyError(code, message, options) {
|
|
@@ -69495,7 +69819,16 @@ function parseContractMarkerRow(row) {
|
|
|
69495
69819
|
const messages = result.map((p) => p.message).join("; ");
|
|
69496
69820
|
throw sqlFamilyError("CONTRACT.MARKER_ROW_CORRUPT", `Invalid contract marker row: ${messages}`, {
|
|
69497
69821
|
why: "The contract marker row read from the database does not match the expected marker shape.",
|
|
69498
|
-
fix: "Re-sign the database with `prisma
|
|
69822
|
+
fix: "Re-sign the database with `prisma db sign`, or repair the marker table.",
|
|
69823
|
+
nextActions: [{
|
|
69824
|
+
kind: "run-command",
|
|
69825
|
+
label: "Re-sign the database",
|
|
69826
|
+
command: "{bin} db sign"
|
|
69827
|
+
}, {
|
|
69828
|
+
kind: "user-choice",
|
|
69829
|
+
label: "Repair the marker table by hand",
|
|
69830
|
+
reason: messages
|
|
69831
|
+
}],
|
|
69499
69832
|
meta: { issues: messages }
|
|
69500
69833
|
});
|
|
69501
69834
|
}
|
|
@@ -70284,12 +70617,14 @@ var PostgresControlAdapter = class {
|
|
|
70284
70617
|
const checkResult = await driver.query(`SELECT
|
|
70285
70618
|
cl.relname AS table_name,
|
|
70286
70619
|
c.conname AS constraint_name,
|
|
70287
|
-
|
|
70620
|
+
pg_get_expr(c.conbin, c.conrelid) AS check_expression
|
|
70288
70621
|
FROM pg_catalog.pg_constraint c
|
|
70289
70622
|
JOIN pg_catalog.pg_class cl ON cl.oid = c.conrelid
|
|
70290
70623
|
JOIN pg_catalog.pg_namespace ns ON ns.oid = cl.relnamespace
|
|
70291
70624
|
WHERE ns.nspname = $1
|
|
70292
70625
|
AND c.contype = 'c'
|
|
70626
|
+
AND c.conislocal
|
|
70627
|
+
AND c.conrelid <> 0
|
|
70293
70628
|
ORDER BY cl.relname, c.conname`, [schema]);
|
|
70294
70629
|
const columnsByTable = groupBy(columnsResult.rows, "table_name");
|
|
70295
70630
|
const pksByTable = groupBy(pkResult.rows, "table_name");
|
|
@@ -70431,15 +70766,11 @@ var PostgresControlAdapter = class {
|
|
|
70431
70766
|
columns: Object.freeze([...columnNames])
|
|
70432
70767
|
};
|
|
70433
70768
|
});
|
|
70434
|
-
const checksForTable = []
|
|
70435
|
-
|
|
70436
|
-
|
|
70437
|
-
|
|
70438
|
-
|
|
70439
|
-
column: parsed.column,
|
|
70440
|
-
permittedValues: parsed.permittedValues
|
|
70441
|
-
});
|
|
70442
|
-
}
|
|
70769
|
+
const checksForTable = (checksByTable.get(tableName) ?? []).map((checkRow) => ({
|
|
70770
|
+
naming: namingOfLiveName(checkRow.constraint_name),
|
|
70771
|
+
expression: checkRow.check_expression,
|
|
70772
|
+
dependsOn: postgresColumnDependsOn(schema, tableName, Object.keys(columns))
|
|
70773
|
+
}));
|
|
70443
70774
|
tableInputs[tableName] = {
|
|
70444
70775
|
name: tableName,
|
|
70445
70776
|
columns,
|
|
@@ -70730,75 +71061,6 @@ function groupBy(items, key) {
|
|
|
70730
71061
|
}
|
|
70731
71062
|
return map;
|
|
70732
71063
|
}
|
|
70733
|
-
/**
|
|
70734
|
-
* Parses a Postgres check-constraint definition string (as returned by
|
|
70735
|
-
* `pg_get_constraintdef`) into a column name and permitted values array.
|
|
70736
|
-
*
|
|
70737
|
-
* Handles two shapes that Postgres emits for enum-style checks:
|
|
70738
|
-
*
|
|
70739
|
-
* 1. `= ANY (ARRAY[...])` — Postgres rewrites `col IN ('a','b')` to this form:
|
|
70740
|
-
* `CHECK ((col = ANY (ARRAY['a'::text, 'b'::text])))`
|
|
70741
|
-
*
|
|
70742
|
-
* 2. `IN (...)` — stays as-is when written directly:
|
|
70743
|
-
* `CHECK ((col IN ('a', 'b')))`
|
|
70744
|
-
*
|
|
70745
|
-
* Column names may be plain identifiers (`status`) or double-quoted identifiers
|
|
70746
|
-
* (`"my-col"`). Double-quoted identifiers with embedded `""` are un-escaped to a
|
|
70747
|
-
* single `"`.
|
|
70748
|
-
*
|
|
70749
|
-
* String literal values may contain Postgres-style doubled single-quotes (`''`),
|
|
70750
|
-
* which are un-escaped to a single `'` (e.g. `O''Brien` → `O'Brien`).
|
|
70751
|
-
*
|
|
70752
|
-
* Returns `{ column, permittedValues }` when the predicate matches one of
|
|
70753
|
-
* the two recognised shapes. Returns `undefined` for anything else (e.g.
|
|
70754
|
-
* a free-form SQL predicate that wasn't emitted by this slice).
|
|
70755
|
-
*/
|
|
70756
|
-
function parseCheckConstraintDef(constraintdef) {
|
|
70757
|
-
const afterCheck = constraintdef.replace(/^CHECK\s*\(/i, "").replace(/\)$/, "").trim();
|
|
70758
|
-
const inner = afterCheck.startsWith("(") && afterCheck.endsWith(")") ? afterCheck.slice(1, -1).trim() : afterCheck;
|
|
70759
|
-
const anyArrayMatch = inner.match(/^(?:"((?:[^"]|"")*)"|(\w+))\s*=\s*ANY\s*\(\s*ARRAY\s*\[(.+)\]\s*\)\s*$/i);
|
|
70760
|
-
if (anyArrayMatch) {
|
|
70761
|
-
const column = anyArrayMatch[1] !== void 0 ? anyArrayMatch[1].replace(/""/g, "\"") : anyArrayMatch[2];
|
|
70762
|
-
const arrayBody = anyArrayMatch[3];
|
|
70763
|
-
if (!column || !arrayBody) return void 0;
|
|
70764
|
-
const permittedValues = extractArrayLiterals(arrayBody);
|
|
70765
|
-
return permittedValues ? {
|
|
70766
|
-
column,
|
|
70767
|
-
permittedValues
|
|
70768
|
-
} : void 0;
|
|
70769
|
-
}
|
|
70770
|
-
const inMatch = inner.match(/^(?:"((?:[^"]|"")*)"|(\w+))\s+IN\s*\((.+)\)\s*$/i);
|
|
70771
|
-
if (inMatch) {
|
|
70772
|
-
const column = inMatch[1] !== void 0 ? inMatch[1].replace(/""/g, "\"") : inMatch[2];
|
|
70773
|
-
const listBody = inMatch[3];
|
|
70774
|
-
if (!column || !listBody) return void 0;
|
|
70775
|
-
const permittedValues = extractQuotedLiterals(listBody);
|
|
70776
|
-
return permittedValues ? {
|
|
70777
|
-
column,
|
|
70778
|
-
permittedValues
|
|
70779
|
-
} : void 0;
|
|
70780
|
-
}
|
|
70781
|
-
}
|
|
70782
|
-
/**
|
|
70783
|
-
* Extracts string literals from an `ARRAY[...]` body.
|
|
70784
|
-
* Handles `'value'::type` casts by stripping the cast part.
|
|
70785
|
-
* Postgres stores single quotes inside values as doubled single-quotes (`''`);
|
|
70786
|
-
* each extracted value is un-escaped so `O''Brien` becomes `O'Brien`.
|
|
70787
|
-
*/
|
|
70788
|
-
function extractArrayLiterals(arrayBody) {
|
|
70789
|
-
const values = [...arrayBody.matchAll(/'((?:[^'\\]|\\.|'')*)'\s*(?:::[^\s,\]]+)?/g)].map((m) => (m[1] ?? "").replace(/''/g, "'"));
|
|
70790
|
-
return values.length > 0 ? values : void 0;
|
|
70791
|
-
}
|
|
70792
|
-
/**
|
|
70793
|
-
* Extracts string literals from an `IN (...)` list.
|
|
70794
|
-
* Handles single-quoted literals with possible escaped quotes.
|
|
70795
|
-
* Postgres stores single quotes inside values as doubled single-quotes (`''`);
|
|
70796
|
-
* each extracted value is un-escaped so `O''Brien` becomes `O'Brien`.
|
|
70797
|
-
*/
|
|
70798
|
-
function extractQuotedLiterals(listBody) {
|
|
70799
|
-
const values = [...listBody.matchAll(/'((?:[^'\\]|\\.|'')*)'/g)].map((m) => (m[1] ?? "").replace(/''/g, "'"));
|
|
70800
|
-
return values.length > 0 ? values : void 0;
|
|
70801
|
-
}
|
|
70802
71064
|
function pgIsTextLikeNativeType(nativeType) {
|
|
70803
71065
|
return nativeType === "text" || nativeType === "varchar" || nativeType.startsWith("varchar(") || nativeType === "character varying" || nativeType.startsWith("character varying(") || nativeType === "char" || nativeType.startsWith("char(") || nativeType === "character" || nativeType.startsWith("character(");
|
|
70804
71066
|
}
|
|
@@ -70837,14 +71099,28 @@ function pgInlineLiteral(wire, nativeType) {
|
|
|
70837
71099
|
nativeType
|
|
70838
71100
|
} });
|
|
70839
71101
|
}
|
|
71102
|
+
const SERIAL_FAMILY_TYPES = /* @__PURE__ */ new Set([
|
|
71103
|
+
"serial",
|
|
71104
|
+
"serial4",
|
|
71105
|
+
"bigserial",
|
|
71106
|
+
"serial8",
|
|
71107
|
+
"smallserial",
|
|
71108
|
+
"serial2"
|
|
71109
|
+
]);
|
|
70840
71110
|
async function pgRenderDdlColumnDefault(def, nativeType, codecLookup, codecRef) {
|
|
70841
71111
|
if (def.kind === "function") {
|
|
70842
|
-
if (def.expression === "autoincrement()")
|
|
71112
|
+
if (def.expression === "autoincrement()") {
|
|
71113
|
+
if (!SERIAL_FAMILY_TYPES.has(nativeType.toLowerCase())) throw postgresError("CONTRACT.DEFAULT_INVALID", `Column type "${nativeType}" has an autoincrement() default but is not a SERIAL-family pseudo-type. Autoincrement columns must declare their type as SERIAL (or SERIAL4), BIGSERIAL (or SERIAL8), or SMALLSERIAL (or SERIAL2) — e.g. col(name, "SERIAL", { default: fn("autoincrement()") }).`, { meta: { nativeType } });
|
|
71114
|
+
return "";
|
|
71115
|
+
}
|
|
70843
71116
|
return `DEFAULT (${def.expression})`;
|
|
70844
71117
|
}
|
|
70845
71118
|
if (codecRef !== void 0) {
|
|
70846
71119
|
const codec = codecLookup.get(codecRef.codecId);
|
|
70847
|
-
if (codec !== void 0)
|
|
71120
|
+
if (codec !== void 0) {
|
|
71121
|
+
const value = def.value instanceof Date ? def.value : codec.decodeJson(def.value);
|
|
71122
|
+
return `DEFAULT ${pgInlineLiteral(await codec.encode(value, {}), nativeType)}`;
|
|
71123
|
+
}
|
|
70848
71124
|
}
|
|
70849
71125
|
return `DEFAULT ${pgInlineLiteral(def.value, nativeType)}`;
|
|
70850
71126
|
}
|
|
@@ -71045,15 +71321,28 @@ const produces = (operation, input, codecId) => ({
|
|
|
71045
71321
|
},
|
|
71046
71322
|
nullable: true
|
|
71047
71323
|
});
|
|
71048
|
-
/**
|
|
71324
|
+
/** The same, for an operation that builds its own expression. */
|
|
71325
|
+
const producesVia = (operation, input, codecId, lower) => ({
|
|
71326
|
+
...produces(operation, input, codecId),
|
|
71327
|
+
lower
|
|
71328
|
+
});
|
|
71329
|
+
/** The SQL aggregate a lossless variant computes with. `sumBigInt` is a `sum` read exactly, `countBigInt` a `count`, `avgDecimal` an `avg`: the variants differ in how the result is read, never in what the database computes. */
|
|
71330
|
+
const computedWith = (fn) => ({ expr }) => new AggregateExpr(fn, expr);
|
|
71331
|
+
/** `avg` over an integer column, rounded once. PostgreSQL computes the exact `numeric` mean and the cast turns that one value into the `double precision` the result codec reads; casting the input instead would round every value before it was accumulated. */
|
|
71332
|
+
const avgCastToFloat8 = ({ expr }) => CastExpr.as(new AggregateExpr("avg", expr), "float8");
|
|
71333
|
+
/** Integer codecs whose `sum` widens to `bigint` — every built-in integer bar the 64-bit ones, whose sum goes to `numeric` instead. */
|
|
71049
71334
|
const SUM_WIDENS_TO_INT8 = [
|
|
71050
71335
|
PG_INT2_CODEC_ID,
|
|
71051
71336
|
PG_INT4_CODEC_ID,
|
|
71052
71337
|
PG_INT_CODEC_ID,
|
|
71053
71338
|
SQL_INT_CODEC_ID
|
|
71054
71339
|
];
|
|
71055
|
-
/**
|
|
71056
|
-
const
|
|
71340
|
+
/** The 64-bit integer codecs: PostgreSQL computes their `sum` as a `numeric`, a total free to leave the range an `int8` holds. */
|
|
71341
|
+
const SUM_WIDENS_TO_NUMERIC = [PG_INT8_CODEC_ID, PG_INT8_NUMBER_CODEC_ID];
|
|
71342
|
+
/** The integer codecs a `sum` reads back as a `number`: every fixed-width one, whatever its own application type. */
|
|
71343
|
+
const FIXED_WIDTH_INTEGER_CODECS = [...SUM_WIDENS_TO_INT8, ...SUM_WIDENS_TO_NUMERIC];
|
|
71344
|
+
/** Every built-in integer codec, the unbounded one included: `avg` over any of them is a `numeric` mean. */
|
|
71345
|
+
const INTEGER_CODECS = [...FIXED_WIDTH_INTEGER_CODECS, PG_UNBOUNDED_INT_CODEC_ID];
|
|
71057
71346
|
/** Codecs over `double precision`, whose `sum` and `avg` stay there. */
|
|
71058
71347
|
const DOUBLE_PRECISION_CODECS = [
|
|
71059
71348
|
PG_FLOAT8_CODEC_ID,
|
|
@@ -71091,20 +71380,36 @@ const postgresAggregateDescriptors = [
|
|
|
71091
71380
|
{
|
|
71092
71381
|
operation: "count",
|
|
71093
71382
|
input: { kind: "any" },
|
|
71383
|
+
output: {
|
|
71384
|
+
kind: "codec",
|
|
71385
|
+
codecId: PG_INT8_NUMBER_CODEC_ID
|
|
71386
|
+
},
|
|
71387
|
+
nullable: false,
|
|
71388
|
+
emptyResultJson: 0
|
|
71389
|
+
},
|
|
71390
|
+
{
|
|
71391
|
+
operation: "countBigInt",
|
|
71392
|
+
input: { kind: "any" },
|
|
71094
71393
|
output: {
|
|
71095
71394
|
kind: "codec",
|
|
71096
71395
|
codecId: PG_INT8_CODEC_ID
|
|
71097
71396
|
},
|
|
71098
|
-
nullable: false
|
|
71397
|
+
nullable: false,
|
|
71398
|
+
emptyResultJson: "0",
|
|
71399
|
+
lower: computedWith("count")
|
|
71099
71400
|
},
|
|
71100
|
-
...
|
|
71101
|
-
|
|
71401
|
+
...FIXED_WIDTH_INTEGER_CODECS.map((codecId) => produces("sum", overCodec(codecId), PG_INT8_NUMBER_CODEC_ID)),
|
|
71402
|
+
...SUM_WIDENS_TO_INT8.map((codecId) => producesVia("sumBigInt", overCodec(codecId), PG_INT8_CODEC_ID, computedWith("sum"))),
|
|
71403
|
+
...SUM_WIDENS_TO_NUMERIC.map((codecId) => producesVia("sumBigInt", overCodec(codecId), PG_UNBOUNDED_INT_CODEC_ID, computedWith("sum"))),
|
|
71404
|
+
producesVia("sumBigInt", overCodec(PG_UNBOUNDED_INT_CODEC_ID), PG_UNBOUNDED_INT_CODEC_ID, computedWith("sum")),
|
|
71102
71405
|
produces("sum", overCodec(PG_FLOAT4_CODEC_ID), PG_FLOAT4_CODEC_ID),
|
|
71103
71406
|
...DOUBLE_PRECISION_CODECS.map((codecId) => produces("sum", overCodec(codecId), PG_FLOAT8_CODEC_ID)),
|
|
71104
71407
|
produces("sum", overCodec(PG_NUMERIC_CODEC_ID), PG_NUMERIC_CODEC_ID),
|
|
71408
|
+
produces("sum", overCodec(PG_UNBOUNDED_INT_CODEC_ID), PG_UNBOUNDED_INT_CODEC_ID),
|
|
71105
71409
|
produces("sum", overCodec(PG_INTERVAL_CODEC_ID), PG_INTERVAL_CODEC_ID),
|
|
71106
71410
|
produces("sum", overCodec(PG_TIME_CODEC_ID), PG_INTERVAL_CODEC_ID),
|
|
71107
|
-
...
|
|
71411
|
+
...INTEGER_CODECS.map((codecId) => producesVia("avg", overCodec(codecId), PG_FLOAT8_CODEC_ID, avgCastToFloat8)),
|
|
71412
|
+
...[...INTEGER_CODECS, PG_NUMERIC_CODEC_ID].map((codecId) => producesVia("avgDecimal", overCodec(codecId), PG_NUMERIC_CODEC_ID, computedWith("avg"))),
|
|
71108
71413
|
...[PG_FLOAT4_CODEC_ID, ...DOUBLE_PRECISION_CODECS].map((codecId) => produces("avg", overCodec(codecId), PG_FLOAT8_CODEC_ID)),
|
|
71109
71414
|
produces("avg", overCodec(PG_NUMERIC_CODEC_ID), PG_NUMERIC_CODEC_ID),
|
|
71110
71415
|
produces("avg", overCodec(PG_INTERVAL_CODEC_ID), PG_INTERVAL_CODEC_ID),
|
|
@@ -71196,7 +71501,8 @@ const postgresAdapterDescriptorMeta = {
|
|
|
71196
71501
|
returning: true,
|
|
71197
71502
|
defaultInInsert: true,
|
|
71198
71503
|
lateral: true,
|
|
71199
|
-
scalarList: true
|
|
71504
|
+
scalarList: true,
|
|
71505
|
+
checkConstraint: true
|
|
71200
71506
|
}
|
|
71201
71507
|
},
|
|
71202
71508
|
types: {
|
|
@@ -71513,9 +71819,9 @@ function classifyDiffEntityKind(issue, entityKindOf) {
|
|
|
71513
71819
|
* issue reason. The vocabulary maps one-to-one: an undeclared live entity or
|
|
71514
71820
|
* namespace is `extraTopLevelObject`, an undeclared live field
|
|
71515
71821
|
* `extraNestedElement`, undeclared auxiliaries (constraints, indexes,
|
|
71516
|
-
* defaults) and structural leaves (policies) `extraAuxiliary`;
|
|
71517
|
-
*
|
|
71518
|
-
* `
|
|
71822
|
+
* defaults) and structural leaves (policies) `extraAuxiliary`; every paired
|
|
71823
|
+
* divergence is `declaredIncompatible`; anything the database lacks is
|
|
71824
|
+
* `declaredMissing`.
|
|
71519
71825
|
* `granularityOf` is the target's classifier, so target and extension node
|
|
71520
71826
|
* kinds classify without the family importing them.
|
|
71521
71827
|
*/
|
|
@@ -71527,7 +71833,6 @@ function classifySqlDiffIssue(issue, granularityOf) {
|
|
|
71527
71833
|
if (granularity === "field") return "extraNestedElement";
|
|
71528
71834
|
return "extraAuxiliary";
|
|
71529
71835
|
}
|
|
71530
|
-
if (issueNode$1(issue)?.nodeKind === RelationalSchemaNodeKind.check) return "valueDrift";
|
|
71531
71836
|
return "declaredIncompatible";
|
|
71532
71837
|
}
|
|
71533
71838
|
/**
|
|
@@ -71929,7 +72234,11 @@ const sortTargets = [{
|
|
|
71929
72234
|
"table",
|
|
71930
72235
|
"*"
|
|
71931
72236
|
],
|
|
71932
|
-
arrayKeys: [
|
|
72237
|
+
arrayKeys: [
|
|
72238
|
+
"checks",
|
|
72239
|
+
"indexes",
|
|
72240
|
+
"uniques"
|
|
72241
|
+
]
|
|
71933
72242
|
}];
|
|
71934
72243
|
const matchesPreserveEmptyPattern = createPreserveEmptyPredicate(preserveEmptyPatterns);
|
|
71935
72244
|
const shouldPreserveEmpty = (path) => isColumnDefaultValuePath(path) || matchesPreserveEmptyPattern(path);
|
|
@@ -72731,27 +73040,29 @@ function generateStorageNamespacesType(namespaces) {
|
|
|
72731
73040
|
}
|
|
72732
73041
|
const EXACT_NAME_BODY_PREAMBLE = "Drift detection compares the authored SQL text byte-for-byte against Postgres's reprinted form, which is only reliable when the text was captured by contract infer.";
|
|
72733
73042
|
/**
|
|
72734
|
-
* Per-subject remediation: an index moves to wire naming via
|
|
72735
|
-
* a policy has no such parameter — dropping `@@map` makes the
|
|
72736
|
-
* the wire prefix.
|
|
73043
|
+
* Per-subject remediation: an index or check moves to wire naming via
|
|
73044
|
+
* `name:`; a policy has no such parameter — dropping `@@map` makes the
|
|
73045
|
+
* block's head the wire prefix.
|
|
72737
73046
|
*/
|
|
72738
73047
|
const EXACT_NAME_BODY_REMEDIATION = {
|
|
72739
73048
|
index: "For hand-authored definitions, use name: and let Prisma Next manage the physical name; to migrate an adopted object to wire naming, replace map: with name: (keeping the body text unchanged) and apply the resulting rename migration.",
|
|
72740
|
-
policy: "For hand-authored definitions, drop @@map and let the policy block's head name the policy; to migrate an adopted policy to wire naming, remove @@map (keeping the body text unchanged) and apply the resulting rename migration."
|
|
73049
|
+
policy: "For hand-authored definitions, drop @@map and let the policy block's head name the policy; to migrate an adopted policy to wire naming, remove @@map (keeping the body text unchanged) and apply the resulting rename migration.",
|
|
73050
|
+
check: "For hand-authored definitions, use name: and let Prisma Next manage the physical name; to migrate an adopted check to wire naming, replace map: with name: (keeping the body text unchanged) and apply the resulting rename migration."
|
|
72741
73051
|
};
|
|
72742
|
-
/** What the user actually wrote, per subject: index `map:`, policy `@@map`. */
|
|
73052
|
+
/** What the user actually wrote, per subject: index and check `map:`, policy `@@map`. */
|
|
72743
73053
|
const EXACT_NAME_FEATURE = {
|
|
72744
73054
|
index: "map:",
|
|
72745
|
-
policy: "@@map"
|
|
73055
|
+
policy: "@@map",
|
|
73056
|
+
check: "map:"
|
|
72746
73057
|
};
|
|
72747
73058
|
const EXACT_NAME_BODY_WARNING_CODE = "PN_EXACT_NAME_BODY_COMPARISON";
|
|
72748
73059
|
/**
|
|
72749
73060
|
* Mints the exact-name body-comparison warning for a `map:`-named object
|
|
72750
73061
|
* carrying a hand-authorable SQL body — fully formed, so the transport and
|
|
72751
|
-
* the flush stay generic. `subject`
|
|
72752
|
-
*
|
|
72753
|
-
* subject-specific end to end, so a batched summary
|
|
72754
|
-
* code + summary) is true of every object it covers.
|
|
73062
|
+
* the flush stay generic. `subject` distinguishes the index, policy, and
|
|
73063
|
+
* check callers that mint this same warning; the feature name and the
|
|
73064
|
+
* remediation are subject-specific end to end, so a batched summary
|
|
73065
|
+
* (grouped on code + summary) is true of every object it covers.
|
|
72755
73066
|
*/
|
|
72756
73067
|
function exactNameBodyWarning(subject, exactName) {
|
|
72757
73068
|
const item = `${subject} "${exactName}"`;
|
|
@@ -73119,6 +73430,26 @@ function rejectDuplicateWireNamedIndexContent(indexes, coordinate, errors) {
|
|
|
73119
73430
|
seenContent.add(content);
|
|
73120
73431
|
}
|
|
73121
73432
|
}
|
|
73433
|
+
/**
|
|
73434
|
+
* Two wire-named checks with the same predicate are one check written twice —
|
|
73435
|
+
* the content hash is their identity, so neither spelling can survive, and
|
|
73436
|
+
* whitespace variants of one predicate collapse onto the same hash. An
|
|
73437
|
+
* exact-named check is identified by its name instead, so content twins under
|
|
73438
|
+
* two names are legal (the legacy shape a database adopts from) and a repeated
|
|
73439
|
+
* name is rejected by the named-object check.
|
|
73440
|
+
*/
|
|
73441
|
+
function rejectDuplicateWireNamedCheckContent(checks, coordinate, errors) {
|
|
73442
|
+
const seenContent = /* @__PURE__ */ new Set();
|
|
73443
|
+
for (const check of checks) {
|
|
73444
|
+
if (check.prefix === void 0) continue;
|
|
73445
|
+
const content = computeCheckContentHash(check.expression);
|
|
73446
|
+
if (seenContent.has(content)) {
|
|
73447
|
+
errors.push(`${coordinate}: duplicate check constraint definition (expression "${check.expression}")`);
|
|
73448
|
+
continue;
|
|
73449
|
+
}
|
|
73450
|
+
seenContent.add(content);
|
|
73451
|
+
}
|
|
73452
|
+
}
|
|
73122
73453
|
function isContractFieldType(value) {
|
|
73123
73454
|
if (!isPlainRecord(value)) return false;
|
|
73124
73455
|
const kind = value["kind"];
|
|
@@ -73308,18 +73639,7 @@ function validateStorageSemantics(storage) {
|
|
|
73308
73639
|
if (fk.onDelete === "setDefault" && !column.nullable && column.default === void 0) errors.push(`Namespace "${namespaceId}" table "${tableName}": onDelete setDefault on foreign key column "${colName}" which is NOT NULL and has no DEFAULT`);
|
|
73309
73640
|
if (fk.onUpdate === "setDefault" && !column.nullable && column.default === void 0) errors.push(`Namespace "${namespaceId}" table "${tableName}": onUpdate setDefault on foreign key column "${colName}" which is NOT NULL and has no DEFAULT`);
|
|
73310
73641
|
}
|
|
73311
|
-
|
|
73312
|
-
for (const check of table.checks ?? []) {
|
|
73313
|
-
const signature = JSON.stringify({
|
|
73314
|
-
column: check.column,
|
|
73315
|
-
valueSet: check.valueSet
|
|
73316
|
-
});
|
|
73317
|
-
if (seenCheckDefinitions.has(signature)) {
|
|
73318
|
-
errors.push(`Namespace "${namespaceId}" table "${tableName}": duplicate check constraint definition on column "${check.column}"`);
|
|
73319
|
-
continue;
|
|
73320
|
-
}
|
|
73321
|
-
seenCheckDefinitions.add(signature);
|
|
73322
|
-
}
|
|
73642
|
+
rejectDuplicateWireNamedCheckContent(table.checks ?? [], tableCoordinate, errors);
|
|
73323
73643
|
}
|
|
73324
73644
|
return errors;
|
|
73325
73645
|
}
|
|
@@ -73369,7 +73689,6 @@ function validateSqlStorageConsistency(contract) {
|
|
|
73369
73689
|
}
|
|
73370
73690
|
for (const unique of table.uniques) for (const colName of unique.columns) if (!columnNames.has(colName)) throw new ContractValidationError(`Namespace "${namespaceId}" table "${tableName}" unique constraint references non-existent column "${colName}"`, "storage");
|
|
73371
73691
|
for (const index of table.indexes) for (const colName of index.columns ?? []) if (!columnNames.has(colName)) throw new ContractValidationError(`Namespace "${namespaceId}" table "${tableName}" index references non-existent column "${colName}"`, "storage");
|
|
73372
|
-
for (const check of table.checks ?? []) if (!columnNames.has(check.column)) throw new ContractValidationError(`Namespace "${namespaceId}" table "${tableName}" check constraint "${check.name}" references non-existent column "${check.column}"`, "storage");
|
|
73373
73692
|
for (const [colName, column] of Object.entries(table.columns)) if (!column.nullable && column.default?.kind === "literal" && column.default.value === null) throw new ContractValidationError(`Namespace "${namespaceId}" table "${tableName}" column "${colName}" is NOT NULL but has a literal null default`, "storage");
|
|
73374
73693
|
for (const fk of table.foreignKeys) {
|
|
73375
73694
|
if (fk.source.namespaceId !== namespaceId || fk.source.tableName !== tableName) throw new ContractValidationError(`Namespace "${namespaceId}" table "${tableName}" contains foreignKey with mismatched source coordinates (${fk.source.namespaceId}.${fk.source.tableName})`, "storage");
|
|
@@ -74289,14 +74608,65 @@ const OK_VOID = ResultImpl.ok(void 0);
|
|
|
74289
74608
|
function okVoid() {
|
|
74290
74609
|
return OK_VOID;
|
|
74291
74610
|
}
|
|
74611
|
+
const _DRIVE_LETTER_START_RE = /^[A-Za-z]:\//;
|
|
74292
74612
|
function normalizeWindowsPath(input = "") {
|
|
74293
74613
|
if (!input) return input;
|
|
74294
74614
|
return input.replace(/\\/g, "/").replace(_DRIVE_LETTER_START_RE, (r) => r.toUpperCase());
|
|
74295
74615
|
}
|
|
74616
|
+
const _UNC_REGEX = /^[/\\]{2}/;
|
|
74617
|
+
const _IS_ABSOLUTE_RE = /^[/\\](?![/\\])|^[/\\]{2}(?!\.)|^[A-Za-z]:[/\\]/;
|
|
74618
|
+
const _DRIVE_LETTER_RE = /^[A-Za-z]:$/;
|
|
74619
|
+
const _ROOT_FOLDER_RE = /^\/([A-Za-z]:)?$/;
|
|
74620
|
+
const normalize = function(path) {
|
|
74621
|
+
if (path.length === 0) return ".";
|
|
74622
|
+
path = normalizeWindowsPath(path);
|
|
74623
|
+
const isUNCPath = path.match(_UNC_REGEX);
|
|
74624
|
+
const isPathAbsolute = isAbsolute(path);
|
|
74625
|
+
const trailingSeparator = path[path.length - 1] === "/";
|
|
74626
|
+
path = normalizeString(path, !isPathAbsolute);
|
|
74627
|
+
if (path.length === 0) {
|
|
74628
|
+
if (isPathAbsolute) return "/";
|
|
74629
|
+
return trailingSeparator ? "./" : ".";
|
|
74630
|
+
}
|
|
74631
|
+
if (trailingSeparator) path += "/";
|
|
74632
|
+
if (_DRIVE_LETTER_RE.test(path)) path += "/";
|
|
74633
|
+
if (isUNCPath) {
|
|
74634
|
+
if (!isPathAbsolute) return `//./${path}`;
|
|
74635
|
+
return `//${path}`;
|
|
74636
|
+
}
|
|
74637
|
+
return isPathAbsolute && !isAbsolute(path) ? `/${path}` : path;
|
|
74638
|
+
};
|
|
74639
|
+
const join$1 = function(...segments) {
|
|
74640
|
+
let path = "";
|
|
74641
|
+
for (const seg of segments) {
|
|
74642
|
+
if (!seg) continue;
|
|
74643
|
+
if (path.length > 0) {
|
|
74644
|
+
const pathTrailing = path[path.length - 1] === "/";
|
|
74645
|
+
const segLeading = seg[0] === "/";
|
|
74646
|
+
if (pathTrailing && segLeading) path += seg.slice(1);
|
|
74647
|
+
else path += pathTrailing || segLeading ? seg : `/${seg}`;
|
|
74648
|
+
} else path += seg;
|
|
74649
|
+
}
|
|
74650
|
+
return normalize(path);
|
|
74651
|
+
};
|
|
74296
74652
|
function cwd() {
|
|
74297
74653
|
if (typeof process !== "undefined" && typeof process.cwd === "function") return process.cwd().replace(/\\/g, "/");
|
|
74298
74654
|
return "/";
|
|
74299
74655
|
}
|
|
74656
|
+
const resolve = function(...arguments_) {
|
|
74657
|
+
arguments_ = arguments_.map((argument) => normalizeWindowsPath(argument));
|
|
74658
|
+
let resolvedPath = "";
|
|
74659
|
+
let resolvedAbsolute = false;
|
|
74660
|
+
for (let index = arguments_.length - 1; index >= -1 && !resolvedAbsolute; index--) {
|
|
74661
|
+
const path = index >= 0 ? arguments_[index] : cwd();
|
|
74662
|
+
if (!path || path.length === 0) continue;
|
|
74663
|
+
resolvedPath = `${path}/${resolvedPath}`;
|
|
74664
|
+
resolvedAbsolute = isAbsolute(path);
|
|
74665
|
+
}
|
|
74666
|
+
resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute);
|
|
74667
|
+
if (resolvedAbsolute && !isAbsolute(resolvedPath)) return `/${resolvedPath}`;
|
|
74668
|
+
return resolvedPath.length > 0 ? resolvedPath : ".";
|
|
74669
|
+
};
|
|
74300
74670
|
function normalizeString(path, allowAboveRoot) {
|
|
74301
74671
|
let res = "";
|
|
74302
74672
|
let lastSegmentLength = 0;
|
|
@@ -74347,107 +74717,38 @@ function normalizeString(path, allowAboveRoot) {
|
|
|
74347
74717
|
}
|
|
74348
74718
|
return res;
|
|
74349
74719
|
}
|
|
74350
|
-
|
|
74351
|
-
|
|
74352
|
-
|
|
74353
|
-
|
|
74354
|
-
|
|
74355
|
-
|
|
74356
|
-
|
|
74357
|
-
|
|
74358
|
-
|
|
74359
|
-
|
|
74360
|
-
|
|
74361
|
-
|
|
74362
|
-
|
|
74363
|
-
|
|
74364
|
-
|
|
74365
|
-
|
|
74366
|
-
|
|
74367
|
-
|
|
74368
|
-
|
|
74369
|
-
|
|
74370
|
-
|
|
74371
|
-
|
|
74372
|
-
|
|
74373
|
-
|
|
74374
|
-
|
|
74375
|
-
if (
|
|
74376
|
-
|
|
74377
|
-
|
|
74378
|
-
}
|
|
74379
|
-
if (trailingSeparator) path += "/";
|
|
74380
|
-
if (_DRIVE_LETTER_RE.test(path)) path += "/";
|
|
74381
|
-
if (isUNCPath) {
|
|
74382
|
-
if (!isPathAbsolute) return `//./${path}`;
|
|
74383
|
-
return `//${path}`;
|
|
74384
|
-
}
|
|
74385
|
-
return isPathAbsolute && !isAbsolute(path) ? `/${path}` : path;
|
|
74386
|
-
};
|
|
74387
|
-
join$1 = function(...segments) {
|
|
74388
|
-
let path = "";
|
|
74389
|
-
for (const seg of segments) {
|
|
74390
|
-
if (!seg) continue;
|
|
74391
|
-
if (path.length > 0) {
|
|
74392
|
-
const pathTrailing = path[path.length - 1] === "/";
|
|
74393
|
-
const segLeading = seg[0] === "/";
|
|
74394
|
-
if (pathTrailing && segLeading) path += seg.slice(1);
|
|
74395
|
-
else path += pathTrailing || segLeading ? seg : `/${seg}`;
|
|
74396
|
-
} else path += seg;
|
|
74397
|
-
}
|
|
74398
|
-
return normalize(path);
|
|
74399
|
-
};
|
|
74400
|
-
resolve = function(...arguments_) {
|
|
74401
|
-
arguments_ = arguments_.map((argument) => normalizeWindowsPath(argument));
|
|
74402
|
-
let resolvedPath = "";
|
|
74403
|
-
let resolvedAbsolute = false;
|
|
74404
|
-
for (let index = arguments_.length - 1; index >= -1 && !resolvedAbsolute; index--) {
|
|
74405
|
-
const path = index >= 0 ? arguments_[index] : cwd();
|
|
74406
|
-
if (!path || path.length === 0) continue;
|
|
74407
|
-
resolvedPath = `${path}/${resolvedPath}`;
|
|
74408
|
-
resolvedAbsolute = isAbsolute(path);
|
|
74409
|
-
}
|
|
74410
|
-
resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute);
|
|
74411
|
-
if (resolvedAbsolute && !isAbsolute(resolvedPath)) return `/${resolvedPath}`;
|
|
74412
|
-
return resolvedPath.length > 0 ? resolvedPath : ".";
|
|
74413
|
-
};
|
|
74414
|
-
isAbsolute = function(p) {
|
|
74415
|
-
return _IS_ABSOLUTE_RE.test(p);
|
|
74416
|
-
};
|
|
74417
|
-
relative = function(from, to) {
|
|
74418
|
-
const _from = resolve(from).replace(_ROOT_FOLDER_RE, "$1").split("/");
|
|
74419
|
-
const _to = resolve(to).replace(_ROOT_FOLDER_RE, "$1").split("/");
|
|
74420
|
-
if (_to[0][1] === ":" && _from[0][1] === ":" && _from[0] !== _to[0]) return _to.join("/");
|
|
74421
|
-
const _fromCopy = [..._from];
|
|
74422
|
-
for (const segment of _fromCopy) {
|
|
74423
|
-
if (_to[0] !== segment) break;
|
|
74424
|
-
_from.shift();
|
|
74425
|
-
_to.shift();
|
|
74426
|
-
}
|
|
74427
|
-
return [..._from.map(() => ".."), ..._to].join("/");
|
|
74428
|
-
};
|
|
74429
|
-
dirname$1 = function(p) {
|
|
74430
|
-
const segments = normalizeWindowsPath(p).replace(/\/$/, "").split("/").slice(0, -1);
|
|
74431
|
-
if (segments.length === 1 && _DRIVE_LETTER_RE.test(segments[0])) segments[0] += "/";
|
|
74432
|
-
return segments.join("/") || (isAbsolute(p) ? "/" : ".");
|
|
74433
|
-
};
|
|
74434
|
-
basename = function(p, extension) {
|
|
74435
|
-
const segments = normalizeWindowsPath(p).split("/");
|
|
74436
|
-
let lastSegment = "";
|
|
74437
|
-
for (let i = segments.length - 1; i >= 0; i--) {
|
|
74438
|
-
const val = segments[i];
|
|
74439
|
-
if (val) {
|
|
74440
|
-
lastSegment = val;
|
|
74441
|
-
break;
|
|
74442
|
-
}
|
|
74720
|
+
const isAbsolute = function(p) {
|
|
74721
|
+
return _IS_ABSOLUTE_RE.test(p);
|
|
74722
|
+
};
|
|
74723
|
+
const relative = function(from, to) {
|
|
74724
|
+
const _from = resolve(from).replace(_ROOT_FOLDER_RE, "$1").split("/");
|
|
74725
|
+
const _to = resolve(to).replace(_ROOT_FOLDER_RE, "$1").split("/");
|
|
74726
|
+
if (_to[0][1] === ":" && _from[0][1] === ":" && _from[0] !== _to[0]) return _to.join("/");
|
|
74727
|
+
const _fromCopy = [..._from];
|
|
74728
|
+
for (const segment of _fromCopy) {
|
|
74729
|
+
if (_to[0] !== segment) break;
|
|
74730
|
+
_from.shift();
|
|
74731
|
+
_to.shift();
|
|
74732
|
+
}
|
|
74733
|
+
return [..._from.map(() => ".."), ..._to].join("/");
|
|
74734
|
+
};
|
|
74735
|
+
const dirname$1 = function(p) {
|
|
74736
|
+
const segments = normalizeWindowsPath(p).replace(/\/$/, "").split("/").slice(0, -1);
|
|
74737
|
+
if (segments.length === 1 && _DRIVE_LETTER_RE.test(segments[0])) segments[0] += "/";
|
|
74738
|
+
return segments.join("/") || (isAbsolute(p) ? "/" : ".");
|
|
74739
|
+
};
|
|
74740
|
+
const basename = function(p, extension) {
|
|
74741
|
+
const segments = normalizeWindowsPath(p).split("/");
|
|
74742
|
+
let lastSegment = "";
|
|
74743
|
+
for (let i = segments.length - 1; i >= 0; i--) {
|
|
74744
|
+
const val = segments[i];
|
|
74745
|
+
if (val) {
|
|
74746
|
+
lastSegment = val;
|
|
74747
|
+
break;
|
|
74443
74748
|
}
|
|
74444
|
-
|
|
74445
|
-
|
|
74446
|
-
}
|
|
74447
|
-
var init_dist = __esmMin((() => {
|
|
74448
|
-
init_pathe_M_eThtNZ();
|
|
74449
|
-
}));
|
|
74450
|
-
init_dist();
|
|
74749
|
+
}
|
|
74750
|
+
return extension && lastSegment.endsWith(extension) ? lastSegment.slice(0, -extension.length) : lastSegment;
|
|
74751
|
+
};
|
|
74451
74752
|
/**
|
|
74452
74753
|
* Build the canonical "re-emit this package" remediation hint.
|
|
74453
74754
|
*
|
|
@@ -74476,40 +74777,30 @@ function reemitHint(dir, fallback) {
|
|
|
74476
74777
|
* - category: Always 'MIGRATION'
|
|
74477
74778
|
* - why: Explains the cause in plain language
|
|
74478
74779
|
* - fix: Actionable remediation step
|
|
74479
|
-
* -
|
|
74780
|
+
* - meta: Machine-readable structured data for agents
|
|
74480
74781
|
*/
|
|
74481
|
-
var MigrationToolsError = class extends
|
|
74482
|
-
|
|
74483
|
-
category = "MIGRATION";
|
|
74484
|
-
why;
|
|
74485
|
-
fix;
|
|
74486
|
-
details;
|
|
74782
|
+
var MigrationToolsError = class extends CliStructuredError {
|
|
74783
|
+
category;
|
|
74487
74784
|
constructor(code, summary, options) {
|
|
74488
|
-
super(summary);
|
|
74489
|
-
this.
|
|
74490
|
-
this.code = code;
|
|
74491
|
-
this.why = options.why;
|
|
74492
|
-
this.fix = options.fix;
|
|
74493
|
-
this.details = options.details;
|
|
74785
|
+
super(code, summary, options);
|
|
74786
|
+
this.category = "MIGRATION";
|
|
74494
74787
|
}
|
|
74495
74788
|
static is(error) {
|
|
74496
|
-
|
|
74497
|
-
const candidate = error;
|
|
74498
|
-
return candidate.name === "MigrationToolsError" && typeof candidate.code === "string";
|
|
74789
|
+
return CliStructuredError.is(error) && "category" in error && error.category === "MIGRATION" && error.code.startsWith("MIGRATION.");
|
|
74499
74790
|
}
|
|
74500
74791
|
};
|
|
74501
74792
|
function errorDirectoryExists(dir) {
|
|
74502
74793
|
return new MigrationToolsError("MIGRATION.DIR_EXISTS", "Migration directory already exists", {
|
|
74503
74794
|
why: `The directory "${dir}" already exists. Each migration must have a unique directory.`,
|
|
74504
74795
|
fix: "Use --name to pick a different name, or delete the existing directory and re-run.",
|
|
74505
|
-
|
|
74796
|
+
meta: { dir }
|
|
74506
74797
|
});
|
|
74507
74798
|
}
|
|
74508
74799
|
function errorMissingFile(file, dir) {
|
|
74509
74800
|
return new MigrationToolsError("MIGRATION.FILE_MISSING", `Missing ${file}`, {
|
|
74510
74801
|
why: `Expected "${file}" in "${dir}" but the file does not exist.`,
|
|
74511
74802
|
fix: reemitHint(dir, "or delete the directory if the migration is unwanted and the source TypeScript is gone."),
|
|
74512
|
-
|
|
74803
|
+
meta: {
|
|
74513
74804
|
file,
|
|
74514
74805
|
dir
|
|
74515
74806
|
}
|
|
@@ -74519,7 +74810,7 @@ function errorInvalidJson(filePath, parseError) {
|
|
|
74519
74810
|
return new MigrationToolsError("MIGRATION.INVALID_JSON", "Invalid JSON in migration file", {
|
|
74520
74811
|
why: `Failed to parse "${filePath}": ${parseError}`,
|
|
74521
74812
|
fix: reemitHint(dirname$1(filePath), "or restore the directory from version control."),
|
|
74522
|
-
|
|
74813
|
+
meta: {
|
|
74523
74814
|
filePath,
|
|
74524
74815
|
parseError
|
|
74525
74816
|
}
|
|
@@ -74529,7 +74820,7 @@ function errorInvalidManifest(filePath, reason) {
|
|
|
74529
74820
|
return new MigrationToolsError("MIGRATION.INVALID_MANIFEST", "Invalid migration manifest", {
|
|
74530
74821
|
why: `Migration manifest at "${filePath}" is invalid: ${reason}`,
|
|
74531
74822
|
fix: reemitHint(dirname$1(filePath), "or restore the directory from version control."),
|
|
74532
|
-
|
|
74823
|
+
meta: {
|
|
74533
74824
|
filePath,
|
|
74534
74825
|
reason
|
|
74535
74826
|
}
|
|
@@ -74539,21 +74830,21 @@ function errorDescribeMissingEndContract() {
|
|
|
74539
74830
|
return new MigrationToolsError("MIGRATION.DESCRIBE_INVALID", "Migration.describe(): provide endContractJson or override describe() — a migration needs a destination contract hash.", {
|
|
74540
74831
|
why: "Migration.describe() was called on a migration that carries no endContractJson and does not override describe(), so no destination contract hash can be derived.",
|
|
74541
74832
|
fix: "Set endContractJson on the migration, or override describe() to return the { from, to } metadata explicitly.",
|
|
74542
|
-
|
|
74833
|
+
meta: { reason: "missing-end-contract" }
|
|
74543
74834
|
});
|
|
74544
74835
|
}
|
|
74545
74836
|
function errorSpaceHeadRefMissing(spaceId) {
|
|
74546
74837
|
return new MigrationToolsError("MIGRATION.CHECK_HEAD_REF_MISSING", `Contract space "${spaceId}" has no head ref; its contract cannot be resolved from the snapshot store without one.`, {
|
|
74547
74838
|
why: `Contract space "${spaceId}" declares no refs/head.json, so there is no hash to resolve its contract against the snapshot store.`,
|
|
74548
74839
|
fix: "Re-emit the contract-space migrations and head-ref artifacts (the extension's contract-space build), or restore refs/head.json from version control.",
|
|
74549
|
-
|
|
74840
|
+
meta: { spaceId }
|
|
74550
74841
|
});
|
|
74551
74842
|
}
|
|
74552
74843
|
function errorInvalidSpaceId(spaceId) {
|
|
74553
74844
|
return new MigrationToolsError("MIGRATION.INVALID_SPACE_ID", "Invalid contract space identifier", {
|
|
74554
74845
|
why: `The space id "${spaceId}" does not match the required pattern /^[a-z][a-z0-9_-]{0,63}$/. Space ids are used as filesystem directory names under \`migrations/\`, so the pattern is conservative on purpose.`,
|
|
74555
74846
|
fix: "Pick a lowercase identifier that begins with a letter and contains only lowercase letters, digits, hyphens, or underscores; max 64 characters total.",
|
|
74556
|
-
|
|
74847
|
+
meta: { spaceId }
|
|
74557
74848
|
});
|
|
74558
74849
|
}
|
|
74559
74850
|
function errorDescriptorHeadHashMismatch(args) {
|
|
@@ -74561,7 +74852,7 @@ function errorDescriptorHeadHashMismatch(args) {
|
|
|
74561
74852
|
return new MigrationToolsError("MIGRATION.DESCRIPTOR_HEAD_HASH_MISMATCH", "Extension descriptor's headRef.hash does not match its contractJson", {
|
|
74562
74853
|
why: `Extension "${extensionId}" publishes a \`contractSpace\` whose \`headRef.hash\` (${headRefHash}) does not match the canonical hash recomputed from \`contractSpace.contractJson\` (${recomputedHash}). This means the extension descriptor was published with stale \`headRef.hash\` — typically because the contract was bumped without rerunning the extension's emit pipeline.`,
|
|
74563
74854
|
fix: "Re-run the extension authoring pipeline so `contractJson.storage.storageHash` and `headRef.hash` agree, then republish the extension. If you are the extension author and you intentionally bumped `contractJson`, recompute and update `headRef.hash` (and refresh any on-disk migration metadata that derives from it).",
|
|
74564
|
-
|
|
74855
|
+
meta: {
|
|
74565
74856
|
extensionId,
|
|
74566
74857
|
recomputedHash,
|
|
74567
74858
|
headRefHash
|
|
@@ -74572,7 +74863,7 @@ function errorInvalidRefFile(filePath, reason) {
|
|
|
74572
74863
|
return new MigrationToolsError("MIGRATION.INVALID_REF_FILE", "Invalid ref file", {
|
|
74573
74864
|
why: `Ref file at "${filePath}" is invalid: ${reason}`,
|
|
74574
74865
|
fix: "Ensure the ref file contains valid JSON with { \"hash\": \"<64 hex chars>\", \"invariants\": [\"...\"] }.",
|
|
74575
|
-
|
|
74866
|
+
meta: {
|
|
74576
74867
|
path: filePath,
|
|
74577
74868
|
reason
|
|
74578
74869
|
}
|
|
@@ -74582,21 +74873,21 @@ function errorInvalidRefName(refName) {
|
|
|
74582
74873
|
return new MigrationToolsError("MIGRATION.INVALID_REF_NAME", "Invalid ref name", {
|
|
74583
74874
|
why: `Ref name "${refName}" is invalid. Names must be lowercase alphanumeric with hyphens or forward slashes (no "." or ".." segments).`,
|
|
74584
74875
|
fix: `Use a valid ref name (e.g., "staging", "envs/production").`,
|
|
74585
|
-
|
|
74876
|
+
meta: { refName }
|
|
74586
74877
|
});
|
|
74587
74878
|
}
|
|
74588
74879
|
function errorInvalidInvariantId(invariantId) {
|
|
74589
74880
|
return new MigrationToolsError("MIGRATION.INVALID_INVARIANT_ID", "Invalid invariantId", {
|
|
74590
74881
|
why: `invariantId ${JSON.stringify(invariantId)} is invalid. Ids must be non-empty and contain no whitespace or control characters (including Unicode whitespace like NBSP); other content (kebab-case, camelCase, namespaced, Unicode letters) is allowed.`,
|
|
74591
74882
|
fix: "Pick an invariantId without spaces, tabs, newlines, or control characters — e.g. \"backfill-user-phone\", \"users/backfill-phone\", or \"BackfillUserPhone\".",
|
|
74592
|
-
|
|
74883
|
+
meta: { invariantId }
|
|
74593
74884
|
});
|
|
74594
74885
|
}
|
|
74595
74886
|
function errorDuplicateInvariantInEdge(invariantId) {
|
|
74596
74887
|
return new MigrationToolsError("MIGRATION.DUPLICATE_INVARIANT_IN_EDGE", "Duplicate invariantId on a single migration", {
|
|
74597
74888
|
why: `invariantId "${invariantId}" is declared by more than one dataTransform on the same migration. The marker stores invariants as a set and the routing layer treats them as edge-level, so two ops cannot share a routing identity.`,
|
|
74598
74889
|
fix: "Rename one of the conflicting dataTransform invariantIds, or drop invariantId on the op that does not need to be routing-visible.",
|
|
74599
|
-
|
|
74890
|
+
meta: { invariantId }
|
|
74600
74891
|
});
|
|
74601
74892
|
}
|
|
74602
74893
|
function errorProvidedInvariantsMismatch(filePath, stored, derived) {
|
|
@@ -74607,7 +74898,7 @@ function errorProvidedInvariantsMismatch(filePath, stored, derived) {
|
|
|
74607
74898
|
return new MigrationToolsError("MIGRATION.PROVIDED_INVARIANTS_MISMATCH", "providedInvariants on migration.json disagrees with ops.json", {
|
|
74608
74899
|
why: missing.length === 0 && extra.length === 0 ? `migration.json at "${filePath}" stores providedInvariants ${JSON.stringify(stored)}, but the canonical value derived from ops.json is ${JSON.stringify(derived)} — same ids, different order. Canonical providedInvariants is sorted ascending.` : `migration.json at "${filePath}" stores providedInvariants ${JSON.stringify(stored)}, but the value derived from ops.json is ${JSON.stringify(derived)}. The manifest copy was likely hand-edited without re-emitting.`,
|
|
74609
74900
|
fix: reemitHint(dirname$1(filePath), "or restore the directory from version control."),
|
|
74610
|
-
|
|
74901
|
+
meta: {
|
|
74611
74902
|
filePath,
|
|
74612
74903
|
stored,
|
|
74613
74904
|
derived,
|
|
@@ -74625,7 +74916,7 @@ function errorNoInvariantPath(args) {
|
|
|
74625
74916
|
return new MigrationToolsError("MIGRATION.NO_INVARIANT_PATH", "No path covers the required invariants", {
|
|
74626
74917
|
why: `${refClause} requires invariants the reachable path doesn't cover. required=[${required.map((id) => JSON.stringify(id)).join(", ")}], missing=[${missingList}].`,
|
|
74627
74918
|
fix: "Add a migration on the path that runs `dataTransform({ invariantId: \"<id>\", … })` for each missing invariant, or retarget the ref to a hash whose path already provides them.",
|
|
74628
|
-
|
|
74919
|
+
meta: {
|
|
74629
74920
|
required,
|
|
74630
74921
|
missing,
|
|
74631
74922
|
structuralPath,
|
|
@@ -74637,7 +74928,7 @@ function errorMigrationHashMismatch(dir, storedHash, computedHash) {
|
|
|
74637
74928
|
return new MigrationToolsError("MIGRATION.HASH_MISMATCH", "Migration package is corrupt", {
|
|
74638
74929
|
why: `Stored migrationHash "${storedHash}" does not match the recomputed hash "${computedHash}" for "${relative(process.cwd(), dir)}". The migration.json or ops.json has been edited or partially written since emit.`,
|
|
74639
74930
|
fix: reemitHint(dir, "or restore the directory from version control."),
|
|
74640
|
-
|
|
74931
|
+
meta: {
|
|
74641
74932
|
dir,
|
|
74642
74933
|
storedHash,
|
|
74643
74934
|
computedHash
|
|
@@ -74653,8 +74944,24 @@ function errorMigrationHashMismatch(dir, storedHash, computedHash) {
|
|
|
74653
74944
|
function errorRefNotResolvable(refName) {
|
|
74654
74945
|
return new MigrationToolsError("MIGRATION.REF_NOT_RESOLVABLE", `Ref "${refName}" is not resolvable`, {
|
|
74655
74946
|
why: `Ref "${refName}" has no pointer file, and the hash being resolved is not a node in the migration graph either — there is nothing to materialize a contract from.`,
|
|
74656
|
-
fix: `Create the ref with "prisma
|
|
74657
|
-
|
|
74947
|
+
fix: `Create the ref with "prisma ref set ${refName} <hash>" (or advance it via "prisma db update --advance-ref ${refName}"), or pass a hash that is a node in the migration graph.`,
|
|
74948
|
+
nextActions: [
|
|
74949
|
+
{
|
|
74950
|
+
kind: "run-command",
|
|
74951
|
+
label: `Create the ref "${refName}"`,
|
|
74952
|
+
command: `{bin} ref set ${refName} <hash>`
|
|
74953
|
+
},
|
|
74954
|
+
{
|
|
74955
|
+
kind: "run-command",
|
|
74956
|
+
label: `Advance the ref "${refName}" as part of an update`,
|
|
74957
|
+
command: `{bin} db update --advance-ref ${refName}`
|
|
74958
|
+
},
|
|
74959
|
+
{
|
|
74960
|
+
kind: "user-choice",
|
|
74961
|
+
label: "Pass a hash that is already a node in the migration graph"
|
|
74962
|
+
}
|
|
74963
|
+
],
|
|
74964
|
+
meta: {
|
|
74658
74965
|
refName,
|
|
74659
74966
|
identifier: refName
|
|
74660
74967
|
}
|
|
@@ -74664,20 +74971,21 @@ function errorBundleNotFoundForGraphNode(hash, explicitLabel) {
|
|
|
74664
74971
|
return new MigrationToolsError("MIGRATION.BUNDLE_NOT_FOUND_FOR_GRAPH_NODE", explicitLabel ? `No migration bundle found for reference "${explicitLabel}" (resolved hash: ${hash})` : `No migration bundle found for graph node ${hash}`, {
|
|
74665
74972
|
why: `The hash ${hash} is a graph node but no on-disk migration package has a destination (\`to\`) hash matching it.`,
|
|
74666
74973
|
fix: "Provide a ref or hash that corresponds to an existing migration package, or run `migration list` to see available migrations.",
|
|
74667
|
-
|
|
74974
|
+
meta: {
|
|
74668
74975
|
hash,
|
|
74669
74976
|
...explicitLabel ? { explicitLabel } : {}
|
|
74670
74977
|
}
|
|
74671
74978
|
});
|
|
74672
74979
|
}
|
|
74673
|
-
function errorContractDeserializationFailed(filePath, message) {
|
|
74980
|
+
function errorContractDeserializationFailed(filePath, message, options) {
|
|
74674
74981
|
return new MigrationToolsError("MIGRATION.CONTRACT_DESERIALIZATION_FAILED", "Contract failed to deserialize", {
|
|
74675
74982
|
why: `Contract at "${filePath}" failed to deserialize: ${message}`,
|
|
74676
74983
|
fix: reemitHint(dirname$1(filePath), "or restore the directory from version control."),
|
|
74677
|
-
|
|
74984
|
+
meta: {
|
|
74678
74985
|
filePath,
|
|
74679
74986
|
message
|
|
74680
|
-
}
|
|
74987
|
+
},
|
|
74988
|
+
...ifDefined("cause", options?.cause)
|
|
74681
74989
|
});
|
|
74682
74990
|
}
|
|
74683
74991
|
function errorHashNotInGraph(hash, graph) {
|
|
@@ -74685,8 +74993,17 @@ function errorHashNotInGraph(hash, graph) {
|
|
|
74685
74993
|
const reachableList = reachableHashes.length > 0 ? reachableHashes.join(", ") : "(none)";
|
|
74686
74994
|
return new MigrationToolsError("MIGRATION.HASH_NOT_IN_GRAPH", `Hash "${hash}" is not a node in the migration graph`, {
|
|
74687
74995
|
why: `The migration graph contains nodes ${reachableList}; "${hash}" isn't one of them.`,
|
|
74688
|
-
fix: `Pass a hash that's the from-or-to of an on-disk migration bundle, use --from with a graph-node hash, or run "prisma
|
|
74689
|
-
|
|
74996
|
+
fix: `Pass a hash that's the from-or-to of an on-disk migration bundle, use --from with a graph-node hash, or run "prisma migration plan" to introduce it.`,
|
|
74997
|
+
nextActions: [{
|
|
74998
|
+
kind: "user-choice",
|
|
74999
|
+
label: "Pass a hash that is the from-or-to of an on-disk migration bundle, or use --from with a graph-node hash",
|
|
75000
|
+
reason: `Graph nodes: ${reachableList}.`
|
|
75001
|
+
}, {
|
|
75002
|
+
kind: "run-command",
|
|
75003
|
+
label: `Introduce "${hash}" by planning a migration for it`,
|
|
75004
|
+
command: "{bin} migration plan"
|
|
75005
|
+
}],
|
|
75006
|
+
meta: {
|
|
74690
75007
|
hash,
|
|
74691
75008
|
reachableHashes
|
|
74692
75009
|
}
|
|
@@ -74695,8 +75012,23 @@ function errorHashNotInGraph(hash, graph) {
|
|
|
74695
75012
|
function errorContractSnapshotMissing(storageHash, expectedPath) {
|
|
74696
75013
|
return new MigrationToolsError("MIGRATION.CONTRACT_SNAPSHOT_MISSING", "Contract snapshot is missing", {
|
|
74697
75014
|
why: `Expected a contract snapshot for ${storageHash} at "${expectedPath}" but the file does not exist.`,
|
|
74698
|
-
fix: "Re-emit the contract snapshot by re-running the command that authored the migration referencing this hash (`prisma
|
|
74699
|
-
|
|
75015
|
+
fix: "Re-emit the contract snapshot by re-running the command that authored the migration referencing this hash (`prisma migration plan` for app-space migrations; the extension's contract-space build for extension spaces), or restore migrations/snapshots/ from version control.",
|
|
75016
|
+
nextActions: [
|
|
75017
|
+
{
|
|
75018
|
+
kind: "run-command",
|
|
75019
|
+
label: "Re-emit the snapshot for an app-space migration",
|
|
75020
|
+
command: "{bin} migration plan"
|
|
75021
|
+
},
|
|
75022
|
+
{
|
|
75023
|
+
kind: "user-choice",
|
|
75024
|
+
label: "For an extension space, re-run that extension's contract-space build instead"
|
|
75025
|
+
},
|
|
75026
|
+
{
|
|
75027
|
+
kind: "user-choice",
|
|
75028
|
+
label: "Restore migrations/snapshots/ from version control"
|
|
75029
|
+
}
|
|
75030
|
+
],
|
|
75031
|
+
meta: {
|
|
74700
75032
|
storageHash,
|
|
74701
75033
|
expectedPath
|
|
74702
75034
|
}
|
|
@@ -74706,7 +75038,7 @@ function errorContractSnapshotHashMismatch(storageHash, actualHash, dir) {
|
|
|
74706
75038
|
return new MigrationToolsError("MIGRATION.CONTRACT_SNAPSHOT_HASH_MISMATCH", "Contract snapshot hash mismatch", {
|
|
74707
75039
|
why: `The contract JSON's inner storage.storageHash ("${actualHash}") does not match the requested storage hash ("${storageHash}") for snapshot directory "${dir}".`,
|
|
74708
75040
|
fix: "Pass a contractJson whose storage.storageHash equals the storageHash argument passed to writeContractSnapshot — the two must agree by construction.",
|
|
74709
|
-
|
|
75041
|
+
meta: {
|
|
74710
75042
|
storageHash,
|
|
74711
75043
|
actualHash,
|
|
74712
75044
|
dir
|
|
@@ -74717,14 +75049,13 @@ function errorMigrationContractViewMissing(className, accessor, jsonField) {
|
|
|
74717
75049
|
return new MigrationToolsError("MIGRATION.CONTRACT_VIEW_MISSING", `${className}.${accessor} requires ${jsonField}`, {
|
|
74718
75050
|
why: `${className}.${accessor} was read, but this instance has no ${jsonField} to build the view from.`,
|
|
74719
75051
|
fix: `Set ${jsonField} to the migration's committed contract JSON, or avoid reading ${accessor} on a migration that overrides describe() and carries no contract.`,
|
|
74720
|
-
|
|
75052
|
+
meta: {
|
|
74721
75053
|
className,
|
|
74722
75054
|
accessor,
|
|
74723
75055
|
jsonField
|
|
74724
75056
|
}
|
|
74725
75057
|
});
|
|
74726
75058
|
}
|
|
74727
|
-
init_dist();
|
|
74728
75059
|
const CONTRACT_JSON_FILE = "contract.json";
|
|
74729
75060
|
const CONTRACT_DTS_FILE = "contract.d.ts";
|
|
74730
75061
|
function hasErrnoCode$3(error, code) {
|
|
@@ -74942,7 +75273,6 @@ const MigrationOpsSchema = type({
|
|
|
74942
75273
|
operationClass: "'additive' | 'widening' | 'destructive' | 'data'",
|
|
74943
75274
|
"invariantId?": "string"
|
|
74944
75275
|
}).array();
|
|
74945
|
-
init_dist();
|
|
74946
75276
|
const MANIFEST_FILE = "migration.json";
|
|
74947
75277
|
const OPS_FILE = "ops.json";
|
|
74948
75278
|
function hasErrnoCode$2(error, code) {
|
|
@@ -75178,14 +75508,14 @@ async function readMigrationsDir(migrationsRoot, options) {
|
|
|
75178
75508
|
const dirName = entry;
|
|
75179
75509
|
if (MigrationToolsError.is(error)) {
|
|
75180
75510
|
if (error.code === "MIGRATION.HASH_MISMATCH") {
|
|
75181
|
-
const
|
|
75511
|
+
const meta = error.meta;
|
|
75182
75512
|
const rawPkg = await readMigrationPackageRaw(entryPath);
|
|
75183
75513
|
if (rawPkg !== null) packages.push(rawPkg);
|
|
75184
75514
|
problems.push({
|
|
75185
75515
|
kind: "hashMismatch",
|
|
75186
75516
|
dirName,
|
|
75187
|
-
stored: typeof
|
|
75188
|
-
computed: typeof
|
|
75517
|
+
stored: typeof meta?.["storedHash"] === "string" ? meta["storedHash"] : "",
|
|
75518
|
+
computed: typeof meta?.["computedHash"] === "string" ? meta["computedHash"] : ""
|
|
75189
75519
|
});
|
|
75190
75520
|
continue;
|
|
75191
75521
|
}
|
|
@@ -75213,7 +75543,6 @@ async function readMigrationsDir(migrationsRoot, options) {
|
|
|
75213
75543
|
problems
|
|
75214
75544
|
};
|
|
75215
75545
|
}
|
|
75216
|
-
init_dist();
|
|
75217
75546
|
/**
|
|
75218
75547
|
* Pattern a contract-space identifier must match. The constraint is
|
|
75219
75548
|
* filesystem-friendly: lowercase letters / digits / hyphen / underscore,
|
|
@@ -75709,7 +76038,6 @@ function invariantViableAlternativesAtStep(required, coverageBeforeTakingEdge, o
|
|
|
75709
76038
|
if (required.size === 0) return [...outgoing];
|
|
75710
76039
|
return outgoing.filter((e) => [...required].every((id) => coverageBeforeTakingEdge.has(id) || e.invariants.includes(id)));
|
|
75711
76040
|
}
|
|
75712
|
-
init_dist();
|
|
75713
76041
|
/**
|
|
75714
76042
|
* Assert that an extension descriptor is self-consistent: the
|
|
75715
76043
|
* `headRef.hash` it publishes must match the canonical hash recomputed
|
|
@@ -75726,7 +76054,7 @@ init_dist();
|
|
|
75726
76054
|
*
|
|
75727
76055
|
* Synchronous, pure, no I/O. Throws
|
|
75728
76056
|
* `MIGRATION.DESCRIPTOR_HEAD_HASH_MISMATCH` on failure with both the
|
|
75729
|
-
* recomputed and published hashes in `
|
|
76057
|
+
* recomputed and published hashes in `meta` so callers can surface a
|
|
75730
76058
|
* clear remediation hint without re-deriving them.
|
|
75731
76059
|
*/
|
|
75732
76060
|
function assertDescriptorSelfConsistency(inputs) {
|
|
@@ -76411,70 +76739,11 @@ function resolveColumnTypeMetadata$1(column, storageTypes) {
|
|
|
76411
76739
|
};
|
|
76412
76740
|
throw new InternalError(`Storage type "${column.typeRef}" has an unknown polymorphic kind; expected a codec-typed StorageTypeInstance.`);
|
|
76413
76741
|
}
|
|
76414
|
-
|
|
76415
|
-
* Resolves a `ValueSetRef` to its permitted values from the contract storage.
|
|
76416
|
-
*
|
|
76417
|
-
* Throws when the referenced namespace or value-set is absent — this indicates
|
|
76418
|
-
* the contract was built incorrectly (the check and the value-set must be
|
|
76419
|
-
* co-emitted by the lowering step). Used by `convertCheck` (schema-IR
|
|
76420
|
-
* projection), `verifyCheckConstraints` (verification), and
|
|
76421
|
-
* `checkConstraintPlanCallStrategy` (migration planning) so all three agree on
|
|
76422
|
-
* the resolved values and the error behavior on a missing reference.
|
|
76423
|
-
*/
|
|
76424
|
-
function allStrings(values) {
|
|
76425
|
-
return values.every((value) => typeof value === "string");
|
|
76426
|
-
}
|
|
76427
|
-
function resolveValueSetValues(ref, storage, contextLabel) {
|
|
76428
|
-
const ns = storage.namespaces[ref.namespaceId];
|
|
76429
|
-
if (!ns) throw sqlFamilyError("CONTRACT.NAMESPACE_UNKNOWN", `resolveValueSetValues: namespace "${ref.namespaceId}" not found in storage (${contextLabel})`, {
|
|
76430
|
-
why: "A value-set reference names a namespace the contract storage does not declare.",
|
|
76431
|
-
fix: "Regenerate the contract from its authoring source; do not hand-edit contract JSON.",
|
|
76432
|
-
meta: {
|
|
76433
|
-
namespaceId: ref.namespaceId,
|
|
76434
|
-
context: contextLabel
|
|
76435
|
-
}
|
|
76436
|
-
});
|
|
76437
|
-
const valueSet = ns.entries.valueSet?.[ref.entityName];
|
|
76438
|
-
if (!valueSet) throw sqlFamilyError("CONTRACT.ENUM_UNKNOWN", `resolveValueSetValues: value-set "${ref.entityName}" not found in namespace "${ref.namespaceId}" (${contextLabel})`, {
|
|
76439
|
-
why: "A value-set reference names an entry its namespace does not declare.",
|
|
76440
|
-
fix: "Regenerate the contract from its authoring source; do not hand-edit contract JSON.",
|
|
76441
|
-
meta: {
|
|
76442
|
-
valueSet: ref.entityName,
|
|
76443
|
-
namespaceId: ref.namespaceId,
|
|
76444
|
-
context: contextLabel
|
|
76445
|
-
}
|
|
76446
|
-
});
|
|
76447
|
-
const values = valueSet.values;
|
|
76448
|
-
if (!allStrings(values)) throw sqlFamilyError("CONTRACT.ENUM_INVALID", `resolveValueSetValues: value-set "${ref.entityName}" in namespace "${ref.namespaceId}" has a non-string value; numeric-enum CHECK constraints are not yet supported (${contextLabel})`, {
|
|
76449
|
-
why: "Only string value-sets can be rendered as CHECK constraints; this value-set carries a non-string value.",
|
|
76450
|
-
fix: "Use string enum values, or drop the CHECK-constrained enum until numeric enums are supported.",
|
|
76451
|
-
meta: {
|
|
76452
|
-
valueSet: ref.entityName,
|
|
76453
|
-
namespaceId: ref.namespaceId,
|
|
76454
|
-
context: contextLabel
|
|
76455
|
-
}
|
|
76456
|
-
});
|
|
76457
|
-
return values;
|
|
76458
|
-
}
|
|
76459
|
-
/**
|
|
76460
|
-
* Projects a `CheckConstraint` IR into an `SqlCheckConstraintIRInput` by
|
|
76461
|
-
* resolving the permitted values from the storage value-set it references.
|
|
76462
|
-
*
|
|
76463
|
-
* The `CheckConstraint.valueSet` ref points to
|
|
76464
|
-
* `storage.namespaces[namespaceId].entries.valueSet[name]`. The resolved
|
|
76465
|
-
* values are lifted directly from `StorageValueSet.values` so verification
|
|
76466
|
-
* compares value sets, not SQL predicate strings.
|
|
76467
|
-
*
|
|
76468
|
-
* Throws if the referenced namespace or value-set is absent — this
|
|
76469
|
-
* indicates the contract was built incorrectly (the check and the
|
|
76470
|
-
* value-set must be co-emitted by the lowering step).
|
|
76471
|
-
*/
|
|
76472
|
-
function convertCheck(check, storage) {
|
|
76473
|
-
const permittedValues = resolveValueSetValues(check.valueSet, storage, `check "${check.name}"`);
|
|
76742
|
+
function convertCheck(check, tableName, tableColumns) {
|
|
76474
76743
|
return {
|
|
76475
|
-
|
|
76476
|
-
|
|
76477
|
-
|
|
76744
|
+
naming: namingOf(check.name, check.prefix),
|
|
76745
|
+
expression: check.expression,
|
|
76746
|
+
dependsOn: flatColumnDependsOn(tableName, tableColumns)
|
|
76478
76747
|
};
|
|
76479
76748
|
}
|
|
76480
76749
|
function convertUnique(unique, tableName) {
|
|
@@ -76572,7 +76841,7 @@ function convertForeignKey(fk, storage) {
|
|
|
76572
76841
|
function convertTable(name, table, storageTypes, expandNativeType, renderDefault, resolveDefault, storage) {
|
|
76573
76842
|
const columns = {};
|
|
76574
76843
|
for (const [colName, colDef] of Object.entries(table.columns)) columns[colName] = convertColumn(colName, colDef, storageTypes, expandNativeType, renderDefault, resolveDefault);
|
|
76575
|
-
const checks = table.checks && table.checks.length > 0 ? table.checks.map((c) => convertCheck(c,
|
|
76844
|
+
const checks = table.checks && table.checks.length > 0 ? table.checks.map((c) => convertCheck(c, name, Object.keys(table.columns))) : void 0;
|
|
76576
76845
|
return new SqlTableIR({
|
|
76577
76846
|
name,
|
|
76578
76847
|
columns,
|
|
@@ -76947,6 +77216,19 @@ function runnerFailure(code, summary, options) {
|
|
|
76947
77216
|
Object.freeze({ allowedOperationClasses: Object.freeze(["additive"]) });
|
|
76948
77217
|
var control_default = new SqlFamilyDescriptor();
|
|
76949
77218
|
/**
|
|
77219
|
+
* Name of the synthesised namespace bucket the framework parser uses for
|
|
77220
|
+
* top-level declarations that appear outside any `namespace { … }` block.
|
|
77221
|
+
* The double-underscore decoration signals that the identifier is parser-
|
|
77222
|
+
* synthesised and never appears in user-authored PSL source — writing
|
|
77223
|
+
* `namespace __unspecified__ { … }` is a parse error.
|
|
77224
|
+
*
|
|
77225
|
+
* Distinct from the IR sentinel `__unbound__`: the PSL bucket describes
|
|
77226
|
+
* syntactic absence at the parser layer; the IR sentinel describes a late-
|
|
77227
|
+
* bound storage slot at the IR layer. Per-target interpreters decide how
|
|
77228
|
+
* (or whether) to map the PSL bucket to the IR sentinel.
|
|
77229
|
+
*/
|
|
77230
|
+
const UNSPECIFIED_PSL_NAMESPACE_ID = "__unspecified__";
|
|
77231
|
+
/**
|
|
76950
77232
|
* Stores `entries`; exposes `models`/`enums`/`compositeTypes` as getters over
|
|
76951
77233
|
* it. The getters are prototype members (non-enumerable), so spreading or
|
|
76952
77234
|
* `JSON.stringify`-ing a namespace copies only `entries`, never a duplicate view.
|
|
@@ -78193,6 +78475,10 @@ var PostgresControlDriver = class {
|
|
|
78193
78475
|
throw normalizePgError(error);
|
|
78194
78476
|
}
|
|
78195
78477
|
}
|
|
78478
|
+
async databaseName() {
|
|
78479
|
+
const name = (await this.query("select current_database() as name")).rows[0]?.name;
|
|
78480
|
+
return typeof name === "string" && name.length > 0 ? name : void 0;
|
|
78481
|
+
}
|
|
78196
78482
|
async close() {
|
|
78197
78483
|
await this.client.end().catch(() => {});
|
|
78198
78484
|
}
|
|
@@ -78216,18 +78502,53 @@ const postgresDriverDescriptor = {
|
|
|
78216
78502
|
} catch {}
|
|
78217
78503
|
const codeFromSqlState = SqlQueryError.is(normalized) ? normalized.sqlState : void 0;
|
|
78218
78504
|
const causeCode = "cause" in normalized && normalized.cause ? normalized.cause.code : void 0;
|
|
78219
|
-
const
|
|
78220
|
-
throw errorRuntime("Database connection failed", {
|
|
78505
|
+
const sqlState = codeFromSqlState ?? causeCode;
|
|
78506
|
+
throw errorRuntime("DRIVER.CONNECTION_FAILED", "Database connection failed", {
|
|
78221
78507
|
why: normalized.message,
|
|
78222
78508
|
fix: "Verify the database URL, ensure the database is reachable, and confirm credentials/permissions",
|
|
78223
78509
|
meta: {
|
|
78224
|
-
...ifDefined("
|
|
78510
|
+
...ifDefined("sqlState", sqlState),
|
|
78225
78511
|
...redacted
|
|
78226
|
-
}
|
|
78512
|
+
},
|
|
78513
|
+
cause: error
|
|
78227
78514
|
});
|
|
78228
78515
|
}
|
|
78229
78516
|
}
|
|
78230
78517
|
};
|
|
78518
|
+
/**
|
|
78519
|
+
* Renders the checks a Postgres column needs, as opaque predicate text.
|
|
78520
|
+
*
|
|
78521
|
+
* A text-backed domain enum has no type-level enforcement, so membership is a
|
|
78522
|
+
* predicate: `IN` for a scalar, and `<@` containment for an array — an array
|
|
78523
|
+
* column cannot use `IN` at all (`operator does not exist: text[] = text`),
|
|
78524
|
+
* and containment additionally rejects NULL elements. Every list column also
|
|
78525
|
+
* gets an element-non-null check, which no Postgres column type can express.
|
|
78526
|
+
*
|
|
78527
|
+
* The array side casts the COLUMN to `text[]` rather than assuming its element
|
|
78528
|
+
* type already is: `<@` needs both operands in one type, so a `varchar[]` or
|
|
78529
|
+
* `char[]` column meeting a bare `text[]` literal raises the same
|
|
78530
|
+
* `operator does not exist` this project exists to eliminate. The scalar `IN`
|
|
78531
|
+
* form needs no cast — `varchar = text` resolves on its own.
|
|
78532
|
+
*/
|
|
78533
|
+
function postgresRenderCheckExpressions(input) {
|
|
78534
|
+
const candidates = [];
|
|
78535
|
+
const column = quoteIdentifier(input.columnName);
|
|
78536
|
+
if (input.memberValues !== void 0) {
|
|
78537
|
+
invariant(input.memberValues.length > 0, `check for "${input.tableName}"."${input.columnName}": empty member set; both authoring surfaces reject a member-less enum before rendering`);
|
|
78538
|
+
const members = input.memberValues.map((value) => `'${escapeLiteral(value)}'`).join(", ");
|
|
78539
|
+
candidates.push({
|
|
78540
|
+
kind: "membership",
|
|
78541
|
+
columnName: input.columnName,
|
|
78542
|
+
expression: input.many ? `${column}::text[] <@ ARRAY[${members}]::text[]` : `${column} IN (${members})`
|
|
78543
|
+
});
|
|
78544
|
+
}
|
|
78545
|
+
if (input.many) candidates.push({
|
|
78546
|
+
kind: "elementNotNull",
|
|
78547
|
+
columnName: input.columnName,
|
|
78548
|
+
expression: `array_position(${column}, NULL) IS NULL`
|
|
78549
|
+
});
|
|
78550
|
+
return candidates;
|
|
78551
|
+
}
|
|
78231
78552
|
/** Postgres's default schema; `postgresTargetDescriptorMeta.defaultNamespaceId` is this value. */
|
|
78232
78553
|
const DEFAULT_NAMESPACE_ID = "public";
|
|
78233
78554
|
/**
|
|
@@ -78298,14 +78619,30 @@ const PSL_ROLE_BLOCK_OUTSIDE_UNBOUND_NAMESPACE = "PSL_ROLE_BLOCK_OUTSIDE_UNBOUND
|
|
|
78298
78619
|
* descriptor's `columnFromEntity` hook (see `codecs.ts`) converts that
|
|
78299
78620
|
* entity into the column's `typeParams` and native type.
|
|
78300
78621
|
*/
|
|
78301
|
-
const postgresAuthoringTypes = {
|
|
78302
|
-
|
|
78303
|
-
|
|
78304
|
-
|
|
78305
|
-
|
|
78622
|
+
const postgresAuthoringTypes = {
|
|
78623
|
+
BigIntNumber: {
|
|
78624
|
+
kind: "typeConstructor",
|
|
78625
|
+
output: {
|
|
78626
|
+
codecId: "pg/int8number@1",
|
|
78627
|
+
nativeType: "int8"
|
|
78628
|
+
}
|
|
78306
78629
|
},
|
|
78307
|
-
|
|
78308
|
-
|
|
78630
|
+
UnboundedInt: {
|
|
78631
|
+
kind: "typeConstructor",
|
|
78632
|
+
output: {
|
|
78633
|
+
codecId: "pg/unboundedint@1",
|
|
78634
|
+
nativeType: "numeric"
|
|
78635
|
+
}
|
|
78636
|
+
},
|
|
78637
|
+
pg: { enum: {
|
|
78638
|
+
kind: "typeConstructor",
|
|
78639
|
+
entityRefArg: {
|
|
78640
|
+
index: 0,
|
|
78641
|
+
entityKind: "native_enum"
|
|
78642
|
+
},
|
|
78643
|
+
output: { codecId: PG_ENUM_CODEC_ID }
|
|
78644
|
+
} }
|
|
78645
|
+
};
|
|
78309
78646
|
/**
|
|
78310
78647
|
* Maps a `policy_<op>` keyword to the RLS operation it authors. The keyword
|
|
78311
78648
|
* IS the operation (per the project's rejection of a `policy { operation = … }`
|
|
@@ -79042,6 +79379,7 @@ const postgresTargetDescriptorMeta = {
|
|
|
79042
79379
|
modelAttributes: postgresAuthoringModelAttributes,
|
|
79043
79380
|
createNamespace: postgresCreateNamespace,
|
|
79044
79381
|
qualifyColumnType: postgresQualifyColumnType,
|
|
79382
|
+
renderCheckExpressions: postgresRenderCheckExpressions,
|
|
79045
79383
|
lowerEntityHandles: postgresLowerEntityHandles
|
|
79046
79384
|
}
|
|
79047
79385
|
};
|
|
@@ -79651,9 +79989,8 @@ async function addForeignKey(schemaName, tableName, fk, lowerer) {
|
|
|
79651
79989
|
postcheck: [step(`verify FK "${fk.name}" exists`, present.sql, present.params)]
|
|
79652
79990
|
};
|
|
79653
79991
|
}
|
|
79654
|
-
async function addCheckConstraint(schemaName, tableName, constraintName,
|
|
79992
|
+
async function addCheckConstraint(schemaName, tableName, constraintName, expression, lowerer) {
|
|
79655
79993
|
const qualified = qualifyTableName(schemaName, tableName);
|
|
79656
|
-
const valueList = values.map((v) => `'${escapeLiteral(v)}'`).join(", ");
|
|
79657
79994
|
const { absent, present } = await constraintCheckSteps(lowerer, {
|
|
79658
79995
|
constraintName,
|
|
79659
79996
|
schema: schemaName,
|
|
@@ -79661,14 +79998,36 @@ async function addCheckConstraint(schemaName, tableName, constraintName, column,
|
|
|
79661
79998
|
});
|
|
79662
79999
|
return {
|
|
79663
80000
|
id: `checkConstraint.${tableName}.${constraintName}`,
|
|
79664
|
-
label: `Add check constraint "${constraintName}" on "${tableName}"
|
|
80001
|
+
label: `Add check constraint "${constraintName}" on "${tableName}"`,
|
|
79665
80002
|
operationClass: "additive",
|
|
79666
80003
|
target: targetDetails("checkConstraint", constraintName, schemaName, tableName),
|
|
79667
80004
|
precheck: [step(`ensure constraint "${constraintName}" does not exist`, absent.sql, absent.params)],
|
|
79668
|
-
execute: [step(`add check constraint "${constraintName}"`, `ALTER TABLE ${qualified} ADD CONSTRAINT ${quoteIdentifier(constraintName)} CHECK (${
|
|
80005
|
+
execute: [step(`add check constraint "${constraintName}"`, `ALTER TABLE ${qualified} ADD CONSTRAINT ${quoteIdentifier(constraintName)} CHECK (${expression})`)],
|
|
79669
80006
|
postcheck: [step(`verify constraint "${constraintName}" exists`, present.sql, present.params)]
|
|
79670
80007
|
};
|
|
79671
80008
|
}
|
|
80009
|
+
async function renameCheckConstraint(schemaName, tableName, fromName, toName, lowerer) {
|
|
80010
|
+
const qualified = qualifyTableName(schemaName, tableName);
|
|
80011
|
+
const from = await constraintCheckSteps(lowerer, {
|
|
80012
|
+
constraintName: fromName,
|
|
80013
|
+
schema: schemaName,
|
|
80014
|
+
table: tableName
|
|
80015
|
+
});
|
|
80016
|
+
const to = await constraintCheckSteps(lowerer, {
|
|
80017
|
+
constraintName: toName,
|
|
80018
|
+
schema: schemaName,
|
|
80019
|
+
table: tableName
|
|
80020
|
+
});
|
|
80021
|
+
return {
|
|
80022
|
+
id: `checkConstraint.${schemaName}.${tableName}.${fromName}.rename`,
|
|
80023
|
+
label: `Rename check constraint "${fromName}" to "${toName}" on "${tableName}"`,
|
|
80024
|
+
operationClass: "widening",
|
|
80025
|
+
target: targetDetails("checkConstraint", toName, schemaName, tableName),
|
|
80026
|
+
precheck: [step(`ensure constraint "${fromName}" exists`, from.present.sql, from.present.params), step(`ensure constraint "${toName}" does not exist`, to.absent.sql, to.absent.params)],
|
|
80027
|
+
execute: [step(`rename check constraint "${fromName}" to "${toName}"`, `ALTER TABLE ${qualified} RENAME CONSTRAINT ${quoteIdentifier(fromName)} TO ${quoteIdentifier(toName)}`)],
|
|
80028
|
+
postcheck: [step(`verify constraint "${toName}" exists`, to.present.sql, to.present.params)]
|
|
80029
|
+
};
|
|
80030
|
+
}
|
|
79672
80031
|
async function dropCheckConstraint(schemaName, tableName, constraintName, lowerer) {
|
|
79673
80032
|
const qualified = qualifyTableName(schemaName, tableName);
|
|
79674
80033
|
const { absent, present } = await constraintCheckSteps(lowerer, {
|
|
@@ -80750,31 +81109,63 @@ var DropConstraintCall = class extends PostgresOpFactoryCallNode {
|
|
|
80750
81109
|
return [];
|
|
80751
81110
|
}
|
|
80752
81111
|
};
|
|
81112
|
+
var RenameCheckConstraintCall = class extends PostgresOpFactoryCallNode {
|
|
81113
|
+
factoryName = "renameCheckConstraint";
|
|
81114
|
+
operationClass = "widening";
|
|
81115
|
+
schemaName;
|
|
81116
|
+
tableName;
|
|
81117
|
+
oldConstraintName;
|
|
81118
|
+
newConstraintName;
|
|
81119
|
+
label;
|
|
81120
|
+
constructor(schemaName, tableName, oldConstraintName, newConstraintName) {
|
|
81121
|
+
super();
|
|
81122
|
+
this.schemaName = schemaName;
|
|
81123
|
+
this.tableName = tableName;
|
|
81124
|
+
this.oldConstraintName = oldConstraintName;
|
|
81125
|
+
this.newConstraintName = newConstraintName;
|
|
81126
|
+
this.label = `Rename check constraint "${oldConstraintName}" to "${newConstraintName}" on "${tableName}"`;
|
|
81127
|
+
this.freeze();
|
|
81128
|
+
}
|
|
81129
|
+
async toOp(lowerer) {
|
|
81130
|
+
if (lowerer === void 0) throw postgresError("MIGRATION.POSTGRES_CONTROL_STACK_MISSING", `RenameCheckConstraintCall.toOp: a lowerer is required on the Postgres planner path (constraint "${this.oldConstraintName}" on table "${this.tableName}"). Pass the control adapter to createPostgresMigrationPlanner.`, { meta: { factory: "RenameCheckConstraintCall" } });
|
|
81131
|
+
return renameCheckConstraint(this.schemaName, this.tableName, this.oldConstraintName, this.newConstraintName, lowerer);
|
|
81132
|
+
}
|
|
81133
|
+
renderTypeScript() {
|
|
81134
|
+
const opts = [];
|
|
81135
|
+
if (this.schemaName !== "__unbound__") opts.push(`schema: ${jsonToTsSource(this.schemaName)}`);
|
|
81136
|
+
opts.push(`table: ${jsonToTsSource(this.tableName)}`);
|
|
81137
|
+
opts.push(`from: ${jsonToTsSource(this.oldConstraintName)}`);
|
|
81138
|
+
opts.push(`to: ${jsonToTsSource(this.newConstraintName)}`);
|
|
81139
|
+
return `this.renameCheckConstraint({ ${opts.join(", ")} })`;
|
|
81140
|
+
}
|
|
81141
|
+
importRequirements() {
|
|
81142
|
+
return [];
|
|
81143
|
+
}
|
|
81144
|
+
};
|
|
80753
81145
|
var AddCheckConstraintCall = class extends PostgresOpFactoryCallNode {
|
|
80754
81146
|
factoryName = "addCheckConstraint";
|
|
80755
81147
|
operationClass = "additive";
|
|
80756
81148
|
schemaName;
|
|
80757
81149
|
tableName;
|
|
80758
81150
|
constraintName;
|
|
80759
|
-
|
|
80760
|
-
|
|
81151
|
+
/** Opaque SQL: the predicate body, rendered verbatim inside `CHECK (…)`. */
|
|
81152
|
+
expression;
|
|
80761
81153
|
label;
|
|
80762
|
-
constructor(schemaName, tableName, constraintName,
|
|
81154
|
+
constructor(schemaName, tableName, constraintName, expression) {
|
|
80763
81155
|
super();
|
|
80764
81156
|
this.schemaName = schemaName;
|
|
80765
81157
|
this.tableName = tableName;
|
|
80766
81158
|
this.constraintName = constraintName;
|
|
80767
|
-
this.
|
|
80768
|
-
this.
|
|
80769
|
-
this.label = `Add check constraint "${constraintName}" on "${tableName}"."${column}"`;
|
|
81159
|
+
this.expression = expression;
|
|
81160
|
+
this.label = `Add check constraint "${constraintName}" on "${tableName}"`;
|
|
80770
81161
|
this.freeze();
|
|
80771
81162
|
}
|
|
80772
81163
|
async toOp(lowerer) {
|
|
80773
81164
|
if (lowerer === void 0) throw postgresError("MIGRATION.POSTGRES_CONTROL_STACK_MISSING", `AddCheckConstraintCall.toOp: a lowerer is required on the Postgres planner path (constraint "${this.constraintName}" on table "${this.tableName}"). Pass the control adapter to createPostgresMigrationPlanner.`, { meta: { factory: "AddCheckConstraintCall" } });
|
|
80774
|
-
return addCheckConstraint(this.schemaName, this.tableName, this.constraintName, this.
|
|
81165
|
+
return addCheckConstraint(this.schemaName, this.tableName, this.constraintName, this.expression, lowerer);
|
|
80775
81166
|
}
|
|
80776
81167
|
renderTypeScript() {
|
|
80777
|
-
return `this.addCheckConstraint({ ${constraintCallOptions(this.schemaName, this.tableName, this.constraintName)},
|
|
81168
|
+
return `this.addCheckConstraint({ ${constraintCallOptions(this.schemaName, this.tableName, this.constraintName)}, expression: ${jsonToTsSource(this.expression)} })`;
|
|
80778
81169
|
}
|
|
80779
81170
|
importRequirements() {
|
|
80780
81171
|
return [];
|
|
@@ -81542,21 +81933,6 @@ function tableAt(storage, namespaceId, tableName) {
|
|
|
81542
81933
|
return ns.entries.table?.[tableName];
|
|
81543
81934
|
}
|
|
81544
81935
|
/**
|
|
81545
|
-
* Resolve the DDL schema name for a namespace coordinate. Postgres-aware
|
|
81546
|
-
* namespaces dispatch to their polymorphic `ddlSchemaName` override —
|
|
81547
|
-
* named schemas return their own id; the unbound singleton returns
|
|
81548
|
-
* `UNBOUND_NAMESPACE_ID`. Legacy single-namespace contracts whose
|
|
81549
|
-
* `__unbound__` slot is the framework-default `SqlUnboundNamespace`
|
|
81550
|
-
* (rather than the Postgres-aware `PostgresUnboundSchema`) flow the
|
|
81551
|
-
* coordinate through unchanged so downstream `qualifyTableName`
|
|
81552
|
-
* resolves polymorphically.
|
|
81553
|
-
*/
|
|
81554
|
-
function resolveDdlSchemaForNamespace(ctx, namespaceId) {
|
|
81555
|
-
const namespace = ctx.toContract.storage.namespaces[namespaceId];
|
|
81556
|
-
if (isPostgresSchema(namespace)) return namespace.ddlSchemaName(ctx.toContract.storage);
|
|
81557
|
-
return namespaceId;
|
|
81558
|
-
}
|
|
81559
|
-
/**
|
|
81560
81936
|
* Recovers the contract namespace id for a DDL schema name embedded in a
|
|
81561
81937
|
* diff-issue path (`path[1]`). The strategies need the CONTRACT column/table
|
|
81562
81938
|
* (for codec-hook reads and eligibility probes the retained subsystems still
|
|
@@ -81709,90 +82085,6 @@ const nullableTighteningCallStrategy = (issues, ctx) => {
|
|
|
81709
82085
|
};
|
|
81710
82086
|
};
|
|
81711
82087
|
/**
|
|
81712
|
-
* Collects every check constraint from a table in the contract storage.
|
|
81713
|
-
* Returns an empty array when the table has no checks or the table is absent.
|
|
81714
|
-
*/
|
|
81715
|
-
function collectContractChecks(storage, namespaceId, tableName) {
|
|
81716
|
-
const ns = storage.namespaces[namespaceId];
|
|
81717
|
-
const tableRaw = ns !== void 0 ? ns.entries.table?.[tableName] : void 0;
|
|
81718
|
-
if (!(tableRaw instanceof StorageTable)) return [];
|
|
81719
|
-
const checks = tableRaw.checks;
|
|
81720
|
-
if (!checks || checks.length === 0) return [];
|
|
81721
|
-
return checks.map((c) => ({
|
|
81722
|
-
name: c.name,
|
|
81723
|
-
column: c.column,
|
|
81724
|
-
permittedValues: resolveValueSetValues(c.valueSet, storage, `check "${c.name}" on "${tableName}"`)
|
|
81725
|
-
}));
|
|
81726
|
-
}
|
|
81727
|
-
/**
|
|
81728
|
-
* Compares two value arrays as unordered sets.
|
|
81729
|
-
*/
|
|
81730
|
-
function checkValueSetsEqual(a, b) {
|
|
81731
|
-
if (a.length !== b.length) return false;
|
|
81732
|
-
const bSet = new Set(b);
|
|
81733
|
-
return a.every((v) => bSet.has(v));
|
|
81734
|
-
}
|
|
81735
|
-
/**
|
|
81736
|
-
* Plans check-constraint migrations for `enumType`-authored columns.
|
|
81737
|
-
*
|
|
81738
|
-
* Walks every namespace's tables in the target contract (the check nodes'
|
|
81739
|
-
* resolved `permittedValues` are ultimately sourced from the same
|
|
81740
|
-
* contract-declared value sets, so walking the contract directly is the
|
|
81741
|
-
* simplest faithful port — the strategy's decisions never depend on which
|
|
81742
|
-
* ISSUES happen to be in the input list, only on the contract + live schema
|
|
81743
|
-
* shapes). For each table that carries `checks`, diffs the contract-expected
|
|
81744
|
-
* checks against the live schema's checks:
|
|
81745
|
-
*
|
|
81746
|
-
* - Check in contract, absent from live DB → `AddCheckConstraintCall`.
|
|
81747
|
-
* - Check in live DB, absent from contract → `DropCheckConstraintCall`.
|
|
81748
|
-
* - Check on both sides but value sets differ → `DropCheckConstraintCall`
|
|
81749
|
-
* then `AddCheckConstraintCall` (drop + recreate; a check predicate cannot
|
|
81750
|
-
* be altered in place).
|
|
81751
|
-
*
|
|
81752
|
-
* Consumes every `sql-check-constraint` issue on a table this walk handles
|
|
81753
|
-
* (not-found/not-expected/not-equal), leaving check issues on tables with
|
|
81754
|
-
* NO contract checks to `mapNodeIssueToCall`'s `not-expected` fallback.
|
|
81755
|
-
*/
|
|
81756
|
-
const checkConstraintPlanCallStrategy = (issues, ctx) => {
|
|
81757
|
-
const calls = [];
|
|
81758
|
-
const handledIssueKeys = /* @__PURE__ */ new Set();
|
|
81759
|
-
for (const [namespaceId, ns] of Object.entries(ctx.toContract.storage.namespaces)) for (const tableName of Object.keys(ns.entries.table ?? {})) {
|
|
81760
|
-
const contractChecks = collectContractChecks(ctx.toContract.storage, namespaceId, tableName);
|
|
81761
|
-
if (contractChecks.length === 0) continue;
|
|
81762
|
-
const liveChecks = ctx.schema.tables[tableName]?.checks ?? [];
|
|
81763
|
-
const ddlSchema = resolveDdlSchemaForNamespace(ctx, namespaceId);
|
|
81764
|
-
for (const contractCheck of contractChecks) {
|
|
81765
|
-
const liveCheck = liveChecks.find((c) => c.name === contractCheck.name);
|
|
81766
|
-
const issueKey = `${tableName} ${contractCheck.name}`;
|
|
81767
|
-
if (!liveCheck) {
|
|
81768
|
-
calls.push(new AddCheckConstraintCall(ddlSchema, tableName, contractCheck.name, contractCheck.column, contractCheck.permittedValues));
|
|
81769
|
-
handledIssueKeys.add(issueKey);
|
|
81770
|
-
} else if (!checkValueSetsEqual(contractCheck.permittedValues, liveCheck.permittedValues)) {
|
|
81771
|
-
calls.push(new DropCheckConstraintCall(ddlSchema, tableName, contractCheck.name), new AddCheckConstraintCall(ddlSchema, tableName, contractCheck.name, contractCheck.column, contractCheck.permittedValues));
|
|
81772
|
-
handledIssueKeys.add(issueKey);
|
|
81773
|
-
} else handledIssueKeys.add(issueKey);
|
|
81774
|
-
}
|
|
81775
|
-
for (const liveCheck of liveChecks) if (!contractChecks.some((c) => c.name === liveCheck.name)) {
|
|
81776
|
-
const issueKey = `${tableName} ${liveCheck.name}`;
|
|
81777
|
-
calls.push(new DropCheckConstraintCall(ddlSchema, tableName, liveCheck.name));
|
|
81778
|
-
handledIssueKeys.add(issueKey);
|
|
81779
|
-
}
|
|
81780
|
-
}
|
|
81781
|
-
if (calls.length === 0 && handledIssueKeys.size === 0) return { kind: "no_match" };
|
|
81782
|
-
return {
|
|
81783
|
-
kind: "match",
|
|
81784
|
-
issues: issues.filter((issue) => {
|
|
81785
|
-
const node = issueNode(issue);
|
|
81786
|
-
if (node === void 0 || node.nodeKind !== RelationalSchemaNodeKind.check) return true;
|
|
81787
|
-
const tableName = issueTableName(issue);
|
|
81788
|
-
if (tableName === void 0) return true;
|
|
81789
|
-
const checkName = blindCast(node).name;
|
|
81790
|
-
return !handledIssueKeys.has(`${tableName} ${checkName}`);
|
|
81791
|
-
}),
|
|
81792
|
-
calls
|
|
81793
|
-
};
|
|
81794
|
-
};
|
|
81795
|
-
/**
|
|
81796
82088
|
* Dispatches codec-typed storage types through their codec's
|
|
81797
82089
|
* `planTypeOperations` hook (the authoritative source for codec-driven DDL
|
|
81798
82090
|
* such as custom type creation). Codec extension/type ops are not modeled as
|
|
@@ -81938,28 +82230,9 @@ const postgresPlannerStrategies = [
|
|
|
81938
82230
|
notNullBackfillCallStrategy,
|
|
81939
82231
|
typeChangeCallStrategy,
|
|
81940
82232
|
nullableTighteningCallStrategy,
|
|
81941
|
-
checkConstraintPlanCallStrategy,
|
|
81942
82233
|
storageTypePlanCallStrategy,
|
|
81943
82234
|
notNullAddColumnCallStrategy
|
|
81944
82235
|
];
|
|
81945
|
-
/**
|
|
81946
|
-
* Deterministic name for the element-non-null CHECK constraint on a scalar-array
|
|
81947
|
-
* column. Distinct `_elem_not_null` suffix avoids collision with the enum
|
|
81948
|
-
* value-set `_check` constraints. Re-emitting the same schema produces the same
|
|
81949
|
-
* name, so `pg_get_constraintdef`-based verify sees no drift.
|
|
81950
|
-
*/
|
|
81951
|
-
function elementNonNullCheckName(tableName, columnName) {
|
|
81952
|
-
return `${tableName}_${columnName}_elem_not_null`;
|
|
81953
|
-
}
|
|
81954
|
-
/**
|
|
81955
|
-
* Predicate enforcing that a scalar-array column carries no NULL element. The
|
|
81956
|
-
* array column itself may be NULL (container nullability is the column's NOT NULL
|
|
81957
|
-
* clause); `array_position` over a NULL array yields NULL, which a CHECK treats
|
|
81958
|
-
* as satisfied, so a nullable array column is unaffected.
|
|
81959
|
-
*/
|
|
81960
|
-
function elementNonNullCheckExpression(columnName) {
|
|
81961
|
-
return `array_position(${quoteIdentifier(columnName)}, NULL) IS NULL`;
|
|
81962
|
-
}
|
|
81963
82236
|
function issueConflict(kind, summary, location) {
|
|
81964
82237
|
return {
|
|
81965
82238
|
kind,
|
|
@@ -81994,7 +82267,8 @@ function classifyCall(call) {
|
|
|
81994
82267
|
case "dropCheckConstraint":
|
|
81995
82268
|
case "dropIndex":
|
|
81996
82269
|
case "dropDefault": return "drop";
|
|
81997
|
-
case "addCheckConstraint":
|
|
82270
|
+
case "addCheckConstraint":
|
|
82271
|
+
case "renameCheckConstraint": return "unique";
|
|
81998
82272
|
case "createTable": return "table";
|
|
81999
82273
|
case "enableRowLevelSecurity":
|
|
82000
82274
|
case "disableRowLevelSecurity": return "rlsEnable";
|
|
@@ -82055,6 +82329,7 @@ function locationForCall(call) {
|
|
|
82055
82329
|
if (anyCall.indexName) location.index = anyCall.indexName;
|
|
82056
82330
|
else if (anyCall.newIndexName) location.index = anyCall.newIndexName;
|
|
82057
82331
|
if (anyCall.constraintName) location.constraint = anyCall.constraintName;
|
|
82332
|
+
else if (anyCall.newConstraintName) location.constraint = anyCall.newConstraintName;
|
|
82058
82333
|
if (anyCall.policyName) location.rlsPolicy = anyCall.policyName;
|
|
82059
82334
|
else if (anyCall.policy?.name) location.rlsPolicy = anyCall.policy.name;
|
|
82060
82335
|
else if (anyCall.newPolicyName) location.rlsPolicy = anyCall.newPolicyName;
|
|
@@ -82105,17 +82380,6 @@ function issueColumnName(issue) {
|
|
|
82105
82380
|
function emissionSchemaName(ctx, ddlSchemaName) {
|
|
82106
82381
|
return resolveNamespaceIdForDdlSchema(ctx.toContract, ddlSchemaName) === "__unbound__" ? UNBOUND_NAMESPACE_ID : ddlSchemaName;
|
|
82107
82382
|
}
|
|
82108
|
-
/**
|
|
82109
|
-
* Whether a column node is a scalar-array (`many: true`) column. The family
|
|
82110
|
-
* converter (`contractToSchemaIR`'s `convertColumn`) never stamps `many` on
|
|
82111
|
-
* the derived node — array-ness is folded into the `[]` suffix on
|
|
82112
|
-
* `nativeType` instead — so the node-derived check reads the suffix; `.many`
|
|
82113
|
-
* is still checked first for nodes a caller stamps directly (e.g. hand-built
|
|
82114
|
-
* test fixtures, or an adapter that populates it at introspection).
|
|
82115
|
-
*/
|
|
82116
|
-
function isManyColumn(column) {
|
|
82117
|
-
return column.many === true || column.nativeType.endsWith("[]");
|
|
82118
|
-
}
|
|
82119
82383
|
/** Whether the expected/actual native type (resolved, or raw+many fallback) differs — mirrors `SqlColumnIR.isEqualTo`'s type comparison. */
|
|
82120
82384
|
function columnTypeChanged(expected, actual) {
|
|
82121
82385
|
if (expected.resolvedNativeType !== void 0 && actual.resolvedNativeType !== void 0) return expected.resolvedNativeType !== actual.resolvedNativeType;
|
|
@@ -82156,7 +82420,7 @@ function fkSpecFromNode(fk, tableName) {
|
|
|
82156
82420
|
/**
|
|
82157
82421
|
* Builds the `CreateTable` + child `CreateIndex` / `AddForeignKey` / `AddUnique`
|
|
82158
82422
|
* calls for a newly-expected table, reading only the table node's children. The
|
|
82159
|
-
* PK and
|
|
82423
|
+
* PK and every declared CHECK go inline as table constraints; indexes
|
|
82160
82424
|
* (declared + FK-backing, already merged and ordered at derivation) and the
|
|
82161
82425
|
* FK / unique constraints are separate calls (re-bucketed downstream). Every
|
|
82162
82426
|
* column's DDL is resolved from its `codecRef` via `renderColumnDdl`.
|
|
@@ -82164,8 +82428,8 @@ function fkSpecFromNode(fk, tableName) {
|
|
|
82164
82428
|
function buildCreateTableCallsFromNode(schemaName, ddlSchemaName, table, codecHooks) {
|
|
82165
82429
|
const ddlColumns = Object.values(table.columns).map((c) => renderColumnDdl(c.name, c, codecHooks));
|
|
82166
82430
|
const primaryKeyConstraints = table.primaryKey ? [primaryKey([...table.primaryKey.columns], { ...ifDefined("name", table.primaryKey.name) })] : [];
|
|
82167
|
-
const
|
|
82168
|
-
const allTableConstraints = [...primaryKeyConstraints, ...
|
|
82431
|
+
const declaredChecks = (table.checks ?? []).map((c) => checkExpression(c.name, c.expression));
|
|
82432
|
+
const allTableConstraints = [...primaryKeyConstraints, ...declaredChecks];
|
|
82169
82433
|
const calls = [new CreateTableCall(schemaName, table.name, ddlColumns, allTableConstraints.length > 0 ? allTableConstraints : void 0)];
|
|
82170
82434
|
for (const index of table.indexes) calls.push(createIndexCallFromNode(index, schemaName, table.name));
|
|
82171
82435
|
for (const fk of table.foreignKeys) calls.push(new AddForeignKeyCall(schemaName, table.name, fkSpecFromNode(fk, table.name)));
|
|
@@ -82307,9 +82571,20 @@ function mapIndexNodeIssue(issue, schemaName, tableName) {
|
|
|
82307
82571
|
if (issueOutcome(issue) === "not-expected") return ok$1([new DropIndexCall(schemaName, tableName, blindCast(issue.actual).name)]);
|
|
82308
82572
|
return notOk(nodeConflict("indexIncompatible", issue.path.join("/")));
|
|
82309
82573
|
}
|
|
82574
|
+
/**
|
|
82575
|
+
* The index treatment: a missing check is added, an undeclared live check is
|
|
82576
|
+
* dropped, and a paired divergence is a conflict. `not-equal` is reachable only
|
|
82577
|
+
* for an exact-named expected check — a wire-named one compares by name, so a
|
|
82578
|
+
* changed predicate re-suffixes the name and arrives as missing + extra
|
|
82579
|
+
* instead.
|
|
82580
|
+
*/
|
|
82310
82581
|
function mapCheckNodeIssue(issue, schemaName, tableName) {
|
|
82582
|
+
if (issueOutcome(issue) === "not-found") {
|
|
82583
|
+
const check = blindCast(issue.expected);
|
|
82584
|
+
return ok$1([new AddCheckConstraintCall(schemaName, tableName, check.name, check.expression)]);
|
|
82585
|
+
}
|
|
82311
82586
|
if (issueOutcome(issue) === "not-expected") return ok$1([new DropCheckConstraintCall(schemaName, tableName, blindCast(issue.actual).name)]);
|
|
82312
|
-
return notOk(nodeConflict("unsupportedOperation",
|
|
82587
|
+
return notOk(nodeConflict("unsupportedOperation", issue.path.join("/")));
|
|
82313
82588
|
}
|
|
82314
82589
|
/**
|
|
82315
82590
|
* Maps one node-typed diff issue to its migration call(s), dispatching on the
|
|
@@ -83554,7 +83829,10 @@ var PostgresMigration = class extends SqlMigration {
|
|
|
83554
83829
|
return new AddForeignKeyCall(options.schema, options.table, options.foreignKey).toOp(this.controlAdapterFor("addForeignKey"));
|
|
83555
83830
|
}
|
|
83556
83831
|
addCheckConstraint(options) {
|
|
83557
|
-
return new AddCheckConstraintCall(options.schema, options.table, options.constraint, options.
|
|
83832
|
+
return new AddCheckConstraintCall(options.schema, options.table, options.constraint, options.expression).toOp(this.controlAdapterFor("addCheckConstraint"));
|
|
83833
|
+
}
|
|
83834
|
+
renameCheckConstraint(options) {
|
|
83835
|
+
return new RenameCheckConstraintCall(options.schema ?? "__unbound__", options.table, options.from, options.to).toOp(this.controlAdapterFor("renameCheckConstraint"));
|
|
83558
83836
|
}
|
|
83559
83837
|
dropCheckConstraint(options) {
|
|
83560
83838
|
return new DropCheckConstraintCall(options.schema, options.table, options.constraint).toOp(this.controlAdapterFor("dropCheckConstraint"));
|
|
@@ -214683,7 +214961,7 @@ function shebangLineFor(runtime) {
|
|
|
214683
214961
|
* to `'postgres'`, so user-authored migrations don't need to thread
|
|
214684
214962
|
* target-details or redeclare `targetId`.
|
|
214685
214963
|
* - `MigrationCLI` — the migration-file CLI entrypoint, re-exported from
|
|
214686
|
-
* `@internal/cli/migration-cli`. Loads `prisma
|
|
214964
|
+
* `@internal/cli/migration-cli`. Loads `prisma.config.ts`,
|
|
214687
214965
|
* assembles a `ControlStack`, and instantiates the migration class.
|
|
214688
214966
|
* The migration file owns this dependency directly: pulling CLI
|
|
214689
214967
|
* machinery in at script run time is acceptable because the script's
|
|
@@ -214945,7 +215223,9 @@ var PostgresMigrationPlanner = class {
|
|
|
214945
215223
|
schema: options.schema
|
|
214946
215224
|
}), ...gated];
|
|
214947
215225
|
const indexRenames = this.pairIndexRenames(options, schemaIssues);
|
|
214948
|
-
const
|
|
215226
|
+
const checkRenames = this.pairCheckRenames(options, schemaIssues);
|
|
215227
|
+
const renameConsumed = /* @__PURE__ */ new Set([...indexRenames.consumed, ...checkRenames.consumed]);
|
|
215228
|
+
const plannableIssues = renameConsumed.size === 0 ? schemaIssues : schemaIssues.filter((issue) => !renameConsumed.has(issue));
|
|
214949
215229
|
const codecHooks = extractCodecControlHooks(options.frameworkComponents);
|
|
214950
215230
|
const storageTypes = options.contract.storage.types ?? {};
|
|
214951
215231
|
const relationalSchema = relationalNamespaceNode(options.schema, schemaName);
|
|
@@ -214970,7 +215250,7 @@ var PostgresMigrationPlanner = class {
|
|
|
214970
215250
|
const schemaDiff = this.planPostgresSchemaDiff(options, policyDiffIssues);
|
|
214971
215251
|
if (!result.ok || schemaDiff.conflicts.length > 0) return plannerFailure([...result.ok ? [] : result.failure, ...schemaDiff.conflicts]);
|
|
214972
215252
|
const indexRenamePartition = partitionCallsByControlPolicy({
|
|
214973
|
-
calls: indexRenames.calls,
|
|
215253
|
+
calls: [...indexRenames.calls, ...checkRenames.calls],
|
|
214974
215254
|
contract: options.contract,
|
|
214975
215255
|
resolveControlPolicySubject: (call) => resolvePostgresCallControlPolicySubject(call, options.contract),
|
|
214976
215256
|
resolveFactoryName: (call) => call.factoryName
|
|
@@ -215078,11 +215358,101 @@ var PostgresMigrationPlanner = class {
|
|
|
215078
215358
|
finding.tableName,
|
|
215079
215359
|
hash
|
|
215080
215360
|
]);
|
|
215081
|
-
const rename = (missingFinding, candidate) => {
|
|
215082
|
-
consumed.add(missingFinding.issue);
|
|
215083
|
-
consumed.add(candidate.issue);
|
|
215084
|
-
calls.push(new RenameIndexCall(emissionSchema(missingFinding.ddlSchema), missingFinding.tableName, candidate.node.name, missingFinding.node.name));
|
|
215085
|
-
};
|
|
215361
|
+
const rename = (missingFinding, candidate) => {
|
|
215362
|
+
consumed.add(missingFinding.issue);
|
|
215363
|
+
consumed.add(candidate.issue);
|
|
215364
|
+
calls.push(new RenameIndexCall(emissionSchema(missingFinding.ddlSchema), missingFinding.tableName, candidate.node.name, missingFinding.node.name));
|
|
215365
|
+
};
|
|
215366
|
+
const sortedMissing = [...missing].sort(byName);
|
|
215367
|
+
const extrasByHash = /* @__PURE__ */ new Map();
|
|
215368
|
+
for (const finding of extra) {
|
|
215369
|
+
const parsed = parseWireName(finding.node.name);
|
|
215370
|
+
if (parsed === void 0) continue;
|
|
215371
|
+
const key = pairingKey(finding, parsed.hash);
|
|
215372
|
+
const group = extrasByHash.get(key) ?? [];
|
|
215373
|
+
group.push(finding);
|
|
215374
|
+
extrasByHash.set(key, group);
|
|
215375
|
+
}
|
|
215376
|
+
for (const group of extrasByHash.values()) group.sort(byName);
|
|
215377
|
+
for (const missingFinding of sortedMissing) {
|
|
215378
|
+
const parsed = parseWireName(missingFinding.node.name);
|
|
215379
|
+
if (parsed === void 0) continue;
|
|
215380
|
+
const candidate = extrasByHash.get(pairingKey(missingFinding, parsed.hash))?.shift();
|
|
215381
|
+
if (candidate === void 0) continue;
|
|
215382
|
+
rename(missingFinding, candidate);
|
|
215383
|
+
}
|
|
215384
|
+
const sortedExtras = [...extra].sort(byName);
|
|
215385
|
+
for (const missingFinding of sortedMissing) {
|
|
215386
|
+
if (consumed.has(missingFinding.issue)) continue;
|
|
215387
|
+
if (missingFinding.node.prefix === void 0) continue;
|
|
215388
|
+
const candidate = sortedExtras.find((extraFinding) => !consumed.has(extraFinding.issue) && extraFinding.ddlSchema === missingFinding.ddlSchema && extraFinding.tableName === missingFinding.tableName && missingFinding.node.contentEquals(extraFinding.node, {
|
|
215389
|
+
columnPresence: "matching",
|
|
215390
|
+
bodies: "verbatim"
|
|
215391
|
+
}));
|
|
215392
|
+
if (candidate === void 0) continue;
|
|
215393
|
+
rename(missingFinding, candidate);
|
|
215394
|
+
}
|
|
215395
|
+
return {
|
|
215396
|
+
calls,
|
|
215397
|
+
consumed
|
|
215398
|
+
};
|
|
215399
|
+
}
|
|
215400
|
+
/**
|
|
215401
|
+
* Check-constraint rename post-pass: a `not-found` and a `not-expected`
|
|
215402
|
+
* check on the same table whose wire-name content hashes match but whose
|
|
215403
|
+
* prefixes differ is a prefix-only rename, and collapses into one
|
|
215404
|
+
* `ALTER TABLE … RENAME CONSTRAINT`.
|
|
215405
|
+
*
|
|
215406
|
+
* This is the index pass's hash-pairing phase and nothing else. There is
|
|
215407
|
+
* deliberately no content-pairing phase: a live check body is whatever
|
|
215408
|
+
* Postgres reprinted, so it never byte-matches the authored text, and
|
|
215409
|
+
* pairing an exact-named live check by content would bless whatever
|
|
215410
|
+
* predicate is actually live. Adoption of an old exact-named check stays
|
|
215411
|
+
* drop + add.
|
|
215412
|
+
*
|
|
215413
|
+
* Runs only when the policy allows `widening` (rename's class). Without it
|
|
215414
|
+
* the pass no-ops and the pair degrades to the slice-1 behavior: an add,
|
|
215415
|
+
* plus a drop when `destructive` is allowed too.
|
|
215416
|
+
*/
|
|
215417
|
+
pairCheckRenames(options, issues) {
|
|
215418
|
+
const consumed = /* @__PURE__ */ new Set();
|
|
215419
|
+
const calls = [];
|
|
215420
|
+
if (!options.policy.allowedOperationClasses.includes("widening")) return {
|
|
215421
|
+
calls,
|
|
215422
|
+
consumed
|
|
215423
|
+
};
|
|
215424
|
+
const missing = [];
|
|
215425
|
+
const extra = [];
|
|
215426
|
+
for (const issue of issues) {
|
|
215427
|
+
const node = issueNode(issue);
|
|
215428
|
+
if (node === void 0 || !SqlCheckConstraintIR.is(node)) continue;
|
|
215429
|
+
const ddlSchema = issue.path[1];
|
|
215430
|
+
const tableName = issue.path[2];
|
|
215431
|
+
if (ddlSchema === void 0 || tableName === void 0) continue;
|
|
215432
|
+
if (issueOutcome(issue) === "not-found") missing.push({
|
|
215433
|
+
issue,
|
|
215434
|
+
node,
|
|
215435
|
+
ddlSchema,
|
|
215436
|
+
tableName
|
|
215437
|
+
});
|
|
215438
|
+
else if (issueOutcome(issue) === "not-expected") extra.push({
|
|
215439
|
+
issue,
|
|
215440
|
+
node,
|
|
215441
|
+
ddlSchema,
|
|
215442
|
+
tableName
|
|
215443
|
+
});
|
|
215444
|
+
}
|
|
215445
|
+
if (missing.length === 0 || extra.length === 0) return {
|
|
215446
|
+
calls,
|
|
215447
|
+
consumed
|
|
215448
|
+
};
|
|
215449
|
+
const byName = (a, b) => a.node.name < b.node.name ? -1 : a.node.name > b.node.name ? 1 : 0;
|
|
215450
|
+
const emissionSchema = (ddlSchema) => resolveNamespaceIdForDdlSchema(options.contract, ddlSchema) === "__unbound__" ? UNBOUND_NAMESPACE_ID : ddlSchema;
|
|
215451
|
+
const pairingKey = (finding, hash) => JSON.stringify([
|
|
215452
|
+
finding.ddlSchema,
|
|
215453
|
+
finding.tableName,
|
|
215454
|
+
hash
|
|
215455
|
+
]);
|
|
215086
215456
|
const sortedMissing = [...missing].sort(byName);
|
|
215087
215457
|
const extrasByHash = /* @__PURE__ */ new Map();
|
|
215088
215458
|
for (const finding of extra) {
|
|
@@ -215099,18 +215469,9 @@ var PostgresMigrationPlanner = class {
|
|
|
215099
215469
|
if (parsed === void 0) continue;
|
|
215100
215470
|
const candidate = extrasByHash.get(pairingKey(missingFinding, parsed.hash))?.shift();
|
|
215101
215471
|
if (candidate === void 0) continue;
|
|
215102
|
-
|
|
215103
|
-
|
|
215104
|
-
|
|
215105
|
-
for (const missingFinding of sortedMissing) {
|
|
215106
|
-
if (consumed.has(missingFinding.issue)) continue;
|
|
215107
|
-
if (missingFinding.node.prefix === void 0) continue;
|
|
215108
|
-
const candidate = sortedExtras.find((extraFinding) => !consumed.has(extraFinding.issue) && extraFinding.ddlSchema === missingFinding.ddlSchema && extraFinding.tableName === missingFinding.tableName && missingFinding.node.contentEquals(extraFinding.node, {
|
|
215109
|
-
columnPresence: "matching",
|
|
215110
|
-
bodies: "verbatim"
|
|
215111
|
-
}));
|
|
215112
|
-
if (candidate === void 0) continue;
|
|
215113
|
-
rename(missingFinding, candidate);
|
|
215472
|
+
consumed.add(missingFinding.issue);
|
|
215473
|
+
consumed.add(candidate.issue);
|
|
215474
|
+
calls.push(new RenameCheckConstraintCall(emissionSchema(missingFinding.ddlSchema), missingFinding.tableName, candidate.node.name, missingFinding.node.name));
|
|
215114
215475
|
}
|
|
215115
215476
|
return {
|
|
215116
215477
|
calls,
|
|
@@ -216945,6 +217306,20 @@ function buildIndexAttribute(index, fieldNames) {
|
|
|
216945
217306
|
}
|
|
216946
217307
|
return buildAttribute("model", "index", args);
|
|
216947
217308
|
}
|
|
217309
|
+
/**
|
|
217310
|
+
* Emits one `@@check` attribute for a live, non-derived check, always in the
|
|
217311
|
+
* `map:` form. Re-detecting `name:` is not attempted: the live expression is
|
|
217312
|
+
* Postgres's own reprint, but a wire-named check's hash was taken over the
|
|
217313
|
+
* author's original text, so recomputing the hash from the reprint would
|
|
217314
|
+
* essentially never match. `map:` plus the verbatim reprint is correct
|
|
217315
|
+
* regardless — a reprint compared against a later reprint of the same
|
|
217316
|
+
* expression is stable, so the emitted contract signs the live database with
|
|
217317
|
+
* zero pending operations. `buildPolicyBlocks` makes the same call for
|
|
217318
|
+
* `@@map` on adopted RLS policies, for the same reason.
|
|
217319
|
+
*/
|
|
217320
|
+
function buildCheckAttribute(check) {
|
|
217321
|
+
return buildAttribute("model", "check", [namedArg("expression", `"${escapePslString(check.expression)}"`), namedArg("map", `"${escapePslString(check.name)}"`)]);
|
|
217322
|
+
}
|
|
216948
217323
|
function buildModel(table, typeMap, enumNameMap, fieldNamesByTable, defaultMapping, rawDefaultParser, relationFields, danglingForeignKeys, rlsEnabled = false, policySkipNotes = []) {
|
|
216949
217324
|
const { name: modelName, map: mapName } = toModelName(table.name);
|
|
216950
217325
|
const fieldNameMap = fieldNamesByTable.get(table.name);
|
|
@@ -216957,8 +217332,9 @@ function buildModel(table, typeMap, enumNameMap, fieldNamesByTable, defaultMappi
|
|
|
216957
217332
|
const existingConstraintName = uniqueColumns.get(columnName);
|
|
216958
217333
|
if (!uniqueColumns.has(columnName) || existingConstraintName === void 0 && unique.name) uniqueColumns.set(columnName, unique.name);
|
|
216959
217334
|
}
|
|
217335
|
+
const derivedCheckNames = computeDerivedCheckNames(table);
|
|
216960
217336
|
const fields = [];
|
|
216961
|
-
for (const column of Object.values(table.columns)) fields.push(buildScalarField(column, table, typeMap, enumNameMap, fieldNameMap, defaultMapping, rawDefaultParser, pkColumns, isSinglePk, singlePkConstraintName, uniqueColumns));
|
|
217337
|
+
for (const column of Object.values(table.columns)) fields.push(buildScalarField(column, table, typeMap, enumNameMap, fieldNameMap, defaultMapping, rawDefaultParser, pkColumns, isSinglePk, singlePkConstraintName, uniqueColumns, derivedCheckNames));
|
|
216962
217338
|
const usedFieldNames = new Set(fields.map((field) => field.name));
|
|
216963
217339
|
for (const rel of relationFields) fields.push(buildRelationField(rel, table.name, fieldNamesByTable, usedFieldNames));
|
|
216964
217340
|
const modelAttributes = [];
|
|
@@ -216974,6 +217350,7 @@ function buildModel(table, typeMap, enumNameMap, fieldNamesByTable, defaultMappi
|
|
|
216974
217350
|
const indexFieldNames = index.columns?.map((columnName) => resolveColumnFieldName(fieldNamesByTable, table.name, columnName));
|
|
216975
217351
|
modelAttributes.push(buildIndexAttribute(index, indexFieldNames));
|
|
216976
217352
|
}
|
|
217353
|
+
for (const check of table.checks ?? []) if (!derivedCheckNames.has(check.name)) modelAttributes.push(buildCheckAttribute(check));
|
|
216977
217354
|
if (mapName) modelAttributes.push(buildMapAttribute("model", mapName));
|
|
216978
217355
|
if (rlsEnabled) modelAttributes.push(buildAttribute("model", "rls", []));
|
|
216979
217356
|
const warnings = [];
|
|
@@ -216990,7 +217367,35 @@ function buildModel(table, typeMap, enumNameMap, fieldNamesByTable, defaultMappi
|
|
|
216990
217367
|
...comment !== void 0 ? { comment } : {}
|
|
216991
217368
|
};
|
|
216992
217369
|
}
|
|
216993
|
-
|
|
217370
|
+
/**
|
|
217371
|
+
* The live check names that are derived: a live check's name matches
|
|
217372
|
+
* `formatWireName(composeCheckWirePrefix(table, column, kind), computeCheckContentHash(expression))`
|
|
217373
|
+
* for some column of the table and some candidate `postgresRenderCheckExpressions`
|
|
217374
|
+
* would render for that column. Never by comparing expressions — the live
|
|
217375
|
+
* body is a Postgres reprint, never the authored text. One set serves both
|
|
217376
|
+
* the `@noCheck` waiver below and `@@check` exclusion in `buildModel`, so the
|
|
217377
|
+
* two decisions cannot drift apart.
|
|
217378
|
+
*
|
|
217379
|
+
* `membership` is unreachable here today: infer never emits domain enums
|
|
217380
|
+
* (`enumType()` is not inferred), so no inferred column has member values and
|
|
217381
|
+
* no membership check is ever derived. The day domain-enum inference exists,
|
|
217382
|
+
* its slice extends this by threading the column's member values through.
|
|
217383
|
+
*/
|
|
217384
|
+
function computeDerivedCheckNames(table) {
|
|
217385
|
+
const liveCheckNames = new Set((table.checks ?? []).map((check) => check.name));
|
|
217386
|
+
const derivedCheckNames = /* @__PURE__ */ new Set();
|
|
217387
|
+
for (const column of Object.values(table.columns)) for (const candidate of postgresRenderCheckExpressions({
|
|
217388
|
+
tableName: table.name,
|
|
217389
|
+
columnName: column.name,
|
|
217390
|
+
many: column.many === true,
|
|
217391
|
+
memberValues: void 0
|
|
217392
|
+
})) {
|
|
217393
|
+
const derivedName = formatWireName(composeCheckWirePrefix(table.name, column.name, candidate.kind), computeCheckContentHash(candidate.expression));
|
|
217394
|
+
if (liveCheckNames.has(derivedName)) derivedCheckNames.add(derivedName);
|
|
217395
|
+
}
|
|
217396
|
+
return derivedCheckNames;
|
|
217397
|
+
}
|
|
217398
|
+
function buildScalarField(column, table, typeMap, enumNameMap, fieldNameMap, defaultMapping, rawDefaultParser, pkColumns, isSinglePk, singlePkConstraintName, uniqueColumns, derivedCheckNames) {
|
|
216994
217399
|
const resolvedField = fieldNameMap?.get(column.name);
|
|
216995
217400
|
const fieldName = resolvedField?.fieldName ?? toFieldName(column.name).name;
|
|
216996
217401
|
const fieldMap = resolvedField?.fieldMap;
|
|
@@ -217043,6 +217448,15 @@ function buildScalarField(column, table, typeMap, enumNameMap, fieldNameMap, def
|
|
|
217043
217448
|
const uniqueConstraintName = uniqueColumns.get(column.name);
|
|
217044
217449
|
attributes.push(buildSimpleConstraintFieldAttribute("unique", uniqueConstraintName));
|
|
217045
217450
|
}
|
|
217451
|
+
if (column.many === true) {
|
|
217452
|
+
const waivedKinds = postgresRenderCheckExpressions({
|
|
217453
|
+
tableName: table.name,
|
|
217454
|
+
columnName: column.name,
|
|
217455
|
+
many: true,
|
|
217456
|
+
memberValues: void 0
|
|
217457
|
+
}).filter((candidate) => !derivedCheckNames.has(formatWireName(composeCheckWirePrefix(table.name, column.name, candidate.kind), computeCheckContentHash(candidate.expression)))).map((candidate) => candidate.kind);
|
|
217458
|
+
if (waivedKinds.length > 0) attributes.push(buildAttribute("field", "noCheck", waivedKinds.map(positionalArg)));
|
|
217459
|
+
}
|
|
217046
217460
|
if (fieldMap !== void 0) attributes.push(buildMapAttribute("field", fieldMap));
|
|
217047
217461
|
return {
|
|
217048
217462
|
kind: "field",
|
|
@@ -217299,11 +217713,15 @@ function createPostgresTypeMap(enumTypeNames) {
|
|
|
217299
217713
|
* Relation inference, name transforms, generic default mapping, and raw-default
|
|
217300
217714
|
* parsing are shape-neutral utilities imported from the SQL family.
|
|
217301
217715
|
*
|
|
217302
|
-
*
|
|
217303
|
-
*
|
|
217304
|
-
*
|
|
217305
|
-
*
|
|
217306
|
-
*
|
|
217716
|
+
* The tree's tables (across its namespaces — `contract infer` introspects a
|
|
217717
|
+
* single live namespace) are gathered into the model set and emitted in one
|
|
217718
|
+
* bucket, alongside native-enum and RLS policy blocks. That bucket is named
|
|
217719
|
+
* after the introspected schema when the content needs a `namespace { … }`
|
|
217720
|
+
* wrap, and is the flat `UNSPECIFIED_PSL_NAMESPACE_ID` bucket otherwise. This
|
|
217721
|
+
* entry point emits nothing else, so its output is always exactly one bucket
|
|
217722
|
+
* and byte-identical to the prior flat inference. {@link buildPslDocumentAst}
|
|
217723
|
+
* can emit a second, always-flat bucket for content that must stay top-level
|
|
217724
|
+
* even under a wrap; no caller asks for one yet.
|
|
217307
217725
|
*
|
|
217308
217726
|
* `describedContracts` — the stack's extension packs' already-assembled
|
|
217309
217727
|
* contracts, each paired with its space id — is consulted while gathering
|
|
@@ -217391,7 +217809,24 @@ function inferPostgresPslContract(tree, describedContracts) {
|
|
|
217391
217809
|
policiesByTable
|
|
217392
217810
|
});
|
|
217393
217811
|
}
|
|
217394
|
-
|
|
217812
|
+
/**
|
|
217813
|
+
* Builds the PSL document for one introspected schema.
|
|
217814
|
+
*
|
|
217815
|
+
* `namespaceName` wraps the output in `namespace <name> { … }`; omit it for
|
|
217816
|
+
* flat output. `topLevelExtensionBlocks` are declarations that must stay
|
|
217817
|
+
* top-level even when a wrap applies, such as a recovered domain enum — a
|
|
217818
|
+
* family `enum` inside a namespace is a hard diagnostic. They land in their
|
|
217819
|
+
* own always-flat bucket when a wrap applies, and in the single flat bucket
|
|
217820
|
+
* when none does; either way they print unwrapped.
|
|
217821
|
+
*
|
|
217822
|
+
* Their names are reserved before the policy blocks are built, so a policy
|
|
217823
|
+
* renames itself out of the way. Against the rest of the top-level scope — the
|
|
217824
|
+
* models, the native enums, PSL's scalar type names, and the other blocks in
|
|
217825
|
+
* the list — a clash throws instead: a block's name is its contract key
|
|
217826
|
+
* (`entries.valueSet[name]`, with no `@@map` escape), so it cannot be rewritten
|
|
217827
|
+
* here.
|
|
217828
|
+
*/
|
|
217829
|
+
function buildPslDocumentAst(schemaIR, options, foreignKeyExtras, namespaceName, rlsExtras, topLevelExtensionBlocks = []) {
|
|
217395
217830
|
const { typeMap, defaultMapping, parseRawDefault: rawDefaultParser } = options;
|
|
217396
217831
|
const { extraRelationsByTable, crossSpaceFieldNamesByTable, danglingForeignKeysByTable } = foreignKeyExtras;
|
|
217397
217832
|
const modelNames = buildTopLevelNameMap(Object.keys(schemaIR.tables), toModelName, "model", "table");
|
|
@@ -217401,19 +217836,48 @@ function buildPslDocumentAst(schemaIR, options, foreignKeyExtras, namespaceName,
|
|
|
217401
217836
|
if (namespaceName !== void 0) for (const [typeName, pslName] of bareEnumNameMap) enumNameMap.set(`${namespaceName}.${typeName}`, pslName);
|
|
217402
217837
|
const fieldNamesByTable = new Map([...crossSpaceFieldNamesByTable, ...buildFieldNamesByTable(schemaIR.tables)]);
|
|
217403
217838
|
const { relationsByTable } = inferRelations(schemaIR.tables, modelNameMap);
|
|
217404
|
-
const policyEmission = buildPolicyBlocks(rlsExtras?.policiesByTable ?? /* @__PURE__ */ new Map(), modelNameMap, /* @__PURE__ */ new Set([
|
|
217839
|
+
const policyEmission = buildPolicyBlocks(rlsExtras?.policiesByTable ?? /* @__PURE__ */ new Map(), modelNameMap, /* @__PURE__ */ new Set([
|
|
217840
|
+
...modelNameMap.values(),
|
|
217841
|
+
...bareEnumNameMap.values(),
|
|
217842
|
+
...topLevelExtensionBlocks.map((block) => block.name)
|
|
217843
|
+
]));
|
|
217844
|
+
const claimedTopLevelNames = /* @__PURE__ */ new Set([
|
|
217845
|
+
...PSL_SCALAR_TYPE_NAMES,
|
|
217846
|
+
...modelNameMap.values(),
|
|
217847
|
+
...bareEnumNameMap.values()
|
|
217848
|
+
]);
|
|
217849
|
+
for (const block of topLevelExtensionBlocks) {
|
|
217850
|
+
if (claimedTopLevelNames.has(block.name)) throw postgresError("CONTRACT.NAME_DUPLICATE", `contract infer: recovered ${block.keyword} "${block.name}" collides with a model, a native enum, a PSL scalar type, or another recovered declaration of the same name. Rename the recovered declaration, or exclude it.`, { meta: {
|
|
217851
|
+
kind: block.keyword,
|
|
217852
|
+
name: block.name
|
|
217853
|
+
} });
|
|
217854
|
+
claimedTopLevelNames.add(block.name);
|
|
217855
|
+
}
|
|
217405
217856
|
const models = [];
|
|
217406
217857
|
for (const table of Object.values(schemaIR.tables)) models.push(buildModel(table, typeMap, enumNameMap, fieldNamesByTable, defaultMapping, rawDefaultParser, [...relationsByTable.get(table.name) ?? [], ...extraRelationsByTable.get(table.name) ?? []], danglingForeignKeysByTable.get(table.name) ?? [], rlsExtras?.rlsEnabledTables.has(table.name) ?? false, policyEmission.skipNotesByTable.get(table.name) ?? []));
|
|
217407
217858
|
const sortedModels = topologicalSort(models, schemaIR.tables, modelNameMap);
|
|
217859
|
+
const separateTopLevelBucket = namespaceName !== void 0 && namespaceName !== "__unspecified__" && topLevelExtensionBlocks.length > 0;
|
|
217860
|
+
const namespaces = [];
|
|
217861
|
+
if (separateTopLevelBucket) namespaces.push(makePslNamespace({
|
|
217862
|
+
kind: "namespace",
|
|
217863
|
+
name: UNSPECIFIED_PSL_NAMESPACE_ID,
|
|
217864
|
+
entries: makePslNamespaceEntries([], [], topLevelExtensionBlocks),
|
|
217865
|
+
span: SYNTHETIC_SPAN
|
|
217866
|
+
}));
|
|
217867
|
+
namespaces.push(makePslNamespace({
|
|
217868
|
+
kind: "namespace",
|
|
217869
|
+
name: namespaceName ?? "__unspecified__",
|
|
217870
|
+
entries: makePslNamespaceEntries(sortedModels, [], [
|
|
217871
|
+
...separateTopLevelBucket ? [] : topLevelExtensionBlocks,
|
|
217872
|
+
...enumBlocks,
|
|
217873
|
+
...policyEmission.blocks
|
|
217874
|
+
]),
|
|
217875
|
+
span: SYNTHETIC_SPAN
|
|
217876
|
+
}));
|
|
217408
217877
|
return {
|
|
217409
217878
|
kind: "document",
|
|
217410
217879
|
sourceId: "<sql-schema-ir>",
|
|
217411
|
-
namespaces
|
|
217412
|
-
kind: "namespace",
|
|
217413
|
-
name: namespaceName ?? "__unspecified__",
|
|
217414
|
-
entries: makePslNamespaceEntries(sortedModels, [], [...enumBlocks, ...policyEmission.blocks]),
|
|
217415
|
-
span: SYNTHETIC_SPAN
|
|
217416
|
-
})],
|
|
217880
|
+
namespaces,
|
|
217417
217881
|
span: SYNTHETIC_SPAN
|
|
217418
217882
|
};
|
|
217419
217883
|
}
|
|
@@ -217472,107 +217936,6 @@ const postgresTargetDescriptor = {
|
|
|
217472
217936
|
return createPostgresMigrationRunner(family);
|
|
217473
217937
|
}
|
|
217474
217938
|
};
|
|
217475
|
-
/**
|
|
217476
|
-
* Asserts that all framework components are compatible with the expected family and target.
|
|
217477
|
-
*
|
|
217478
|
-
* This function validates that each component in the framework components array:
|
|
217479
|
-
* - Has kind 'target', 'adapter', 'extension', or 'driver'
|
|
217480
|
-
* - Has familyId matching expectedFamilyId
|
|
217481
|
-
* - Has targetId matching expectedTargetId
|
|
217482
|
-
*
|
|
217483
|
-
* This validation happens at the CLI composition boundary, before passing components
|
|
217484
|
-
* to typed planner/runner instances. It fills the gap between runtime validation
|
|
217485
|
-
* (via `validateConfig()`) and compile-time type enforcement.
|
|
217486
|
-
*
|
|
217487
|
-
* @param expectedFamilyId - The expected family ID (e.g., 'sql')
|
|
217488
|
-
* @param expectedTargetId - The expected target ID (e.g., 'postgres')
|
|
217489
|
-
* @param frameworkComponents - Array of framework components to validate
|
|
217490
|
-
* @returns The same array typed as TargetBoundComponentDescriptor
|
|
217491
|
-
* @throws CliStructuredError if any component is incompatible
|
|
217492
|
-
*
|
|
217493
|
-
* @example
|
|
217494
|
-
* ```ts
|
|
217495
|
-
* const config = await loadConfig();
|
|
217496
|
-
* const frameworkComponents = [config.target, config.adapter, ...(config.extensions ?? [])];
|
|
217497
|
-
*
|
|
217498
|
-
* // Validate and type-narrow components before passing to planner
|
|
217499
|
-
* const typedComponents = assertFrameworkComponentsCompatible(
|
|
217500
|
-
* config.family.familyId,
|
|
217501
|
-
* config.target.targetId,
|
|
217502
|
-
* frameworkComponents
|
|
217503
|
-
* );
|
|
217504
|
-
*
|
|
217505
|
-
* const planner = target.migrations.createPlanner(familyInstance);
|
|
217506
|
-
* planner.plan({ contract, schema, policy, frameworkComponents: typedComponents });
|
|
217507
|
-
* ```
|
|
217508
|
-
*/
|
|
217509
|
-
function assertFrameworkComponentsCompatible(expectedFamilyId, expectedTargetId, frameworkComponents) {
|
|
217510
|
-
for (let i = 0; i < frameworkComponents.length; i++) {
|
|
217511
|
-
const component = frameworkComponents[i];
|
|
217512
|
-
if (typeof component !== "object" || component === null) throw errorConfigValidation("frameworkComponents[]", { why: `Framework component at index ${i} must be an object` });
|
|
217513
|
-
const record = component;
|
|
217514
|
-
if (!Object.hasOwn(record, "kind")) throw errorConfigValidation("frameworkComponents[].kind", { why: `Framework component at index ${i} must have 'kind' property` });
|
|
217515
|
-
const kind = record["kind"];
|
|
217516
|
-
if (kind !== "target" && kind !== "adapter" && kind !== "extension" && kind !== "driver") throw errorConfigValidation("frameworkComponents[].kind", { why: `Framework component at index ${i} has invalid kind '${String(kind)}' (must be 'target', 'adapter', 'extension', or 'driver')` });
|
|
217517
|
-
if (!Object.hasOwn(record, "familyId")) throw errorConfigValidation("frameworkComponents[].familyId", { why: `Framework component at index ${i} (kind: ${String(kind)}) must have 'familyId' property` });
|
|
217518
|
-
const familyId = record["familyId"];
|
|
217519
|
-
if (familyId !== expectedFamilyId) throw errorConfigValidation("frameworkComponents[].familyId", { why: `Framework component at index ${i} (kind: ${String(kind)}) has familyId '${String(familyId)}' but expected '${expectedFamilyId}'` });
|
|
217520
|
-
if (!Object.hasOwn(record, "targetId")) throw errorConfigValidation("frameworkComponents[].targetId", { why: `Framework component at index ${i} (kind: ${String(kind)}) must have 'targetId' property` });
|
|
217521
|
-
const targetId = record["targetId"];
|
|
217522
|
-
if (targetId !== expectedTargetId) throw errorConfigValidation("frameworkComponents[].targetId", { why: `Framework component at index ${i} (kind: ${String(kind)}) has targetId '${String(targetId)}' but expected '${expectedTargetId}'` });
|
|
217523
|
-
}
|
|
217524
|
-
return frameworkComponents;
|
|
217525
|
-
}
|
|
217526
|
-
function isPlainObject(value) {
|
|
217527
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
217528
|
-
}
|
|
217529
|
-
function sortDeep(value) {
|
|
217530
|
-
if (Array.isArray(value)) return value.map(sortDeep);
|
|
217531
|
-
if (!isPlainObject(value)) return value;
|
|
217532
|
-
const entries = Object.entries(value).sort(([a], [b]) => a.localeCompare(b));
|
|
217533
|
-
const next = {};
|
|
217534
|
-
for (const [key, child] of entries) next[key] = sortDeep(child);
|
|
217535
|
-
return next;
|
|
217536
|
-
}
|
|
217537
|
-
function sortDeepTyped(value) {
|
|
217538
|
-
return sortDeep(value);
|
|
217539
|
-
}
|
|
217540
|
-
function extractExtensionPackMeta(component) {
|
|
217541
|
-
const { kind, id, version, capabilities, types } = component;
|
|
217542
|
-
const base = {
|
|
217543
|
-
kind,
|
|
217544
|
-
id,
|
|
217545
|
-
familyId: component.familyId,
|
|
217546
|
-
targetId: component.targetId,
|
|
217547
|
-
version
|
|
217548
|
-
};
|
|
217549
|
-
if (capabilities) base["capabilities"] = capabilities;
|
|
217550
|
-
if (types) if (types.codecTypes) {
|
|
217551
|
-
const { controlPlaneHooks: _, codecDescriptors: _cd, ...cleanedCodecTypes } = types.codecTypes;
|
|
217552
|
-
base["types"] = {
|
|
217553
|
-
...types,
|
|
217554
|
-
codecTypes: cleanedCodecTypes
|
|
217555
|
-
};
|
|
217556
|
-
} else base["types"] = types;
|
|
217557
|
-
return base;
|
|
217558
|
-
}
|
|
217559
|
-
/**
|
|
217560
|
-
* Enriches a raw contract with framework-derived metadata: capabilities from all component descriptors and extension pack metadata from extension descriptors. Produces deterministically sorted output.
|
|
217561
|
-
*/
|
|
217562
|
-
function enrichContract(ir, components) {
|
|
217563
|
-
const mergedCapabilities = mergeCapabilityMatrices(ir.capabilities, components);
|
|
217564
|
-
const extensionsMeta = {};
|
|
217565
|
-
for (const component of components) if (component.kind === "extension") extensionsMeta[component.id] = extractExtensionPackMeta(component);
|
|
217566
|
-
const extensions = Object.keys(extensionsMeta).length > 0 ? {
|
|
217567
|
-
...ir.extensions,
|
|
217568
|
-
...extensionsMeta
|
|
217569
|
-
} : ir.extensions;
|
|
217570
|
-
return {
|
|
217571
|
-
...ir,
|
|
217572
|
-
capabilities: sortDeepTyped(mergedCapabilities),
|
|
217573
|
-
extensions: sortDeepTyped(extensions)
|
|
217574
|
-
};
|
|
217575
|
-
}
|
|
217576
217939
|
const JSON_EXTENSION = ".json";
|
|
217577
217940
|
function getEmittedArtifactPaths(outputJsonPath) {
|
|
217578
217941
|
if (!outputJsonPath.endsWith(JSON_EXTENSION)) throw emitterError("CONFIG.VALIDATION_FAILED", "Contract output path must end with .json", { meta: {
|
|
@@ -217633,8 +217996,8 @@ function generateContractDts(contract, emitter, codecTypeImports, hashes, option
|
|
|
217633
217996
|
const extraTypeExports = emitter.getStorageTypeExports?.(contract, codecLookup);
|
|
217634
217997
|
const contractWrapper = emitter.getContractWrapper("ContractBase", "TypeMaps");
|
|
217635
217998
|
return `// ⚠️ GENERATED FILE - DO NOT EDIT
|
|
217636
|
-
// This file is automatically generated by 'prisma
|
|
217637
|
-
// To regenerate, run: prisma
|
|
217999
|
+
// This file is automatically generated by 'prisma contract emit'.
|
|
218000
|
+
// To regenerate, run: prisma contract emit
|
|
217638
218001
|
${importLines.join("\n")}
|
|
217639
218002
|
|
|
217640
218003
|
${familyImportLines.join("\n")}
|
|
@@ -217694,8 +218057,8 @@ async function emit(contract, stack, targetFamily, options) {
|
|
|
217694
218057
|
...canonicalized,
|
|
217695
218058
|
_generated: {
|
|
217696
218059
|
warning: "⚠️ GENERATED FILE - DO NOT EDIT",
|
|
217697
|
-
message: "This file is automatically generated by \"prisma
|
|
217698
|
-
regenerate: "To regenerate, run: prisma
|
|
218060
|
+
message: "This file is automatically generated by \"prisma contract emit\".",
|
|
218061
|
+
regenerate: "To regenerate, run: prisma contract emit"
|
|
217699
218062
|
}
|
|
217700
218063
|
}, null, 2);
|
|
217701
218064
|
const generateOptions = {
|
|
@@ -217725,7 +218088,6 @@ function isGraphNode(hash, graph) {
|
|
|
217725
218088
|
if (hash === "empty") return true;
|
|
217726
218089
|
return graph.nodes.has(hash);
|
|
217727
218090
|
}
|
|
217728
|
-
init_dist();
|
|
217729
218091
|
/**
|
|
217730
218092
|
* The system head ref lives at `refs/head.json`. It is read (and its
|
|
217731
218093
|
* corruption judged) through `readContractSpaceHeadRef`, not as a
|
|
@@ -217766,8 +218128,13 @@ async function readRef(refsDir, name) {
|
|
|
217766
218128
|
} catch (error) {
|
|
217767
218129
|
if (error instanceof Error && error.code === "ENOENT") throw new MigrationToolsError("MIGRATION.UNKNOWN_REF", `Unknown ref "${name}"`, {
|
|
217768
218130
|
why: `No ref file found at "${filePath}".`,
|
|
217769
|
-
fix: `Create the ref with: prisma
|
|
217770
|
-
|
|
218131
|
+
fix: `Create the ref with: prisma ref set ${name} <hash>`,
|
|
218132
|
+
nextActions: [{
|
|
218133
|
+
kind: "run-command",
|
|
218134
|
+
label: `Create the ref "${name}"`,
|
|
218135
|
+
command: `{bin} ref set ${name} <hash>`
|
|
218136
|
+
}],
|
|
218137
|
+
meta: {
|
|
217771
218138
|
refName: name,
|
|
217772
218139
|
filePath
|
|
217773
218140
|
}
|
|
@@ -217850,7 +218217,6 @@ async function readRefsTolerant(refsDir) {
|
|
|
217850
218217
|
problems
|
|
217851
218218
|
};
|
|
217852
218219
|
}
|
|
217853
|
-
init_dist();
|
|
217854
218220
|
function contractAtMemoKey(hash, refName) {
|
|
217855
218221
|
return `${hash}\0${refName ?? ""}`;
|
|
217856
218222
|
}
|
|
@@ -218844,6 +219210,109 @@ function runVerifyMigration(input) {
|
|
|
218844
219210
|
});
|
|
218845
219211
|
}
|
|
218846
219212
|
/**
|
|
219213
|
+
* Asserts that all framework components are compatible with the expected family and target.
|
|
219214
|
+
*
|
|
219215
|
+
* This function validates that each component in the framework components array:
|
|
219216
|
+
* - Has kind 'target', 'adapter', 'extension', or 'driver'
|
|
219217
|
+
* - Has familyId matching expectedFamilyId
|
|
219218
|
+
* - Has targetId matching expectedTargetId
|
|
219219
|
+
*
|
|
219220
|
+
* This validation happens at the CLI composition boundary, before passing components
|
|
219221
|
+
* to typed planner/runner instances. It fills the gap between runtime validation
|
|
219222
|
+
* (via the config loader's `collectConfigIssues` diagnostics) and compile-time
|
|
219223
|
+
* type enforcement.
|
|
219224
|
+
*
|
|
219225
|
+
* @param expectedFamilyId - The expected family ID (e.g., 'sql')
|
|
219226
|
+
* @param expectedTargetId - The expected target ID (e.g., 'postgres')
|
|
219227
|
+
* @param frameworkComponents - Array of framework components to validate
|
|
219228
|
+
* @returns The same array typed as TargetBoundComponentDescriptor
|
|
219229
|
+
* @throws CliStructuredError if any component is incompatible
|
|
219230
|
+
*
|
|
219231
|
+
* @example
|
|
219232
|
+
* ```ts
|
|
219233
|
+
* const configResult = await loadConfigForSections(undefined, ['family', 'target', 'adapter', 'extensions']);
|
|
219234
|
+
* const config = configResult.assertOk();
|
|
219235
|
+
* const frameworkComponents = [config.target, config.adapter, ...(config.extensions ?? [])];
|
|
219236
|
+
*
|
|
219237
|
+
* // Validate and type-narrow components before passing to planner
|
|
219238
|
+
* const typedComponents = assertFrameworkComponentsCompatible(
|
|
219239
|
+
* config.family.familyId,
|
|
219240
|
+
* config.target.targetId,
|
|
219241
|
+
* frameworkComponents
|
|
219242
|
+
* );
|
|
219243
|
+
*
|
|
219244
|
+
* const planner = target.migrations.createPlanner(familyInstance);
|
|
219245
|
+
* planner.plan({ contract, schema, policy, frameworkComponents: typedComponents });
|
|
219246
|
+
* ```
|
|
219247
|
+
*/
|
|
219248
|
+
function assertFrameworkComponentsCompatible(expectedFamilyId, expectedTargetId, frameworkComponents) {
|
|
219249
|
+
for (let i = 0; i < frameworkComponents.length; i++) {
|
|
219250
|
+
const component = frameworkComponents[i];
|
|
219251
|
+
if (typeof component !== "object" || component === null) throw errorConfigValidation("frameworkComponents[]", { why: `Framework component at index ${i} must be an object` });
|
|
219252
|
+
const record = component;
|
|
219253
|
+
if (!Object.hasOwn(record, "kind")) throw errorConfigValidation("frameworkComponents[].kind", { why: `Framework component at index ${i} must have 'kind' property` });
|
|
219254
|
+
const kind = record["kind"];
|
|
219255
|
+
if (kind !== "target" && kind !== "adapter" && kind !== "extension" && kind !== "driver") throw errorConfigValidation("frameworkComponents[].kind", { why: `Framework component at index ${i} has invalid kind '${String(kind)}' (must be 'target', 'adapter', 'extension', or 'driver')` });
|
|
219256
|
+
if (!Object.hasOwn(record, "familyId")) throw errorConfigValidation("frameworkComponents[].familyId", { why: `Framework component at index ${i} (kind: ${String(kind)}) must have 'familyId' property` });
|
|
219257
|
+
const familyId = record["familyId"];
|
|
219258
|
+
if (familyId !== expectedFamilyId) throw errorConfigValidation("frameworkComponents[].familyId", { why: `Framework component at index ${i} (kind: ${String(kind)}) has familyId '${String(familyId)}' but expected '${expectedFamilyId}'` });
|
|
219259
|
+
if (!Object.hasOwn(record, "targetId")) throw errorConfigValidation("frameworkComponents[].targetId", { why: `Framework component at index ${i} (kind: ${String(kind)}) must have 'targetId' property` });
|
|
219260
|
+
const targetId = record["targetId"];
|
|
219261
|
+
if (targetId !== expectedTargetId) throw errorConfigValidation("frameworkComponents[].targetId", { why: `Framework component at index ${i} (kind: ${String(kind)}) has targetId '${String(targetId)}' but expected '${expectedTargetId}'` });
|
|
219262
|
+
}
|
|
219263
|
+
return frameworkComponents;
|
|
219264
|
+
}
|
|
219265
|
+
function isPlainObject(value) {
|
|
219266
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
219267
|
+
}
|
|
219268
|
+
function sortDeep(value) {
|
|
219269
|
+
if (Array.isArray(value)) return value.map(sortDeep);
|
|
219270
|
+
if (!isPlainObject(value)) return value;
|
|
219271
|
+
const entries = Object.entries(value).sort(([a], [b]) => a.localeCompare(b));
|
|
219272
|
+
const next = {};
|
|
219273
|
+
for (const [key, child] of entries) next[key] = sortDeep(child);
|
|
219274
|
+
return next;
|
|
219275
|
+
}
|
|
219276
|
+
function sortDeepTyped(value) {
|
|
219277
|
+
return sortDeep(value);
|
|
219278
|
+
}
|
|
219279
|
+
function extractExtensionPackMeta(component) {
|
|
219280
|
+
const { kind, id, version, capabilities, types } = component;
|
|
219281
|
+
const base = {
|
|
219282
|
+
kind,
|
|
219283
|
+
id,
|
|
219284
|
+
familyId: component.familyId,
|
|
219285
|
+
targetId: component.targetId,
|
|
219286
|
+
version
|
|
219287
|
+
};
|
|
219288
|
+
if (capabilities) base["capabilities"] = capabilities;
|
|
219289
|
+
if (types) if (types.codecTypes) {
|
|
219290
|
+
const { controlPlaneHooks: _, codecDescriptors: _cd, ...cleanedCodecTypes } = types.codecTypes;
|
|
219291
|
+
base["types"] = {
|
|
219292
|
+
...types,
|
|
219293
|
+
codecTypes: cleanedCodecTypes
|
|
219294
|
+
};
|
|
219295
|
+
} else base["types"] = types;
|
|
219296
|
+
return base;
|
|
219297
|
+
}
|
|
219298
|
+
/**
|
|
219299
|
+
* Enriches a raw contract with framework-derived metadata: capabilities from all component descriptors and extension pack metadata from extension descriptors. Produces deterministically sorted output.
|
|
219300
|
+
*/
|
|
219301
|
+
function enrichContract(ir, components) {
|
|
219302
|
+
const mergedCapabilities = mergeCapabilityMatrices(ir.capabilities, components);
|
|
219303
|
+
const extensionsMeta = {};
|
|
219304
|
+
for (const component of components) if (component.kind === "extension") extensionsMeta[component.id] = extractExtensionPackMeta(component);
|
|
219305
|
+
const extensions = Object.keys(extensionsMeta).length > 0 ? {
|
|
219306
|
+
...ir.extensions,
|
|
219307
|
+
...extensionsMeta
|
|
219308
|
+
} : ir.extensions;
|
|
219309
|
+
return {
|
|
219310
|
+
...ir,
|
|
219311
|
+
capabilities: sortDeepTyped(mergedCapabilities),
|
|
219312
|
+
extensions: sortDeepTyped(extensions)
|
|
219313
|
+
};
|
|
219314
|
+
}
|
|
219315
|
+
/**
|
|
218847
219316
|
* Minimal aggregate-loader projection that extracts `id` + `targetId`
|
|
218848
219317
|
* from raw extension pack descriptors **without invoking any
|
|
218849
219318
|
* `contractSpace` accessor**. Inspects the own-property descriptor so
|
|
@@ -218962,7 +219431,7 @@ function mapIntegrityViolations(violations) {
|
|
|
218962
219431
|
const contractUnreadable = violations.find((v) => v.kind === "contractUnreadable");
|
|
218963
219432
|
if (contractUnreadable && contractUnreadable.kind === "contractUnreadable") return contractSpaceViolationError(`Contract-space contract validation failed for "${contractUnreadable.spaceId}"`, {
|
|
218964
219433
|
why: contractUnreadable.detail,
|
|
218965
|
-
fix: "Re-emit the extension contract with `prisma-
|
|
219434
|
+
fix: "Re-emit the extension contract with `prisma-cli contract emit`, or fix the extension pack descriptor producing the invalid contract.",
|
|
218966
219435
|
violations: [contractUnreadable]
|
|
218967
219436
|
});
|
|
218968
219437
|
const structural = violations[0];
|
|
@@ -219036,6 +219505,20 @@ function stripOperations(operations) {
|
|
|
219036
219505
|
}));
|
|
219037
219506
|
}
|
|
219038
219507
|
/**
|
|
219508
|
+
* Content identity of a `db update` plan: what it does (the ordered display
|
|
219509
|
+
* operations) and where it lands (the destination storage hash). A
|
|
219510
|
+
* `DESTRUCTIVE_CHANGES` refusal names the refused plan by this hash, and the
|
|
219511
|
+
* apply that carries the consent back recomputes it to prove it is still
|
|
219512
|
+
* applying the plan that was consented to.
|
|
219513
|
+
*/
|
|
219514
|
+
function computePlanHash(plan) {
|
|
219515
|
+
const canonical = canonicalizeJson({
|
|
219516
|
+
operations: plan.operations,
|
|
219517
|
+
destination: { storageHash: plan.destination.storageHash }
|
|
219518
|
+
});
|
|
219519
|
+
return createHash("sha256").update(canonical).digest("hex");
|
|
219520
|
+
}
|
|
219521
|
+
/**
|
|
219039
219522
|
* Span id emitted via `onProgress` for the run phase. Stable
|
|
219040
219523
|
* identifier consumed by the structured-output renderer and by tests.
|
|
219041
219524
|
*/
|
|
@@ -219094,7 +219577,8 @@ async function runMigration(inputs) {
|
|
|
219094
219577
|
...runnerResult.failure.meta ?? {},
|
|
219095
219578
|
failingSpace: runnerResult.failure.failingSpace,
|
|
219096
219579
|
runnerErrorCode: runnerResult.failure.code
|
|
219097
|
-
}
|
|
219580
|
+
},
|
|
219581
|
+
cause: runnerResult.failure
|
|
219098
219582
|
});
|
|
219099
219583
|
}
|
|
219100
219584
|
onProgress?.({
|
|
@@ -219287,6 +219771,24 @@ async function executeRun(options) {
|
|
|
219287
219771
|
...ifDefined("warnings", plannerWarnings)
|
|
219288
219772
|
});
|
|
219289
219773
|
}
|
|
219774
|
+
if (options.consentedPlanHash !== void 0) {
|
|
219775
|
+
const planHash = computePlanHash({
|
|
219776
|
+
operations: stripOperations(orderedResolutions.flatMap((r) => r.entry.displayOps)),
|
|
219777
|
+
destination: appPlan.destination
|
|
219778
|
+
});
|
|
219779
|
+
if (planHash !== options.consentedPlanHash) return notOk({
|
|
219780
|
+
code: "CONSENT_PLAN_MISMATCH",
|
|
219781
|
+
summary: "The plan changed between consent and apply",
|
|
219782
|
+
why: "The plan recomputed for the consented apply is not the plan that was consented to, so applying it could destroy something nobody agreed to.",
|
|
219783
|
+
conflicts: void 0,
|
|
219784
|
+
meta: void 0,
|
|
219785
|
+
consentPlanMismatch: {
|
|
219786
|
+
consentedPlanHash: options.consentedPlanHash,
|
|
219787
|
+
planHash
|
|
219788
|
+
},
|
|
219789
|
+
...ifDefined("warnings", plannerWarnings)
|
|
219790
|
+
});
|
|
219791
|
+
}
|
|
219290
219792
|
const applied = await runMigration({
|
|
219291
219793
|
aggregate,
|
|
219292
219794
|
perSpacePlans: planResult.value.perSpace,
|
|
@@ -219303,7 +219805,8 @@ async function executeRun(options) {
|
|
|
219303
219805
|
summary: applied.failure.summary,
|
|
219304
219806
|
...ifDefined("why", applied.failure.why),
|
|
219305
219807
|
meta: applied.failure.meta,
|
|
219306
|
-
...ifDefined("warnings", plannerWarnings)
|
|
219808
|
+
...ifDefined("warnings", plannerWarnings),
|
|
219809
|
+
...ifDefined("cause", applied.failure.cause)
|
|
219307
219810
|
});
|
|
219308
219811
|
const aggregateOps = applied.value.orderedResolutions.flatMap((r) => r.entry.displayOps);
|
|
219309
219812
|
const summary = action === "dbInit" ? `Applied ${applied.value.totalOpsExecuted} operation(s) across ${applied.value.orderedResolutions.length} space(s), database signed` : applied.value.totalOpsExecuted === 0 ? `Database already matches contract across ${applied.value.orderedResolutions.length} space(s), signature updated` : `Applied ${applied.value.totalOpsExecuted} operation(s) across ${applied.value.orderedResolutions.length} space(s), signature updated`;
|
|
@@ -219426,7 +219929,8 @@ function buildRunnerFailure(args) {
|
|
|
219426
219929
|
why: args.why,
|
|
219427
219930
|
meta: args.meta,
|
|
219428
219931
|
conflicts: void 0,
|
|
219429
|
-
...ifDefined("warnings", args.warnings)
|
|
219932
|
+
...ifDefined("warnings", args.warnings),
|
|
219933
|
+
...ifDefined("cause", args.cause)
|
|
219430
219934
|
}));
|
|
219431
219935
|
}
|
|
219432
219936
|
/**
|
|
@@ -219482,13 +219986,14 @@ async function executeDbUpdate(options) {
|
|
|
219482
219986
|
action: "dbUpdate",
|
|
219483
219987
|
...ifDefined("onProgress", options.onProgress)
|
|
219484
219988
|
};
|
|
219485
|
-
if (options.mode === "apply" && !options.acceptDataLoss) {
|
|
219486
|
-
const
|
|
219487
|
-
if (
|
|
219989
|
+
if (options.mode === "apply" && !options.acceptDataLoss && options.consent === void 0) {
|
|
219990
|
+
const refusal = await guardDestructiveChanges(sharedInputs);
|
|
219991
|
+
if (refusal !== null) return refusal;
|
|
219488
219992
|
}
|
|
219489
219993
|
return await executeRun({
|
|
219490
219994
|
...sharedInputs,
|
|
219491
|
-
mode: options.mode
|
|
219995
|
+
mode: options.mode,
|
|
219996
|
+
...ifDefined("consentedPlanHash", options.consent?.planHash)
|
|
219492
219997
|
});
|
|
219493
219998
|
}
|
|
219494
219999
|
/**
|
|
@@ -219509,12 +220014,22 @@ async function guardDestructiveChanges(sharedInputs) {
|
|
|
219509
220014
|
label: op.label
|
|
219510
220015
|
}));
|
|
219511
220016
|
if (destructiveOps.length === 0) return null;
|
|
220017
|
+
const databaseName = await sharedInputs.driver.databaseName?.();
|
|
219512
220018
|
return notOk({
|
|
219513
220019
|
code: "DESTRUCTIVE_CHANGES",
|
|
219514
220020
|
summary: `Planned ${destructiveOps.length} destructive operation(s) that require confirmation`,
|
|
219515
|
-
why: "Destructive operations require
|
|
220021
|
+
why: "Destructive operations require explicit consent, which the caller has not given",
|
|
219516
220022
|
conflicts: void 0,
|
|
219517
|
-
meta:
|
|
220023
|
+
meta: void 0,
|
|
220024
|
+
destructiveChanges: {
|
|
220025
|
+
destructiveOperations: destructiveOps,
|
|
220026
|
+
databaseName,
|
|
220027
|
+
planHash: computePlanHash({
|
|
220028
|
+
operations: planResult.value.plan.operations,
|
|
220029
|
+
destination: planResult.value.destination
|
|
220030
|
+
})
|
|
220031
|
+
},
|
|
220032
|
+
...ifDefined("warnings", planResult.value.warnings)
|
|
219518
220033
|
});
|
|
219519
220034
|
}
|
|
219520
220035
|
/**
|
|
@@ -219538,9 +220053,9 @@ const SPAN_IDS = {
|
|
|
219538
220053
|
* schema introspection.
|
|
219539
220054
|
* 3. **Verify**: {@link verifyMigration} returns per-space `markerCheck` +
|
|
219540
220055
|
* per-space `schemaCheck` (each contract space verified against the full schema,
|
|
219541
|
-
* then scoped to its own contract space). Marker
|
|
219542
|
-
*
|
|
219543
|
-
*
|
|
220056
|
+
* then scoped to its own contract space). Marker drift is returned as the
|
|
220057
|
+
* success value's `markerDrift` envelope for callers to settle as a
|
|
220058
|
+
* finding. Verify results are returned to the caller verbatim.
|
|
219544
220059
|
*/
|
|
219545
220060
|
async function executeDbVerify(options) {
|
|
219546
220061
|
const { driver, familyInstance, onProgress, skipSchema, skipMarker } = options;
|
|
@@ -219661,17 +220176,14 @@ function finaliseVerifyResult(args) {
|
|
|
219661
220176
|
docsUrl: "https://pris.ly/contract-spaces"
|
|
219662
220177
|
}));
|
|
219663
220178
|
}
|
|
219664
|
-
const
|
|
219665
|
-
|
|
219666
|
-
emitVerifySpan(onProgress, "spanEndError");
|
|
219667
|
-
return notOk(markerError);
|
|
219668
|
-
}
|
|
219669
|
-
emitVerifySpan(onProgress, "spanEndOk");
|
|
220179
|
+
const markerDrift = skipMarker ? null : mapMarkerCheckFailures(aggregate.app.spaceId, verifyResult.value.markerCheck);
|
|
220180
|
+
emitVerifySpan(onProgress, markerDrift === null ? "spanEndOk" : "spanEndError");
|
|
219670
220181
|
return ok$1({
|
|
219671
220182
|
schemaResults: verifyResult.value.schemaCheck.perSpace,
|
|
219672
220183
|
unclaimed: verifyResult.value.schemaCheck.unclaimed,
|
|
219673
220184
|
spaceOrder: [aggregate.app.spaceId, ...aggregate.extensions.map((e) => e.spaceId)],
|
|
219674
|
-
appSpaceId: aggregate.app.spaceId
|
|
220185
|
+
appSpaceId: aggregate.app.spaceId,
|
|
220186
|
+
markerDrift
|
|
219675
220187
|
});
|
|
219676
220188
|
}
|
|
219677
220189
|
function buildSkippedSchemaResult(space) {
|
|
@@ -219704,7 +220216,7 @@ function mapMarkerCheckFailures(appSpaceId, section) {
|
|
|
219704
220216
|
violations.push({
|
|
219705
220217
|
kind: "hashMismatch",
|
|
219706
220218
|
spaceId,
|
|
219707
|
-
remediation: spaceId === appSpaceId ? "Run `prisma-
|
|
220219
|
+
remediation: spaceId === appSpaceId ? "Run `prisma-cli db update` to advance the marker, or roll the database back to the recorded hash." : `Apply on-disk migrations under \`migrations/${spaceId}/\` to advance the marker, or remove the conflicting marker row.`
|
|
219708
220220
|
});
|
|
219709
220221
|
continue;
|
|
219710
220222
|
}
|
|
@@ -219717,7 +220229,7 @@ function mapMarkerCheckFailures(appSpaceId, section) {
|
|
|
219717
220229
|
for (const orphan of section.orphanMarkers) violations.push({
|
|
219718
220230
|
kind: "orphanMarker",
|
|
219719
220231
|
spaceId: orphan.spaceId,
|
|
219720
|
-
remediation: `Add the corresponding extension to \`extensions\` in \`prisma
|
|
220232
|
+
remediation: `Add the corresponding extension to \`extensions\` in \`prisma.config.ts\`, or delete the orphan marker row for "${orphan.spaceId}".`
|
|
219721
220233
|
});
|
|
219722
220234
|
if (violations.length === 0) return null;
|
|
219723
220235
|
const lines = violations.map((v) => `- [${v.kind}] ${v.spaceId}: ${v.remediation}`);
|
|
@@ -219849,7 +220361,8 @@ async function executeMigrate(options) {
|
|
|
219849
220361
|
code: "RUNNER_FAILED",
|
|
219850
220362
|
summary: applied.failure.summary,
|
|
219851
220363
|
why: applied.failure.why,
|
|
219852
|
-
meta: applied.failure.meta
|
|
220364
|
+
meta: applied.failure.meta,
|
|
220365
|
+
...ifDefined("cause", applied.failure.cause)
|
|
219853
220366
|
});
|
|
219854
220367
|
const orderedAll = canonicalOrder.filter((spaceId) => perSpacePlans.has(spaceId) || atHeadResolutions.has(spaceId)).map((spaceId) => {
|
|
219855
220368
|
if (perSpacePlans.has(spaceId)) {
|
|
@@ -220374,6 +220887,7 @@ var ControlClientImpl = class {
|
|
|
220374
220887
|
targetId: this.options.target.targetId,
|
|
220375
220888
|
extensions: this.options.extensions ?? [],
|
|
220376
220889
|
...ifDefined("acceptDataLoss", options.acceptDataLoss),
|
|
220890
|
+
...ifDefined("consent", options.consent),
|
|
220377
220891
|
...ifDefined("onProgress", onProgress)
|
|
220378
220892
|
});
|
|
220379
220893
|
}
|
|
@@ -220627,7 +221141,7 @@ function createPostgresControlClient(options = {}) {
|
|
|
220627
221141
|
...ifDefined("extensions", options.extensions)
|
|
220628
221142
|
});
|
|
220629
221143
|
}
|
|
220630
|
-
var version = "0.
|
|
221144
|
+
var version = "0.10.0-dev.2";
|
|
220631
221145
|
var migration_default = {
|
|
220632
221146
|
from: null,
|
|
220633
221147
|
to: "6bbd4dc1c19c8aa5e0d60c9755e0f8ea07ba1c01d20c48cf3aa7226e4ee7d33f",
|