@seip/blue-bird 0.3.3 → 0.3.4
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/.env_example +23 -13
- package/LICENSE +21 -21
- package/README.md +79 -79
- package/backend/index.js +12 -12
- package/backend/routes/api.js +34 -34
- package/backend/routes/frontend.js +1 -8
- package/core/app.js +359 -359
- package/core/auth.js +69 -69
- package/core/cache.js +35 -35
- package/core/cli/component.js +42 -42
- package/core/cli/init.js +120 -118
- package/core/cli/react.js +383 -411
- package/core/cli/route.js +42 -42
- package/core/cli/scaffolding-auth.js +967 -0
- package/core/config.js +41 -41
- package/core/debug.js +248 -248
- package/core/logger.js +80 -80
- package/core/middleware.js +27 -27
- package/core/router.js +134 -134
- package/core/swagger.js +24 -24
- package/core/template.js +288 -288
- package/core/upload.js +76 -76
- package/core/validate.js +291 -290
- package/frontend/index.html +28 -22
- package/frontend/resources/js/App.jsx +28 -42
- package/frontend/resources/js/Main.jsx +17 -17
- package/frontend/resources/js/blue-bird/components/Button.jsx +67 -0
- package/frontend/resources/js/blue-bird/components/Card.jsx +17 -0
- package/frontend/resources/js/blue-bird/components/DataTable.jsx +126 -0
- package/frontend/resources/js/blue-bird/components/Input.jsx +21 -0
- package/frontend/resources/js/blue-bird/components/Label.jsx +12 -0
- package/frontend/resources/js/blue-bird/components/Modal.jsx +27 -0
- package/frontend/resources/js/blue-bird/components/Translate.jsx +12 -0
- package/frontend/resources/js/blue-bird/components/Typography.jsx +25 -0
- package/frontend/resources/js/blue-bird/contexts/LanguageContext.jsx +29 -0
- package/frontend/resources/js/blue-bird/contexts/SnackbarContext.jsx +38 -0
- package/frontend/resources/js/blue-bird/contexts/ThemeContext.jsx +49 -0
- package/frontend/resources/js/blue-bird/locales/en.json +30 -0
- package/frontend/resources/js/blue-bird/locales/es.json +30 -0
- package/frontend/resources/js/pages/About.jsx +33 -15
- package/frontend/resources/js/pages/Home.jsx +93 -68
- package/package.json +56 -55
- package/vite.config.js +21 -21
package/core/auth.js
CHANGED
|
@@ -1,69 +1,69 @@
|
|
|
1
|
-
import jwt from "jsonwebtoken";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Auth class to handle JWT generation, verification and protection.
|
|
5
|
-
*/
|
|
6
|
-
class Auth {
|
|
7
|
-
/**
|
|
8
|
-
* Generates a JWT token.
|
|
9
|
-
* @param {Object} payload - The data to store in the token.
|
|
10
|
-
* @param {string} [secret=process.env.JWT_SECRET] - The secret key.
|
|
11
|
-
* @param {string|number} [expiresIn='24h'] - Expiration time.
|
|
12
|
-
* @returns {string} The generated token.
|
|
13
|
-
* @example
|
|
14
|
-
* const token = Auth.generateToken({ id: 1 });
|
|
15
|
-
* console.log(token);
|
|
16
|
-
*
|
|
17
|
-
*/
|
|
18
|
-
static generateToken(payload, secret = process.env.JWT_SECRET || 'blue-bird-secret', expiresIn = '24h') {
|
|
19
|
-
return jwt.sign(payload, secret, { expiresIn });
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Verifies a JWT token.
|
|
24
|
-
* @param {string} token - The token to verify.
|
|
25
|
-
* @param {string} [secret=process.env.JWT_SECRET] - The secret key.
|
|
26
|
-
* @returns {Object|null} The decoded payload or null if invalid.
|
|
27
|
-
* @example
|
|
28
|
-
* const token = Auth.generateToken({ id: 1 });
|
|
29
|
-
* const decoded = Auth.verifyToken(token);
|
|
30
|
-
* console.log(decoded);
|
|
31
|
-
*/
|
|
32
|
-
static verifyToken(token, secret = process.env.JWT_SECRET || 'blue-bird-secret') {
|
|
33
|
-
try {
|
|
34
|
-
return jwt.verify(token, secret);
|
|
35
|
-
} catch (error) {
|
|
36
|
-
return null;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Middleware to protect routes. Checks for token in Cookies or Authorization header.
|
|
42
|
-
* @param {Object} options - Options for protection.
|
|
43
|
-
* @param {string} [options.redirect] - URL to redirect if not authenticated (for web routes).
|
|
44
|
-
* @returns {Function} Express middleware.
|
|
45
|
-
* @example
|
|
46
|
-
* app.use(Auth.protect({ redirect: "/login" }));
|
|
47
|
-
*/
|
|
48
|
-
static protect(options = { redirect: null }) {
|
|
49
|
-
return (req, res, next) => {
|
|
50
|
-
const token = req.cookies?.token || req.headers.authorization?.split(" ")[1];
|
|
51
|
-
|
|
52
|
-
if (!token) {
|
|
53
|
-
if (options.redirect) return res.redirect(options.redirect);
|
|
54
|
-
return res.status(401).json({ message: "Unauthorized: No token provided" });
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const decoded = this.verifyToken(token);
|
|
58
|
-
if (!decoded) {
|
|
59
|
-
if (options.redirect) return res.redirect(options.redirect);
|
|
60
|
-
return res.status(401).json({ message: "Unauthorized: Invalid token" });
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
req.user = decoded;
|
|
64
|
-
next();
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export default Auth;
|
|
1
|
+
import jwt from "jsonwebtoken";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Auth class to handle JWT generation, verification and protection.
|
|
5
|
+
*/
|
|
6
|
+
class Auth {
|
|
7
|
+
/**
|
|
8
|
+
* Generates a JWT token.
|
|
9
|
+
* @param {Object} payload - The data to store in the token.
|
|
10
|
+
* @param {string} [secret=process.env.JWT_SECRET] - The secret key.
|
|
11
|
+
* @param {string|number} [expiresIn='24h'] - Expiration time.
|
|
12
|
+
* @returns {string} The generated token.
|
|
13
|
+
* @example
|
|
14
|
+
* const token = Auth.generateToken({ id: 1 });
|
|
15
|
+
* console.log(token);
|
|
16
|
+
*
|
|
17
|
+
*/
|
|
18
|
+
static generateToken(payload, secret = process.env.JWT_SECRET || 'blue-bird-secret', expiresIn = '24h') {
|
|
19
|
+
return jwt.sign(payload, secret, { expiresIn });
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Verifies a JWT token.
|
|
24
|
+
* @param {string} token - The token to verify.
|
|
25
|
+
* @param {string} [secret=process.env.JWT_SECRET] - The secret key.
|
|
26
|
+
* @returns {Object|null} The decoded payload or null if invalid.
|
|
27
|
+
* @example
|
|
28
|
+
* const token = Auth.generateToken({ id: 1 });
|
|
29
|
+
* const decoded = Auth.verifyToken(token);
|
|
30
|
+
* console.log(decoded);
|
|
31
|
+
*/
|
|
32
|
+
static verifyToken(token, secret = process.env.JWT_SECRET || 'blue-bird-secret') {
|
|
33
|
+
try {
|
|
34
|
+
return jwt.verify(token, secret);
|
|
35
|
+
} catch (error) {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Middleware to protect routes. Checks for token in Cookies or Authorization header.
|
|
42
|
+
* @param {Object} options - Options for protection.
|
|
43
|
+
* @param {string} [options.redirect] - URL to redirect if not authenticated (for web routes).
|
|
44
|
+
* @returns {Function} Express middleware.
|
|
45
|
+
* @example
|
|
46
|
+
* app.use(Auth.protect({ redirect: "/login" }));
|
|
47
|
+
*/
|
|
48
|
+
static protect(options = { redirect: null }) {
|
|
49
|
+
return (req, res, next) => {
|
|
50
|
+
const token = req.cookies?.token || req.headers.authorization?.split(" ")[1];
|
|
51
|
+
|
|
52
|
+
if (!token) {
|
|
53
|
+
if (options.redirect) return res.redirect(options.redirect);
|
|
54
|
+
return res.status(401).json({ message: "Unauthorized: No token provided" });
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const decoded = this.verifyToken(token);
|
|
58
|
+
if (!decoded) {
|
|
59
|
+
if (options.redirect) return res.redirect(options.redirect);
|
|
60
|
+
return res.status(401).json({ message: "Unauthorized: Invalid token" });
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
req.user = decoded;
|
|
64
|
+
next();
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export default Auth;
|
package/core/cache.js
CHANGED
|
@@ -1,36 +1,36 @@
|
|
|
1
|
-
const CACHE = {};
|
|
2
|
-
/**
|
|
3
|
-
* Cache Middleware
|
|
4
|
-
* @example
|
|
5
|
-
* router.get("/stats",
|
|
6
|
-
Cache.middleware(120),
|
|
7
|
-
controller.stats
|
|
8
|
-
);
|
|
9
|
-
* */
|
|
10
|
-
class Cache {
|
|
11
|
-
|
|
12
|
-
static middleware(seconds = 60) {
|
|
13
|
-
return (req, res, next) => {
|
|
14
|
-
|
|
15
|
-
const key = req.originalUrl;
|
|
16
|
-
|
|
17
|
-
if (CACHE[key] && CACHE[key].expiry > Date.now()) {
|
|
18
|
-
return res.json(CACHE[key].data);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const originalJson = res.json.bind(res);
|
|
22
|
-
|
|
23
|
-
res.json = (body) => {
|
|
24
|
-
CACHE[key] = {
|
|
25
|
-
data: body,
|
|
26
|
-
expiry: Date.now() + seconds * 1000
|
|
27
|
-
};
|
|
28
|
-
return originalJson(body);
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
next();
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
1
|
+
const CACHE = {};
|
|
2
|
+
/**
|
|
3
|
+
* Cache Middleware
|
|
4
|
+
* @example
|
|
5
|
+
* router.get("/stats",
|
|
6
|
+
Cache.middleware(120),
|
|
7
|
+
controller.stats
|
|
8
|
+
);
|
|
9
|
+
* */
|
|
10
|
+
class Cache {
|
|
11
|
+
|
|
12
|
+
static middleware(seconds = 60) {
|
|
13
|
+
return (req, res, next) => {
|
|
14
|
+
|
|
15
|
+
const key = req.originalUrl;
|
|
16
|
+
|
|
17
|
+
if (CACHE[key] && CACHE[key].expiry > Date.now()) {
|
|
18
|
+
return res.json(CACHE[key].data);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const originalJson = res.json.bind(res);
|
|
22
|
+
|
|
23
|
+
res.json = (body) => {
|
|
24
|
+
CACHE[key] = {
|
|
25
|
+
data: body,
|
|
26
|
+
expiry: Date.now() + seconds * 1000
|
|
27
|
+
};
|
|
28
|
+
return originalJson(body);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
next();
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
36
|
export default Cache;
|
package/core/cli/component.js
CHANGED
|
@@ -1,42 +1,42 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
|
-
import fs from "node:fs";
|
|
3
|
-
import Config from "../config.js";
|
|
4
|
-
|
|
5
|
-
const __dirname = Config.dirname();
|
|
6
|
-
|
|
7
|
-
class ComponentCLI {
|
|
8
|
-
/**
|
|
9
|
-
* Create component react
|
|
10
|
-
* @return {void}
|
|
11
|
-
* /
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
create() {
|
|
15
|
-
const folder = path.join(process.cwd(), "frontend/resources/components");
|
|
16
|
-
if (!fs.existsSync(folder)) {
|
|
17
|
-
fs.mkdirSync(folder, { recursive: true });
|
|
18
|
-
}
|
|
19
|
-
let nameComponent =`Component-${Math.random().toString(36).substring(7)}`;
|
|
20
|
-
const nameParam = process.argv[2];
|
|
21
|
-
if (nameParam.length > 0 && typeof nameParam === "string") {
|
|
22
|
-
nameComponent = nameParam;
|
|
23
|
-
nameComponent = nameComponent.charAt(0).toUpperCase() + nameComponent.slice(1);
|
|
24
|
-
}
|
|
25
|
-
const filePath = path.join(folder, `${nameComponent}.jsx`);
|
|
26
|
-
const content = `import React from 'react';
|
|
27
|
-
|
|
28
|
-
export default function ${nameComponent}() {
|
|
29
|
-
return (
|
|
30
|
-
<div>
|
|
31
|
-
<h1>${nameComponent} Component</h1>
|
|
32
|
-
</div>
|
|
33
|
-
);
|
|
34
|
-
}
|
|
35
|
-
`;
|
|
36
|
-
fs.writeFileSync(filePath, content);
|
|
37
|
-
console.log(`Component ${nameComponent} created at ${filePath}`);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const componentCLI = new ComponentCLI();
|
|
42
|
-
componentCLI.create();
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import Config from "../config.js";
|
|
4
|
+
|
|
5
|
+
const __dirname = Config.dirname();
|
|
6
|
+
|
|
7
|
+
class ComponentCLI {
|
|
8
|
+
/**
|
|
9
|
+
* Create component react
|
|
10
|
+
* @return {void}
|
|
11
|
+
* /
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
create() {
|
|
15
|
+
const folder = path.join(process.cwd(), "frontend/resources/components");
|
|
16
|
+
if (!fs.existsSync(folder)) {
|
|
17
|
+
fs.mkdirSync(folder, { recursive: true });
|
|
18
|
+
}
|
|
19
|
+
let nameComponent =`Component-${Math.random().toString(36).substring(7)}`;
|
|
20
|
+
const nameParam = process.argv[2];
|
|
21
|
+
if (nameParam.length > 0 && typeof nameParam === "string") {
|
|
22
|
+
nameComponent = nameParam;
|
|
23
|
+
nameComponent = nameComponent.charAt(0).toUpperCase() + nameComponent.slice(1);
|
|
24
|
+
}
|
|
25
|
+
const filePath = path.join(folder, `${nameComponent}.jsx`);
|
|
26
|
+
const content = `import React from 'react';
|
|
27
|
+
|
|
28
|
+
export default function ${nameComponent}() {
|
|
29
|
+
return (
|
|
30
|
+
<div>
|
|
31
|
+
<h1>${nameComponent} Component</h1>
|
|
32
|
+
</div>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
`;
|
|
36
|
+
fs.writeFileSync(filePath, content);
|
|
37
|
+
console.log(`Component ${nameComponent} created at ${filePath}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const componentCLI = new ComponentCLI();
|
|
42
|
+
componentCLI.create();
|
package/core/cli/init.js
CHANGED
|
@@ -1,118 +1,120 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import fs from "node:fs";
|
|
4
|
-
import path from "node:path";
|
|
5
|
-
import chalk from "chalk";
|
|
6
|
-
|
|
7
|
-
class ProjectInit {
|
|
8
|
-
constructor() {
|
|
9
|
-
this.appDir = process.cwd();
|
|
10
|
-
this.sourceDir = path.resolve(import.meta.dirname, "../../");
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
async run() {
|
|
14
|
-
console.log(chalk.cyan("Starting Blue Bird project initialization..."));
|
|
15
|
-
|
|
16
|
-
const itemsToCopy = [
|
|
17
|
-
"backend",
|
|
18
|
-
"frontend",
|
|
19
|
-
".env_example"
|
|
20
|
-
];
|
|
21
|
-
|
|
22
|
-
try {
|
|
23
|
-
itemsToCopy.forEach(item => {
|
|
24
|
-
const src = path.join(this.sourceDir, item);
|
|
25
|
-
const dest = path.join(this.appDir, item);
|
|
26
|
-
|
|
27
|
-
if (fs.existsSync(src)) {
|
|
28
|
-
if (!fs.existsSync(dest)) {
|
|
29
|
-
this.copyRecursive(src, dest);
|
|
30
|
-
console.log(chalk.green(`✓ Copied ${item} to root.`));
|
|
31
|
-
} else {
|
|
32
|
-
console.log(chalk.yellow(`! ${item} already exists, skipping.`));
|
|
33
|
-
}
|
|
34
|
-
} else {
|
|
35
|
-
console.warn(chalk.red(`✗ Source ${item} not found in ${this.sourceDir}`));
|
|
36
|
-
}
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
const envPath = path.join(this.appDir, ".env");
|
|
40
|
-
const envExamplePath = path.join(this.appDir, ".env_example");
|
|
41
|
-
if (fs.existsSync(envExamplePath) && !fs.existsSync(envPath)) {
|
|
42
|
-
fs.copyFileSync(envExamplePath, envPath);
|
|
43
|
-
console.log(chalk.green("✓ Created .env from .env_example."));
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
this.updatePackageJson();
|
|
47
|
-
|
|
48
|
-
console.log(chalk.blue("\nBlue Bird initialization completed!"));
|
|
49
|
-
console.log(chalk.white("Next steps:"));
|
|
50
|
-
console.log(chalk.bold(" npm install"));
|
|
51
|
-
console.log(chalk.bold(" npm run react"));
|
|
52
|
-
console.log(chalk.bold(" npm run dev"));
|
|
53
|
-
|
|
54
|
-
} catch (error) {
|
|
55
|
-
console.error(chalk.red("Error during initialization:"), error.message);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
updatePackageJson() {
|
|
60
|
-
const pkgPath = path.join(this.appDir, "package.json");
|
|
61
|
-
if (fs.existsSync(pkgPath)) {
|
|
62
|
-
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
63
|
-
pkg.scripts = pkg.scripts || {};
|
|
64
|
-
|
|
65
|
-
const scriptsToAdd = {
|
|
66
|
-
"dev": "node --watch --env-file=.env backend/index.js",
|
|
67
|
-
"start": "node --env-file=.env backend/index.js",
|
|
68
|
-
"react": "blue-bird react",
|
|
69
|
-
"init": "blue-bird",
|
|
70
|
-
"route": "blue-bird route",
|
|
71
|
-
"component": "blue-bird component",
|
|
72
|
-
"swagger-install": "blue-bird swagger-install"
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
else if (command === "
|
|
115
|
-
else if (command === "
|
|
116
|
-
else
|
|
117
|
-
|
|
118
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import chalk from "chalk";
|
|
6
|
+
|
|
7
|
+
class ProjectInit {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.appDir = process.cwd();
|
|
10
|
+
this.sourceDir = path.resolve(import.meta.dirname, "../../");
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async run() {
|
|
14
|
+
console.log(chalk.cyan("Starting Blue Bird project initialization..."));
|
|
15
|
+
|
|
16
|
+
const itemsToCopy = [
|
|
17
|
+
"backend",
|
|
18
|
+
"frontend",
|
|
19
|
+
".env_example"
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
itemsToCopy.forEach(item => {
|
|
24
|
+
const src = path.join(this.sourceDir, item);
|
|
25
|
+
const dest = path.join(this.appDir, item);
|
|
26
|
+
|
|
27
|
+
if (fs.existsSync(src)) {
|
|
28
|
+
if (!fs.existsSync(dest)) {
|
|
29
|
+
this.copyRecursive(src, dest);
|
|
30
|
+
console.log(chalk.green(`✓ Copied ${item} to root.`));
|
|
31
|
+
} else {
|
|
32
|
+
console.log(chalk.yellow(`! ${item} already exists, skipping.`));
|
|
33
|
+
}
|
|
34
|
+
} else {
|
|
35
|
+
console.warn(chalk.red(`✗ Source ${item} not found in ${this.sourceDir}`));
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const envPath = path.join(this.appDir, ".env");
|
|
40
|
+
const envExamplePath = path.join(this.appDir, ".env_example");
|
|
41
|
+
if (fs.existsSync(envExamplePath) && !fs.existsSync(envPath)) {
|
|
42
|
+
fs.copyFileSync(envExamplePath, envPath);
|
|
43
|
+
console.log(chalk.green("✓ Created .env from .env_example."));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
this.updatePackageJson();
|
|
47
|
+
|
|
48
|
+
console.log(chalk.blue("\nBlue Bird initialization completed!"));
|
|
49
|
+
console.log(chalk.white("Next steps:"));
|
|
50
|
+
console.log(chalk.bold(" npm install"));
|
|
51
|
+
console.log(chalk.bold(" npm run react"));
|
|
52
|
+
console.log(chalk.bold(" npm run dev"));
|
|
53
|
+
|
|
54
|
+
} catch (error) {
|
|
55
|
+
console.error(chalk.red("Error during initialization:"), error.message);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
updatePackageJson() {
|
|
60
|
+
const pkgPath = path.join(this.appDir, "package.json");
|
|
61
|
+
if (fs.existsSync(pkgPath)) {
|
|
62
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
63
|
+
pkg.scripts = pkg.scripts || {};
|
|
64
|
+
|
|
65
|
+
const scriptsToAdd = {
|
|
66
|
+
"dev": "node --watch --env-file=.env backend/index.js",
|
|
67
|
+
"start": "node --env-file=.env backend/index.js",
|
|
68
|
+
"react": "blue-bird react",
|
|
69
|
+
"init": "blue-bird",
|
|
70
|
+
"route": "blue-bird route",
|
|
71
|
+
"component": "blue-bird component",
|
|
72
|
+
"swagger-install": "blue-bird swagger-install",
|
|
73
|
+
"scaffolding-auth": "blue-bird scaffolding-auth"
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
let updated = false;
|
|
77
|
+
for (const [key, value] of Object.entries(scriptsToAdd)) {
|
|
78
|
+
if (!pkg.scripts[key]) {
|
|
79
|
+
pkg.scripts[key] = value;
|
|
80
|
+
updated = true;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (updated) {
|
|
85
|
+
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
|
|
86
|
+
console.log(chalk.green("✓ Updated package.json scripts."));
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
copyRecursive(src, dest) {
|
|
92
|
+
const stats = fs.statSync(src);
|
|
93
|
+
const isDirectory = stats.isDirectory();
|
|
94
|
+
|
|
95
|
+
if (isDirectory) {
|
|
96
|
+
if (!fs.existsSync(dest)) {
|
|
97
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
98
|
+
}
|
|
99
|
+
fs.readdirSync(src).forEach(childItemName => {
|
|
100
|
+
this.copyRecursive(path.join(src, childItemName), path.join(dest, childItemName));
|
|
101
|
+
});
|
|
102
|
+
} else {
|
|
103
|
+
fs.copyFileSync(src, dest);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const initializer = new ProjectInit();
|
|
109
|
+
|
|
110
|
+
const args = process.argv.slice(2);
|
|
111
|
+
const command = args[0];
|
|
112
|
+
|
|
113
|
+
if (command === "react") import("./react.js");
|
|
114
|
+
else if (command === "route") import("./route.js")
|
|
115
|
+
else if (command === "component") import("./component.js")
|
|
116
|
+
else if (command === "swagger-install") import("./swagger.js")
|
|
117
|
+
else if (command === "scaffolding-auth") import("./scaffolding-auth.js")
|
|
118
|
+
else initializer.run();
|
|
119
|
+
|
|
120
|
+
|