create-fullstack-boilerplate 1.0.0 → 2.1.0
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/index.js +38 -6
- package/lib/addDB.js +4 -2
- package/lib/addRoute.js +4 -2
- package/lib/assertDependency.js +14 -0
- package/lib/copyProject.js +4 -2
- package/lib/ensureDir.js +7 -0
- package/lib/installDeps.js +9 -9
- package/lib/runInstall.js +10 -0
- package/lib/setupExtraDB.js +4 -2
- package/lib/testDBConnection.js +60 -2
- package/lib/utils.js +67 -14
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
1
|
+
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
(async () => {
|
|
4
4
|
const argv = process.argv.slice(2);
|
|
@@ -15,30 +15,62 @@
|
|
|
15
15
|
|
|
16
16
|
// ---- Your existing create-project code ----
|
|
17
17
|
const path = require("path");
|
|
18
|
-
const { ensure } = require("./lib/utils");
|
|
18
|
+
// const { ensure } = require("./lib/utils");
|
|
19
19
|
const copyProject = require("./lib/copyProject");
|
|
20
|
-
const
|
|
20
|
+
const { runInstall, installDBDriver } = require("./lib/utils");
|
|
21
21
|
const setupMainDB = require("./lib/setupMainDB");
|
|
22
22
|
const setupExtraDB = require("./lib/setupExtraDB");
|
|
23
23
|
const testDBConnection = require("./lib/testDBConnection");
|
|
24
24
|
const { mainPrompts, extraDBPrompts } = require("./lib/prompts");
|
|
25
25
|
|
|
26
|
-
const fs =
|
|
26
|
+
const fs = require("fs-extra");
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
// Resolve template folder dynamically
|
|
30
|
+
let templateDir;
|
|
31
|
+
|
|
32
|
+
// Try __dirname first (works for local/dev)
|
|
33
|
+
const localTemplate = path.join(__dirname, "template");
|
|
34
|
+
if (fs.existsSync(localTemplate)) {
|
|
35
|
+
templateDir = localTemplate;
|
|
36
|
+
} else {
|
|
37
|
+
// Fallback for npx (temp folder)
|
|
38
|
+
const pkg = require.resolve("create-fullstack-boilerplate/package.json");
|
|
39
|
+
templateDir = path.join(path.dirname(pkg), "template");
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (!fs.existsSync(templateDir)) {
|
|
43
|
+
throw new Error(
|
|
44
|
+
"Template folder not found! Make sure it is included in package.json 'files' and published."
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
console.log("Using template folder:", templateDir);
|
|
49
|
+
|
|
27
50
|
|
|
28
51
|
try {
|
|
29
52
|
console.log("\n🎛️ Setting Up Full Stack Project...\n");
|
|
30
53
|
|
|
31
54
|
const answers = await mainPrompts();
|
|
32
|
-
const templateDir = path.join(__dirname, "template");
|
|
55
|
+
// const templateDir = path.join(__dirname, "template");
|
|
33
56
|
const targetDir = path.join(process.cwd(), answers.projectName);
|
|
34
57
|
|
|
35
58
|
await copyProject(templateDir, targetDir);
|
|
36
59
|
await setupMainDB(targetDir, answers.dbDialect);
|
|
37
|
-
|
|
60
|
+
console.log("➡️ Installing backend dependencies...");
|
|
61
|
+
await runInstall(path.join(targetDir, "backend"));
|
|
62
|
+
|
|
63
|
+
console.log("➡️ Installing frontend dependencies...");
|
|
64
|
+
await runInstall(path.join(targetDir, "frontend"));
|
|
65
|
+
|
|
66
|
+
console.log("➡️ Installing Your Db Dialect: ", answers.dbDialect)
|
|
67
|
+
await installDBDriver(path.join(targetDir, "backend"), answers.dbDialect);
|
|
68
|
+
|
|
38
69
|
|
|
39
70
|
if (answers.addExtraDB) {
|
|
40
71
|
const extraDB = await extraDBPrompts();
|
|
41
72
|
console.log(`\n🔍 Testing connection for ${extraDB.dbKey}...`);
|
|
73
|
+
await installDBDriver(path.join(targetDir, "backend"), extraDB.dialect);
|
|
42
74
|
const ok = await testDBConnection(targetDir, extraDB);
|
|
43
75
|
|
|
44
76
|
if (ok) {
|
package/lib/addDB.js
CHANGED
|
@@ -2,8 +2,10 @@ const path = require("path");
|
|
|
2
2
|
const { extraDBPrompts } = require("./prompts");
|
|
3
3
|
const testDBConnection = require("./testDBConnection");
|
|
4
4
|
const setupExtraDB = require("./setupExtraDB");
|
|
5
|
-
const { ensure } = require("./utils");
|
|
6
|
-
const fs = ensure("fs-extra");
|
|
5
|
+
// const { ensure } = require("./utils");
|
|
6
|
+
// const fs = ensure("fs-extra");
|
|
7
|
+
const fs = require("fs-extra");
|
|
8
|
+
|
|
7
9
|
|
|
8
10
|
module.exports = async function addDB() {
|
|
9
11
|
console.log(`\n➕ Add New Database to Existing Project\n`);
|
package/lib/addRoute.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
const path = require("path");
|
|
2
|
-
const { ensure } = require("./utils");
|
|
2
|
+
// const { ensure } = require("./utils");
|
|
3
3
|
const { routePrompts } = require("./prompts");
|
|
4
|
-
const fs = ensure("fs-extra");
|
|
4
|
+
// const fs = ensure("fs-extra");
|
|
5
|
+
const fs = require("fs-extra");
|
|
6
|
+
|
|
5
7
|
|
|
6
8
|
module.exports = async function addRoute() {
|
|
7
9
|
console.log(`\n➕ Add New Route to Backend\n`);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// const path = require("path");
|
|
2
|
+
|
|
3
|
+
// function assertDependency(depName, cwd) {
|
|
4
|
+
// try {
|
|
5
|
+
// return require(path.join(cwd, "node_modules", depName));
|
|
6
|
+
// } catch (err) {
|
|
7
|
+
// throw new Error(
|
|
8
|
+
// `Dependency '${depName}' is not installed in ${cwd}.\n` +
|
|
9
|
+
// `Run: cd ${cwd} && npm install ${depName}`
|
|
10
|
+
// );
|
|
11
|
+
// }
|
|
12
|
+
// }
|
|
13
|
+
|
|
14
|
+
// module.exports = assertDependency;
|
package/lib/copyProject.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
const {
|
|
2
|
-
const fs = ensure("fs-extra");
|
|
1
|
+
const { log } = require("./utils");
|
|
2
|
+
// const fs = ensure("fs-extra");
|
|
3
|
+
const fs = require("fs-extra");
|
|
4
|
+
|
|
3
5
|
const path = require("path");
|
|
4
6
|
|
|
5
7
|
module.exports = async function copyProject(src, dest) {
|
package/lib/ensureDir.js
ADDED
package/lib/installDeps.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
const execa = require("execa");
|
|
2
|
-
const path = require("path");
|
|
3
|
-
const { log } = require("./utils");
|
|
1
|
+
// const execa = require("execa");
|
|
2
|
+
// const path = require("path");
|
|
3
|
+
// const { log } = require("./utils");
|
|
4
4
|
|
|
5
|
-
module.exports = async function installDeps(targetDir) {
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
// module.exports = async function installDeps(targetDir) {
|
|
6
|
+
// log("Installing backend dependencies...");
|
|
7
|
+
// await execa("npm", ["install"], { cwd: path.join(targetDir, "backend"), stdio: "inherit" });
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
};
|
|
9
|
+
// log("Installing frontend dependencies...");
|
|
10
|
+
// await execa("npm", ["install"], { cwd: path.join(targetDir, "frontend"), stdio: "inherit" });
|
|
11
|
+
// };
|
package/lib/setupExtraDB.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
const path = require("path");
|
|
2
|
-
const { ensure } = require("./utils");
|
|
3
|
-
const fs = ensure("fs-extra");
|
|
2
|
+
// const { ensure } = require("./utils");
|
|
3
|
+
// const fs = ensure("fs-extra");
|
|
4
|
+
const fs = require("fs-extra"); // no assert needed
|
|
5
|
+
|
|
4
6
|
|
|
5
7
|
module.exports = async function setupExtraDB(targetDir, dbConfig) {
|
|
6
8
|
const backendDir = path.join(targetDir, "backend");
|
package/lib/testDBConnection.js
CHANGED
|
@@ -1,8 +1,66 @@
|
|
|
1
|
+
// const path = require("path");
|
|
2
|
+
|
|
3
|
+
// async function testDBConnection(targetDir, dbConfig) {
|
|
4
|
+
// const sequelizePath = path.join(targetDir, "backend", "node_modules", "sequelize");
|
|
5
|
+
// const { Sequelize } = require(sequelizePath);
|
|
6
|
+
|
|
7
|
+
// const sequelize = new Sequelize(
|
|
8
|
+
// dbConfig.database,
|
|
9
|
+
// dbConfig.username,
|
|
10
|
+
// dbConfig.password,
|
|
11
|
+
// {
|
|
12
|
+
// host: dbConfig.host,
|
|
13
|
+
// port: dbConfig.port,
|
|
14
|
+
// dialect: dbConfig.dialect,
|
|
15
|
+
// logging: false
|
|
16
|
+
// }
|
|
17
|
+
// );
|
|
18
|
+
|
|
19
|
+
// try {
|
|
20
|
+
// await sequelize.authenticate();
|
|
21
|
+
// console.log(`✅ Connection successful to ${dbConfig.dbKey}`);
|
|
22
|
+
// await sequelize.close();
|
|
23
|
+
// return true;
|
|
24
|
+
// } catch (err) {
|
|
25
|
+
// console.log(`❌ Failed to connect to ${dbConfig.dbKey}`);
|
|
26
|
+
// console.log("Error:", err.message);
|
|
27
|
+
// return false;
|
|
28
|
+
// }
|
|
29
|
+
// }
|
|
30
|
+
|
|
31
|
+
// module.exports = testDBConnection;
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
1
35
|
const path = require("path");
|
|
36
|
+
const { assertDependency } = require("./utils");
|
|
2
37
|
|
|
3
38
|
async function testDBConnection(targetDir, dbConfig) {
|
|
4
|
-
const
|
|
5
|
-
|
|
39
|
+
const backendDir = path.join(targetDir, "backend");
|
|
40
|
+
|
|
41
|
+
let driver;
|
|
42
|
+
try {
|
|
43
|
+
if (dbConfig.dialect === "mysql") {
|
|
44
|
+
driver = assertDependency("mysql2", backendDir);
|
|
45
|
+
}
|
|
46
|
+
if (dbConfig.dialect === "mariadb") {
|
|
47
|
+
driver = assertDependency("mariadb", backendDir);
|
|
48
|
+
}
|
|
49
|
+
if (dbConfig.dialect === "postgres") {
|
|
50
|
+
driver = assertDependency("pg", backendDir);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
} catch (e) {
|
|
54
|
+
throw new Error(
|
|
55
|
+
`Database driver for '${dbConfig.dialect}' not found. ` +
|
|
56
|
+
`Please install it in backend (e.g. npm install ${dbConfig.dialect === "postgres" ? "pg" : dbConfig.dialect}).`
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// const { Sequelize } = require(
|
|
61
|
+
// path.join(backendDir, "node_modules", "sequelize")
|
|
62
|
+
// );
|
|
63
|
+
const { Sequelize } = assertDependency("sequelize", backendDir);
|
|
6
64
|
|
|
7
65
|
const sequelize = new Sequelize(
|
|
8
66
|
dbConfig.database,
|
package/lib/utils.js
CHANGED
|
@@ -1,24 +1,30 @@
|
|
|
1
|
-
|
|
1
|
+
// function ensure(dep) {
|
|
2
|
+
// try {
|
|
3
|
+
// return require(dep);
|
|
4
|
+
// } catch (e) {
|
|
5
|
+
// console.log(`📦 Installing missing dependency: ${dep}...`);
|
|
6
|
+
// execSync(`npm install ${dep} --silent`, { cwd: __dirname + "/..", stdio: "inherit" });
|
|
7
|
+
// return require(dep);
|
|
8
|
+
// }
|
|
9
|
+
// }
|
|
10
|
+
|
|
2
11
|
|
|
3
|
-
function ensure(dep) {
|
|
4
|
-
try {
|
|
5
|
-
return require(dep);
|
|
6
|
-
} catch (e) {
|
|
7
|
-
console.log(`📦 Installing missing dependency: ${dep}...`);
|
|
8
|
-
execSync(`npm install ${dep} --silent`, { cwd: __dirname + "/..", stdio: "inherit" });
|
|
9
|
-
return require(dep);
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
12
|
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
const fs = require("fs-extra");
|
|
16
|
+
const path = require("path");
|
|
17
|
+
const execa = require("execa");
|
|
18
|
+
|
|
19
|
+
// ------------------ Logging ------------------
|
|
13
20
|
function log(step) {
|
|
14
21
|
console.log(`\n➡️ ${step}`);
|
|
15
22
|
}
|
|
16
23
|
|
|
17
|
-
|
|
18
|
-
const path = require("path");
|
|
19
|
-
|
|
24
|
+
// ------------------ Replace in Files ------------------
|
|
20
25
|
async function replaceInFiles(base, replacements) {
|
|
21
26
|
const exts = [".js", ".ts", ".json", ".md", ".env", ".yml"];
|
|
27
|
+
|
|
22
28
|
async function walk(dir) {
|
|
23
29
|
for (const item of await fs.readdir(dir)) {
|
|
24
30
|
const fullPath = path.join(dir, item);
|
|
@@ -33,7 +39,54 @@ async function replaceInFiles(base, replacements) {
|
|
|
33
39
|
}
|
|
34
40
|
}
|
|
35
41
|
}
|
|
42
|
+
|
|
36
43
|
await walk(base);
|
|
37
44
|
}
|
|
38
45
|
|
|
39
|
-
|
|
46
|
+
// ------------------ Ensure Directory ------------------
|
|
47
|
+
async function ensureDir(dir) {
|
|
48
|
+
await fs.ensureDir(dir);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// ------------------ Assert Dependency ------------------
|
|
52
|
+
function assertDependency(depName, cwd) {
|
|
53
|
+
try {
|
|
54
|
+
return require(path.join(cwd, "node_modules", depName));
|
|
55
|
+
} catch (err) {
|
|
56
|
+
throw new Error(
|
|
57
|
+
`Dependency '${depName}' is not installed in ${cwd}.\n` +
|
|
58
|
+
`Run: cd ${cwd} && npm install ${depName}`
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// ------------------ Run npm install ------------------
|
|
64
|
+
async function runInstall(cwd) {
|
|
65
|
+
await execa("npm", ["install"], {
|
|
66
|
+
cwd,
|
|
67
|
+
stdio: "inherit"
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// ------------------ Installing Dynamic DB Drivers ----------------
|
|
72
|
+
|
|
73
|
+
async function installDBDriver(targetDir, dialect) {
|
|
74
|
+
let pkg;
|
|
75
|
+
if (dialect === "mariadb") pkg = "mariadb";
|
|
76
|
+
if (dialect === "mysql") pkg = "mysql2";
|
|
77
|
+
if (dialect === "postgres") pkg = "pg";
|
|
78
|
+
if (!pkg) return;
|
|
79
|
+
|
|
80
|
+
console.log(`➡️ Installing ${pkg}...`);
|
|
81
|
+
await execa("npm", ["install", pkg], { cwd: targetDir, stdio: "inherit" });
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
module.exports = {
|
|
86
|
+
log,
|
|
87
|
+
replaceInFiles,
|
|
88
|
+
ensureDir,
|
|
89
|
+
assertDependency,
|
|
90
|
+
runInstall,
|
|
91
|
+
installDBDriver
|
|
92
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-fullstack-boilerplate",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "A Full Stack Application Comprised of React for Frontend, Express & Sequelize with Node js for Backend to help developers get started on real implementation instead of spending time setting up projects.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|