@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.
- package/cli/njs.js +33 -5
- package/lib/Build/Manager.js +7 -0
- package/lib/Console/Commands/MigrateCommand.js +27 -70
- package/lib/Console/Commands/MigrateFreshCommand.js +49 -66
- package/lib/Console/Commands/MigrateRollbackCommand.js +52 -0
- package/lib/Console/Commands/MigrateStatusCommand.js +38 -0
- package/lib/Console/Commands/SeedCommand.js +36 -65
- package/lib/Console/Stubs/page-hydration.tsx +9 -9
- package/lib/Core/Paths.js +8 -0
- package/lib/Database/Migration/Checksum.js +23 -0
- package/lib/Database/Migration/MigrationRepository.js +92 -0
- package/lib/Database/Migration/MigrationRunner.js +327 -0
- package/lib/Database/Migration/migrations/0000_00_00_00_00_create_migrations_table.js +21 -0
- package/lib/Database/Migration/migrations/0000_00_00_00_01_create_seeders_table.js +20 -0
- package/lib/Database/Schema/Blueprint.js +0 -40
- package/lib/Database/Schema/Manager.js +29 -40
- package/lib/Database/Seeder/SeederRepository.js +49 -0
- package/lib/Database/Seeder/SeederRunner.js +183 -0
- package/lib/Faker/Data/Address.js +63 -0
- package/lib/Faker/Data/Color.js +72 -0
- package/lib/Faker/Data/Company.js +59 -0
- package/lib/Faker/Data/Date.js +49 -0
- package/lib/Faker/Data/Finance.js +65 -0
- package/lib/Faker/Data/Internet.js +73 -0
- package/lib/Faker/Data/Lorem.js +45 -0
- package/lib/Faker/Data/Person.js +67 -0
- package/lib/Faker/Data/Phone.js +26 -0
- package/lib/Faker/Faker.d.ts +205 -0
- package/lib/Faker/Faker.js +812 -0
- package/lib/View/Manager.js +26 -5
- package/lib/index.d.ts +407 -0
- package/lib/index.js +12 -0
- package/package.json +6 -2
- package/skeleton/config/app.js +20 -0
- package/skeleton/globals.d.ts +68 -1
- 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
|
|
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
|
-
|
|
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
|
|
package/lib/Build/Manager.js
CHANGED
|
@@ -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
|
-
|
|
10
|
-
|
|
11
|
-
#shouldSeed;
|
|
7
|
+
export default async function migrate(options = {}) {
|
|
8
|
+
const { seed: shouldSeed = false } = options;
|
|
12
9
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
-
|
|
20
|
-
|
|
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
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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 (
|
|
50
|
-
|
|
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
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
return
|
|
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
|
-
|
|
92
|
-
migrate(
|
|
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
|
-
|
|
9
|
-
|
|
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
|
-
|
|
12
|
-
|
|
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
|
-
|
|
16
|
-
|
|
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
|
|
29
|
-
await
|
|
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
|
-
|
|
36
|
-
|
|
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
|
-
|
|
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
|
-
|
|
45
|
-
|
|
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
|
|
52
|
-
}
|
|
47
|
+
const result = await MigrationRunner.run();
|
|
53
48
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
49
|
+
if (!result.success) {
|
|
50
|
+
await DB.close();
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
57
53
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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
|
-
|
|
68
|
-
|
|
69
|
-
const seedFiles = fs.readdirSync(seedersDir);
|
|
59
|
+
await DB.close();
|
|
60
|
+
return true;
|
|
70
61
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
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
|
-
|
|
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
|
-
|
|
10
|
-
|
|
6
|
+
export default async function seed(options = {}) {
|
|
7
|
+
const { environment = 'prod', status = false } = options;
|
|
11
8
|
|
|
12
|
-
|
|
13
|
-
|
|
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
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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
|
-
|
|
29
|
-
|
|
27
|
+
let result;
|
|
28
|
+
|
|
29
|
+
if (environment === 'all') {
|
|
30
|
+
result = await SeederRunner.runAll();
|
|
30
31
|
} else {
|
|
31
|
-
await
|
|
32
|
+
result = await SeederRunner.run(environment);
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
await DB.close();
|
|
35
|
-
return
|
|
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
|
-
|
|
54
|
-
|
|
55
|
-
|
|
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
|
-
|
|
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 {
|
|
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
|
|
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
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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",
|
|
50
|
+
document.addEventListener("DOMContentLoaded", mount);
|
|
52
51
|
} else {
|
|
53
|
-
|
|
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;
|