@vibeorm/dsl 0.3.0 → 2.0.0-alpha.1
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 +62 -471
- package/dist/column.d.ts +150 -0
- package/dist/column.d.ts.map +1 -0
- package/dist/enum.d.ts +27 -0
- package/dist/enum.d.ts.map +1 -0
- package/dist/generator/index.d.ts +5 -0
- package/dist/generator/index.d.ts.map +1 -0
- package/dist/generator/prisma.d.ts +19 -0
- package/dist/generator/prisma.d.ts.map +1 -0
- package/dist/index.d.ts +116 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1546 -0
- package/dist/index.js.map +22 -0
- package/dist/model.d.ts +44 -0
- package/dist/model.d.ts.map +1 -0
- package/dist/naming.d.ts +23 -0
- package/dist/naming.d.ts.map +1 -0
- package/dist/relation-plan.d.ts +101 -0
- package/dist/relation-plan.d.ts.map +1 -0
- package/dist/relation.d.ts +23 -0
- package/dist/relation.d.ts.map +1 -0
- package/dist/relations.d.ts +29 -0
- package/dist/relations.d.ts.map +1 -0
- package/dist/schema.d.ts +38 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/templates.d.ts +79 -0
- package/dist/templates.d.ts.map +1 -0
- package/dist/to-ir.d.ts +41 -0
- package/dist/to-ir.d.ts.map +1 -0
- package/dist/types.d.ts +286 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/validate.d.ts +22 -0
- package/dist/validate.d.ts.map +1 -0
- package/package.json +29 -26
- package/src/column.ts +0 -389
- package/src/enum.ts +0 -71
- package/src/generator/index.ts +0 -5
- package/src/generator/prisma.ts +0 -728
- package/src/index.ts +0 -247
- package/src/model.ts +0 -330
- package/src/relation.ts +0 -75
- package/src/relations.ts +0 -293
- package/src/schema.ts +0 -184
- package/src/templates.ts +0 -134
- package/src/types.ts +0 -381
- package/src/validate.ts +0 -141
package/src/types.ts
DELETED
|
@@ -1,381 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Core types for @vibeorm/dsl
|
|
3
|
-
*
|
|
4
|
-
* v3 Changes:
|
|
5
|
-
* - Relations are now defined separately via defineRelations()
|
|
6
|
-
* - Models only contain columns (and children for inline nested models)
|
|
7
|
-
* - Full type-safety for relation column references
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
// ─── Column Types ─────────────────────────
|
|
11
|
-
|
|
12
|
-
export type ColumnType =
|
|
13
|
-
| "string"
|
|
14
|
-
| "int"
|
|
15
|
-
| "bigint"
|
|
16
|
-
| "float"
|
|
17
|
-
| "decimal"
|
|
18
|
-
| "boolean"
|
|
19
|
-
| "datetime"
|
|
20
|
-
| "json"
|
|
21
|
-
| "id"
|
|
22
|
-
| "bytes"
|
|
23
|
-
| "enum"
|
|
24
|
-
| "unsupported";
|
|
25
|
-
|
|
26
|
-
export type IdGeneratorType = "ulid" | "cuid" | "uuid" | "autoincrement" | "none";
|
|
27
|
-
|
|
28
|
-
export type CascadeAction = "Cascade" | "Restrict" | "NoAction" | "SetNull" | "SetDefault";
|
|
29
|
-
|
|
30
|
-
/** PostgreSQL index types supported by Prisma */
|
|
31
|
-
export type IndexType = "BTree" | "Hash" | "Gin" | "Gist" | "SpGist" | "Brin";
|
|
32
|
-
|
|
33
|
-
/** Base column config options */
|
|
34
|
-
export type BaseColumnConfig = {
|
|
35
|
-
optional?: boolean;
|
|
36
|
-
index?: boolean;
|
|
37
|
-
unique?: boolean;
|
|
38
|
-
array?: boolean;
|
|
39
|
-
map?: string; // @map("column_name") - map to different database column name
|
|
40
|
-
dbgenerated?: string; // @default(dbgenerated("...")) - database-native default
|
|
41
|
-
comment?: string; // Generates /// comment above column in Prisma (for Zod generators, docs, etc.)
|
|
42
|
-
[key: string]: unknown;
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
export type StringColumnConfig = BaseColumnConfig & {
|
|
46
|
-
default?: string;
|
|
47
|
-
maxLength?: number; // @db.VarChar(n)
|
|
48
|
-
text?: boolean; // @db.Text
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
export type IntColumnConfig = BaseColumnConfig & {
|
|
52
|
-
default?: number;
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
export type FloatColumnConfig = BaseColumnConfig & {
|
|
56
|
-
default?: number;
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
export type DecimalColumnConfig = BaseColumnConfig & {
|
|
60
|
-
default?: string;
|
|
61
|
-
precision?: number; // @db.Decimal(precision, scale)
|
|
62
|
-
scale?: number; // @db.Decimal(precision, scale)
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
export type BooleanColumnConfig = BaseColumnConfig & {
|
|
66
|
-
default?: boolean;
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
export type DatetimeColumnConfig = BaseColumnConfig & {
|
|
70
|
-
default?: "now";
|
|
71
|
-
updatedAt?: boolean;
|
|
72
|
-
tz?: boolean;
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
export type JsonColumnConfig = BaseColumnConfig & {
|
|
76
|
-
default?: unknown;
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
export type IdColumnConfig = BaseColumnConfig & {
|
|
80
|
-
type?: IdGeneratorType;
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
export type BytesColumnConfig = BaseColumnConfig;
|
|
84
|
-
|
|
85
|
-
export type BigIntColumnConfig = BaseColumnConfig & {
|
|
86
|
-
default?: bigint | number;
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
export type UnsupportedColumnConfig = BaseColumnConfig & {
|
|
90
|
-
dbType: string; // The raw database type string, e.g. "tsvector", "geometry(Point, 4326)"
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
/** v2: Object-based enum config */
|
|
94
|
-
export type InlineEnumConfig<T extends readonly string[] = readonly string[]> =
|
|
95
|
-
BaseColumnConfig & {
|
|
96
|
-
options: T;
|
|
97
|
-
default?: T[number];
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
// ─── Standalone Enum Types ────────────────
|
|
101
|
-
|
|
102
|
-
export type EnumFieldConfig<T extends readonly string[] = readonly string[]> =
|
|
103
|
-
BaseColumnConfig & {
|
|
104
|
-
default?: T[number];
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* EnumDef represents a standalone enum.
|
|
109
|
-
* The field() method returns a ChainableEnumColumn that supports full method chaining.
|
|
110
|
-
*/
|
|
111
|
-
export type EnumDef<T extends readonly string[] = readonly string[]> = {
|
|
112
|
-
__type: "enum";
|
|
113
|
-
__name: string;
|
|
114
|
-
__options: T;
|
|
115
|
-
// Returns a chainable column with full support for .optional(), .index(), .default()
|
|
116
|
-
field(config?: EnumFieldConfig<T>): ChainableEnumColumn<T>;
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Chainable enum column type for proper type inference with method chaining.
|
|
121
|
-
* This mirrors ChainableColumn but with proper default typing for enums.
|
|
122
|
-
*/
|
|
123
|
-
export type ChainableEnumColumn<T extends readonly string[] = readonly string[]> =
|
|
124
|
-
ColumnDef<"enum"> & {
|
|
125
|
-
optional(): ChainableEnumColumn<T>;
|
|
126
|
-
index(): ChainableEnumColumn<T>;
|
|
127
|
-
unique(): ChainableEnumColumn<T>;
|
|
128
|
-
array(): ChainableEnumColumn<T>;
|
|
129
|
-
default(value: T[number]): ChainableEnumColumn<T>;
|
|
130
|
-
};
|
|
131
|
-
|
|
132
|
-
// ─── Column Definition ────────────────────
|
|
133
|
-
|
|
134
|
-
export type ColumnDef<T extends ColumnType = ColumnType> = {
|
|
135
|
-
__type: "column";
|
|
136
|
-
__columnType: T;
|
|
137
|
-
__name?: string;
|
|
138
|
-
__config: BaseColumnConfig;
|
|
139
|
-
__enumValues?: readonly string[];
|
|
140
|
-
__enumName?: string; // Reference to standalone enum name
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
// ─── Children Types ───────────────────────
|
|
144
|
-
|
|
145
|
-
export type ChildrenRelationConfig = {
|
|
146
|
-
name: string;
|
|
147
|
-
schema: SchemaDefinition | ChildrenSchemaCallback;
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
export type ChildrenDef = {
|
|
151
|
-
__type: "children";
|
|
152
|
-
__name: string;
|
|
153
|
-
__schema: SchemaDefinition | ChildrenSchemaCallback;
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
// ─── Model Types ──────────────────────────
|
|
157
|
-
|
|
158
|
-
/** Schema can contain columns and children (no inline relations in v3) */
|
|
159
|
-
export type SchemaDefinition = Record<string, ColumnDef | ChildrenDef>;
|
|
160
|
-
export type ChildrenSchemaCallback = (s: ChildrenBuilder) => SchemaDefinition;
|
|
161
|
-
|
|
162
|
-
/** Children builder - only has children() method */
|
|
163
|
-
export type ChildrenBuilder = {
|
|
164
|
-
children(config: ChildrenRelationConfig): ChildrenDef;
|
|
165
|
-
};
|
|
166
|
-
|
|
167
|
-
export type IndexDef = {
|
|
168
|
-
__type: "index" | "unique";
|
|
169
|
-
__columns: string[];
|
|
170
|
-
__indexType?: IndexType; // PostgreSQL index type (Gin, Gist, Hash, etc.)
|
|
171
|
-
};
|
|
172
|
-
|
|
173
|
-
// ─── Type-Safe Index Builder ──────────────
|
|
174
|
-
|
|
175
|
-
/** Index options for specifying type */
|
|
176
|
-
export type IndexOptions = {
|
|
177
|
-
type?: IndexType;
|
|
178
|
-
};
|
|
179
|
-
|
|
180
|
-
/** Generic index builder that only allows valid column names */
|
|
181
|
-
export type IndexBuilder<TColumns extends string = string> = {
|
|
182
|
-
on<T extends TColumns>(...columns: T[]): IndexDef;
|
|
183
|
-
on<T extends TColumns>(columns: T[], options: IndexOptions): IndexDef;
|
|
184
|
-
unique<T extends TColumns>(...columns: T[]): IndexDef;
|
|
185
|
-
// Convenience methods for typed indexes (PostgreSQL)
|
|
186
|
-
gin<T extends TColumns>(...columns: T[]): IndexDef;
|
|
187
|
-
gist<T extends TColumns>(...columns: T[]): IndexDef;
|
|
188
|
-
hash<T extends TColumns>(...columns: T[]): IndexDef;
|
|
189
|
-
brin<T extends TColumns>(...columns: T[]): IndexDef;
|
|
190
|
-
};
|
|
191
|
-
|
|
192
|
-
/** Index callback type - generic over column names */
|
|
193
|
-
export type IndexCallback<TColumns extends string = string> = (
|
|
194
|
-
i: IndexBuilder<TColumns>
|
|
195
|
-
) => IndexDef[];
|
|
196
|
-
|
|
197
|
-
// ─── Model Definition ─────────────────────
|
|
198
|
-
|
|
199
|
-
/** Generic ModelDef that preserves schema type for type-safe relations */
|
|
200
|
-
export type ModelDef<TSchema extends SchemaDefinition = SchemaDefinition> = {
|
|
201
|
-
__type: "model";
|
|
202
|
-
__name: string;
|
|
203
|
-
__schema: TSchema | ChildrenSchemaCallback;
|
|
204
|
-
__indexes?: IndexCallback;
|
|
205
|
-
__columns: Map<string, ColumnDef>;
|
|
206
|
-
__children: Map<string, ModelDef>;
|
|
207
|
-
__map?: string; // @@map("table_name") - map to different database table name
|
|
208
|
-
__primaryKey?: string[]; // @@id([col1, col2]) - compound primary key
|
|
209
|
-
// Note: __relations removed - now defined separately via defineRelations()
|
|
210
|
-
};
|
|
211
|
-
|
|
212
|
-
// ─── Relations Types (v3 - Drizzle-style) ─
|
|
213
|
-
|
|
214
|
-
/**
|
|
215
|
-
* Column reference - points to Model.column
|
|
216
|
-
* Used in defineRelations() for type-safe from/to references
|
|
217
|
-
*/
|
|
218
|
-
export type ColumnRef<
|
|
219
|
-
TModel extends string = string,
|
|
220
|
-
TColumn extends string = string,
|
|
221
|
-
> = {
|
|
222
|
-
__type: "columnRef";
|
|
223
|
-
__model: TModel;
|
|
224
|
-
__column: TColumn;
|
|
225
|
-
through<TJunction extends string, TJunctionCol extends string>(
|
|
226
|
-
junction: ColumnRef<TJunction, TJunctionCol>
|
|
227
|
-
): ThroughRef<TModel, TColumn, TJunction, TJunctionCol>;
|
|
228
|
-
};
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
* Through reference for many-to-many relations via junction table
|
|
232
|
-
*/
|
|
233
|
-
export type ThroughRef<
|
|
234
|
-
TModel extends string = string,
|
|
235
|
-
TColumn extends string = string,
|
|
236
|
-
TJunction extends string = string,
|
|
237
|
-
TJunctionCol extends string = string,
|
|
238
|
-
> = {
|
|
239
|
-
__type: "throughRef";
|
|
240
|
-
__model: TModel;
|
|
241
|
-
__column: TColumn;
|
|
242
|
-
__junction: TJunction;
|
|
243
|
-
__junctionColumn: TJunctionCol;
|
|
244
|
-
};
|
|
245
|
-
|
|
246
|
-
/**
|
|
247
|
-
* Config for r.one.ModelName({ from, to })
|
|
248
|
-
*/
|
|
249
|
-
export type OneRelationDefConfig<
|
|
250
|
-
TFrom extends ColumnRef | ThroughRef = ColumnRef,
|
|
251
|
-
TTo extends ColumnRef | ThroughRef = ColumnRef,
|
|
252
|
-
> = {
|
|
253
|
-
from: TFrom;
|
|
254
|
-
to: TTo;
|
|
255
|
-
optional?: boolean;
|
|
256
|
-
alias?: string;
|
|
257
|
-
onDelete?: CascadeAction; // Referential action on delete
|
|
258
|
-
onUpdate?: CascadeAction; // Referential action on update
|
|
259
|
-
};
|
|
260
|
-
|
|
261
|
-
/**
|
|
262
|
-
* Config for r.many.ModelName({ from, to })
|
|
263
|
-
*/
|
|
264
|
-
export type ManyRelationDefConfig<
|
|
265
|
-
TFrom extends ColumnRef | ThroughRef = ColumnRef | ThroughRef,
|
|
266
|
-
TTo extends ColumnRef | ThroughRef = ColumnRef | ThroughRef,
|
|
267
|
-
> = {
|
|
268
|
-
from: TFrom;
|
|
269
|
-
to: TTo;
|
|
270
|
-
optional?: boolean;
|
|
271
|
-
alias?: string;
|
|
272
|
-
onDelete?: CascadeAction; // Referential action on delete
|
|
273
|
-
onUpdate?: CascadeAction; // Referential action on update
|
|
274
|
-
};
|
|
275
|
-
|
|
276
|
-
/**
|
|
277
|
-
* Stored relation definition (output of defineRelations)
|
|
278
|
-
*/
|
|
279
|
-
export type StoredRelationDef = {
|
|
280
|
-
__type: "storedRelation";
|
|
281
|
-
__relationType: "one" | "many";
|
|
282
|
-
__targetModel: string;
|
|
283
|
-
__fromModel: string;
|
|
284
|
-
__fromColumn: string;
|
|
285
|
-
__toModel: string;
|
|
286
|
-
__toColumn: string;
|
|
287
|
-
__throughJunction?: string;
|
|
288
|
-
__throughFromCol?: string;
|
|
289
|
-
__throughToCol?: string;
|
|
290
|
-
__optional: boolean;
|
|
291
|
-
__alias?: string;
|
|
292
|
-
__onDelete?: CascadeAction; // Referential action on delete
|
|
293
|
-
__onUpdate?: CascadeAction; // Referential action on update
|
|
294
|
-
};
|
|
295
|
-
|
|
296
|
-
/**
|
|
297
|
-
* Relations map: { ModelName: { relationName: StoredRelationDef } }
|
|
298
|
-
*/
|
|
299
|
-
export type RelationsMap = Record<string, Record<string, StoredRelationDef>>;
|
|
300
|
-
|
|
301
|
-
// ─── Relations Builder Types ──────────────
|
|
302
|
-
|
|
303
|
-
/**
|
|
304
|
-
* Extract column names from a ModelDef's __columns Map
|
|
305
|
-
* This is done at runtime, so we need to encode it in the type system
|
|
306
|
-
*/
|
|
307
|
-
export type ExtractModelColumns<T> = T extends ModelDef<infer TSchema>
|
|
308
|
-
? Extract<keyof TSchema, string>
|
|
309
|
-
: never;
|
|
310
|
-
|
|
311
|
-
/**
|
|
312
|
-
* Relations builder passed to defineRelations callback
|
|
313
|
-
* Provides r.one, r.many, and r.ModelName.columnName access
|
|
314
|
-
*/
|
|
315
|
-
export type RelationsBuilder<TSchema extends Record<string, ModelDef>> = {
|
|
316
|
-
// r.one.ModelName({ from, to }) - creates one-to-one or many-to-one
|
|
317
|
-
one: {
|
|
318
|
-
[K in keyof TSchema & string]: <
|
|
319
|
-
TFrom extends ColumnRef | ThroughRef,
|
|
320
|
-
TTo extends ColumnRef | ThroughRef,
|
|
321
|
-
>(
|
|
322
|
-
config: OneRelationDefConfig<TFrom, TTo>
|
|
323
|
-
) => StoredRelationDef;
|
|
324
|
-
};
|
|
325
|
-
|
|
326
|
-
// r.many.ModelName({ from, to }) - creates one-to-many or many-to-many
|
|
327
|
-
many: {
|
|
328
|
-
[K in keyof TSchema & string]: <
|
|
329
|
-
TFrom extends ColumnRef | ThroughRef,
|
|
330
|
-
TTo extends ColumnRef | ThroughRef,
|
|
331
|
-
>(
|
|
332
|
-
config: ManyRelationDefConfig<TFrom, TTo>
|
|
333
|
-
) => StoredRelationDef;
|
|
334
|
-
};
|
|
335
|
-
} & {
|
|
336
|
-
// r.ModelName.columnName - column references for from/to
|
|
337
|
-
[K in keyof TSchema & string]: ModelColumnRefs<K, TSchema[K]>;
|
|
338
|
-
};
|
|
339
|
-
|
|
340
|
-
/**
|
|
341
|
-
* Column references for a specific model
|
|
342
|
-
* r.User.id, r.User.email, etc.
|
|
343
|
-
*/
|
|
344
|
-
export type ModelColumnRefs<
|
|
345
|
-
TModelName extends string,
|
|
346
|
-
TModel extends ModelDef,
|
|
347
|
-
> = {
|
|
348
|
-
[C in ExtractModelColumns<TModel>]: ColumnRef<TModelName, C>;
|
|
349
|
-
};
|
|
350
|
-
|
|
351
|
-
/**
|
|
352
|
-
* Output type of defineRelations callback
|
|
353
|
-
*/
|
|
354
|
-
export type RelationsOutput<TSchema extends Record<string, ModelDef>> = {
|
|
355
|
-
[K in keyof TSchema]?: Record<string, StoredRelationDef>;
|
|
356
|
-
};
|
|
357
|
-
|
|
358
|
-
// ─── Schema Types ─────────────────────────
|
|
359
|
-
|
|
360
|
-
export type SchemaInput = Record<string, ModelDef | EnumDef | Record<string, ModelDef | EnumDef>>;
|
|
361
|
-
|
|
362
|
-
export type SchemaDef = {
|
|
363
|
-
__type: "schema";
|
|
364
|
-
__models: Map<string, ModelDef>;
|
|
365
|
-
__enums: Map<string, readonly string[]>;
|
|
366
|
-
__relations: RelationsMap;
|
|
367
|
-
};
|
|
368
|
-
|
|
369
|
-
// ─── Generator Types ──────────────────────
|
|
370
|
-
|
|
371
|
-
export type PrismaGeneratorConfig = {
|
|
372
|
-
output?: string;
|
|
373
|
-
};
|
|
374
|
-
|
|
375
|
-
export type GeneratorConfig = {
|
|
376
|
-
prisma?: PrismaGeneratorConfig;
|
|
377
|
-
};
|
|
378
|
-
|
|
379
|
-
export type GeneratorOutput = {
|
|
380
|
-
prisma?: string;
|
|
381
|
-
};
|
package/src/validate.ts
DELETED
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Schema validation for @vibeorm/dsl
|
|
3
|
-
*
|
|
4
|
-
* Validates a SchemaDef for common issues before generation:
|
|
5
|
-
* - Duplicate model/enum names
|
|
6
|
-
* - Missing FK columns referenced in relations
|
|
7
|
-
* - Relation alias consistency (matching aliases on both sides)
|
|
8
|
-
* - Self-referential relations without aliases
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* const schema = dsl.schema({ User, Post }, { relations });
|
|
12
|
-
* const errors = validateSchema(schema);
|
|
13
|
-
* if (errors.length > 0) {
|
|
14
|
-
* console.error("Schema validation failed:", errors);
|
|
15
|
-
* }
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
import type { SchemaDef, StoredRelationDef } from "./types.ts";
|
|
19
|
-
|
|
20
|
-
// ─── Types ─────────────────────────────────
|
|
21
|
-
|
|
22
|
-
export type ValidationError = {
|
|
23
|
-
type: "error" | "warning";
|
|
24
|
-
message: string;
|
|
25
|
-
model?: string;
|
|
26
|
-
relation?: string;
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
// ─── Validation ─────────────────────────────
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Validates a SchemaDef and returns any issues found.
|
|
33
|
-
* Returns an empty array if the schema is valid.
|
|
34
|
-
*/
|
|
35
|
-
export function validateSchema(schema: SchemaDef): ValidationError[] {
|
|
36
|
-
const errors: ValidationError[] = [];
|
|
37
|
-
|
|
38
|
-
// 1. Check for model/enum name collisions
|
|
39
|
-
const allNames = new Set<string>();
|
|
40
|
-
for (const [name] of schema.__models) {
|
|
41
|
-
if (allNames.has(name)) {
|
|
42
|
-
errors.push({
|
|
43
|
-
type: "error",
|
|
44
|
-
message: `Duplicate name "${name}" - used by both a model and enum/model`,
|
|
45
|
-
model: name,
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
allNames.add(name);
|
|
49
|
-
}
|
|
50
|
-
for (const [name] of schema.__enums) {
|
|
51
|
-
if (allNames.has(name)) {
|
|
52
|
-
errors.push({
|
|
53
|
-
type: "error",
|
|
54
|
-
message: `Duplicate name "${name}" - used by both a model and enum`,
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
allNames.add(name);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// 2. Validate relations
|
|
61
|
-
for (const [modelName, modelRelations] of Object.entries(schema.__relations)) {
|
|
62
|
-
// Check model exists
|
|
63
|
-
if (!schema.__models.has(modelName)) {
|
|
64
|
-
errors.push({
|
|
65
|
-
type: "error",
|
|
66
|
-
message: `Relations defined for unknown model "${modelName}"`,
|
|
67
|
-
model: modelName,
|
|
68
|
-
});
|
|
69
|
-
continue;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const model = schema.__models.get(modelName)!;
|
|
73
|
-
|
|
74
|
-
for (const [relName, rel] of Object.entries(modelRelations)) {
|
|
75
|
-
// Check target model exists
|
|
76
|
-
if (!schema.__models.has(rel.__targetModel)) {
|
|
77
|
-
errors.push({
|
|
78
|
-
type: "error",
|
|
79
|
-
message: `Relation "${relName}" references unknown model "${rel.__targetModel}"`,
|
|
80
|
-
model: modelName,
|
|
81
|
-
relation: relName,
|
|
82
|
-
});
|
|
83
|
-
continue;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// For "one" relations that own the FK, check FK column exists
|
|
87
|
-
if (rel.__relationType === "one" && rel.__fromModel === modelName) {
|
|
88
|
-
if (!model.__columns.has(rel.__fromColumn)) {
|
|
89
|
-
errors.push({
|
|
90
|
-
type: "error",
|
|
91
|
-
message: `Relation "${relName}" references FK column "${rel.__fromColumn}" which doesn't exist on model "${modelName}"`,
|
|
92
|
-
model: modelName,
|
|
93
|
-
relation: relName,
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// Check target column exists
|
|
98
|
-
const targetModel = schema.__models.get(rel.__targetModel);
|
|
99
|
-
if (targetModel && !targetModel.__columns.has(rel.__toColumn)) {
|
|
100
|
-
errors.push({
|
|
101
|
-
type: "error",
|
|
102
|
-
message: `Relation "${relName}" references column "${rel.__toColumn}" which doesn't exist on target model "${rel.__targetModel}"`,
|
|
103
|
-
model: modelName,
|
|
104
|
-
relation: relName,
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// Warn about self-referential relations without aliases
|
|
110
|
-
if (rel.__targetModel === modelName && !rel.__alias) {
|
|
111
|
-
const otherSelfRels = Object.values(modelRelations).filter(
|
|
112
|
-
(r): r is StoredRelationDef =>
|
|
113
|
-
r.__targetModel === modelName && r !== rel
|
|
114
|
-
);
|
|
115
|
-
if (otherSelfRels.length > 0) {
|
|
116
|
-
errors.push({
|
|
117
|
-
type: "warning",
|
|
118
|
-
message: `Self-referential relation "${relName}" on "${modelName}" has no alias - this may cause Prisma ambiguity`,
|
|
119
|
-
model: modelName,
|
|
120
|
-
relation: relName,
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// 3. Check for models with no id column and no primaryKey override
|
|
128
|
-
for (const [modelName, model] of schema.__models) {
|
|
129
|
-
const hasIdCol = Array.from(model.__columns.values()).some(col => col.__columnType === "id");
|
|
130
|
-
const hasPrimaryKey = model.__primaryKey && model.__primaryKey.length > 0;
|
|
131
|
-
if (!hasIdCol && !hasPrimaryKey) {
|
|
132
|
-
errors.push({
|
|
133
|
-
type: "warning",
|
|
134
|
-
message: `Model "${modelName}" has no id column and no compound primaryKey defined`,
|
|
135
|
-
model: modelName,
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
return errors;
|
|
141
|
-
}
|