@famgia/omnify-laravel 0.0.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/dist/index.cjs ADDED
@@ -0,0 +1,959 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ enumToUnionType: () => enumToUnionType,
24
+ extractInlineEnums: () => extractInlineEnums,
25
+ formatColumnMethod: () => formatColumnMethod,
26
+ formatEnum: () => formatEnum,
27
+ formatForeignKey: () => formatForeignKey,
28
+ formatIndex: () => formatIndex,
29
+ formatInterface: () => formatInterface,
30
+ formatMigrationFile: () => formatMigrationFile,
31
+ formatProperty: () => formatProperty,
32
+ formatTypeAlias: () => formatTypeAlias,
33
+ generateDropMigrationForTable: () => generateDropMigrationForTable,
34
+ generateEnums: () => generateEnums,
35
+ generateForeignKey: () => generateForeignKey,
36
+ generateInterfaces: () => generateInterfaces,
37
+ generateMigrationFromSchema: () => generateMigrationFromSchema,
38
+ generateMigrations: () => generateMigrations,
39
+ generatePrimaryKeyColumn: () => generatePrimaryKeyColumn,
40
+ generateSoftDeleteColumn: () => generateSoftDeleteColumn,
41
+ generateTimestampColumns: () => generateTimestampColumns,
42
+ generateTypeScript: () => generateTypeScript,
43
+ generateTypeScriptFile: () => generateTypeScriptFile,
44
+ generateTypeScriptFiles: () => generateTypeScriptFiles,
45
+ getMigrationPath: () => getMigrationPath,
46
+ getPropertyType: () => getPropertyType,
47
+ getTypeScriptPath: () => getTypeScriptPath,
48
+ propertyToColumnMethod: () => propertyToColumnMethod,
49
+ propertyToTSProperty: () => propertyToTSProperty,
50
+ schemaToBlueprint: () => schemaToBlueprint,
51
+ schemaToEnum: () => schemaToEnum,
52
+ schemaToInterface: () => schemaToInterface,
53
+ toColumnName: () => toColumnName,
54
+ toEnumMemberName: () => toEnumMemberName,
55
+ toEnumName: () => toEnumName,
56
+ toInterfaceName: () => toInterfaceName,
57
+ toPropertyName: () => toPropertyName,
58
+ toTableName: () => toTableName
59
+ });
60
+ module.exports = __toCommonJS(index_exports);
61
+
62
+ // src/migration/schema-builder.ts
63
+ var TYPE_METHOD_MAP = {
64
+ String: "string",
65
+ Int: "integer",
66
+ BigInt: "bigInteger",
67
+ Float: "double",
68
+ Boolean: "boolean",
69
+ Text: "text",
70
+ LongText: "longText",
71
+ Date: "date",
72
+ Time: "time",
73
+ Timestamp: "timestamp",
74
+ Json: "json",
75
+ Email: "string",
76
+ Password: "string",
77
+ File: "string",
78
+ MultiFile: "json",
79
+ Enum: "enum",
80
+ Select: "string",
81
+ Lookup: "unsignedBigInteger"
82
+ };
83
+ var PK_METHOD_MAP = {
84
+ Int: "increments",
85
+ BigInt: "bigIncrements",
86
+ Uuid: "uuid",
87
+ String: "string"
88
+ };
89
+ function toColumnName(propertyName) {
90
+ return propertyName.replace(/([A-Z])/g, "_$1").toLowerCase().replace(/^_/, "");
91
+ }
92
+ function toTableName(schemaName) {
93
+ const snakeCase = schemaName.replace(/([A-Z])/g, "_$1").toLowerCase().replace(/^_/, "");
94
+ if (snakeCase.endsWith("y")) {
95
+ return snakeCase.slice(0, -1) + "ies";
96
+ } else if (snakeCase.endsWith("s") || snakeCase.endsWith("x") || snakeCase.endsWith("ch") || snakeCase.endsWith("sh")) {
97
+ return snakeCase + "es";
98
+ } else {
99
+ return snakeCase + "s";
100
+ }
101
+ }
102
+ function propertyToColumnMethod(propertyName, property) {
103
+ if (property.type === "Association") {
104
+ return null;
105
+ }
106
+ const columnName = toColumnName(propertyName);
107
+ const method = TYPE_METHOD_MAP[property.type] ?? "string";
108
+ const args = [columnName];
109
+ const modifiers = [];
110
+ const propWithLength = property;
111
+ if (method === "string" && propWithLength.length) {
112
+ args.push(propWithLength.length);
113
+ }
114
+ if (property.type === "Enum") {
115
+ const enumProp = property;
116
+ if (enumProp.enum && enumProp.enum.length > 0) {
117
+ args.push(enumProp.enum);
118
+ }
119
+ }
120
+ const baseProp = property;
121
+ if (baseProp.nullable) {
122
+ modifiers.push({ method: "nullable" });
123
+ }
124
+ if (baseProp.unique) {
125
+ modifiers.push({ method: "unique" });
126
+ }
127
+ if (baseProp.default !== void 0) {
128
+ const defaultValue = typeof baseProp.default === "string" ? baseProp.default : JSON.stringify(baseProp.default);
129
+ modifiers.push({ method: "default", args: [defaultValue] });
130
+ }
131
+ if (baseProp.unsigned && (method === "integer" || method === "bigInteger")) {
132
+ modifiers.push({ method: "unsigned" });
133
+ }
134
+ return {
135
+ name: columnName,
136
+ method,
137
+ args,
138
+ modifiers
139
+ };
140
+ }
141
+ function generatePrimaryKeyColumn(pkType = "BigInt") {
142
+ const method = PK_METHOD_MAP[pkType] ?? "bigIncrements";
143
+ if (pkType === "Uuid") {
144
+ return {
145
+ name: "id",
146
+ method: "uuid",
147
+ args: ["id"],
148
+ modifiers: [{ method: "primary" }]
149
+ };
150
+ }
151
+ if (pkType === "String") {
152
+ return {
153
+ name: "id",
154
+ method: "string",
155
+ args: ["id", 255],
156
+ modifiers: [{ method: "primary" }]
157
+ };
158
+ }
159
+ return {
160
+ name: "id",
161
+ method,
162
+ args: ["id"],
163
+ modifiers: []
164
+ };
165
+ }
166
+ function generateTimestampColumns() {
167
+ return [
168
+ {
169
+ name: "created_at",
170
+ method: "timestamp",
171
+ args: ["created_at"],
172
+ modifiers: [{ method: "nullable" }]
173
+ },
174
+ {
175
+ name: "updated_at",
176
+ method: "timestamp",
177
+ args: ["updated_at"],
178
+ modifiers: [{ method: "nullable" }]
179
+ }
180
+ ];
181
+ }
182
+ function generateSoftDeleteColumn() {
183
+ return {
184
+ name: "deleted_at",
185
+ method: "timestamp",
186
+ args: ["deleted_at"],
187
+ modifiers: [{ method: "nullable" }]
188
+ };
189
+ }
190
+ function generateForeignKey(propertyName, property, allSchemas) {
191
+ if (property.type !== "Association") {
192
+ return null;
193
+ }
194
+ const assocProp = property;
195
+ if (assocProp.relation !== "ManyToOne" && assocProp.relation !== "OneToOne") {
196
+ return null;
197
+ }
198
+ const columnName = toColumnName(propertyName) + "_id";
199
+ const targetSchema = assocProp.target ? allSchemas[assocProp.target] : void 0;
200
+ const targetTable = assocProp.target ? toTableName(assocProp.target) : "unknown";
201
+ const targetPkType = targetSchema?.options?.primaryKeyType ?? "BigInt";
202
+ let method = "unsignedBigInteger";
203
+ if (targetPkType === "Int") {
204
+ method = "unsignedInteger";
205
+ } else if (targetPkType === "Uuid") {
206
+ method = "uuid";
207
+ } else if (targetPkType === "String") {
208
+ method = "string";
209
+ }
210
+ const column = {
211
+ name: columnName,
212
+ method,
213
+ args: [columnName],
214
+ modifiers: assocProp.relation === "ManyToOne" ? [{ method: "nullable" }] : []
215
+ };
216
+ const foreignKey = {
217
+ columns: [columnName],
218
+ references: "id",
219
+ on: [targetTable],
220
+ onDelete: assocProp.onDelete ?? "restrict",
221
+ onUpdate: assocProp.onUpdate ?? "cascade"
222
+ };
223
+ const index = {
224
+ name: `idx_${columnName}`,
225
+ columns: [columnName],
226
+ unique: false
227
+ };
228
+ return { column, foreignKey, index };
229
+ }
230
+ function schemaToBlueprint(schema, allSchemas) {
231
+ const tableName = toTableName(schema.name);
232
+ const columns = [];
233
+ const foreignKeys = [];
234
+ const indexes = [];
235
+ const pkType = schema.options?.primaryKeyType ?? "BigInt";
236
+ columns.push(generatePrimaryKeyColumn(pkType));
237
+ if (schema.properties) {
238
+ for (const [propName, property] of Object.entries(schema.properties)) {
239
+ const columnMethod = propertyToColumnMethod(propName, property);
240
+ if (columnMethod) {
241
+ columns.push(columnMethod);
242
+ }
243
+ const fkResult = generateForeignKey(propName, property, allSchemas);
244
+ if (fkResult) {
245
+ columns.push(fkResult.column);
246
+ foreignKeys.push(fkResult.foreignKey);
247
+ indexes.push(fkResult.index);
248
+ }
249
+ }
250
+ }
251
+ if (schema.options?.timestamps !== false) {
252
+ columns.push(...generateTimestampColumns());
253
+ }
254
+ if (schema.options?.softDelete) {
255
+ columns.push(generateSoftDeleteColumn());
256
+ }
257
+ if (schema.options?.indexes) {
258
+ for (const index of schema.options.indexes) {
259
+ indexes.push({
260
+ name: index.name,
261
+ columns: index.columns.map(toColumnName),
262
+ unique: index.unique ?? false
263
+ });
264
+ }
265
+ }
266
+ if (schema.options?.unique) {
267
+ const uniqueConstraints = Array.isArray(schema.options.unique[0]) ? schema.options.unique : [schema.options.unique];
268
+ for (const constraint of uniqueConstraints) {
269
+ indexes.push({
270
+ columns: constraint.map(toColumnName),
271
+ unique: true
272
+ });
273
+ }
274
+ }
275
+ return {
276
+ tableName,
277
+ columns,
278
+ primaryKey: ["id"],
279
+ foreignKeys,
280
+ indexes
281
+ };
282
+ }
283
+ function formatColumnMethod(column) {
284
+ const args = column.args.map((arg) => {
285
+ if (typeof arg === "string") {
286
+ return `'${arg}'`;
287
+ }
288
+ if (Array.isArray(arg)) {
289
+ return `[${arg.map((v) => `'${v}'`).join(", ")}]`;
290
+ }
291
+ return String(arg);
292
+ }).join(", ");
293
+ let code = `$table->${column.method}(${args})`;
294
+ for (const modifier of column.modifiers) {
295
+ if (modifier.args && modifier.args.length > 0) {
296
+ const modArgs = modifier.args.map((arg) => {
297
+ if (typeof arg === "string") {
298
+ return `'${arg}'`;
299
+ }
300
+ return String(arg);
301
+ }).join(", ");
302
+ code += `->${modifier.method}(${modArgs})`;
303
+ } else {
304
+ code += `->${modifier.method}()`;
305
+ }
306
+ }
307
+ return code + ";";
308
+ }
309
+ function formatForeignKey(fk) {
310
+ const column = fk.columns[0];
311
+ const table = fk.on[0];
312
+ let code = `$table->foreign('${column}')->references('${fk.references}')->on('${table}')`;
313
+ if (fk.onDelete) {
314
+ code += `->onDelete('${fk.onDelete}')`;
315
+ }
316
+ if (fk.onUpdate) {
317
+ code += `->onUpdate('${fk.onUpdate}')`;
318
+ }
319
+ return code + ";";
320
+ }
321
+ function formatIndex(index) {
322
+ const columns = index.columns.length === 1 ? `'${index.columns[0]}'` : `[${index.columns.map((c) => `'${c}'`).join(", ")}]`;
323
+ const method = index.unique ? "unique" : "index";
324
+ const name = index.name ? `, '${index.name}'` : "";
325
+ return `$table->${method}(${columns}${name});`;
326
+ }
327
+
328
+ // src/migration/generator.ts
329
+ function generateTimestamp() {
330
+ const now = /* @__PURE__ */ new Date();
331
+ const year = now.getFullYear();
332
+ const month = String(now.getMonth() + 1).padStart(2, "0");
333
+ const day = String(now.getDate()).padStart(2, "0");
334
+ const hours = String(now.getHours()).padStart(2, "0");
335
+ const minutes = String(now.getMinutes()).padStart(2, "0");
336
+ const seconds = String(now.getSeconds()).padStart(2, "0");
337
+ return `${year}_${month}_${day}_${hours}${minutes}${seconds}`;
338
+ }
339
+ function toClassName(tableName, type) {
340
+ const pascalCase = tableName.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
341
+ switch (type) {
342
+ case "create":
343
+ return `Create${pascalCase}Table`;
344
+ case "alter":
345
+ return `Alter${pascalCase}Table`;
346
+ case "drop":
347
+ return `Drop${pascalCase}Table`;
348
+ }
349
+ }
350
+ function generateFileName(tableName, type, timestamp) {
351
+ const ts = timestamp ?? generateTimestamp();
352
+ const action = type === "create" ? "create" : type === "drop" ? "drop" : "update";
353
+ return `${ts}_${action}_${tableName}_table.php`;
354
+ }
355
+ function renderCreateTableUp(blueprint) {
356
+ const lines = [];
357
+ for (const column of blueprint.columns) {
358
+ lines.push(` ${formatColumnMethod(column)}`);
359
+ }
360
+ return lines.join("\n");
361
+ }
362
+ function renderForeignKeys(blueprint) {
363
+ if (blueprint.foreignKeys.length === 0) {
364
+ return "";
365
+ }
366
+ const lines = blueprint.foreignKeys.map((fk) => ` ${formatForeignKey(fk)}`);
367
+ return "\n" + lines.join("\n");
368
+ }
369
+ function renderIndexes(blueprint) {
370
+ const customIndexes = blueprint.indexes.filter((idx) => {
371
+ if (idx.unique && idx.columns.length === 1) {
372
+ return false;
373
+ }
374
+ return true;
375
+ });
376
+ if (customIndexes.length === 0) {
377
+ return "";
378
+ }
379
+ const lines = customIndexes.map((idx) => ` ${formatIndex(idx)}`);
380
+ return "\n" + lines.join("\n");
381
+ }
382
+ function generateCreateMigration(blueprint, options = {}) {
383
+ const className = toClassName(blueprint.tableName, "create");
384
+ const fileName = generateFileName(blueprint.tableName, "create", options.timestamp);
385
+ const connection = options.connection ? `
386
+ protected $connection = '${options.connection}';
387
+ ` : "";
388
+ const upContent = renderCreateTableUp(blueprint);
389
+ const foreignKeyContent = renderForeignKeys(blueprint);
390
+ const indexContent = renderIndexes(blueprint);
391
+ const content = `<?php
392
+
393
+ use Illuminate\\Database\\Migrations\\Migration;
394
+ use Illuminate\\Database\\Schema\\Blueprint;
395
+ use Illuminate\\Support\\Facades\\Schema;
396
+
397
+ return new class extends Migration
398
+ {${connection}
399
+ /**
400
+ * Run the migrations.
401
+ */
402
+ public function up(): void
403
+ {
404
+ Schema::create('${blueprint.tableName}', function (Blueprint $table) {
405
+ ${upContent}${foreignKeyContent}${indexContent}
406
+ });
407
+ }
408
+
409
+ /**
410
+ * Reverse the migrations.
411
+ */
412
+ public function down(): void
413
+ {
414
+ Schema::dropIfExists('${blueprint.tableName}');
415
+ }
416
+ };
417
+ `;
418
+ return {
419
+ fileName,
420
+ className,
421
+ content,
422
+ tables: [blueprint.tableName],
423
+ type: "create"
424
+ };
425
+ }
426
+ function generateDropMigration(tableName, options = {}) {
427
+ const className = toClassName(tableName, "drop");
428
+ const fileName = generateFileName(tableName, "drop", options.timestamp);
429
+ const connection = options.connection ? `
430
+ protected $connection = '${options.connection}';
431
+ ` : "";
432
+ const content = `<?php
433
+
434
+ use Illuminate\\Database\\Migrations\\Migration;
435
+ use Illuminate\\Database\\Schema\\Blueprint;
436
+ use Illuminate\\Support\\Facades\\Schema;
437
+
438
+ return new class extends Migration
439
+ {${connection}
440
+ /**
441
+ * Run the migrations.
442
+ */
443
+ public function up(): void
444
+ {
445
+ Schema::dropIfExists('${tableName}');
446
+ }
447
+
448
+ /**
449
+ * Reverse the migrations.
450
+ */
451
+ public function down(): void
452
+ {
453
+ // Cannot recreate table without schema information
454
+ // This is a one-way migration
455
+ }
456
+ };
457
+ `;
458
+ return {
459
+ fileName,
460
+ className,
461
+ content,
462
+ tables: [tableName],
463
+ type: "drop"
464
+ };
465
+ }
466
+ function generateMigrations(schemas, options = {}) {
467
+ const migrations = [];
468
+ let timestampOffset = 0;
469
+ for (const schema of Object.values(schemas)) {
470
+ if (schema.kind === "enum") {
471
+ continue;
472
+ }
473
+ const timestamp = options.timestamp ?? generateTimestamp();
474
+ const offsetTimestamp = incrementTimestamp(timestamp, timestampOffset);
475
+ timestampOffset++;
476
+ const blueprint = schemaToBlueprint(schema, schemas);
477
+ const migration = generateCreateMigration(blueprint, {
478
+ ...options,
479
+ timestamp: offsetTimestamp
480
+ });
481
+ migrations.push(migration);
482
+ }
483
+ return migrations;
484
+ }
485
+ function incrementTimestamp(timestamp, seconds) {
486
+ if (seconds === 0) return timestamp;
487
+ const parts = timestamp.split("_");
488
+ if (parts.length < 4) {
489
+ return timestamp;
490
+ }
491
+ const yearPart = parts[0] ?? "2024";
492
+ const monthPart = parts[1] ?? "01";
493
+ const dayPart = parts[2] ?? "01";
494
+ const timePart = parts[3] ?? "000000";
495
+ const year = parseInt(yearPart, 10);
496
+ const month = parseInt(monthPart, 10) - 1;
497
+ const day = parseInt(dayPart, 10);
498
+ const hours = parseInt(timePart.substring(0, 2), 10);
499
+ const minutes = parseInt(timePart.substring(2, 4), 10);
500
+ const secs = parseInt(timePart.substring(4, 6), 10);
501
+ const date = new Date(year, month, day, hours, minutes, secs + seconds);
502
+ const newYear = date.getFullYear();
503
+ const newMonth = String(date.getMonth() + 1).padStart(2, "0");
504
+ const newDay = String(date.getDate()).padStart(2, "0");
505
+ const newHours = String(date.getHours()).padStart(2, "0");
506
+ const newMinutes = String(date.getMinutes()).padStart(2, "0");
507
+ const newSecs = String(date.getSeconds()).padStart(2, "0");
508
+ return `${newYear}_${newMonth}_${newDay}_${newHours}${newMinutes}${newSecs}`;
509
+ }
510
+ function generateMigrationFromSchema(schema, allSchemas, options = {}) {
511
+ const blueprint = schemaToBlueprint(schema, allSchemas);
512
+ return generateCreateMigration(blueprint, options);
513
+ }
514
+ function generateDropMigrationForTable(tableName, options = {}) {
515
+ return generateDropMigration(tableName, options);
516
+ }
517
+ function formatMigrationFile(migration) {
518
+ return migration.content;
519
+ }
520
+ function getMigrationPath(migration, outputDir = "database/migrations") {
521
+ return `${outputDir}/${migration.fileName}`;
522
+ }
523
+
524
+ // src/typescript/interface-generator.ts
525
+ var TYPE_MAP = {
526
+ String: "string",
527
+ Int: "number",
528
+ BigInt: "number",
529
+ Float: "number",
530
+ Boolean: "boolean",
531
+ Text: "string",
532
+ LongText: "string",
533
+ Date: "string",
534
+ Time: "string",
535
+ Timestamp: "string",
536
+ Json: "unknown",
537
+ Email: "string",
538
+ Password: "string",
539
+ File: "string",
540
+ MultiFile: "string[]",
541
+ Enum: "string",
542
+ Select: "string",
543
+ Lookup: "number"
544
+ };
545
+ var PK_TYPE_MAP = {
546
+ Int: "number",
547
+ BigInt: "number",
548
+ Uuid: "string",
549
+ String: "string"
550
+ };
551
+ function toPropertyName(name) {
552
+ return name;
553
+ }
554
+ function toInterfaceName(schemaName) {
555
+ return schemaName;
556
+ }
557
+ function getPropertyType(property, _allSchemas) {
558
+ if (property.type === "Association") {
559
+ const assocProp = property;
560
+ const targetName = assocProp.target ?? "unknown";
561
+ switch (assocProp.relation) {
562
+ case "OneToOne":
563
+ case "ManyToOne":
564
+ return targetName;
565
+ case "OneToMany":
566
+ case "ManyToMany":
567
+ return `${targetName}[]`;
568
+ default:
569
+ return "unknown";
570
+ }
571
+ }
572
+ if (property.type === "Enum") {
573
+ const enumProp = property;
574
+ if (typeof enumProp.enum === "string") {
575
+ return enumProp.enum;
576
+ }
577
+ if (Array.isArray(enumProp.enum)) {
578
+ return enumProp.enum.map((v) => `'${v}'`).join(" | ");
579
+ }
580
+ }
581
+ if (property.type === "Select") {
582
+ const selectProp = property;
583
+ if (selectProp.options && selectProp.options.length > 0) {
584
+ return selectProp.options.map((v) => `'${v}'`).join(" | ");
585
+ }
586
+ }
587
+ return TYPE_MAP[property.type] ?? "unknown";
588
+ }
589
+ function propertyToTSProperty(propertyName, property, allSchemas, options = {}) {
590
+ const type = getPropertyType(property, allSchemas);
591
+ const baseProp = property;
592
+ return {
593
+ name: toPropertyName(propertyName),
594
+ type,
595
+ optional: baseProp.nullable ?? false,
596
+ readonly: options.readonly ?? true,
597
+ comment: baseProp.displayName
598
+ };
599
+ }
600
+ function schemaToInterface(schema, allSchemas, options = {}) {
601
+ const properties = [];
602
+ const pkType = schema.options?.primaryKeyType ?? "BigInt";
603
+ properties.push({
604
+ name: "id",
605
+ type: PK_TYPE_MAP[pkType] ?? "number",
606
+ optional: false,
607
+ readonly: options.readonly ?? true,
608
+ comment: "Primary key"
609
+ });
610
+ if (schema.properties) {
611
+ for (const [propName, property] of Object.entries(schema.properties)) {
612
+ properties.push(propertyToTSProperty(propName, property, allSchemas, options));
613
+ }
614
+ }
615
+ if (schema.options?.timestamps !== false) {
616
+ properties.push(
617
+ {
618
+ name: "createdAt",
619
+ type: "string",
620
+ optional: true,
621
+ readonly: options.readonly ?? true,
622
+ comment: "Creation timestamp"
623
+ },
624
+ {
625
+ name: "updatedAt",
626
+ type: "string",
627
+ optional: true,
628
+ readonly: options.readonly ?? true,
629
+ comment: "Last update timestamp"
630
+ }
631
+ );
632
+ }
633
+ if (schema.options?.softDelete) {
634
+ properties.push({
635
+ name: "deletedAt",
636
+ type: "string",
637
+ optional: true,
638
+ readonly: options.readonly ?? true,
639
+ comment: "Soft delete timestamp"
640
+ });
641
+ }
642
+ return {
643
+ name: toInterfaceName(schema.name),
644
+ properties,
645
+ comment: schema.displayName ?? schema.name
646
+ };
647
+ }
648
+ function formatProperty(property) {
649
+ const readonly = property.readonly ? "readonly " : "";
650
+ const optional = property.optional ? "?" : "";
651
+ const comment = property.comment ? ` /** ${property.comment} */
652
+ ` : "";
653
+ return `${comment} ${readonly}${property.name}${optional}: ${property.type};`;
654
+ }
655
+ function formatInterface(iface) {
656
+ const comment = iface.comment ? `/**
657
+ * ${iface.comment}
658
+ */
659
+ ` : "";
660
+ const extendsClause = iface.extends && iface.extends.length > 0 ? ` extends ${iface.extends.join(", ")}` : "";
661
+ const properties = iface.properties.map(formatProperty).join("\n");
662
+ return `${comment}export interface ${iface.name}${extendsClause} {
663
+ ${properties}
664
+ }`;
665
+ }
666
+ function generateInterfaces(schemas, options = {}) {
667
+ const interfaces = [];
668
+ for (const schema of Object.values(schemas)) {
669
+ if (schema.kind === "enum") {
670
+ continue;
671
+ }
672
+ interfaces.push(schemaToInterface(schema, schemas, options));
673
+ }
674
+ return interfaces;
675
+ }
676
+
677
+ // src/typescript/enum-generator.ts
678
+ function toEnumMemberName(value) {
679
+ return value.split(/[-_\s]+/).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join("").replace(/[^a-zA-Z0-9]/g, "");
680
+ }
681
+ function toEnumName(schemaName) {
682
+ return schemaName;
683
+ }
684
+ function schemaToEnum(schema) {
685
+ if (schema.kind !== "enum" || !schema.values) {
686
+ return null;
687
+ }
688
+ const values = schema.values.map((value) => ({
689
+ name: toEnumMemberName(value),
690
+ value
691
+ }));
692
+ return {
693
+ name: toEnumName(schema.name),
694
+ values,
695
+ comment: schema.displayName ?? schema.name
696
+ };
697
+ }
698
+ function generateEnums(schemas) {
699
+ const enums = [];
700
+ for (const schema of Object.values(schemas)) {
701
+ if (schema.kind === "enum") {
702
+ const enumDef = schemaToEnum(schema);
703
+ if (enumDef) {
704
+ enums.push(enumDef);
705
+ }
706
+ }
707
+ }
708
+ return enums;
709
+ }
710
+ function formatEnum(enumDef) {
711
+ const comment = enumDef.comment ? `/**
712
+ * ${enumDef.comment}
713
+ */
714
+ ` : "";
715
+ const values = enumDef.values.map((v) => ` ${v.name} = '${v.value}',`).join("\n");
716
+ return `${comment}export enum ${enumDef.name} {
717
+ ${values}
718
+ }`;
719
+ }
720
+ function enumToUnionType(enumDef) {
721
+ const type = enumDef.values.map((v) => `'${v.value}'`).join(" | ");
722
+ return {
723
+ name: enumDef.name,
724
+ type,
725
+ comment: enumDef.comment
726
+ };
727
+ }
728
+ function formatTypeAlias(alias) {
729
+ const comment = alias.comment ? `/**
730
+ * ${alias.comment}
731
+ */
732
+ ` : "";
733
+ return `${comment}export type ${alias.name} = ${alias.type};`;
734
+ }
735
+ function extractInlineEnums(schemas) {
736
+ const typeAliases = [];
737
+ for (const schema of Object.values(schemas)) {
738
+ if (schema.kind === "enum" || !schema.properties) {
739
+ continue;
740
+ }
741
+ for (const [propName, property] of Object.entries(schema.properties)) {
742
+ if (property.type === "Enum") {
743
+ const enumProp = property;
744
+ if (Array.isArray(enumProp.enum) && enumProp.enum.length > 0) {
745
+ const typeName = `${schema.name}${propName.charAt(0).toUpperCase() + propName.slice(1)}`;
746
+ typeAliases.push({
747
+ name: typeName,
748
+ type: enumProp.enum.map((v) => `'${v}'`).join(" | "),
749
+ comment: enumProp.displayName ?? `${schema.name} ${propName} enum`
750
+ });
751
+ }
752
+ }
753
+ if (property.type === "Select") {
754
+ const selectProp = property;
755
+ if (selectProp.options && selectProp.options.length > 0) {
756
+ const typeName = `${schema.name}${propName.charAt(0).toUpperCase() + propName.slice(1)}`;
757
+ typeAliases.push({
758
+ name: typeName,
759
+ type: selectProp.options.map((v) => `'${v}'`).join(" | "),
760
+ comment: selectProp.displayName ?? `${schema.name} ${propName} options`
761
+ });
762
+ }
763
+ }
764
+ }
765
+ }
766
+ return typeAliases;
767
+ }
768
+
769
+ // src/typescript/generator.ts
770
+ var DEFAULT_OPTIONS = {
771
+ singleFile: true,
772
+ fileName: "types.ts",
773
+ readonly: true,
774
+ strictNullChecks: true
775
+ };
776
+ function generateHeader() {
777
+ return `/**
778
+ * Auto-generated TypeScript types from Omnify schemas.
779
+ * DO NOT EDIT - This file is automatically generated.
780
+ */
781
+
782
+ `;
783
+ }
784
+ function generateTypeScriptFile(schemas, options = {}) {
785
+ const opts = { ...DEFAULT_OPTIONS, ...options };
786
+ const parts = [generateHeader()];
787
+ const types = [];
788
+ const enums = generateEnums(schemas);
789
+ if (enums.length > 0) {
790
+ parts.push("// Enums\n");
791
+ for (const enumDef of enums) {
792
+ parts.push(formatEnum(enumDef));
793
+ parts.push("\n\n");
794
+ types.push(enumDef.name);
795
+ }
796
+ }
797
+ const inlineEnums = extractInlineEnums(schemas);
798
+ if (inlineEnums.length > 0) {
799
+ parts.push("// Type Aliases\n");
800
+ for (const alias of inlineEnums) {
801
+ parts.push(formatTypeAlias(alias));
802
+ parts.push("\n\n");
803
+ types.push(alias.name);
804
+ }
805
+ }
806
+ const interfaces = generateInterfaces(schemas, opts);
807
+ if (interfaces.length > 0) {
808
+ parts.push("// Interfaces\n");
809
+ for (const iface of interfaces) {
810
+ parts.push(formatInterface(iface));
811
+ parts.push("\n\n");
812
+ types.push(iface.name);
813
+ }
814
+ }
815
+ return {
816
+ fileName: opts.fileName ?? "types.ts",
817
+ content: parts.join("").trim() + "\n",
818
+ types
819
+ };
820
+ }
821
+ function generateTypeScriptFiles(schemas, options = {}) {
822
+ const opts = { ...DEFAULT_OPTIONS, ...options };
823
+ const files = [];
824
+ const enums = generateEnums(schemas);
825
+ if (enums.length > 0) {
826
+ const content = generateHeader() + enums.map(formatEnum).join("\n\n") + "\n";
827
+ files.push({
828
+ fileName: "enums.ts",
829
+ content,
830
+ types: enums.map((e) => e.name)
831
+ });
832
+ }
833
+ const inlineEnums = extractInlineEnums(schemas);
834
+ if (inlineEnums.length > 0) {
835
+ const content = generateHeader() + inlineEnums.map(formatTypeAlias).join("\n\n") + "\n";
836
+ files.push({
837
+ fileName: "type-aliases.ts",
838
+ content,
839
+ types: inlineEnums.map((a) => a.name)
840
+ });
841
+ }
842
+ const interfaces = generateInterfaces(schemas, opts);
843
+ for (const iface of interfaces) {
844
+ const imports = collectImports(iface, enums, inlineEnums, interfaces);
845
+ const importStatement = formatImports(imports);
846
+ const content = generateHeader() + (importStatement ? importStatement + "\n\n" : "") + formatInterface(iface) + "\n";
847
+ files.push({
848
+ fileName: `${toKebabCase(iface.name)}.ts`,
849
+ content,
850
+ types: [iface.name]
851
+ });
852
+ }
853
+ const indexContent = generateIndexFile(files);
854
+ files.push({
855
+ fileName: "index.ts",
856
+ content: indexContent,
857
+ types: []
858
+ });
859
+ return files;
860
+ }
861
+ function toKebabCase(name) {
862
+ return name.replace(/([A-Z])/g, "-$1").toLowerCase().replace(/^-/, "");
863
+ }
864
+ function collectImports(iface, enums, typeAliases, allInterfaces) {
865
+ const imports = /* @__PURE__ */ new Map();
866
+ const enumNames = new Set(enums.map((e) => e.name));
867
+ const aliasNames = new Set(typeAliases.map((a) => a.name));
868
+ const interfaceNames = new Set(allInterfaces.map((i) => i.name));
869
+ for (const prop of iface.properties) {
870
+ if (enumNames.has(prop.type)) {
871
+ const existing = imports.get("./enums.js") ?? [];
872
+ if (!existing.includes(prop.type)) {
873
+ imports.set("./enums.js", [...existing, prop.type]);
874
+ }
875
+ }
876
+ if (aliasNames.has(prop.type)) {
877
+ const existing = imports.get("./type-aliases.js") ?? [];
878
+ if (!existing.includes(prop.type)) {
879
+ imports.set("./type-aliases.js", [...existing, prop.type]);
880
+ }
881
+ }
882
+ const baseType = prop.type.replace("[]", "");
883
+ if (interfaceNames.has(baseType) && baseType !== iface.name) {
884
+ const fileName = `./${toKebabCase(baseType)}.js`;
885
+ const existing = imports.get(fileName) ?? [];
886
+ if (!existing.includes(baseType)) {
887
+ imports.set(fileName, [...existing, baseType]);
888
+ }
889
+ }
890
+ }
891
+ return imports;
892
+ }
893
+ function formatImports(imports) {
894
+ if (imports.size === 0) return "";
895
+ const lines = [];
896
+ for (const [path, names] of imports) {
897
+ lines.push(`import type { ${names.join(", ")} } from '${path}';`);
898
+ }
899
+ return lines.join("\n");
900
+ }
901
+ function generateIndexFile(files) {
902
+ const exports2 = [generateHeader().trim(), ""];
903
+ for (const file of files) {
904
+ if (file.fileName === "index.ts") continue;
905
+ const moduleName = file.fileName.replace(".ts", ".js");
906
+ exports2.push(`export * from './${moduleName}';`);
907
+ }
908
+ return exports2.join("\n") + "\n";
909
+ }
910
+ function generateTypeScript(schemas, options = {}) {
911
+ const opts = { ...DEFAULT_OPTIONS, ...options };
912
+ if (opts.singleFile) {
913
+ return [generateTypeScriptFile(schemas, opts)];
914
+ }
915
+ return generateTypeScriptFiles(schemas, opts);
916
+ }
917
+ function getTypeScriptPath(file, outputDir = "src/types") {
918
+ return `${outputDir}/${file.fileName}`;
919
+ }
920
+ // Annotate the CommonJS export names for ESM import in node:
921
+ 0 && (module.exports = {
922
+ enumToUnionType,
923
+ extractInlineEnums,
924
+ formatColumnMethod,
925
+ formatEnum,
926
+ formatForeignKey,
927
+ formatIndex,
928
+ formatInterface,
929
+ formatMigrationFile,
930
+ formatProperty,
931
+ formatTypeAlias,
932
+ generateDropMigrationForTable,
933
+ generateEnums,
934
+ generateForeignKey,
935
+ generateInterfaces,
936
+ generateMigrationFromSchema,
937
+ generateMigrations,
938
+ generatePrimaryKeyColumn,
939
+ generateSoftDeleteColumn,
940
+ generateTimestampColumns,
941
+ generateTypeScript,
942
+ generateTypeScriptFile,
943
+ generateTypeScriptFiles,
944
+ getMigrationPath,
945
+ getPropertyType,
946
+ getTypeScriptPath,
947
+ propertyToColumnMethod,
948
+ propertyToTSProperty,
949
+ schemaToBlueprint,
950
+ schemaToEnum,
951
+ schemaToInterface,
952
+ toColumnName,
953
+ toEnumMemberName,
954
+ toEnumName,
955
+ toInterfaceName,
956
+ toPropertyName,
957
+ toTableName
958
+ });
959
+ //# sourceMappingURL=index.cjs.map