prisma-laravel-migrate 0.0.13 → 0.0.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -14,45 +14,181 @@ npm install prisma-laravel-migrate --save-dev
14
14
  ```
15
15
 
16
16
  ---
17
+ 🛠️ Configuration layers
17
18
 
18
- ## 🛠️ Prisma Generator Setup
19
+ The generators read options in **three tiers (highest → lowest)**:
19
20
 
20
- Add both generator blocks to **`schema.prisma`**:
21
+ 1. **Environment override** `PRISMA_LARAVEL_CFG=/path/to/laravel.config.js`
22
+ 2. **Shared project file** – **`prisma/laravel.config.js`** (auto‑loaded if present)
23
+ 3. **`generator … { … }` blocks** in `schema.prisma`
21
24
 
22
- ```prisma
23
- generator migrate {
24
- provider = "prisma-laravel-migrations"
25
- stubDir = "./prisma/stubs"
25
+ A key in tier ① shadows the same key in ② and ③; tier ② shadows tier ③.
26
+
27
+ ### 📁 Shared project file — `prisma/laravel.config.js`
28
+
29
+ ```js
30
+ /** Global to all Prisma‑Laravel generators */
31
+ module.exports = {
32
+ /* -- table decoration ------------------------------- */
33
+ tablePrefix: "tx_",
34
+ tableSuffix: "_arch",
35
+
36
+ /* -- default stub root ------------------------------ */
37
+ stubDir: "prisma/stubs",
26
38
 
27
- output = "database/migrations" // fallback
28
- outputDir = "database/migrations" // takes precedence
39
+ /* -- global dry‑run --------------------------------- */
40
+ noEmit: false,
41
+
42
+ /* -- override default outputs ----------------------- */
43
+ output: {
44
+ migrations: "database/migrations",
45
+ models: "app/Models",
46
+ enums: "app/Enums"
47
+ },
29
48
 
30
- noEmit = false // skip writing if true
31
- groups = "./prisma/group-stubs.js"
49
+ /* -- per‑generator overrides ------------------------ */
50
+ migrate: {
51
+ groups: "./prisma/migrate-groups.js",
52
+ rules : "./prisma/custom-rules.js"
53
+ },
54
+
55
+ modeler: {
56
+ groups: [
57
+ { stubFile: "audit.stub", tables: ["logs","audit_trails"] }
58
+ ],
59
+ outputEnumDir: "app/Enums",
60
+ overwriteExisting: true
61
+ }
62
+ };
63
+ ```
64
+
65
+ <details>
66
+ <summary>Type reference</summary>
67
+
68
+ ```ts
69
+ export interface Rule {
70
+ test(
71
+ def: ColumnDefinition,
72
+ allDefs: ColumnDefinition[],
73
+ dmmf: DMMF.Document
74
+ ): boolean;
75
+ render(
76
+ def: ColumnDefinition,
77
+ allDefs: ColumnDefinition[],
78
+ dmmf: DMMF.Document
79
+ ): Render;
80
+ }
81
+ /* ------------------------------------------------------------
82
+ * Re-usable stub-group description
83
+ * ---------------------------------------------------------- */
84
+ export interface StubGroupConfig {
85
+ /** Path relative to stubDir/<type>/ (e.g. "auth.stub") */
86
+ stubFile: string;
87
+ tables: string[]; // ["users","accounts",…] or enum names
32
88
  }
33
89
 
34
- generator modeler {
35
- provider = "prisma-laravel-models"
36
- stubDir = "./prisma/stubs"
90
+ /* ------------------------------------------------------------
91
+ * Per-generator overrides (migration / modeler)
92
+ * ---------------------------------------------------------- */
93
+ export interface LaravelGeneratorConfig {
94
+
95
+ /** Override stubDir only for this generator */
96
+ stubDir?: string;
97
+
98
+ /** Where the generated PHP goes (overrides block) */
99
+ outputDir?: string;
100
+
101
+ overwriteExisting?: boolean;
37
102
 
38
- output = "app/Models"
39
- outputDir = "app/Models" // overrides output
40
- outputEnumDir = "app/Enums"
103
+ /**
104
+ * Stub grouping:
105
+ * string – path to a JS module exporting StubGroupConfig[]
106
+ * • array – the group definitions themselves
107
+ */
108
+ groups?: string | StubGroupConfig[];
41
109
 
42
- noEmit = false
43
- groups = "./prisma/group-stubs.js"
110
+ /** Skip file emission for *this* generator only */
111
+ noEmit?: boolean;
44
112
  }
113
+
114
+ /* ------------------------------------------------------------
115
+ * Top-level shared config (visible to all generators)
116
+ * ---------------------------------------------------------- */
117
+ export interface LaravelSharedConfig {
118
+ /** Table name decoration */
119
+ tablePrefix?: string;
120
+ tableSuffix?: string;
121
+
122
+ /** Default stub root (migration/, model/, enum/) */
123
+ stubDir?: string;
124
+
125
+ /** Global “don’t write files” switch */
126
+ noEmit?: boolean;
127
+
128
+ /** Override default output folders */
129
+ output?: {
130
+ migrations?: string;
131
+ models?: string;
132
+ enums?: string;
133
+ };
134
+
135
+ /** Per-generator fine-tuning */
136
+ migrate?: Partial<MigratorConfigOverride>;
137
+ modeler?: Partial<ModelConfigOverride>;
138
+ }
139
+
140
+
141
+ /* --- Migrator-specific extra keys ---------------------------------------- */
142
+ export interface MigratorConfigOverride extends LaravelGeneratorConfig {
143
+ /**
144
+ * Custom migration rules:
145
+ * • string – path to JS module exporting Rule[]
146
+ * • Rule[] – rules array inline
147
+ */
148
+ rules?: string | Rule[];
149
+
150
+ stubPath?: string;
151
+ }
152
+
153
+
154
+ export interface ModelConfigOverride extends LaravelGeneratorConfig {
155
+ modelStubPath?: string;
156
+ enumStubPath?: string;
157
+ /** Extra folder for enums (modeler only) */
158
+ outputEnumDir?: string;
159
+ }
160
+ ```
161
+
162
+ </details>
163
+
164
+ ---
165
+
166
+ ## 🛠️ Prisma Generator Setup (quick)
167
+
168
+ Even with the shared file you may still keep minimal blocks in `schema.prisma`:
169
+
170
+ ```prisma
171
+ generator migrate {
172
+ provider = "prisma-laravel-migrations"
173
+ stubDir = "./prisma/stubs"
174
+ }
175
+
176
+ generator modeler {
177
+ provider = "prisma-laravel-models"
178
+ stubDir = "./prisma/stubs"
45
179
  ```
46
180
 
47
181
  ### Field Reference
48
182
 
49
- | Key | Notes |
50
- | --- | --- |
51
- | `outputDir / output` | Destination folder (`outputDir` overrides `output`). |
52
- | `outputEnumDir` | (modeler) directory for generated enum classes. |
53
- | `stubDir` | Root stub folder (`migration/`, `model/`, `enum/`). |
54
- | `groups` | JS module that maps stub files to table groups. |
55
- | `noEmit` | If `true`, generator parses but **writes no** files (dry‑run). |
183
+ | Key | Notes |
184
+ | ---------------------- | --------------------------------------------------------------------------------------------------------- |
185
+ | `outputDir / output` | Destination folder (`outputDir` overrides `output`). |
186
+ | `outputEnumDir` | (modeler) directory for generated enum classes. |
187
+ | `stubDir` | Root stub folder (`migration/`, `model/`, `enum/`). |
188
+ | `tablePrefix` | String prepended to every generated **physical** table name. |
189
+ | `tableSuffix` | String appended to every generated **physical** table name. |
190
+ | `groups` | JS module *or* inline array that maps stub files to table groups. |
191
+ | `noEmit` | If `true`, generator parses and validates but **does not write** any files (dry-run / CI mode). |
56
192
 
57
193
  ---
58
194
 
@@ -408,6 +544,12 @@ your Eloquent model.
408
544
  | `@ignore` | Relation field | Skips generating the relationship method |
409
545
  | `@with` (no args) | Relation field | Adds that single relation to `$with` |
410
546
  | `@with(rel1,rel2,…)` | Model only | Adds listed relations to `$with` |
547
+ | **NEW** `@trait:Full\Namespace\MyTrait` | Model only | Adds `use MyTrait;` inside the class |
548
+ | **NEW** `@implements:Full\Interface as Alias`| Model only | Adds the interface (with alias) to the class’s `implements` list |
549
+ | **NEW** `@observer:App\Observers\FooObserver`| Model only | Generates a `boot()` method that calls `static::observe(FooObserver::class);` |
550
+ | **NEW** `@factory:FooFactory` | Model only | Adds `use HasFactory;` and `protected static string $factory = FooFactory::class;` |
551
+ | **NEW** `@touch{col1,col2}` | Model only | Generates `protected $touches = ['col1','col2'];` |
552
+ | **NEW** `@appends{attr1,attr2}` | Model only | Generates `protected $appends = ['attr1','attr2'];` plus `$this->getAttrAttribute()` stubs |
411
553
 
412
554
  > **Syntax options**
413
555
  > • Inline:
@@ -418,7 +560,15 @@ your Eloquent model.
418
560
  > `/// @fillable{name,balance}`
419
561
  > • Model eager‑load:
420
562
  > `/// @with(posts,roles)`
421
-
563
+ > • **Traits / implements**:
564
+ > `/// @trait:Illuminate\Auth\Authenticatable`
565
+ > `/// @implements:Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract`
566
+ > • **Observers / factory**:
567
+ > `/// @observer:App\Observers\UserObserver`
568
+ > `/// @factory:UserFactory`
569
+ > • **Touches / appends**:
570
+ > `/// @touch{company,profile}`
571
+ > `/// @appends{full_name,age}`
422
572
  ---
423
573
 
424
574
  #### Example
@@ -467,6 +617,71 @@ protected $with = ['posts','comments'];
467
617
  `@ignore` prevents the `company()` relation method.
468
618
  Combine multiple inline directives; they’re processed left‑to‑right.
469
619
 
620
+
621
+ #### Example: Combined Directives
622
+
623
+ ```prisma
624
+ /// @fillable{name,balance}
625
+ /// @hidden{secretToken}
626
+ /// @guarded{password,apiToken}
627
+ /// @trait:Illuminate\Auth\Authenticatable
628
+ /// @implements:Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract
629
+ /// @observer:App\Observers\UserObserver
630
+ /// @factory:UserFactory
631
+ /// @touch{company}
632
+ /// @appends{full_name}
633
+ model User {
634
+ id Int @id @default(autoincrement())
635
+ email String @unique /// @hidden @fillable
636
+ password String /// @hidden @guarded
637
+ balance Decimal @default(0.0) /// @cast{decimal:2}
638
+ profile Json? /// @type{ import:'@types/forms', type:'ProfileDTO' }
639
+ company Company? @relation(fields:[companyId], references:[id]) /// @ignore
640
+ companyId Int?
641
+ posts Post[] /// @with
642
+ }
643
+ ```
644
+
645
+ **Generated output (simplified)**
646
+
647
+ ```php
648
+ use Illuminate\Auth\Authenticatable;
649
+ use Illuminate\Database\Eloquent\Factories\HasFactory;
650
+ use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
651
+ use App\Observers\UserObserver;
652
+
653
+ class User extends Model implements AuthenticatableContract
654
+ {
655
+ use HasFactory, Authenticatable;
656
+
657
+ protected $fillable = ['name','balance','email'];
658
+ protected $hidden = ['secretToken','password'];
659
+ protected $guarded = ['password','apiToken'];
660
+
661
+ protected $casts = ['balance' => 'decimal:2'];
662
+ protected $touches = ['company'];
663
+ protected $appends = ['full_name'];
664
+ protected static string $factory = UserFactory::class;
665
+
666
+ protected static function boot()
667
+ {
668
+ parent::boot();
669
+ static::observe(UserObserver::class);
670
+ }
671
+
672
+ public function getFullNameAttribute()
673
+ {
674
+ // TODO
675
+ return $this->attributes['full_name'] ?? null;
676
+ }
677
+
678
+ public function posts()
679
+ {
680
+ return $this->hasMany(Post::class);
681
+ }
682
+ }
683
+ ```
684
+
470
685
  ---
471
686
 
472
687
  ## 💡 Tips
@@ -477,6 +692,110 @@ Combine multiple inline directives; they’re processed left‑to‑right.
477
692
 
478
693
  ---
479
694
 
695
+ ## 📚 Programmatic API (ES / TypeScript)
696
+
697
+ Use the library directly in a script or build tool instead of the CLI.
698
+
699
+ ```ts
700
+ import {
701
+ generateLaravelSchema,
702
+ generateLaravelModels,
703
+ sortMigrations,
704
+ } from 'prisma-laravel-migrate';
705
+ import { readFileSync, writeFileSync } from 'fs';
706
+ import { getDMMF } from '@prisma/sdk';
707
+
708
+ (async () => {
709
+ /* 1. Load schema & build DMMF */
710
+ const schemaPath = 'prisma/schema.prisma';
711
+ const datamodel = readFileSync(schemaPath, 'utf8');
712
+ const dmmf = await getDMMF({ datamodel });
713
+
714
+ /* 2. Run generators entirely in-memory */
715
+ const migrations = generateLaravelSchema({
716
+ dmmf,
717
+ schemaPath, // ← always pass this
718
+ generator : { config: {} } as any,
719
+ });
720
+
721
+ const { models, enums } = generateLaravelModels({
722
+ dmmf,
723
+ schemaPath,
724
+ generator : { config: {} } as any,
725
+ });
726
+
727
+ /* 3. Inspect or write output */
728
+ sortMigrations(migrations).forEach(m => {
729
+ writeFileSync(`./out/${m.tableName}.php`, m.statements.join('\n'), 'utf8');
730
+ });
731
+ })();
732
+ ```
733
+
734
+ ### Custom migration rules in code
735
+
736
+ ```ts
737
+ import { Rule } from 'prisma-laravel-migrate';
738
+
739
+ const softDeleteRule: Rule = {
740
+ test: d => d.name === 'deleted_at' && d.migrationType === 'timestamp',
741
+ render: () => ({
742
+ column : 'deleted_at',
743
+ snippet: ["$table->timestamp('deleted_at')->nullable();"],
744
+ }),
745
+ };
746
+
747
+ generateLaravelSchema({
748
+ dmmf,
749
+ schemaPath: 'prisma/schema.prisma',
750
+ generator : { config: { rules: [softDeleteRule] } } as any,
751
+ });
752
+ ```
753
+
754
+ ### Public exports
755
+
756
+ | Export | Purpose |
757
+ | -------------------------------- | --------------------------------------------------- |
758
+ | `generateLaravelSchema` | Build migration objects (and optionally write files)|
759
+ | `generateLaravelModels` | Build model + enum definitions |
760
+ | `sortMigrations` | Topologically sort migrations by FK dependencies |
761
+ | `Rule` | Type helper for custom migration shortcuts |
762
+ | _types_ (`column-definition-types`, `laravel-config`) | Full TypeScript typings |
763
+
764
+ ```ts
765
+ import {
766
+ ColumnDefinition,
767
+ LaravelSharedConfig,
768
+ MigratorConfigOverride,
769
+ } from 'prisma-laravel-migrate';
770
+ ```
771
+
772
+ > **Heads-up:**
773
+ > `generateLaravelSchema` and `generateLaravelModels` **write files by default**
774
+ > (honouring the `outputDir` settings).
775
+ > If you only want the in-memory objects—e.g. to capture the returned
776
+ > `migrations`, `models`, or `enums` arrays—set
777
+ > `noEmit: true` in either
778
+ >
779
+ > * the per-call `generator.config` object:
780
+ > ```ts
781
+ > generateLaravelSchema({
782
+ > dmmf,
783
+ > schemaPath,
784
+ > generator: { config: { noEmit: true } } as any,
785
+ > });
786
+ > ```
787
+ > * **or** in `prisma/laravel.config.js`:
788
+ > ```js
789
+ > module.exports = {
790
+ > migrate: { noEmit: true },
791
+ > modeler: { noEmit: true },
792
+ > };
793
+ > ```
794
+ > This prevents any files from being created or overwritten while still
795
+ > returning the fully-populated data structures for custom processing.
796
+
797
+ ---
798
+
480
799
  ## 📜 License
481
800
 
482
801
  MIT — Happy scaffolding! 🎉
@@ -0,0 +1,245 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import fs from 'fs/promises';
4
+ import path from 'path';
5
+ import { fileURLToPath } from 'url';
6
+ import * as dmf from '@prisma/sdk';
7
+ import { generateLaravelSchema } from '../generator/migrator/index.js';
8
+ import { generateLaravelModels } from '../generator/modeler/index.js';
9
+ import { existsSync, readFileSync } from 'fs';
10
+ import { spawn } from 'child_process';
11
+ const cli = new Command();
12
+ cli
13
+ .name('prisma-laravel-cli')
14
+ .description('Initialize and customize Prisma→Laravel generators & stubs')
15
+ .version('0.1.0');
16
+ function generatorBlock(base, // singular
17
+ stubDirRel, extras = []) {
18
+ const name = `${base}s`; // migrations / models
19
+ const provider = `prisma-laravel-${name}s`; // prisma-laravel-migrations
20
+ const extra = extras.length ? "\n " + extras.join("\n ") : "";
21
+ return `
22
+ generator ${name} {
23
+ provider = "${provider}"
24
+ stubDir = "${stubDirRel}"${extra}
25
+ }
26
+ `;
27
+ }
28
+ //
29
+ // init
30
+ //
31
+ cli
32
+ .command("init")
33
+ .description("Inject generators into schema.prisma and scaffold stubs/")
34
+ .option("-s, --schema <path>", "Prisma schema file", "prisma/schema.prisma")
35
+ .action(async (opts) => {
36
+ /* 1. Paths ------------------------------------------------------ */
37
+ const schemaPath = path.resolve(process.cwd(), opts.schema);
38
+ const schemaDir = path.dirname(schemaPath); // prisma/
39
+ const userStubs = path.join(schemaDir, "stubs"); // prisma/stubs
40
+ const stubDirRel = "./" + path.relative(schemaDir, userStubs).replace(/\\/g, "/"); // "./stubs"
41
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
42
+ const pkgStubs = path.resolve(__dirname, "../stubs"); // bundled stubs
43
+ /* 2. Load schema.prisma ---------------------------------------- */
44
+ let schema = await fs.readFile(schemaPath, "utf-8");
45
+ const hasGen = (base) => new RegExp(`generator\\s+${base}s\\s*\\{`).test(schema);
46
+ /* 3. Inject generator blocks if missing ------------------------ */
47
+ if (!hasGen("migration")) {
48
+ schema += generatorBlock("migration", stubDirRel, [
49
+ 'outputDir = "database/migrations"',
50
+ ]);
51
+ console.log("➡️ Added migrations generator");
52
+ }
53
+ if (!hasGen("model")) {
54
+ schema += generatorBlock("model", stubDirRel, [
55
+ 'outputDir = "app/Models"',
56
+ 'outputEnumDir = "app/Enums"',
57
+ ]);
58
+ console.log("➡️ Added models generator");
59
+ }
60
+ await fs.writeFile(schemaPath, schema, "utf-8");
61
+ console.log(`✅ Updated ${schemaPath}`);
62
+ /* 4. Copy default stub files ---------------------------------- */
63
+ const stubTypes = ["migration", "model", "enum"];
64
+ for (const type of stubTypes) {
65
+ const targetDir = path.join(userStubs, type);
66
+ await fs.mkdir(targetDir, { recursive: true });
67
+ /* index.stub */
68
+ const src = path.join(pkgStubs, `${type}.stub`);
69
+ const dst = path.join(targetDir, "index.stub");
70
+ try {
71
+ await fs.access(dst);
72
+ }
73
+ catch {
74
+ await fs.copyFile(src, dst);
75
+ console.log(`➡️ Copied ${type}.stub → stubs/${type}/index.stub`);
76
+ }
77
+ /* simple-model.stub */
78
+ if (type === "model") {
79
+ const src2 = path.join(pkgStubs, "simple-model.stub");
80
+ const dst2 = path.join(targetDir, "simple-model.stub");
81
+ try {
82
+ await fs.access(dst2);
83
+ }
84
+ catch {
85
+ await fs.copyFile(src2, dst2);
86
+ console.log("➡️ Copied simple-model.stub → stubs/model/simple-model.stub");
87
+ }
88
+ }
89
+ }
90
+ /* 5. Create laravel.config.js if absent ------------------------ */
91
+ const cfgPath = path.join(schemaDir, "prisma-laravel.config.js");
92
+ try {
93
+ await fs.access(cfgPath);
94
+ }
95
+ catch {
96
+ const cfgTemplate = `
97
+ // prisma/prisma-laravel.config.js
98
+ module.exports = {
99
+ tablePrefix: "", // e.g. "tx_"
100
+ tableSuffix: "", // e.g. "_arch"
101
+ stubDir: "${stubDirRel}",
102
+ // migrate: { noEmit: false },
103
+ // modeler: { noEmit: false }
104
+ };
105
+ `;
106
+ await fs.writeFile(cfgPath, cfgTemplate.trimStart(), "utf-8");
107
+ console.log("➡️ Created laravel.config.js");
108
+ }
109
+ console.log("🎉 Initialization complete!");
110
+ });
111
+ //
112
+ // customize
113
+ //
114
+ cli
115
+ .command('customize')
116
+ .alias('c')
117
+ .description('Scaffold per-table stub files from index.stub')
118
+ .option('-s, --schema <path>', 'Prisma schema file', 'prisma/schema.prisma')
119
+ .option('-t, --types <list>', 'Comma-separated: migration,model,enum', (val) => val.split(',').map(s => s.trim().toLowerCase()), [])
120
+ .option('-n, --names <list>', 'Comma-separated base names', (val) => val.split(',').map(s => s.trim()), [])
121
+ .action(async (opts) => {
122
+ const want = opts.types;
123
+ const bases = opts.names;
124
+ if (!want.length)
125
+ throw new Error('Specify at least one type with -t');
126
+ if (!bases.length)
127
+ throw new Error('Specify at least one name with -n');
128
+ // enums stand alone
129
+ if (want.includes('enum') && want.length > 1) {
130
+ throw new Error('`enum` cannot be combined with other types');
131
+ }
132
+ const schemaDir = path.dirname(path.resolve(process.cwd(), opts.schema));
133
+ const stubRoot = path.join(schemaDir, 'stubs');
134
+ const doBoth = want.includes('migration') && want.includes('model');
135
+ for (const t of want) {
136
+ if (t === 'enum') {
137
+ const dir = path.join(stubRoot, 'enum');
138
+ const idx = path.join(dir, 'index.stub');
139
+ await fs.mkdir(dir, { recursive: true });
140
+ for (const name of bases) {
141
+ const dst = path.join(dir, `${name}.stub`);
142
+ try {
143
+ await fs.access(dst);
144
+ console.log(`🟡 Skip enum/${name}.stub`);
145
+ }
146
+ catch {
147
+ await fs.copyFile(idx, dst);
148
+ console.log(`✅ Created enum/${name}.stub`);
149
+ }
150
+ }
151
+ continue;
152
+ }
153
+ for (const kind of doBoth ? ['migration', 'model'] : [t]) {
154
+ const dir = path.join(stubRoot, kind);
155
+ const idx = path.join(dir, 'index.stub');
156
+ await fs.mkdir(dir, { recursive: true });
157
+ for (const base of bases) {
158
+ const dst = path.join(dir, `${base}.stub`);
159
+ try {
160
+ await fs.access(dst);
161
+ console.log(`🟡 Skip ${kind}/${base}.stub`);
162
+ }
163
+ catch {
164
+ await fs.copyFile(idx, dst);
165
+ console.log(`✅ Created ${kind}/${base}.stub`);
166
+ }
167
+ }
168
+ }
169
+ }
170
+ console.log('🎉 Customize complete!');
171
+ });
172
+ //
173
+ // proxy to Prisma generate
174
+ //
175
+ cli
176
+ .command('gen')
177
+ .description('Run Prisma generate, or skip it (--skipGenerate), then run Laravel generators')
178
+ .option('--config <path>', 'Path to prisma-laravel config file')
179
+ .option('--skipGenerate', 'Only run the Laravel generators (no Prisma generate)')
180
+ .action(async (opts) => {
181
+ const configPath = opts.config
182
+ ? path.resolve(process.cwd(), opts.config)
183
+ : path.resolve(process.cwd(), 'prisma-laravel.config.js');
184
+ if (!existsSync(configPath)) {
185
+ console.error(`❌ Config file not found: ${configPath}`);
186
+ process.exit(1);
187
+ }
188
+ const cfgMod = await import(configPath);
189
+ const cfg = cfgMod.default ?? cfgMod;
190
+ if (!cfg.generator?.config) {
191
+ console.error('❌ `generator.config` is required in your config.');
192
+ process.exit(1);
193
+ }
194
+ const schemaPrismaPath = cfg.schemaPath
195
+ ? path.resolve(process.cwd(), cfg.schemaPath)
196
+ : path.resolve(process.cwd(), 'prisma/schema.prisma');
197
+ if (!existsSync(schemaPrismaPath)) {
198
+ console.error(`❌ Schema not found: ${schemaPrismaPath}`);
199
+ process.exit(1);
200
+ }
201
+ const run = async () => {
202
+ const datamodel = readFileSync(schemaPrismaPath, 'utf-8');
203
+ const sdk = dmf.default ?? dmf;
204
+ const { dmmf } = await sdk.getDMMF({ datamodel });
205
+ await generateLaravelSchema({
206
+ dmmf,
207
+ //@ts-ignore
208
+ generator: { config: cfg.generator.config },
209
+ otherGenerators: [],
210
+ schemaPath: schemaPrismaPath,
211
+ datasources: [],
212
+ datamodel,
213
+ version: '',
214
+ });
215
+ await generateLaravelModels({
216
+ dmmf,
217
+ //@ts-ignore
218
+ generator: { config: cfg.generator.config },
219
+ otherGenerators: [],
220
+ schemaPath: schemaPrismaPath,
221
+ datasources: [],
222
+ datamodel,
223
+ version: '',
224
+ });
225
+ };
226
+ if (opts.skipGenerate) {
227
+ await run();
228
+ }
229
+ else {
230
+ const prisma = spawn('npx', ['prisma', 'generate'], {
231
+ stdio: 'inherit',
232
+ shell: true,
233
+ });
234
+ prisma.on('exit', (code) => {
235
+ if (code !== 0)
236
+ process.exit(code);
237
+ run().catch(e => {
238
+ console.error('❌ Gen failed:', e.message ?? e);
239
+ process.exit(1);
240
+ });
241
+ });
242
+ }
243
+ });
244
+ cli.parse(process.argv);
245
+ //# sourceMappingURL=cli.js.map
@@ -9,4 +9,4 @@ generatorHandler({
9
9
  prettyName: 'Laravel Schema',
10
10
  }),
11
11
  });
12
- //# sourceMappingURL=index.js.map
12
+ //# sourceMappingURL=migrator.index.js.map