@famgia/omnify-laravel 0.0.5 → 0.0.6
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/{chunk-AVGA7WYF.js → chunk-BA63DET3.js} +143 -2
- package/dist/chunk-BA63DET3.js.map +1 -0
- package/dist/index.cjs +142 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/dist/plugin.cjs +142 -1
- package/dist/plugin.cjs.map +1 -1
- package/dist/plugin.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-AVGA7WYF.js.map +0 -1
|
@@ -134,6 +134,9 @@ function generateForeignKey(propertyName, property, allSchemas) {
|
|
|
134
134
|
if (assocProp.relation !== "ManyToOne" && assocProp.relation !== "OneToOne") {
|
|
135
135
|
return null;
|
|
136
136
|
}
|
|
137
|
+
if (assocProp.mappedBy) {
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
137
140
|
const columnName = toColumnName(propertyName) + "_id";
|
|
138
141
|
const targetSchema = assocProp.target ? allSchemas[assocProp.target] : void 0;
|
|
139
142
|
const targetTable = assocProp.target ? toTableName(assocProp.target) : "unknown";
|
|
@@ -263,6 +266,122 @@ function formatIndex(index) {
|
|
|
263
266
|
const name = index.name ? `, '${index.name}'` : "";
|
|
264
267
|
return `$table->${method}(${columns}${name});`;
|
|
265
268
|
}
|
|
269
|
+
function generatePivotTableName(sourceTable, targetTable, customName) {
|
|
270
|
+
if (customName) {
|
|
271
|
+
return customName;
|
|
272
|
+
}
|
|
273
|
+
const tables = [sourceTable, targetTable].sort();
|
|
274
|
+
const singular1 = tables[0].replace(/ies$/, "y").replace(/s$/, "");
|
|
275
|
+
const singular2 = tables[1].replace(/ies$/, "y").replace(/s$/, "");
|
|
276
|
+
return `${singular1}_${singular2}`;
|
|
277
|
+
}
|
|
278
|
+
function extractManyToManyRelations(schema, allSchemas) {
|
|
279
|
+
const pivotTables = [];
|
|
280
|
+
if (!schema.properties) {
|
|
281
|
+
return pivotTables;
|
|
282
|
+
}
|
|
283
|
+
const sourceTable = toTableName(schema.name);
|
|
284
|
+
const sourcePkType = schema.options?.primaryKeyType ?? "BigInt";
|
|
285
|
+
for (const [, property] of Object.entries(schema.properties)) {
|
|
286
|
+
if (property.type !== "Association") {
|
|
287
|
+
continue;
|
|
288
|
+
}
|
|
289
|
+
const assocProp = property;
|
|
290
|
+
if (assocProp.relation !== "ManyToMany") {
|
|
291
|
+
continue;
|
|
292
|
+
}
|
|
293
|
+
const targetName = assocProp.target;
|
|
294
|
+
if (!targetName) {
|
|
295
|
+
continue;
|
|
296
|
+
}
|
|
297
|
+
const targetSchema = allSchemas[targetName];
|
|
298
|
+
const targetTable = toTableName(targetName);
|
|
299
|
+
const targetPkType = targetSchema?.options?.primaryKeyType ?? "BigInt";
|
|
300
|
+
const isOwningSide = assocProp.owning ?? schema.name < targetName;
|
|
301
|
+
if (!isOwningSide) {
|
|
302
|
+
continue;
|
|
303
|
+
}
|
|
304
|
+
const pivotTableName = generatePivotTableName(sourceTable, targetTable, assocProp.joinTable);
|
|
305
|
+
const sourceColumn = sourceTable.replace(/ies$/, "y").replace(/s$/, "") + "_id";
|
|
306
|
+
const targetColumn = targetTable.replace(/ies$/, "y").replace(/s$/, "") + "_id";
|
|
307
|
+
pivotTables.push({
|
|
308
|
+
tableName: pivotTableName,
|
|
309
|
+
sourceTable,
|
|
310
|
+
targetTable,
|
|
311
|
+
sourceColumn,
|
|
312
|
+
targetColumn,
|
|
313
|
+
sourcePkType,
|
|
314
|
+
targetPkType,
|
|
315
|
+
onDelete: assocProp.onDelete,
|
|
316
|
+
onUpdate: assocProp.onUpdate
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
return pivotTables;
|
|
320
|
+
}
|
|
321
|
+
function generatePivotTableBlueprint(pivot) {
|
|
322
|
+
const columns = [];
|
|
323
|
+
const foreignKeys = [];
|
|
324
|
+
const indexes = [];
|
|
325
|
+
const getMethodForPkType = (pkType) => {
|
|
326
|
+
switch (pkType) {
|
|
327
|
+
case "Int":
|
|
328
|
+
return "unsignedInteger";
|
|
329
|
+
case "Uuid":
|
|
330
|
+
return "uuid";
|
|
331
|
+
case "String":
|
|
332
|
+
return "string";
|
|
333
|
+
default:
|
|
334
|
+
return "unsignedBigInteger";
|
|
335
|
+
}
|
|
336
|
+
};
|
|
337
|
+
columns.push({
|
|
338
|
+
name: pivot.sourceColumn,
|
|
339
|
+
method: getMethodForPkType(pivot.sourcePkType),
|
|
340
|
+
args: [pivot.sourceColumn],
|
|
341
|
+
modifiers: []
|
|
342
|
+
});
|
|
343
|
+
columns.push({
|
|
344
|
+
name: pivot.targetColumn,
|
|
345
|
+
method: getMethodForPkType(pivot.targetPkType),
|
|
346
|
+
args: [pivot.targetColumn],
|
|
347
|
+
modifiers: []
|
|
348
|
+
});
|
|
349
|
+
foreignKeys.push({
|
|
350
|
+
columns: [pivot.sourceColumn],
|
|
351
|
+
references: "id",
|
|
352
|
+
on: [pivot.sourceTable],
|
|
353
|
+
onDelete: pivot.onDelete ?? "cascade",
|
|
354
|
+
onUpdate: pivot.onUpdate ?? "cascade"
|
|
355
|
+
});
|
|
356
|
+
foreignKeys.push({
|
|
357
|
+
columns: [pivot.targetColumn],
|
|
358
|
+
references: "id",
|
|
359
|
+
on: [pivot.targetTable],
|
|
360
|
+
onDelete: pivot.onDelete ?? "cascade",
|
|
361
|
+
onUpdate: pivot.onUpdate ?? "cascade"
|
|
362
|
+
});
|
|
363
|
+
indexes.push({
|
|
364
|
+
columns: [pivot.sourceColumn, pivot.targetColumn],
|
|
365
|
+
unique: true
|
|
366
|
+
});
|
|
367
|
+
indexes.push({
|
|
368
|
+
name: `idx_${pivot.sourceColumn}`,
|
|
369
|
+
columns: [pivot.sourceColumn],
|
|
370
|
+
unique: false
|
|
371
|
+
});
|
|
372
|
+
indexes.push({
|
|
373
|
+
name: `idx_${pivot.targetColumn}`,
|
|
374
|
+
columns: [pivot.targetColumn],
|
|
375
|
+
unique: false
|
|
376
|
+
});
|
|
377
|
+
return {
|
|
378
|
+
tableName: pivot.tableName,
|
|
379
|
+
columns,
|
|
380
|
+
primaryKey: [pivot.sourceColumn, pivot.targetColumn],
|
|
381
|
+
foreignKeys,
|
|
382
|
+
indexes
|
|
383
|
+
};
|
|
384
|
+
}
|
|
266
385
|
|
|
267
386
|
// src/migration/generator.ts
|
|
268
387
|
function generateTimestamp() {
|
|
@@ -404,6 +523,7 @@ return new class extends Migration
|
|
|
404
523
|
}
|
|
405
524
|
function generateMigrations(schemas, options = {}) {
|
|
406
525
|
const migrations = [];
|
|
526
|
+
const pivotTablesGenerated = /* @__PURE__ */ new Set();
|
|
407
527
|
let timestampOffset = 0;
|
|
408
528
|
for (const schema of Object.values(schemas)) {
|
|
409
529
|
if (schema.kind === "enum") {
|
|
@@ -419,6 +539,27 @@ function generateMigrations(schemas, options = {}) {
|
|
|
419
539
|
});
|
|
420
540
|
migrations.push(migration);
|
|
421
541
|
}
|
|
542
|
+
for (const schema of Object.values(schemas)) {
|
|
543
|
+
if (schema.kind === "enum") {
|
|
544
|
+
continue;
|
|
545
|
+
}
|
|
546
|
+
const pivotTables = extractManyToManyRelations(schema, schemas);
|
|
547
|
+
for (const pivot of pivotTables) {
|
|
548
|
+
if (pivotTablesGenerated.has(pivot.tableName)) {
|
|
549
|
+
continue;
|
|
550
|
+
}
|
|
551
|
+
pivotTablesGenerated.add(pivot.tableName);
|
|
552
|
+
const timestamp = options.timestamp ?? generateTimestamp();
|
|
553
|
+
const offsetTimestamp = incrementTimestamp(timestamp, timestampOffset);
|
|
554
|
+
timestampOffset++;
|
|
555
|
+
const blueprint = generatePivotTableBlueprint(pivot);
|
|
556
|
+
const migration = generateCreateMigration(blueprint, {
|
|
557
|
+
...options,
|
|
558
|
+
timestamp: offsetTimestamp
|
|
559
|
+
});
|
|
560
|
+
migrations.push(migration);
|
|
561
|
+
}
|
|
562
|
+
}
|
|
422
563
|
return migrations;
|
|
423
564
|
}
|
|
424
565
|
function incrementTimestamp(timestamp, seconds) {
|
|
@@ -873,7 +1014,7 @@ function laravelPlugin(options) {
|
|
|
873
1014
|
const resolved = resolveOptions(options);
|
|
874
1015
|
return {
|
|
875
1016
|
name: "@famgia/omnify-laravel",
|
|
876
|
-
version: "0.0.
|
|
1017
|
+
version: "0.0.6",
|
|
877
1018
|
generators: [
|
|
878
1019
|
// Laravel Migrations Generator
|
|
879
1020
|
...resolved.generateMigrations ? [
|
|
@@ -962,4 +1103,4 @@ export {
|
|
|
962
1103
|
getTypeScriptPath,
|
|
963
1104
|
laravelPlugin
|
|
964
1105
|
};
|
|
965
|
-
//# sourceMappingURL=chunk-
|
|
1106
|
+
//# sourceMappingURL=chunk-BA63DET3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/migration/schema-builder.ts","../src/migration/generator.ts","../src/typescript/interface-generator.ts","../src/typescript/enum-generator.ts","../src/typescript/generator.ts","../src/plugin.ts"],"sourcesContent":["/**\n * @famgia/omnify-laravel - Schema Builder Converter\n *\n * Converts SQL types and operations to Laravel Schema Builder methods.\n */\n\nimport type { PropertyDefinition, LoadedSchema, SchemaCollection } from '@famgia/omnify-types';\nimport type {\n ColumnMethod,\n ColumnModifier,\n ForeignKeyDefinition,\n IndexDefinition,\n TableBlueprint,\n} from './types.js';\n\n/**\n * Maps Omnify property types to Laravel column methods.\n */\nconst TYPE_METHOD_MAP: Record<string, string> = {\n String: 'string',\n Int: 'integer',\n BigInt: 'bigInteger',\n Float: 'double',\n Boolean: 'boolean',\n Text: 'text',\n LongText: 'longText',\n Date: 'date',\n Time: 'time',\n Timestamp: 'timestamp',\n Json: 'json',\n Email: 'string',\n Password: 'string',\n File: 'string',\n MultiFile: 'json',\n Enum: 'enum',\n Select: 'string',\n Lookup: 'unsignedBigInteger',\n};\n\n/**\n * Maps primary key types to Laravel methods.\n */\nconst PK_METHOD_MAP: Record<string, string> = {\n Int: 'increments',\n BigInt: 'bigIncrements',\n Uuid: 'uuid',\n String: 'string',\n};\n\n/**\n * Converts a property name to snake_case column name.\n */\nexport function toColumnName(propertyName: string): string {\n return propertyName.replace(/([A-Z])/g, '_$1').toLowerCase().replace(/^_/, '');\n}\n\n/**\n * Converts schema name to snake_case plural table name.\n */\nexport function toTableName(schemaName: string): string {\n const snakeCase = schemaName\n .replace(/([A-Z])/g, '_$1')\n .toLowerCase()\n .replace(/^_/, '');\n\n // Simple pluralization\n if (snakeCase.endsWith('y')) {\n return snakeCase.slice(0, -1) + 'ies';\n } else if (\n snakeCase.endsWith('s') ||\n snakeCase.endsWith('x') ||\n snakeCase.endsWith('ch') ||\n snakeCase.endsWith('sh')\n ) {\n return snakeCase + 'es';\n } else {\n return snakeCase + 's';\n }\n}\n\n/**\n * Converts a property to Laravel column method.\n */\nexport function propertyToColumnMethod(\n propertyName: string,\n property: PropertyDefinition\n): ColumnMethod | null {\n // Skip associations - they're handled separately\n if (property.type === 'Association') {\n return null;\n }\n\n const columnName = toColumnName(propertyName);\n const method = TYPE_METHOD_MAP[property.type] ?? 'string';\n const args: (string | number | boolean)[] = [columnName];\n const modifiers: ColumnModifier[] = [];\n\n // Handle length for string types\n const propWithLength = property as { length?: number };\n if (method === 'string' && propWithLength.length) {\n args.push(propWithLength.length);\n }\n\n // Handle enum values\n if (property.type === 'Enum') {\n const enumProp = property as { enum?: readonly string[] };\n if (enumProp.enum && enumProp.enum.length > 0) {\n args.push(enumProp.enum as unknown as string);\n }\n }\n\n // Add modifiers\n const baseProp = property as {\n nullable?: boolean;\n unique?: boolean;\n default?: unknown;\n unsigned?: boolean;\n };\n\n if (baseProp.nullable) {\n modifiers.push({ method: 'nullable' });\n }\n\n if (baseProp.unique) {\n modifiers.push({ method: 'unique' });\n }\n\n if (baseProp.default !== undefined) {\n const defaultValue = typeof baseProp.default === 'string'\n ? baseProp.default\n : JSON.stringify(baseProp.default);\n modifiers.push({ method: 'default', args: [defaultValue] });\n }\n\n if (baseProp.unsigned && (method === 'integer' || method === 'bigInteger')) {\n modifiers.push({ method: 'unsigned' });\n }\n\n return {\n name: columnName,\n method,\n args,\n modifiers,\n };\n}\n\n/**\n * Generates primary key column method.\n */\nexport function generatePrimaryKeyColumn(\n pkType: 'Int' | 'BigInt' | 'Uuid' | 'String' = 'BigInt'\n): ColumnMethod {\n const method = PK_METHOD_MAP[pkType] ?? 'bigIncrements';\n\n if (pkType === 'Uuid') {\n return {\n name: 'id',\n method: 'uuid',\n args: ['id'],\n modifiers: [{ method: 'primary' }],\n };\n }\n\n if (pkType === 'String') {\n return {\n name: 'id',\n method: 'string',\n args: ['id', 255],\n modifiers: [{ method: 'primary' }],\n };\n }\n\n // For Int/BigInt, use increments which auto-creates primary key\n return {\n name: 'id',\n method,\n args: ['id'],\n modifiers: [],\n };\n}\n\n/**\n * Generates timestamp columns.\n */\nexport function generateTimestampColumns(): ColumnMethod[] {\n return [\n {\n name: 'created_at',\n method: 'timestamp',\n args: ['created_at'],\n modifiers: [{ method: 'nullable' }],\n },\n {\n name: 'updated_at',\n method: 'timestamp',\n args: ['updated_at'],\n modifiers: [{ method: 'nullable' }],\n },\n ];\n}\n\n/**\n * Generates soft delete column.\n */\nexport function generateSoftDeleteColumn(): ColumnMethod {\n return {\n name: 'deleted_at',\n method: 'timestamp',\n args: ['deleted_at'],\n modifiers: [{ method: 'nullable' }],\n };\n}\n\n/**\n * Generates foreign key column and constraint from association.\n */\nexport function generateForeignKey(\n propertyName: string,\n property: PropertyDefinition,\n allSchemas: SchemaCollection\n): { column: ColumnMethod; foreignKey: ForeignKeyDefinition; index: IndexDefinition } | null {\n if (property.type !== 'Association') {\n return null;\n }\n\n const assocProp = property as {\n relation?: string;\n target?: string;\n onDelete?: string;\n onUpdate?: string;\n mappedBy?: string;\n owningSide?: boolean;\n };\n\n // Only create FK column for ManyToOne and OneToOne (owning side)\n if (assocProp.relation !== 'ManyToOne' && assocProp.relation !== 'OneToOne') {\n return null;\n }\n\n // Skip inverse side (mappedBy means this is the inverse side)\n if (assocProp.mappedBy) {\n return null;\n }\n\n const columnName = toColumnName(propertyName) + '_id';\n const targetSchema = assocProp.target ? allSchemas[assocProp.target] : undefined;\n const targetTable = assocProp.target ? toTableName(assocProp.target) : 'unknown';\n const targetPkType = targetSchema?.options?.primaryKeyType ?? 'BigInt';\n\n // Determine column method based on target PK type\n let method = 'unsignedBigInteger';\n if (targetPkType === 'Int') {\n method = 'unsignedInteger';\n } else if (targetPkType === 'Uuid') {\n method = 'uuid';\n } else if (targetPkType === 'String') {\n method = 'string';\n }\n\n const column: ColumnMethod = {\n name: columnName,\n method,\n args: [columnName],\n modifiers: assocProp.relation === 'ManyToOne' ? [{ method: 'nullable' }] : [],\n };\n\n const foreignKey: ForeignKeyDefinition = {\n columns: [columnName],\n references: 'id',\n on: [targetTable],\n onDelete: assocProp.onDelete ?? 'restrict',\n onUpdate: assocProp.onUpdate ?? 'cascade',\n };\n\n const index: IndexDefinition = {\n name: `idx_${columnName}`,\n columns: [columnName],\n unique: false,\n };\n\n return { column, foreignKey, index };\n}\n\n/**\n * Generates table blueprint from schema.\n */\nexport function schemaToBlueprint(\n schema: LoadedSchema,\n allSchemas: SchemaCollection\n): TableBlueprint {\n const tableName = toTableName(schema.name);\n const columns: ColumnMethod[] = [];\n const foreignKeys: ForeignKeyDefinition[] = [];\n const indexes: IndexDefinition[] = [];\n\n // Primary key\n const pkType = (schema.options?.primaryKeyType ?? 'BigInt') as 'Int' | 'BigInt' | 'Uuid' | 'String';\n columns.push(generatePrimaryKeyColumn(pkType));\n\n // Process properties\n if (schema.properties) {\n for (const [propName, property] of Object.entries(schema.properties)) {\n // Handle regular columns\n const columnMethod = propertyToColumnMethod(propName, property);\n if (columnMethod) {\n columns.push(columnMethod);\n }\n\n // Handle foreign keys\n const fkResult = generateForeignKey(propName, property, allSchemas);\n if (fkResult) {\n columns.push(fkResult.column);\n foreignKeys.push(fkResult.foreignKey);\n indexes.push(fkResult.index);\n }\n }\n }\n\n // Timestamps\n if (schema.options?.timestamps !== false) {\n columns.push(...generateTimestampColumns());\n }\n\n // Soft delete\n if (schema.options?.softDelete) {\n columns.push(generateSoftDeleteColumn());\n }\n\n // Custom indexes\n if (schema.options?.indexes) {\n for (const index of schema.options.indexes) {\n indexes.push({\n name: index.name,\n columns: index.columns.map(toColumnName),\n unique: index.unique ?? false,\n });\n }\n }\n\n // Unique constraints\n if (schema.options?.unique) {\n const uniqueConstraints = Array.isArray(schema.options.unique[0])\n ? (schema.options.unique as readonly (readonly string[])[])\n : [schema.options.unique as readonly string[]];\n\n for (const constraint of uniqueConstraints) {\n indexes.push({\n columns: constraint.map(toColumnName),\n unique: true,\n });\n }\n }\n\n return {\n tableName,\n columns,\n primaryKey: ['id'],\n foreignKeys,\n indexes,\n };\n}\n\n/**\n * Formats a column method to PHP code.\n */\nexport function formatColumnMethod(column: ColumnMethod): string {\n const args = column.args.map(arg => {\n if (typeof arg === 'string') {\n return `'${arg}'`;\n }\n if (Array.isArray(arg)) {\n return `[${(arg as string[]).map(v => `'${v}'`).join(', ')}]`;\n }\n return String(arg);\n }).join(', ');\n\n let code = `$table->${column.method}(${args})`;\n\n for (const modifier of column.modifiers) {\n if (modifier.args && modifier.args.length > 0) {\n const modArgs = modifier.args.map(arg => {\n if (typeof arg === 'string') {\n return `'${arg}'`;\n }\n return String(arg);\n }).join(', ');\n code += `->${modifier.method}(${modArgs})`;\n } else {\n code += `->${modifier.method}()`;\n }\n }\n\n return code + ';';\n}\n\n/**\n * Formats a foreign key to PHP code.\n */\nexport function formatForeignKey(fk: ForeignKeyDefinition): string {\n const column = fk.columns[0];\n const table = fk.on[0];\n let code = `$table->foreign('${column}')->references('${fk.references}')->on('${table}')`;\n\n if (fk.onDelete) {\n code += `->onDelete('${fk.onDelete}')`;\n }\n if (fk.onUpdate) {\n code += `->onUpdate('${fk.onUpdate}')`;\n }\n\n return code + ';';\n}\n\n/**\n * Formats an index to PHP code.\n */\nexport function formatIndex(index: IndexDefinition): string {\n const columns = index.columns.length === 1\n ? `'${index.columns[0]}'`\n : `[${index.columns.map(c => `'${c}'`).join(', ')}]`;\n\n const method = index.unique ? 'unique' : 'index';\n const name = index.name ? `, '${index.name}'` : '';\n\n return `$table->${method}(${columns}${name});`;\n}\n\n/**\n * Pivot table information for ManyToMany relationships.\n */\nexport interface PivotTableInfo {\n tableName: string;\n sourceTable: string;\n targetTable: string;\n sourceColumn: string;\n targetColumn: string;\n sourcePkType: 'Int' | 'BigInt' | 'Uuid' | 'String';\n targetPkType: 'Int' | 'BigInt' | 'Uuid' | 'String';\n onDelete: string | undefined;\n onUpdate: string | undefined;\n}\n\n/**\n * Generates pivot table name for ManyToMany relationship.\n * Uses alphabetical ordering for consistency.\n */\nexport function generatePivotTableName(\n sourceTable: string,\n targetTable: string,\n customName?: string\n): string {\n if (customName) {\n return customName;\n }\n\n // Sort alphabetically for consistent naming\n const tables = [sourceTable, targetTable].sort();\n // Remove trailing 's' and join with underscore\n const singular1 = tables[0]!.replace(/ies$/, 'y').replace(/s$/, '');\n const singular2 = tables[1]!.replace(/ies$/, 'y').replace(/s$/, '');\n return `${singular1}_${singular2}`;\n}\n\n/**\n * Extracts ManyToMany relationships from a schema.\n */\nexport function extractManyToManyRelations(\n schema: LoadedSchema,\n allSchemas: SchemaCollection\n): PivotTableInfo[] {\n const pivotTables: PivotTableInfo[] = [];\n\n if (!schema.properties) {\n return pivotTables;\n }\n\n const sourceTable = toTableName(schema.name);\n const sourcePkType = (schema.options?.primaryKeyType ?? 'BigInt') as 'Int' | 'BigInt' | 'Uuid' | 'String';\n\n for (const [, property] of Object.entries(schema.properties)) {\n if (property.type !== 'Association') {\n continue;\n }\n\n const assocProp = property as {\n relation?: string;\n target?: string;\n joinTable?: string;\n onDelete?: string;\n onUpdate?: string;\n owning?: boolean;\n };\n\n // Only handle ManyToMany on the owning side (or if not specified, use alphabetical order)\n if (assocProp.relation !== 'ManyToMany') {\n continue;\n }\n\n const targetName = assocProp.target;\n if (!targetName) {\n continue;\n }\n\n const targetSchema = allSchemas[targetName];\n const targetTable = toTableName(targetName);\n const targetPkType = (targetSchema?.options?.primaryKeyType ?? 'BigInt') as 'Int' | 'BigInt' | 'Uuid' | 'String';\n\n // Determine if this side owns the relationship\n // Default: alphabetically first schema owns it\n const isOwningSide = assocProp.owning ?? (schema.name < targetName);\n\n if (!isOwningSide) {\n continue; // Skip non-owning side to avoid duplicate pivot tables\n }\n\n const pivotTableName = generatePivotTableName(sourceTable, targetTable, assocProp.joinTable);\n\n // Column names: singular form of table name + _id\n const sourceColumn = sourceTable.replace(/ies$/, 'y').replace(/s$/, '') + '_id';\n const targetColumn = targetTable.replace(/ies$/, 'y').replace(/s$/, '') + '_id';\n\n pivotTables.push({\n tableName: pivotTableName,\n sourceTable,\n targetTable,\n sourceColumn,\n targetColumn,\n sourcePkType,\n targetPkType,\n onDelete: assocProp.onDelete,\n onUpdate: assocProp.onUpdate,\n });\n }\n\n return pivotTables;\n}\n\n/**\n * Generates blueprint for a pivot table.\n */\nexport function generatePivotTableBlueprint(pivot: PivotTableInfo): TableBlueprint {\n const columns: ColumnMethod[] = [];\n const foreignKeys: ForeignKeyDefinition[] = [];\n const indexes: IndexDefinition[] = [];\n\n // Determine column methods based on PK types\n const getMethodForPkType = (pkType: string): string => {\n switch (pkType) {\n case 'Int': return 'unsignedInteger';\n case 'Uuid': return 'uuid';\n case 'String': return 'string';\n default: return 'unsignedBigInteger';\n }\n };\n\n // Source column\n columns.push({\n name: pivot.sourceColumn,\n method: getMethodForPkType(pivot.sourcePkType),\n args: [pivot.sourceColumn],\n modifiers: [],\n });\n\n // Target column\n columns.push({\n name: pivot.targetColumn,\n method: getMethodForPkType(pivot.targetPkType),\n args: [pivot.targetColumn],\n modifiers: [],\n });\n\n // Foreign keys\n foreignKeys.push({\n columns: [pivot.sourceColumn],\n references: 'id',\n on: [pivot.sourceTable],\n onDelete: pivot.onDelete ?? 'cascade',\n onUpdate: pivot.onUpdate ?? 'cascade',\n });\n\n foreignKeys.push({\n columns: [pivot.targetColumn],\n references: 'id',\n on: [pivot.targetTable],\n onDelete: pivot.onDelete ?? 'cascade',\n onUpdate: pivot.onUpdate ?? 'cascade',\n });\n\n // Composite primary key / unique constraint\n indexes.push({\n columns: [pivot.sourceColumn, pivot.targetColumn],\n unique: true,\n });\n\n // Individual indexes for faster lookups\n indexes.push({\n name: `idx_${pivot.sourceColumn}`,\n columns: [pivot.sourceColumn],\n unique: false,\n });\n\n indexes.push({\n name: `idx_${pivot.targetColumn}`,\n columns: [pivot.targetColumn],\n unique: false,\n });\n\n return {\n tableName: pivot.tableName,\n columns,\n primaryKey: [pivot.sourceColumn, pivot.targetColumn],\n foreignKeys,\n indexes,\n };\n}\n","/**\n * @famgia/omnify-laravel - Migration Generator\n *\n * Generates Laravel migration files from schemas.\n */\n\nimport type { LoadedSchema, SchemaCollection } from '@famgia/omnify-types';\nimport type {\n MigrationFile,\n MigrationOptions,\n TableBlueprint,\n} from './types.js';\nimport {\n schemaToBlueprint,\n formatColumnMethod,\n formatForeignKey,\n formatIndex,\n extractManyToManyRelations,\n generatePivotTableBlueprint,\n} from './schema-builder.js';\n\n/**\n * Generates timestamp prefix for migration file name.\n */\nfunction generateTimestamp(): string {\n const now = new Date();\n const year = now.getFullYear();\n const month = String(now.getMonth() + 1).padStart(2, '0');\n const day = String(now.getDate()).padStart(2, '0');\n const hours = String(now.getHours()).padStart(2, '0');\n const minutes = String(now.getMinutes()).padStart(2, '0');\n const seconds = String(now.getSeconds()).padStart(2, '0');\n return `${year}_${month}_${day}_${hours}${minutes}${seconds}`;\n}\n\n/**\n * Converts table name to Laravel migration class name.\n */\nfunction toClassName(tableName: string, type: 'create' | 'alter' | 'drop'): string {\n const pascalCase = tableName\n .split('_')\n .map(word => word.charAt(0).toUpperCase() + word.slice(1))\n .join('');\n\n switch (type) {\n case 'create':\n return `Create${pascalCase}Table`;\n case 'alter':\n return `Alter${pascalCase}Table`;\n case 'drop':\n return `Drop${pascalCase}Table`;\n }\n}\n\n/**\n * Generates file name for migration.\n */\nfunction generateFileName(\n tableName: string,\n type: 'create' | 'alter' | 'drop',\n timestamp?: string\n): string {\n const ts = timestamp ?? generateTimestamp();\n const action = type === 'create' ? 'create' : type === 'drop' ? 'drop' : 'update';\n return `${ts}_${action}_${tableName}_table.php`;\n}\n\n/**\n * Renders the up method body for a create table operation.\n */\nfunction renderCreateTableUp(blueprint: TableBlueprint): string {\n const lines: string[] = [];\n\n // Column definitions\n for (const column of blueprint.columns) {\n lines.push(` ${formatColumnMethod(column)}`);\n }\n\n // Foreign keys (separate for Laravel best practices)\n // Note: Foreign keys should be in a separate migration or at the end\n // We'll include them in the same migration for simplicity\n\n return lines.join('\\n');\n}\n\n/**\n * Renders foreign key constraints (usually added after all columns).\n */\nfunction renderForeignKeys(blueprint: TableBlueprint): string {\n if (blueprint.foreignKeys.length === 0) {\n return '';\n }\n\n const lines = blueprint.foreignKeys.map(fk => ` ${formatForeignKey(fk)}`);\n return '\\n' + lines.join('\\n');\n}\n\n/**\n * Renders indexes.\n */\nfunction renderIndexes(blueprint: TableBlueprint): string {\n // Filter out indexes that are already handled (primary key, unique columns)\n const customIndexes = blueprint.indexes.filter(idx => {\n // Skip single-column unique indexes (handled by column modifier)\n if (idx.unique && idx.columns.length === 1) {\n return false;\n }\n return true;\n });\n\n if (customIndexes.length === 0) {\n return '';\n }\n\n const lines = customIndexes.map(idx => ` ${formatIndex(idx)}`);\n return '\\n' + lines.join('\\n');\n}\n\n/**\n * Generates a create table migration.\n */\nfunction generateCreateMigration(\n blueprint: TableBlueprint,\n options: MigrationOptions = {}\n): MigrationFile {\n const className = toClassName(blueprint.tableName, 'create');\n const fileName = generateFileName(blueprint.tableName, 'create', options.timestamp);\n\n const connection = options.connection\n ? `\\n protected $connection = '${options.connection}';\\n`\n : '';\n\n const upContent = renderCreateTableUp(blueprint);\n const foreignKeyContent = renderForeignKeys(blueprint);\n const indexContent = renderIndexes(blueprint);\n\n const content = `<?php\n\nuse Illuminate\\\\Database\\\\Migrations\\\\Migration;\nuse Illuminate\\\\Database\\\\Schema\\\\Blueprint;\nuse Illuminate\\\\Support\\\\Facades\\\\Schema;\n\nreturn new class extends Migration\n{${connection}\n /**\n * Run the migrations.\n */\n public function up(): void\n {\n Schema::create('${blueprint.tableName}', function (Blueprint $table) {\n${upContent}${foreignKeyContent}${indexContent}\n });\n }\n\n /**\n * Reverse the migrations.\n */\n public function down(): void\n {\n Schema::dropIfExists('${blueprint.tableName}');\n }\n};\n`;\n\n return {\n fileName,\n className,\n content,\n tables: [blueprint.tableName],\n type: 'create',\n };\n}\n\n/**\n * Generates a drop table migration.\n */\nfunction generateDropMigration(\n tableName: string,\n options: MigrationOptions = {}\n): MigrationFile {\n const className = toClassName(tableName, 'drop');\n const fileName = generateFileName(tableName, 'drop', options.timestamp);\n\n const connection = options.connection\n ? `\\n protected $connection = '${options.connection}';\\n`\n : '';\n\n const content = `<?php\n\nuse Illuminate\\\\Database\\\\Migrations\\\\Migration;\nuse Illuminate\\\\Database\\\\Schema\\\\Blueprint;\nuse Illuminate\\\\Support\\\\Facades\\\\Schema;\n\nreturn new class extends Migration\n{${connection}\n /**\n * Run the migrations.\n */\n public function up(): void\n {\n Schema::dropIfExists('${tableName}');\n }\n\n /**\n * Reverse the migrations.\n */\n public function down(): void\n {\n // Cannot recreate table without schema information\n // This is a one-way migration\n }\n};\n`;\n\n return {\n fileName,\n className,\n content,\n tables: [tableName],\n type: 'drop',\n };\n}\n\n/**\n * Generates migrations for all schemas.\n */\nexport function generateMigrations(\n schemas: SchemaCollection,\n options: MigrationOptions = {}\n): MigrationFile[] {\n const migrations: MigrationFile[] = [];\n const pivotTablesGenerated = new Set<string>();\n let timestampOffset = 0;\n\n // First pass: generate main table migrations\n for (const schema of Object.values(schemas)) {\n // Skip enum schemas\n if (schema.kind === 'enum') {\n continue;\n }\n\n // Generate timestamp with offset to ensure unique filenames\n const timestamp = options.timestamp ?? generateTimestamp();\n const offsetTimestamp = incrementTimestamp(timestamp, timestampOffset);\n timestampOffset++;\n\n const blueprint = schemaToBlueprint(schema, schemas);\n const migration = generateCreateMigration(blueprint, {\n ...options,\n timestamp: offsetTimestamp,\n });\n migrations.push(migration);\n }\n\n // Second pass: generate pivot table migrations for ManyToMany\n for (const schema of Object.values(schemas)) {\n if (schema.kind === 'enum') {\n continue;\n }\n\n const pivotTables = extractManyToManyRelations(schema, schemas);\n\n for (const pivot of pivotTables) {\n // Skip if already generated\n if (pivotTablesGenerated.has(pivot.tableName)) {\n continue;\n }\n pivotTablesGenerated.add(pivot.tableName);\n\n const timestamp = options.timestamp ?? generateTimestamp();\n const offsetTimestamp = incrementTimestamp(timestamp, timestampOffset);\n timestampOffset++;\n\n const blueprint = generatePivotTableBlueprint(pivot);\n const migration = generateCreateMigration(blueprint, {\n ...options,\n timestamp: offsetTimestamp,\n });\n migrations.push(migration);\n }\n }\n\n return migrations;\n}\n\n/**\n * Increments a timestamp by seconds.\n */\nfunction incrementTimestamp(timestamp: string, seconds: number): string {\n if (seconds === 0) return timestamp;\n\n // Parse timestamp: YYYY_MM_DD_HHMMSS\n const parts = timestamp.split('_');\n if (parts.length < 4) {\n // Invalid format, return original\n return timestamp;\n }\n\n const yearPart = parts[0] ?? '2024';\n const monthPart = parts[1] ?? '01';\n const dayPart = parts[2] ?? '01';\n const timePart = parts[3] ?? '000000';\n\n const year = parseInt(yearPart, 10);\n const month = parseInt(monthPart, 10) - 1;\n const day = parseInt(dayPart, 10);\n const hours = parseInt(timePart.substring(0, 2), 10);\n const minutes = parseInt(timePart.substring(2, 4), 10);\n const secs = parseInt(timePart.substring(4, 6), 10);\n\n const date = new Date(year, month, day, hours, minutes, secs + seconds);\n\n const newYear = date.getFullYear();\n const newMonth = String(date.getMonth() + 1).padStart(2, '0');\n const newDay = String(date.getDate()).padStart(2, '0');\n const newHours = String(date.getHours()).padStart(2, '0');\n const newMinutes = String(date.getMinutes()).padStart(2, '0');\n const newSecs = String(date.getSeconds()).padStart(2, '0');\n\n return `${newYear}_${newMonth}_${newDay}_${newHours}${newMinutes}${newSecs}`;\n}\n\n/**\n * Generates migration from a single schema.\n */\nexport function generateMigrationFromSchema(\n schema: LoadedSchema,\n allSchemas: SchemaCollection,\n options: MigrationOptions = {}\n): MigrationFile {\n const blueprint = schemaToBlueprint(schema, allSchemas);\n return generateCreateMigration(blueprint, options);\n}\n\n/**\n * Generates drop migration for a table.\n */\nexport function generateDropMigrationForTable(\n tableName: string,\n options: MigrationOptions = {}\n): MigrationFile {\n return generateDropMigration(tableName, options);\n}\n\n/**\n * Formats migration content for writing to file.\n */\nexport function formatMigrationFile(migration: MigrationFile): string {\n return migration.content;\n}\n\n/**\n * Gets the output path for a migration file.\n */\nexport function getMigrationPath(\n migration: MigrationFile,\n outputDir: string = 'database/migrations'\n): string {\n return `${outputDir}/${migration.fileName}`;\n}\n","/**\n * @famgia/omnify-laravel - TypeScript Interface Generator\n *\n * Generates TypeScript interfaces from schemas.\n */\n\nimport type { LoadedSchema, PropertyDefinition, SchemaCollection } from '@famgia/omnify-types';\nimport type { TSInterface, TSProperty, TypeScriptOptions } from './types.js';\n\n/**\n * Maps Omnify property types to TypeScript types.\n */\nconst TYPE_MAP: Record<string, string> = {\n String: 'string',\n Int: 'number',\n BigInt: 'number',\n Float: 'number',\n Boolean: 'boolean',\n Text: 'string',\n LongText: 'string',\n Date: 'string',\n Time: 'string',\n Timestamp: 'string',\n Json: 'unknown',\n Email: 'string',\n Password: 'string',\n File: 'string',\n MultiFile: 'string[]',\n Enum: 'string',\n Select: 'string',\n Lookup: 'number',\n};\n\n/**\n * Maps primary key types to TypeScript types.\n */\nconst PK_TYPE_MAP: Record<string, string> = {\n Int: 'number',\n BigInt: 'number',\n Uuid: 'string',\n String: 'string',\n};\n\n/**\n * Converts property name to TypeScript property name.\n * Preserves camelCase.\n */\nexport function toPropertyName(name: string): string {\n return name;\n}\n\n/**\n * Converts schema name to TypeScript interface name.\n * Preserves PascalCase.\n */\nexport function toInterfaceName(schemaName: string): string {\n return schemaName;\n}\n\n/**\n * Gets TypeScript type for a property.\n */\nexport function getPropertyType(\n property: PropertyDefinition,\n _allSchemas: SchemaCollection\n): string {\n // Handle associations\n if (property.type === 'Association') {\n const assocProp = property as {\n relation?: string;\n target?: string;\n };\n\n const targetName = assocProp.target ?? 'unknown';\n\n switch (assocProp.relation) {\n case 'OneToOne':\n case 'ManyToOne':\n return targetName;\n case 'OneToMany':\n case 'ManyToMany':\n return `${targetName}[]`;\n default:\n return 'unknown';\n }\n }\n\n // Handle enum types\n if (property.type === 'Enum') {\n const enumProp = property as { enum?: string | readonly string[] };\n if (typeof enumProp.enum === 'string') {\n // Reference to a named enum\n return enumProp.enum;\n }\n if (Array.isArray(enumProp.enum)) {\n // Inline enum - create union type\n return enumProp.enum.map(v => `'${v}'`).join(' | ');\n }\n }\n\n // Handle Select with options\n if (property.type === 'Select') {\n const selectProp = property as { options?: readonly string[] };\n if (selectProp.options && selectProp.options.length > 0) {\n return selectProp.options.map(v => `'${v}'`).join(' | ');\n }\n }\n\n // Standard type mapping\n return TYPE_MAP[property.type] ?? 'unknown';\n}\n\n/**\n * Converts a property to TypeScript property definition.\n */\nexport function propertyToTSProperty(\n propertyName: string,\n property: PropertyDefinition,\n allSchemas: SchemaCollection,\n options: TypeScriptOptions = {}\n): TSProperty {\n const type = getPropertyType(property, allSchemas);\n const baseProp = property as { nullable?: boolean; displayName?: string };\n\n return {\n name: toPropertyName(propertyName),\n type,\n optional: baseProp.nullable ?? false,\n readonly: options.readonly ?? true,\n comment: baseProp.displayName,\n };\n}\n\n/**\n * Generates TypeScript interface from schema.\n */\nexport function schemaToInterface(\n schema: LoadedSchema,\n allSchemas: SchemaCollection,\n options: TypeScriptOptions = {}\n): TSInterface {\n const properties: TSProperty[] = [];\n\n // ID property\n const pkType = (schema.options?.primaryKeyType ?? 'BigInt') as keyof typeof PK_TYPE_MAP;\n properties.push({\n name: 'id',\n type: PK_TYPE_MAP[pkType] ?? 'number',\n optional: false,\n readonly: options.readonly ?? true,\n comment: 'Primary key',\n });\n\n // Schema properties\n if (schema.properties) {\n for (const [propName, property] of Object.entries(schema.properties)) {\n properties.push(propertyToTSProperty(propName, property, allSchemas, options));\n }\n }\n\n // Timestamps\n if (schema.options?.timestamps !== false) {\n properties.push(\n {\n name: 'createdAt',\n type: 'string',\n optional: true,\n readonly: options.readonly ?? true,\n comment: 'Creation timestamp',\n },\n {\n name: 'updatedAt',\n type: 'string',\n optional: true,\n readonly: options.readonly ?? true,\n comment: 'Last update timestamp',\n }\n );\n }\n\n // Soft delete\n if (schema.options?.softDelete) {\n properties.push({\n name: 'deletedAt',\n type: 'string',\n optional: true,\n readonly: options.readonly ?? true,\n comment: 'Soft delete timestamp',\n });\n }\n\n return {\n name: toInterfaceName(schema.name),\n properties,\n comment: schema.displayName ?? schema.name,\n };\n}\n\n/**\n * Formats a TypeScript property.\n */\nexport function formatProperty(property: TSProperty): string {\n const readonly = property.readonly ? 'readonly ' : '';\n const optional = property.optional ? '?' : '';\n const comment = property.comment ? ` /** ${property.comment} */\\n` : '';\n return `${comment} ${readonly}${property.name}${optional}: ${property.type};`;\n}\n\n/**\n * Formats a TypeScript interface.\n */\nexport function formatInterface(iface: TSInterface): string {\n const comment = iface.comment ? `/**\\n * ${iface.comment}\\n */\\n` : '';\n const extendsClause = iface.extends && iface.extends.length > 0\n ? ` extends ${iface.extends.join(', ')}`\n : '';\n const properties = iface.properties.map(formatProperty).join('\\n');\n\n return `${comment}export interface ${iface.name}${extendsClause} {\\n${properties}\\n}`;\n}\n\n/**\n * Generates interfaces for all schemas.\n */\nexport function generateInterfaces(\n schemas: SchemaCollection,\n options: TypeScriptOptions = {}\n): TSInterface[] {\n const interfaces: TSInterface[] = [];\n\n for (const schema of Object.values(schemas)) {\n // Skip enum schemas\n if (schema.kind === 'enum') {\n continue;\n }\n\n interfaces.push(schemaToInterface(schema, schemas, options));\n }\n\n return interfaces;\n}\n","/**\n * @famgia/omnify-laravel - TypeScript Enum Generator\n *\n * Generates TypeScript enums from schema enum definitions.\n */\n\nimport type { LoadedSchema, SchemaCollection } from '@famgia/omnify-types';\nimport type { TSEnum, TSEnumValue, TSTypeAlias } from './types.js';\n\n/**\n * Converts enum value to valid TypeScript enum member name.\n */\nexport function toEnumMemberName(value: string): string {\n // Convert to PascalCase and remove invalid characters\n return value\n .split(/[-_\\s]+/)\n .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join('')\n .replace(/[^a-zA-Z0-9]/g, '');\n}\n\n/**\n * Converts schema name to TypeScript enum name.\n */\nexport function toEnumName(schemaName: string): string {\n return schemaName;\n}\n\n/**\n * Generates TypeScript enum from schema enum.\n */\nexport function schemaToEnum(schema: LoadedSchema): TSEnum | null {\n if (schema.kind !== 'enum' || !schema.values) {\n return null;\n }\n\n const values: TSEnumValue[] = schema.values.map(value => ({\n name: toEnumMemberName(value),\n value,\n }));\n\n return {\n name: toEnumName(schema.name),\n values,\n comment: schema.displayName ?? schema.name,\n };\n}\n\n/**\n * Generates enums for all enum schemas.\n */\nexport function generateEnums(schemas: SchemaCollection): TSEnum[] {\n const enums: TSEnum[] = [];\n\n for (const schema of Object.values(schemas)) {\n if (schema.kind === 'enum') {\n const enumDef = schemaToEnum(schema);\n if (enumDef) {\n enums.push(enumDef);\n }\n }\n }\n\n return enums;\n}\n\n/**\n * Formats a TypeScript enum.\n */\nexport function formatEnum(enumDef: TSEnum): string {\n const comment = enumDef.comment ? `/**\\n * ${enumDef.comment}\\n */\\n` : '';\n const values = enumDef.values\n .map(v => ` ${v.name} = '${v.value}',`)\n .join('\\n');\n\n return `${comment}export enum ${enumDef.name} {\\n${values}\\n}`;\n}\n\n/**\n * Generates a union type alias as an alternative to enum.\n */\nexport function enumToUnionType(enumDef: TSEnum): TSTypeAlias {\n const type = enumDef.values\n .map(v => `'${v.value}'`)\n .join(' | ');\n\n return {\n name: enumDef.name,\n type,\n comment: enumDef.comment,\n };\n}\n\n/**\n * Formats a TypeScript type alias.\n */\nexport function formatTypeAlias(alias: TSTypeAlias): string {\n const comment = alias.comment ? `/**\\n * ${alias.comment}\\n */\\n` : '';\n return `${comment}export type ${alias.name} = ${alias.type};`;\n}\n\n/**\n * Extracts inline enums from properties for type generation.\n */\nexport function extractInlineEnums(schemas: SchemaCollection): TSTypeAlias[] {\n const typeAliases: TSTypeAlias[] = [];\n\n for (const schema of Object.values(schemas)) {\n if (schema.kind === 'enum' || !schema.properties) {\n continue;\n }\n\n for (const [propName, property] of Object.entries(schema.properties)) {\n if (property.type === 'Enum') {\n const enumProp = property as { enum?: readonly string[]; displayName?: string };\n\n // Only handle inline array enums (not references to named enums)\n if (Array.isArray(enumProp.enum) && enumProp.enum.length > 0) {\n const typeName = `${schema.name}${propName.charAt(0).toUpperCase() + propName.slice(1)}`;\n typeAliases.push({\n name: typeName,\n type: enumProp.enum.map(v => `'${v}'`).join(' | '),\n comment: enumProp.displayName ?? `${schema.name} ${propName} enum`,\n });\n }\n }\n\n if (property.type === 'Select') {\n const selectProp = property as { options?: readonly string[]; displayName?: string };\n\n if (selectProp.options && selectProp.options.length > 0) {\n const typeName = `${schema.name}${propName.charAt(0).toUpperCase() + propName.slice(1)}`;\n typeAliases.push({\n name: typeName,\n type: selectProp.options.map(v => `'${v}'`).join(' | '),\n comment: selectProp.displayName ?? `${schema.name} ${propName} options`,\n });\n }\n }\n }\n }\n\n return typeAliases;\n}\n","/**\n * @famgia/omnify-laravel - TypeScript Generator\n *\n * Main TypeScript code generator combining interfaces, enums, and types.\n */\n\nimport type { SchemaCollection } from '@famgia/omnify-types';\nimport type { TypeScriptFile, TypeScriptOptions, TSInterface, TSEnum, TSTypeAlias } from './types.js';\nimport { generateInterfaces, formatInterface } from './interface-generator.js';\nimport { generateEnums, formatEnum, formatTypeAlias, extractInlineEnums } from './enum-generator.js';\n\n/**\n * Default options for TypeScript generation.\n */\nconst DEFAULT_OPTIONS: TypeScriptOptions = {\n singleFile: true,\n fileName: 'types.ts',\n readonly: true,\n strictNullChecks: true,\n};\n\n/**\n * Generates the file header comment.\n */\nfunction generateHeader(): string {\n return `/**\n * Auto-generated TypeScript types from Omnify schemas.\n * DO NOT EDIT - This file is automatically generated.\n */\n\n`;\n}\n\n/**\n * Generates all TypeScript code as a single file.\n */\nexport function generateTypeScriptFile(\n schemas: SchemaCollection,\n options: TypeScriptOptions = {}\n): TypeScriptFile {\n const opts = { ...DEFAULT_OPTIONS, ...options };\n const parts: string[] = [generateHeader()];\n const types: string[] = [];\n\n // Generate enums first (they're referenced by interfaces)\n const enums = generateEnums(schemas);\n if (enums.length > 0) {\n parts.push('// Enums\\n');\n for (const enumDef of enums) {\n parts.push(formatEnum(enumDef));\n parts.push('\\n\\n');\n types.push(enumDef.name);\n }\n }\n\n // Generate inline enum type aliases\n const inlineEnums = extractInlineEnums(schemas);\n if (inlineEnums.length > 0) {\n parts.push('// Type Aliases\\n');\n for (const alias of inlineEnums) {\n parts.push(formatTypeAlias(alias));\n parts.push('\\n\\n');\n types.push(alias.name);\n }\n }\n\n // Generate interfaces\n const interfaces = generateInterfaces(schemas, opts);\n if (interfaces.length > 0) {\n parts.push('// Interfaces\\n');\n for (const iface of interfaces) {\n parts.push(formatInterface(iface));\n parts.push('\\n\\n');\n types.push(iface.name);\n }\n }\n\n return {\n fileName: opts.fileName ?? 'types.ts',\n content: parts.join('').trim() + '\\n',\n types,\n };\n}\n\n/**\n * Generates TypeScript code as multiple files.\n */\nexport function generateTypeScriptFiles(\n schemas: SchemaCollection,\n options: TypeScriptOptions = {}\n): TypeScriptFile[] {\n const opts = { ...DEFAULT_OPTIONS, ...options };\n const files: TypeScriptFile[] = [];\n\n // Enums file\n const enums = generateEnums(schemas);\n if (enums.length > 0) {\n const content = generateHeader() +\n enums.map(formatEnum).join('\\n\\n') + '\\n';\n files.push({\n fileName: 'enums.ts',\n content,\n types: enums.map(e => e.name),\n });\n }\n\n // Inline enums/type aliases file\n const inlineEnums = extractInlineEnums(schemas);\n if (inlineEnums.length > 0) {\n const content = generateHeader() +\n inlineEnums.map(formatTypeAlias).join('\\n\\n') + '\\n';\n files.push({\n fileName: 'type-aliases.ts',\n content,\n types: inlineEnums.map(a => a.name),\n });\n }\n\n // Individual interface files\n const interfaces = generateInterfaces(schemas, opts);\n for (const iface of interfaces) {\n const imports = collectImports(iface, enums, inlineEnums, interfaces);\n const importStatement = formatImports(imports);\n\n const content = generateHeader() +\n (importStatement ? importStatement + '\\n\\n' : '') +\n formatInterface(iface) + '\\n';\n\n files.push({\n fileName: `${toKebabCase(iface.name)}.ts`,\n content,\n types: [iface.name],\n });\n }\n\n // Index file\n const indexContent = generateIndexFile(files);\n files.push({\n fileName: 'index.ts',\n content: indexContent,\n types: [],\n });\n\n return files;\n}\n\n/**\n * Converts PascalCase to kebab-case.\n */\nfunction toKebabCase(name: string): string {\n return name\n .replace(/([A-Z])/g, '-$1')\n .toLowerCase()\n .replace(/^-/, '');\n}\n\n/**\n * Collects imports needed for an interface.\n */\nfunction collectImports(\n iface: TSInterface,\n enums: TSEnum[],\n typeAliases: TSTypeAlias[],\n allInterfaces: TSInterface[]\n): Map<string, string[]> {\n const imports = new Map<string, string[]>();\n const enumNames = new Set(enums.map(e => e.name));\n const aliasNames = new Set(typeAliases.map(a => a.name));\n const interfaceNames = new Set(allInterfaces.map(i => i.name));\n\n for (const prop of iface.properties) {\n // Check if type references an enum\n if (enumNames.has(prop.type)) {\n const existing = imports.get('./enums.js') ?? [];\n if (!existing.includes(prop.type)) {\n imports.set('./enums.js', [...existing, prop.type]);\n }\n }\n\n // Check if type references a type alias\n if (aliasNames.has(prop.type)) {\n const existing = imports.get('./type-aliases.js') ?? [];\n if (!existing.includes(prop.type)) {\n imports.set('./type-aliases.js', [...existing, prop.type]);\n }\n }\n\n // Check if type references another interface (for relationships)\n const baseType = prop.type.replace('[]', '');\n if (interfaceNames.has(baseType) && baseType !== iface.name) {\n const fileName = `./${toKebabCase(baseType)}.js`;\n const existing = imports.get(fileName) ?? [];\n if (!existing.includes(baseType)) {\n imports.set(fileName, [...existing, baseType]);\n }\n }\n }\n\n return imports;\n}\n\n/**\n * Formats import statements.\n */\nfunction formatImports(imports: Map<string, string[]>): string {\n if (imports.size === 0) return '';\n\n const lines: string[] = [];\n for (const [path, names] of imports) {\n lines.push(`import type { ${names.join(', ')} } from '${path}';`);\n }\n return lines.join('\\n');\n}\n\n/**\n * Generates index.ts file for re-exports.\n */\nfunction generateIndexFile(files: TypeScriptFile[]): string {\n const exports: string[] = [generateHeader().trim(), ''];\n\n for (const file of files) {\n if (file.fileName === 'index.ts') continue;\n const moduleName = file.fileName.replace('.ts', '.js');\n exports.push(`export * from './${moduleName}';`);\n }\n\n return exports.join('\\n') + '\\n';\n}\n\n/**\n * Generates TypeScript types with configurable output.\n */\nexport function generateTypeScript(\n schemas: SchemaCollection,\n options: TypeScriptOptions = {}\n): TypeScriptFile[] {\n const opts = { ...DEFAULT_OPTIONS, ...options };\n\n if (opts.singleFile) {\n return [generateTypeScriptFile(schemas, opts)];\n }\n\n return generateTypeScriptFiles(schemas, opts);\n}\n\n/**\n * Gets output path for a TypeScript file.\n */\nexport function getTypeScriptPath(\n file: TypeScriptFile,\n outputDir: string = 'src/types'\n): string {\n return `${outputDir}/${file.fileName}`;\n}\n","/**\n * @famgia/omnify-laravel - Plugin\n *\n * Plugin wrapper for Laravel migration and TypeScript type generators.\n *\n * @example\n * ```typescript\n * import { defineConfig } from '@famgia/omnify';\n * import laravel from '@famgia/omnify-laravel/plugin';\n *\n * export default defineConfig({\n * plugins: [\n * laravel({\n * migrationsPath: 'database/migrations',\n * typesPath: 'resources/js/types',\n * singleFile: true,\n * }),\n * ],\n * });\n * ```\n */\n\nimport type { OmnifyPlugin, GeneratorOutput, GeneratorContext } from '@famgia/omnify-types';\nimport { generateMigrations, getMigrationPath, type MigrationOptions } from './migration/index.js';\nimport { generateTypeScript, type TypeScriptOptions } from './typescript/index.js';\n\n/**\n * Options for the Laravel plugin.\n */\nexport interface LaravelPluginOptions {\n /**\n * Path for Laravel migration files.\n * @default 'database/migrations'\n */\n migrationsPath?: string;\n\n /**\n * Path for TypeScript type files.\n * @default 'types'\n */\n typesPath?: string;\n\n /**\n * Generate all types in a single file.\n * @default true\n */\n singleFile?: boolean;\n\n /**\n * Database connection name for migrations.\n */\n connection?: string;\n\n /**\n * Custom timestamp for migration file names (mainly for testing).\n */\n timestamp?: string;\n\n /**\n * Generate TypeScript types.\n * @default true\n */\n generateTypes?: boolean;\n\n /**\n * Generate Laravel migrations.\n * @default true\n */\n generateMigrations?: boolean;\n}\n\n/**\n * Resolved options with defaults applied.\n */\ninterface ResolvedOptions {\n migrationsPath: string;\n typesPath: string;\n singleFile: boolean;\n connection: string | undefined;\n timestamp: string | undefined;\n generateTypes: boolean;\n generateMigrations: boolean;\n}\n\n/**\n * Resolves options with defaults.\n */\nfunction resolveOptions(options?: LaravelPluginOptions): ResolvedOptions {\n return {\n migrationsPath: options?.migrationsPath ?? 'database/migrations',\n typesPath: options?.typesPath ?? 'types',\n singleFile: options?.singleFile ?? true,\n connection: options?.connection,\n timestamp: options?.timestamp,\n generateTypes: options?.generateTypes ?? true,\n generateMigrations: options?.generateMigrations ?? true,\n };\n}\n\n/**\n * Creates the Laravel plugin with the specified options.\n *\n * @param options - Plugin configuration options\n * @returns OmnifyPlugin configured for Laravel\n */\nexport default function laravelPlugin(options?: LaravelPluginOptions): OmnifyPlugin {\n const resolved = resolveOptions(options);\n\n return {\n name: '@famgia/omnify-laravel',\n version: '0.0.6',\n\n generators: [\n // Laravel Migrations Generator\n ...(resolved.generateMigrations\n ? [\n {\n name: 'laravel-migrations',\n description: 'Generate Laravel migration files',\n\n generate: async (ctx: GeneratorContext): Promise<GeneratorOutput[]> => {\n const migrationOptions: MigrationOptions = {\n connection: resolved.connection,\n timestamp: resolved.timestamp,\n };\n\n const migrations = generateMigrations(ctx.schemas, migrationOptions);\n\n return migrations.map((migration) => ({\n path: getMigrationPath(migration, resolved.migrationsPath),\n content: migration.content,\n type: 'migration' as const,\n metadata: {\n tableName: migration.tables[0],\n migrationType: migration.type,\n },\n }));\n },\n },\n ]\n : []),\n\n // TypeScript Types Generator\n ...(resolved.generateTypes\n ? [\n {\n name: 'typescript-types',\n description: 'Generate TypeScript type definitions',\n\n generate: async (ctx: GeneratorContext): Promise<GeneratorOutput[]> => {\n const tsOptions: TypeScriptOptions = {\n singleFile: resolved.singleFile,\n };\n\n const files = generateTypeScript(ctx.schemas, tsOptions);\n\n return files.map((file) => ({\n path: `${resolved.typesPath}/${file.fileName}`,\n content: file.content,\n type: 'type' as const,\n metadata: {\n types: file.types,\n },\n }));\n },\n },\n ]\n : []),\n ],\n };\n}\n\n// Named export for flexibility\nexport { laravelPlugin };\n"],"mappings":"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","names":[]}
|
package/dist/index.cjs
CHANGED
|
@@ -196,6 +196,9 @@ function generateForeignKey(propertyName, property, allSchemas) {
|
|
|
196
196
|
if (assocProp.relation !== "ManyToOne" && assocProp.relation !== "OneToOne") {
|
|
197
197
|
return null;
|
|
198
198
|
}
|
|
199
|
+
if (assocProp.mappedBy) {
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
199
202
|
const columnName = toColumnName(propertyName) + "_id";
|
|
200
203
|
const targetSchema = assocProp.target ? allSchemas[assocProp.target] : void 0;
|
|
201
204
|
const targetTable = assocProp.target ? toTableName(assocProp.target) : "unknown";
|
|
@@ -325,6 +328,122 @@ function formatIndex(index) {
|
|
|
325
328
|
const name = index.name ? `, '${index.name}'` : "";
|
|
326
329
|
return `$table->${method}(${columns}${name});`;
|
|
327
330
|
}
|
|
331
|
+
function generatePivotTableName(sourceTable, targetTable, customName) {
|
|
332
|
+
if (customName) {
|
|
333
|
+
return customName;
|
|
334
|
+
}
|
|
335
|
+
const tables = [sourceTable, targetTable].sort();
|
|
336
|
+
const singular1 = tables[0].replace(/ies$/, "y").replace(/s$/, "");
|
|
337
|
+
const singular2 = tables[1].replace(/ies$/, "y").replace(/s$/, "");
|
|
338
|
+
return `${singular1}_${singular2}`;
|
|
339
|
+
}
|
|
340
|
+
function extractManyToManyRelations(schema, allSchemas) {
|
|
341
|
+
const pivotTables = [];
|
|
342
|
+
if (!schema.properties) {
|
|
343
|
+
return pivotTables;
|
|
344
|
+
}
|
|
345
|
+
const sourceTable = toTableName(schema.name);
|
|
346
|
+
const sourcePkType = schema.options?.primaryKeyType ?? "BigInt";
|
|
347
|
+
for (const [, property] of Object.entries(schema.properties)) {
|
|
348
|
+
if (property.type !== "Association") {
|
|
349
|
+
continue;
|
|
350
|
+
}
|
|
351
|
+
const assocProp = property;
|
|
352
|
+
if (assocProp.relation !== "ManyToMany") {
|
|
353
|
+
continue;
|
|
354
|
+
}
|
|
355
|
+
const targetName = assocProp.target;
|
|
356
|
+
if (!targetName) {
|
|
357
|
+
continue;
|
|
358
|
+
}
|
|
359
|
+
const targetSchema = allSchemas[targetName];
|
|
360
|
+
const targetTable = toTableName(targetName);
|
|
361
|
+
const targetPkType = targetSchema?.options?.primaryKeyType ?? "BigInt";
|
|
362
|
+
const isOwningSide = assocProp.owning ?? schema.name < targetName;
|
|
363
|
+
if (!isOwningSide) {
|
|
364
|
+
continue;
|
|
365
|
+
}
|
|
366
|
+
const pivotTableName = generatePivotTableName(sourceTable, targetTable, assocProp.joinTable);
|
|
367
|
+
const sourceColumn = sourceTable.replace(/ies$/, "y").replace(/s$/, "") + "_id";
|
|
368
|
+
const targetColumn = targetTable.replace(/ies$/, "y").replace(/s$/, "") + "_id";
|
|
369
|
+
pivotTables.push({
|
|
370
|
+
tableName: pivotTableName,
|
|
371
|
+
sourceTable,
|
|
372
|
+
targetTable,
|
|
373
|
+
sourceColumn,
|
|
374
|
+
targetColumn,
|
|
375
|
+
sourcePkType,
|
|
376
|
+
targetPkType,
|
|
377
|
+
onDelete: assocProp.onDelete,
|
|
378
|
+
onUpdate: assocProp.onUpdate
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
return pivotTables;
|
|
382
|
+
}
|
|
383
|
+
function generatePivotTableBlueprint(pivot) {
|
|
384
|
+
const columns = [];
|
|
385
|
+
const foreignKeys = [];
|
|
386
|
+
const indexes = [];
|
|
387
|
+
const getMethodForPkType = (pkType) => {
|
|
388
|
+
switch (pkType) {
|
|
389
|
+
case "Int":
|
|
390
|
+
return "unsignedInteger";
|
|
391
|
+
case "Uuid":
|
|
392
|
+
return "uuid";
|
|
393
|
+
case "String":
|
|
394
|
+
return "string";
|
|
395
|
+
default:
|
|
396
|
+
return "unsignedBigInteger";
|
|
397
|
+
}
|
|
398
|
+
};
|
|
399
|
+
columns.push({
|
|
400
|
+
name: pivot.sourceColumn,
|
|
401
|
+
method: getMethodForPkType(pivot.sourcePkType),
|
|
402
|
+
args: [pivot.sourceColumn],
|
|
403
|
+
modifiers: []
|
|
404
|
+
});
|
|
405
|
+
columns.push({
|
|
406
|
+
name: pivot.targetColumn,
|
|
407
|
+
method: getMethodForPkType(pivot.targetPkType),
|
|
408
|
+
args: [pivot.targetColumn],
|
|
409
|
+
modifiers: []
|
|
410
|
+
});
|
|
411
|
+
foreignKeys.push({
|
|
412
|
+
columns: [pivot.sourceColumn],
|
|
413
|
+
references: "id",
|
|
414
|
+
on: [pivot.sourceTable],
|
|
415
|
+
onDelete: pivot.onDelete ?? "cascade",
|
|
416
|
+
onUpdate: pivot.onUpdate ?? "cascade"
|
|
417
|
+
});
|
|
418
|
+
foreignKeys.push({
|
|
419
|
+
columns: [pivot.targetColumn],
|
|
420
|
+
references: "id",
|
|
421
|
+
on: [pivot.targetTable],
|
|
422
|
+
onDelete: pivot.onDelete ?? "cascade",
|
|
423
|
+
onUpdate: pivot.onUpdate ?? "cascade"
|
|
424
|
+
});
|
|
425
|
+
indexes.push({
|
|
426
|
+
columns: [pivot.sourceColumn, pivot.targetColumn],
|
|
427
|
+
unique: true
|
|
428
|
+
});
|
|
429
|
+
indexes.push({
|
|
430
|
+
name: `idx_${pivot.sourceColumn}`,
|
|
431
|
+
columns: [pivot.sourceColumn],
|
|
432
|
+
unique: false
|
|
433
|
+
});
|
|
434
|
+
indexes.push({
|
|
435
|
+
name: `idx_${pivot.targetColumn}`,
|
|
436
|
+
columns: [pivot.targetColumn],
|
|
437
|
+
unique: false
|
|
438
|
+
});
|
|
439
|
+
return {
|
|
440
|
+
tableName: pivot.tableName,
|
|
441
|
+
columns,
|
|
442
|
+
primaryKey: [pivot.sourceColumn, pivot.targetColumn],
|
|
443
|
+
foreignKeys,
|
|
444
|
+
indexes
|
|
445
|
+
};
|
|
446
|
+
}
|
|
328
447
|
|
|
329
448
|
// src/migration/generator.ts
|
|
330
449
|
function generateTimestamp() {
|
|
@@ -466,6 +585,7 @@ return new class extends Migration
|
|
|
466
585
|
}
|
|
467
586
|
function generateMigrations(schemas, options = {}) {
|
|
468
587
|
const migrations = [];
|
|
588
|
+
const pivotTablesGenerated = /* @__PURE__ */ new Set();
|
|
469
589
|
let timestampOffset = 0;
|
|
470
590
|
for (const schema of Object.values(schemas)) {
|
|
471
591
|
if (schema.kind === "enum") {
|
|
@@ -481,6 +601,27 @@ function generateMigrations(schemas, options = {}) {
|
|
|
481
601
|
});
|
|
482
602
|
migrations.push(migration);
|
|
483
603
|
}
|
|
604
|
+
for (const schema of Object.values(schemas)) {
|
|
605
|
+
if (schema.kind === "enum") {
|
|
606
|
+
continue;
|
|
607
|
+
}
|
|
608
|
+
const pivotTables = extractManyToManyRelations(schema, schemas);
|
|
609
|
+
for (const pivot of pivotTables) {
|
|
610
|
+
if (pivotTablesGenerated.has(pivot.tableName)) {
|
|
611
|
+
continue;
|
|
612
|
+
}
|
|
613
|
+
pivotTablesGenerated.add(pivot.tableName);
|
|
614
|
+
const timestamp = options.timestamp ?? generateTimestamp();
|
|
615
|
+
const offsetTimestamp = incrementTimestamp(timestamp, timestampOffset);
|
|
616
|
+
timestampOffset++;
|
|
617
|
+
const blueprint = generatePivotTableBlueprint(pivot);
|
|
618
|
+
const migration = generateCreateMigration(blueprint, {
|
|
619
|
+
...options,
|
|
620
|
+
timestamp: offsetTimestamp
|
|
621
|
+
});
|
|
622
|
+
migrations.push(migration);
|
|
623
|
+
}
|
|
624
|
+
}
|
|
484
625
|
return migrations;
|
|
485
626
|
}
|
|
486
627
|
function incrementTimestamp(timestamp, seconds) {
|
|
@@ -935,7 +1076,7 @@ function laravelPlugin(options) {
|
|
|
935
1076
|
const resolved = resolveOptions(options);
|
|
936
1077
|
return {
|
|
937
1078
|
name: "@famgia/omnify-laravel",
|
|
938
|
-
version: "0.0.
|
|
1079
|
+
version: "0.0.6",
|
|
939
1080
|
generators: [
|
|
940
1081
|
// Laravel Migrations Generator
|
|
941
1082
|
...resolved.generateMigrations ? [
|