@nitronjs/framework 0.1.21 → 0.1.23

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.
Files changed (35) hide show
  1. package/cli/create.js +28 -4
  2. package/cli/njs.js +33 -5
  3. package/lib/Console/Commands/MigrateCommand.js +27 -70
  4. package/lib/Console/Commands/MigrateFreshCommand.js +49 -66
  5. package/lib/Console/Commands/MigrateRollbackCommand.js +52 -0
  6. package/lib/Console/Commands/MigrateStatusCommand.js +38 -0
  7. package/lib/Console/Commands/SeedCommand.js +36 -65
  8. package/lib/Core/Paths.js +8 -0
  9. package/lib/Database/Migration/Checksum.js +23 -0
  10. package/lib/Database/Migration/MigrationRepository.js +92 -0
  11. package/lib/Database/Migration/MigrationRunner.js +327 -0
  12. package/lib/Database/Migration/migrations/0000_00_00_00_00_create_migrations_table.js +21 -0
  13. package/lib/Database/Migration/migrations/0000_00_00_00_01_create_seeders_table.js +20 -0
  14. package/lib/Database/Schema/Blueprint.js +0 -40
  15. package/lib/Database/Schema/Manager.js +29 -40
  16. package/lib/Database/Seeder/SeederRepository.js +49 -0
  17. package/lib/Database/Seeder/SeederRunner.js +183 -0
  18. package/lib/Faker/Data/Address.js +63 -0
  19. package/lib/Faker/Data/Color.js +72 -0
  20. package/lib/Faker/Data/Company.js +59 -0
  21. package/lib/Faker/Data/Date.js +49 -0
  22. package/lib/Faker/Data/Finance.js +65 -0
  23. package/lib/Faker/Data/Internet.js +73 -0
  24. package/lib/Faker/Data/Lorem.js +45 -0
  25. package/lib/Faker/Data/Person.js +67 -0
  26. package/lib/Faker/Data/Phone.js +26 -0
  27. package/lib/Faker/Faker.d.ts +205 -0
  28. package/lib/Faker/Faker.js +812 -0
  29. package/lib/View/Manager.js +26 -5
  30. package/lib/index.d.ts +407 -0
  31. package/lib/index.js +12 -0
  32. package/package.json +6 -2
  33. package/skeleton/config/app.js +20 -0
  34. package/skeleton/globals.d.ts +68 -1
  35. package/skeleton/tsconfig.json +6 -16
package/cli/create.js CHANGED
@@ -32,6 +32,27 @@ function logStep(message, status = "pending") {
32
32
  console.log(` ${icons[status]} ${message}`);
33
33
  }
34
34
 
35
+ function startSpinner(message) {
36
+ if (!process.stdout.isTTY) {
37
+ return () => {};
38
+ }
39
+
40
+ const frames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
41
+ let i = 0;
42
+ const line = () => ` ${COLORS.yellow}${frames[i]}${COLORS.reset} ${message}`;
43
+
44
+ process.stdout.write(line());
45
+ const timer = setInterval(() => {
46
+ i = (i + 1) % frames.length;
47
+ process.stdout.write(`\r${line()}`);
48
+ }, 120);
49
+
50
+ return () => {
51
+ clearInterval(timer);
52
+ process.stdout.write(`\r${" ".repeat(message.length + 4)}\r`);
53
+ };
54
+ }
55
+
35
56
  function printBanner() {
36
57
  console.log();
37
58
  log("███╗ ██╗██╗████████╗██████╗ ██████╗ ███╗ ██╗ ██╗███████╗", COLORS.cyan);
@@ -150,12 +171,12 @@ function updateEnvFile(projectPath) {
150
171
  function runNpmInstall(projectPath) {
151
172
  return new Promise((resolve, reject) => {
152
173
  const isWindows = process.platform === "win32";
153
- const npm = isWindows ? "npm.cmd" : "npm";
174
+ const npm = isWindows ? (process.env.ComSpec || "cmd.exe") : "npm";
175
+ const npmArgs = isWindows ? ["/d", "/s", "/c", "npm", "install"] : ["install"];
154
176
 
155
- const child = spawn(npm, ["install"], {
177
+ const child = spawn(npm, npmArgs, {
156
178
  cwd: projectPath,
157
- stdio: ["ignore", "pipe", "pipe"],
158
- shell: isWindows
179
+ stdio: ["ignore", "pipe", "pipe"]
159
180
  });
160
181
 
161
182
  let output = "";
@@ -262,10 +283,13 @@ export default async function create(projectName, options = {}) {
262
283
  logStep("APP_KEY generated", "success");
263
284
 
264
285
  logStep("Installing dependencies (this may take a moment)...", "running");
286
+ const stopSpinner = startSpinner("Installing dependencies...");
265
287
  try {
266
288
  await runNpmInstall(projectPath);
289
+ stopSpinner();
267
290
  logStep("Dependencies installed", "success");
268
291
  } catch (error) {
292
+ stopSpinner();
269
293
  logStep("Failed to install dependencies", "error");
270
294
  if (error.output) {
271
295
  log(`${COLORS.dim}${error.output}${COLORS.reset}`);
package/cli/njs.js CHANGED
@@ -28,9 +28,14 @@ ${COLORS.bold}Development:${COLORS.reset}
28
28
  ${COLORS.bold}Database:${COLORS.reset}
29
29
  ${COLORS.cyan}njs migrate${COLORS.reset} Run database migrations
30
30
  ${COLORS.cyan}njs migrate --seed${COLORS.reset} Run migrations and seeders
31
+ ${COLORS.cyan}njs migrate:rollback${COLORS.reset} Rollback the last batch of migrations
32
+ ${COLORS.cyan}njs migrate:status${COLORS.reset} Show the status of each migration
31
33
  ${COLORS.cyan}njs migrate:fresh${COLORS.reset} Drop all tables and re-migrate
32
34
  ${COLORS.cyan}njs migrate:fresh --seed${COLORS.reset} Fresh migrate with seeders
33
- ${COLORS.cyan}njs seed${COLORS.reset} Run database seeders
35
+ ${COLORS.cyan}njs seed${COLORS.reset} Run prod seeders
36
+ ${COLORS.cyan}njs seed --dev${COLORS.reset} Run dev seeders
37
+ ${COLORS.cyan}njs seed --all${COLORS.reset} Run all seeders (prod + dev)
38
+ ${COLORS.cyan}njs seed --status${COLORS.reset} Show the status of each seeder
34
39
 
35
40
  ${COLORS.bold}Generators:${COLORS.reset}
36
41
  ${COLORS.cyan}njs make:controller${COLORS.reset} Create a new controller
@@ -66,7 +71,7 @@ const additionalArgs = args.slice(1);
66
71
 
67
72
  const KNOWN_COMMANDS = [
68
73
  "dev", "start", "build",
69
- "migrate", "migrate:fresh", "seed",
74
+ "migrate", "migrate:rollback", "migrate:status", "migrate:fresh", "seed",
70
75
  "storage:link",
71
76
  "make:controller", "make:middleware", "make:model", "make:migration", "make:seeder"
72
77
  ];
@@ -105,19 +110,42 @@ async function run() {
105
110
 
106
111
  case "migrate": {
107
112
  const { default: Migrate } = await import("../lib/Console/Commands/MigrateCommand.js");
108
- await Migrate(additionalArgs.includes("--seed"));
113
+ await Migrate({ seed: additionalArgs.includes("--seed") });
114
+ break;
115
+ }
116
+
117
+ case "migrate:rollback": {
118
+ const { default: Rollback } = await import("../lib/Console/Commands/MigrateRollbackCommand.js");
119
+ const stepArg = additionalArgs.find(arg => arg.startsWith('--step='));
120
+ const step = stepArg ? parseInt(stepArg.split('=')[1], 10) : 1;
121
+ const all = additionalArgs.includes('--all');
122
+ await Rollback({ step, all });
123
+ break;
124
+ }
125
+
126
+ case "migrate:status": {
127
+ const { default: Status } = await import("../lib/Console/Commands/MigrateStatusCommand.js");
128
+ await Status();
109
129
  break;
110
130
  }
111
131
 
112
132
  case "migrate:fresh": {
113
133
  const { default: MigrateFresh } = await import("../lib/Console/Commands/MigrateFreshCommand.js");
114
- await MigrateFresh(additionalArgs.includes("--seed"));
134
+ await MigrateFresh({ seed: additionalArgs.includes("--seed") });
115
135
  break;
116
136
  }
117
137
 
118
138
  case "seed": {
119
139
  const { default: Seed } = await import("../lib/Console/Commands/SeedCommand.js");
120
- await Seed();
140
+ const showStatus = additionalArgs.includes('--status');
141
+ const isDev = additionalArgs.includes('--dev');
142
+ const isAll = additionalArgs.includes('--all');
143
+
144
+ let environment = 'prod';
145
+ if (isDev) environment = 'dev';
146
+ if (isAll) environment = 'all';
147
+
148
+ await Seed({ environment, status: showStatus });
121
149
  break;
122
150
  }
123
151
 
@@ -1,95 +1,52 @@
1
- import fs from 'fs';
2
- import path from 'path';
3
- import { pathToFileURL } from 'url';
4
1
  import dotenv from 'dotenv';
5
2
  import DB from '../../Database/DB.js';
6
- import Paths from '../../Core/Paths.js';
7
3
  import Config from '../../Core/Config.js';
4
+ import MigrationRunner from '../../Database/Migration/MigrationRunner.js';
5
+ import seed from './SeedCommand.js';
8
6
 
9
- class Migrate {
10
- #files;
11
- #shouldSeed;
7
+ export default async function migrate(options = {}) {
8
+ const { seed: shouldSeed = false } = options;
12
9
 
13
- constructor(files = null, shouldSeed = false) {
14
- const migrationsDir = Paths.migrations;
15
- this.#files = files || fs.readdirSync(migrationsDir);
16
- this.#shouldSeed = shouldSeed;
10
+ dotenv.config({ quiet: true });
11
+ await Config.initialize();
12
+
13
+ try {
14
+ await DB.setup();
15
+ } catch (error) {
16
+ console.error('❌ Database setup failed:', error.message);
17
+ console.error('Check your .env file and ensure the database exists and is accessible');
18
+ return false;
17
19
  }
18
20
 
19
- async run() {
20
- dotenv.config({ quiet: true });
21
- await Config.initialize();
22
-
23
- try {
24
- await DB.setup();
25
- } catch (error) {
26
- console.error('❌ Database setup failed:', error.message);
27
- console.error('Check your .env file and ensure the database exists and is accessible');
28
- return false;
29
- }
21
+ try {
22
+ const result = await MigrationRunner.run();
30
23
 
31
- const migrationsDir = Paths.migrations;
32
- for (const file of this.#files) {
33
- const filePath = Paths.migrationUrl(file);
34
- const module = await import(filePath);
35
-
36
- console.log(`📦 [\x1b[36m${module.default.name}\x1b[0m] Creating table...`);
37
- try {
38
- await module.default.up();
39
- console.log(`✅ [\x1b[36m${module.default.name}\x1b[0m] Table created successfully\n`);
40
- } catch (error) {
41
- if (this.#isTableExistsError(error)) {
42
- console.log(`⚠️ [\x1b[36m${module.default.name}\x1b[0m] Table already exists, skipping\n`);
43
- continue;
44
- }
45
- throw error;
46
- }
24
+ if (!result.success) {
25
+ await DB.close();
26
+ return false;
47
27
  }
48
28
 
49
- if (this.#shouldSeed) {
50
- await this.#runSeeders();
29
+ if (shouldSeed && result.ran.length > 0) {
30
+ console.log('\n');
31
+ await seed();
51
32
  }
52
33
 
53
34
  await DB.close();
54
35
  return true;
55
- }
56
-
57
- async #runSeeders() {
58
- const seedersDir = Paths.seeders;
59
- const seedFiles = fs.readdirSync(seedersDir);
60
-
61
- for (const file of seedFiles) {
62
- const filePath = pathToFileURL(path.join(seedersDir, file)).href;
63
- const seeder = await import(filePath);
64
- console.log(`🌱 [\x1b[36m${seeder.default.name}\x1b[0m] Seeding...`);
65
- await seeder.default.run();
66
- console.log(`✅ [\x1b[36m${seeder.default.name}\x1b[0m] Seeding completed\n`);
67
- }
68
- }
69
36
 
70
- #isTableExistsError(error) {
71
- const message = String(error?.message || "").toLowerCase();
72
-
73
- return message.includes("already exists") ||
74
- message.includes("table exists") ||
75
- message.includes("errno 1050") ||
76
- message.includes("er_table_exists_error") ||
77
- message.includes("duplicate table");
37
+ } catch (error) {
38
+ console.error('❌ Migration error:', error.message);
39
+ await DB.close();
40
+ return false;
78
41
  }
79
42
  }
80
43
 
81
- export default async function migrate(shouldSeed = false, files = null) {
82
- const instance = new Migrate(files, shouldSeed);
83
- return instance.run();
84
- }
85
-
86
- // Auto-run when called directly
87
44
  const isMain = process.argv[1]?.endsWith("MigrateCommand.js");
88
45
  if (isMain) {
89
46
  const args = process.argv.slice(2);
90
47
  const shouldSeed = args.includes("--seed");
91
- const files = args.filter(arg => arg !== "--seed");
92
- migrate(shouldSeed, files.length > 0 ? files : null)
48
+
49
+ migrate({ seed: shouldSeed })
93
50
  .then(success => process.exit(success ? 0 : 1))
94
51
  .catch(err => {
95
52
  console.error(err);
@@ -1,94 +1,77 @@
1
- import fs from 'fs';
2
- import path from 'path';
3
1
  import dotenv from 'dotenv';
4
2
  import DB from '../../Database/DB.js';
5
- import Paths from '../../Core/Paths.js';
6
3
  import Config from '../../Core/Config.js';
4
+ import MigrationRunner from '../../Database/Migration/MigrationRunner.js';
5
+ import seed from './SeedCommand.js';
7
6
 
8
- class MigrateFresh {
9
- #shouldSeed;
7
+ const COLORS = {
8
+ reset: '\x1b[0m',
9
+ green: '\x1b[32m',
10
+ yellow: '\x1b[33m',
11
+ cyan: '\x1b[36m',
12
+ dim: '\x1b[2m'
13
+ };
10
14
 
11
- constructor(shouldSeed = false) {
12
- this.#shouldSeed = shouldSeed;
15
+ export default async function migrateFresh(options = {}) {
16
+ const { seed: shouldSeed = false } = options;
17
+
18
+ dotenv.config({ quiet: true });
19
+ await Config.initialize();
20
+
21
+ try {
22
+ await DB.setup();
23
+ } catch (error) {
24
+ console.error('❌ Database setup failed:', error.message);
25
+ console.error('Check your .env file and ensure the database exists and is accessible');
26
+ return false;
13
27
  }
14
28
 
15
- async run() {
16
- dotenv.config({ quiet: true });
17
- await Config.initialize();
18
-
19
- try {
20
- await DB.setup();
21
- }
22
- catch (error) {
23
- console.error('❌ Database setup failed:', error.message);
24
- console.error('Check your .env file and ensure the database exists and is accessible');
25
- return false;
26
- }
29
+ try {
30
+ console.log(`${COLORS.yellow}⚠️ Dropping all tables...${COLORS.reset}\n`);
27
31
 
28
- await this.#dropAllTables();
29
- await this.#runMigrations();
30
-
31
- if (this.#shouldSeed) {
32
- await this.#runSeeders();
33
- }
32
+ const [tableRows] = await DB.query("SHOW TABLES");
33
+ await DB.rawQuery("SET FOREIGN_KEY_CHECKS = 0");
34
34
 
35
- await DB.close();
36
- return true;
37
- }
35
+ for (const row of tableRows) {
36
+ const tableName = Object.values(row)[0];
37
+ console.log(`${COLORS.dim}Dropping:${COLORS.reset} ${COLORS.cyan}${tableName}${COLORS.reset}`);
38
+ await DB.rawQuery(`DROP TABLE IF EXISTS \`${tableName}\``);
39
+ }
38
40
 
39
- async #dropAllTables() {
40
- const connection = await DB.connection();
41
- const currentTables = await connection.query("SHOW TABLES");
42
- await connection.query("SET FOREIGN_KEY_CHECKS = 0");
41
+ await DB.rawQuery("SET FOREIGN_KEY_CHECKS = 1");
43
42
 
44
- for (const table of currentTables[0]) {
45
- const tableName = Object.values(table)[0];
46
- console.log(`❌ [\x1b[36m${tableName}\x1b[0m] Dropping table...`);
47
- await connection.query(`DROP TABLE IF EXISTS \`${tableName}\``);
48
- console.log(`✅ [\x1b[36m${tableName}\x1b[0m] Table dropped\n`);
43
+ if (tableRows.length > 0) {
44
+ console.log(`\n${COLORS.green}✅ Dropped ${tableRows.length} table(s)${COLORS.reset}\n`);
49
45
  }
50
46
 
51
- await connection.query("SET FOREIGN_KEY_CHECKS = 1");
52
- }
47
+ const result = await MigrationRunner.run();
53
48
 
54
- async #runMigrations() {
55
- const migrationsDir = Paths.migrations;
56
- const files = fs.readdirSync(migrationsDir);
49
+ if (!result.success) {
50
+ await DB.close();
51
+ return false;
52
+ }
57
53
 
58
- for (const file of files) {
59
- const filePath = Paths.migrationUrl(file);
60
- const module = await import(filePath);
61
- console.log(`📦 [\x1b[36m${module.default.name}\x1b[0m] Creating table...`);
62
- await module.default.up();
63
- console.log(`✅ [\x1b[36m${module.default.name}\x1b[0m] Table created successfully\n`);
54
+ if (shouldSeed && result.ran.length > 0) {
55
+ console.log('\n');
56
+ await seed();
64
57
  }
65
- }
66
58
 
67
- async #runSeeders() {
68
- const seedersDir = Paths.seeders;
69
- const seedFiles = fs.readdirSync(seedersDir);
59
+ await DB.close();
60
+ return true;
70
61
 
71
- for (const file of seedFiles) {
72
- const filePath = Paths.seederUrl(file);
73
- const seeder = await import(filePath);
74
- console.log(`🌱 [\x1b[36m${seeder.default.name}\x1b[0m] Seeding...`);
75
- await seeder.default.run();
76
- console.log(`✅ [\x1b[36m${seeder.default.name}\x1b[0m] Seeding completed\n`);
77
- }
62
+ } catch (error) {
63
+ console.error('❌ Fresh migration error:', error.message);
64
+ await DB.close();
65
+ return false;
78
66
  }
79
67
  }
80
68
 
81
- export default async function migrateFresh(shouldSeed = false) {
82
- const instance = new MigrateFresh(shouldSeed);
83
- return instance.run();
84
- }
85
-
86
- // Auto-run when called directly
87
69
  const isMain = process.argv[1]?.endsWith("MigrateFreshCommand.js");
88
70
  if (isMain) {
89
71
  const args = process.argv.slice(2);
90
72
  const shouldSeed = args.includes("--seed");
91
- migrateFresh(shouldSeed)
73
+
74
+ migrateFresh({ seed: shouldSeed })
92
75
  .then(success => process.exit(success ? 0 : 1))
93
76
  .catch(err => {
94
77
  console.error(err);
@@ -0,0 +1,52 @@
1
+ import dotenv from 'dotenv';
2
+ import DB from '../../Database/DB.js';
3
+ import Config from '../../Core/Config.js';
4
+ import MigrationRunner from '../../Database/Migration/MigrationRunner.js';
5
+
6
+ export default async function rollback(options = {}) {
7
+ const { step = 1, all = false } = options;
8
+
9
+ dotenv.config({ quiet: true });
10
+ await Config.initialize();
11
+
12
+ try {
13
+ await DB.setup();
14
+ } catch (error) {
15
+ console.error('❌ Database setup failed:', error.message);
16
+ console.error('Check your .env file and ensure the database exists and is accessible');
17
+ return false;
18
+ }
19
+
20
+ try {
21
+ let result;
22
+
23
+ if (all) {
24
+ result = await MigrationRunner.reset();
25
+ } else {
26
+ result = await MigrationRunner.rollback(step);
27
+ }
28
+
29
+ await DB.close();
30
+ return result.success;
31
+
32
+ } catch (error) {
33
+ console.error('❌ Rollback error:', error.message);
34
+ await DB.close();
35
+ return false;
36
+ }
37
+ }
38
+
39
+ const isMain = process.argv[1]?.endsWith("MigrateRollbackCommand.js");
40
+ if (isMain) {
41
+ const args = process.argv.slice(2);
42
+ const stepArg = args.find(arg => arg.startsWith('--step='));
43
+ const step = stepArg ? parseInt(stepArg.split('=')[1], 10) : 1;
44
+ const all = args.includes('--all');
45
+
46
+ rollback({ step, all })
47
+ .then(success => process.exit(success ? 0 : 1))
48
+ .catch(err => {
49
+ console.error(err);
50
+ process.exit(1);
51
+ });
52
+ }
@@ -0,0 +1,38 @@
1
+ import dotenv from 'dotenv';
2
+ import DB from '../../Database/DB.js';
3
+ import Config from '../../Core/Config.js';
4
+ import MigrationRunner from '../../Database/Migration/MigrationRunner.js';
5
+
6
+ export default async function status() {
7
+ dotenv.config({ quiet: true });
8
+ await Config.initialize();
9
+
10
+ try {
11
+ await DB.setup();
12
+ } catch (error) {
13
+ console.error('❌ Database setup failed:', error.message);
14
+ console.error('Check your .env file and ensure the database exists and is accessible');
15
+ return false;
16
+ }
17
+
18
+ try {
19
+ await MigrationRunner.printStatus();
20
+ await DB.close();
21
+ return true;
22
+
23
+ } catch (error) {
24
+ console.error('❌ Status error:', error.message);
25
+ await DB.close();
26
+ return false;
27
+ }
28
+ }
29
+
30
+ const isMain = process.argv[1]?.endsWith("MigrateStatusCommand.js");
31
+ if (isMain) {
32
+ status()
33
+ .then(success => process.exit(success ? 0 : 1))
34
+ .catch(err => {
35
+ console.error(err);
36
+ process.exit(1);
37
+ });
38
+ }
@@ -1,89 +1,60 @@
1
- #!/usr/bin/env node
2
- import fs from 'fs';
3
- import path from 'path';
4
1
  import dotenv from 'dotenv';
5
2
  import DB from '../../Database/DB.js';
6
- import Paths from '../../Core/Paths.js';
7
3
  import Config from '../../Core/Config.js';
4
+ import SeederRunner from '../../Database/Seeder/SeederRunner.js';
8
5
 
9
- class Seed {
10
- #seederClass;
6
+ export default async function seed(options = {}) {
7
+ const { environment = 'prod', status = false } = options;
11
8
 
12
- constructor(seederClass = null) {
13
- this.#seederClass = seederClass;
9
+ dotenv.config({ quiet: true });
10
+ await Config.initialize();
11
+
12
+ try {
13
+ await DB.setup();
14
+ } catch (error) {
15
+ console.error('❌ Database setup failed:', error.message);
16
+ console.error('Check your .env file and ensure the database exists and is accessible');
17
+ return false;
14
18
  }
15
19
 
16
- async run() {
17
- dotenv.config({ quiet: true });
18
- await Config.initialize();
19
-
20
- try {
21
- await DB.setup();
22
- } catch (error) {
23
- console.error('❌ Database setup failed:', error.message);
24
- console.error('Check your .env file and ensure the database exists and is accessible');
25
- return false;
20
+ try {
21
+ if (status) {
22
+ await SeederRunner.printStatus();
23
+ await DB.close();
24
+ return true;
26
25
  }
27
26
 
28
- if (this.#seederClass) {
29
- await this.#runSeeder(this.#seederClass);
27
+ let result;
28
+
29
+ if (environment === 'all') {
30
+ result = await SeederRunner.runAll();
30
31
  } else {
31
- await this.#runAllSeeders();
32
+ result = await SeederRunner.run(environment);
32
33
  }
33
34
 
34
35
  await DB.close();
35
- return true;
36
- }
37
-
38
- async #runSeeder(className) {
39
- const file = className + ".js";
40
- const filePath = Paths.seederUrl(file);
41
-
42
- try {
43
- const seeder = await import(filePath);
44
- console.log(`🌱 [\x1b[36m${seeder.default.name}\x1b[0m] Seeding...`);
45
- await seeder.default.run();
46
- console.log(`✅ [\x1b[36m${seeder.default.name}\x1b[0m] Seeding completed\n`);
47
- } catch (error) {
48
- console.error(`❌ Seeder '${className}' not found or failed:`, error.message);
49
- throw error;
50
- }
51
- }
36
+ return result.success;
52
37
 
53
- async #runAllSeeders() {
54
- const seedersDir = Paths.seeders;
55
- const seedFiles = fs.readdirSync(seedersDir);
56
-
57
- if (seedFiles.length === 0) {
58
- console.log("No seeders found in database/seeders");
59
- return;
60
- }
61
-
62
- for (const file of seedFiles) {
63
- const filePath = Paths.seederUrl(file);
64
- const seeder = await import(filePath);
65
- console.log(`🌱 [\x1b[36m${seeder.default.name}\x1b[0m] Seeding...`);
66
- await seeder.default.run();
67
- console.log(`✅ [\x1b[36m${seeder.default.name}\x1b[0m] Seeding completed\n`);
68
- }
38
+ } catch (error) {
39
+ console.error('❌ Seeding error:', error.message);
40
+ await DB.close();
41
+ return false;
69
42
  }
70
43
  }
71
44
 
72
- export default async function seed(seederClass = null) {
73
- const instance = new Seed(seederClass);
74
- return instance.run();
75
- }
76
-
77
- // Auto-run when called directly
78
45
  const isMain = process.argv[1]?.endsWith("SeedCommand.js");
79
46
  if (isMain) {
80
47
  const args = process.argv.slice(2);
81
- const classArg = args.find(arg => arg.startsWith('--class='));
82
- const seederClass = classArg
83
- ? classArg.split('=')[1]
84
- : (args[0] && !args[0].startsWith('-') ? args[0] : null);
85
48
 
86
- seed(seederClass)
49
+ const showStatus = args.includes('--status');
50
+ const isDev = args.includes('--dev');
51
+ const isAll = args.includes('--all');
52
+
53
+ let environment = 'prod';
54
+ if (isDev) environment = 'dev';
55
+ if (isAll) environment = 'all';
56
+
57
+ seed({ environment, status: showStatus })
87
58
  .then(success => process.exit(success ? 0 : 1))
88
59
  .catch(err => {
89
60
  console.error(err);
package/lib/Core/Paths.js CHANGED
@@ -92,6 +92,14 @@ class Paths {
92
92
  return path.join(this.#project, "database/seeders");
93
93
  }
94
94
 
95
+ static get seedersProd() {
96
+ return path.join(this.#project, "database/seeders/prod");
97
+ }
98
+
99
+ static get seedersDev() {
100
+ return path.join(this.#project, "database/seeders/dev");
101
+ }
102
+
95
103
  static get storage() {
96
104
  return path.join(this.#project, "storage");
97
105
  }
@@ -0,0 +1,23 @@
1
+ import { createHash } from 'crypto';
2
+ import fs from 'fs';
3
+
4
+ class Checksum {
5
+
6
+ static fromFile(filePath) {
7
+ const content = fs.readFileSync(filePath, 'utf8');
8
+ return this.fromContent(content);
9
+ }
10
+
11
+ static fromContent(content) {
12
+ const normalized = content.replace(/\r\n/g, '\n').trim();
13
+ return createHash('sha256').update(normalized, 'utf8').digest('hex');
14
+ }
15
+
16
+ static verify(filePath, expectedChecksum) {
17
+ const actualChecksum = this.fromFile(filePath);
18
+ return actualChecksum === expectedChecksum;
19
+ }
20
+
21
+ }
22
+
23
+ export default Checksum;