arkormx 0.2.2 → 0.2.4
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/cli.mjs +254 -9
- package/dist/index.cjs +261 -9
- package/dist/index.d.cts +137 -2
- package/dist/index.d.mts +137 -2
- package/dist/index.mjs +255 -10
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -27,11 +27,22 @@ interface SchemaIndex {
|
|
|
27
27
|
columns: string[];
|
|
28
28
|
name?: string;
|
|
29
29
|
}
|
|
30
|
+
type SchemaForeignKeyAction = 'cascade' | 'restrict' | 'setNull' | 'noAction' | 'setDefault';
|
|
31
|
+
interface SchemaForeignKey {
|
|
32
|
+
column: string;
|
|
33
|
+
referencesTable: string;
|
|
34
|
+
referencesColumn: string;
|
|
35
|
+
onDelete?: SchemaForeignKeyAction;
|
|
36
|
+
relationAlias?: string;
|
|
37
|
+
inverseRelationAlias?: string;
|
|
38
|
+
fieldAlias?: string;
|
|
39
|
+
}
|
|
30
40
|
interface SchemaTableCreateOperation {
|
|
31
41
|
type: 'createTable';
|
|
32
42
|
table: string;
|
|
33
43
|
columns: SchemaColumn[];
|
|
34
44
|
indexes: SchemaIndex[];
|
|
45
|
+
foreignKeys: SchemaForeignKey[];
|
|
35
46
|
}
|
|
36
47
|
interface SchemaTableAlterOperation {
|
|
37
48
|
type: 'alterTable';
|
|
@@ -39,6 +50,7 @@ interface SchemaTableAlterOperation {
|
|
|
39
50
|
addColumns: SchemaColumn[];
|
|
40
51
|
dropColumns: string[];
|
|
41
52
|
addIndexes: SchemaIndex[];
|
|
53
|
+
addForeignKeys: SchemaForeignKey[];
|
|
42
54
|
}
|
|
43
55
|
interface SchemaTableDropOperation {
|
|
44
56
|
type: 'dropTable';
|
|
@@ -2286,6 +2298,60 @@ declare class SeedCommand extends Command<CliApp> {
|
|
|
2286
2298
|
private loadSeederClassesFromFile;
|
|
2287
2299
|
}
|
|
2288
2300
|
//#endregion
|
|
2301
|
+
//#region src/database/ForeignKeyBuilder.d.ts
|
|
2302
|
+
/**
|
|
2303
|
+
* The ForeignKeyBuilder class provides a fluent interface for defining
|
|
2304
|
+
* foreign key constraints in a migration. It allows you to specify
|
|
2305
|
+
* the referenced table and column, as well as actions to take on
|
|
2306
|
+
* delete and aliases for the relation.
|
|
2307
|
+
*
|
|
2308
|
+
* @author Legacy (3m1n3nc3)
|
|
2309
|
+
* @since 0.2.2
|
|
2310
|
+
*/
|
|
2311
|
+
declare class ForeignKeyBuilder {
|
|
2312
|
+
private readonly foreignKey;
|
|
2313
|
+
constructor(foreignKey: SchemaForeignKey);
|
|
2314
|
+
/**
|
|
2315
|
+
* Defines the referenced table and column for this foreign key constraint.
|
|
2316
|
+
*
|
|
2317
|
+
* @param table
|
|
2318
|
+
* @param column
|
|
2319
|
+
* @returns
|
|
2320
|
+
*/
|
|
2321
|
+
references(table: string, column: string): this;
|
|
2322
|
+
/**
|
|
2323
|
+
* Defines the action to take when a referenced record is deleted, such
|
|
2324
|
+
* as "CASCADE", "SET NULL", or "RESTRICT".
|
|
2325
|
+
*
|
|
2326
|
+
* @param action
|
|
2327
|
+
* @returns
|
|
2328
|
+
*/
|
|
2329
|
+
onDelete(action: SchemaForeignKeyAction): this;
|
|
2330
|
+
/**
|
|
2331
|
+
* Defines an alias for the relation represented by this foreign key, which
|
|
2332
|
+
* can be used in the ORM for more intuitive access to related models.
|
|
2333
|
+
*
|
|
2334
|
+
* @param name
|
|
2335
|
+
* @returns
|
|
2336
|
+
*/
|
|
2337
|
+
alias(name: string): this;
|
|
2338
|
+
/**
|
|
2339
|
+
* Defines an alias for the inverse relation represented by this foreign key.
|
|
2340
|
+
*
|
|
2341
|
+
* @param name
|
|
2342
|
+
* @returns
|
|
2343
|
+
*/
|
|
2344
|
+
inverseAlias(name: string): this;
|
|
2345
|
+
/**
|
|
2346
|
+
* Defines an alias for the foreign key field itself, which can be
|
|
2347
|
+
* used in the ORM for more intuitive access to the foreign key value.
|
|
2348
|
+
*
|
|
2349
|
+
* @param fieldName
|
|
2350
|
+
* @returns
|
|
2351
|
+
*/
|
|
2352
|
+
as(fieldName: string): this;
|
|
2353
|
+
}
|
|
2354
|
+
//#endregion
|
|
2289
2355
|
//#region src/database/TableBuilder.d.ts
|
|
2290
2356
|
/**
|
|
2291
2357
|
* The TableBuilder class provides a fluent interface for defining
|
|
@@ -2298,6 +2364,7 @@ declare class TableBuilder {
|
|
|
2298
2364
|
private readonly columns;
|
|
2299
2365
|
private readonly dropColumnNames;
|
|
2300
2366
|
private readonly indexes;
|
|
2367
|
+
private readonly foreignKeys;
|
|
2301
2368
|
private latestColumnName;
|
|
2302
2369
|
/**
|
|
2303
2370
|
* Defines a primary key column in the table.
|
|
@@ -2475,6 +2542,21 @@ declare class TableBuilder {
|
|
|
2475
2542
|
* @returns The current TableBuilder instance for chaining.
|
|
2476
2543
|
*/
|
|
2477
2544
|
index(columns?: string | string[], name?: string): this;
|
|
2545
|
+
/**
|
|
2546
|
+
* Defines a foreign key relation for an existing column.
|
|
2547
|
+
*
|
|
2548
|
+
* @param column The local foreign key column name.
|
|
2549
|
+
* @returns A fluent foreign key builder.
|
|
2550
|
+
*/
|
|
2551
|
+
foreignKey(column: string): ForeignKeyBuilder;
|
|
2552
|
+
/**
|
|
2553
|
+
* Defines a foreign key relation for a column, using a
|
|
2554
|
+
* conventional naming pattern.
|
|
2555
|
+
*
|
|
2556
|
+
* @param column
|
|
2557
|
+
* @returns
|
|
2558
|
+
*/
|
|
2559
|
+
foreign(column?: string): ForeignKeyBuilder;
|
|
2478
2560
|
/**
|
|
2479
2561
|
* Returns a deep copy of the defined columns for the table.
|
|
2480
2562
|
*
|
|
@@ -2493,6 +2575,12 @@ declare class TableBuilder {
|
|
|
2493
2575
|
* @returns
|
|
2494
2576
|
*/
|
|
2495
2577
|
getIndexes(): SchemaIndex[];
|
|
2578
|
+
/**
|
|
2579
|
+
* Returns a deep copy of the defined foreign keys for the table.
|
|
2580
|
+
*
|
|
2581
|
+
* @returns
|
|
2582
|
+
*/
|
|
2583
|
+
getForeignKeys(): SchemaForeignKey[];
|
|
2496
2584
|
/**
|
|
2497
2585
|
* Defines a column in the table with the given name.
|
|
2498
2586
|
*
|
|
@@ -2683,10 +2771,57 @@ declare const buildFieldLine: (column: SchemaColumn) => string;
|
|
|
2683
2771
|
/**
|
|
2684
2772
|
* Build a Prisma model-level @@index definition line.
|
|
2685
2773
|
*
|
|
2686
|
-
* @param index
|
|
2774
|
+
* @param index The schema index definition to convert to a Prisma \@\@index line.
|
|
2687
2775
|
* @returns
|
|
2688
2776
|
*/
|
|
2689
2777
|
declare const buildIndexLine: (index: SchemaIndex) => string;
|
|
2778
|
+
/**
|
|
2779
|
+
* Derive a relation field name from a foreign key column name by applying
|
|
2780
|
+
* common conventions, such as removing "Id" suffixes and converting to camelCase.
|
|
2781
|
+
*
|
|
2782
|
+
* @param columnName The name of the foreign key column.
|
|
2783
|
+
* @returns The derived relation field name.
|
|
2784
|
+
*/
|
|
2785
|
+
declare const deriveRelationFieldName: (columnName: string) => string;
|
|
2786
|
+
/**
|
|
2787
|
+
* Derive a relation name for the inverse side of a relation based on the
|
|
2788
|
+
* source and target model names, using an explicit alias if provided or a
|
|
2789
|
+
* convention of combining the target model name with the last segment of
|
|
2790
|
+
* the source model name.
|
|
2791
|
+
*
|
|
2792
|
+
* @param sourceModelName The name of the source model in the relation.
|
|
2793
|
+
* @param targetModelName The name of the target model in the relation.
|
|
2794
|
+
* @param explicitAlias An optional explicit alias for the inverse relation.
|
|
2795
|
+
* @returns The derived or explicit inverse relation alias.
|
|
2796
|
+
*/
|
|
2797
|
+
declare const deriveInverseRelationAlias: (sourceModelName: string, targetModelName: string, explicitAlias?: string) => string;
|
|
2798
|
+
declare const deriveCollectionFieldName: (modelName: string) => string;
|
|
2799
|
+
/**
|
|
2800
|
+
* Format a SchemaForeignKeyAction value as a Prisma onDelete action string.
|
|
2801
|
+
*
|
|
2802
|
+
* @param action The foreign key action to format.
|
|
2803
|
+
* @returns The corresponding Prisma onDelete action string.
|
|
2804
|
+
*/
|
|
2805
|
+
declare const formatRelationAction: (action: SchemaForeignKeyAction) => string;
|
|
2806
|
+
/**
|
|
2807
|
+
* Build a Prisma relation field line based on a SchemaForeignKey
|
|
2808
|
+
* definition, including relation name and onDelete action.
|
|
2809
|
+
*
|
|
2810
|
+
* @param foreignKey The foreign key definition to convert to a relation line.
|
|
2811
|
+
* @returns The corresponding Prisma schema line for the relation field.
|
|
2812
|
+
*/
|
|
2813
|
+
declare const buildRelationLine: (foreignKey: SchemaForeignKey) => string;
|
|
2814
|
+
/**
|
|
2815
|
+
* Build a Prisma relation field line for the inverse side of a relation, based
|
|
2816
|
+
* on the source and target model names and the foreign key definition, using
|
|
2817
|
+
* naming conventions and any explicit inverse alias provided.
|
|
2818
|
+
*
|
|
2819
|
+
* @param sourceModelName The name of the source model in the relation.
|
|
2820
|
+
* @param targetModelName The name of the target model in the relation.
|
|
2821
|
+
* @param foreignKey The foreign key definition for the relation.
|
|
2822
|
+
* @returns The Prisma schema line for the inverse relation field.
|
|
2823
|
+
*/
|
|
2824
|
+
declare const buildInverseRelationLine: (sourceModelName: string, targetModelName: string, foreignKey: SchemaForeignKey) => string;
|
|
2690
2825
|
/**
|
|
2691
2826
|
* Build a Prisma model block string based on a SchemaTableCreateOperation, including
|
|
2692
2827
|
* all fields and any necessary mapping.
|
|
@@ -2945,4 +3080,4 @@ declare class URLDriver {
|
|
|
2945
3080
|
url(page: number): string;
|
|
2946
3081
|
}
|
|
2947
3082
|
//#endregion
|
|
2948
|
-
export { ArkormCollection, ArkormException, CliApp, InitCommand, InlineFactory, LengthAwarePaginator, MIGRATION_BRAND, MakeFactoryCommand, MakeMigrationCommand, MakeModelCommand, MakeSeederCommand, MigrateCommand, Migration, Model, ModelFactory, ModelNotFoundException, ModelsSyncCommand, PRISMA_MODEL_REGEX, Paginator, PrismaDelegateMap, QueryBuilder, SEEDER_BRAND, SchemaBuilder, SeedCommand, Seeder, SeederCallArgument, SeederConstructor, SeederInput, TableBuilder, URLDriver, applyAlterTableOperation, applyCreateTableOperation, applyDropTableOperation, applyMigrationToPrismaSchema, applyOperationsToPrismaSchema, buildFieldLine, buildIndexLine, buildMigrationSource, buildModelBlock, configureArkormRuntime, createMigrationTimestamp, createPrismaAdapter, createPrismaDelegateMap, defineConfig, defineFactory, ensureArkormConfigLoading, escapeRegex, findModelBlock, formatDefaultValue, generateMigrationFile, getDefaultStubsPath, getMigrationPlan, getRuntimePaginationURLDriverFactory, getRuntimePrismaClient, getUserConfig, inferDelegateName, isDelegateLike, loadArkormConfig, pad, resetArkormRuntimeForTests, resolveCast, resolveMigrationClassName, resolvePrismaType, runMigrationWithPrisma, runPrismaCommand, toMigrationFileSlug, toModelName };
|
|
3083
|
+
export { ArkormCollection, ArkormException, CliApp, ForeignKeyBuilder, InitCommand, InlineFactory, LengthAwarePaginator, MIGRATION_BRAND, MakeFactoryCommand, MakeMigrationCommand, MakeModelCommand, MakeSeederCommand, MigrateCommand, Migration, Model, ModelFactory, ModelNotFoundException, ModelsSyncCommand, PRISMA_MODEL_REGEX, Paginator, PrismaDelegateMap, QueryBuilder, SEEDER_BRAND, SchemaBuilder, SeedCommand, Seeder, SeederCallArgument, SeederConstructor, SeederInput, TableBuilder, URLDriver, applyAlterTableOperation, applyCreateTableOperation, applyDropTableOperation, applyMigrationToPrismaSchema, applyOperationsToPrismaSchema, buildFieldLine, buildIndexLine, buildInverseRelationLine, buildMigrationSource, buildModelBlock, buildRelationLine, configureArkormRuntime, createMigrationTimestamp, createPrismaAdapter, createPrismaDelegateMap, defineConfig, defineFactory, deriveCollectionFieldName, deriveInverseRelationAlias, deriveRelationFieldName, ensureArkormConfigLoading, escapeRegex, findModelBlock, formatDefaultValue, formatRelationAction, generateMigrationFile, getDefaultStubsPath, getMigrationPlan, getRuntimePaginationURLDriverFactory, getRuntimePrismaClient, getUserConfig, inferDelegateName, isDelegateLike, loadArkormConfig, pad, resetArkormRuntimeForTests, resolveCast, resolveMigrationClassName, resolvePrismaType, runMigrationWithPrisma, runPrismaCommand, toMigrationFileSlug, toModelName };
|
package/dist/index.mjs
CHANGED
|
@@ -88,6 +88,79 @@ var ArkormException = class extends Error {
|
|
|
88
88
|
}
|
|
89
89
|
};
|
|
90
90
|
|
|
91
|
+
//#endregion
|
|
92
|
+
//#region src/database/ForeignKeyBuilder.ts
|
|
93
|
+
/**
|
|
94
|
+
* The ForeignKeyBuilder class provides a fluent interface for defining
|
|
95
|
+
* foreign key constraints in a migration. It allows you to specify
|
|
96
|
+
* the referenced table and column, as well as actions to take on
|
|
97
|
+
* delete and aliases for the relation.
|
|
98
|
+
*
|
|
99
|
+
* @author Legacy (3m1n3nc3)
|
|
100
|
+
* @since 0.2.2
|
|
101
|
+
*/
|
|
102
|
+
var ForeignKeyBuilder = class {
|
|
103
|
+
foreignKey;
|
|
104
|
+
constructor(foreignKey) {
|
|
105
|
+
this.foreignKey = foreignKey;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Defines the referenced table and column for this foreign key constraint.
|
|
109
|
+
*
|
|
110
|
+
* @param table
|
|
111
|
+
* @param column
|
|
112
|
+
* @returns
|
|
113
|
+
*/
|
|
114
|
+
references(table, column) {
|
|
115
|
+
this.foreignKey.referencesTable = table;
|
|
116
|
+
this.foreignKey.referencesColumn = column;
|
|
117
|
+
return this;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Defines the action to take when a referenced record is deleted, such
|
|
121
|
+
* as "CASCADE", "SET NULL", or "RESTRICT".
|
|
122
|
+
*
|
|
123
|
+
* @param action
|
|
124
|
+
* @returns
|
|
125
|
+
*/
|
|
126
|
+
onDelete(action) {
|
|
127
|
+
this.foreignKey.onDelete = action;
|
|
128
|
+
return this;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Defines an alias for the relation represented by this foreign key, which
|
|
132
|
+
* can be used in the ORM for more intuitive access to related models.
|
|
133
|
+
*
|
|
134
|
+
* @param name
|
|
135
|
+
* @returns
|
|
136
|
+
*/
|
|
137
|
+
alias(name) {
|
|
138
|
+
this.foreignKey.relationAlias = name;
|
|
139
|
+
return this;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Defines an alias for the inverse relation represented by this foreign key.
|
|
143
|
+
*
|
|
144
|
+
* @param name
|
|
145
|
+
* @returns
|
|
146
|
+
*/
|
|
147
|
+
inverseAlias(name) {
|
|
148
|
+
this.foreignKey.inverseRelationAlias = name;
|
|
149
|
+
return this;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Defines an alias for the foreign key field itself, which can be
|
|
153
|
+
* used in the ORM for more intuitive access to the foreign key value.
|
|
154
|
+
*
|
|
155
|
+
* @param fieldName
|
|
156
|
+
* @returns
|
|
157
|
+
*/
|
|
158
|
+
as(fieldName) {
|
|
159
|
+
this.foreignKey.fieldAlias = fieldName;
|
|
160
|
+
return this;
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
|
|
91
164
|
//#endregion
|
|
92
165
|
//#region src/database/TableBuilder.ts
|
|
93
166
|
/**
|
|
@@ -101,6 +174,7 @@ var TableBuilder = class {
|
|
|
101
174
|
columns = [];
|
|
102
175
|
dropColumnNames = [];
|
|
103
176
|
indexes = [];
|
|
177
|
+
foreignKeys = [];
|
|
104
178
|
latestColumnName;
|
|
105
179
|
/**
|
|
106
180
|
* Defines a primary key column in the table.
|
|
@@ -343,6 +417,32 @@ var TableBuilder = class {
|
|
|
343
417
|
return this;
|
|
344
418
|
}
|
|
345
419
|
/**
|
|
420
|
+
* Defines a foreign key relation for an existing column.
|
|
421
|
+
*
|
|
422
|
+
* @param column The local foreign key column name.
|
|
423
|
+
* @returns A fluent foreign key builder.
|
|
424
|
+
*/
|
|
425
|
+
foreignKey(column) {
|
|
426
|
+
const entry = {
|
|
427
|
+
column,
|
|
428
|
+
referencesTable: "",
|
|
429
|
+
referencesColumn: "id"
|
|
430
|
+
};
|
|
431
|
+
this.foreignKeys.push(entry);
|
|
432
|
+
return new ForeignKeyBuilder(entry);
|
|
433
|
+
}
|
|
434
|
+
/**
|
|
435
|
+
* Defines a foreign key relation for a column, using a
|
|
436
|
+
* conventional naming pattern.
|
|
437
|
+
*
|
|
438
|
+
* @param column
|
|
439
|
+
* @returns
|
|
440
|
+
*/
|
|
441
|
+
foreign(column) {
|
|
442
|
+
const columnName = this.resolveColumn(column).name;
|
|
443
|
+
return this.foreignKey(columnName + (column ? "" : "Id"));
|
|
444
|
+
}
|
|
445
|
+
/**
|
|
346
446
|
* Returns a deep copy of the defined columns for the table.
|
|
347
447
|
*
|
|
348
448
|
* @returns
|
|
@@ -370,6 +470,14 @@ var TableBuilder = class {
|
|
|
370
470
|
}));
|
|
371
471
|
}
|
|
372
472
|
/**
|
|
473
|
+
* Returns a deep copy of the defined foreign keys for the table.
|
|
474
|
+
*
|
|
475
|
+
* @returns
|
|
476
|
+
*/
|
|
477
|
+
getForeignKeys() {
|
|
478
|
+
return this.foreignKeys.map((foreignKey) => ({ ...foreignKey }));
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
373
481
|
* Defines a column in the table with the given name.
|
|
374
482
|
*
|
|
375
483
|
* @param name The name of the column.
|
|
@@ -432,7 +540,8 @@ var SchemaBuilder = class {
|
|
|
432
540
|
type: "createTable",
|
|
433
541
|
table,
|
|
434
542
|
columns: builder.getColumns(),
|
|
435
|
-
indexes: builder.getIndexes()
|
|
543
|
+
indexes: builder.getIndexes(),
|
|
544
|
+
foreignKeys: builder.getForeignKeys()
|
|
436
545
|
});
|
|
437
546
|
return this;
|
|
438
547
|
}
|
|
@@ -451,7 +560,8 @@ var SchemaBuilder = class {
|
|
|
451
560
|
table,
|
|
452
561
|
addColumns: builder.getColumns(),
|
|
453
562
|
dropColumns: builder.getDropColumns(),
|
|
454
|
-
addIndexes: builder.getIndexes()
|
|
563
|
+
addIndexes: builder.getIndexes(),
|
|
564
|
+
addForeignKeys: builder.getForeignKeys()
|
|
455
565
|
});
|
|
456
566
|
return this;
|
|
457
567
|
}
|
|
@@ -481,7 +591,8 @@ var SchemaBuilder = class {
|
|
|
481
591
|
indexes: operation.indexes.map((index) => ({
|
|
482
592
|
...index,
|
|
483
593
|
columns: [...index.columns]
|
|
484
|
-
}))
|
|
594
|
+
})),
|
|
595
|
+
foreignKeys: operation.foreignKeys.map((foreignKey) => ({ ...foreignKey }))
|
|
485
596
|
};
|
|
486
597
|
if (operation.type === "alterTable") return {
|
|
487
598
|
...operation,
|
|
@@ -490,7 +601,8 @@ var SchemaBuilder = class {
|
|
|
490
601
|
addIndexes: operation.addIndexes.map((index) => ({
|
|
491
602
|
...index,
|
|
492
603
|
columns: [...index.columns]
|
|
493
|
-
}))
|
|
604
|
+
})),
|
|
605
|
+
addForeignKeys: operation.addForeignKeys.map((foreignKey) => ({ ...foreignKey }))
|
|
494
606
|
};
|
|
495
607
|
return { ...operation };
|
|
496
608
|
});
|
|
@@ -575,13 +687,139 @@ const buildFieldLine = (column) => {
|
|
|
575
687
|
/**
|
|
576
688
|
* Build a Prisma model-level @@index definition line.
|
|
577
689
|
*
|
|
578
|
-
* @param index
|
|
690
|
+
* @param index The schema index definition to convert to a Prisma \@\@index line.
|
|
579
691
|
* @returns
|
|
580
692
|
*/
|
|
581
693
|
const buildIndexLine = (index) => {
|
|
582
694
|
return ` @@index([${index.columns.join(", ")}]${typeof index.name === "string" && index.name.trim().length > 0 ? `, name: "${index.name.replace(/"/g, "\\\"")}"` : ""})`;
|
|
583
695
|
};
|
|
584
696
|
/**
|
|
697
|
+
* Derive a relation field name from a foreign key column name by applying
|
|
698
|
+
* common conventions, such as removing "Id" suffixes and converting to camelCase.
|
|
699
|
+
*
|
|
700
|
+
* @param columnName The name of the foreign key column.
|
|
701
|
+
* @returns The derived relation field name.
|
|
702
|
+
*/
|
|
703
|
+
const deriveRelationFieldName = (columnName) => {
|
|
704
|
+
const trimmed = columnName.trim();
|
|
705
|
+
if (!trimmed) return "relation";
|
|
706
|
+
if (trimmed.endsWith("Id") && trimmed.length > 2) {
|
|
707
|
+
const root = trimmed.slice(0, -2);
|
|
708
|
+
return `${root.charAt(0).toLowerCase()}${root.slice(1)}`;
|
|
709
|
+
}
|
|
710
|
+
if (trimmed.endsWith("_id") && trimmed.length > 3) return trimmed.slice(0, -3).replace(/_([a-zA-Z0-9])/g, (_, letter) => letter.toUpperCase());
|
|
711
|
+
return `${trimmed.charAt(0).toLowerCase()}${trimmed.slice(1)}`;
|
|
712
|
+
};
|
|
713
|
+
const pascalWords = (value) => {
|
|
714
|
+
return value.match(/[A-Z][a-z0-9]*/g) ?? [value];
|
|
715
|
+
};
|
|
716
|
+
/**
|
|
717
|
+
* Derive a relation name for the inverse side of a relation based on the
|
|
718
|
+
* source and target model names, using an explicit alias if provided or a
|
|
719
|
+
* convention of combining the target model name with the last segment of
|
|
720
|
+
* the source model name.
|
|
721
|
+
*
|
|
722
|
+
* @param sourceModelName The name of the source model in the relation.
|
|
723
|
+
* @param targetModelName The name of the target model in the relation.
|
|
724
|
+
* @param explicitAlias An optional explicit alias for the inverse relation.
|
|
725
|
+
* @returns The derived or explicit inverse relation alias.
|
|
726
|
+
*/
|
|
727
|
+
const deriveInverseRelationAlias = (sourceModelName, targetModelName, explicitAlias) => {
|
|
728
|
+
if (explicitAlias && explicitAlias.trim().length > 0) return explicitAlias.trim();
|
|
729
|
+
const sourceWords = pascalWords(sourceModelName);
|
|
730
|
+
return `${sourceWords[sourceWords.length - 1] ?? sourceModelName}${targetModelName}`;
|
|
731
|
+
};
|
|
732
|
+
const deriveCollectionFieldName = (modelName) => {
|
|
733
|
+
if (!modelName) return "items";
|
|
734
|
+
const camel = `${modelName.charAt(0).toLowerCase()}${modelName.slice(1)}`;
|
|
735
|
+
if (camel.endsWith("s")) return `${camel}es`;
|
|
736
|
+
return `${camel}s`;
|
|
737
|
+
};
|
|
738
|
+
/**
|
|
739
|
+
* Format a SchemaForeignKeyAction value as a Prisma onDelete action string.
|
|
740
|
+
*
|
|
741
|
+
* @param action The foreign key action to format.
|
|
742
|
+
* @returns The corresponding Prisma onDelete action string.
|
|
743
|
+
*/
|
|
744
|
+
const formatRelationAction = (action) => {
|
|
745
|
+
if (action === "cascade") return "Cascade";
|
|
746
|
+
if (action === "restrict") return "Restrict";
|
|
747
|
+
if (action === "setNull") return "SetNull";
|
|
748
|
+
if (action === "setDefault") return "SetDefault";
|
|
749
|
+
return "NoAction";
|
|
750
|
+
};
|
|
751
|
+
/**
|
|
752
|
+
* Build a Prisma relation field line based on a SchemaForeignKey
|
|
753
|
+
* definition, including relation name and onDelete action.
|
|
754
|
+
*
|
|
755
|
+
* @param foreignKey The foreign key definition to convert to a relation line.
|
|
756
|
+
* @returns The corresponding Prisma schema line for the relation field.
|
|
757
|
+
*/
|
|
758
|
+
const buildRelationLine = (foreignKey) => {
|
|
759
|
+
if (!foreignKey.referencesTable.trim()) throw new ArkormException(`Foreign key [${foreignKey.column}] must define a referenced table.`);
|
|
760
|
+
if (!foreignKey.referencesColumn.trim()) throw new ArkormException(`Foreign key [${foreignKey.column}] must define a referenced column.`);
|
|
761
|
+
const fieldName = foreignKey.fieldAlias?.trim() || deriveRelationFieldName(foreignKey.column);
|
|
762
|
+
const targetModel = toModelName(foreignKey.referencesTable);
|
|
763
|
+
const relationName = foreignKey.relationAlias?.trim();
|
|
764
|
+
const relationPrefix = relationName ? `@relation("${relationName.replace(/"/g, "\\\"")}", ` : "@relation(";
|
|
765
|
+
const onDelete = foreignKey.onDelete ? `, onDelete: ${formatRelationAction(foreignKey.onDelete)}` : "";
|
|
766
|
+
return ` ${fieldName} ${targetModel} ${relationPrefix}fields: [${foreignKey.column}], references: [${foreignKey.referencesColumn}]${onDelete})`;
|
|
767
|
+
};
|
|
768
|
+
/**
|
|
769
|
+
* Build a Prisma relation field line for the inverse side of a relation, based
|
|
770
|
+
* on the source and target model names and the foreign key definition, using
|
|
771
|
+
* naming conventions and any explicit inverse alias provided.
|
|
772
|
+
*
|
|
773
|
+
* @param sourceModelName The name of the source model in the relation.
|
|
774
|
+
* @param targetModelName The name of the target model in the relation.
|
|
775
|
+
* @param foreignKey The foreign key definition for the relation.
|
|
776
|
+
* @returns The Prisma schema line for the inverse relation field.
|
|
777
|
+
*/
|
|
778
|
+
const buildInverseRelationLine = (sourceModelName, targetModelName, foreignKey) => {
|
|
779
|
+
return ` ${deriveCollectionFieldName(sourceModelName)} ${sourceModelName}[] @relation("${deriveInverseRelationAlias(sourceModelName, targetModelName, foreignKey.inverseRelationAlias).replace(/"/g, "\\\"")}")`;
|
|
780
|
+
};
|
|
781
|
+
/**
|
|
782
|
+
* Inject a line into the body of a Prisma model block if it does not already
|
|
783
|
+
* exist, using a provided existence check function to determine if the line
|
|
784
|
+
* is already present.
|
|
785
|
+
*
|
|
786
|
+
* @param bodyLines The lines of the model block body to modify.
|
|
787
|
+
* @param line The line to inject if it does not already exist.
|
|
788
|
+
* @param exists A function that checks if a given line already exists in the body.
|
|
789
|
+
* @returns
|
|
790
|
+
*/
|
|
791
|
+
const injectLineIntoModelBody = (bodyLines, line, exists) => {
|
|
792
|
+
if (bodyLines.some(exists)) return bodyLines;
|
|
793
|
+
const insertIndex = Math.max(1, bodyLines.length - 1);
|
|
794
|
+
bodyLines.splice(insertIndex, 0, line);
|
|
795
|
+
return bodyLines;
|
|
796
|
+
};
|
|
797
|
+
/**
|
|
798
|
+
* Apply inverse relation definitions to a Prisma schema string based on the
|
|
799
|
+
* foreign keys defined in a create or alter table operation, ensuring that
|
|
800
|
+
* related models have corresponding relation fields for bi-directional navigation.
|
|
801
|
+
*
|
|
802
|
+
* @param schema The Prisma schema string to modify.
|
|
803
|
+
* @param sourceModelName The name of the source model in the relation.
|
|
804
|
+
* @param foreignKeys An array of foreign key definitions to process.
|
|
805
|
+
* @returns The updated Prisma schema string with inverse relations applied.
|
|
806
|
+
*/
|
|
807
|
+
const applyInverseRelations = (schema, sourceModelName, foreignKeys) => {
|
|
808
|
+
let nextSchema = schema;
|
|
809
|
+
for (const foreignKey of foreignKeys) {
|
|
810
|
+
const targetModel = findModelBlock(nextSchema, foreignKey.referencesTable);
|
|
811
|
+
if (!targetModel) continue;
|
|
812
|
+
const inverseLine = buildInverseRelationLine(sourceModelName, targetModel.modelName, foreignKey);
|
|
813
|
+
const targetBodyLines = targetModel.block.split("\n");
|
|
814
|
+
const fieldName = deriveCollectionFieldName(sourceModelName);
|
|
815
|
+
const fieldRegex = new RegExp(`^\\s*${escapeRegex(fieldName)}\\s+`);
|
|
816
|
+
injectLineIntoModelBody(targetBodyLines, inverseLine, (line) => fieldRegex.test(line));
|
|
817
|
+
const updatedTarget = targetBodyLines.join("\n");
|
|
818
|
+
nextSchema = `${nextSchema.slice(0, targetModel.start)}${updatedTarget}${nextSchema.slice(targetModel.end)}`;
|
|
819
|
+
}
|
|
820
|
+
return nextSchema;
|
|
821
|
+
};
|
|
822
|
+
/**
|
|
585
823
|
* Build a Prisma model block string based on a SchemaTableCreateOperation, including
|
|
586
824
|
* all fields and any necessary mapping.
|
|
587
825
|
*
|
|
@@ -592,12 +830,14 @@ const buildModelBlock = (operation) => {
|
|
|
592
830
|
const modelName = toModelName(operation.table);
|
|
593
831
|
const mapped = operation.table !== modelName.toLowerCase();
|
|
594
832
|
const fields = operation.columns.map(buildFieldLine);
|
|
833
|
+
const relations = (operation.foreignKeys ?? []).map(buildRelationLine);
|
|
595
834
|
const metadata = [...(operation.indexes ?? []).map(buildIndexLine), ...mapped ? [` @@map("${str(operation.table).snake()}")`] : []];
|
|
596
835
|
return `model ${modelName} {\n${(metadata.length > 0 ? [
|
|
597
836
|
...fields,
|
|
837
|
+
...relations,
|
|
598
838
|
"",
|
|
599
839
|
...metadata
|
|
600
|
-
] : fields).join("\n")}\n}`;
|
|
840
|
+
] : [...fields, ...relations]).join("\n")}\n}`;
|
|
601
841
|
};
|
|
602
842
|
/**
|
|
603
843
|
* Find the Prisma model block in a schema string that corresponds to a given
|
|
@@ -647,7 +887,7 @@ const findModelBlock = (schema, table) => {
|
|
|
647
887
|
const applyCreateTableOperation = (schema, operation) => {
|
|
648
888
|
if (findModelBlock(schema, operation.table)) throw new ArkormException(`Prisma model for table [${operation.table}] already exists.`);
|
|
649
889
|
const block = buildModelBlock(operation);
|
|
650
|
-
return `${schema.trimEnd()}\n\n${block}\n
|
|
890
|
+
return applyInverseRelations(`${schema.trimEnd()}\n\n${block}\n`, toModelName(operation.table), operation.foreignKeys ?? []);
|
|
651
891
|
};
|
|
652
892
|
/**
|
|
653
893
|
* Apply an alter table operation to a Prisma schema string, modifying the model
|
|
@@ -684,8 +924,13 @@ const applyAlterTableOperation = (schema, operation) => {
|
|
|
684
924
|
const insertIndex = Math.max(1, bodyLines.length - 1);
|
|
685
925
|
bodyLines.splice(insertIndex, 0, indexLine);
|
|
686
926
|
});
|
|
927
|
+
for (const foreignKey of operation.addForeignKeys ?? []) {
|
|
928
|
+
const relationLine = buildRelationLine(foreignKey);
|
|
929
|
+
const relationRegex = new RegExp(`^\\s*${escapeRegex(foreignKey.fieldAlias?.trim() || deriveRelationFieldName(foreignKey.column))}\\s+`);
|
|
930
|
+
injectLineIntoModelBody(bodyLines, relationLine, (line) => relationRegex.test(line));
|
|
931
|
+
}
|
|
687
932
|
block = bodyLines.join("\n");
|
|
688
|
-
return `${schema.slice(0, model.start)}${block}${schema.slice(model.end)}
|
|
933
|
+
return applyInverseRelations(`${schema.slice(0, model.start)}${block}${schema.slice(model.end)}`, model.modelName, operation.addForeignKeys ?? []);
|
|
689
934
|
};
|
|
690
935
|
/**
|
|
691
936
|
* Apply a drop table operation to a Prisma schema string, removing the model block
|
|
@@ -1807,7 +2052,7 @@ var MigrateCommand = class extends Command {
|
|
|
1807
2052
|
const migrationsDir = this.app.resolveRuntimeDirectoryPath(configuredMigrationsDir);
|
|
1808
2053
|
if (!existsSync$1(migrationsDir)) return void this.error(`Error: Migrations directory not found: ${this.app.formatPathForLog(configuredMigrationsDir)}`);
|
|
1809
2054
|
const schemaPath = this.option("schema") ? resolve(String(this.option("schema"))) : join$1(process.cwd(), "prisma", "schema.prisma");
|
|
1810
|
-
const classes = this.option("all") ? await this.loadAllMigrations(migrationsDir) : (await this.loadNamedMigration(migrationsDir, this.argument("name"))).filter(([cls]) => cls !== void 0);
|
|
2055
|
+
const classes = this.option("all") || !this.argument("name") ? await this.loadAllMigrations(migrationsDir) : (await this.loadNamedMigration(migrationsDir, this.argument("name"))).filter(([cls]) => cls !== void 0);
|
|
1811
2056
|
if (classes.length === 0) return void this.error("Error: No migration classes found to run.");
|
|
1812
2057
|
for (const [MigrationClassItem] of classes) await applyMigrationToPrismaSchema(MigrationClassItem, {
|
|
1813
2058
|
schemaPath,
|
|
@@ -4842,4 +5087,4 @@ var Model = class Model {
|
|
|
4842
5087
|
};
|
|
4843
5088
|
|
|
4844
5089
|
//#endregion
|
|
4845
|
-
export { ArkormCollection, ArkormException, CliApp, InitCommand, InlineFactory, LengthAwarePaginator, MIGRATION_BRAND, MakeFactoryCommand, MakeMigrationCommand, MakeModelCommand, MakeSeederCommand, MigrateCommand, Migration, Model, ModelFactory, ModelNotFoundException, ModelsSyncCommand, PRISMA_MODEL_REGEX, Paginator, QueryBuilder, SEEDER_BRAND, SchemaBuilder, SeedCommand, Seeder, TableBuilder, URLDriver, applyAlterTableOperation, applyCreateTableOperation, applyDropTableOperation, applyMigrationToPrismaSchema, applyOperationsToPrismaSchema, buildFieldLine, buildIndexLine, buildMigrationSource, buildModelBlock, configureArkormRuntime, createMigrationTimestamp, createPrismaAdapter, createPrismaDelegateMap, defineConfig, defineFactory, ensureArkormConfigLoading, escapeRegex, findModelBlock, formatDefaultValue, generateMigrationFile, getDefaultStubsPath, getMigrationPlan, getRuntimePaginationURLDriverFactory, getRuntimePrismaClient, getUserConfig, inferDelegateName, isDelegateLike, loadArkormConfig, pad, resetArkormRuntimeForTests, resolveCast, resolveMigrationClassName, resolvePrismaType, runMigrationWithPrisma, runPrismaCommand, toMigrationFileSlug, toModelName };
|
|
5090
|
+
export { ArkormCollection, ArkormException, CliApp, ForeignKeyBuilder, InitCommand, InlineFactory, LengthAwarePaginator, MIGRATION_BRAND, MakeFactoryCommand, MakeMigrationCommand, MakeModelCommand, MakeSeederCommand, MigrateCommand, Migration, Model, ModelFactory, ModelNotFoundException, ModelsSyncCommand, PRISMA_MODEL_REGEX, Paginator, QueryBuilder, SEEDER_BRAND, SchemaBuilder, SeedCommand, Seeder, TableBuilder, URLDriver, applyAlterTableOperation, applyCreateTableOperation, applyDropTableOperation, applyMigrationToPrismaSchema, applyOperationsToPrismaSchema, buildFieldLine, buildIndexLine, buildInverseRelationLine, buildMigrationSource, buildModelBlock, buildRelationLine, configureArkormRuntime, createMigrationTimestamp, createPrismaAdapter, createPrismaDelegateMap, defineConfig, defineFactory, deriveCollectionFieldName, deriveInverseRelationAlias, deriveRelationFieldName, ensureArkormConfigLoading, escapeRegex, findModelBlock, formatDefaultValue, formatRelationAction, generateMigrationFile, getDefaultStubsPath, getMigrationPlan, getRuntimePaginationURLDriverFactory, getRuntimePrismaClient, getUserConfig, inferDelegateName, isDelegateLike, loadArkormConfig, pad, resetArkormRuntimeForTests, resolveCast, resolveMigrationClassName, resolvePrismaType, runMigrationWithPrisma, runPrismaCommand, toMigrationFileSlug, toModelName };
|