@nitronjs/framework 0.1.22 → 0.1.24

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 (36) hide show
  1. package/cli/njs.js +33 -5
  2. package/lib/Build/Manager.js +7 -0
  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/Console/Stubs/page-hydration.tsx +9 -9
  9. package/lib/Core/Paths.js +8 -0
  10. package/lib/Database/Migration/Checksum.js +23 -0
  11. package/lib/Database/Migration/MigrationRepository.js +92 -0
  12. package/lib/Database/Migration/MigrationRunner.js +327 -0
  13. package/lib/Database/Migration/migrations/0000_00_00_00_00_create_migrations_table.js +21 -0
  14. package/lib/Database/Migration/migrations/0000_00_00_00_01_create_seeders_table.js +20 -0
  15. package/lib/Database/Schema/Blueprint.js +0 -40
  16. package/lib/Database/Schema/Manager.js +29 -40
  17. package/lib/Database/Seeder/SeederRepository.js +49 -0
  18. package/lib/Database/Seeder/SeederRunner.js +183 -0
  19. package/lib/Faker/Data/Address.js +63 -0
  20. package/lib/Faker/Data/Color.js +72 -0
  21. package/lib/Faker/Data/Company.js +59 -0
  22. package/lib/Faker/Data/Date.js +49 -0
  23. package/lib/Faker/Data/Finance.js +65 -0
  24. package/lib/Faker/Data/Internet.js +73 -0
  25. package/lib/Faker/Data/Lorem.js +45 -0
  26. package/lib/Faker/Data/Person.js +67 -0
  27. package/lib/Faker/Data/Phone.js +26 -0
  28. package/lib/Faker/Faker.d.ts +205 -0
  29. package/lib/Faker/Faker.js +812 -0
  30. package/lib/View/Manager.js +26 -5
  31. package/lib/index.d.ts +407 -0
  32. package/lib/index.js +12 -0
  33. package/package.json +6 -2
  34. package/skeleton/config/app.js +20 -0
  35. package/skeleton/globals.d.ts +68 -1
  36. package/skeleton/tsconfig.json +6 -16
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
 
@@ -102,6 +102,7 @@ function wrapWithDepth(children) {
102
102
 
103
103
  function createIsland(Component, name) {
104
104
  function IslandBoundary(props) {
105
+ // Nested client components render normally (already inside an island)
105
106
  if (React.useContext(DepthContext)) {
106
107
  return OriginalJsx.jsx(Component, props);
107
108
  }
@@ -115,6 +116,8 @@ function createIsland(Component, name) {
115
116
  ctx.props[id] = safeProps;
116
117
  }
117
118
 
119
+ // SSR: Render full HTML for SEO and initial paint
120
+ // Client: Will re-render with createRoot for animations to work
118
121
  return OriginalJsx.jsx('div', {
119
122
  'data-cid': id,
120
123
  'data-island': name,
@@ -445,12 +448,16 @@ class Builder {
445
448
  const importName = sanitizeName(baseName) + "_" + index++;
446
449
  imports.push(`import ${importName} from "${relativePath}";`);
447
450
  manifestEntries.push(` "${baseName}": ${importName}`);
451
+ // Also add displayName entry
452
+ manifestEntries.push(` [${importName}.displayName || ${importName}.name || "${baseName}"]: ${importName}`);
448
453
  }
449
454
 
450
455
  for (const namedExport of componentMeta.named || []) {
451
456
  const importName = sanitizeName(namedExport) + "_" + index++;
452
457
  imports.push(`import { ${namedExport} as ${importName} } from "${relativePath}";`);
453
458
  manifestEntries.push(` "${namedExport}": ${importName}`);
459
+ // Also add displayName entry
460
+ manifestEntries.push(` [${importName}.displayName || ${importName}.name || "${namedExport}"]: ${importName}`);
454
461
  }
455
462
  }
456
463
 
@@ -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);
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import { hydrateRoot } from "react-dom/client";
2
+ import { createRoot } from "react-dom/client";
3
3
 
4
4
  // __COMPONENT_IMPORTS__
5
5
 
@@ -13,7 +13,7 @@ const componentManifest: Record<string, React.ComponentType<any>> = {};
13
13
 
14
14
  // __COMPONENT_MANIFEST__
15
15
 
16
- function hydrate() {
16
+ function mount() {
17
17
  const props = window.__NITRON_PROPS__ || {};
18
18
 
19
19
  const islands = document.querySelectorAll<HTMLElement>("[data-cid]");
@@ -35,11 +35,10 @@ function hydrate() {
35
35
  const componentProps = props[componentId] || {};
36
36
 
37
37
  try {
38
- hydrateRoot(
39
- element,
40
- React.createElement(Component, componentProps),
41
- { identifierPrefix: componentId }
42
- );
38
+ // Use createRoot for full client-side rendering
39
+ // This ensures animations and effects work correctly
40
+ const root = createRoot(element);
41
+ root.render(React.createElement(Component, componentProps));
43
42
  } catch {
44
43
  }
45
44
  });
@@ -48,7 +47,8 @@ function hydrate() {
48
47
  }
49
48
 
50
49
  if (document.readyState === "loading") {
51
- document.addEventListener("DOMContentLoaded", hydrate);
50
+ document.addEventListener("DOMContentLoaded", mount);
52
51
  } else {
53
- hydrate();
52
+ mount();
54
53
  }
54
+
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;