@vibeorm/schema 2.0.0-alpha.6 → 2.0.0-alpha.8
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/README.md +1 -1
- package/dist/capabilities.d.ts +10 -3
- package/dist/capabilities.d.ts.map +1 -1
- package/dist/errors.d.ts +99 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/index.d.ts +11 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +697 -14
- package/dist/index.js.map +10 -8
- package/dist/ir.d.ts +54 -0
- package/dist/ir.d.ts.map +1 -1
- package/dist/m2m.d.ts +10 -1
- package/dist/m2m.d.ts.map +1 -1
- package/dist/prisma-literal.d.ts +59 -0
- package/dist/prisma-literal.d.ts.map +1 -0
- package/dist/reserved.d.ts.map +1 -1
- package/dist/validate.d.ts +26 -1
- package/dist/validate.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -16,18 +16,26 @@ function providerToDialect(params) {
|
|
|
16
16
|
function isEnumType(fieldType) {
|
|
17
17
|
return typeof fieldType === "object" && "enum" in fieldType;
|
|
18
18
|
}
|
|
19
|
+
var ENUM_STORAGES = ["database", "string"];
|
|
20
|
+
function enumStorageOf(params) {
|
|
21
|
+
return params.enumDef.storage ?? "database";
|
|
22
|
+
}
|
|
19
23
|
// packages/schema/src/errors.ts
|
|
20
24
|
var VIBE_ERROR_CODES = [
|
|
21
25
|
"VIBE_NOT_FOUND",
|
|
22
26
|
"VIBE_UNIQUE_VIOLATION",
|
|
23
27
|
"VIBE_FK_VIOLATION",
|
|
24
28
|
"VIBE_VALIDATION",
|
|
29
|
+
"VIBE_DATA_INVALID",
|
|
25
30
|
"VIBE_SCHEMA_INVALID",
|
|
26
31
|
"VIBE_UNSUPPORTED_CAPABILITY",
|
|
27
32
|
"VIBE_STALE_CLIENT",
|
|
28
33
|
"VIBE_CONFIG",
|
|
29
34
|
"VIBE_MIGRATION",
|
|
30
35
|
"VIBE_TRANSACTION",
|
|
36
|
+
"VIBE_SCOPED",
|
|
37
|
+
"VIBE_RLS_CONTEXT",
|
|
38
|
+
"VIBE_PERMISSION_DENIED",
|
|
31
39
|
"VIBE_ADAPTER",
|
|
32
40
|
"VIBE_INTERNAL"
|
|
33
41
|
];
|
|
@@ -50,6 +58,23 @@ function unsupportedCapability(params) {
|
|
|
50
58
|
meta: { dialect, feature }
|
|
51
59
|
});
|
|
52
60
|
}
|
|
61
|
+
var STORED_VALUE_PREVIEW_LENGTH = 80;
|
|
62
|
+
function describeStoredValue(params) {
|
|
63
|
+
const { value } = params;
|
|
64
|
+
if (typeof value !== "string")
|
|
65
|
+
return value === null ? "null" : typeof value;
|
|
66
|
+
return value.length > STORED_VALUE_PREVIEW_LENGTH ? `${value.slice(0, STORED_VALUE_PREVIEW_LENGTH)}\u2026` : value;
|
|
67
|
+
}
|
|
68
|
+
function invalidStoredData(params) {
|
|
69
|
+
const { model, field, enum: enumName, value } = params;
|
|
70
|
+
const preview = describeStoredValue({ value });
|
|
71
|
+
const invariant = enumName === undefined ? "the schema's invariant" : `enum ${enumName}`;
|
|
72
|
+
return new VibeError({
|
|
73
|
+
code: "VIBE_DATA_INVALID",
|
|
74
|
+
message: `Stored value on ${model}.${field} violates ${invariant}: ${JSON.stringify(preview)} \u2014 clean the rows (or stop the writer) before reading them through the ORM`,
|
|
75
|
+
meta: { model, field, ...enumName === undefined ? {} : { enum: enumName }, value: preview }
|
|
76
|
+
});
|
|
77
|
+
}
|
|
53
78
|
function internalError(params) {
|
|
54
79
|
return new VibeError({
|
|
55
80
|
code: "VIBE_INTERNAL",
|
|
@@ -57,6 +82,154 @@ function internalError(params) {
|
|
|
57
82
|
meta: params.meta
|
|
58
83
|
});
|
|
59
84
|
}
|
|
85
|
+
var RLS_CONTEXT_REASONS = Object.freeze([
|
|
86
|
+
"missing",
|
|
87
|
+
"invalid",
|
|
88
|
+
"expired",
|
|
89
|
+
"conflicting"
|
|
90
|
+
]);
|
|
91
|
+
|
|
92
|
+
class RlsContextError extends VibeError {
|
|
93
|
+
reason;
|
|
94
|
+
constructor(params) {
|
|
95
|
+
super({
|
|
96
|
+
code: "VIBE_RLS_CONTEXT",
|
|
97
|
+
message: `Native RLS context is ${params.reason}${params.key === undefined ? "" : ` at key ${JSON.stringify(params.key)}`}`,
|
|
98
|
+
meta: { reason: params.reason, ...params.key === undefined ? {} : { key: params.key } }
|
|
99
|
+
});
|
|
100
|
+
this.name = "RlsContextError";
|
|
101
|
+
this.reason = params.reason;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
var SCOPED_REFUSAL_REASONS = [
|
|
105
|
+
"policy_conflict",
|
|
106
|
+
"unclassified_model",
|
|
107
|
+
"unknown_model",
|
|
108
|
+
"unknown_column",
|
|
109
|
+
"column_not_scopeable",
|
|
110
|
+
"unknown_relation",
|
|
111
|
+
"through_chain_invalid",
|
|
112
|
+
"invalid_entry",
|
|
113
|
+
"scope_type_mismatch",
|
|
114
|
+
"null_scope",
|
|
115
|
+
"raw_forbidden",
|
|
116
|
+
"rescope_forbidden",
|
|
117
|
+
"explicit_scope_mismatch",
|
|
118
|
+
"through_fk_write",
|
|
119
|
+
"nested_refused",
|
|
120
|
+
"relation_orderby_on_scoped",
|
|
121
|
+
"count_on_scoped_relation"
|
|
122
|
+
];
|
|
123
|
+
|
|
124
|
+
class ScopedQueryError extends VibeError {
|
|
125
|
+
model;
|
|
126
|
+
path;
|
|
127
|
+
reason;
|
|
128
|
+
constructor(params) {
|
|
129
|
+
super({
|
|
130
|
+
code: "VIBE_SCOPED",
|
|
131
|
+
message: params.message,
|
|
132
|
+
meta: { ...params.meta, model: params.model, path: params.path, reason: params.reason }
|
|
133
|
+
});
|
|
134
|
+
this.name = "ScopedQueryError";
|
|
135
|
+
this.model = params.model;
|
|
136
|
+
this.path = params.path;
|
|
137
|
+
this.reason = params.reason;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
// packages/schema/src/prisma-literal.ts
|
|
141
|
+
var STRING_ESCAPES = {
|
|
142
|
+
'"': '"',
|
|
143
|
+
"'": "'",
|
|
144
|
+
"\\": "\\",
|
|
145
|
+
"/": "/",
|
|
146
|
+
n: `
|
|
147
|
+
`,
|
|
148
|
+
r: "\r",
|
|
149
|
+
t: "\t",
|
|
150
|
+
b: "\b",
|
|
151
|
+
f: "\f"
|
|
152
|
+
};
|
|
153
|
+
function malformed(params) {
|
|
154
|
+
return new VibeError({
|
|
155
|
+
code: "VIBE_SCHEMA_INVALID",
|
|
156
|
+
message: `Malformed string literal ${JSON.stringify(params.raw)}: ${params.detail}`,
|
|
157
|
+
meta: { issues: [{ rule: "malformed-string-literal", message: params.detail }], literal: params.raw }
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
function decodePrismaString(params) {
|
|
161
|
+
const { raw } = params;
|
|
162
|
+
const quoted = raw.length >= 2 && raw.startsWith('"') && raw.endsWith('"');
|
|
163
|
+
const body = quoted ? raw.slice(1, -1) : raw;
|
|
164
|
+
if (!body.includes("\\"))
|
|
165
|
+
return body;
|
|
166
|
+
let out = "";
|
|
167
|
+
for (let index = 0;index < body.length; index += 1) {
|
|
168
|
+
const char = body[index];
|
|
169
|
+
if (char !== "\\") {
|
|
170
|
+
out += char;
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
const next = body[index + 1];
|
|
174
|
+
if (next === undefined)
|
|
175
|
+
throw malformed({ raw, detail: "it ends with a lone backslash" });
|
|
176
|
+
if (next === "u") {
|
|
177
|
+
const digits = body.slice(index + 2, index + 6);
|
|
178
|
+
if (!/^[0-9a-fA-F]{4}$/.test(digits)) {
|
|
179
|
+
throw malformed({ raw, detail: `\\u must be followed by four hex digits, found "${digits}"` });
|
|
180
|
+
}
|
|
181
|
+
out += String.fromCharCode(Number.parseInt(digits, 16));
|
|
182
|
+
index += 5;
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
const decoded = STRING_ESCAPES[next];
|
|
186
|
+
if (decoded === undefined)
|
|
187
|
+
throw malformed({ raw, detail: `unknown escape "\\${next}"` });
|
|
188
|
+
out += decoded;
|
|
189
|
+
index += 1;
|
|
190
|
+
}
|
|
191
|
+
return out;
|
|
192
|
+
}
|
|
193
|
+
function unicodeEscape(params) {
|
|
194
|
+
return `\\u${params.char.charCodeAt(0).toString(16).padStart(4, "0")}`;
|
|
195
|
+
}
|
|
196
|
+
function encodePrismaString(params) {
|
|
197
|
+
const { value } = params;
|
|
198
|
+
let out = '"';
|
|
199
|
+
for (const char of value) {
|
|
200
|
+
if (char === "\\")
|
|
201
|
+
out += "\\\\";
|
|
202
|
+
else if (char === '"')
|
|
203
|
+
out += "\\\"";
|
|
204
|
+
else if (char === `
|
|
205
|
+
`)
|
|
206
|
+
out += "\\n";
|
|
207
|
+
else if (char === "\r")
|
|
208
|
+
out += "\\r";
|
|
209
|
+
else if (char === "\t")
|
|
210
|
+
out += "\\t";
|
|
211
|
+
else if (char < " " || char === "\x7F")
|
|
212
|
+
out += unicodeEscape({ char });
|
|
213
|
+
else
|
|
214
|
+
out += char;
|
|
215
|
+
}
|
|
216
|
+
return `${out}"`;
|
|
217
|
+
}
|
|
218
|
+
var INTEGER_LITERAL = /^-?\d+$/;
|
|
219
|
+
function exactIntegerLiteral(params) {
|
|
220
|
+
const { text } = params;
|
|
221
|
+
if (!INTEGER_LITERAL.test(text)) {
|
|
222
|
+
throw new VibeError({
|
|
223
|
+
code: "VIBE_SCHEMA_INVALID",
|
|
224
|
+
message: `Not an integer literal: ${JSON.stringify(text)}`,
|
|
225
|
+
meta: { issues: [{ rule: "malformed-integer-literal", message: text }], literal: text }
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
const asNumber = Number(text);
|
|
229
|
+
if (Number.isSafeInteger(asNumber))
|
|
230
|
+
return asNumber;
|
|
231
|
+
return BigInt(text).toString();
|
|
232
|
+
}
|
|
60
233
|
// packages/schema/src/reserved.ts
|
|
61
234
|
var RESERVED_DELEGATE_NAMES = [
|
|
62
235
|
"findMany",
|
|
@@ -69,6 +242,7 @@ var RESERVED_DELEGATE_NAMES = [
|
|
|
69
242
|
"createManyAndReturn",
|
|
70
243
|
"update",
|
|
71
244
|
"updateMany",
|
|
245
|
+
"updateManyAndReturn",
|
|
72
246
|
"upsert",
|
|
73
247
|
"delete",
|
|
74
248
|
"deleteMany",
|
|
@@ -89,7 +263,8 @@ var RESERVED_CLIENT_NAMES = [
|
|
|
89
263
|
"$extends",
|
|
90
264
|
"$defineView",
|
|
91
265
|
"$withPolicy",
|
|
92
|
-
"$bypassPolicy"
|
|
266
|
+
"$bypassPolicy",
|
|
267
|
+
"$scoped"
|
|
93
268
|
];
|
|
94
269
|
var RESERVED_COLUMN_PREFIX = "__vibe_";
|
|
95
270
|
function isReservedDelegateName(params) {
|
|
@@ -292,7 +467,260 @@ function validateComputedConfig(params) {
|
|
|
292
467
|
});
|
|
293
468
|
}
|
|
294
469
|
}
|
|
470
|
+
// packages/schema/src/capabilities.ts
|
|
471
|
+
var POSTGRES_CAPABILITIES = Object.freeze({
|
|
472
|
+
nativeRowLevelSecurity: true,
|
|
473
|
+
returning: true,
|
|
474
|
+
scalarArrays: true,
|
|
475
|
+
nativeEnums: true,
|
|
476
|
+
ilike: true,
|
|
477
|
+
lateralJoin: true,
|
|
478
|
+
distinctOn: true,
|
|
479
|
+
partialIndexes: true,
|
|
480
|
+
conflictTargetConstraint: true,
|
|
481
|
+
transactionalDdl: true,
|
|
482
|
+
createManyAndReturn: true,
|
|
483
|
+
jsonColumnType: true,
|
|
484
|
+
orderByNulls: true,
|
|
485
|
+
fullTextEngines: Object.freeze(["bm25", "tsvector"])
|
|
486
|
+
});
|
|
487
|
+
var SQLITE_CAPABILITIES = Object.freeze({
|
|
488
|
+
nativeRowLevelSecurity: false,
|
|
489
|
+
returning: true,
|
|
490
|
+
scalarArrays: false,
|
|
491
|
+
nativeEnums: false,
|
|
492
|
+
ilike: false,
|
|
493
|
+
lateralJoin: false,
|
|
494
|
+
distinctOn: false,
|
|
495
|
+
partialIndexes: true,
|
|
496
|
+
conflictTargetConstraint: false,
|
|
497
|
+
transactionalDdl: true,
|
|
498
|
+
createManyAndReturn: true,
|
|
499
|
+
jsonColumnType: false,
|
|
500
|
+
orderByNulls: true,
|
|
501
|
+
fullTextEngines: Object.freeze(["fts5"])
|
|
502
|
+
});
|
|
503
|
+
var MYSQL_CAPABILITIES = Object.freeze({
|
|
504
|
+
nativeRowLevelSecurity: false,
|
|
505
|
+
returning: false,
|
|
506
|
+
scalarArrays: false,
|
|
507
|
+
nativeEnums: true,
|
|
508
|
+
ilike: false,
|
|
509
|
+
lateralJoin: false,
|
|
510
|
+
distinctOn: false,
|
|
511
|
+
partialIndexes: false,
|
|
512
|
+
conflictTargetConstraint: false,
|
|
513
|
+
transactionalDdl: false,
|
|
514
|
+
createManyAndReturn: false,
|
|
515
|
+
jsonColumnType: true,
|
|
516
|
+
orderByNulls: false,
|
|
517
|
+
fullTextEngines: Object.freeze(["fulltext"])
|
|
518
|
+
});
|
|
519
|
+
var DIALECT_CAPABILITIES = Object.freeze({
|
|
520
|
+
postgres: POSTGRES_CAPABILITIES,
|
|
521
|
+
sqlite: SQLITE_CAPABILITIES,
|
|
522
|
+
mysql: MYSQL_CAPABILITIES
|
|
523
|
+
});
|
|
524
|
+
|
|
295
525
|
// packages/schema/src/validate.ts
|
|
526
|
+
var RESERVED_ENUM_NAMES = [
|
|
527
|
+
"enumValidators",
|
|
528
|
+
"enumValidator",
|
|
529
|
+
"OmittedKeys",
|
|
530
|
+
"ExactKeys",
|
|
531
|
+
"PossibleKeys",
|
|
532
|
+
"UncertainKeys",
|
|
533
|
+
"HasSelectedField",
|
|
534
|
+
"Provided",
|
|
535
|
+
"ViewDelegateMap",
|
|
536
|
+
"extensionManifest",
|
|
537
|
+
"extensionMounts",
|
|
538
|
+
"computedManifest",
|
|
539
|
+
"Object",
|
|
540
|
+
"Set",
|
|
541
|
+
"JSON",
|
|
542
|
+
"Record",
|
|
543
|
+
"Readonly",
|
|
544
|
+
"ReadonlyArray",
|
|
545
|
+
"Partial",
|
|
546
|
+
"Omit",
|
|
547
|
+
"NonNullable",
|
|
548
|
+
"Promise",
|
|
549
|
+
"PromiseLike",
|
|
550
|
+
"Awaited",
|
|
551
|
+
"TemplateStringsArray",
|
|
552
|
+
"Date",
|
|
553
|
+
"Uint8Array",
|
|
554
|
+
"schema",
|
|
555
|
+
"VibeClient",
|
|
556
|
+
"VibeClientInstance",
|
|
557
|
+
"VibeClientOptions",
|
|
558
|
+
"VibeError",
|
|
559
|
+
"VibeErrorCode",
|
|
560
|
+
"BatchPayload",
|
|
561
|
+
"UpsertManyPayload",
|
|
562
|
+
"QueryMode",
|
|
563
|
+
"RelationStrategy",
|
|
564
|
+
"SortOrder",
|
|
565
|
+
"SortOrderWithNulls",
|
|
566
|
+
"KeysetToken",
|
|
567
|
+
"KeysetOptions",
|
|
568
|
+
"JsonValue",
|
|
569
|
+
"InputJsonValue",
|
|
570
|
+
"InputJsonArray",
|
|
571
|
+
"InputJsonObject",
|
|
572
|
+
"VibeTelemetryOptions",
|
|
573
|
+
"VibeTelemetryExporter",
|
|
574
|
+
"VibeTelemetryOperationEvent",
|
|
575
|
+
"VibeTelemetryStatementEvent",
|
|
576
|
+
"VibeTelemetryHandle",
|
|
577
|
+
"ScopedClientInstance",
|
|
578
|
+
"ScopedModelsConfig",
|
|
579
|
+
"ScopedNestedMode",
|
|
580
|
+
"ViewClient",
|
|
581
|
+
"ViewDefinitionInput",
|
|
582
|
+
"ViewRow",
|
|
583
|
+
"createClient",
|
|
584
|
+
"DatabaseAdapter",
|
|
585
|
+
"DbNow",
|
|
586
|
+
"QueryEvent",
|
|
587
|
+
"Skip",
|
|
588
|
+
"TransactionOptions",
|
|
589
|
+
"SchemaIR",
|
|
590
|
+
"VibeExtension",
|
|
591
|
+
"ComputedConfig",
|
|
592
|
+
"WriteValidators",
|
|
593
|
+
"String",
|
|
594
|
+
"Bool",
|
|
595
|
+
"Int",
|
|
596
|
+
"BigInt",
|
|
597
|
+
"Float",
|
|
598
|
+
"Decimal",
|
|
599
|
+
"DateTime",
|
|
600
|
+
"Json",
|
|
601
|
+
"Bytes",
|
|
602
|
+
...["String", "Bool", "Int", "BigInt", "Float", "Decimal", "DateTime", "Json", "Bytes"].flatMap((prefix) => ["Filter", "NullableFilter", "ListFilter"].map((suffix) => `${prefix}${suffix}`)),
|
|
603
|
+
...["Int", "Float", "BigInt", "Decimal"].flatMap((prefix) => [`${prefix}FieldUpdateOperationsInput`, `Nullable${prefix}FieldUpdateOperationsInput`])
|
|
604
|
+
];
|
|
605
|
+
var GENERATED_TYPE_NAMES = {
|
|
606
|
+
enumSuffixes: ["", "Filter", "NullableFilter", "ListFilter", "Validator"],
|
|
607
|
+
modelSuffixes: [
|
|
608
|
+
"",
|
|
609
|
+
"ScalarFieldEnum",
|
|
610
|
+
"SelectableFieldEnum",
|
|
611
|
+
"Relations",
|
|
612
|
+
"CountSelect",
|
|
613
|
+
"Select",
|
|
614
|
+
"Include",
|
|
615
|
+
"OmitInput",
|
|
616
|
+
"Args",
|
|
617
|
+
"ListRelationFilter",
|
|
618
|
+
"RelationFilter",
|
|
619
|
+
"WhereInput",
|
|
620
|
+
"WhereUniqueInput",
|
|
621
|
+
"OrderByInput",
|
|
622
|
+
"CreateInput",
|
|
623
|
+
"UncheckedCreateInput",
|
|
624
|
+
"CreateManyInput",
|
|
625
|
+
"UpdateInput",
|
|
626
|
+
"UncheckedUpdateInput",
|
|
627
|
+
"UpdateManyInput",
|
|
628
|
+
"CountAggregateInput",
|
|
629
|
+
"AvgAggregateInput",
|
|
630
|
+
"SumAggregateInput",
|
|
631
|
+
"MinAggregateInput",
|
|
632
|
+
"MaxAggregateInput",
|
|
633
|
+
"FindManyArgs",
|
|
634
|
+
"FindFirstArgs",
|
|
635
|
+
"FindUniqueArgs",
|
|
636
|
+
"CreateArgs",
|
|
637
|
+
"ConflictTarget",
|
|
638
|
+
"CreateOnConflictInput",
|
|
639
|
+
"CreateOrSkipArgs",
|
|
640
|
+
"CreateManyArgs",
|
|
641
|
+
"CreateManyAndReturnArgs",
|
|
642
|
+
"UpdateArgs",
|
|
643
|
+
"UpdateManyArgs",
|
|
644
|
+
"UpdateWhereInput",
|
|
645
|
+
"UpdateManyAndReturnArgs",
|
|
646
|
+
"UpsertArgs",
|
|
647
|
+
"UpsertManyArgs",
|
|
648
|
+
"DeleteArgs",
|
|
649
|
+
"DeleteManyArgs",
|
|
650
|
+
"CountArgs",
|
|
651
|
+
"AggregateArgs",
|
|
652
|
+
"GroupByArgs",
|
|
653
|
+
"OmitBase",
|
|
654
|
+
"CountResult",
|
|
655
|
+
"CountPayload",
|
|
656
|
+
"AggregateValues",
|
|
657
|
+
"AggregateSelection",
|
|
658
|
+
"CountOutput",
|
|
659
|
+
"RelationPayload",
|
|
660
|
+
"IncludePayload",
|
|
661
|
+
"GetPayload",
|
|
662
|
+
"AggregateResult",
|
|
663
|
+
"GroupByResult",
|
|
664
|
+
"Delegate",
|
|
665
|
+
"ViewFields",
|
|
666
|
+
"ViewSelect",
|
|
667
|
+
"ViewInclude",
|
|
668
|
+
"ViewNestedArgs",
|
|
669
|
+
"ViewFindManyArgs",
|
|
670
|
+
"ViewFindUniqueArgs",
|
|
671
|
+
"ViewScalars",
|
|
672
|
+
"ViewSelectScalars",
|
|
673
|
+
"ViewReveal",
|
|
674
|
+
"ViewRelationResult",
|
|
675
|
+
"ViewIncludeResult",
|
|
676
|
+
"ViewResult",
|
|
677
|
+
"ViewDelegate"
|
|
678
|
+
],
|
|
679
|
+
nestedPrefixes: [
|
|
680
|
+
"Create",
|
|
681
|
+
"UncheckedCreate",
|
|
682
|
+
"Update",
|
|
683
|
+
"UncheckedUpdate",
|
|
684
|
+
"ConnectOrCreate",
|
|
685
|
+
"CreateNestedMany",
|
|
686
|
+
"UpdateNestedMany",
|
|
687
|
+
"CreateNestedOne",
|
|
688
|
+
"UpdateNestedOne",
|
|
689
|
+
"UpdateWithWhereUnique",
|
|
690
|
+
"UpdateManyWithWhere",
|
|
691
|
+
"UpsertWithWhereUnique"
|
|
692
|
+
]
|
|
693
|
+
};
|
|
694
|
+
function validateGeneratedNames(params) {
|
|
695
|
+
const { schema, issues } = params;
|
|
696
|
+
const owners = new Map(RESERVED_ENUM_NAMES.map((name) => [name, "generated client"]));
|
|
697
|
+
if (schema.rls !== undefined) {
|
|
698
|
+
owners.set("RlsContext", "native RLS client");
|
|
699
|
+
owners.set("BoundVibeClientInstance", "native RLS client");
|
|
700
|
+
}
|
|
701
|
+
const register = (params2) => {
|
|
702
|
+
const previous = owners.get(params2.name);
|
|
703
|
+
if (previous !== undefined && previous !== params2.owner) {
|
|
704
|
+
issues.push({ rule: "generated-name-collision", message: `Generated name "${params2.name}" from ${params2.owner} conflicts with ${previous}` });
|
|
705
|
+
} else {
|
|
706
|
+
owners.set(params2.name, params2.owner);
|
|
707
|
+
}
|
|
708
|
+
};
|
|
709
|
+
for (const model of schema.models) {
|
|
710
|
+
const owner = `model "${model.name}"`;
|
|
711
|
+
for (const suffix of GENERATED_TYPE_NAMES.modelSuffixes)
|
|
712
|
+
register({ name: `${model.name}${suffix}`, owner });
|
|
713
|
+
const withouts = ["", ...model.relations.map((relation) => `Without${relation.name.charAt(0).toUpperCase()}${relation.name.slice(1)}`)];
|
|
714
|
+
for (const without of withouts) {
|
|
715
|
+
for (const prefix of GENERATED_TYPE_NAMES.nestedPrefixes)
|
|
716
|
+
register({ name: `${model.name}${prefix}${without}Input`, owner });
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
for (const declared of schema.enums) {
|
|
720
|
+
for (const suffix of GENERATED_TYPE_NAMES.enumSuffixes)
|
|
721
|
+
register({ name: `${declared.name}${suffix}`, owner: `enum "${declared.name}"` });
|
|
722
|
+
}
|
|
723
|
+
}
|
|
296
724
|
function validateSchemaIR(params) {
|
|
297
725
|
const { schema } = params;
|
|
298
726
|
const issues = [];
|
|
@@ -308,15 +736,15 @@ function validateSchemaIR(params) {
|
|
|
308
736
|
modelByName.set(model.name, model);
|
|
309
737
|
}
|
|
310
738
|
}
|
|
311
|
-
const
|
|
739
|
+
const enumByName = new Map;
|
|
312
740
|
for (const enumDef of schema.enums) {
|
|
313
|
-
if (
|
|
741
|
+
if (enumByName.has(enumDef.name)) {
|
|
314
742
|
issues.push({
|
|
315
743
|
rule: "duplicate-enum",
|
|
316
744
|
message: `Duplicate enum name "${enumDef.name}"`
|
|
317
745
|
});
|
|
318
746
|
} else {
|
|
319
|
-
|
|
747
|
+
enumByName.set(enumDef.name, enumDef);
|
|
320
748
|
}
|
|
321
749
|
if (enumDef.values.length === 0) {
|
|
322
750
|
issues.push({
|
|
@@ -324,9 +752,52 @@ function validateSchemaIR(params) {
|
|
|
324
752
|
message: `Enum "${enumDef.name}" has no values`
|
|
325
753
|
});
|
|
326
754
|
}
|
|
755
|
+
const seenValues = new Set;
|
|
756
|
+
for (const value of enumDef.values) {
|
|
757
|
+
if (seenValues.has(value)) {
|
|
758
|
+
issues.push({
|
|
759
|
+
rule: "duplicate-enum-value",
|
|
760
|
+
message: `Enum "${enumDef.name}" lists value "${value}" more than once`
|
|
761
|
+
});
|
|
762
|
+
}
|
|
763
|
+
seenValues.add(value);
|
|
764
|
+
}
|
|
765
|
+
if (enumDef.storage !== undefined && !ENUM_STORAGES.includes(enumDef.storage)) {
|
|
766
|
+
issues.push({
|
|
767
|
+
rule: "invalid-enum-storage",
|
|
768
|
+
message: `Enum "${enumDef.name}" has storage ${JSON.stringify(enumDef.storage)} \u2014 expected one of ${ENUM_STORAGES.join(", ")}`
|
|
769
|
+
});
|
|
770
|
+
}
|
|
771
|
+
if (modelByName.has(enumDef.name)) {
|
|
772
|
+
issues.push({
|
|
773
|
+
rule: "enum-model-name-collision",
|
|
774
|
+
message: `Enum "${enumDef.name}" shares its name with a model \u2014 the generated client exports one type per name`,
|
|
775
|
+
model: enumDef.name
|
|
776
|
+
});
|
|
777
|
+
}
|
|
778
|
+
if (RESERVED_ENUM_NAMES.includes(enumDef.name)) {
|
|
779
|
+
issues.push({
|
|
780
|
+
rule: "enum-reserved-name",
|
|
781
|
+
message: `Enum "${enumDef.name}" collides with a name the generated client already exports or imports`
|
|
782
|
+
});
|
|
783
|
+
}
|
|
327
784
|
}
|
|
328
785
|
for (const model of schema.models) {
|
|
329
|
-
validateModel({ model, modelByName,
|
|
786
|
+
validateModel({ model, modelByName, enumByName, issues });
|
|
787
|
+
}
|
|
788
|
+
for (const model of schema.models) {
|
|
789
|
+
for (const relation of model.relations) {
|
|
790
|
+
if (relation.targetModel !== model.name)
|
|
791
|
+
continue;
|
|
792
|
+
if (!isImplicitManyToManyRelation({ model, relation, models: schema.models }))
|
|
793
|
+
continue;
|
|
794
|
+
issues.push({
|
|
795
|
+
rule: "implicit-self-many-to-many",
|
|
796
|
+
message: `Relation "${model.name}.${relation.name}" is an implicit self many-to-many. Both sides of a self ` + `relation own the same join-table column, so this field and its inverse read the same rows. Replace ` + `it with an explicit junction model carrying one foreign key per direction, each under its own ` + `@relation name, and point "${relation.name}" at that model. Worked example, and the row copy for a ` + `join table that already exists: docs/queries.md, "Directed self relations".`,
|
|
797
|
+
model: model.name,
|
|
798
|
+
field: relation.name
|
|
799
|
+
});
|
|
800
|
+
}
|
|
330
801
|
}
|
|
331
802
|
const provider = schema.datasource.provider;
|
|
332
803
|
for (const model of schema.models) {
|
|
@@ -424,10 +895,12 @@ function validateSchemaIR(params) {
|
|
|
424
895
|
});
|
|
425
896
|
}
|
|
426
897
|
}
|
|
898
|
+
validateGeneratedNames({ schema, issues });
|
|
899
|
+
validateNativeRls({ schema, issues });
|
|
427
900
|
return issues;
|
|
428
901
|
}
|
|
429
902
|
function validateModel(params) {
|
|
430
|
-
const { model, modelByName,
|
|
903
|
+
const { model, modelByName, enumByName, issues } = params;
|
|
431
904
|
const memberNames = new Set;
|
|
432
905
|
for (const field of model.fields) {
|
|
433
906
|
if (memberNames.has(field.name)) {
|
|
@@ -439,13 +912,27 @@ function validateModel(params) {
|
|
|
439
912
|
});
|
|
440
913
|
}
|
|
441
914
|
memberNames.add(field.name);
|
|
442
|
-
if (isEnumType(field.type)
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
915
|
+
if (isEnumType(field.type)) {
|
|
916
|
+
const enumDef = enumByName.get(field.type.enum);
|
|
917
|
+
if (enumDef === undefined) {
|
|
918
|
+
issues.push({
|
|
919
|
+
rule: "unknown-enum",
|
|
920
|
+
message: `Field "${model.name}.${field.name}" references unknown enum "${field.type.enum}"`,
|
|
921
|
+
model: model.name,
|
|
922
|
+
field: field.name
|
|
923
|
+
});
|
|
924
|
+
} else {
|
|
925
|
+
const defaultValue = field.default;
|
|
926
|
+
const candidate = defaultValue === undefined ? undefined : defaultValue.kind === "enumValue" ? defaultValue.value : defaultValue.kind === "literal" && typeof defaultValue.value === "string" ? defaultValue.value : undefined;
|
|
927
|
+
if (candidate !== undefined && !enumDef.values.includes(candidate)) {
|
|
928
|
+
issues.push({
|
|
929
|
+
rule: "enum-default-not-member",
|
|
930
|
+
message: `Default "${candidate}" on "${model.name}.${field.name}" is not a member of enum "${enumDef.name}" (${enumDef.values.join(", ")})`,
|
|
931
|
+
model: model.name,
|
|
932
|
+
field: field.name
|
|
933
|
+
});
|
|
934
|
+
}
|
|
935
|
+
}
|
|
449
936
|
}
|
|
450
937
|
const columnName = field.dbName ?? field.name;
|
|
451
938
|
if (columnName.startsWith(RESERVED_COLUMN_PREFIX)) {
|
|
@@ -609,6 +1096,10 @@ function validateModel(params) {
|
|
|
609
1096
|
}
|
|
610
1097
|
}
|
|
611
1098
|
function assertValidSchemaIR(params) {
|
|
1099
|
+
const dialect = providerToDialect({ provider: params.schema.datasource.provider });
|
|
1100
|
+
if (params.schema.rls !== undefined && !DIALECT_CAPABILITIES[dialect].nativeRowLevelSecurity) {
|
|
1101
|
+
throw unsupportedCapability({ dialect, feature: "nativeRowLevelSecurity" });
|
|
1102
|
+
}
|
|
612
1103
|
const issues = validateSchemaIR(params);
|
|
613
1104
|
if (issues.length > 0) {
|
|
614
1105
|
throw new VibeError({
|
|
@@ -618,6 +1109,181 @@ function assertValidSchemaIR(params) {
|
|
|
618
1109
|
});
|
|
619
1110
|
}
|
|
620
1111
|
}
|
|
1112
|
+
function rlsRecord(value) {
|
|
1113
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null) && Reflect.ownKeys(value).every((key) => {
|
|
1114
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
1115
|
+
return typeof key === "string" && descriptor?.enumerable === true && "value" in descriptor;
|
|
1116
|
+
});
|
|
1117
|
+
}
|
|
1118
|
+
function rlsKeys(params) {
|
|
1119
|
+
const own = Reflect.ownKeys(params.value);
|
|
1120
|
+
return own.length === params.keys.length && params.keys.every((key) => Object.hasOwn(params.value, key));
|
|
1121
|
+
}
|
|
1122
|
+
function validateRlsContextIR(params) {
|
|
1123
|
+
const { context } = params;
|
|
1124
|
+
const issues = [];
|
|
1125
|
+
if (!rlsRecord(context))
|
|
1126
|
+
return [{ rule: "rls-invalid-context", message: "Native RLS context must be a named scalar-slot map" }];
|
|
1127
|
+
const seen = new Set;
|
|
1128
|
+
for (const key of Reflect.ownKeys(context)) {
|
|
1129
|
+
const slot = typeof key === "string" ? context[key] : undefined;
|
|
1130
|
+
if (typeof key !== "string" || !/^[A-Za-z_][A-Za-z0-9_]*$/.test(key) || seen.has(key.toLowerCase()) || !rlsRecord(slot) || !rlsKeys({ value: slot, keys: ["type", "nullable"] }) || typeof slot.nullable !== "boolean" || (typeof slot.type !== "string" || !["String", "Boolean", "Int", "BigInt", "Float", "Decimal", "DateTime"].includes(slot.type))) {
|
|
1131
|
+
issues.push({ rule: "rls-invalid-context", message: `Invalid native RLS context slot ${String(key)}; use distinct setting keys and supported scalar slots with explicit nullable` });
|
|
1132
|
+
}
|
|
1133
|
+
if (typeof key === "string")
|
|
1134
|
+
seen.add(key.toLowerCase());
|
|
1135
|
+
}
|
|
1136
|
+
return issues;
|
|
1137
|
+
}
|
|
1138
|
+
function isImplicitManyToManyRelation(params) {
|
|
1139
|
+
const { model, relation, models } = params;
|
|
1140
|
+
if (model.isView || !relation.isList || (relation.fields?.length ?? 0) !== 0)
|
|
1141
|
+
return false;
|
|
1142
|
+
const target = models.find((candidate) => candidate.name === relation.targetModel);
|
|
1143
|
+
if (target === undefined || target.isView)
|
|
1144
|
+
return false;
|
|
1145
|
+
const counterpart = soleRelationCounterpart({ relation, ownModel: model.name, target });
|
|
1146
|
+
if (counterpart === undefined || !counterpart.isList || (counterpart.fields?.length ?? 0) !== 0)
|
|
1147
|
+
return false;
|
|
1148
|
+
return soleRelationCounterpart({ relation: counterpart, ownModel: target.name, target: model }) === relation;
|
|
1149
|
+
}
|
|
1150
|
+
function soleRelationCounterpart(params) {
|
|
1151
|
+
const { relation, ownModel, target } = params;
|
|
1152
|
+
const candidates = target.relations.filter((candidate) => candidate !== relation && candidate.targetModel === ownModel && candidate.relationName === relation.relationName);
|
|
1153
|
+
return candidates.length === 1 ? candidates[0] : undefined;
|
|
1154
|
+
}
|
|
1155
|
+
function validateNativeRls(params) {
|
|
1156
|
+
const { schema, issues } = params;
|
|
1157
|
+
if (schema.rls === undefined) {
|
|
1158
|
+
if (schema.models.some((model) => model.rls !== undefined)) {
|
|
1159
|
+
issues.push({ rule: "rls-missing-context", message: "Model RLS rules require a schema-level rls.context declaration" });
|
|
1160
|
+
}
|
|
1161
|
+
return;
|
|
1162
|
+
}
|
|
1163
|
+
const dialect = providerToDialect({ provider: schema.datasource.provider });
|
|
1164
|
+
if (!DIALECT_CAPABILITIES[dialect].nativeRowLevelSecurity) {
|
|
1165
|
+
issues.push({ rule: "rls-unsupported-capability", message: `nativeRowLevelSecurity is not supported on ${dialect}` });
|
|
1166
|
+
}
|
|
1167
|
+
if (!rlsRecord(schema.rls) || !rlsKeys({ value: schema.rls, keys: ["context"] })) {
|
|
1168
|
+
issues.push({ rule: "rls-invalid-context", message: "Native RLS supports only a schema-level context declaration" });
|
|
1169
|
+
return;
|
|
1170
|
+
}
|
|
1171
|
+
const contextIssues = validateRlsContextIR({ context: schema.rls.context });
|
|
1172
|
+
issues.push(...contextIssues);
|
|
1173
|
+
const context = contextIssues.length === 0 ? schema.rls.context : undefined;
|
|
1174
|
+
const byName = new Map(schema.models.map((model) => [model.name, model]));
|
|
1175
|
+
const tables = new Set;
|
|
1176
|
+
const throughTargets = new Map;
|
|
1177
|
+
for (const model of schema.models) {
|
|
1178
|
+
const add = (params2) => {
|
|
1179
|
+
issues.push({ ...params2, model: model.name });
|
|
1180
|
+
};
|
|
1181
|
+
const table = model.dbName ?? model.name;
|
|
1182
|
+
if (tables.has(table))
|
|
1183
|
+
add({ rule: "rls-duplicate-table", message: `RLS models share physical table ${table}` });
|
|
1184
|
+
tables.add(table);
|
|
1185
|
+
const columns = new Set;
|
|
1186
|
+
for (const field of model.fields) {
|
|
1187
|
+
const name = field.dbName ?? field.name;
|
|
1188
|
+
if (columns.has(name))
|
|
1189
|
+
add({ rule: "rls-duplicate-column", message: `RLS model ${model.name} repeats physical column ${name}`, field: field.name });
|
|
1190
|
+
columns.add(name);
|
|
1191
|
+
}
|
|
1192
|
+
if (model.policy !== undefined)
|
|
1193
|
+
add({ rule: "rls-policy-conflict", message: "Native RLS cannot combine with application-level ModelIR.policy" });
|
|
1194
|
+
if (model.isView)
|
|
1195
|
+
add({ rule: "rls-view-unsupported", message: "Database views are not supported on native RLS clients; remove the view declaration" });
|
|
1196
|
+
if (model.rls === undefined) {
|
|
1197
|
+
add({ rule: "rls-unclassified-model", message: `Classify ${model.name} as where, through, unprotected or deny` });
|
|
1198
|
+
continue;
|
|
1199
|
+
}
|
|
1200
|
+
if (model.rls !== "unprotected") {
|
|
1201
|
+
for (const relation of model.relations) {
|
|
1202
|
+
if (isImplicitManyToManyRelation({ model, relation, models: schema.models })) {
|
|
1203
|
+
add({ rule: "rls-implicit-many-to-many", message: "Protected implicit many-to-many relations need an explicit junction model with its own rule", field: relation.name });
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
const rule = model.rls;
|
|
1208
|
+
if (rule === "unprotected" || rule === "deny")
|
|
1209
|
+
continue;
|
|
1210
|
+
if (!rlsRecord(rule)) {
|
|
1211
|
+
add({ rule: "rls-invalid-rule", message: "Native RLS accepts where, through, unprotected or deny only" });
|
|
1212
|
+
continue;
|
|
1213
|
+
}
|
|
1214
|
+
if (rlsKeys({ value: rule, keys: ["where"] }) && rlsRecord(rule.where) && Reflect.ownKeys(rule.where).length > 0) {
|
|
1215
|
+
for (const fieldName of Reflect.ownKeys(rule.where)) {
|
|
1216
|
+
const ref = typeof fieldName === "string" ? rule.where[fieldName] : undefined;
|
|
1217
|
+
if (!rlsRecord(ref) || !rlsKeys({ value: ref, keys: ["context"] }) || typeof ref.context !== "string") {
|
|
1218
|
+
add({ rule: "rls-invalid-rule", message: "Ownership equality accepts a context reference only" });
|
|
1219
|
+
continue;
|
|
1220
|
+
}
|
|
1221
|
+
const field = model.fields.find((f) => f.name === fieldName);
|
|
1222
|
+
if (field === undefined) {
|
|
1223
|
+
add({ rule: "rls-unknown-field", message: `Native RLS requires a direct scalar field, not path ${String(fieldName)}` });
|
|
1224
|
+
} else if (field.isList || field.isUnsupported || isEnumType(field.type) || field.type === "Json" || field.type === "Bytes") {
|
|
1225
|
+
add({ rule: "rls-unsupported-field", message: "Native RLS ownership requires a supported non-list scalar", field: field.name });
|
|
1226
|
+
} else if (context !== undefined) {
|
|
1227
|
+
const slot = Object.hasOwn(context, ref.context) ? context[ref.context] : undefined;
|
|
1228
|
+
if (slot === undefined)
|
|
1229
|
+
add({ rule: "rls-unknown-context", message: `Unknown native RLS context key ${ref.context}`, field: field.name });
|
|
1230
|
+
else if (slot.type !== field.type)
|
|
1231
|
+
add({ rule: "rls-context-type-mismatch", message: `Context ${ref.context} does not match ${model.name}.${field.name}`, field: field.name });
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
continue;
|
|
1235
|
+
}
|
|
1236
|
+
if (rlsKeys({ value: rule, keys: ["through"] }) && typeof rule.through === "string") {
|
|
1237
|
+
const relation = model.relations.find((r) => r.name === rule.through);
|
|
1238
|
+
const target = relation === undefined ? undefined : byName.get(relation.targetModel);
|
|
1239
|
+
if (relation === undefined || target === undefined || relation.model !== model.name || relation.isList || relation.type !== "oneToOne" && relation.type !== "manyToOne" || !validRlsForeignKey({ model, target, relation })) {
|
|
1240
|
+
add({ rule: "rls-invalid-through", message: "Native RLS through requires a to-one relation with an actual, complete foreign key on this model" });
|
|
1241
|
+
continue;
|
|
1242
|
+
}
|
|
1243
|
+
if (relation.isOptional || relation.fields?.some((name) => model.fields.find((field) => field.name === name)?.isOptional)) {
|
|
1244
|
+
add({ rule: "rls-nullable-through", message: "Native RLS through requires a non-nullable parent relation and foreign key; NULL parent links cannot satisfy WITH CHECK. Make the link required or use a direct ownership rule", field: relation.name });
|
|
1245
|
+
continue;
|
|
1246
|
+
}
|
|
1247
|
+
if (table === "parent")
|
|
1248
|
+
add({ rule: "rls-through-alias-conflict", message: "A through table mapped to parent would shadow the fixed policy parent alias; use another table name" });
|
|
1249
|
+
throughTargets.set(model.name, target.name);
|
|
1250
|
+
continue;
|
|
1251
|
+
}
|
|
1252
|
+
add({ rule: "rls-invalid-rule", message: "Native RLS accepts a nonempty equality map or a single through relation; extra properties and operation-specific rules refuse" });
|
|
1253
|
+
}
|
|
1254
|
+
for (const [origin, first] of throughTargets) {
|
|
1255
|
+
const seen = new Set([origin]);
|
|
1256
|
+
let current = first;
|
|
1257
|
+
while (current !== undefined && !seen.has(current)) {
|
|
1258
|
+
seen.add(current);
|
|
1259
|
+
const rule = byName.get(current)?.rls;
|
|
1260
|
+
if (rlsRecord(rule) && rlsKeys({ value: rule, keys: ["where"] }))
|
|
1261
|
+
break;
|
|
1262
|
+
current = throughTargets.get(current);
|
|
1263
|
+
}
|
|
1264
|
+
if (current === undefined || current === origin || throughTargets.has(current) && seen.has(current)) {
|
|
1265
|
+
issues.push({ rule: "rls-through-chain-invalid", message: `Through chain from ${origin} must be acyclic and end in a direct where rule`, model: origin });
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1269
|
+
function validRlsForeignKey(params) {
|
|
1270
|
+
const { model, target, relation } = params;
|
|
1271
|
+
const fields = relation.fields;
|
|
1272
|
+
const refs = relation.references;
|
|
1273
|
+
if (fields === undefined || refs === undefined || fields.length === 0 || fields.length !== refs.length || new Set(fields).size !== fields.length || new Set(refs).size !== refs.length)
|
|
1274
|
+
return false;
|
|
1275
|
+
const validFields = fields.every((name, index) => {
|
|
1276
|
+
const field = model.fields.find((f) => f.name === name);
|
|
1277
|
+
const ref = target.fields.find((f) => f.name === refs[index]);
|
|
1278
|
+
return field !== undefined && ref !== undefined && !field.isList && !ref.isList && !field.isUnsupported && !ref.isUnsupported && (field.type === ref.type || isEnumType(field.type) && isEnumType(ref.type) && field.type.enum === ref.type.enum);
|
|
1279
|
+
});
|
|
1280
|
+
const uniqueSets = [
|
|
1281
|
+
...target.fields.filter((f) => f.isId || f.isUnique).map((f) => [f.name]),
|
|
1282
|
+
...target.primaryKey === undefined ? [] : [target.primaryKey.fields],
|
|
1283
|
+
...target.indexes.filter((index) => index.kind === "unique" && index.where === undefined).map((index) => index.fields.map((f) => f.name))
|
|
1284
|
+
];
|
|
1285
|
+
return validFields && uniqueSets.some((set) => set.length === refs.length && set.every((name) => refs.includes(name)));
|
|
1286
|
+
}
|
|
621
1287
|
// packages/schema/src/m2m.ts
|
|
622
1288
|
function implicitJoinTable(params) {
|
|
623
1289
|
const sorted = [params.modelA, params.modelB].sort();
|
|
@@ -634,28 +1300,45 @@ function implicitJoinTable(params) {
|
|
|
634
1300
|
}
|
|
635
1301
|
export {
|
|
636
1302
|
validateSchemaIR,
|
|
1303
|
+
validateRlsContextIR,
|
|
637
1304
|
validateComputedConfig,
|
|
638
1305
|
unsupportedCapability,
|
|
639
1306
|
providerToDialect,
|
|
640
1307
|
mergeExtensionDeclarations,
|
|
641
1308
|
isReservedDelegateName,
|
|
642
1309
|
isReservedClientName,
|
|
1310
|
+
isImplicitManyToManyRelation,
|
|
643
1311
|
isEnumType,
|
|
1312
|
+
invalidStoredData,
|
|
644
1313
|
internalError,
|
|
645
1314
|
implicitJoinTable,
|
|
646
1315
|
extensionOptionsHash,
|
|
647
1316
|
extensionManifestEntry,
|
|
648
1317
|
extensionDeclarations,
|
|
1318
|
+
exactIntegerLiteral,
|
|
1319
|
+
enumStorageOf,
|
|
1320
|
+
encodePrismaString,
|
|
649
1321
|
defineExtension,
|
|
1322
|
+
decodePrismaString,
|
|
650
1323
|
buildExtensionRegistry,
|
|
651
1324
|
buildComputedManifest,
|
|
652
1325
|
assertValidSchemaIR,
|
|
653
1326
|
VibeError,
|
|
654
1327
|
VIBE_ERROR_CODES,
|
|
1328
|
+
ScopedQueryError,
|
|
1329
|
+
SQLITE_CAPABILITIES,
|
|
1330
|
+
SCOPED_REFUSAL_REASONS,
|
|
1331
|
+
RlsContextError,
|
|
1332
|
+
RLS_CONTEXT_REASONS,
|
|
1333
|
+
RESERVED_ENUM_NAMES,
|
|
655
1334
|
RESERVED_DELEGATE_NAMES,
|
|
656
1335
|
RESERVED_CLIENT_NAMES,
|
|
1336
|
+
POSTGRES_CAPABILITIES,
|
|
1337
|
+
MYSQL_CAPABILITIES,
|
|
1338
|
+
ENUM_STORAGES,
|
|
657
1339
|
EMPTY_EXTENSION_REGISTRY,
|
|
1340
|
+
DIALECT_CAPABILITIES,
|
|
658
1341
|
DIALECTS
|
|
659
1342
|
};
|
|
660
1343
|
|
|
661
|
-
//# debugId=
|
|
1344
|
+
//# debugId=917A26DA81AB84E364756E2164756E21
|