ilana-orm 1.0.12 → 1.0.14
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 +57 -30
- package/database/DB.mjs +169 -0
- package/database/schema-builder.mjs +219 -0
- package/orm/Factory.mjs +198 -0
- package/orm/Seeder.mjs +153 -0
- package/package.json +5 -1
package/cli/ilana.js
CHANGED
|
@@ -90,6 +90,17 @@ function isESModuleProject() {
|
|
|
90
90
|
return false;
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
+
function getProjectStructure() {
|
|
94
|
+
const hasSrc = fs.existsSync(path.join(process.cwd(), 'src'));
|
|
95
|
+
return {
|
|
96
|
+
hasSrc,
|
|
97
|
+
modelsDir: hasSrc ? 'src/models' : 'models',
|
|
98
|
+
databaseDir: hasSrc ? 'src/database' : 'database',
|
|
99
|
+
observersDir: hasSrc ? 'src/observers' : 'observers',
|
|
100
|
+
castsDir: hasSrc ? 'src/casts' : 'casts'
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
93
104
|
function getFileExtension() {
|
|
94
105
|
return isTypeScriptProject() ? '.ts' : '.js';
|
|
95
106
|
}
|
|
@@ -109,8 +120,9 @@ function pluralize(str) {
|
|
|
109
120
|
}
|
|
110
121
|
|
|
111
122
|
function getESModuleConfigTemplate() {
|
|
123
|
+
const structure = getProjectStructure();
|
|
112
124
|
return `import 'dotenv/config';
|
|
113
|
-
import Database from 'ilana-orm/database/connection';
|
|
125
|
+
import Database from 'ilana-orm/database/connection.js';
|
|
114
126
|
|
|
115
127
|
const config = {
|
|
116
128
|
default: process.env.DB_CONNECTION || 'mysql',
|
|
@@ -150,12 +162,12 @@ const config = {
|
|
|
150
162
|
},
|
|
151
163
|
|
|
152
164
|
migrations: {
|
|
153
|
-
directory: '
|
|
165
|
+
directory: './${structure.databaseDir}/migrations',
|
|
154
166
|
tableName: 'migrations'
|
|
155
167
|
},
|
|
156
168
|
|
|
157
169
|
seeds: {
|
|
158
|
-
directory: '
|
|
170
|
+
directory: './${structure.databaseDir}/seeds'
|
|
159
171
|
}
|
|
160
172
|
};
|
|
161
173
|
|
|
@@ -167,6 +179,7 @@ export default config;
|
|
|
167
179
|
}
|
|
168
180
|
|
|
169
181
|
function getCommonJSConfigTemplate() {
|
|
182
|
+
const structure = getProjectStructure();
|
|
170
183
|
return `require('dotenv').config();
|
|
171
184
|
const Database = require('ilana-orm/database/connection');
|
|
172
185
|
|
|
@@ -208,12 +221,12 @@ const config = {
|
|
|
208
221
|
},
|
|
209
222
|
|
|
210
223
|
migrations: {
|
|
211
|
-
directory: '
|
|
224
|
+
directory: './${structure.databaseDir}/migrations',
|
|
212
225
|
tableName: 'migrations'
|
|
213
226
|
},
|
|
214
227
|
|
|
215
228
|
seeds: {
|
|
216
|
-
directory: '
|
|
229
|
+
directory: './${structure.databaseDir}/seeds'
|
|
217
230
|
}
|
|
218
231
|
};
|
|
219
232
|
|
|
@@ -228,7 +241,8 @@ function generateModel(name, options = {}) {
|
|
|
228
241
|
const className = toPascalCase(name);
|
|
229
242
|
const tableName = pluralize(toSnakeCase(name));
|
|
230
243
|
const fileName = `${className}${getFileExtension()}`;
|
|
231
|
-
const
|
|
244
|
+
const structure = getProjectStructure();
|
|
245
|
+
const filePath = path.join(process.cwd(), structure.modelsDir, fileName);
|
|
232
246
|
|
|
233
247
|
if (fs.existsSync(filePath)) {
|
|
234
248
|
console.error(`Model ${className} already exists at models/${fileName}`);
|
|
@@ -241,7 +255,7 @@ function generateModel(name, options = {}) {
|
|
|
241
255
|
|
|
242
256
|
const template = options.pivot ? getPivotModelTemplate(className, tableName) : getModelTemplate(className, tableName);
|
|
243
257
|
fs.writeFileSync(filePath, template);
|
|
244
|
-
console.log(`Created model:
|
|
258
|
+
console.log(`Created model: ${structure.modelsDir}/${fileName}`);
|
|
245
259
|
|
|
246
260
|
if (options.migration || options.all) {
|
|
247
261
|
const migrationName = `create_${tableName}_table`;
|
|
@@ -449,15 +463,17 @@ module.exports = ${className};
|
|
|
449
463
|
|
|
450
464
|
function generateFactory(className) {
|
|
451
465
|
const fileName = `${className}Factory${getFileExtension()}`;
|
|
452
|
-
const
|
|
466
|
+
const structure = getProjectStructure();
|
|
467
|
+
const filePath = path.join(process.cwd(), structure.databaseDir, 'factories', fileName);
|
|
453
468
|
|
|
454
469
|
if (!fs.existsSync(path.dirname(filePath))) {
|
|
455
470
|
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
456
471
|
}
|
|
457
472
|
|
|
473
|
+
const modelPath = structure.hasSrc ? `../models/${className}.js` : `../../models/${className}.js`;
|
|
458
474
|
const template = isTypeScriptProject() ?
|
|
459
475
|
`import { defineFactory } from 'ilana-orm/orm/Factory.js';
|
|
460
|
-
import ${className} from '
|
|
476
|
+
import ${className} from '${modelPath}';
|
|
461
477
|
|
|
462
478
|
export default defineFactory(${className}, (faker) => ({
|
|
463
479
|
// Define your factory attributes here
|
|
@@ -469,7 +485,7 @@ export default defineFactory(${className}, (faker) => ({
|
|
|
469
485
|
}));
|
|
470
486
|
` :
|
|
471
487
|
`const { defineFactory } = require('ilana-orm/orm/Factory');
|
|
472
|
-
const ${className} = require('
|
|
488
|
+
const ${className} = require('${modelPath.replace('.js', '')}');
|
|
473
489
|
|
|
474
490
|
module.exports = defineFactory(${className}, (faker) => ({
|
|
475
491
|
// Define your factory attributes here
|
|
@@ -482,20 +498,22 @@ module.exports = defineFactory(${className}, (faker) => ({
|
|
|
482
498
|
`;
|
|
483
499
|
|
|
484
500
|
fs.writeFileSync(filePath, template);
|
|
485
|
-
console.log(`Created factory: factories/${fileName}`);
|
|
501
|
+
console.log(`Created factory: ${structure.databaseDir}/factories/${fileName}`);
|
|
486
502
|
}
|
|
487
503
|
|
|
488
504
|
function generateSeeder(className) {
|
|
489
505
|
const fileName = `${className}Seeder${getFileExtension()}`;
|
|
490
|
-
const
|
|
506
|
+
const structure = getProjectStructure();
|
|
507
|
+
const filePath = path.join(process.cwd(), structure.databaseDir, 'seeds', fileName);
|
|
491
508
|
|
|
492
509
|
if (!fs.existsSync(path.dirname(filePath))) {
|
|
493
510
|
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
494
511
|
}
|
|
495
512
|
|
|
513
|
+
const modelPath = structure.hasSrc ? `../models/${className}.js` : `../../models/${className}.js`;
|
|
496
514
|
const template = isTypeScriptProject() ?
|
|
497
515
|
`import Seeder from 'ilana-orm/orm/Seeder.js';
|
|
498
|
-
import ${className} from '
|
|
516
|
+
import ${className} from '${modelPath}';
|
|
499
517
|
import '../factories/${className}Factory.js';
|
|
500
518
|
|
|
501
519
|
export default class ${className}Seeder extends Seeder {
|
|
@@ -510,7 +528,7 @@ export default class ${className}Seeder extends Seeder {
|
|
|
510
528
|
}
|
|
511
529
|
` :
|
|
512
530
|
`const Seeder = require('ilana-orm/orm/Seeder');
|
|
513
|
-
const ${className} = require('
|
|
531
|
+
const ${className} = require('${modelPath.replace('.js', '')}');
|
|
514
532
|
require('../factories/${className}Factory');
|
|
515
533
|
|
|
516
534
|
class ${className}Seeder extends Seeder {
|
|
@@ -528,16 +546,16 @@ module.exports = ${className}Seeder;
|
|
|
528
546
|
`;
|
|
529
547
|
|
|
530
548
|
fs.writeFileSync(filePath, template);
|
|
531
|
-
console.log(`Created seeder: seeds/${fileName}`);
|
|
549
|
+
console.log(`Created seeder: ${structure.databaseDir}/seeds/${fileName}`);
|
|
532
550
|
}
|
|
533
551
|
|
|
534
552
|
function getObserverTemplate(className, modelName) {
|
|
535
553
|
const isESModule = isESModuleProject();
|
|
536
|
-
|
|
554
|
+
|
|
537
555
|
if (isTypeScriptProject()) {
|
|
538
556
|
const importStatement = modelName ? `import ${modelName} from '../models/${modelName}.js';\n\n` : '';
|
|
539
557
|
const modelType = modelName || 'any';
|
|
540
|
-
|
|
558
|
+
|
|
541
559
|
return `${importStatement}export default class ${className}Observer {
|
|
542
560
|
async creating(model: ${modelType}): Promise<void> {
|
|
543
561
|
// Logic before creating model
|
|
@@ -581,10 +599,10 @@ function getObserverTemplate(className, modelName) {
|
|
|
581
599
|
}
|
|
582
600
|
`;
|
|
583
601
|
}
|
|
584
|
-
|
|
602
|
+
|
|
585
603
|
if (isESModule) {
|
|
586
604
|
const importStatement = modelName ? `import ${modelName} from '../models/${modelName}.js';\n\n` : '';
|
|
587
|
-
|
|
605
|
+
|
|
588
606
|
return `${importStatement}class ${className}Observer {
|
|
589
607
|
async creating(model) {
|
|
590
608
|
// Logic before creating model
|
|
@@ -630,9 +648,9 @@ function getObserverTemplate(className, modelName) {
|
|
|
630
648
|
export default ${className}Observer;
|
|
631
649
|
`;
|
|
632
650
|
}
|
|
633
|
-
|
|
651
|
+
|
|
634
652
|
const importStatement = modelName ? `const ${modelName} = require('../models/${modelName}');\n\n` : '';
|
|
635
|
-
|
|
653
|
+
|
|
636
654
|
return `${importStatement}class ${className}Observer {
|
|
637
655
|
async creating(model) {
|
|
638
656
|
// Logic before creating model
|
|
@@ -681,7 +699,7 @@ module.exports = ${className}Observer;
|
|
|
681
699
|
|
|
682
700
|
function getCastTemplate(className) {
|
|
683
701
|
const isESModule = isESModuleProject();
|
|
684
|
-
|
|
702
|
+
|
|
685
703
|
if (isTypeScriptProject()) {
|
|
686
704
|
return `export default class ${className}Cast {
|
|
687
705
|
get(value: any): any {
|
|
@@ -696,7 +714,7 @@ function getCastTemplate(className) {
|
|
|
696
714
|
}
|
|
697
715
|
`;
|
|
698
716
|
}
|
|
699
|
-
|
|
717
|
+
|
|
700
718
|
if (isESModule) {
|
|
701
719
|
return `class ${className}Cast {
|
|
702
720
|
get(value) {
|
|
@@ -713,7 +731,7 @@ function getCastTemplate(className) {
|
|
|
713
731
|
export default ${className}Cast;
|
|
714
732
|
`;
|
|
715
733
|
}
|
|
716
|
-
|
|
734
|
+
|
|
717
735
|
return `class ${className}Cast {
|
|
718
736
|
get(value) {
|
|
719
737
|
// Transform value when retrieving from database
|
|
@@ -736,7 +754,13 @@ const commands = {
|
|
|
736
754
|
console.log('Setting up Ilana ORM...');
|
|
737
755
|
|
|
738
756
|
// Create directories
|
|
739
|
-
const
|
|
757
|
+
const structure = getProjectStructure();
|
|
758
|
+
const dirs = [
|
|
759
|
+
structure.modelsDir,
|
|
760
|
+
`${structure.databaseDir}/migrations`,
|
|
761
|
+
`${structure.databaseDir}/factories`,
|
|
762
|
+
`${structure.databaseDir}/seeds`
|
|
763
|
+
];
|
|
740
764
|
for (const dir of dirs) {
|
|
741
765
|
if (!fs.existsSync(dir)) {
|
|
742
766
|
fs.mkdirSync(dir, { recursive: true });
|
|
@@ -1053,7 +1077,8 @@ DB_TIMEZONE=UTC
|
|
|
1053
1077
|
}
|
|
1054
1078
|
}
|
|
1055
1079
|
|
|
1056
|
-
const
|
|
1080
|
+
const structure = getProjectStructure();
|
|
1081
|
+
const seedsPath = path.join(process.cwd(), structure.databaseDir, 'seeds');
|
|
1057
1082
|
if (!fs.existsSync(seedsPath)) {
|
|
1058
1083
|
console.log('No seeds directory found');
|
|
1059
1084
|
process.exit(0);
|
|
@@ -1125,7 +1150,8 @@ DB_TIMEZONE=UTC
|
|
|
1125
1150
|
|
|
1126
1151
|
const className = toPascalCase(name.replace('Observer', ''));
|
|
1127
1152
|
const fileName = `${className}Observer${getFileExtension()}`;
|
|
1128
|
-
const
|
|
1153
|
+
const structure = getProjectStructure();
|
|
1154
|
+
const filePath = path.join(process.cwd(), structure.observersDir, fileName);
|
|
1129
1155
|
|
|
1130
1156
|
if (!fs.existsSync(path.dirname(filePath))) {
|
|
1131
1157
|
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
@@ -1133,7 +1159,7 @@ DB_TIMEZONE=UTC
|
|
|
1133
1159
|
|
|
1134
1160
|
const template = getObserverTemplate(className, modelName);
|
|
1135
1161
|
fs.writeFileSync(filePath, template);
|
|
1136
|
-
console.log(`Created observer:
|
|
1162
|
+
console.log(`Created observer: ${structure.observersDir}/${fileName}`);
|
|
1137
1163
|
|
|
1138
1164
|
if (modelName) {
|
|
1139
1165
|
console.log(`Observer configured for model: ${modelName}`);
|
|
@@ -1149,7 +1175,8 @@ DB_TIMEZONE=UTC
|
|
|
1149
1175
|
|
|
1150
1176
|
const className = toPascalCase(name.replace('Cast', ''));
|
|
1151
1177
|
const fileName = `${className}Cast${getFileExtension()}`;
|
|
1152
|
-
const
|
|
1178
|
+
const structure = getProjectStructure();
|
|
1179
|
+
const filePath = path.join(process.cwd(), structure.castsDir, fileName);
|
|
1153
1180
|
|
|
1154
1181
|
if (!fs.existsSync(path.dirname(filePath))) {
|
|
1155
1182
|
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
@@ -1157,7 +1184,7 @@ DB_TIMEZONE=UTC
|
|
|
1157
1184
|
|
|
1158
1185
|
const template = getCastTemplate(className);
|
|
1159
1186
|
fs.writeFileSync(filePath, template);
|
|
1160
|
-
console.log(`Created cast:
|
|
1187
|
+
console.log(`Created cast: ${structure.castsDir}/${fileName}`);
|
|
1161
1188
|
},
|
|
1162
1189
|
|
|
1163
1190
|
help() {
|
package/database/DB.mjs
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import Database from './connection.mjs';
|
|
2
|
+
|
|
3
|
+
// DB facade - provides static methods for database operations
|
|
4
|
+
class DB {
|
|
5
|
+
static connection(name) {
|
|
6
|
+
return Database.connection(name);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
static table(tableName, connection) {
|
|
10
|
+
return Database.table(tableName, connection);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
static raw(query, bindings, connection) {
|
|
14
|
+
return Database.raw(query, bindings, connection);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
static select(query, bindings, connection) {
|
|
18
|
+
return Database.select(query, bindings, connection);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
static insert(table, data, connection) {
|
|
22
|
+
return Database.insert(table, data, connection);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
static update(table, data, where, connection) {
|
|
26
|
+
return Database.update(table, data, where, connection);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
static delete(table, where, connection) {
|
|
30
|
+
return Database.delete(table, where, connection);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
static transaction(callback, connection) {
|
|
34
|
+
return Database.transaction(callback, connection);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
static beginTransaction(connection) {
|
|
38
|
+
return Database.beginTransaction(connection);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
static commit(trx) {
|
|
42
|
+
return Database.commit(trx);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
static rollback(trx) {
|
|
46
|
+
return Database.rollback(trx);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
static schema(connection) {
|
|
50
|
+
return Database.schema(connection);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
static migrate(connection) {
|
|
54
|
+
return Database.migrate(connection);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
static seed(connection) {
|
|
58
|
+
return Database.seed(connection);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
static destroy(connection) {
|
|
62
|
+
return Database.destroy(connection);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
static destroyAll() {
|
|
66
|
+
return Database.destroyAll();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
static configure(config) {
|
|
70
|
+
return Database.configure(config);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
static getInstance(connection) {
|
|
74
|
+
return Database.getInstance(connection);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
static getConfig() {
|
|
78
|
+
return Database.getConfig();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
static setConfig(config) {
|
|
82
|
+
return Database.setConfig(config);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Query builder methods
|
|
86
|
+
static query(connection) {
|
|
87
|
+
return Database.getInstance(connection);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
static from(table, connection) {
|
|
91
|
+
return Database.table(table, connection);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Aggregation methods
|
|
95
|
+
static count(table, column = '*', connection) {
|
|
96
|
+
return Database.table(table, connection).count(column);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
static sum(table, column, connection) {
|
|
100
|
+
return Database.table(table, connection).sum(column);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
static avg(table, column, connection) {
|
|
104
|
+
return Database.table(table, connection).avg(column);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
static min(table, column, connection) {
|
|
108
|
+
return Database.table(table, connection).min(column);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
static max(table, column, connection) {
|
|
112
|
+
return Database.table(table, connection).max(column);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Utility methods
|
|
116
|
+
static listen(event, callback) {
|
|
117
|
+
return Database.listen(event, callback);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
static unlisten(event, callback) {
|
|
121
|
+
return Database.unlisten(event, callback);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
static enableQueryLog() {
|
|
125
|
+
return Database.enableQueryLog();
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
static disableQueryLog() {
|
|
129
|
+
return Database.disableQueryLog();
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
static getQueryLog() {
|
|
133
|
+
return Database.getQueryLog();
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
static flushQueryLog() {
|
|
137
|
+
return Database.flushQueryLog();
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
static pretend(callback, connection) {
|
|
141
|
+
return Database.pretend(callback, connection);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
static reconnect(connection) {
|
|
145
|
+
return Database.reconnect(connection);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
static disconnect(connection) {
|
|
149
|
+
return Database.disconnect(connection);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
static getConnectionName() {
|
|
153
|
+
return Database.getConnectionName();
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
static setConnectionName(name) {
|
|
157
|
+
return Database.setConnectionName(name);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
static getTablePrefix(connection) {
|
|
161
|
+
return Database.getTablePrefix(connection);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
static setTablePrefix(prefix, connection) {
|
|
165
|
+
return Database.setTablePrefix(prefix, connection);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export default DB;
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import Database from './connection.mjs';
|
|
2
|
+
|
|
3
|
+
class SchemaBuilder {
|
|
4
|
+
constructor(connection) {
|
|
5
|
+
this.knex = Database.connection(connection);
|
|
6
|
+
this.currentTable = '';
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
createTable(tableName, callback) {
|
|
10
|
+
return this.knex.schema.createTable(tableName, callback);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
dropTable(tableName) {
|
|
14
|
+
return this.knex.schema.dropTable(tableName);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
dropTableIfExists(tableName) {
|
|
18
|
+
return this.knex.schema.dropTableIfExists(tableName);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
renameTable(from, to) {
|
|
22
|
+
return this.knex.schema.renameTable(from, to);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
hasTable(tableName) {
|
|
26
|
+
return this.knex.schema.hasTable(tableName);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
hasColumn(tableName, columnName) {
|
|
30
|
+
return this.knex.schema.hasColumn(tableName, columnName);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
table(tableName, callback) {
|
|
34
|
+
return this.knex.schema.table(tableName, callback);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
alterTable(tableName, callback) {
|
|
38
|
+
return this.knex.schema.alterTable(tableName, callback);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
raw(statement) {
|
|
42
|
+
return this.knex.raw(statement);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// PostgreSQL specific
|
|
46
|
+
createSchema(schemaName) {
|
|
47
|
+
return this.knex.schema.createSchema(schemaName);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
dropSchema(schemaName) {
|
|
51
|
+
return this.knex.schema.dropSchema(schemaName);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Advanced column types
|
|
55
|
+
jsonb(columnName) {
|
|
56
|
+
if (this.knex.client.config.client === 'pg') {
|
|
57
|
+
return this.knex.schema.jsonb ? this.knex.schema.jsonb(columnName) : this.knex.schema.json(columnName);
|
|
58
|
+
}
|
|
59
|
+
return this.knex.schema.json(columnName);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
geometry(columnName, geometryType) {
|
|
63
|
+
return this.knex.schema.specificType(columnName, geometryType || 'geometry');
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
point(columnName) {
|
|
67
|
+
return this.knex.schema.specificType(columnName, 'point');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
lineString(columnName) {
|
|
71
|
+
return this.knex.schema.specificType(columnName, 'linestring');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
polygon(columnName) {
|
|
75
|
+
return this.knex.schema.specificType(columnName, 'polygon');
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
inet(columnName) {
|
|
79
|
+
return this.knex.schema.specificType(columnName, 'inet');
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
macaddr(columnName) {
|
|
83
|
+
return this.knex.schema.specificType(columnName, 'macaddr');
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
specificType(columnName, type) {
|
|
87
|
+
return this.knex.schema.specificType(columnName, type);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Enhanced column modifiers with database-specific implementations
|
|
91
|
+
after(columnName) {
|
|
92
|
+
if (this.knex.client.config.client === 'mysql2') {
|
|
93
|
+
return this.knex.schema.raw(`AFTER ${columnName}`);
|
|
94
|
+
}
|
|
95
|
+
return this;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
first() {
|
|
99
|
+
if (this.knex.client.config.client === 'mysql2') {
|
|
100
|
+
return this.knex.schema.raw('FIRST');
|
|
101
|
+
}
|
|
102
|
+
return this;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
checkPositive(column) {
|
|
106
|
+
const client = this.knex.client.config.client;
|
|
107
|
+
if (client === 'pg') {
|
|
108
|
+
return this.knex.raw(`ALTER TABLE ${this.currentTable} ADD CONSTRAINT ${column}_positive CHECK (${column} > 0)`);
|
|
109
|
+
} else if (client === 'mysql2') {
|
|
110
|
+
return this.knex.raw(`ALTER TABLE ${this.currentTable} ADD CONSTRAINT ${column}_positive CHECK (${column} > 0)`);
|
|
111
|
+
}
|
|
112
|
+
return Promise.resolve();
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
checkRegex(column, pattern) {
|
|
116
|
+
const client = this.knex.client.config.client;
|
|
117
|
+
if (client === 'pg') {
|
|
118
|
+
return this.knex.raw(`ALTER TABLE ${this.currentTable} ADD CONSTRAINT ${column}_regex CHECK (${column} ~ '${pattern}')`);
|
|
119
|
+
} else if (client === 'mysql2') {
|
|
120
|
+
return this.knex.raw(`ALTER TABLE ${this.currentTable} ADD CONSTRAINT ${column}_regex CHECK (${column} REGEXP '${pattern}')`);
|
|
121
|
+
}
|
|
122
|
+
return Promise.resolve();
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
generatedAs(column, expression) {
|
|
126
|
+
const client = this.knex.client.config.client;
|
|
127
|
+
if (client === 'mysql2') {
|
|
128
|
+
return this.knex.raw(`ALTER TABLE ${this.currentTable} ADD ${column} VARCHAR(255) GENERATED ALWAYS AS (${expression}) STORED`);
|
|
129
|
+
} else if (client === 'pg') {
|
|
130
|
+
return this.knex.raw(`ALTER TABLE ${this.currentTable} ADD ${column} TEXT GENERATED ALWAYS AS (${expression}) STORED`);
|
|
131
|
+
}
|
|
132
|
+
return Promise.resolve();
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
collate(tableName, collation) {
|
|
136
|
+
const client = this.knex.client.config.client;
|
|
137
|
+
if (client === 'mysql2') {
|
|
138
|
+
return this.knex.raw(`ALTER TABLE ${tableName} COLLATE ${collation}`);
|
|
139
|
+
} else if (client === 'pg') {
|
|
140
|
+
return this.knex.raw(`ALTER TABLE ${tableName} ALTER COLUMN name TYPE TEXT COLLATE "${collation}"`);
|
|
141
|
+
}
|
|
142
|
+
return Promise.resolve();
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Enhanced PostgreSQL types
|
|
146
|
+
array(columnName, type = 'text') {
|
|
147
|
+
if (this.knex.client.config.client === 'pg') {
|
|
148
|
+
return this.knex.schema.specificType(columnName, `${type}[]`);
|
|
149
|
+
}
|
|
150
|
+
return this.knex.schema.json(columnName);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
numrange(columnName) {
|
|
154
|
+
return this.knex.schema.specificType(columnName, 'numrange');
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
daterange(columnName) {
|
|
158
|
+
return this.knex.schema.specificType(columnName, 'daterange');
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
tsvector(columnName) {
|
|
162
|
+
return this.knex.schema.specificType(columnName, 'tsvector');
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Enhanced MySQL types
|
|
166
|
+
fulltext(columns, indexName) {
|
|
167
|
+
if (this.knex.client.config.client === 'mysql2') {
|
|
168
|
+
const name = indexName || `${columns.join('_')}_fulltext`;
|
|
169
|
+
return this.knex.raw(`ALTER TABLE ${this.currentTable} ADD FULLTEXT INDEX ${name} (${columns.join(', ')})`);
|
|
170
|
+
}
|
|
171
|
+
return Promise.resolve();
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
spatial(column, indexName) {
|
|
175
|
+
if (this.knex.client.config.client === 'mysql2') {
|
|
176
|
+
const name = indexName || `${column}_spatial`;
|
|
177
|
+
return this.knex.raw(`ALTER TABLE ${this.currentTable} ADD SPATIAL INDEX ${name} (${column})`);
|
|
178
|
+
}
|
|
179
|
+
return Promise.resolve();
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
setCurrentTable(tableName) {
|
|
183
|
+
this.currentTable = tableName;
|
|
184
|
+
return this;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Enhanced utility methods
|
|
188
|
+
get client() {
|
|
189
|
+
return this.knex.client;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
get fn() {
|
|
193
|
+
return this.knex.fn;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Database-specific utilities
|
|
197
|
+
enableExtension(name) {
|
|
198
|
+
if (this.knex.client.config.client === 'pg') {
|
|
199
|
+
return this.knex.raw(`CREATE EXTENSION IF NOT EXISTS "${name}"`);
|
|
200
|
+
}
|
|
201
|
+
return Promise.resolve();
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
createEnum(name, values) {
|
|
205
|
+
if (this.knex.client.config.client === 'pg') {
|
|
206
|
+
return this.knex.raw(`CREATE TYPE ${name} AS ENUM (${values.map(v => `'${v}'`).join(', ')})`);
|
|
207
|
+
}
|
|
208
|
+
return Promise.resolve();
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
dropEnum(name) {
|
|
212
|
+
if (this.knex.client.config.client === 'pg') {
|
|
213
|
+
return this.knex.raw(`DROP TYPE IF EXISTS ${name}`);
|
|
214
|
+
}
|
|
215
|
+
return Promise.resolve();
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export default SchemaBuilder;
|
package/orm/Factory.mjs
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { faker } from '@faker-js/faker';
|
|
2
|
+
|
|
3
|
+
class Factory {
|
|
4
|
+
constructor(model, definition) {
|
|
5
|
+
this.model = model;
|
|
6
|
+
this.definition = definition;
|
|
7
|
+
this.states = new Map();
|
|
8
|
+
this.afterCreating = [];
|
|
9
|
+
this.afterMaking = [];
|
|
10
|
+
this.count = 1;
|
|
11
|
+
this.activeStates = [];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
static define(model, definition) {
|
|
15
|
+
return new Factory(model, definition);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
state(name, attributes) {
|
|
19
|
+
if (typeof attributes === 'function') {
|
|
20
|
+
this.states.set(name, attributes);
|
|
21
|
+
} else {
|
|
22
|
+
this.states.set(name, () => attributes);
|
|
23
|
+
}
|
|
24
|
+
return this;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
times(count) {
|
|
28
|
+
this.count = count;
|
|
29
|
+
return this;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
as(stateName) {
|
|
33
|
+
this.activeStates.push(stateName);
|
|
34
|
+
return this;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
afterCreating(callback) {
|
|
38
|
+
this.afterCreating.push(callback);
|
|
39
|
+
return this;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
afterMaking(callback) {
|
|
43
|
+
this.afterMaking.push(callback);
|
|
44
|
+
return this;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async make(attributes = {}) {
|
|
48
|
+
const instances = [];
|
|
49
|
+
|
|
50
|
+
for (let i = 0; i < this.count; i++) {
|
|
51
|
+
const baseAttributes = this.definition(faker);
|
|
52
|
+
|
|
53
|
+
// Apply states
|
|
54
|
+
let stateAttributes = {};
|
|
55
|
+
for (const stateName of this.activeStates) {
|
|
56
|
+
if (this.states.has(stateName)) {
|
|
57
|
+
const stateDefinition = this.states.get(stateName);
|
|
58
|
+
stateAttributes = { ...stateAttributes, ...stateDefinition(faker) };
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const finalAttributes = { ...baseAttributes, ...stateAttributes, ...attributes };
|
|
63
|
+
const instance = new this.model(finalAttributes);
|
|
64
|
+
|
|
65
|
+
// Run after making callbacks
|
|
66
|
+
for (const callback of this.afterMaking) {
|
|
67
|
+
await callback(instance);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
instances.push(instance);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return this.count === 1 ? instances[0] : instances;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async create(attributes = {}) {
|
|
77
|
+
const instances = await this.make(attributes);
|
|
78
|
+
const instancesToSave = Array.isArray(instances) ? instances : [instances];
|
|
79
|
+
const savedInstances = [];
|
|
80
|
+
|
|
81
|
+
for (const instance of instancesToSave) {
|
|
82
|
+
const saved = await instance.save();
|
|
83
|
+
|
|
84
|
+
// Run after creating callbacks
|
|
85
|
+
for (const callback of this.afterCreating) {
|
|
86
|
+
await callback(saved);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
savedInstances.push(saved);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return this.count === 1 ? savedInstances[0] : savedInstances;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async createMany(count, attributes = {}) {
|
|
96
|
+
return this.times(count).create(attributes);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async makeMany(count, attributes = {}) {
|
|
100
|
+
return this.times(count).make(attributes);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Relationship factories
|
|
104
|
+
for(model) {
|
|
105
|
+
return new RelationshipFactory(this, model);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Sequence support
|
|
109
|
+
sequence(callback) {
|
|
110
|
+
let counter = 0;
|
|
111
|
+
const originalDefinition = this.definition;
|
|
112
|
+
|
|
113
|
+
this.definition = (faker) => {
|
|
114
|
+
const baseAttributes = originalDefinition(faker);
|
|
115
|
+
const sequenceAttributes = callback(++counter, faker);
|
|
116
|
+
return { ...baseAttributes, ...sequenceAttributes };
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
return this;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Conditional attributes
|
|
123
|
+
when(condition, attributes) {
|
|
124
|
+
const originalDefinition = this.definition;
|
|
125
|
+
|
|
126
|
+
this.definition = (faker) => {
|
|
127
|
+
const baseAttributes = originalDefinition(faker);
|
|
128
|
+
if (condition) {
|
|
129
|
+
const conditionalAttributes = typeof attributes === 'function'
|
|
130
|
+
? attributes(faker)
|
|
131
|
+
: attributes;
|
|
132
|
+
return { ...baseAttributes, ...conditionalAttributes };
|
|
133
|
+
}
|
|
134
|
+
return baseAttributes;
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
return this;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Raw attributes (bypass model instantiation)
|
|
141
|
+
raw(attributes = {}) {
|
|
142
|
+
const baseAttributes = this.definition(faker);
|
|
143
|
+
|
|
144
|
+
// Apply states
|
|
145
|
+
let stateAttributes = {};
|
|
146
|
+
for (const stateName of this.activeStates) {
|
|
147
|
+
if (this.states.has(stateName)) {
|
|
148
|
+
const stateDefinition = this.states.get(stateName);
|
|
149
|
+
stateAttributes = { ...stateAttributes, ...stateDefinition(faker) };
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return { ...baseAttributes, ...stateAttributes, ...attributes };
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
class RelationshipFactory {
|
|
158
|
+
constructor(parentFactory, model) {
|
|
159
|
+
this.parentFactory = parentFactory;
|
|
160
|
+
this.model = model;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
create(attributes = {}) {
|
|
164
|
+
// This would create related models
|
|
165
|
+
// Implementation depends on relationship type
|
|
166
|
+
return this.model.factory().create(attributes);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
make(attributes = {}) {
|
|
170
|
+
return this.model.factory().make(attributes);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Global factory registry
|
|
175
|
+
const factories = new Map();
|
|
176
|
+
|
|
177
|
+
export function defineFactory(model, definition) {
|
|
178
|
+
const factory = new Factory(model, definition);
|
|
179
|
+
factories.set(model.name, factory);
|
|
180
|
+
|
|
181
|
+
// Add factory method to model
|
|
182
|
+
model.factory = function(attributes) {
|
|
183
|
+
const factoryInstance = new Factory(model, definition);
|
|
184
|
+
if (attributes) {
|
|
185
|
+
return factoryInstance.make(attributes);
|
|
186
|
+
}
|
|
187
|
+
return factoryInstance;
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
return factory;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export function getFactory(modelName) {
|
|
194
|
+
return factories.get(modelName);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export { Factory, faker };
|
|
198
|
+
export default Factory;
|
package/orm/Seeder.mjs
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import Database from '../database/connection.mjs';
|
|
2
|
+
|
|
3
|
+
class Seeder {
|
|
4
|
+
constructor() {
|
|
5
|
+
this.db = Database;
|
|
6
|
+
this.batchSize = 1000;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// Batch processing utilities
|
|
10
|
+
async createInBatches(factory, count, attributes = {}) {
|
|
11
|
+
const results = [];
|
|
12
|
+
const batches = Math.ceil(count / this.batchSize);
|
|
13
|
+
|
|
14
|
+
for (let i = 0; i < batches; i++) {
|
|
15
|
+
const currentBatchSize = Math.min(this.batchSize, count - (i * this.batchSize));
|
|
16
|
+
const batch = await factory.times(currentBatchSize).create(attributes);
|
|
17
|
+
results.push(...(Array.isArray(batch) ? batch : [batch]));
|
|
18
|
+
|
|
19
|
+
if (batches > 1) {
|
|
20
|
+
console.log(`Batch ${i + 1}/${batches} completed (${results.length}/${count})`);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return results;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async disableForeignKeyChecks() {
|
|
28
|
+
const client = this.db.connection(this.connection).client.config.client;
|
|
29
|
+
|
|
30
|
+
if (client === 'mysql2') {
|
|
31
|
+
await this.db.raw('SET FOREIGN_KEY_CHECKS = 0');
|
|
32
|
+
} else if (client === 'pg') {
|
|
33
|
+
await this.db.raw('SET session_replication_role = replica');
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async enableForeignKeyChecks() {
|
|
38
|
+
const client = this.db.connection(this.connection).client.config.client;
|
|
39
|
+
|
|
40
|
+
if (client === 'mysql2') {
|
|
41
|
+
await this.db.raw('SET FOREIGN_KEY_CHECKS = 1');
|
|
42
|
+
} else if (client === 'pg') {
|
|
43
|
+
await this.db.raw('SET session_replication_role = DEFAULT');
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async call(seeders) {
|
|
48
|
+
// Handle both single seeder and array of seeders
|
|
49
|
+
const seederArray = Array.isArray(seeders) ? seeders : [seeders];
|
|
50
|
+
|
|
51
|
+
for (const SeederClass of seederArray) {
|
|
52
|
+
const seeder = new SeederClass();
|
|
53
|
+
if (this.connection) {
|
|
54
|
+
seeder.connection = this.connection;
|
|
55
|
+
}
|
|
56
|
+
await seeder.run();
|
|
57
|
+
console.log(`Seeded: ${SeederClass.name}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async callWith(seeders, connection) {
|
|
62
|
+
for (const [name, SeederClass] of Object.entries(seeders)) {
|
|
63
|
+
const seeder = new SeederClass();
|
|
64
|
+
if (connection || this.connection) {
|
|
65
|
+
seeder.connection = connection || this.connection;
|
|
66
|
+
}
|
|
67
|
+
await seeder.run();
|
|
68
|
+
console.log(`Seeded: ${name}`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async callOnce(SeederClass, identifier) {
|
|
73
|
+
const tableName = 'seeder_log';
|
|
74
|
+
|
|
75
|
+
// Ensure seeder log table exists
|
|
76
|
+
const knex = this.db.getInstance();
|
|
77
|
+
const hasTable = await knex.schema.hasTable(tableName);
|
|
78
|
+
if (!hasTable) {
|
|
79
|
+
await knex.schema.createTable(tableName, (table) => {
|
|
80
|
+
table.increments('id');
|
|
81
|
+
table.string('seeder');
|
|
82
|
+
table.timestamp('executed_at').defaultTo(knex.fn.now());
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Check if already executed
|
|
87
|
+
const exists = await this.db.table(tableName).where('seeder', identifier).first();
|
|
88
|
+
if (exists) {
|
|
89
|
+
console.log(`Skipped: ${identifier} (already executed)`);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Execute seeder
|
|
94
|
+
const seeder = new SeederClass();
|
|
95
|
+
if (this.connection) {
|
|
96
|
+
seeder.connection = this.connection;
|
|
97
|
+
}
|
|
98
|
+
await seeder.run();
|
|
99
|
+
|
|
100
|
+
// Log execution
|
|
101
|
+
await this.db.table(tableName).insert({
|
|
102
|
+
seeder: identifier,
|
|
103
|
+
executed_at: new Date()
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
console.log(`Seeded: ${identifier}`);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
async progress(total, callback) {
|
|
110
|
+
let completed = 0;
|
|
111
|
+
const updateProgress = (count) => {
|
|
112
|
+
completed += count;
|
|
113
|
+
const percentage = Math.round((completed / total) * 100);
|
|
114
|
+
console.log(`Progress: ${percentage}% (${completed}/${total})`);
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
await callback(updateProgress);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
async truncate(table) {
|
|
121
|
+
await this.db.table(table, this.connection).truncate();
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
async truncateInOrder(tables) {
|
|
125
|
+
await this.disableForeignKeyChecks();
|
|
126
|
+
|
|
127
|
+
for (const table of tables) {
|
|
128
|
+
await this.truncate(table);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
await this.enableForeignKeyChecks();
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
async wipeDatabase() {
|
|
135
|
+
const knex = this.db.connection(this.connection);
|
|
136
|
+
let tables = [];
|
|
137
|
+
|
|
138
|
+
if (knex.client.config.client === 'sqlite3') {
|
|
139
|
+
const result = await knex.raw("SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'");
|
|
140
|
+
tables = result.map((row) => row.name);
|
|
141
|
+
} else if (knex.client.config.client === 'mysql2') {
|
|
142
|
+
const result = await knex.raw('SHOW TABLES');
|
|
143
|
+
tables = result[0].map((row) => Object.values(row)[0]);
|
|
144
|
+
} else if (knex.client.config.client === 'pg') {
|
|
145
|
+
const result = await knex.raw("SELECT tablename FROM pg_tables WHERE schemaname = 'public'");
|
|
146
|
+
tables = result.rows.map((row) => row.tablename);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
await this.truncateInOrder(tables);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export default Seeder;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ilana-orm",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.14",
|
|
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",
|
|
@@ -36,12 +36,15 @@
|
|
|
36
36
|
"types": "./database/connection.d.ts"
|
|
37
37
|
},
|
|
38
38
|
"./database/schema-builder": {
|
|
39
|
+
"import": "./database/schema-builder.mjs",
|
|
39
40
|
"require": "./database/schema-builder.js"
|
|
40
41
|
},
|
|
41
42
|
"./orm/Seeder": {
|
|
43
|
+
"import": "./orm/Seeder.mjs",
|
|
42
44
|
"require": "./orm/Seeder.js"
|
|
43
45
|
},
|
|
44
46
|
"./orm/Factory": {
|
|
47
|
+
"import": "./orm/Factory.mjs",
|
|
45
48
|
"require": "./orm/Factory.js"
|
|
46
49
|
},
|
|
47
50
|
"./orm/ModelRegistry": {
|
|
@@ -58,6 +61,7 @@
|
|
|
58
61
|
"require": "./orm/MigrationRunner.js"
|
|
59
62
|
},
|
|
60
63
|
"./database/DB": {
|
|
64
|
+
"import": "./database/DB.mjs",
|
|
61
65
|
"require": "./database/DB.js"
|
|
62
66
|
}
|
|
63
67
|
},
|