@vibeorm/schema 5.9.0 → 5.10.0
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/capabilities.d.ts +11 -0
- package/dist/exclusion.d.ts +8 -0
- package/dist/extension.d.ts +0 -5
- package/dist/failure-kind.d.ts +72 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +516 -7
- package/dist/index.js.map +16 -10
- package/dist/native-rls-admission.d.ts +1 -1
- package/dist/partial-predicate.d.ts +18 -0
- package/dist/reserved.d.ts +0 -10
- package/dist/row-rules.d.ts +1 -22
- package/dist/sealed.d.ts +16 -0
- package/dist/suggest.d.ts +53 -0
- package/dist/unique-keys.d.ts +48 -0
- package/dist/validate.d.ts +4 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -222,9 +222,12 @@ var RESERVED_DELEGATE_NAMES = [
|
|
|
222
222
|
"delete",
|
|
223
223
|
"deleteMany",
|
|
224
224
|
"count",
|
|
225
|
+
"exists",
|
|
225
226
|
"aggregate",
|
|
226
227
|
"groupBy",
|
|
227
|
-
"fields"
|
|
228
|
+
"fields",
|
|
229
|
+
"uniques",
|
|
230
|
+
"exclusions"
|
|
228
231
|
];
|
|
229
232
|
var RESERVED_CLIENT_NAMES = [
|
|
230
233
|
"$connect",
|
|
@@ -254,7 +257,8 @@ var RESERVED_CLIENT_NAMES = [
|
|
|
254
257
|
"$withContext",
|
|
255
258
|
"$advisoryLock",
|
|
256
259
|
"$advisoryLocks",
|
|
257
|
-
"$tryAdvisoryLock"
|
|
260
|
+
"$tryAdvisoryLock",
|
|
261
|
+
"$sql"
|
|
258
262
|
];
|
|
259
263
|
var RESERVED_COLUMN_PREFIX = "__vibe_";
|
|
260
264
|
function isReservedDelegateName(params) {
|
|
@@ -479,7 +483,8 @@ var POSTGRES_CAPABILITIES = Object.freeze({
|
|
|
479
483
|
filteredAggregates: "filterClause",
|
|
480
484
|
groupingSets: "groupingSets",
|
|
481
485
|
rowCapture: true,
|
|
482
|
-
returningReadsJoinedSource: true
|
|
486
|
+
returningReadsJoinedSource: true,
|
|
487
|
+
upsertSkipUnchanged: true
|
|
483
488
|
});
|
|
484
489
|
var SQLITE_CAPABILITIES = Object.freeze({
|
|
485
490
|
rowRuleAppendOnly: true,
|
|
@@ -526,7 +531,8 @@ var SQLITE_CAPABILITIES = Object.freeze({
|
|
|
526
531
|
filteredAggregates: "filterClause",
|
|
527
532
|
groupingSets: "none",
|
|
528
533
|
rowCapture: false,
|
|
529
|
-
returningReadsJoinedSource: false
|
|
534
|
+
returningReadsJoinedSource: false,
|
|
535
|
+
upsertSkipUnchanged: true
|
|
530
536
|
});
|
|
531
537
|
var MYSQL_CAPABILITIES = Object.freeze({
|
|
532
538
|
rowRuleAppendOnly: true,
|
|
@@ -573,7 +579,8 @@ var MYSQL_CAPABILITIES = Object.freeze({
|
|
|
573
579
|
filteredAggregates: "caseWhen",
|
|
574
580
|
groupingSets: "rollup",
|
|
575
581
|
rowCapture: false,
|
|
576
|
-
returningReadsJoinedSource: false
|
|
582
|
+
returningReadsJoinedSource: false,
|
|
583
|
+
upsertSkipUnchanged: true
|
|
577
584
|
});
|
|
578
585
|
var DIALECT_CAPABILITIES = Object.freeze({
|
|
579
586
|
postgres: POSTGRES_CAPABILITIES,
|
|
@@ -1566,12 +1573,81 @@ function assertSqlNamespace(params) {
|
|
|
1566
1573
|
function qualifiedSqlName(params) {
|
|
1567
1574
|
return { namespace: params.namespace ?? params.defaultNamespace ?? SQL_NAMESPACES.postgres, name: params.name };
|
|
1568
1575
|
}
|
|
1576
|
+
// packages/schema/src/sealed.ts
|
|
1577
|
+
var sealed = new WeakSet;
|
|
1578
|
+
var valid = new WeakSet;
|
|
1579
|
+
var admitted = new WeakMap;
|
|
1580
|
+
function sealSchemaIR(params) {
|
|
1581
|
+
if (sealed.has(params.schema))
|
|
1582
|
+
return params.schema;
|
|
1583
|
+
const copy = frozenPlainCopy({ value: params.schema });
|
|
1584
|
+
if (copy === undefined)
|
|
1585
|
+
return params.schema;
|
|
1586
|
+
sealed.add(copy);
|
|
1587
|
+
return copy;
|
|
1588
|
+
}
|
|
1589
|
+
function isKnownValidSchemaIR(params) {
|
|
1590
|
+
return valid.has(params.schema);
|
|
1591
|
+
}
|
|
1592
|
+
function rememberValidSchemaIR(params) {
|
|
1593
|
+
if (sealed.has(params.schema))
|
|
1594
|
+
valid.add(params.schema);
|
|
1595
|
+
}
|
|
1596
|
+
function isKnownAdmittedSchemaIR(params) {
|
|
1597
|
+
return admitted.get(params.schema)?.includes(params.dialect) === true;
|
|
1598
|
+
}
|
|
1599
|
+
function rememberAdmittedSchemaIR(params) {
|
|
1600
|
+
if (!sealed.has(params.schema))
|
|
1601
|
+
return;
|
|
1602
|
+
const dialects = admitted.get(params.schema);
|
|
1603
|
+
if (dialects === undefined)
|
|
1604
|
+
admitted.set(params.schema, [params.dialect]);
|
|
1605
|
+
else if (!dialects.includes(params.dialect))
|
|
1606
|
+
dialects.push(params.dialect);
|
|
1607
|
+
}
|
|
1608
|
+
function frozenPlainCopy(params) {
|
|
1609
|
+
const { value } = params;
|
|
1610
|
+
if (typeof value === "function" || typeof value === "symbol")
|
|
1611
|
+
return;
|
|
1612
|
+
if (typeof value !== "object" || value === null)
|
|
1613
|
+
return value;
|
|
1614
|
+
if (Array.isArray(value)) {
|
|
1615
|
+
if (Object.getPrototypeOf(value) !== Array.prototype)
|
|
1616
|
+
return;
|
|
1617
|
+
const out = [];
|
|
1618
|
+
for (let index = 0;index < value.length; index++) {
|
|
1619
|
+
const member = value[index];
|
|
1620
|
+
const item = frozenPlainCopy({ value: member });
|
|
1621
|
+
if (item === undefined && member !== undefined)
|
|
1622
|
+
return;
|
|
1623
|
+
out.push(item);
|
|
1624
|
+
}
|
|
1625
|
+
return Object.freeze(out);
|
|
1626
|
+
}
|
|
1627
|
+
const prototype = Object.getPrototypeOf(value);
|
|
1628
|
+
if (prototype !== Object.prototype && prototype !== null)
|
|
1629
|
+
return;
|
|
1630
|
+
if (Object.getOwnPropertySymbols(value).length > 0)
|
|
1631
|
+
return;
|
|
1632
|
+
const out = prototype === null ? Object.create(null) : {};
|
|
1633
|
+
for (const key of Object.keys(value)) {
|
|
1634
|
+
const member = value[key];
|
|
1635
|
+
const item = frozenPlainCopy({ value: member });
|
|
1636
|
+
if (item === undefined && member !== undefined)
|
|
1637
|
+
return;
|
|
1638
|
+
Object.defineProperty(out, key, { value: item, enumerable: true, writable: true, configurable: true });
|
|
1639
|
+
}
|
|
1640
|
+
return Object.freeze(out);
|
|
1641
|
+
}
|
|
1642
|
+
|
|
1569
1643
|
// packages/schema/src/native-rls-admission.ts
|
|
1570
1644
|
function assertNativeRlsAdmission(params) {
|
|
1571
1645
|
const { schema } = params;
|
|
1572
1646
|
if (schema.rls === undefined && !schema.models.some((model) => model.rls !== undefined))
|
|
1573
1647
|
return;
|
|
1574
1648
|
const dialect = params.dialect ?? providerToDialect({ provider: schema.datasource.provider });
|
|
1649
|
+
if (isKnownAdmittedSchemaIR({ schema, dialect }))
|
|
1650
|
+
return;
|
|
1575
1651
|
if (!DIALECT_CAPABILITIES[dialect].nativeRowLevelSecurity) {
|
|
1576
1652
|
throw unsupportedCapability({ dialect, feature: "nativeRowLevelSecurity" });
|
|
1577
1653
|
}
|
|
@@ -1589,6 +1665,7 @@ function assertNativeRlsAdmission(params) {
|
|
|
1589
1665
|
});
|
|
1590
1666
|
}
|
|
1591
1667
|
}
|
|
1668
|
+
rememberAdmittedSchemaIR({ schema, dialect });
|
|
1592
1669
|
}
|
|
1593
1670
|
// packages/schema/src/model-sql-namespace.ts
|
|
1594
1671
|
function modelSqlNamespace(params) {
|
|
@@ -2554,6 +2631,24 @@ function prepareDatabaseModuleSchema(params) {
|
|
|
2554
2631
|
enums: schema.enums.map((entry) => enumStorageOf({ enumDef: entry }) === "database" ? { ...entry, namespace } : entry)
|
|
2555
2632
|
};
|
|
2556
2633
|
}
|
|
2634
|
+
// packages/schema/src/exclusion.ts
|
|
2635
|
+
function exclusionFields(params) {
|
|
2636
|
+
const { source } = params.exclusion;
|
|
2637
|
+
if (source === undefined)
|
|
2638
|
+
return;
|
|
2639
|
+
const fields = new Set;
|
|
2640
|
+
for (const key of source.keys) {
|
|
2641
|
+
if ("field" in key)
|
|
2642
|
+
fields.add(key.field);
|
|
2643
|
+
else
|
|
2644
|
+
for (const field of key.fields)
|
|
2645
|
+
fields.add(field);
|
|
2646
|
+
}
|
|
2647
|
+
for (const endpoint of [source.range.lower, source.range.upper])
|
|
2648
|
+
if ("field" in endpoint)
|
|
2649
|
+
fields.add(endpoint.field);
|
|
2650
|
+
return [...fields];
|
|
2651
|
+
}
|
|
2557
2652
|
// packages/schema/src/check-rules.ts
|
|
2558
2653
|
var CHECK_RULE_GROUP_MAX = 8;
|
|
2559
2654
|
var field = (name) => ({ kind: "field", name });
|
|
@@ -2717,6 +2812,133 @@ function dialectCollation(params) {
|
|
|
2717
2812
|
return;
|
|
2718
2813
|
}
|
|
2719
2814
|
}
|
|
2815
|
+
// packages/schema/src/failure-kind.ts
|
|
2816
|
+
var CONNECTION_FAILURE_REASONS = Object.freeze([
|
|
2817
|
+
"connection-refused",
|
|
2818
|
+
"connection-timeout",
|
|
2819
|
+
"connection-lost",
|
|
2820
|
+
"connection-not-writable",
|
|
2821
|
+
"acquire-timeout",
|
|
2822
|
+
"pool-exhausted",
|
|
2823
|
+
"pool-closed",
|
|
2824
|
+
"too-many-connections",
|
|
2825
|
+
"server-shutdown"
|
|
2826
|
+
]);
|
|
2827
|
+
var CONNECTION_REASON_SET = new Set(CONNECTION_FAILURE_REASONS);
|
|
2828
|
+
function isConnectionFailureReason(params) {
|
|
2829
|
+
return typeof params.value === "string" && CONNECTION_REASON_SET.has(params.value);
|
|
2830
|
+
}
|
|
2831
|
+
var FAILURE_KINDS = Object.freeze([
|
|
2832
|
+
"connection",
|
|
2833
|
+
"conflict",
|
|
2834
|
+
"timeout",
|
|
2835
|
+
"constraint"
|
|
2836
|
+
]);
|
|
2837
|
+
var VIBE_CODE_SET = new Set(VIBE_ERROR_CODES);
|
|
2838
|
+
var CONFLICT_REASONS = new Set(["deadlock", "serialization-failure", "busy"]);
|
|
2839
|
+
var TIMEOUT_REASONS = new Set(["timeout", "transaction-deadline"]);
|
|
2840
|
+
var POSTGRES_CONSTRAINT_SQLSTATES = new Set(["23502", "23514"]);
|
|
2841
|
+
var SQLITE_CONSTRAINT_CODES = new Set([
|
|
2842
|
+
"SQLITE_CONSTRAINT_NOTNULL",
|
|
2843
|
+
"SQLITE_CONSTRAINT_CHECK",
|
|
2844
|
+
"SQLITE_CONSTRAINT_TRIGGER"
|
|
2845
|
+
]);
|
|
2846
|
+
var MYSQL_CONSTRAINT_ERRNOS = new Set([1048, 1364, 3819]);
|
|
2847
|
+
function constraintRefusal(params) {
|
|
2848
|
+
const { meta } = params;
|
|
2849
|
+
if (typeof meta.sqlstate === "string")
|
|
2850
|
+
return POSTGRES_CONSTRAINT_SQLSTATES.has(meta.sqlstate);
|
|
2851
|
+
if (typeof meta.sqlState === "string" && typeof meta.errno === "number")
|
|
2852
|
+
return MYSQL_CONSTRAINT_ERRNOS.has(meta.errno);
|
|
2853
|
+
return typeof meta.code === "string" && SQLITE_CONSTRAINT_CODES.has(meta.code);
|
|
2854
|
+
}
|
|
2855
|
+
function failureKindOf(params) {
|
|
2856
|
+
const { error } = params;
|
|
2857
|
+
if (typeof error !== "object" || error === null)
|
|
2858
|
+
return;
|
|
2859
|
+
const { code, meta } = error;
|
|
2860
|
+
if (typeof code !== "string" || !VIBE_CODE_SET.has(code))
|
|
2861
|
+
return;
|
|
2862
|
+
const facts = typeof meta === "object" && meta !== null ? meta : {};
|
|
2863
|
+
const reason = facts.reason;
|
|
2864
|
+
switch (code) {
|
|
2865
|
+
case "VIBE_ADAPTER":
|
|
2866
|
+
if (isConnectionFailureReason({ value: reason }))
|
|
2867
|
+
return "connection";
|
|
2868
|
+
return typeof reason === "string" && TIMEOUT_REASONS.has(reason) ? "timeout" : undefined;
|
|
2869
|
+
case "VIBE_TRANSACTION":
|
|
2870
|
+
if (typeof reason !== "string")
|
|
2871
|
+
return;
|
|
2872
|
+
if (CONFLICT_REASONS.has(reason))
|
|
2873
|
+
return "conflict";
|
|
2874
|
+
return TIMEOUT_REASONS.has(reason) ? "timeout" : undefined;
|
|
2875
|
+
case "VIBE_UNIQUE_VIOLATION":
|
|
2876
|
+
case "VIBE_FK_VIOLATION":
|
|
2877
|
+
case "VIBE_EXCLUSION_VIOLATION":
|
|
2878
|
+
return "constraint";
|
|
2879
|
+
case "VIBE_VALIDATION":
|
|
2880
|
+
return constraintRefusal({ meta: facts }) ? "constraint" : undefined;
|
|
2881
|
+
default:
|
|
2882
|
+
return;
|
|
2883
|
+
}
|
|
2884
|
+
}
|
|
2885
|
+
// packages/schema/src/suggest.ts
|
|
2886
|
+
function editDistance(params) {
|
|
2887
|
+
const { from, to } = params;
|
|
2888
|
+
const rows = from.length + 1;
|
|
2889
|
+
const columns = to.length + 1;
|
|
2890
|
+
const table = new Array(rows * columns).fill(0);
|
|
2891
|
+
for (let row = 0;row < rows; row++)
|
|
2892
|
+
table[row * columns] = row;
|
|
2893
|
+
for (let column = 0;column < columns; column++)
|
|
2894
|
+
table[column] = column;
|
|
2895
|
+
for (let row = 1;row < rows; row++) {
|
|
2896
|
+
for (let column = 1;column < columns; column++) {
|
|
2897
|
+
const cost = from[row - 1] === to[column - 1] ? 0 : 1;
|
|
2898
|
+
let best = Math.min(table[(row - 1) * columns + column] + 1, table[row * columns + column - 1] + 1, table[(row - 1) * columns + column - 1] + cost);
|
|
2899
|
+
if (row > 1 && column > 1 && from[row - 1] === to[column - 2] && from[row - 2] === to[column - 1]) {
|
|
2900
|
+
best = Math.min(best, table[(row - 2) * columns + column - 2] + 1);
|
|
2901
|
+
}
|
|
2902
|
+
table[row * columns + column] = best;
|
|
2903
|
+
}
|
|
2904
|
+
}
|
|
2905
|
+
return table[rows * columns - 1];
|
|
2906
|
+
}
|
|
2907
|
+
function suggestName(params) {
|
|
2908
|
+
const { name } = params;
|
|
2909
|
+
let best;
|
|
2910
|
+
let bestDistance = Number.POSITIVE_INFINITY;
|
|
2911
|
+
let tied = false;
|
|
2912
|
+
for (const candidate of new Set(params.candidates)) {
|
|
2913
|
+
if (candidate === name)
|
|
2914
|
+
continue;
|
|
2915
|
+
const distance = editDistance({ from: name, to: candidate });
|
|
2916
|
+
const limit = Math.max(2, Math.floor(Math.max(name.length, candidate.length) / 3));
|
|
2917
|
+
if (distance > limit || distance >= name.length)
|
|
2918
|
+
continue;
|
|
2919
|
+
if (distance < bestDistance) {
|
|
2920
|
+
best = candidate;
|
|
2921
|
+
bestDistance = distance;
|
|
2922
|
+
tied = false;
|
|
2923
|
+
} else if (distance === bestDistance) {
|
|
2924
|
+
tied = true;
|
|
2925
|
+
}
|
|
2926
|
+
}
|
|
2927
|
+
return tied ? undefined : best;
|
|
2928
|
+
}
|
|
2929
|
+
function didYouMean(params) {
|
|
2930
|
+
return params.suggestion === undefined ? "" : ` \u2014 did you mean ${JSON.stringify(params.suggestion)}?`;
|
|
2931
|
+
}
|
|
2932
|
+
var unknownNameMetas = new WeakSet;
|
|
2933
|
+
function withSuggestion(params) {
|
|
2934
|
+
const suggestion = suggestName({ name: params.name, candidates: params.candidates });
|
|
2935
|
+
const meta = suggestion === undefined ? params.meta : { ...params.meta, suggestion };
|
|
2936
|
+
unknownNameMetas.add(meta);
|
|
2937
|
+
return { message: suggestion === undefined ? params.message : `${params.message}${didYouMean({ suggestion })}`, meta };
|
|
2938
|
+
}
|
|
2939
|
+
function isUnknownNameRefusal(params) {
|
|
2940
|
+
return unknownNameMetas.has(params.meta);
|
|
2941
|
+
}
|
|
2720
2942
|
// packages/schema/src/computed.ts
|
|
2721
2943
|
function buildComputedManifest(params) {
|
|
2722
2944
|
const { computed } = params;
|
|
@@ -2755,6 +2977,8 @@ function validateComputedConfig(params) {
|
|
|
2755
2977
|
}
|
|
2756
2978
|
if (fieldName === "_count")
|
|
2757
2979
|
problems.push(`"${at}" collides with the _count projection`);
|
|
2980
|
+
if (fieldName === "_aggregate")
|
|
2981
|
+
problems.push(`"${at}" collides with the _aggregate projection`);
|
|
2758
2982
|
if (model.fields.some((field) => field.name === fieldName)) {
|
|
2759
2983
|
problems.push(`"${at}" collides with a schema field of the same name`);
|
|
2760
2984
|
}
|
|
@@ -3043,6 +3267,8 @@ var RESERVED_ENUM_NAMES = [
|
|
|
3043
3267
|
"BagKeys",
|
|
3044
3268
|
"__VibeBagKeysIn",
|
|
3045
3269
|
"__VibeCertain",
|
|
3270
|
+
"__VibeAllOn",
|
|
3271
|
+
"__VibeAggregateSelection",
|
|
3046
3272
|
"IncludedRelation",
|
|
3047
3273
|
"IncludedCount",
|
|
3048
3274
|
"ViewDelegateMap",
|
|
@@ -3051,8 +3277,21 @@ var RESERVED_ENUM_NAMES = [
|
|
|
3051
3277
|
"__VibeAt",
|
|
3052
3278
|
"__VibeItem",
|
|
3053
3279
|
"__VibeExact",
|
|
3280
|
+
"__VibeLiteral",
|
|
3054
3281
|
"__VibePreviousInput",
|
|
3055
3282
|
"__VibePrevious",
|
|
3283
|
+
"__VibeUpdated",
|
|
3284
|
+
"__VibeDeleted",
|
|
3285
|
+
"__VibeOrNullRow",
|
|
3286
|
+
"__VibeUpserted",
|
|
3287
|
+
"__VibeCreated",
|
|
3288
|
+
"__VibeAggregateValue",
|
|
3289
|
+
"__VibeSplitEntries",
|
|
3290
|
+
"__VibeViewAggregates",
|
|
3291
|
+
"__VibeViewBucket",
|
|
3292
|
+
"__VibeViewFiltered",
|
|
3293
|
+
"__VibeViewBy",
|
|
3294
|
+
"__VibeViewByKey",
|
|
3056
3295
|
"extensionManifest",
|
|
3057
3296
|
"extensionMounts",
|
|
3058
3297
|
"computedManifest",
|
|
@@ -3065,6 +3304,7 @@ var RESERVED_ENUM_NAMES = [
|
|
|
3065
3304
|
"Partial",
|
|
3066
3305
|
"Omit",
|
|
3067
3306
|
"NonNullable",
|
|
3307
|
+
"NoInfer",
|
|
3068
3308
|
"Promise",
|
|
3069
3309
|
"PromiseLike",
|
|
3070
3310
|
"Awaited",
|
|
@@ -3137,6 +3377,7 @@ var RESERVED_ENUM_NAMES = [
|
|
|
3137
3377
|
"TransactionLocalSettings",
|
|
3138
3378
|
"VibeUpdateManySources",
|
|
3139
3379
|
"VibeModelRows",
|
|
3380
|
+
"VibeUniqueKeys",
|
|
3140
3381
|
"VibeHandleTypes",
|
|
3141
3382
|
"ClientContext",
|
|
3142
3383
|
"QueryOperation",
|
|
@@ -3251,6 +3492,10 @@ var GENERATED_TYPE_NAMES = {
|
|
|
3251
3492
|
"OmitBase",
|
|
3252
3493
|
"CountResult",
|
|
3253
3494
|
"CountPayload",
|
|
3495
|
+
"AggregateEntries",
|
|
3496
|
+
"AggregateEntryArgs",
|
|
3497
|
+
"AggregateOf",
|
|
3498
|
+
"AggregatePayload",
|
|
3254
3499
|
"AggregateValues",
|
|
3255
3500
|
"AggregateSelection",
|
|
3256
3501
|
"CountOutput",
|
|
@@ -3267,6 +3512,7 @@ var GENERATED_TYPE_NAMES = {
|
|
|
3267
3512
|
"ViewNestedArgs",
|
|
3268
3513
|
"ViewFindManyArgs",
|
|
3269
3514
|
"ViewFindUniqueArgs",
|
|
3515
|
+
"ViewAggregateBag",
|
|
3270
3516
|
"ViewScalars",
|
|
3271
3517
|
"ViewSelectScalars",
|
|
3272
3518
|
"ViewReveal",
|
|
@@ -4531,6 +4777,12 @@ function assertMysqlCheckReferentialActions(params) {
|
|
|
4531
4777
|
}
|
|
4532
4778
|
}
|
|
4533
4779
|
function assertValidSchemaIR(params) {
|
|
4780
|
+
if (isKnownValidSchemaIR(params))
|
|
4781
|
+
return;
|
|
4782
|
+
assertSchemaIRNow(params);
|
|
4783
|
+
rememberValidSchemaIR(params);
|
|
4784
|
+
}
|
|
4785
|
+
function assertSchemaIRNow(params) {
|
|
4534
4786
|
const rowRules = createRowRuleValidationContext(params);
|
|
4535
4787
|
const dialect = providerToDialect({ provider: params.schema.datasource.provider });
|
|
4536
4788
|
assertIndexExpressions({ schema: params.schema, dialect });
|
|
@@ -4849,13 +5101,259 @@ function validRlsForeignKey(params) {
|
|
|
4849
5101
|
];
|
|
4850
5102
|
return validFields && uniqueSets.some((set) => set.length === refs.length && set.every((name) => refs.includes(name)));
|
|
4851
5103
|
}
|
|
5104
|
+
// packages/schema/src/partial-predicate.ts
|
|
5105
|
+
function normalizeWhere(params) {
|
|
5106
|
+
const { where } = params;
|
|
5107
|
+
if (where === undefined || where.trim() === "")
|
|
5108
|
+
return "";
|
|
5109
|
+
if (/\$|\\|--|\/\*/.test(where))
|
|
5110
|
+
return `raw:${where.trim()}`;
|
|
5111
|
+
const tokens = tokenizeWhere({ text: where });
|
|
5112
|
+
const parsed = parseOrExpression({ tokens, at: 0 });
|
|
5113
|
+
return parsed !== undefined && parsed.at === tokens.length ? parsed.text : tokens.join(" ");
|
|
5114
|
+
}
|
|
5115
|
+
function tokenizeWhere(params) {
|
|
5116
|
+
const { text } = params;
|
|
5117
|
+
const tokens = [];
|
|
5118
|
+
let i = 0;
|
|
5119
|
+
while (i < text.length) {
|
|
5120
|
+
const ch = text[i];
|
|
5121
|
+
if (/\s/.test(ch)) {
|
|
5122
|
+
i += 1;
|
|
5123
|
+
continue;
|
|
5124
|
+
}
|
|
5125
|
+
if (ch === "'") {
|
|
5126
|
+
let literal = "'";
|
|
5127
|
+
i += 1;
|
|
5128
|
+
while (i < text.length) {
|
|
5129
|
+
literal += text[i];
|
|
5130
|
+
if (text[i] === "'") {
|
|
5131
|
+
if (text[i + 1] === "'") {
|
|
5132
|
+
literal += "'";
|
|
5133
|
+
i += 2;
|
|
5134
|
+
continue;
|
|
5135
|
+
}
|
|
5136
|
+
i += 1;
|
|
5137
|
+
break;
|
|
5138
|
+
}
|
|
5139
|
+
i += 1;
|
|
5140
|
+
}
|
|
5141
|
+
tokens.push(literal);
|
|
5142
|
+
continue;
|
|
5143
|
+
}
|
|
5144
|
+
if (ch === '"' || ch === "`") {
|
|
5145
|
+
let name = "";
|
|
5146
|
+
i += 1;
|
|
5147
|
+
while (i < text.length) {
|
|
5148
|
+
if (text[i] === ch) {
|
|
5149
|
+
if (text[i + 1] !== ch) {
|
|
5150
|
+
i += 1;
|
|
5151
|
+
break;
|
|
5152
|
+
}
|
|
5153
|
+
name += ch;
|
|
5154
|
+
i += 2;
|
|
5155
|
+
} else {
|
|
5156
|
+
name += text[i];
|
|
5157
|
+
i += 1;
|
|
5158
|
+
}
|
|
5159
|
+
}
|
|
5160
|
+
tokens.push(JSON.stringify(name));
|
|
5161
|
+
continue;
|
|
5162
|
+
}
|
|
5163
|
+
if (ch === "[") {
|
|
5164
|
+
const end = text.indexOf("]", i + 1);
|
|
5165
|
+
const inner = end === -1 ? undefined : text.slice(i + 1, end);
|
|
5166
|
+
if (inner !== undefined && tokens[tokens.length - 1] !== "array" && /^[A-Za-z_][A-Za-z_0-9$]*$/.test(inner)) {
|
|
5167
|
+
tokens.push(JSON.stringify(inner));
|
|
5168
|
+
i = end + 1;
|
|
5169
|
+
continue;
|
|
5170
|
+
}
|
|
5171
|
+
tokens.push(ch);
|
|
5172
|
+
i += 1;
|
|
5173
|
+
continue;
|
|
5174
|
+
}
|
|
5175
|
+
const word = /^[A-Za-z_][A-Za-z_0-9$]*/.exec(text.slice(i));
|
|
5176
|
+
if (word !== null) {
|
|
5177
|
+
tokens.push(word[0].toLowerCase());
|
|
5178
|
+
i += word[0].length;
|
|
5179
|
+
continue;
|
|
5180
|
+
}
|
|
5181
|
+
const number = /^[0-9]+(?:\.[0-9]+)?/.exec(text.slice(i));
|
|
5182
|
+
if (number !== null) {
|
|
5183
|
+
tokens.push(number[0]);
|
|
5184
|
+
i += number[0].length;
|
|
5185
|
+
continue;
|
|
5186
|
+
}
|
|
5187
|
+
tokens.push(ch);
|
|
5188
|
+
i += 1;
|
|
5189
|
+
}
|
|
5190
|
+
return tokens;
|
|
5191
|
+
}
|
|
5192
|
+
function parseOrExpression(params) {
|
|
5193
|
+
const first = parseAndExpression({ tokens: params.tokens, at: params.at });
|
|
5194
|
+
if (first === undefined)
|
|
5195
|
+
return;
|
|
5196
|
+
let at = first.at;
|
|
5197
|
+
const parts = [first.text];
|
|
5198
|
+
while (params.tokens[at] === "or") {
|
|
5199
|
+
const next = parseAndExpression({ tokens: params.tokens, at: at + 1 });
|
|
5200
|
+
if (next === undefined)
|
|
5201
|
+
return;
|
|
5202
|
+
parts.push(next.text);
|
|
5203
|
+
at = next.at;
|
|
5204
|
+
}
|
|
5205
|
+
return parts.length === 1 ? { text: parts[0], at, kind: first.kind } : { text: parts.join(" or "), at, kind: "or" };
|
|
5206
|
+
}
|
|
5207
|
+
function parseAndExpression(params) {
|
|
5208
|
+
const first = parsePrimaryExpression({ tokens: params.tokens, at: params.at });
|
|
5209
|
+
if (first === undefined)
|
|
5210
|
+
return;
|
|
5211
|
+
let at = first.at;
|
|
5212
|
+
const operands = [first];
|
|
5213
|
+
while (params.tokens[at] === "and") {
|
|
5214
|
+
const next = parsePrimaryExpression({ tokens: params.tokens, at: at + 1 });
|
|
5215
|
+
if (next === undefined)
|
|
5216
|
+
return;
|
|
5217
|
+
operands.push(next);
|
|
5218
|
+
at = next.at;
|
|
5219
|
+
}
|
|
5220
|
+
return operands.length === 1 ? { text: first.text, at, kind: first.kind } : {
|
|
5221
|
+
text: operands.map((operand) => operand.kind === "or" ? `(${operand.text})` : operand.text).join(" and "),
|
|
5222
|
+
at,
|
|
5223
|
+
kind: "and"
|
|
5224
|
+
};
|
|
5225
|
+
}
|
|
5226
|
+
function parsePrimaryExpression(params) {
|
|
5227
|
+
const { tokens } = params;
|
|
5228
|
+
let at = params.at;
|
|
5229
|
+
if (tokens[at] === "not") {
|
|
5230
|
+
const operand = parsePrimaryExpression({ tokens, at: at + 1 });
|
|
5231
|
+
if (operand === undefined)
|
|
5232
|
+
return;
|
|
5233
|
+
const inner = operand.kind === "atom" ? operand.text : `(${operand.text})`;
|
|
5234
|
+
return { text: `not ${inner}`, at: operand.at, kind: "atom" };
|
|
5235
|
+
}
|
|
5236
|
+
if (tokens[at] === "(") {
|
|
5237
|
+
const inner = parseOrExpression({ tokens, at: at + 1 });
|
|
5238
|
+
if (inner === undefined || tokens[inner.at] !== ")")
|
|
5239
|
+
return;
|
|
5240
|
+
return { text: inner.text, at: inner.at + 1, kind: inner.kind };
|
|
5241
|
+
}
|
|
5242
|
+
const parts = [];
|
|
5243
|
+
let depth = 0;
|
|
5244
|
+
while (at < tokens.length) {
|
|
5245
|
+
const token = tokens[at];
|
|
5246
|
+
if (depth === 0 && (token === "and" || token === "or" || token === ")"))
|
|
5247
|
+
break;
|
|
5248
|
+
if (token === "(")
|
|
5249
|
+
depth += 1;
|
|
5250
|
+
if (token === ")")
|
|
5251
|
+
depth -= 1;
|
|
5252
|
+
parts.push(token);
|
|
5253
|
+
at += 1;
|
|
5254
|
+
}
|
|
5255
|
+
if (parts.length === 0)
|
|
5256
|
+
return;
|
|
5257
|
+
if (parts[1] === "is" && (parts.length === 3 && parts[2] === "null" || parts.length === 4 && parts[2] === "not" && parts[3] === "null")) {
|
|
5258
|
+
const quoted = /^"([a-z_][a-z_0-9]*)"$/.exec(parts[0]);
|
|
5259
|
+
if (quoted !== null && !/^(?:true|false|null|unknown|default|user|current_.*|session_user|system_user|localtime|localtimestamp|and|or|not|is)$/.test(quoted[1]))
|
|
5260
|
+
parts[0] = quoted[1];
|
|
5261
|
+
}
|
|
5262
|
+
return { text: parts.join(" "), at, kind: "atom" };
|
|
5263
|
+
}
|
|
5264
|
+
|
|
5265
|
+
// packages/schema/src/unique-keys.ts
|
|
5266
|
+
var RANK = { primaryKey: 0, field: 1, block: 2, partial: 3, expression: 4 };
|
|
5267
|
+
function comparisonKey(params) {
|
|
5268
|
+
const { model, index } = params;
|
|
5269
|
+
const common = [index.nullsNotDistinct === true, normalizeWhere({ where: index.where }), index.include ?? []];
|
|
5270
|
+
if (isExpressionIndex({ index }))
|
|
5271
|
+
return JSON.stringify(["expression", indexKeyDefinitionKey({ index, model }), ...common]);
|
|
5272
|
+
return JSON.stringify(["fields", index.fields.map((field) => [field.name, field.sort === "desc", field.operatorClass ?? null]), ...common]);
|
|
5273
|
+
}
|
|
5274
|
+
function modelUniqueKeys(params) {
|
|
5275
|
+
const { model, dialect } = params;
|
|
5276
|
+
if (model.isView)
|
|
5277
|
+
return [];
|
|
5278
|
+
const table = model.dbName ?? model.name;
|
|
5279
|
+
const columnOf = (name) => model.fields.find((field) => field.name === name)?.dbName ?? name;
|
|
5280
|
+
const candidates = [];
|
|
5281
|
+
const primaryKey = model.primaryKey?.fields ?? model.fields.filter((field) => field.isId).map((field) => field.name);
|
|
5282
|
+
if (primaryKey.length > 0) {
|
|
5283
|
+
const name = dialect === "mysql" ? "PRIMARY" : dialect === "sqlite" ? null : model.primaryKeyConstraintName ?? defaultPrimaryKeyName({ table, dialect });
|
|
5284
|
+
candidates.push({
|
|
5285
|
+
rank: RANK.primaryKey,
|
|
5286
|
+
order: 0,
|
|
5287
|
+
natural: model.primaryKey?.clientName ?? primaryKey.join("_"),
|
|
5288
|
+
fallback: model.primaryKeyConstraintName ?? defaultPrimaryKeyName({ table, dialect: "sqlite" }),
|
|
5289
|
+
entry: { name, names: name === null ? [] : [name], fields: primaryKey, primaryKey: true, partial: false }
|
|
5290
|
+
});
|
|
5291
|
+
}
|
|
5292
|
+
const seen = new Set;
|
|
5293
|
+
const add = (params) => {
|
|
5294
|
+
const { index } = params;
|
|
5295
|
+
const identity = comparisonKey({ model, index });
|
|
5296
|
+
if (seen.has(identity))
|
|
5297
|
+
return;
|
|
5298
|
+
seen.add(identity);
|
|
5299
|
+
const partial = index.where !== undefined;
|
|
5300
|
+
if (isExpressionIndex({ index })) {
|
|
5301
|
+
const sourceFields = indexKeyFieldNames({ index });
|
|
5302
|
+
const indexName = index.name ?? (sourceFields === undefined ? undefined : defaultExpressionIndexName({ table, model, index, dialect }));
|
|
5303
|
+
if (indexName === undefined)
|
|
5304
|
+
return;
|
|
5305
|
+
const names = [...new Set([index.constraintName ?? indexName, indexName])];
|
|
5306
|
+
candidates.push({
|
|
5307
|
+
rank: RANK.expression,
|
|
5308
|
+
order: params.order,
|
|
5309
|
+
natural: sourceFields?.join("_"),
|
|
5310
|
+
fallback: index.name ?? defaultExpressionIndexName({ table, model, index, dialect: "sqlite" }),
|
|
5311
|
+
entry: { name: names[0], names, ...sourceFields === undefined ? {} : { sourceFields }, primaryKey: false, partial }
|
|
5312
|
+
});
|
|
5313
|
+
return;
|
|
5314
|
+
}
|
|
5315
|
+
const fields = index.fields.map((field) => field.name);
|
|
5316
|
+
const indexName = index.name ?? defaultIndexName({ table, columns: fields.map(columnOf), unique: true, dialect });
|
|
5317
|
+
const names = [...new Set([index.constraintName ?? indexName, indexName])];
|
|
5318
|
+
candidates.push({
|
|
5319
|
+
rank: partial ? RANK.partial : params.rank,
|
|
5320
|
+
order: params.order,
|
|
5321
|
+
natural: index.clientName ?? fields.join("_"),
|
|
5322
|
+
fallback: index.constraintName ?? index.name ?? defaultIndexName({ table, columns: fields.map(columnOf), unique: true, dialect: "sqlite" }),
|
|
5323
|
+
entry: { name: names[0], names, fields, primaryKey: false, partial }
|
|
5324
|
+
});
|
|
5325
|
+
};
|
|
5326
|
+
const fieldKey = (name) => ({ kind: "unique", fields: [{ name }] });
|
|
5327
|
+
model.indexes.forEach((index, position) => {
|
|
5328
|
+
if (index.kind !== "unique")
|
|
5329
|
+
return;
|
|
5330
|
+
const own = isExpressionIndex({ index }) || index.fields.length !== 1 ? -1 : model.fields.findIndex((field) => field.isUnique && field.name === index.fields[0].name && comparisonKey({ model, index }) === comparisonKey({ model, index: fieldKey(field.name) }));
|
|
5331
|
+
add({ index, rank: own >= 0 ? RANK.field : RANK.block, order: own >= 0 ? own : position });
|
|
5332
|
+
});
|
|
5333
|
+
model.fields.forEach((field, position) => {
|
|
5334
|
+
if (field.isUnique)
|
|
5335
|
+
add({ index: fieldKey(field.name), rank: RANK.field, order: position });
|
|
5336
|
+
});
|
|
5337
|
+
const claimed = new Set;
|
|
5338
|
+
const keyed = new Map;
|
|
5339
|
+
for (const candidate of [...candidates].sort((left, right) => left.rank - right.rank || left.order - right.order)) {
|
|
5340
|
+
let key = candidate.natural !== undefined && !claimed.has(candidate.natural) ? candidate.natural : candidate.fallback;
|
|
5341
|
+
for (let suffix = 2;claimed.has(key); suffix++)
|
|
5342
|
+
key = `${candidate.fallback}_${suffix}`;
|
|
5343
|
+
claimed.add(key);
|
|
5344
|
+
keyed.set(candidate, key);
|
|
5345
|
+
}
|
|
5346
|
+
return candidates.sort((left, right) => left.rank - right.rank || left.order - right.order).map((candidate) => ({ key: keyed.get(candidate), ...candidate.entry }));
|
|
5347
|
+
}
|
|
4852
5348
|
export {
|
|
4853
5349
|
CHECK_RULE_GROUP_MAX,
|
|
5350
|
+
CONNECTION_FAILURE_REASONS,
|
|
4854
5351
|
DATE_TRUNCATION_UNITS,
|
|
4855
5352
|
DIALECTS,
|
|
4856
5353
|
DIALECT_CAPABILITIES,
|
|
4857
5354
|
EMPTY_EXTENSION_REGISTRY,
|
|
4858
5355
|
ENUM_STORAGES,
|
|
5356
|
+
FAILURE_KINDS,
|
|
4859
5357
|
IDENTIFIER_LIMITS,
|
|
4860
5358
|
INCLUDE_INDEX_KINDS,
|
|
4861
5359
|
MYSQL_CAPABILITIES,
|
|
@@ -4910,13 +5408,17 @@ export {
|
|
|
4910
5408
|
defaultRowRuleName,
|
|
4911
5409
|
defineExtension,
|
|
4912
5410
|
dialectCollation,
|
|
5411
|
+
didYouMean,
|
|
5412
|
+
editDistance,
|
|
4913
5413
|
encodePrismaString,
|
|
4914
5414
|
enumStorageOf,
|
|
4915
5415
|
exactDecimalLiteral,
|
|
4916
5416
|
exactIntegerLiteral,
|
|
5417
|
+
exclusionFields,
|
|
4917
5418
|
extensionDeclarations,
|
|
4918
5419
|
extensionManifestEntry,
|
|
4919
5420
|
extensionOptionsHash,
|
|
5421
|
+
failureKindOf,
|
|
4920
5422
|
fieldTypeIdentity,
|
|
4921
5423
|
fitDefaultName,
|
|
4922
5424
|
generatedColumnFromSql,
|
|
@@ -4939,6 +5441,7 @@ export {
|
|
|
4939
5441
|
internalError,
|
|
4940
5442
|
invalidStoredData,
|
|
4941
5443
|
isCanonicalLocalDate,
|
|
5444
|
+
isConnectionFailureReason,
|
|
4942
5445
|
isEnumType,
|
|
4943
5446
|
isExpressionIndex,
|
|
4944
5447
|
isImplicitManyToManyRelation,
|
|
@@ -4950,17 +5453,20 @@ export {
|
|
|
4950
5453
|
isSqlObjectDefinition,
|
|
4951
5454
|
isSqlObjectIdentity,
|
|
4952
5455
|
isToastStorageKey,
|
|
5456
|
+
isUnknownNameRefusal,
|
|
4953
5457
|
jsonSchemaRefIssue,
|
|
4954
5458
|
jsonTypeAnnotationIssue,
|
|
4955
5459
|
jsonTypeAnnotationRef,
|
|
4956
5460
|
localDateCheckName,
|
|
4957
5461
|
mergeExtensionDeclarations,
|
|
4958
5462
|
modelSqlNamespace,
|
|
5463
|
+
modelUniqueKeys,
|
|
4959
5464
|
mysqlIndexKeyWidth,
|
|
4960
5465
|
mysqlRowRuleMessageByteLength,
|
|
4961
5466
|
normalizeJsonSchemaRef,
|
|
4962
5467
|
normalizeRowRules,
|
|
4963
5468
|
normalizeValidatorRef,
|
|
5469
|
+
normalizeWhere,
|
|
4964
5470
|
parseTableStorageValue,
|
|
4965
5471
|
postgresGeneratedObjectName,
|
|
4966
5472
|
predicateCapabilityIssue,
|
|
@@ -4984,12 +5490,14 @@ export {
|
|
|
4984
5490
|
rowRuleTriggerName,
|
|
4985
5491
|
scalarListDefault,
|
|
4986
5492
|
schemaRowRuleIdentities,
|
|
5493
|
+
sealSchemaIR,
|
|
4987
5494
|
serializeJsonDefault,
|
|
4988
5495
|
setDefaultRelationOf,
|
|
4989
5496
|
sqlNamespaceIssue,
|
|
4990
5497
|
sqlObjectKey,
|
|
4991
5498
|
sqlObjectNamespace,
|
|
4992
5499
|
sqliteRowRuleConstraint,
|
|
5500
|
+
suggestName,
|
|
4993
5501
|
tableStorageEntries,
|
|
4994
5502
|
tableStorageKeyFromPrisma,
|
|
4995
5503
|
tableStoragePrismaKey,
|
|
@@ -5001,7 +5509,8 @@ export {
|
|
|
5001
5509
|
validateRlsContextIR,
|
|
5002
5510
|
validateRowRules,
|
|
5003
5511
|
validateSchemaIR,
|
|
5004
|
-
validatorRefIssue
|
|
5512
|
+
validatorRefIssue,
|
|
5513
|
+
withSuggestion
|
|
5005
5514
|
};
|
|
5006
5515
|
|
|
5007
|
-
//# debugId=
|
|
5516
|
+
//# debugId=D9E0341E199A9F8664756E2164756E21
|