@prisma-next/family-sql 0.14.0-dev.39 → 0.14.0-dev.40
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/contract-to-schema-ir-S-evq8E6.mjs +264 -0
- package/dist/contract-to-schema-ir-S-evq8E6.mjs.map +1 -0
- package/dist/{control-adapter-B2q9WN1V.d.mts → control-adapter-DHYFuOBy.d.mts} +14 -17
- package/dist/{control-adapter-B2q9WN1V.d.mts.map → control-adapter-DHYFuOBy.d.mts.map} +1 -1
- package/dist/control-adapter.d.mts +1 -1
- package/dist/control.d.mts +17 -2
- package/dist/control.d.mts.map +1 -1
- package/dist/control.mjs +42 -943
- package/dist/control.mjs.map +1 -1
- package/dist/{schema-verify.d.mts → diff.d.mts} +4 -4
- package/dist/diff.d.mts.map +1 -0
- package/dist/{verify-sql-schema-CEY7b78t.mjs → diff.mjs} +154 -244
- package/dist/diff.mjs.map +1 -0
- package/dist/migration.d.mts +1 -1
- package/dist/psl-infer.d.mts +80 -0
- package/dist/psl-infer.d.mts.map +1 -0
- package/dist/psl-infer.mjs +334 -0
- package/dist/psl-infer.mjs.map +1 -0
- package/dist/{verify-sql-schema-B8uEjw2s.d.mts → sql-schema-diff-6z36dZt6.d.mts} +43 -4
- package/dist/sql-schema-diff-6z36dZt6.d.mts.map +1 -0
- package/dist/{types-BxsFkHYv.d.mts → types-CkOIJXxU.d.mts} +83 -16
- package/dist/types-CkOIJXxU.d.mts.map +1 -0
- package/package.json +23 -22
- package/src/core/control-adapter.ts +12 -24
- package/src/core/control-instance.ts +113 -45
- package/src/core/{schema-verify/verify-sql-schema.ts → diff/sql-schema-diff.ts} +196 -8
- package/src/core/{schema-verify → diff}/verify-helpers.ts +12 -0
- package/src/core/migrations/contract-to-schema-ir.ts +48 -13
- package/src/core/migrations/field-event-planner.ts +3 -8
- package/src/core/migrations/schema-differ.ts +40 -0
- package/src/core/migrations/types.ts +43 -2
- package/src/core/psl-contract-infer/printer-config.ts +0 -6
- package/src/exports/control.ts +1 -0
- package/src/exports/diff.ts +18 -0
- package/src/exports/psl-infer.ts +36 -0
- package/dist/schema-verify.d.mts.map +0 -1
- package/dist/schema-verify.mjs +0 -2
- package/dist/types-BxsFkHYv.d.mts.map +0 -1
- package/dist/verify-sql-schema-B8uEjw2s.d.mts.map +0 -1
- package/dist/verify-sql-schema-CEY7b78t.mjs.map +0 -1
- package/src/core/psl-contract-infer/postgres-default-mapping.ts +0 -16
- package/src/core/psl-contract-infer/postgres-type-map.ts +0 -157
- package/src/core/psl-contract-infer/sql-schema-ir-to-psl-ast.ts +0 -795
- package/src/exports/schema-verify.ts +0 -18
- /package/src/core/{schema-verify → diff}/control-verify-emit.ts +0 -0
- /package/src/core/{schema-verify → diff}/verifier-disposition.ts +0 -0
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
//#region src/core/psl-contract-infer/default-mapping.ts
|
|
2
|
+
const DEFAULT_FUNCTION_ATTRIBUTES = {
|
|
3
|
+
"autoincrement()": "@default(autoincrement())",
|
|
4
|
+
"now()": "@default(now())"
|
|
5
|
+
};
|
|
6
|
+
function mapDefault(columnDefault, options) {
|
|
7
|
+
switch (columnDefault.kind) {
|
|
8
|
+
case "literal": return { attribute: `@default(${formatLiteralValue(columnDefault.value)})` };
|
|
9
|
+
case "function": {
|
|
10
|
+
const attribute = options?.functionAttributes?.[columnDefault.expression] ?? DEFAULT_FUNCTION_ATTRIBUTES[columnDefault.expression] ?? options?.fallbackFunctionAttribute?.(columnDefault.expression);
|
|
11
|
+
return attribute ? { attribute } : { comment: `// Raw default: ${columnDefault.expression.replace(/[\r\n]+/g, " ")}` };
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
function formatLiteralValue(value) {
|
|
16
|
+
if (value === null) return "null";
|
|
17
|
+
switch (typeof value) {
|
|
18
|
+
case "boolean":
|
|
19
|
+
case "number": return String(value);
|
|
20
|
+
case "string": return quoteString(value);
|
|
21
|
+
default: return quoteString(JSON.stringify(value));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function quoteString(str) {
|
|
25
|
+
return `"${escapeString(str)}"`;
|
|
26
|
+
}
|
|
27
|
+
function escapeString(str) {
|
|
28
|
+
return JSON.stringify(str).slice(1, -1);
|
|
29
|
+
}
|
|
30
|
+
//#endregion
|
|
31
|
+
//#region src/core/psl-contract-infer/name-transforms.ts
|
|
32
|
+
const PSL_RESERVED_WORDS = new Set([
|
|
33
|
+
"model",
|
|
34
|
+
"enum",
|
|
35
|
+
"types",
|
|
36
|
+
"type",
|
|
37
|
+
"generator",
|
|
38
|
+
"datasource"
|
|
39
|
+
]);
|
|
40
|
+
const IDENTIFIER_PART_PATTERN = /[A-Za-z0-9]+/g;
|
|
41
|
+
function hasSeparators(input) {
|
|
42
|
+
return /[^A-Za-z0-9]/.test(input);
|
|
43
|
+
}
|
|
44
|
+
function extractIdentifierParts(input) {
|
|
45
|
+
return input.match(IDENTIFIER_PART_PATTERN) ?? [];
|
|
46
|
+
}
|
|
47
|
+
function createSyntheticIdentifier(input) {
|
|
48
|
+
let hash = 2166136261;
|
|
49
|
+
for (const char of input) {
|
|
50
|
+
hash ^= char.codePointAt(0) ?? 0;
|
|
51
|
+
hash = Math.imul(hash, 16777619);
|
|
52
|
+
}
|
|
53
|
+
return `x${(hash >>> 0).toString(16)}`;
|
|
54
|
+
}
|
|
55
|
+
function sanitizeIdentifierCharacters(input) {
|
|
56
|
+
const sanitized = input.replace(/[^\w]/g, "");
|
|
57
|
+
return sanitized.length > 0 ? sanitized : createSyntheticIdentifier(input);
|
|
58
|
+
}
|
|
59
|
+
function capitalize(word) {
|
|
60
|
+
return word.charAt(0).toUpperCase() + word.slice(1);
|
|
61
|
+
}
|
|
62
|
+
function snakeToPascalCase(input) {
|
|
63
|
+
const parts = extractIdentifierParts(input);
|
|
64
|
+
if (parts.length === 0) return capitalize(sanitizeIdentifierCharacters(input));
|
|
65
|
+
return parts.map(capitalize).join("");
|
|
66
|
+
}
|
|
67
|
+
function snakeToCamelCase(input) {
|
|
68
|
+
const parts = extractIdentifierParts(input);
|
|
69
|
+
if (parts.length === 0) return sanitizeIdentifierCharacters(input);
|
|
70
|
+
const [firstPart = input, ...rest] = parts;
|
|
71
|
+
return firstPart.charAt(0).toLowerCase() + firstPart.slice(1) + rest.map(capitalize).join("");
|
|
72
|
+
}
|
|
73
|
+
function needsEscaping(name) {
|
|
74
|
+
return PSL_RESERVED_WORDS.has(name.toLowerCase()) || /^\d/.test(name);
|
|
75
|
+
}
|
|
76
|
+
function escapeName(name) {
|
|
77
|
+
return `_${name}`;
|
|
78
|
+
}
|
|
79
|
+
function escapeIfNeeded(name) {
|
|
80
|
+
return needsEscaping(name) ? escapeName(name) : name;
|
|
81
|
+
}
|
|
82
|
+
function toModelName(tableName) {
|
|
83
|
+
let name;
|
|
84
|
+
if (hasSeparators(tableName)) name = snakeToPascalCase(tableName);
|
|
85
|
+
else name = tableName.charAt(0).toUpperCase() + tableName.slice(1);
|
|
86
|
+
if (needsEscaping(name)) return {
|
|
87
|
+
name: escapeName(name),
|
|
88
|
+
map: tableName
|
|
89
|
+
};
|
|
90
|
+
if (name !== tableName) return {
|
|
91
|
+
name,
|
|
92
|
+
map: tableName
|
|
93
|
+
};
|
|
94
|
+
return { name };
|
|
95
|
+
}
|
|
96
|
+
function toFieldName(columnName) {
|
|
97
|
+
let name;
|
|
98
|
+
if (hasSeparators(columnName)) name = snakeToCamelCase(columnName);
|
|
99
|
+
else name = columnName.charAt(0).toLowerCase() + columnName.slice(1);
|
|
100
|
+
if (needsEscaping(name)) return {
|
|
101
|
+
name: escapeName(name),
|
|
102
|
+
map: columnName
|
|
103
|
+
};
|
|
104
|
+
if (name !== columnName) return {
|
|
105
|
+
name,
|
|
106
|
+
map: columnName
|
|
107
|
+
};
|
|
108
|
+
return { name };
|
|
109
|
+
}
|
|
110
|
+
function toEnumName(pgTypeName) {
|
|
111
|
+
let name;
|
|
112
|
+
if (hasSeparators(pgTypeName)) name = snakeToPascalCase(pgTypeName);
|
|
113
|
+
else name = pgTypeName.charAt(0).toUpperCase() + pgTypeName.slice(1);
|
|
114
|
+
if (needsEscaping(name)) return {
|
|
115
|
+
name: escapeName(name),
|
|
116
|
+
map: pgTypeName
|
|
117
|
+
};
|
|
118
|
+
if (name !== pgTypeName) return {
|
|
119
|
+
name,
|
|
120
|
+
map: pgTypeName
|
|
121
|
+
};
|
|
122
|
+
return { name };
|
|
123
|
+
}
|
|
124
|
+
function pluralize(word) {
|
|
125
|
+
if (word.endsWith("s") || word.endsWith("x") || word.endsWith("z") || word.endsWith("ch") || word.endsWith("sh")) return `${word}es`;
|
|
126
|
+
if (word.endsWith("y") && !/[aeiou]y$/i.test(word)) return `${word.slice(0, -1)}ies`;
|
|
127
|
+
return `${word}s`;
|
|
128
|
+
}
|
|
129
|
+
function deriveRelationFieldName(fkColumns, referencedTableName) {
|
|
130
|
+
if (fkColumns.length === 1) {
|
|
131
|
+
const [col = referencedTableName] = fkColumns;
|
|
132
|
+
const stripped = col.replace(/_id$/i, "").replace(/Id$/, "");
|
|
133
|
+
if (stripped.length > 0 && stripped !== col) return escapeIfNeeded(snakeToCamelCase(stripped));
|
|
134
|
+
return escapeIfNeeded(snakeToCamelCase(referencedTableName));
|
|
135
|
+
}
|
|
136
|
+
return escapeIfNeeded(snakeToCamelCase(referencedTableName));
|
|
137
|
+
}
|
|
138
|
+
function deriveBackRelationFieldName(childModelName, isOneToOne) {
|
|
139
|
+
const base = childModelName.charAt(0).toLowerCase() + childModelName.slice(1);
|
|
140
|
+
return isOneToOne ? base : pluralize(base);
|
|
141
|
+
}
|
|
142
|
+
function toNamedTypeName(columnName) {
|
|
143
|
+
let name;
|
|
144
|
+
if (hasSeparators(columnName)) name = snakeToPascalCase(columnName);
|
|
145
|
+
else name = columnName.charAt(0).toUpperCase() + columnName.slice(1);
|
|
146
|
+
return escapeIfNeeded(name);
|
|
147
|
+
}
|
|
148
|
+
//#endregion
|
|
149
|
+
//#region src/core/psl-contract-infer/raw-default-parser.ts
|
|
150
|
+
const NEXTVAL_PATTERN = /^nextval\s*\(/i;
|
|
151
|
+
const NOW_FUNCTION_PATTERN = /^(now\s*\(\s*\)|CURRENT_TIMESTAMP)$/i;
|
|
152
|
+
const CLOCK_TIMESTAMP_PATTERN = /^clock_timestamp\s*\(\s*\)$/i;
|
|
153
|
+
const TIMESTAMP_CAST_SUFFIX = /::timestamp(?:tz|\s+(?:with|without)\s+time\s+zone)?$/i;
|
|
154
|
+
const TEXT_CAST_SUFFIX = /::text$/i;
|
|
155
|
+
const NOW_LITERAL_PATTERN = /^'now'$/i;
|
|
156
|
+
const UUID_PATTERN = /^gen_random_uuid\s*\(\s*\)$/i;
|
|
157
|
+
const UUID_OSSP_PATTERN = /^uuid_generate_v4\s*\(\s*\)$/i;
|
|
158
|
+
const NULL_PATTERN = /^NULL(?:::.+)?$/i;
|
|
159
|
+
const TRUE_PATTERN = /^true$/i;
|
|
160
|
+
const FALSE_PATTERN = /^false$/i;
|
|
161
|
+
const NUMERIC_PATTERN = /^-?\d+(\.\d+)?$/;
|
|
162
|
+
const JSON_CAST_SUFFIX = /::jsonb?$/i;
|
|
163
|
+
const STRING_LITERAL_PATTERN = /^'((?:[^']|'')*)'(?:::(?:"[^"]+"|[\w\s]+)(?:\(\d+\))?)?$/;
|
|
164
|
+
function canonicalizeTimestampDefault(expr) {
|
|
165
|
+
if (NOW_FUNCTION_PATTERN.test(expr)) return "now()";
|
|
166
|
+
if (CLOCK_TIMESTAMP_PATTERN.test(expr)) return "clock_timestamp()";
|
|
167
|
+
if (!TIMESTAMP_CAST_SUFFIX.test(expr)) return void 0;
|
|
168
|
+
let inner = expr.replace(TIMESTAMP_CAST_SUFFIX, "").trim();
|
|
169
|
+
if (inner.startsWith("(") && inner.endsWith(")")) inner = inner.slice(1, -1).trim();
|
|
170
|
+
if (NOW_FUNCTION_PATTERN.test(inner)) return "now()";
|
|
171
|
+
if (CLOCK_TIMESTAMP_PATTERN.test(inner)) return "clock_timestamp()";
|
|
172
|
+
inner = inner.replace(TEXT_CAST_SUFFIX, "").trim();
|
|
173
|
+
if (NOW_LITERAL_PATTERN.test(inner)) return "now()";
|
|
174
|
+
}
|
|
175
|
+
function parseRawDefault(rawDefault, nativeType) {
|
|
176
|
+
const trimmed = rawDefault.trim();
|
|
177
|
+
const normalizedType = nativeType?.toLowerCase();
|
|
178
|
+
if (NEXTVAL_PATTERN.test(trimmed)) return {
|
|
179
|
+
kind: "function",
|
|
180
|
+
expression: "autoincrement()"
|
|
181
|
+
};
|
|
182
|
+
const canonicalTimestamp = canonicalizeTimestampDefault(trimmed);
|
|
183
|
+
if (canonicalTimestamp) return {
|
|
184
|
+
kind: "function",
|
|
185
|
+
expression: canonicalTimestamp
|
|
186
|
+
};
|
|
187
|
+
if (UUID_PATTERN.test(trimmed) || UUID_OSSP_PATTERN.test(trimmed)) return {
|
|
188
|
+
kind: "function",
|
|
189
|
+
expression: "gen_random_uuid()"
|
|
190
|
+
};
|
|
191
|
+
if (NULL_PATTERN.test(trimmed)) return {
|
|
192
|
+
kind: "literal",
|
|
193
|
+
value: null
|
|
194
|
+
};
|
|
195
|
+
if (TRUE_PATTERN.test(trimmed)) return {
|
|
196
|
+
kind: "literal",
|
|
197
|
+
value: true
|
|
198
|
+
};
|
|
199
|
+
if (FALSE_PATTERN.test(trimmed)) return {
|
|
200
|
+
kind: "literal",
|
|
201
|
+
value: false
|
|
202
|
+
};
|
|
203
|
+
if (NUMERIC_PATTERN.test(trimmed)) return {
|
|
204
|
+
kind: "literal",
|
|
205
|
+
value: Number(trimmed)
|
|
206
|
+
};
|
|
207
|
+
const stringMatch = trimmed.match(STRING_LITERAL_PATTERN);
|
|
208
|
+
if (stringMatch?.[1] !== void 0) {
|
|
209
|
+
const unescaped = stringMatch[1].replace(/''/g, "'");
|
|
210
|
+
if (normalizedType === "json" || normalizedType === "jsonb") {
|
|
211
|
+
if (JSON_CAST_SUFFIX.test(trimmed)) return {
|
|
212
|
+
kind: "function",
|
|
213
|
+
expression: trimmed
|
|
214
|
+
};
|
|
215
|
+
try {
|
|
216
|
+
return {
|
|
217
|
+
kind: "literal",
|
|
218
|
+
value: JSON.parse(unescaped)
|
|
219
|
+
};
|
|
220
|
+
} catch {}
|
|
221
|
+
}
|
|
222
|
+
return {
|
|
223
|
+
kind: "literal",
|
|
224
|
+
value: unescaped
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
return {
|
|
228
|
+
kind: "function",
|
|
229
|
+
expression: trimmed
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
//#endregion
|
|
233
|
+
//#region src/core/psl-contract-infer/relation-inference.ts
|
|
234
|
+
const DEFAULT_ON_DELETE = "noAction";
|
|
235
|
+
const DEFAULT_ON_UPDATE = "noAction";
|
|
236
|
+
const REFERENTIAL_ACTION_PSL = {
|
|
237
|
+
noAction: "NoAction",
|
|
238
|
+
restrict: "Restrict",
|
|
239
|
+
cascade: "Cascade",
|
|
240
|
+
setNull: "SetNull",
|
|
241
|
+
setDefault: "SetDefault"
|
|
242
|
+
};
|
|
243
|
+
function inferRelations(tables, modelNameMap) {
|
|
244
|
+
const relationsByTable = /* @__PURE__ */ new Map();
|
|
245
|
+
const fkCountByPair = /* @__PURE__ */ new Map();
|
|
246
|
+
for (const table of Object.values(tables)) for (const fk of table.foreignKeys) {
|
|
247
|
+
const pairKey = `${table.name}→${fk.referencedTable}`;
|
|
248
|
+
fkCountByPair.set(pairKey, (fkCountByPair.get(pairKey) ?? 0) + 1);
|
|
249
|
+
}
|
|
250
|
+
const usedFieldNames = /* @__PURE__ */ new Map();
|
|
251
|
+
for (const table of Object.values(tables)) {
|
|
252
|
+
const names = /* @__PURE__ */ new Set();
|
|
253
|
+
for (const col of Object.values(table.columns)) names.add(col.name);
|
|
254
|
+
usedFieldNames.set(table.name, names);
|
|
255
|
+
}
|
|
256
|
+
for (const table of Object.values(tables)) for (const fk of table.foreignKeys) {
|
|
257
|
+
const childTableName = table.name;
|
|
258
|
+
const parentTableName = fk.referencedTable;
|
|
259
|
+
const childUsed = usedFieldNames.get(childTableName);
|
|
260
|
+
const childModelName = modelNameMap.get(childTableName) ?? childTableName;
|
|
261
|
+
const parentModelName = modelNameMap.get(parentTableName) ?? parentTableName;
|
|
262
|
+
const pairKey = `${childTableName}→${parentTableName}`;
|
|
263
|
+
const isSelfRelation = childTableName === parentTableName;
|
|
264
|
+
const needsRelationName = fkCountByPair.get(pairKey) > 1 || isSelfRelation;
|
|
265
|
+
const isOneToOne = detectOneToOne(fk, table);
|
|
266
|
+
const childRelFieldName = resolveUniqueFieldName(deriveRelationFieldName(fk.columns, parentTableName), childUsed, parentModelName);
|
|
267
|
+
const relationName = needsRelationName ? deriveRelationName(fk, childRelFieldName, parentModelName, isSelfRelation) : void 0;
|
|
268
|
+
addRelationField(relationsByTable, childTableName, buildChildRelationField(childRelFieldName, parentModelName, fk, fk.columns.some((columnName) => table.columns[columnName]?.nullable ?? false), relationName));
|
|
269
|
+
childUsed.add(childRelFieldName);
|
|
270
|
+
const parentUsed = usedFieldNames.get(parentTableName) ?? /* @__PURE__ */ new Set();
|
|
271
|
+
usedFieldNames.set(parentTableName, parentUsed);
|
|
272
|
+
const backRelFieldName = resolveUniqueFieldName(deriveBackRelationFieldName(childModelName, isOneToOne), parentUsed, childModelName);
|
|
273
|
+
addRelationField(relationsByTable, parentTableName, {
|
|
274
|
+
fieldName: backRelFieldName,
|
|
275
|
+
typeName: childModelName,
|
|
276
|
+
optional: isOneToOne,
|
|
277
|
+
list: !isOneToOne,
|
|
278
|
+
relationName
|
|
279
|
+
});
|
|
280
|
+
parentUsed.add(backRelFieldName);
|
|
281
|
+
}
|
|
282
|
+
return { relationsByTable };
|
|
283
|
+
}
|
|
284
|
+
function detectOneToOne(fk, table) {
|
|
285
|
+
const fkCols = [...fk.columns].sort();
|
|
286
|
+
if (table.primaryKey) {
|
|
287
|
+
const pkCols = [...table.primaryKey.columns].sort();
|
|
288
|
+
if (pkCols.length === fkCols.length && pkCols.every((c, i) => c === fkCols[i])) return true;
|
|
289
|
+
}
|
|
290
|
+
for (const unique of table.uniques) {
|
|
291
|
+
const uniqueCols = [...unique.columns].sort();
|
|
292
|
+
if (uniqueCols.length === fkCols.length && uniqueCols.every((c, i) => c === fkCols[i])) return true;
|
|
293
|
+
}
|
|
294
|
+
return false;
|
|
295
|
+
}
|
|
296
|
+
function deriveRelationName(fk, childRelationFieldName, parentModelName, isSelfRelation) {
|
|
297
|
+
if (fk.name) return fk.name;
|
|
298
|
+
if (isSelfRelation) return `${childRelationFieldName.charAt(0).toUpperCase() + childRelationFieldName.slice(1)}${pluralize(parentModelName)}`;
|
|
299
|
+
return fk.columns.join("_");
|
|
300
|
+
}
|
|
301
|
+
function buildChildRelationField(fieldName, parentModelName, fk, optional, relationName) {
|
|
302
|
+
const onDelete = fk.onDelete && fk.onDelete !== DEFAULT_ON_DELETE ? fk.onDelete : void 0;
|
|
303
|
+
const onUpdate = fk.onUpdate && fk.onUpdate !== DEFAULT_ON_UPDATE ? fk.onUpdate : void 0;
|
|
304
|
+
return {
|
|
305
|
+
fieldName,
|
|
306
|
+
typeName: parentModelName,
|
|
307
|
+
referencedTableName: fk.referencedTable,
|
|
308
|
+
optional,
|
|
309
|
+
list: false,
|
|
310
|
+
relationName,
|
|
311
|
+
fkName: fk.name,
|
|
312
|
+
fields: fk.columns,
|
|
313
|
+
references: fk.referencedColumns,
|
|
314
|
+
onDelete: onDelete ? REFERENTIAL_ACTION_PSL[onDelete] : void 0,
|
|
315
|
+
onUpdate: onUpdate ? REFERENTIAL_ACTION_PSL[onUpdate] : void 0
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
function resolveUniqueFieldName(desired, usedNames, fallbackSuffix) {
|
|
319
|
+
if (!usedNames.has(desired)) return desired;
|
|
320
|
+
const withSuffix = `${desired}${fallbackSuffix}`;
|
|
321
|
+
if (!usedNames.has(withSuffix)) return withSuffix;
|
|
322
|
+
let counter = 2;
|
|
323
|
+
while (usedNames.has(`${desired}${counter}`)) counter++;
|
|
324
|
+
return `${desired}${counter}`;
|
|
325
|
+
}
|
|
326
|
+
function addRelationField(map, tableName, field) {
|
|
327
|
+
const existing = map.get(tableName);
|
|
328
|
+
if (existing) existing.push(field);
|
|
329
|
+
else map.set(tableName, [field]);
|
|
330
|
+
}
|
|
331
|
+
//#endregion
|
|
332
|
+
export { deriveBackRelationFieldName, deriveRelationFieldName, inferRelations, mapDefault, parseRawDefault, pluralize, toEnumName, toFieldName, toModelName, toNamedTypeName };
|
|
333
|
+
|
|
334
|
+
//# sourceMappingURL=psl-infer.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"psl-infer.mjs","names":[],"sources":["../src/core/psl-contract-infer/default-mapping.ts","../src/core/psl-contract-infer/name-transforms.ts","../src/core/psl-contract-infer/raw-default-parser.ts","../src/core/psl-contract-infer/relation-inference.ts"],"sourcesContent":["import type { ColumnDefault } from '@prisma-next/contract/types';\n\nconst DEFAULT_FUNCTION_ATTRIBUTES: Readonly<Record<string, string>> = {\n 'autoincrement()': '@default(autoincrement())',\n 'now()': '@default(now())',\n};\n\nexport interface DefaultMappingOptions {\n readonly functionAttributes?: Readonly<Record<string, string>>;\n readonly fallbackFunctionAttribute?: ((expression: string) => string | undefined) | undefined;\n}\n\nexport type DefaultMappingResult = { readonly attribute: string } | { readonly comment: string };\n\nexport function mapDefault(\n columnDefault: ColumnDefault,\n options?: DefaultMappingOptions,\n): DefaultMappingResult {\n switch (columnDefault.kind) {\n case 'literal':\n return { attribute: `@default(${formatLiteralValue(columnDefault.value)})` };\n case 'function': {\n const attribute =\n options?.functionAttributes?.[columnDefault.expression] ??\n DEFAULT_FUNCTION_ATTRIBUTES[columnDefault.expression] ??\n options?.fallbackFunctionAttribute?.(columnDefault.expression);\n return attribute\n ? { attribute }\n : { comment: `// Raw default: ${columnDefault.expression.replace(/[\\r\\n]+/g, ' ')}` };\n }\n }\n}\n\nfunction formatLiteralValue(value: unknown): string {\n if (value === null) {\n return 'null';\n }\n\n switch (typeof value) {\n case 'boolean':\n case 'number':\n return String(value);\n case 'string':\n return quoteString(value);\n default:\n return quoteString(JSON.stringify(value));\n }\n}\n\nfunction quoteString(str: string): string {\n return `\"${escapeString(str)}\"`;\n}\n\nfunction escapeString(str: string): string {\n return JSON.stringify(str).slice(1, -1);\n}\n","const PSL_RESERVED_WORDS = new Set(['model', 'enum', 'types', 'type', 'generator', 'datasource']);\n\nconst IDENTIFIER_PART_PATTERN = /[A-Za-z0-9]+/g;\n\ntype NameResult = {\n readonly name: string;\n readonly map?: string;\n};\n\nfunction hasSeparators(input: string): boolean {\n return /[^A-Za-z0-9]/.test(input);\n}\n\nfunction extractIdentifierParts(input: string): string[] {\n return input.match(IDENTIFIER_PART_PATTERN) ?? [];\n}\n\nfunction createSyntheticIdentifier(input: string): string {\n let hash = 2166136261;\n\n for (const char of input) {\n hash ^= char.codePointAt(0) ?? 0;\n hash = Math.imul(hash, 16777619);\n }\n\n return `x${(hash >>> 0).toString(16)}`;\n}\n\nfunction sanitizeIdentifierCharacters(input: string): string {\n const sanitized = input.replace(/[^\\w]/g, '');\n return sanitized.length > 0 ? sanitized : createSyntheticIdentifier(input);\n}\n\nfunction capitalize(word: string): string {\n return word.charAt(0).toUpperCase() + word.slice(1);\n}\n\nfunction snakeToPascalCase(input: string): string {\n const parts = extractIdentifierParts(input);\n if (parts.length === 0) {\n return capitalize(sanitizeIdentifierCharacters(input));\n }\n return parts.map(capitalize).join('');\n}\n\nfunction snakeToCamelCase(input: string): string {\n const parts = extractIdentifierParts(input);\n if (parts.length === 0) {\n return sanitizeIdentifierCharacters(input);\n }\n const [firstPart = input, ...rest] = parts;\n return firstPart.charAt(0).toLowerCase() + firstPart.slice(1) + rest.map(capitalize).join('');\n}\n\nfunction needsEscaping(name: string): boolean {\n return PSL_RESERVED_WORDS.has(name.toLowerCase()) || /^\\d/.test(name);\n}\n\nfunction escapeName(name: string): string {\n return `_${name}`;\n}\n\nfunction escapeIfNeeded(name: string): string {\n return needsEscaping(name) ? escapeName(name) : name;\n}\n\nexport function toModelName(tableName: string): NameResult {\n let name: string;\n\n if (hasSeparators(tableName)) {\n name = snakeToPascalCase(tableName);\n } else {\n name = tableName.charAt(0).toUpperCase() + tableName.slice(1);\n }\n\n if (needsEscaping(name)) {\n const escaped = escapeName(name);\n return { name: escaped, map: tableName };\n }\n\n if (name !== tableName) {\n return { name, map: tableName };\n }\n\n return { name };\n}\n\nexport function toFieldName(columnName: string): NameResult {\n let name: string;\n\n if (hasSeparators(columnName)) {\n name = snakeToCamelCase(columnName);\n } else {\n name = columnName.charAt(0).toLowerCase() + columnName.slice(1);\n }\n\n if (needsEscaping(name)) {\n const escaped = escapeName(name);\n return { name: escaped, map: columnName };\n }\n\n if (name !== columnName) {\n return { name, map: columnName };\n }\n\n return { name };\n}\n\nexport function toEnumName(pgTypeName: string): NameResult {\n let name: string;\n\n if (hasSeparators(pgTypeName)) {\n name = snakeToPascalCase(pgTypeName);\n } else {\n name = pgTypeName.charAt(0).toUpperCase() + pgTypeName.slice(1);\n }\n\n if (needsEscaping(name)) {\n const escaped = escapeName(name);\n return { name: escaped, map: pgTypeName };\n }\n\n if (name !== pgTypeName) {\n return { name, map: pgTypeName };\n }\n\n return { name };\n}\n\nexport function pluralize(word: string): string {\n if (\n word.endsWith('s') ||\n word.endsWith('x') ||\n word.endsWith('z') ||\n word.endsWith('ch') ||\n word.endsWith('sh')\n ) {\n return `${word}es`;\n }\n if (word.endsWith('y') && !/[aeiou]y$/i.test(word)) {\n return `${word.slice(0, -1)}ies`;\n }\n return `${word}s`;\n}\n\nexport function deriveRelationFieldName(\n fkColumns: readonly string[],\n referencedTableName: string,\n): string {\n if (fkColumns.length === 1) {\n const [col = referencedTableName] = fkColumns;\n const stripped = col.replace(/_id$/i, '').replace(/Id$/, '');\n\n if (stripped.length > 0 && stripped !== col) {\n return escapeIfNeeded(snakeToCamelCase(stripped));\n }\n return escapeIfNeeded(snakeToCamelCase(referencedTableName));\n }\n\n return escapeIfNeeded(snakeToCamelCase(referencedTableName));\n}\n\nexport function deriveBackRelationFieldName(childModelName: string, isOneToOne: boolean): string {\n const base = childModelName.charAt(0).toLowerCase() + childModelName.slice(1);\n return isOneToOne ? base : pluralize(base);\n}\n\nexport function toNamedTypeName(columnName: string): string {\n let name: string;\n\n if (hasSeparators(columnName)) {\n name = snakeToPascalCase(columnName);\n } else {\n name = columnName.charAt(0).toUpperCase() + columnName.slice(1);\n }\n\n return escapeIfNeeded(name);\n}\n","import type { ColumnDefault } from '@prisma-next/contract/types';\n\nconst NEXTVAL_PATTERN = /^nextval\\s*\\(/i;\nconst NOW_FUNCTION_PATTERN = /^(now\\s*\\(\\s*\\)|CURRENT_TIMESTAMP)$/i;\nconst CLOCK_TIMESTAMP_PATTERN = /^clock_timestamp\\s*\\(\\s*\\)$/i;\nconst TIMESTAMP_CAST_SUFFIX = /::timestamp(?:tz|\\s+(?:with|without)\\s+time\\s+zone)?$/i;\nconst TEXT_CAST_SUFFIX = /::text$/i;\nconst NOW_LITERAL_PATTERN = /^'now'$/i;\nconst UUID_PATTERN = /^gen_random_uuid\\s*\\(\\s*\\)$/i;\nconst UUID_OSSP_PATTERN = /^uuid_generate_v4\\s*\\(\\s*\\)$/i;\nconst NULL_PATTERN = /^NULL(?:::.+)?$/i;\nconst TRUE_PATTERN = /^true$/i;\nconst FALSE_PATTERN = /^false$/i;\nconst NUMERIC_PATTERN = /^-?\\d+(\\.\\d+)?$/;\nconst JSON_CAST_SUFFIX = /::jsonb?$/i;\nconst STRING_LITERAL_PATTERN = /^'((?:[^']|'')*)'(?:::(?:\"[^\"]+\"|[\\w\\s]+)(?:\\(\\d+\\))?)?$/;\n\nfunction canonicalizeTimestampDefault(expr: string): string | undefined {\n if (NOW_FUNCTION_PATTERN.test(expr)) return 'now()';\n if (CLOCK_TIMESTAMP_PATTERN.test(expr)) return 'clock_timestamp()';\n\n if (!TIMESTAMP_CAST_SUFFIX.test(expr)) return undefined;\n\n let inner = expr.replace(TIMESTAMP_CAST_SUFFIX, '').trim();\n if (inner.startsWith('(') && inner.endsWith(')')) {\n inner = inner.slice(1, -1).trim();\n }\n\n if (NOW_FUNCTION_PATTERN.test(inner)) return 'now()';\n if (CLOCK_TIMESTAMP_PATTERN.test(inner)) return 'clock_timestamp()';\n\n inner = inner.replace(TEXT_CAST_SUFFIX, '').trim();\n if (NOW_LITERAL_PATTERN.test(inner)) return 'now()';\n\n return undefined;\n}\n\nexport function parseRawDefault(\n rawDefault: string,\n nativeType?: string,\n): ColumnDefault | undefined {\n const trimmed = rawDefault.trim();\n const normalizedType = nativeType?.toLowerCase();\n\n if (NEXTVAL_PATTERN.test(trimmed)) {\n return { kind: 'function', expression: 'autoincrement()' };\n }\n\n const canonicalTimestamp = canonicalizeTimestampDefault(trimmed);\n if (canonicalTimestamp) {\n return { kind: 'function', expression: canonicalTimestamp };\n }\n\n if (UUID_PATTERN.test(trimmed) || UUID_OSSP_PATTERN.test(trimmed)) {\n return { kind: 'function', expression: 'gen_random_uuid()' };\n }\n\n if (NULL_PATTERN.test(trimmed)) {\n return { kind: 'literal', value: null };\n }\n\n if (TRUE_PATTERN.test(trimmed)) {\n return { kind: 'literal', value: true };\n }\n\n if (FALSE_PATTERN.test(trimmed)) {\n return { kind: 'literal', value: false };\n }\n\n if (NUMERIC_PATTERN.test(trimmed)) {\n return { kind: 'literal', value: Number(trimmed) };\n }\n\n const stringMatch = trimmed.match(STRING_LITERAL_PATTERN);\n if (stringMatch?.[1] !== undefined) {\n const unescaped = stringMatch[1].replace(/''/g, \"'\");\n if (normalizedType === 'json' || normalizedType === 'jsonb') {\n if (JSON_CAST_SUFFIX.test(trimmed)) {\n return { kind: 'function', expression: trimmed };\n }\n try {\n return { kind: 'literal', value: JSON.parse(unescaped) };\n } catch {\n // Fall through to the string form for malformed/non-JSON values.\n }\n }\n return { kind: 'literal', value: unescaped };\n }\n\n return { kind: 'function', expression: trimmed };\n}\n","import type { SqlForeignKeyIR, SqlTableIR } from '@prisma-next/sql-schema-ir/types';\nimport { deriveBackRelationFieldName, deriveRelationFieldName, pluralize } from './name-transforms';\nimport type { RelationField } from './printer-config';\n\nconst DEFAULT_ON_DELETE = 'noAction';\nconst DEFAULT_ON_UPDATE = 'noAction';\n\nconst REFERENTIAL_ACTION_PSL: Record<string, string> = {\n noAction: 'NoAction',\n restrict: 'Restrict',\n cascade: 'Cascade',\n setNull: 'SetNull',\n setDefault: 'SetDefault',\n};\n\nexport type InferredRelations = {\n readonly relationsByTable: ReadonlyMap<string, readonly RelationField[]>;\n};\n\nexport function inferRelations(\n tables: Record<string, SqlTableIR>,\n modelNameMap: ReadonlyMap<string, string>,\n): InferredRelations {\n const relationsByTable = new Map<string, RelationField[]>();\n\n const fkCountByPair = new Map<string, number>();\n for (const table of Object.values(tables)) {\n for (const fk of table.foreignKeys) {\n const pairKey = `${table.name}→${fk.referencedTable}`;\n fkCountByPair.set(pairKey, (fkCountByPair.get(pairKey) ?? 0) + 1);\n }\n }\n\n const usedFieldNames = new Map<string, Set<string>>();\n for (const table of Object.values(tables)) {\n const names = new Set<string>();\n for (const col of Object.values(table.columns)) {\n names.add(col.name);\n }\n usedFieldNames.set(table.name, names);\n }\n\n for (const table of Object.values(tables)) {\n for (const fk of table.foreignKeys) {\n const childTableName = table.name;\n const parentTableName = fk.referencedTable;\n const childUsed = usedFieldNames.get(childTableName) as Set<string>;\n const childModelName = modelNameMap.get(childTableName) ?? childTableName;\n const parentModelName = modelNameMap.get(parentTableName) ?? parentTableName;\n const pairKey = `${childTableName}→${parentTableName}`;\n const isSelfRelation = childTableName === parentTableName;\n const needsRelationName = (fkCountByPair.get(pairKey) as number) > 1 || isSelfRelation;\n\n const isOneToOne = detectOneToOne(fk, table);\n\n const childRelFieldName = resolveUniqueFieldName(\n deriveRelationFieldName(fk.columns, parentTableName),\n childUsed,\n parentModelName,\n );\n const relationName = needsRelationName\n ? deriveRelationName(fk, childRelFieldName, parentModelName, isSelfRelation)\n : undefined;\n const childOptional = fk.columns.some(\n (columnName) => table.columns[columnName]?.nullable ?? false,\n );\n\n const childRelField = buildChildRelationField(\n childRelFieldName,\n parentModelName,\n fk,\n childOptional,\n relationName,\n );\n\n addRelationField(relationsByTable, childTableName, childRelField);\n childUsed.add(childRelFieldName);\n\n const parentUsed = usedFieldNames.get(parentTableName) ?? new Set();\n usedFieldNames.set(parentTableName, parentUsed);\n\n const backRelFieldName = resolveUniqueFieldName(\n deriveBackRelationFieldName(childModelName, isOneToOne),\n parentUsed,\n childModelName,\n );\n\n const backRelField: RelationField = {\n fieldName: backRelFieldName,\n typeName: childModelName,\n optional: isOneToOne,\n list: !isOneToOne,\n relationName,\n };\n\n addRelationField(relationsByTable, parentTableName, backRelField);\n parentUsed.add(backRelFieldName);\n }\n }\n\n return { relationsByTable };\n}\n\nfunction detectOneToOne(fk: SqlForeignKeyIR, table: SqlTableIR): boolean {\n const fkCols = [...fk.columns].sort();\n\n if (table.primaryKey) {\n const pkCols = [...table.primaryKey.columns].sort();\n if (pkCols.length === fkCols.length && pkCols.every((c, i) => c === fkCols[i])) {\n return true;\n }\n }\n\n for (const unique of table.uniques) {\n const uniqueCols = [...unique.columns].sort();\n if (uniqueCols.length === fkCols.length && uniqueCols.every((c, i) => c === fkCols[i])) {\n return true;\n }\n }\n\n return false;\n}\n\nfunction deriveRelationName(\n fk: SqlForeignKeyIR,\n childRelationFieldName: string,\n parentModelName: string,\n isSelfRelation: boolean,\n): string {\n if (fk.name) {\n return fk.name;\n }\n if (isSelfRelation) {\n return `${childRelationFieldName.charAt(0).toUpperCase() + childRelationFieldName.slice(1)}${pluralize(parentModelName)}`;\n }\n return fk.columns.join('_');\n}\n\nfunction buildChildRelationField(\n fieldName: string,\n parentModelName: string,\n fk: SqlForeignKeyIR,\n optional: boolean,\n relationName?: string,\n): RelationField {\n const onDelete = fk.onDelete && fk.onDelete !== DEFAULT_ON_DELETE ? fk.onDelete : undefined;\n const onUpdate = fk.onUpdate && fk.onUpdate !== DEFAULT_ON_UPDATE ? fk.onUpdate : undefined;\n\n return {\n fieldName,\n typeName: parentModelName,\n referencedTableName: fk.referencedTable,\n optional,\n list: false,\n relationName,\n fkName: fk.name,\n fields: fk.columns,\n references: fk.referencedColumns,\n onDelete: onDelete ? REFERENTIAL_ACTION_PSL[onDelete] : undefined,\n onUpdate: onUpdate ? REFERENTIAL_ACTION_PSL[onUpdate] : undefined,\n };\n}\n\nfunction resolveUniqueFieldName(\n desired: string,\n usedNames: ReadonlySet<string>,\n fallbackSuffix: string,\n): string {\n if (!usedNames.has(desired)) {\n return desired;\n }\n\n const withSuffix = `${desired}${fallbackSuffix}`;\n if (!usedNames.has(withSuffix)) {\n return withSuffix;\n }\n\n let counter = 2;\n while (usedNames.has(`${desired}${counter}`)) {\n counter++;\n }\n return `${desired}${counter}`;\n}\n\nfunction addRelationField(\n map: Map<string, RelationField[]>,\n tableName: string,\n field: RelationField,\n): void {\n const existing = map.get(tableName);\n if (existing) {\n existing.push(field);\n } else {\n map.set(tableName, [field]);\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { ColumnDefault, Contract } from "@prisma-next/contract/types";
|
|
2
2
|
import { OperationContext, VerifyDatabaseSchemaResult } from "@prisma-next/framework-components/control";
|
|
3
3
|
import { SqlStorage } from "@prisma-next/sql-contract/types";
|
|
4
|
-
import { SqlSchemaIR } from "@prisma-next/sql-schema-ir/types";
|
|
4
|
+
import { SqlSchemaIR, SqlSchemaIRNode } from "@prisma-next/sql-schema-ir/types";
|
|
5
5
|
import { TargetBoundComponentDescriptor } from "@prisma-next/framework-components/components";
|
|
6
6
|
|
|
7
|
-
//#region src/core/
|
|
7
|
+
//#region src/core/diff/sql-schema-diff.d.ts
|
|
8
8
|
/**
|
|
9
9
|
* Function type for normalizing raw database default expressions into ColumnDefault.
|
|
10
10
|
* Target-specific implementations handle database dialect differences.
|
|
@@ -49,6 +49,15 @@ interface VerifySqlSchemaOptions {
|
|
|
49
49
|
* with contract native types (e.g., Postgres 'varchar' → 'character varying').
|
|
50
50
|
*/
|
|
51
51
|
readonly normalizeNativeType?: NativeTypeNormalizer;
|
|
52
|
+
/**
|
|
53
|
+
* When set, only the contract tables in these namespace ids are checked
|
|
54
|
+
* against `schema` (the matching actual namespace node). The full contract is
|
|
55
|
+
* still consulted for cross-namespace value-set / control-policy resolution.
|
|
56
|
+
* Used by the multi-schema verify, which pairs each contract namespace to its
|
|
57
|
+
* own actual node. Absent ⇒ all contract namespaces are checked against the
|
|
58
|
+
* single (flat) `schema` — the single-schema / SQLite path.
|
|
59
|
+
*/
|
|
60
|
+
readonly restrictToNamespaceIds?: ReadonlySet<string>;
|
|
52
61
|
}
|
|
53
62
|
/**
|
|
54
63
|
* Verifies that a SqlSchemaIR matches a Contract.
|
|
@@ -61,6 +70,36 @@ interface VerifySqlSchemaOptions {
|
|
|
61
70
|
* @returns VerifyDatabaseSchemaResult with verification tree and issues
|
|
62
71
|
*/
|
|
63
72
|
declare function verifySqlSchema(options: VerifySqlSchemaOptions): VerifyDatabaseSchemaResult;
|
|
73
|
+
/**
|
|
74
|
+
* The single per-namespace-paired relational verify shared by the migration
|
|
75
|
+
* planner and the family schema verify — there is exactly one such operation.
|
|
76
|
+
*
|
|
77
|
+
* Each contract namespace is paired to the introspected namespace node holding
|
|
78
|
+
* the same DDL schema, then `verifySqlSchema` checks that namespace's tables
|
|
79
|
+
* against the matching actual node (a contract table under `auth` is only ever
|
|
80
|
+
* looked up in the `auth` actual node, so a multi-schema database no longer
|
|
81
|
+
* reports tables in other schemas as missing). The full contract is passed every
|
|
82
|
+
* time — `restrictToNamespaceIds` scopes only which tables are checked, so
|
|
83
|
+
* cross-namespace value-set / control-policy resolution is unaffected.
|
|
84
|
+
*
|
|
85
|
+
* The DDL schema of each contract namespace is read from a single-namespace
|
|
86
|
+
* expected projection (`buildExpectedSchema`), which both callers already build
|
|
87
|
+
* the same way. Empty contract namespaces verify nothing and are skipped.
|
|
88
|
+
* Single-schema (one namespace) and SQLite's flat schema are one pairing —
|
|
89
|
+
* byte-identical to the prior per-node verify.
|
|
90
|
+
*/
|
|
91
|
+
declare function verifySqlSchemaTree(options: {
|
|
92
|
+
readonly contract: Contract<SqlStorage>;
|
|
93
|
+
readonly actualSchema: SqlSchemaIRNode;
|
|
94
|
+
readonly buildExpectedSchema: (contract: Contract<SqlStorage>) => SqlSchemaIRNode;
|
|
95
|
+
readonly strict: boolean;
|
|
96
|
+
readonly typeMetadataRegistry: ReadonlyMap<string, {
|
|
97
|
+
nativeType?: string;
|
|
98
|
+
}>;
|
|
99
|
+
readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'sql', string>>;
|
|
100
|
+
readonly normalizeDefault?: DefaultNormalizer;
|
|
101
|
+
readonly normalizeNativeType?: NativeTypeNormalizer;
|
|
102
|
+
}): VerifyDatabaseSchemaResult;
|
|
64
103
|
//#endregion
|
|
65
|
-
export { verifySqlSchema as i, NativeTypeNormalizer as n, VerifySqlSchemaOptions as r, DefaultNormalizer as t };
|
|
66
|
-
//# sourceMappingURL=
|
|
104
|
+
export { verifySqlSchemaTree as a, verifySqlSchema as i, NativeTypeNormalizer as n, VerifySqlSchemaOptions as r, DefaultNormalizer as t };
|
|
105
|
+
//# sourceMappingURL=sql-schema-diff-6z36dZt6.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sql-schema-diff-6z36dZt6.d.mts","names":[],"sources":["../src/core/diff/sql-schema-diff.ts"],"mappings":";;;;;;;;;;AA4EkB;KAHN,iBAAA,IACV,UAAA,UACA,UAAA,aACG,aAAa;;;;AAOoC;AAKtD;KALY,oBAAA,IAAwB,UAAkB;;;;UAKrC,sBAAA;EAQI;EAAA,SANV,QAAA,EAAU,QAAA,CAAS,UAAA;EAagB;EAAA,SAXnC,MAAA,EAAQ,WAAA;EAiBW;EAAA,SAfnB,MAAA;EA8ByB;EAAA,SA5BzB,OAAA,GAAU,gBAAA;EA4B0B;EAAA,SA1BpC,oBAAA,EAAsB,WAAA;IAAsB,UAAA;EAAA;EAN5C;;;;EAAA,SAWA,mBAAA,EAAqB,aAAA,CAAc,8BAAA;EALnC;;;;;EAAA,SAWA,gBAAA,GAAmB,iBAAA;EAAnB;;;;;EAAA,SAMA,mBAAA,GAAsB,oBAAA;EASc;AAAA;AAa/C;;;;;;EAb+C,SAApC,sBAAA,GAAyB,WAAA;AAAA;AAawD;AAkyC5F;;;;;;;;;AAlyC4F,iBAA5E,eAAA,CAAgB,OAAA,EAAS,sBAAA,GAAyB,0BAA0B;;;;;;;;;;;;;;;;;;;iBAkyC5E,mBAAA,CAAoB,OAAA;EAAA,SACzB,QAAA,EAAU,QAAA,CAAS,UAAA;EAAA,SACnB,YAAA,EAAc,eAAA;EAAA,SACd,mBAAA,GAAsB,QAAA,EAAU,QAAA,CAAS,UAAA,MAAgB,eAAA;EAAA,SACzD,MAAA;EAAA,SACA,oBAAA,EAAsB,WAAA;IAAsB,UAAA;EAAA;EAAA,SAC5C,mBAAA,EAAqB,aAAA,CAAc,8BAAA;EAAA,SACnC,gBAAA,GAAmB,iBAAA;EAAA,SACnB,mBAAA,GAAsB,oBAAA;AAAA,IAC7B,0BAAA"}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { r as SqlControlAdapter } from "./control-adapter-
|
|
1
|
+
import { r as SqlControlAdapter } from "./control-adapter-DHYFuOBy.mjs";
|
|
2
2
|
import { Contract, ControlPolicy } from "@prisma-next/contract/types";
|
|
3
|
-
import { ContractSerializer, ContractSpace, ControlAdapterDescriptor, ControlExtensionDescriptor, ControlFamilyInstance, ControlStack, MigratableTargetDescriptor, MigrationOperationPolicy, MigrationPlan, MigrationPlanOperation, MigrationPlannerConflict, MigrationPlannerFailureResult, MigrationPlannerSuccessResult, MigrationRunnerExecutionChecks, MigrationRunnerFailure, MigrationRunnerPerSpaceSuccessValue, MigrationRunnerResult, OpFactoryCall, OperationContext, OperationPreview, OperationPreviewCapable, PslContractInferCapable,
|
|
3
|
+
import { ContractSerializer, ContractSpace, ControlAdapterDescriptor, ControlExtensionDescriptor, ControlFamilyInstance, ControlStack, DiffIssue, MigratableTargetDescriptor, MigrationOperationPolicy, MigrationPlan, MigrationPlanOperation, MigrationPlannerConflict, MigrationPlannerFailureResult, MigrationPlannerSuccessResult, MigrationRunnerExecutionChecks, MigrationRunnerFailure, MigrationRunnerPerSpaceSuccessValue, MigrationRunnerResult, OpFactoryCall, OperationContext, OperationPreview, OperationPreviewCapable, PslContractInferCapable, SchemaDiffer, SchemaIssue, SchemaVerifier, SchemaViewCapable, SignDatabaseResult, VerifyDatabaseResult, VerifyDatabaseSchemaResult } from "@prisma-next/framework-components/control";
|
|
4
4
|
import { SqlControlDriverInstance, SqlStorage, StorageColumn, StorageTable, StorageTypeInstance } from "@prisma-next/sql-contract/types";
|
|
5
|
-
import { PslDocumentAst } from "@prisma-next/framework-components/psl-ast";
|
|
6
5
|
import { Result } from "@prisma-next/utils/result";
|
|
7
6
|
import { AnyQueryAst, DdlNode, LowererContext, SqlExecuteRequest } from "@prisma-next/sql-relational-core/ast";
|
|
8
|
-
import { SqlSchemaIR } from "@prisma-next/sql-schema-ir/types";
|
|
7
|
+
import { SqlSchemaIR, SqlSchemaIRNode } from "@prisma-next/sql-schema-ir/types";
|
|
9
8
|
import { TargetBoundComponentDescriptor } from "@prisma-next/framework-components/components";
|
|
10
9
|
import { TypesImportSpec } from "@prisma-next/framework-components/emission";
|
|
10
|
+
import { PslDocumentAst } from "@prisma-next/framework-components/psl-ast";
|
|
11
11
|
import { AggregateMigrationEdgeRef } from "@prisma-next/migration-tools/aggregate";
|
|
12
12
|
import { SqlOperationDescriptors } from "@prisma-next/sql-operations";
|
|
13
13
|
|
|
@@ -24,7 +24,7 @@ interface SqlFamilyInstanceState {
|
|
|
24
24
|
readonly extensionIds: ReadonlyArray<string>;
|
|
25
25
|
readonly typeMetadataRegistry: SqlTypeMetadataRegistry;
|
|
26
26
|
}
|
|
27
|
-
interface SqlControlFamilyInstance extends ControlFamilyInstance<'sql',
|
|
27
|
+
interface SqlControlFamilyInstance extends ControlFamilyInstance<'sql', SqlSchemaIRNode>, SchemaViewCapable<SqlSchemaIRNode>, PslContractInferCapable<SqlSchemaIRNode>, OperationPreviewCapable, SqlFamilyInstanceState {
|
|
28
28
|
/**
|
|
29
29
|
* The family seam-of-record for on-disk contract reads. Structurally
|
|
30
30
|
* validates the JSON envelope, then hydrates IR-class instances via
|
|
@@ -42,18 +42,17 @@ interface SqlControlFamilyInstance extends ControlFamilyInstance<'sql', SqlSchem
|
|
|
42
42
|
readonly configPath?: string;
|
|
43
43
|
}): Promise<VerifyDatabaseResult>;
|
|
44
44
|
/**
|
|
45
|
-
* Verify a contract against an already-introspected schema
|
|
45
|
+
* Verify a contract against an already-introspected schema.
|
|
46
46
|
*
|
|
47
47
|
* Callers that need to verify against the live database compose
|
|
48
48
|
* `introspect({ driver })` + `verifySchema({ contract, schema, ... })`.
|
|
49
|
-
* The aggregate verifier
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
* as `extras`.
|
|
49
|
+
* The aggregate verifier hands in the full introspected schema and scopes
|
|
50
|
+
* the returned result to each member's contract space afterwards — so
|
|
51
|
+
* sibling-space tables never survive as `extras`.
|
|
53
52
|
*/
|
|
54
53
|
verifySchema(options: {
|
|
55
54
|
readonly contract: unknown;
|
|
56
|
-
readonly schema:
|
|
55
|
+
readonly schema: SqlSchemaIRNode;
|
|
57
56
|
readonly strict: boolean;
|
|
58
57
|
readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'sql', string>>;
|
|
59
58
|
}): VerifyDatabaseSchemaResult;
|
|
@@ -66,8 +65,8 @@ interface SqlControlFamilyInstance extends ControlFamilyInstance<'sql', SqlSchem
|
|
|
66
65
|
introspect(options: {
|
|
67
66
|
readonly driver: SqlControlDriverInstance<string>;
|
|
68
67
|
readonly contract?: unknown;
|
|
69
|
-
}): Promise<
|
|
70
|
-
inferPslContract(schemaIR:
|
|
68
|
+
}): Promise<SqlSchemaIRNode>;
|
|
69
|
+
inferPslContract(schemaIR: SqlSchemaIRNode): PslDocumentAst;
|
|
71
70
|
lowerAst(ast: AnyQueryAst | DdlNode, context: LowererContext<unknown>): Promise<SqlExecuteRequest>;
|
|
72
71
|
/**
|
|
73
72
|
* Inserts the initial marker row for `space` (upsert on `space`).
|
|
@@ -114,10 +113,40 @@ interface SqlControlFamilyInstance extends ControlFamilyInstance<'sql', SqlSchem
|
|
|
114
113
|
};
|
|
115
114
|
}): Promise<void>;
|
|
116
115
|
bootstrapControlTableQueries(): readonly DdlNode[];
|
|
117
|
-
bootstrapSignMarkerQueries(): readonly DdlNode[];
|
|
118
116
|
toOperationPreview(operations: readonly MigrationPlanOperation[]): OperationPreview;
|
|
119
117
|
}
|
|
120
118
|
//#endregion
|
|
119
|
+
//#region src/core/migrations/schema-differ.d.ts
|
|
120
|
+
/**
|
|
121
|
+
* Inputs to a SQL target's schema-differ (`diffDatabaseSchema` /
|
|
122
|
+
* `verifyDatabaseSchema` on the descriptor): the contract (the expected side
|
|
123
|
+
* derives from it), the introspected actual schema node, and the resolution
|
|
124
|
+
* context the relational diff needs.
|
|
125
|
+
*/
|
|
126
|
+
interface DiffDatabaseSchemaInput {
|
|
127
|
+
readonly contract: Contract<SqlStorage>;
|
|
128
|
+
readonly schema: SqlSchemaIRNode;
|
|
129
|
+
readonly strict: boolean;
|
|
130
|
+
readonly typeMetadataRegistry: ReadonlyMap<string, {
|
|
131
|
+
readonly nativeType?: string;
|
|
132
|
+
}>;
|
|
133
|
+
readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'sql', string>>;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* The `SchemaDiffer` a SQL target implements: the black-box comparison of the
|
|
137
|
+
* contract's expected schema against the introspected actual schema, projected
|
|
138
|
+
* to the two issue lists. How it computes them is private to the target.
|
|
139
|
+
*/
|
|
140
|
+
type SqlDiffDatabaseSchema = SchemaDiffer<DiffDatabaseSchemaInput>['diff'];
|
|
141
|
+
/**
|
|
142
|
+
* The same combined comparison as {@link SqlDiffDatabaseSchema}, wrapped in the
|
|
143
|
+
* verify envelope (`ok`/`summary`/`code`/`target`/`timings`) plus the
|
|
144
|
+
* pass/warn/fail tree the CLI renders. Verify calls this instead of the diff so
|
|
145
|
+
* the relational walk that produces the tree runs once per verify, not once for
|
|
146
|
+
* the diff and again for the tree.
|
|
147
|
+
*/
|
|
148
|
+
type SqlVerifyDatabaseSchema = (input: DiffDatabaseSchemaInput) => VerifyDatabaseSchemaResult;
|
|
149
|
+
//#endregion
|
|
121
150
|
//#region src/core/migrations/types.d.ts
|
|
122
151
|
type AnyRecord = Readonly<Record<string, unknown>>;
|
|
123
152
|
interface StorageTypePlanResult<TTargetDetails> {
|
|
@@ -356,7 +385,12 @@ interface SqlPlannerFailureResult extends Omit<MigrationPlannerFailureResult, 'c
|
|
|
356
385
|
type SqlPlannerResult<TTargetDetails> = SqlPlannerSuccessResult<TTargetDetails> | SqlPlannerFailureResult;
|
|
357
386
|
interface SqlMigrationPlannerPlanOptions {
|
|
358
387
|
readonly contract: Contract<SqlStorage>;
|
|
359
|
-
|
|
388
|
+
/**
|
|
389
|
+
* The "from"/live schema as the target's introspected node (SQLite a flat
|
|
390
|
+
* `SqlSchemaIR`, Postgres a `PostgresDatabaseSchemaNode` root). Structure-aware
|
|
391
|
+
* consumers narrow the concrete shape before walking it.
|
|
392
|
+
*/
|
|
393
|
+
readonly schema: SqlSchemaIRNode;
|
|
360
394
|
readonly policy: MigrationOperationPolicy;
|
|
361
395
|
readonly schemaName?: string;
|
|
362
396
|
/**
|
|
@@ -391,6 +425,16 @@ interface SqlMigrationPlannerPlanOptions {
|
|
|
391
425
|
* All components must have matching familyId ('sql') and targetId.
|
|
392
426
|
*/
|
|
393
427
|
readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'sql', string>>;
|
|
428
|
+
/**
|
|
429
|
+
* Caller-supplied keep-predicate the planner applies to its schema diff
|
|
430
|
+
* (via `SchemaDiff.filter`) before building operations. The orchestration
|
|
431
|
+
* constructs it so the diff findings reaching op-building are exactly the
|
|
432
|
+
* contract space's own — e.g. dropping the `extra` findings for elements a
|
|
433
|
+
* sibling contract space declares, so the planner never emits DROP ops
|
|
434
|
+
* against another space's tables. The planner applies it blindly and holds
|
|
435
|
+
* no ownership logic. Absent for single-space plans.
|
|
436
|
+
*/
|
|
437
|
+
readonly keepDiffIssue?: (issue: DiffIssue) => boolean;
|
|
394
438
|
}
|
|
395
439
|
interface SqlMigrationPlanner<TTargetDetails> {
|
|
396
440
|
plan(options: SqlMigrationPlannerPlanOptions): SqlPlannerResult<TTargetDetails>;
|
|
@@ -495,6 +539,29 @@ interface SqlControlTargetDescriptor<TTargetId extends string, TTargetDetails, T
|
|
|
495
539
|
* the base, the target-specific dispatch on the subclass.
|
|
496
540
|
*/
|
|
497
541
|
readonly schemaVerifier: SchemaVerifier<TContract, SqlSchemaIR>;
|
|
542
|
+
/**
|
|
543
|
+
* Database→PSL inference for `contract infer`. Target logic (owns the dialect
|
|
544
|
+
* maps), so it lives on the descriptor. Optional: targets without `contract
|
|
545
|
+
* infer` (Mongo) omit it, and the family instance throws when it is absent.
|
|
546
|
+
*/
|
|
547
|
+
readonly inferPslContract?: (schema: SqlSchemaIRNode) => PslDocumentAst;
|
|
548
|
+
/**
|
|
549
|
+
* The single combined database-schema diff of two derived representations —
|
|
550
|
+
* the target's black-box comparison. Every SQL target provides it (Postgres
|
|
551
|
+
* returns relational + policy issues; SQLite returns relational only). It is
|
|
552
|
+
* schema logic on the target, not database I/O, so it lives here rather than
|
|
553
|
+
* on the control adapter. How it computes the two issue sets is private.
|
|
554
|
+
* See {@link SqlDiffDatabaseSchema} / {@link SqlVerifyDatabaseSchema}.
|
|
555
|
+
*/
|
|
556
|
+
readonly diffDatabaseSchema: SqlDiffDatabaseSchema;
|
|
557
|
+
/**
|
|
558
|
+
* The same combined comparison as {@link diffDatabaseSchema}, wrapped in the
|
|
559
|
+
* verify envelope (`ok`/`summary`/`code`/`target`/`timings`) plus the
|
|
560
|
+
* pass/warn/fail tree the CLI renders. Verify calls this instead of
|
|
561
|
+
* `diffDatabaseSchema` so the relational walk that produces the tree runs
|
|
562
|
+
* once per verify, not once for the diff and again for the tree.
|
|
563
|
+
*/
|
|
564
|
+
readonly verifyDatabaseSchema: SqlVerifyDatabaseSchema;
|
|
498
565
|
createPlanner(adapter: SqlControlAdapter<TTargetId>): SqlMigrationPlanner<TTargetDetails>;
|
|
499
566
|
createRunner(family: SqlControlFamilyInstance): SqlMigrationRunner<TTargetDetails>;
|
|
500
567
|
}
|
|
@@ -517,4 +584,4 @@ interface CreateSqlMigrationPlanOptions<TTargetDetails> {
|
|
|
517
584
|
}
|
|
518
585
|
//#endregion
|
|
519
586
|
export { SqlPlannerResult as A, SqlMigrationRunnerResult as C, SqlPlannerConflictKind as D, SqlPlannerConflict as E, StorageTypePlanResult as M, SqlControlFamilyInstance as N, SqlPlannerConflictLocation as O, SqlMigrationRunnerFailure as S, SqlPlanTargetDetails as T, SqlMigrationPlannerPlanOptions as _, FieldEvent as a, SqlMigrationRunnerExecuteCallbacks as b, SqlControlAdapterDescriptor as c, SqlMigrationPlan as d, SqlMigrationPlanContractInfo as f, SqlMigrationPlanner as g, SqlMigrationPlanOperationTarget as h, ExpandNativeTypeInput as i, SqlPlannerSuccessResult as j, SqlPlannerFailureResult as k, SqlControlExtensionDescriptor as l, SqlMigrationPlanOperationStep as m, CodecControlHooks as n, FieldEventContext as o, SqlMigrationPlanOperation as p, CreateSqlMigrationPlanOptions as r, ResolveIdentityValueInput as s, AnyRecord as t, SqlControlTargetDescriptor as u, SqlMigrationRunner as v, SqlMigrationRunnerSuccessValue as w, SqlMigrationRunnerExecuteOptions as x, SqlMigrationRunnerErrorCode as y };
|
|
520
|
-
//# sourceMappingURL=types-
|
|
587
|
+
//# sourceMappingURL=types-CkOIJXxU.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types-CkOIJXxU.d.mts","names":[],"sources":["../src/core/control-instance.ts","../src/core/migrations/schema-differ.ts","../src/core/migrations/types.ts"],"mappings":"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"}
|