@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.
Files changed (46) hide show
  1. package/README.md +62 -471
  2. package/dist/column.d.ts +150 -0
  3. package/dist/column.d.ts.map +1 -0
  4. package/dist/enum.d.ts +27 -0
  5. package/dist/enum.d.ts.map +1 -0
  6. package/dist/generator/index.d.ts +5 -0
  7. package/dist/generator/index.d.ts.map +1 -0
  8. package/dist/generator/prisma.d.ts +19 -0
  9. package/dist/generator/prisma.d.ts.map +1 -0
  10. package/dist/index.d.ts +116 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +1546 -0
  13. package/dist/index.js.map +22 -0
  14. package/dist/model.d.ts +44 -0
  15. package/dist/model.d.ts.map +1 -0
  16. package/dist/naming.d.ts +23 -0
  17. package/dist/naming.d.ts.map +1 -0
  18. package/dist/relation-plan.d.ts +101 -0
  19. package/dist/relation-plan.d.ts.map +1 -0
  20. package/dist/relation.d.ts +23 -0
  21. package/dist/relation.d.ts.map +1 -0
  22. package/dist/relations.d.ts +29 -0
  23. package/dist/relations.d.ts.map +1 -0
  24. package/dist/schema.d.ts +38 -0
  25. package/dist/schema.d.ts.map +1 -0
  26. package/dist/templates.d.ts +79 -0
  27. package/dist/templates.d.ts.map +1 -0
  28. package/dist/to-ir.d.ts +41 -0
  29. package/dist/to-ir.d.ts.map +1 -0
  30. package/dist/types.d.ts +286 -0
  31. package/dist/types.d.ts.map +1 -0
  32. package/dist/validate.d.ts +22 -0
  33. package/dist/validate.d.ts.map +1 -0
  34. package/package.json +29 -26
  35. package/src/column.ts +0 -389
  36. package/src/enum.ts +0 -71
  37. package/src/generator/index.ts +0 -5
  38. package/src/generator/prisma.ts +0 -728
  39. package/src/index.ts +0 -247
  40. package/src/model.ts +0 -330
  41. package/src/relation.ts +0 -75
  42. package/src/relations.ts +0 -293
  43. package/src/schema.ts +0 -184
  44. package/src/templates.ts +0 -134
  45. package/src/types.ts +0 -381
  46. 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
- }