ilana-orm 1.0.5 → 1.0.8

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
@@ -150,10 +150,13 @@ touch ilana.config.js
150
150
 
151
151
  ### 2. Configure Database
152
152
 
153
- Create `ilana.config.js` in your project root:
153
+ **For CommonJS projects**, create `ilana.config.js` in your project root:
154
+
155
+ **For ES Module projects** (with `"type": "module"` in package.json), create `ilana.config.mjs`:
154
156
 
155
157
  ```javascript
156
- module.exports = {
158
+ // ilana.config.mjs
159
+ export default {
157
160
  default: "sqlite",
158
161
 
159
162
  connections: {
@@ -212,11 +215,18 @@ This creates:
212
215
 
213
216
  ### 4. Define the Model
214
217
 
215
- **JavaScript:**
218
+ **JavaScript (CommonJS):**
216
219
 
217
220
  ```javascript
218
221
  // models/User.js
219
222
  const Model = require("ilana-orm/orm/Model");
223
+ ```
224
+
225
+ **JavaScript (ES Modules):**
226
+
227
+ ```javascript
228
+ // models/User.js
229
+ import Model from "ilana-orm/orm/Model";
220
230
 
221
231
  class User extends Model {
222
232
  static table = "users";
@@ -246,7 +256,8 @@ class User extends Model {
246
256
  }
247
257
  }
248
258
 
249
- module.exports = User;
259
+ export default User; // For ES modules
260
+ // module.exports = User; // For CommonJS
250
261
  ```
251
262
 
252
263
  **TypeScript (auto-generated when `tsconfig.json` detected):**
@@ -294,8 +305,14 @@ npx ilana migrate
294
305
 
295
306
  ### 6. Start Using the Model
296
307
 
308
+ **CommonJS:**
297
309
  ```javascript
298
310
  const User = require("./models/User");
311
+ ```
312
+
313
+ **ES Modules:**
314
+ ```javascript
315
+ import User from "./models/User.js";
299
316
 
300
317
  // Create user
301
318
  const user = await User.create({
package/cli/ilana.js CHANGED
@@ -31,26 +31,39 @@ const defaultConfig = {
31
31
 
32
32
  // Load configuration and auto-initialize
33
33
  async function loadConfig() {
34
- const configPath = path.join(process.cwd(), 'ilana.config.js');
35
- if (fs.existsSync(configPath)) {
36
- delete require.cache[configPath];
34
+ const configPathJs = path.join(process.cwd(), 'ilana.config.js');
35
+ const configPathMjs = path.join(process.cwd(), 'ilana.config.mjs');
36
+
37
+ // Try .mjs first (ES modules)
38
+ if (fs.existsSync(configPathMjs)) {
39
+ try {
40
+ const configModule = await import(configPathMjs);
41
+ const config = configModule.default || configModule;
42
+ return config;
43
+ } catch (error) {
44
+ console.error('Error loading ilana.config.mjs:', error.message);
45
+ process.exit(1);
46
+ }
47
+ }
48
+
49
+ // Try .js (CommonJS)
50
+ if (fs.existsSync(configPathJs)) {
51
+ delete require.cache[configPathJs];
37
52
  try {
38
- const config = require(configPath);
39
- // Config file already initializes database
53
+ const config = require(configPathJs);
40
54
  return config;
41
55
  } catch (error) {
42
56
  if (error.code === 'ERR_REQUIRE_ESM') {
43
- // Handle ES modules
44
- const configModule = await import(configPath);
45
- const config = configModule.default || configModule;
46
- return config;
57
+ console.error('Found ilana.config.js but project uses ES modules. Rename to ilana.config.mjs');
58
+ process.exit(1);
47
59
  } else {
48
60
  throw error;
49
61
  }
50
62
  }
51
63
  }
52
- // No config file found - don't initialize with hardcoded default
53
- console.error('No ilana.config.js found. Run "npx ilana setup" first.');
64
+
65
+ // No config file found
66
+ console.error('No ilana.config.js or ilana.config.mjs found. Run "npx ilana setup" first.');
54
67
  process.exit(1);
55
68
  }
56
69
 
@@ -95,6 +108,122 @@ function pluralize(str) {
95
108
  return str + 's';
96
109
  }
97
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
+
98
227
  function generateModel(name, options = {}) {
99
228
  const className = toPascalCase(name);
100
229
  const tableName = pluralize(toSnakeCase(name));
@@ -130,9 +259,11 @@ function generateModel(name, options = {}) {
130
259
  }
131
260
 
132
261
  function getModelTemplate(className, tableName) {
262
+ const isESModule = isESModuleProject();
263
+
133
264
  if (isTypeScriptProject()) {
134
- return `import Model from 'ilana-orm/orm/Model.js';
135
- // import { MoneyCast, EncryptedCast } from 'ilana-orm/orm/CustomCasts.js';
265
+ return `import Model from 'ilana-orm/orm/Model';
266
+ // import { MoneyCast, EncryptedCast } from 'ilana-orm/orm/CustomCasts';
136
267
 
137
268
  export default class ${className} extends Model {
138
269
  protected static table = '${tableName}';
@@ -175,6 +306,53 @@ export default class ${className} extends Model {
175
306
  `;
176
307
  }
177
308
 
309
+ if (isESModule) {
310
+ return `import Model from 'ilana-orm/orm/Model';
311
+ // import { MoneyCast, EncryptedCast } from 'ilana-orm/orm/CustomCasts';
312
+
313
+ class ${className} extends Model {
314
+ static table = '${tableName}';
315
+ static timestamps = true;
316
+ static softDeletes = false;
317
+
318
+ // For UUID primary keys, uncomment:
319
+ // static keyType = 'string';
320
+ // static incrementing = false;
321
+
322
+ fillable = [];
323
+ hidden = [];
324
+ appends = [];
325
+ casts = {
326
+ // Basic casts
327
+ // is_active: 'boolean',
328
+ // metadata: 'json',
329
+ // tags: 'array',
330
+
331
+ // Custom casts
332
+ // price: new MoneyCast(),
333
+ // secret: new EncryptedCast('your-key'),
334
+ };
335
+
336
+ // Define relationships here
337
+ // example() {
338
+ // return this.hasMany(RelatedModel, 'foreign_key');
339
+ // }
340
+
341
+ // Define scopes here
342
+ // static scopeActive(query) {
343
+ // query.where('is_active', true);
344
+ // }
345
+
346
+ // Register for polymorphic relationships
347
+ // static {
348
+ // this.register();
349
+ // }
350
+ }
351
+
352
+ export default ${className};
353
+ `;
354
+ }
355
+
178
356
  return `const Model = require('ilana-orm/orm/Model');
179
357
  // const { MoneyCast, EncryptedCast } = require('ilana-orm/orm/CustomCasts');
180
358
 
@@ -222,8 +400,10 @@ module.exports = ${className};
222
400
  }
223
401
 
224
402
  function getPivotModelTemplate(className, tableName) {
403
+ const isESModule = isESModuleProject();
404
+
225
405
  if (isTypeScriptProject()) {
226
- return `import Model from 'ilana-orm/orm/Model.js';
406
+ return `import Model from 'ilana-orm/orm/Model';
227
407
 
228
408
  export default class ${className} extends Model {
229
409
  protected static table = '${tableName}';
@@ -236,6 +416,22 @@ export default class ${className} extends Model {
236
416
  `;
237
417
  }
238
418
 
419
+ if (isESModule) {
420
+ return `import Model from 'ilana-orm/orm/Model';
421
+
422
+ class ${className} extends Model {
423
+ static table = '${tableName}';
424
+ static timestamps = true;
425
+
426
+ fillable = [];
427
+
428
+ // Define pivot relationships here
429
+ }
430
+
431
+ export default ${className};
432
+ `;
433
+ }
434
+
239
435
  return `const Model = require('ilana-orm/orm/Model');
240
436
 
241
437
  class ${className} extends Model {
@@ -350,126 +546,11 @@ const commands = {
350
546
  }
351
547
 
352
548
  // Create config file if it doesn't exist
353
- const configPath = 'ilana.config.js';
549
+ const isESModule = isESModuleProject();
550
+ const configPath = isESModule ? 'ilana.config.mjs' : 'ilana.config.js';
551
+
354
552
  if (!fs.existsSync(configPath)) {
355
- const isESModule = isESModuleProject();
356
553
  const configTemplate = isESModule ? getESModuleConfigTemplate() : getCommonJSConfigTemplate();
357
-
358
- function getESModuleConfigTemplate() {
359
- return `import 'dotenv/config';
360
- import Database from 'ilana-orm/database/connection.js';
361
-
362
- const config = {
363
- default: process.env.DB_CONNECTION || 'mysql',
364
- timezone: process.env.DB_TIMEZONE || 'UTC',
365
-
366
- connections: {
367
- sqlite: {
368
- client: 'sqlite3',
369
- connection: {
370
- filename: process.env.DB_FILENAME || './database.sqlite'
371
- },
372
- useNullAsDefault: true
373
- },
374
-
375
- mysql: {
376
- client: 'mysql2',
377
- connection: {
378
- host: process.env.DB_HOST || 'localhost',
379
- port: process.env.DB_PORT || 3306,
380
- user: process.env.DB_USERNAME || 'root',
381
- password: process.env.DB_PASSWORD || '',
382
- database: process.env.DB_DATABASE || 'your_database',
383
- timezone: process.env.DB_TIMEZONE || 'UTC'
384
- }
385
- },
386
-
387
- postgres: {
388
- client: 'pg',
389
- connection: {
390
- host: process.env.DB_HOST || 'localhost',
391
- port: process.env.DB_PORT || 5432,
392
- user: process.env.DB_USERNAME || 'postgres',
393
- password: process.env.DB_PASSWORD || '',
394
- database: process.env.DB_DATABASE || 'your_database'
395
- }
396
- }
397
- },
398
-
399
- migrations: {
400
- directory: './database/migrations',
401
- tableName: 'migrations'
402
- },
403
-
404
- seeds: {
405
- directory: './database/seeds'
406
- }
407
- };
408
-
409
- // Auto-initialize database connections
410
- Database.configure(config);
411
-
412
- export default config;
413
- `;
414
- }
415
-
416
- function getCommonJSConfigTemplate() {
417
- return `require('dotenv').config();
418
- const Database = require('ilana-orm/database/connection');
419
-
420
- const config = {
421
- default: process.env.DB_CONNECTION || 'mysql',
422
- timezone: process.env.DB_TIMEZONE || 'UTC',
423
-
424
- connections: {
425
- sqlite: {
426
- client: 'sqlite3',
427
- connection: {
428
- filename: process.env.DB_FILENAME || './database.sqlite'
429
- },
430
- useNullAsDefault: true
431
- },
432
-
433
- mysql: {
434
- client: 'mysql2',
435
- connection: {
436
- host: process.env.DB_HOST || 'localhost',
437
- port: process.env.DB_PORT || 3306,
438
- user: process.env.DB_USERNAME || 'root',
439
- password: process.env.DB_PASSWORD || '',
440
- database: process.env.DB_DATABASE || 'your_database',
441
- timezone: process.env.DB_TIMEZONE || 'UTC'
442
- }
443
- },
444
-
445
- postgres: {
446
- client: 'pg',
447
- connection: {
448
- host: process.env.DB_HOST || 'localhost',
449
- port: process.env.DB_PORT || 5432,
450
- user: process.env.DB_USERNAME || 'postgres',
451
- password: process.env.DB_PASSWORD || '',
452
- database: process.env.DB_DATABASE || 'your_database'
453
- }
454
- }
455
- },
456
-
457
- migrations: {
458
- directory: './database/migrations',
459
- tableName: 'migrations'
460
- },
461
-
462
- seeds: {
463
- directory: './database/seeds'
464
- }
465
- };
466
-
467
- // Auto-initialize database connections
468
- Database.configure(config);
469
-
470
- module.exports = config;
471
- `;
472
- }
473
554
  fs.writeFileSync(configPath, configTemplate);
474
555
  console.log(`Created config file: ${configPath}`);
475
556
  }
@@ -517,6 +598,7 @@ DB_TIMEZONE=UTC
517
598
  console.log('2. Run: ilana make:model User -m');
518
599
  console.log('3. Run: ilana migrate');
519
600
  },
601
+
520
602
  async 'make:migration'(name, ...flags) {
521
603
  if (!name) {
522
604
  console.error('Migration name is required');
@@ -617,329 +699,6 @@ DB_TIMEZONE=UTC
617
699
  generateModel(name, options);
618
700
  },
619
701
 
620
- async migrate(...args) {
621
- await initializeDatabase();
622
- const runner = new MigrationRunner();
623
-
624
- let connection;
625
- let onlyFile;
626
- let toFile;
627
-
628
- for (let i = 0; i < args.length; i++) {
629
- const arg = args[i];
630
- if (arg === '--connection' && args[i + 1]) {
631
- connection = args[i + 1];
632
- i++;
633
- } else if (arg.startsWith('--connection=')) {
634
- connection = arg.split('=')[1];
635
- } else if (arg === '--only' && args[i + 1]) {
636
- onlyFile = args[i + 1];
637
- i++;
638
- } else if (arg.startsWith('--only=')) {
639
- onlyFile = arg.split('=')[1];
640
- } else if (arg === '--to' && args[i + 1]) {
641
- toFile = args[i + 1];
642
- i++;
643
- } else if (arg.startsWith('--to=')) {
644
- toFile = arg.split('=')[1];
645
- } else if (!arg.startsWith('--')) {
646
- connection = arg;
647
- }
648
- }
649
-
650
- await runner.migrate(connection, onlyFile, toFile);
651
- process.exit(0);
652
- },
653
-
654
- async 'migrate:fresh'(...args) {
655
- await initializeDatabase();
656
- const runner = new MigrationRunner();
657
-
658
- let connection;
659
- let withSeed = false;
660
-
661
- for (const arg of args) {
662
- if (arg === '--seed') {
663
- withSeed = true;
664
- } else if (arg.startsWith('--connection=')) {
665
- connection = arg.split('=')[1];
666
- } else if (!arg.startsWith('--')) {
667
- connection = arg;
668
- }
669
- }
670
-
671
- await runner.fresh(connection);
672
-
673
- if (withSeed) {
674
- await commands.seed();
675
- }
676
-
677
- process.exit(0);
678
- },
679
-
680
- async 'migrate:list'(connection) {
681
- await initializeDatabase();
682
- const runner = new MigrationRunner();
683
- await runner.list(connection);
684
- process.exit(0);
685
- },
686
-
687
- async 'migrate:unlock'(connection) {
688
- await initializeDatabase();
689
- const runner = new MigrationRunner();
690
- await runner.unlock(connection);
691
- process.exit(0);
692
- },
693
-
694
- async 'migrate:rollback'(...args) {
695
- await initializeDatabase();
696
- const runner = new MigrationRunner();
697
-
698
- let steps = 1;
699
- let connection;
700
- let toFile;
701
-
702
- for (let i = 0; i < args.length; i++) {
703
- const arg = args[i];
704
- if (arg === '--step' && args[i + 1]) {
705
- steps = parseInt(args[i + 1]);
706
- i++;
707
- } else if (arg.startsWith('--step=')) {
708
- steps = parseInt(arg.split('=')[1]);
709
- } else if (arg === '--connection' && args[i + 1]) {
710
- connection = args[i + 1];
711
- i++;
712
- } else if (arg.startsWith('--connection=')) {
713
- connection = arg.split('=')[1];
714
- } else if (arg === '--to' && args[i + 1]) {
715
- toFile = args[i + 1];
716
- i++;
717
- } else if (arg.startsWith('--to=')) {
718
- toFile = arg.split('=')[1];
719
- } else if (!isNaN(parseInt(arg))) {
720
- steps = parseInt(arg);
721
- } else if (!arg.startsWith('--')) {
722
- connection = arg;
723
- }
724
- }
725
-
726
- await runner.rollback(steps, connection, toFile);
727
- process.exit(0);
728
- },
729
-
730
- async 'migrate:reset'(connection) {
731
- await initializeDatabase();
732
- const runner = new MigrationRunner();
733
- await runner.reset(connection);
734
- process.exit(0);
735
- },
736
-
737
- async 'migrate:refresh'(connection) {
738
- await initializeDatabase();
739
- const runner = new MigrationRunner();
740
- await runner.refresh(connection);
741
- process.exit(0);
742
- },
743
-
744
- async 'migrate:status'(connection) {
745
- await initializeDatabase();
746
- const runner = new MigrationRunner();
747
- await runner.status(connection);
748
- process.exit(0);
749
- },
750
-
751
- async seed(...args) {
752
- await initializeDatabase();
753
-
754
- let seederName;
755
- let connection;
756
-
757
- for (let i = 0; i < args.length; i++) {
758
- const arg = args[i];
759
- if (arg === '--class' && args[i + 1]) {
760
- seederName = args[i + 1];
761
- i++;
762
- } else if (arg.startsWith('--class=')) {
763
- seederName = arg.split('=')[1];
764
- } else if (arg === '--connection' && args[i + 1]) {
765
- connection = args[i + 1];
766
- i++;
767
- } else if (arg.startsWith('--connection=')) {
768
- connection = arg.split('=')[1];
769
- } else if (!arg.startsWith('--')) {
770
- if (!seederName) seederName = arg;
771
- else connection = arg;
772
- }
773
- }
774
-
775
- const seedsPath = path.join(process.cwd(), 'database/seeds');
776
- if (!fs.existsSync(seedsPath)) {
777
- console.log('No seeds directory found');
778
- process.exit(0);
779
- }
780
-
781
- const seedFiles = fs.readdirSync(seedsPath)
782
- .filter(file => file.endsWith('.ts') || file.endsWith('.js'))
783
- .sort();
784
-
785
- if (seedFiles.length === 0) {
786
- console.log('No seed files found');
787
- process.exit(0);
788
- }
789
-
790
- const filesToRun = seederName
791
- ? seedFiles.filter(file => file.includes(seederName))
792
- : seedFiles;
793
-
794
- console.log(`Running ${filesToRun.length} seeders...`);
795
-
796
- for (const file of filesToRun) {
797
- console.log(`Seeding: ${file}`);
798
- const filepath = path.join(seedsPath, file);
799
- delete require.cache[filepath];
800
-
801
- let seederModule;
802
- try {
803
- seederModule = require(filepath);
804
- } catch (error) {
805
- if (error.code === 'ERR_REQUIRE_ESM') {
806
- // Handle ES modules
807
- seederModule = await import(filepath);
808
- } else {
809
- throw error;
810
- }
811
- }
812
-
813
- const SeederClass = seederModule.default || seederModule;
814
- const seeder = new SeederClass();
815
-
816
- if (connection) {
817
- seeder.connection = connection;
818
- }
819
-
820
- if (typeof seeder.run === 'function') {
821
- await seeder.run();
822
- }
823
-
824
- console.log(`Seeded: ${file}`);
825
- }
826
-
827
- console.log('Seeding completed');
828
- process.exit(0);
829
- },
830
-
831
- async 'db:seed'(seederName) {
832
- return commands.seed(seederName);
833
- },
834
-
835
- async 'db:wipe'(connection) {
836
- await initializeDatabase();
837
- const runner = new MigrationRunner();
838
- await runner.wipe(connection);
839
- process.exit(0);
840
- },
841
-
842
- async 'make:observer'(name, ...flags) {
843
- if (!name) {
844
- console.error('Observer name is required');
845
- console.log('Usage: ilana make:observer <ObserverName> [--model=ModelName]');
846
- process.exit(1);
847
- }
848
-
849
- let modelName = '';
850
-
851
- for (const flag of flags) {
852
- if (flag.startsWith('--model=')) {
853
- modelName = flag.split('=')[1];
854
- }
855
- }
856
-
857
- const className = toPascalCase(name.replace('Observer', ''));
858
- const fileName = `${className}Observer${getFileExtension()}`;
859
- const filePath = path.join(process.cwd(), 'observers', fileName);
860
-
861
- if (!fs.existsSync(path.dirname(filePath))) {
862
- fs.mkdirSync(path.dirname(filePath), { recursive: true });
863
- }
864
-
865
- const template = isTypeScriptProject() ?
866
- `${modelName ? `import ${modelName} from '../models/${modelName}.js';\n\n` : ''}export default class ${className}Observer {
867
- async creating(model: ${modelName || 'any'}): Promise<void> {}
868
- async created(model: ${modelName || 'any'}): Promise<void> {}
869
- async updating(model: ${modelName || 'any'}): Promise<void> {}
870
- async updated(model: ${modelName || 'any'}): Promise<void> {}
871
- async saving(model: ${modelName || 'any'}): Promise<void> {}
872
- async saved(model: ${modelName || 'any'}): Promise<void> {}
873
- async deleting(model: ${modelName || 'any'}): Promise<void> {}
874
- async deleted(model: ${modelName || 'any'}): Promise<void> {}
875
- }
876
- ` :
877
- `${modelName ? `const ${modelName} = require('../models/${modelName}');\n\n` : ''}class ${className}Observer {
878
- async creating(model) {}
879
- async created(model) {}
880
- async updating(model) {}
881
- async updated(model) {}
882
- async saving(model) {}
883
- async saved(model) {}
884
- async deleting(model) {}
885
- async deleted(model) {}
886
- }
887
-
888
- module.exports = ${className}Observer;
889
- `;
890
-
891
- fs.writeFileSync(filePath, template);
892
- console.log(`Created observer: observers/${fileName}`);
893
-
894
- if (modelName) {
895
- console.log(`Observer configured for model: ${modelName}`);
896
- }
897
- },
898
-
899
- async 'make:cast'(name) {
900
- if (!name) {
901
- console.error('Cast name is required');
902
- process.exit(1);
903
- }
904
-
905
- const className = toPascalCase(name.replace('Cast', ''));
906
- const fileName = `${className}Cast${getFileExtension()}`;
907
- const filePath = path.join(process.cwd(), 'casts', fileName);
908
-
909
- if (!fs.existsSync(path.dirname(filePath))) {
910
- fs.mkdirSync(path.dirname(filePath), { recursive: true });
911
- }
912
-
913
- const template = isTypeScriptProject() ?
914
- `import { CustomCast } from 'ilana-orm/orm/Model.js';
915
-
916
- export default class ${className}Cast implements CustomCast {
917
- get(value: any): any {
918
- return value;
919
- }
920
-
921
- set(value: any): any {
922
- return value;
923
- }
924
- }
925
- ` :
926
- `class ${className}Cast {
927
- get(value) {
928
- return value;
929
- }
930
-
931
- set(value) {
932
- return value;
933
- }
934
- }
935
-
936
- module.exports = ${className}Cast;
937
- `;
938
-
939
- fs.writeFileSync(filePath, template);
940
- console.log(`Created cast: casts/${fileName}`);
941
- },
942
-
943
702
  help() {
944
703
  console.log(`
945
704
  Ilana ORM CLI
@@ -956,13 +715,6 @@ Available commands:
956
715
  -mfs Generate model + migration + factory + seeder
957
716
 
958
717
  make:migration <name> Create a new migration file
959
- migrate [connection] Run all pending migrations
960
- migrate:rollback [steps] [connection] Rollback the last batch of migrations
961
- migrate:reset [connection] Rollback all migrations
962
- migrate:refresh [connection] Reset and re-run all migrations
963
- migrate:status [connection] Show migration status
964
- seed [name] Run database seeders
965
- db:seed [name] Alias for seed command
966
718
  help Show this help message
967
719
 
968
720
  Examples:
@@ -973,10 +725,6 @@ Examples:
973
725
  ilana make:model Permission --all
974
726
  ilana make:model UserPost --pivot
975
727
  ilana make:migration create_users_table
976
- ilana migrate
977
- ilana migrate mysql
978
- ilana migrate:rollback 2 postgres
979
- ilana seed UserSeeder
980
728
  `);
981
729
  }
982
730
  };
@@ -0,0 +1,7 @@
1
+ // connection.mjs - ES Module wrapper
2
+ import { createRequire } from 'module';
3
+ const require = createRequire(import.meta.url);
4
+
5
+ const Database = require('./connection.js');
6
+
7
+ export default Database;
@@ -0,0 +1,44 @@
1
+ // ilana.config.mjs - ES Module config example
2
+ export default {
3
+ default: "sqlite",
4
+
5
+ connections: {
6
+ sqlite: {
7
+ client: "sqlite3",
8
+ connection: {
9
+ filename: "./database.sqlite",
10
+ },
11
+ },
12
+
13
+ mysql: {
14
+ client: "mysql2",
15
+ connection: {
16
+ host: "localhost",
17
+ port: 3306,
18
+ user: "your_username",
19
+ password: "your_password",
20
+ database: "your_database",
21
+ },
22
+ },
23
+
24
+ postgres: {
25
+ client: "pg",
26
+ connection: {
27
+ host: "localhost",
28
+ port: 5432,
29
+ user: "your_username",
30
+ password: "your_password",
31
+ database: "your_database",
32
+ },
33
+ },
34
+ },
35
+
36
+ migrations: {
37
+ directory: "./migrations",
38
+ tableName: "migrations",
39
+ },
40
+
41
+ seeds: {
42
+ directory: "./seeds",
43
+ },
44
+ };
package/index.mjs ADDED
@@ -0,0 +1,33 @@
1
+ // index.mjs - ES Module wrapper
2
+ import { createRequire } from 'module';
3
+ const require = createRequire(import.meta.url);
4
+
5
+ const exports = require('./index.js');
6
+
7
+ export const {
8
+ Model,
9
+ QueryBuilder,
10
+ Collection,
11
+ Database,
12
+ DB,
13
+ SchemaBuilder,
14
+ MigrationRunner,
15
+ Seeder,
16
+ Factory,
17
+ defineFactory,
18
+ Relation,
19
+ HasOne,
20
+ HasMany,
21
+ BelongsTo,
22
+ BelongsToMany,
23
+ HasManyThrough,
24
+ MorphTo,
25
+ MorphMany,
26
+ MoneyCast,
27
+ EncryptedCast,
28
+ JsonCast,
29
+ ArrayCast,
30
+ DateCast
31
+ } = exports;
32
+
33
+ export default exports.Model;
@@ -0,0 +1,7 @@
1
+ // Collection.mjs - ES Module wrapper
2
+ import { createRequire } from 'module';
3
+ const require = createRequire(import.meta.url);
4
+
5
+ const Collection = require('./Collection.js');
6
+
7
+ export default Collection;
package/orm/Model.js CHANGED
@@ -8,10 +8,14 @@ const Database = require('../database/connection');
8
8
  (function autoLoadConfig() {
9
9
  const fs = require('fs');
10
10
  const path = require('path');
11
- const configPath = path.join(process.cwd(), 'ilana.config.js');
12
- if (fs.existsSync(configPath)) {
13
- delete require.cache[configPath];
14
- require(configPath);
11
+ const configPathJs = path.join(process.cwd(), 'ilana.config.js');
12
+ const configPathMjs = path.join(process.cwd(), 'ilana.config.mjs');
13
+
14
+ if (fs.existsSync(configPathJs)) {
15
+ delete require.cache[configPathJs];
16
+ require(configPathJs);
17
+ } else if (fs.existsSync(configPathMjs)) {
18
+ // For ES modules, we'll handle this in the _getConfig method
15
19
  }
16
20
  })();
17
21
 
@@ -371,9 +375,19 @@ class Model {
371
375
  _getConfig() {
372
376
  try {
373
377
  const path = require('path');
374
- const configPath = path.join(process.cwd(), 'ilana.config.js');
375
- delete require.cache[configPath];
376
- return require(configPath);
378
+ const fs = require('fs');
379
+ const configPathJs = path.join(process.cwd(), 'ilana.config.js');
380
+ const configPathMjs = path.join(process.cwd(), 'ilana.config.mjs');
381
+
382
+ if (fs.existsSync(configPathJs)) {
383
+ delete require.cache[configPathJs];
384
+ return require(configPathJs);
385
+ } else if (fs.existsSync(configPathMjs)) {
386
+ // For ES modules, return a promise or handle async import
387
+ // For now, return null and let the caller handle it
388
+ return null;
389
+ }
390
+ return null;
377
391
  } catch (e) {
378
392
  return null;
379
393
  }
package/orm/Model.mjs ADDED
@@ -0,0 +1,7 @@
1
+ // Model.mjs - ES Module wrapper
2
+ import { createRequire } from 'module';
3
+ const require = createRequire(import.meta.url);
4
+
5
+ const Model = require('./Model.js');
6
+
7
+ export default Model;
@@ -0,0 +1,7 @@
1
+ // ModelRegistry.mjs - ES Module wrapper
2
+ import { createRequire } from 'module';
3
+ const require = createRequire(import.meta.url);
4
+
5
+ const ModelRegistry = require('./ModelRegistry.js');
6
+
7
+ export default ModelRegistry;
@@ -0,0 +1,7 @@
1
+ // QueryBuilder.mjs - ES Module wrapper
2
+ import { createRequire } from 'module';
3
+ const require = createRequire(import.meta.url);
4
+
5
+ const QueryBuilder = require('./QueryBuilder.js');
6
+
7
+ export default QueryBuilder;
@@ -0,0 +1,7 @@
1
+ // Relation.mjs - ES Module wrapper
2
+ import { createRequire } from 'module';
3
+ const require = createRequire(import.meta.url);
4
+
5
+ const Relations = require('./Relation.js');
6
+
7
+ export const { Relation, HasOne, HasMany, BelongsTo, BelongsToMany, HasManyThrough, MorphTo, MorphMany } = Relations;
package/package.json CHANGED
@@ -1,9 +1,36 @@
1
1
  {
2
2
  "name": "ilana-orm",
3
- "version": "1.0.5",
3
+ "version": "1.0.8",
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",
7
+ "exports": {
8
+ ".": {
9
+ "import": "./index.mjs",
10
+ "require": "./index.js",
11
+ "types": "./index.d.ts"
12
+ },
13
+ "./orm/Model": {
14
+ "import": "./orm/Model.mjs",
15
+ "require": "./orm/Model.js",
16
+ "types": "./orm/Model.d.ts"
17
+ },
18
+ "./orm/QueryBuilder": {
19
+ "import": "./orm/QueryBuilder.mjs",
20
+ "require": "./orm/QueryBuilder.js",
21
+ "types": "./orm/QueryBuilder.d.ts"
22
+ },
23
+ "./orm/Collection": {
24
+ "import": "./orm/Collection.mjs",
25
+ "require": "./orm/Collection.js",
26
+ "types": "./orm/Collection.d.ts"
27
+ },
28
+ "./database/connection": {
29
+ "import": "./database/connection.mjs",
30
+ "require": "./database/connection.js",
31
+ "types": "./database/connection.d.ts"
32
+ }
33
+ },
7
34
  "bin": {
8
35
  "ilana": "cli/ilana.js"
9
36
  },
@@ -39,11 +66,14 @@
39
66
  },
40
67
  "files": [
41
68
  "*.js",
69
+ "*.mjs",
42
70
  "*.d.ts",
43
71
  "cli/**/*.js",
44
72
  "database/**/*.js",
73
+ "database/**/*.mjs",
45
74
  "database/**/*.d.ts",
46
75
  "orm/**/*.js",
76
+ "orm/**/*.mjs",
47
77
  "orm/**/*.d.ts",
48
78
  "README.md",
49
79
  "LICENSE",