ilana-orm 1.0.7 → 1.0.9
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/cli/ilana.js +117 -452
- package/orm/CustomCasts.mjs +7 -0
- package/orm/MigrationRunner.js +23 -15
- package/package.json +7 -2
package/cli/ilana.js
CHANGED
|
@@ -108,6 +108,122 @@ function pluralize(str) {
|
|
|
108
108
|
return str + 's';
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
+
function getESModuleConfigTemplate() {
|
|
112
|
+
return `import 'dotenv/config';
|
|
113
|
+
import Database from 'ilana-orm/database/connection';
|
|
114
|
+
|
|
115
|
+
const config = {
|
|
116
|
+
default: process.env.DB_CONNECTION || 'mysql',
|
|
117
|
+
timezone: process.env.DB_TIMEZONE || 'UTC',
|
|
118
|
+
|
|
119
|
+
connections: {
|
|
120
|
+
sqlite: {
|
|
121
|
+
client: 'sqlite3',
|
|
122
|
+
connection: {
|
|
123
|
+
filename: process.env.DB_FILENAME || './database.sqlite'
|
|
124
|
+
},
|
|
125
|
+
useNullAsDefault: true
|
|
126
|
+
},
|
|
127
|
+
|
|
128
|
+
mysql: {
|
|
129
|
+
client: 'mysql2',
|
|
130
|
+
connection: {
|
|
131
|
+
host: process.env.DB_HOST || 'localhost',
|
|
132
|
+
port: process.env.DB_PORT || 3306,
|
|
133
|
+
user: process.env.DB_USERNAME || 'root',
|
|
134
|
+
password: process.env.DB_PASSWORD || '',
|
|
135
|
+
database: process.env.DB_DATABASE || 'your_database',
|
|
136
|
+
timezone: process.env.DB_TIMEZONE || 'UTC'
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
|
|
140
|
+
postgres: {
|
|
141
|
+
client: 'pg',
|
|
142
|
+
connection: {
|
|
143
|
+
host: process.env.DB_HOST || 'localhost',
|
|
144
|
+
port: process.env.DB_PORT || 5432,
|
|
145
|
+
user: process.env.DB_USERNAME || 'postgres',
|
|
146
|
+
password: process.env.DB_PASSWORD || '',
|
|
147
|
+
database: process.env.DB_DATABASE || 'your_database'
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
|
|
152
|
+
migrations: {
|
|
153
|
+
directory: './database/migrations',
|
|
154
|
+
tableName: 'migrations'
|
|
155
|
+
},
|
|
156
|
+
|
|
157
|
+
seeds: {
|
|
158
|
+
directory: './database/seeds'
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
// Auto-initialize database connections
|
|
163
|
+
Database.configure(config);
|
|
164
|
+
|
|
165
|
+
export default config;
|
|
166
|
+
`;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function getCommonJSConfigTemplate() {
|
|
170
|
+
return `require('dotenv').config();
|
|
171
|
+
const Database = require('ilana-orm/database/connection');
|
|
172
|
+
|
|
173
|
+
const config = {
|
|
174
|
+
default: process.env.DB_CONNECTION || 'mysql',
|
|
175
|
+
timezone: process.env.DB_TIMEZONE || 'UTC',
|
|
176
|
+
|
|
177
|
+
connections: {
|
|
178
|
+
sqlite: {
|
|
179
|
+
client: 'sqlite3',
|
|
180
|
+
connection: {
|
|
181
|
+
filename: process.env.DB_FILENAME || './database.sqlite'
|
|
182
|
+
},
|
|
183
|
+
useNullAsDefault: true
|
|
184
|
+
},
|
|
185
|
+
|
|
186
|
+
mysql: {
|
|
187
|
+
client: 'mysql2',
|
|
188
|
+
connection: {
|
|
189
|
+
host: process.env.DB_HOST || 'localhost',
|
|
190
|
+
port: process.env.DB_PORT || 3306,
|
|
191
|
+
user: process.env.DB_USERNAME || 'root',
|
|
192
|
+
password: process.env.DB_PASSWORD || '',
|
|
193
|
+
database: process.env.DB_DATABASE || 'your_database',
|
|
194
|
+
timezone: process.env.DB_TIMEZONE || 'UTC'
|
|
195
|
+
}
|
|
196
|
+
},
|
|
197
|
+
|
|
198
|
+
postgres: {
|
|
199
|
+
client: 'pg',
|
|
200
|
+
connection: {
|
|
201
|
+
host: process.env.DB_HOST || 'localhost',
|
|
202
|
+
port: process.env.DB_PORT || 5432,
|
|
203
|
+
user: process.env.DB_USERNAME || 'postgres',
|
|
204
|
+
password: process.env.DB_PASSWORD || '',
|
|
205
|
+
database: process.env.DB_DATABASE || 'your_database'
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
|
|
210
|
+
migrations: {
|
|
211
|
+
directory: './database/migrations',
|
|
212
|
+
tableName: 'migrations'
|
|
213
|
+
},
|
|
214
|
+
|
|
215
|
+
seeds: {
|
|
216
|
+
directory: './database/seeds'
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
// Auto-initialize database connections
|
|
221
|
+
Database.configure(config);
|
|
222
|
+
|
|
223
|
+
module.exports = config;
|
|
224
|
+
`;
|
|
225
|
+
}
|
|
226
|
+
|
|
111
227
|
function generateModel(name, options = {}) {
|
|
112
228
|
const className = toPascalCase(name);
|
|
113
229
|
const tableName = pluralize(toSnakeCase(name));
|
|
@@ -438,124 +554,6 @@ const commands = {
|
|
|
438
554
|
fs.writeFileSync(configPath, configTemplate);
|
|
439
555
|
console.log(`Created config file: ${configPath}`);
|
|
440
556
|
}
|
|
441
|
-
},
|
|
442
|
-
};
|
|
443
|
-
|
|
444
|
-
function getESModuleConfigTemplate() {
|
|
445
|
-
return `import 'dotenv/config';
|
|
446
|
-
import Database from 'ilana-orm/database/connection.js';
|
|
447
|
-
|
|
448
|
-
const config = {
|
|
449
|
-
default: process.env.DB_CONNECTION || 'mysql',
|
|
450
|
-
timezone: process.env.DB_TIMEZONE || 'UTC',
|
|
451
|
-
|
|
452
|
-
connections: {
|
|
453
|
-
sqlite: {
|
|
454
|
-
client: 'sqlite3',
|
|
455
|
-
connection: {
|
|
456
|
-
filename: process.env.DB_FILENAME || './database.sqlite'
|
|
457
|
-
},
|
|
458
|
-
useNullAsDefault: true
|
|
459
|
-
},
|
|
460
|
-
|
|
461
|
-
mysql: {
|
|
462
|
-
client: 'mysql2',
|
|
463
|
-
connection: {
|
|
464
|
-
host: process.env.DB_HOST || 'localhost',
|
|
465
|
-
port: process.env.DB_PORT || 3306,
|
|
466
|
-
user: process.env.DB_USERNAME || 'root',
|
|
467
|
-
password: process.env.DB_PASSWORD || '',
|
|
468
|
-
database: process.env.DB_DATABASE || 'your_database',
|
|
469
|
-
timezone: process.env.DB_TIMEZONE || 'UTC'
|
|
470
|
-
}
|
|
471
|
-
},
|
|
472
|
-
|
|
473
|
-
postgres: {
|
|
474
|
-
client: 'pg',
|
|
475
|
-
connection: {
|
|
476
|
-
host: process.env.DB_HOST || 'localhost',
|
|
477
|
-
port: process.env.DB_PORT || 5432,
|
|
478
|
-
user: process.env.DB_USERNAME || 'postgres',
|
|
479
|
-
password: process.env.DB_PASSWORD || '',
|
|
480
|
-
database: process.env.DB_DATABASE || 'your_database'
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
},
|
|
484
|
-
|
|
485
|
-
migrations: {
|
|
486
|
-
directory: './database/migrations',
|
|
487
|
-
tableName: 'migrations'
|
|
488
|
-
},
|
|
489
|
-
|
|
490
|
-
seeds: {
|
|
491
|
-
directory: './database/seeds'
|
|
492
|
-
}
|
|
493
|
-
};
|
|
494
|
-
|
|
495
|
-
// Auto-initialize database connections
|
|
496
|
-
Database.configure(config);
|
|
497
|
-
|
|
498
|
-
export default config;
|
|
499
|
-
`;
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
function getCommonJSConfigTemplate() {
|
|
503
|
-
return `require('dotenv').config();
|
|
504
|
-
const Database = require('ilana-orm/database/connection');
|
|
505
|
-
|
|
506
|
-
const config = {
|
|
507
|
-
default: process.env.DB_CONNECTION || 'mysql',
|
|
508
|
-
timezone: process.env.DB_TIMEZONE || 'UTC',
|
|
509
|
-
|
|
510
|
-
connections: {
|
|
511
|
-
sqlite: {
|
|
512
|
-
client: 'sqlite3',
|
|
513
|
-
connection: {
|
|
514
|
-
filename: process.env.DB_FILENAME || './database.sqlite'
|
|
515
|
-
},
|
|
516
|
-
useNullAsDefault: true
|
|
517
|
-
},
|
|
518
|
-
|
|
519
|
-
mysql: {
|
|
520
|
-
client: 'mysql2',
|
|
521
|
-
connection: {
|
|
522
|
-
host: process.env.DB_HOST || 'localhost',
|
|
523
|
-
port: process.env.DB_PORT || 3306,
|
|
524
|
-
user: process.env.DB_USERNAME || 'root',
|
|
525
|
-
password: process.env.DB_PASSWORD || '',
|
|
526
|
-
database: process.env.DB_DATABASE || 'your_database',
|
|
527
|
-
timezone: process.env.DB_TIMEZONE || 'UTC'
|
|
528
|
-
}
|
|
529
|
-
},
|
|
530
|
-
|
|
531
|
-
postgres: {
|
|
532
|
-
client: 'pg',
|
|
533
|
-
connection: {
|
|
534
|
-
host: process.env.DB_HOST || 'localhost',
|
|
535
|
-
port: process.env.DB_PORT || 5432,
|
|
536
|
-
user: process.env.DB_USERNAME || 'postgres',
|
|
537
|
-
password: process.env.DB_PASSWORD || '',
|
|
538
|
-
database: process.env.DB_DATABASE || 'your_database'
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
},
|
|
542
|
-
|
|
543
|
-
migrations: {
|
|
544
|
-
directory: './database/migrations',
|
|
545
|
-
tableName: 'migrations'
|
|
546
|
-
},
|
|
547
|
-
|
|
548
|
-
seeds: {
|
|
549
|
-
directory: './database/seeds'
|
|
550
|
-
}
|
|
551
|
-
};
|
|
552
|
-
|
|
553
|
-
// Auto-initialize database connections
|
|
554
|
-
Database.configure(config);
|
|
555
|
-
|
|
556
|
-
module.exports = config;
|
|
557
|
-
`;
|
|
558
|
-
}
|
|
559
557
|
|
|
560
558
|
// Create .env file if it doesn't exist
|
|
561
559
|
const envPath = '.env';
|
|
@@ -600,6 +598,7 @@ DB_TIMEZONE=UTC
|
|
|
600
598
|
console.log('2. Run: ilana make:model User -m');
|
|
601
599
|
console.log('3. Run: ilana migrate');
|
|
602
600
|
},
|
|
601
|
+
|
|
603
602
|
async 'make:migration'(name, ...flags) {
|
|
604
603
|
if (!name) {
|
|
605
604
|
console.error('Migration name is required');
|
|
@@ -700,329 +699,6 @@ DB_TIMEZONE=UTC
|
|
|
700
699
|
generateModel(name, options);
|
|
701
700
|
},
|
|
702
701
|
|
|
703
|
-
async migrate(...args) {
|
|
704
|
-
await initializeDatabase();
|
|
705
|
-
const runner = new MigrationRunner();
|
|
706
|
-
|
|
707
|
-
let connection;
|
|
708
|
-
let onlyFile;
|
|
709
|
-
let toFile;
|
|
710
|
-
|
|
711
|
-
for (let i = 0; i < args.length; i++) {
|
|
712
|
-
const arg = args[i];
|
|
713
|
-
if (arg === '--connection' && args[i + 1]) {
|
|
714
|
-
connection = args[i + 1];
|
|
715
|
-
i++;
|
|
716
|
-
} else if (arg.startsWith('--connection=')) {
|
|
717
|
-
connection = arg.split('=')[1];
|
|
718
|
-
} else if (arg === '--only' && args[i + 1]) {
|
|
719
|
-
onlyFile = args[i + 1];
|
|
720
|
-
i++;
|
|
721
|
-
} else if (arg.startsWith('--only=')) {
|
|
722
|
-
onlyFile = arg.split('=')[1];
|
|
723
|
-
} else if (arg === '--to' && args[i + 1]) {
|
|
724
|
-
toFile = args[i + 1];
|
|
725
|
-
i++;
|
|
726
|
-
} else if (arg.startsWith('--to=')) {
|
|
727
|
-
toFile = arg.split('=')[1];
|
|
728
|
-
} else if (!arg.startsWith('--')) {
|
|
729
|
-
connection = arg;
|
|
730
|
-
}
|
|
731
|
-
}
|
|
732
|
-
|
|
733
|
-
await runner.migrate(connection, onlyFile, toFile);
|
|
734
|
-
process.exit(0);
|
|
735
|
-
},
|
|
736
|
-
|
|
737
|
-
async 'migrate:fresh'(...args) {
|
|
738
|
-
await initializeDatabase();
|
|
739
|
-
const runner = new MigrationRunner();
|
|
740
|
-
|
|
741
|
-
let connection;
|
|
742
|
-
let withSeed = false;
|
|
743
|
-
|
|
744
|
-
for (const arg of args) {
|
|
745
|
-
if (arg === '--seed') {
|
|
746
|
-
withSeed = true;
|
|
747
|
-
} else if (arg.startsWith('--connection=')) {
|
|
748
|
-
connection = arg.split('=')[1];
|
|
749
|
-
} else if (!arg.startsWith('--')) {
|
|
750
|
-
connection = arg;
|
|
751
|
-
}
|
|
752
|
-
}
|
|
753
|
-
|
|
754
|
-
await runner.fresh(connection);
|
|
755
|
-
|
|
756
|
-
if (withSeed) {
|
|
757
|
-
await commands.seed();
|
|
758
|
-
}
|
|
759
|
-
|
|
760
|
-
process.exit(0);
|
|
761
|
-
},
|
|
762
|
-
|
|
763
|
-
async 'migrate:list'(connection) {
|
|
764
|
-
await initializeDatabase();
|
|
765
|
-
const runner = new MigrationRunner();
|
|
766
|
-
await runner.list(connection);
|
|
767
|
-
process.exit(0);
|
|
768
|
-
},
|
|
769
|
-
|
|
770
|
-
async 'migrate:unlock'(connection) {
|
|
771
|
-
await initializeDatabase();
|
|
772
|
-
const runner = new MigrationRunner();
|
|
773
|
-
await runner.unlock(connection);
|
|
774
|
-
process.exit(0);
|
|
775
|
-
},
|
|
776
|
-
|
|
777
|
-
async 'migrate:rollback'(...args) {
|
|
778
|
-
await initializeDatabase();
|
|
779
|
-
const runner = new MigrationRunner();
|
|
780
|
-
|
|
781
|
-
let steps = 1;
|
|
782
|
-
let connection;
|
|
783
|
-
let toFile;
|
|
784
|
-
|
|
785
|
-
for (let i = 0; i < args.length; i++) {
|
|
786
|
-
const arg = args[i];
|
|
787
|
-
if (arg === '--step' && args[i + 1]) {
|
|
788
|
-
steps = parseInt(args[i + 1]);
|
|
789
|
-
i++;
|
|
790
|
-
} else if (arg.startsWith('--step=')) {
|
|
791
|
-
steps = parseInt(arg.split('=')[1]);
|
|
792
|
-
} else if (arg === '--connection' && args[i + 1]) {
|
|
793
|
-
connection = args[i + 1];
|
|
794
|
-
i++;
|
|
795
|
-
} else if (arg.startsWith('--connection=')) {
|
|
796
|
-
connection = arg.split('=')[1];
|
|
797
|
-
} else if (arg === '--to' && args[i + 1]) {
|
|
798
|
-
toFile = args[i + 1];
|
|
799
|
-
i++;
|
|
800
|
-
} else if (arg.startsWith('--to=')) {
|
|
801
|
-
toFile = arg.split('=')[1];
|
|
802
|
-
} else if (!isNaN(parseInt(arg))) {
|
|
803
|
-
steps = parseInt(arg);
|
|
804
|
-
} else if (!arg.startsWith('--')) {
|
|
805
|
-
connection = arg;
|
|
806
|
-
}
|
|
807
|
-
}
|
|
808
|
-
|
|
809
|
-
await runner.rollback(steps, connection, toFile);
|
|
810
|
-
process.exit(0);
|
|
811
|
-
},
|
|
812
|
-
|
|
813
|
-
async 'migrate:reset'(connection) {
|
|
814
|
-
await initializeDatabase();
|
|
815
|
-
const runner = new MigrationRunner();
|
|
816
|
-
await runner.reset(connection);
|
|
817
|
-
process.exit(0);
|
|
818
|
-
},
|
|
819
|
-
|
|
820
|
-
async 'migrate:refresh'(connection) {
|
|
821
|
-
await initializeDatabase();
|
|
822
|
-
const runner = new MigrationRunner();
|
|
823
|
-
await runner.refresh(connection);
|
|
824
|
-
process.exit(0);
|
|
825
|
-
},
|
|
826
|
-
|
|
827
|
-
async 'migrate:status'(connection) {
|
|
828
|
-
await initializeDatabase();
|
|
829
|
-
const runner = new MigrationRunner();
|
|
830
|
-
await runner.status(connection);
|
|
831
|
-
process.exit(0);
|
|
832
|
-
},
|
|
833
|
-
|
|
834
|
-
async seed(...args) {
|
|
835
|
-
await initializeDatabase();
|
|
836
|
-
|
|
837
|
-
let seederName;
|
|
838
|
-
let connection;
|
|
839
|
-
|
|
840
|
-
for (let i = 0; i < args.length; i++) {
|
|
841
|
-
const arg = args[i];
|
|
842
|
-
if (arg === '--class' && args[i + 1]) {
|
|
843
|
-
seederName = args[i + 1];
|
|
844
|
-
i++;
|
|
845
|
-
} else if (arg.startsWith('--class=')) {
|
|
846
|
-
seederName = arg.split('=')[1];
|
|
847
|
-
} else if (arg === '--connection' && args[i + 1]) {
|
|
848
|
-
connection = args[i + 1];
|
|
849
|
-
i++;
|
|
850
|
-
} else if (arg.startsWith('--connection=')) {
|
|
851
|
-
connection = arg.split('=')[1];
|
|
852
|
-
} else if (!arg.startsWith('--')) {
|
|
853
|
-
if (!seederName) seederName = arg;
|
|
854
|
-
else connection = arg;
|
|
855
|
-
}
|
|
856
|
-
}
|
|
857
|
-
|
|
858
|
-
const seedsPath = path.join(process.cwd(), 'database/seeds');
|
|
859
|
-
if (!fs.existsSync(seedsPath)) {
|
|
860
|
-
console.log('No seeds directory found');
|
|
861
|
-
process.exit(0);
|
|
862
|
-
}
|
|
863
|
-
|
|
864
|
-
const seedFiles = fs.readdirSync(seedsPath)
|
|
865
|
-
.filter(file => file.endsWith('.ts') || file.endsWith('.js'))
|
|
866
|
-
.sort();
|
|
867
|
-
|
|
868
|
-
if (seedFiles.length === 0) {
|
|
869
|
-
console.log('No seed files found');
|
|
870
|
-
process.exit(0);
|
|
871
|
-
}
|
|
872
|
-
|
|
873
|
-
const filesToRun = seederName
|
|
874
|
-
? seedFiles.filter(file => file.includes(seederName))
|
|
875
|
-
: seedFiles;
|
|
876
|
-
|
|
877
|
-
console.log(`Running ${filesToRun.length} seeders...`);
|
|
878
|
-
|
|
879
|
-
for (const file of filesToRun) {
|
|
880
|
-
console.log(`Seeding: ${file}`);
|
|
881
|
-
const filepath = path.join(seedsPath, file);
|
|
882
|
-
delete require.cache[filepath];
|
|
883
|
-
|
|
884
|
-
let seederModule;
|
|
885
|
-
try {
|
|
886
|
-
seederModule = require(filepath);
|
|
887
|
-
} catch (error) {
|
|
888
|
-
if (error.code === 'ERR_REQUIRE_ESM') {
|
|
889
|
-
// Handle ES modules
|
|
890
|
-
seederModule = await import(filepath);
|
|
891
|
-
} else {
|
|
892
|
-
throw error;
|
|
893
|
-
}
|
|
894
|
-
}
|
|
895
|
-
|
|
896
|
-
const SeederClass = seederModule.default || seederModule;
|
|
897
|
-
const seeder = new SeederClass();
|
|
898
|
-
|
|
899
|
-
if (connection) {
|
|
900
|
-
seeder.connection = connection;
|
|
901
|
-
}
|
|
902
|
-
|
|
903
|
-
if (typeof seeder.run === 'function') {
|
|
904
|
-
await seeder.run();
|
|
905
|
-
}
|
|
906
|
-
|
|
907
|
-
console.log(`Seeded: ${file}`);
|
|
908
|
-
}
|
|
909
|
-
|
|
910
|
-
console.log('Seeding completed');
|
|
911
|
-
process.exit(0);
|
|
912
|
-
},
|
|
913
|
-
|
|
914
|
-
async 'db:seed'(seederName) {
|
|
915
|
-
return commands.seed(seederName);
|
|
916
|
-
},
|
|
917
|
-
|
|
918
|
-
async 'db:wipe'(connection) {
|
|
919
|
-
await initializeDatabase();
|
|
920
|
-
const runner = new MigrationRunner();
|
|
921
|
-
await runner.wipe(connection);
|
|
922
|
-
process.exit(0);
|
|
923
|
-
},
|
|
924
|
-
|
|
925
|
-
async 'make:observer'(name, ...flags) {
|
|
926
|
-
if (!name) {
|
|
927
|
-
console.error('Observer name is required');
|
|
928
|
-
console.log('Usage: ilana make:observer <ObserverName> [--model=ModelName]');
|
|
929
|
-
process.exit(1);
|
|
930
|
-
}
|
|
931
|
-
|
|
932
|
-
let modelName = '';
|
|
933
|
-
|
|
934
|
-
for (const flag of flags) {
|
|
935
|
-
if (flag.startsWith('--model=')) {
|
|
936
|
-
modelName = flag.split('=')[1];
|
|
937
|
-
}
|
|
938
|
-
}
|
|
939
|
-
|
|
940
|
-
const className = toPascalCase(name.replace('Observer', ''));
|
|
941
|
-
const fileName = `${className}Observer${getFileExtension()}`;
|
|
942
|
-
const filePath = path.join(process.cwd(), 'observers', fileName);
|
|
943
|
-
|
|
944
|
-
if (!fs.existsSync(path.dirname(filePath))) {
|
|
945
|
-
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
946
|
-
}
|
|
947
|
-
|
|
948
|
-
const template = isTypeScriptProject() ?
|
|
949
|
-
`${modelName ? `import ${modelName} from '../models/${modelName}.js';\n\n` : ''}export default class ${className}Observer {
|
|
950
|
-
async creating(model: ${modelName || 'any'}): Promise<void> {}
|
|
951
|
-
async created(model: ${modelName || 'any'}): Promise<void> {}
|
|
952
|
-
async updating(model: ${modelName || 'any'}): Promise<void> {}
|
|
953
|
-
async updated(model: ${modelName || 'any'}): Promise<void> {}
|
|
954
|
-
async saving(model: ${modelName || 'any'}): Promise<void> {}
|
|
955
|
-
async saved(model: ${modelName || 'any'}): Promise<void> {}
|
|
956
|
-
async deleting(model: ${modelName || 'any'}): Promise<void> {}
|
|
957
|
-
async deleted(model: ${modelName || 'any'}): Promise<void> {}
|
|
958
|
-
}
|
|
959
|
-
` :
|
|
960
|
-
`${modelName ? `const ${modelName} = require('../models/${modelName}');\n\n` : ''}class ${className}Observer {
|
|
961
|
-
async creating(model) {}
|
|
962
|
-
async created(model) {}
|
|
963
|
-
async updating(model) {}
|
|
964
|
-
async updated(model) {}
|
|
965
|
-
async saving(model) {}
|
|
966
|
-
async saved(model) {}
|
|
967
|
-
async deleting(model) {}
|
|
968
|
-
async deleted(model) {}
|
|
969
|
-
}
|
|
970
|
-
|
|
971
|
-
module.exports = ${className}Observer;
|
|
972
|
-
`;
|
|
973
|
-
|
|
974
|
-
fs.writeFileSync(filePath, template);
|
|
975
|
-
console.log(`Created observer: observers/${fileName}`);
|
|
976
|
-
|
|
977
|
-
if (modelName) {
|
|
978
|
-
console.log(`Observer configured for model: ${modelName}`);
|
|
979
|
-
}
|
|
980
|
-
},
|
|
981
|
-
|
|
982
|
-
async 'make:cast'(name) {
|
|
983
|
-
if (!name) {
|
|
984
|
-
console.error('Cast name is required');
|
|
985
|
-
process.exit(1);
|
|
986
|
-
}
|
|
987
|
-
|
|
988
|
-
const className = toPascalCase(name.replace('Cast', ''));
|
|
989
|
-
const fileName = `${className}Cast${getFileExtension()}`;
|
|
990
|
-
const filePath = path.join(process.cwd(), 'casts', fileName);
|
|
991
|
-
|
|
992
|
-
if (!fs.existsSync(path.dirname(filePath))) {
|
|
993
|
-
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
994
|
-
}
|
|
995
|
-
|
|
996
|
-
const template = isTypeScriptProject() ?
|
|
997
|
-
`import { CustomCast } from 'ilana-orm/orm/Model.js';
|
|
998
|
-
|
|
999
|
-
export default class ${className}Cast implements CustomCast {
|
|
1000
|
-
get(value: any): any {
|
|
1001
|
-
return value;
|
|
1002
|
-
}
|
|
1003
|
-
|
|
1004
|
-
set(value: any): any {
|
|
1005
|
-
return value;
|
|
1006
|
-
}
|
|
1007
|
-
}
|
|
1008
|
-
` :
|
|
1009
|
-
`class ${className}Cast {
|
|
1010
|
-
get(value) {
|
|
1011
|
-
return value;
|
|
1012
|
-
}
|
|
1013
|
-
|
|
1014
|
-
set(value) {
|
|
1015
|
-
return value;
|
|
1016
|
-
}
|
|
1017
|
-
}
|
|
1018
|
-
|
|
1019
|
-
module.exports = ${className}Cast;
|
|
1020
|
-
`;
|
|
1021
|
-
|
|
1022
|
-
fs.writeFileSync(filePath, template);
|
|
1023
|
-
console.log(`Created cast: casts/${fileName}`);
|
|
1024
|
-
},
|
|
1025
|
-
|
|
1026
702
|
help() {
|
|
1027
703
|
console.log(`
|
|
1028
704
|
Ilana ORM CLI
|
|
@@ -1039,13 +715,6 @@ Available commands:
|
|
|
1039
715
|
-mfs Generate model + migration + factory + seeder
|
|
1040
716
|
|
|
1041
717
|
make:migration <name> Create a new migration file
|
|
1042
|
-
migrate [connection] Run all pending migrations
|
|
1043
|
-
migrate:rollback [steps] [connection] Rollback the last batch of migrations
|
|
1044
|
-
migrate:reset [connection] Rollback all migrations
|
|
1045
|
-
migrate:refresh [connection] Reset and re-run all migrations
|
|
1046
|
-
migrate:status [connection] Show migration status
|
|
1047
|
-
seed [name] Run database seeders
|
|
1048
|
-
db:seed [name] Alias for seed command
|
|
1049
718
|
help Show this help message
|
|
1050
719
|
|
|
1051
720
|
Examples:
|
|
@@ -1056,10 +725,6 @@ Examples:
|
|
|
1056
725
|
ilana make:model Permission --all
|
|
1057
726
|
ilana make:model UserPost --pivot
|
|
1058
727
|
ilana make:migration create_users_table
|
|
1059
|
-
ilana migrate
|
|
1060
|
-
ilana migrate mysql
|
|
1061
|
-
ilana migrate:rollback 2 postgres
|
|
1062
|
-
ilana seed UserSeeder
|
|
1063
728
|
`);
|
|
1064
729
|
}
|
|
1065
730
|
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// CustomCasts.mjs - ES Module wrapper
|
|
2
|
+
import { createRequire } from 'module';
|
|
3
|
+
const require = createRequire(import.meta.url);
|
|
4
|
+
|
|
5
|
+
const CustomCasts = require('./CustomCasts.js');
|
|
6
|
+
|
|
7
|
+
export const { MoneyCast, EncryptedCast, JsonCast, ArrayCast, DateCast } = CustomCasts;
|
package/orm/MigrationRunner.js
CHANGED
|
@@ -7,19 +7,27 @@ let config = {};
|
|
|
7
7
|
|
|
8
8
|
// Auto-load configuration on first import
|
|
9
9
|
(async function autoLoadConfig() {
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
const configPathJs = path.join(process.cwd(), 'ilana.config.js');
|
|
11
|
+
const configPathMjs = path.join(process.cwd(), 'ilana.config.mjs');
|
|
12
|
+
|
|
13
|
+
// Try .mjs first (ES modules)
|
|
14
|
+
if (fs.existsSync(configPathMjs)) {
|
|
15
|
+
try {
|
|
16
|
+
const configModule = await import(configPathMjs);
|
|
17
|
+
config = configModule.default || configModule;
|
|
18
|
+
} catch (error) {
|
|
19
|
+
console.error('Error loading ilana.config.mjs:', error.message);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
// Try .js (CommonJS)
|
|
23
|
+
else if (fs.existsSync(configPathJs)) {
|
|
24
|
+
delete require.cache[configPathJs];
|
|
13
25
|
try {
|
|
14
|
-
config = require(
|
|
26
|
+
config = require(configPathJs) || {};
|
|
15
27
|
} catch (error) {
|
|
16
28
|
if (error.code === 'ERR_REQUIRE_ESM') {
|
|
17
|
-
|
|
18
|
-
const configModule = await import(configPath);
|
|
29
|
+
const configModule = await import(configPathJs);
|
|
19
30
|
config = configModule.default || configModule;
|
|
20
|
-
if (typeof config.configure === 'function') {
|
|
21
|
-
config.configure(config);
|
|
22
|
-
}
|
|
23
31
|
} else {
|
|
24
32
|
throw error;
|
|
25
33
|
}
|
|
@@ -347,7 +355,7 @@ class MigrationRunner {
|
|
|
347
355
|
|
|
348
356
|
if (isCreate || name.includes('create_')) {
|
|
349
357
|
return isTS ?
|
|
350
|
-
`import SchemaBuilder from 'ilana-orm
|
|
358
|
+
`import type { SchemaBuilder } from 'ilana-orm';
|
|
351
359
|
|
|
352
360
|
export default class ${className} {
|
|
353
361
|
// connection = 'mysql'; // Uncomment to use specific connection
|
|
@@ -364,7 +372,7 @@ export default class ${className} {
|
|
|
364
372
|
}
|
|
365
373
|
}
|
|
366
374
|
` :
|
|
367
|
-
`const SchemaBuilder = require('ilana-orm
|
|
375
|
+
`const { SchemaBuilder } = require('ilana-orm');
|
|
368
376
|
|
|
369
377
|
class ${className} {
|
|
370
378
|
// connection = 'mysql'; // Uncomment to use specific connection
|
|
@@ -385,7 +393,7 @@ module.exports = ${className};
|
|
|
385
393
|
`;
|
|
386
394
|
} else if (tableName) {
|
|
387
395
|
return isTS ?
|
|
388
|
-
`import SchemaBuilder from 'ilana-orm
|
|
396
|
+
`import type { SchemaBuilder } from 'ilana-orm';
|
|
389
397
|
|
|
390
398
|
export default class ${className} {
|
|
391
399
|
// connection = 'mysql'; // Uncomment to use specific connection
|
|
@@ -405,7 +413,7 @@ export default class ${className} {
|
|
|
405
413
|
}
|
|
406
414
|
}
|
|
407
415
|
` :
|
|
408
|
-
`const SchemaBuilder = require('ilana-orm
|
|
416
|
+
`const { SchemaBuilder } = require('ilana-orm');
|
|
409
417
|
|
|
410
418
|
class ${className} {
|
|
411
419
|
// connection = 'mysql'; // Uncomment to use specific connection
|
|
@@ -430,7 +438,7 @@ module.exports = ${className};
|
|
|
430
438
|
}
|
|
431
439
|
|
|
432
440
|
return isTS ?
|
|
433
|
-
`import SchemaBuilder from 'ilana-orm
|
|
441
|
+
`import type { SchemaBuilder } from 'ilana-orm';
|
|
434
442
|
|
|
435
443
|
export default class ${className} {
|
|
436
444
|
// connection = 'mysql'; // Uncomment to use specific connection
|
|
@@ -444,7 +452,7 @@ export default class ${className} {
|
|
|
444
452
|
}
|
|
445
453
|
}
|
|
446
454
|
` :
|
|
447
|
-
`const SchemaBuilder = require('ilana-orm
|
|
455
|
+
`const { SchemaBuilder } = require('ilana-orm');
|
|
448
456
|
|
|
449
457
|
class ${className} {
|
|
450
458
|
// connection = 'mysql'; // Uncomment to use specific connection
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ilana-orm",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.9",
|
|
4
4
|
"description": "A fully-featured, Eloquent-style ORM for Node.js with TypeScript support",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -25,6 +25,11 @@
|
|
|
25
25
|
"require": "./orm/Collection.js",
|
|
26
26
|
"types": "./orm/Collection.d.ts"
|
|
27
27
|
},
|
|
28
|
+
"./orm/CustomCasts": {
|
|
29
|
+
"import": "./orm/CustomCasts.mjs",
|
|
30
|
+
"require": "./orm/CustomCasts.js",
|
|
31
|
+
"types": "./orm/CustomCasts.d.ts"
|
|
32
|
+
},
|
|
28
33
|
"./database/connection": {
|
|
29
34
|
"import": "./database/connection.mjs",
|
|
30
35
|
"require": "./database/connection.js",
|
|
@@ -105,4 +110,4 @@
|
|
|
105
110
|
"engines": {
|
|
106
111
|
"node": ">=16.0.0"
|
|
107
112
|
}
|
|
108
|
-
}
|
|
113
|
+
}
|