create-craftjs 1.0.4 ā 1.0.6
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/README.md +139 -137
- package/bin/index.js +158 -158
- package/package.json +24 -24
- package/template/Dockerfile +57 -12
- package/template/babel.config.json +3 -3
- package/template/craft/commands/build.js +16 -15
- package/template/craft/commands/db-fresh.js +22 -22
- package/template/craft/commands/db-generate.js +23 -23
- package/template/craft/commands/db-migrate.js +22 -22
- package/template/craft/commands/dev.js +16 -16
- package/template/craft/commands/key-generate.js +41 -41
- package/template/craft/commands/make-apidocs.js +121 -121
- package/template/craft/commands/make-command.js +38 -38
- package/template/craft/commands/make-controller.js +95 -95
- package/template/craft/commands/make-dto.js +39 -39
- package/template/craft/commands/make-middleware.js +46 -46
- package/template/craft/commands/make-repository.js +36 -36
- package/template/craft/commands/make-route.js +92 -92
- package/template/craft/commands/make-service.js +39 -39
- package/template/craft/commands/make-test.js +48 -48
- package/template/craft/commands/make-utils.js +30 -30
- package/template/craft/commands/make-validation.js +42 -42
- package/template/craft/commands/make-view.js +42 -42
- package/template/craft/commands/start.js +29 -29
- package/template/craft/commands/test.js +20 -20
- package/template/craft.js +256 -256
- package/template/docker-compose.yml +8 -0
- package/template/nodemon.json +6 -6
- package/template/package-lock.json +8877 -8877
- package/template/package.json +84 -84
- package/template/prisma/schema.prisma +22 -22
- package/template/prisma/seed.ts +29 -29
- package/template/src/apidocs/auth-docs.ts +314 -314
- package/template/src/apidocs/users-docs.ts +240 -240
- package/template/src/config/cloudinary.ts +21 -21
- package/template/src/config/database.ts +90 -90
- package/template/src/config/env.ts +67 -67
- package/template/src/config/logger.ts +139 -139
- package/template/src/config/nodemailer.ts +23 -23
- package/template/src/config/web.ts +47 -47
- package/template/src/controllers/auth-controller.ts +88 -88
- package/template/src/controllers/user-controller.ts +79 -79
- package/template/src/dtos/list-dto.ts +12 -12
- package/template/src/dtos/user-dto.ts +57 -57
- package/template/src/main.ts +28 -28
- package/template/src/middleware/auth-middleware.ts +44 -44
- package/template/src/middleware/error-middleware.ts +27 -27
- package/template/src/middleware/http-logger-middleware.ts +31 -31
- package/template/src/repositories/user-repository.ts +75 -75
- package/template/src/routes/auth-route.ts +20 -20
- package/template/src/routes/main-route.ts +25 -25
- package/template/src/routes/user-route.ts +35 -35
- package/template/src/services/auth-service.ts +162 -162
- package/template/src/services/user-service.ts +102 -102
- package/template/src/types/type-request.ts +6 -6
- package/template/src/utils/async-handler.ts +9 -9
- package/template/src/utils/response-error.ts +10 -10
- package/template/src/utils/response.ts +60 -60
- package/template/src/utils/swagger.ts +135 -135
- package/template/src/utils/validation.ts +7 -7
- package/template/src/validations/user-validation.ts +127 -127
- package/template/src/views/index.ejs +6 -6
- package/template/src/views/layouts/main.ejs +14 -14
- package/template/src/views/partials/header.ejs +3 -3
- package/template/test/user.test.ts +16 -16
- package/template/tsconfig.json +13 -13
- package/template/.dockerignore +0 -4
package/README.md
CHANGED
|
@@ -1,137 +1,139 @@
|
|
|
1
|
-
# CraftJS
|
|
2
|
-
|
|
3
|
-
A starter kit backend framework powered by Express, TypeScript, EJS Engine, and Prisma ā designed for rapid development, simplicity, and scalability.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## Features
|
|
8
|
-
|
|
9
|
-
- **Express.js** based API architecture
|
|
10
|
-
- **TypeScript** support out of the box
|
|
11
|
-
- **Prisma ORM** with scalable database structure
|
|
12
|
-
- **CLI tool** (`craft`) for project automation
|
|
13
|
-
- Built-in **Logger**, **Validation**, **Error handler**, and **Request lifecycle**
|
|
14
|
-
- Predefined project structure for fast onboarding
|
|
15
|
-
|
|
16
|
-
---
|
|
17
|
-
|
|
18
|
-
š” Note: EJS View Engine is included but disabled by default. To enable it:
|
|
19
|
-
Open src/application/web.ts and uncomment the following lines:
|
|
20
|
-
|
|
21
|
-
```bash
|
|
22
|
-
import expressLayouts from "express-ejs-layouts";
|
|
23
|
-
import path from "path";
|
|
24
|
-
|
|
25
|
-
web.set("view engine", "ejs");
|
|
26
|
-
web.set("views", path.join(\_\_dirname, "..", "views"));
|
|
27
|
-
web.use(expressLayouts);
|
|
28
|
-
web.set("layout", "layouts/main");
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
Then, go to src/routes/main-route.ts and uncomment this:
|
|
32
|
-
|
|
33
|
-
```bash
|
|
34
|
-
mainRouter.get("/", (req, res) => {
|
|
35
|
-
res.render("index", { title: "Home Page" });
|
|
36
|
-
});
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
## Getting Started
|
|
40
|
-
|
|
41
|
-
### Scaffold a New Project
|
|
42
|
-
|
|
43
|
-
```bash
|
|
44
|
-
npx create-craftjs my-app
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
OR
|
|
48
|
-
|
|
49
|
-
```bash
|
|
50
|
-
npm init craftjs my-app
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
### Go to project folder
|
|
54
|
-
|
|
55
|
-
```bash
|
|
56
|
-
cd my-app
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
### Run Craft Setup
|
|
60
|
-
|
|
61
|
-
```bash
|
|
62
|
-
npm install
|
|
63
|
-
node craft key:generate
|
|
64
|
-
node craft generate
|
|
65
|
-
node craft db:migrate
|
|
66
|
-
node craft dev
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
### Available Craft Commands
|
|
70
|
-
|
|
71
|
-
```bash
|
|
72
|
-
node craft help
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
---
|
|
76
|
-
|
|
77
|
-
## Project Structure
|
|
78
|
-
|
|
79
|
-
```
|
|
80
|
-
my-app/
|
|
81
|
-
āāā craft/
|
|
82
|
-
āāā src/
|
|
83
|
-
ā āāā apidocs/
|
|
84
|
-
ā āāā config/
|
|
85
|
-
ā āāā controllers/
|
|
86
|
-
ā āāā middleware/
|
|
87
|
-
ā āāā repositories/
|
|
88
|
-
ā āāā dtos/
|
|
89
|
-
ā āāā routes/
|
|
90
|
-
ā āāā services/
|
|
91
|
-
ā āāā types/
|
|
92
|
-
ā āāā utils/
|
|
93
|
-
ā āāā validations/
|
|
94
|
-
ā āāā main.ts
|
|
95
|
-
āāā test/
|
|
96
|
-
āāā logs/
|
|
97
|
-
āāā .
|
|
98
|
-
āāā
|
|
99
|
-
āāā
|
|
100
|
-
āāā .
|
|
101
|
-
āāā
|
|
102
|
-
āāā
|
|
103
|
-
āāā
|
|
104
|
-
āāā
|
|
105
|
-
āāā
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
|
116
|
-
|
|
|
117
|
-
| `craft
|
|
118
|
-
| `craft
|
|
119
|
-
| `craft
|
|
120
|
-
| `craft
|
|
121
|
-
| `craft db:
|
|
122
|
-
| `craft
|
|
123
|
-
| `craft
|
|
124
|
-
| `craft
|
|
125
|
-
| `craft make:
|
|
126
|
-
| `craft make:
|
|
127
|
-
| `craft make:
|
|
128
|
-
| `craft make:
|
|
129
|
-
| `craft make:
|
|
130
|
-
| `craft make:
|
|
131
|
-
| `craft make:
|
|
132
|
-
| `craft make:
|
|
133
|
-
| `craft make:
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
1
|
+
# CraftJS
|
|
2
|
+
|
|
3
|
+
A starter kit backend framework powered by Express, TypeScript, EJS Engine, and Prisma ā designed for rapid development, simplicity, and scalability.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Express.js** based API architecture
|
|
10
|
+
- **TypeScript** support out of the box
|
|
11
|
+
- **Prisma ORM** with scalable database structure
|
|
12
|
+
- **CLI tool** (`craft`) for project automation
|
|
13
|
+
- Built-in **Logger**, **Validation**, **Error handler**, and **Request lifecycle**
|
|
14
|
+
- Predefined project structure for fast onboarding
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
š” Note: EJS View Engine is included but disabled by default. To enable it:
|
|
19
|
+
Open src/application/web.ts and uncomment the following lines:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
import expressLayouts from "express-ejs-layouts";
|
|
23
|
+
import path from "path";
|
|
24
|
+
|
|
25
|
+
web.set("view engine", "ejs");
|
|
26
|
+
web.set("views", path.join(\_\_dirname, "..", "views"));
|
|
27
|
+
web.use(expressLayouts);
|
|
28
|
+
web.set("layout", "layouts/main");
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Then, go to src/routes/main-route.ts and uncomment this:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
mainRouter.get("/", (req, res) => {
|
|
35
|
+
res.render("index", { title: "Home Page" });
|
|
36
|
+
});
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Getting Started
|
|
40
|
+
|
|
41
|
+
### Scaffold a New Project
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
npx create-craftjs my-app
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
OR
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
npm init craftjs my-app
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Go to project folder
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
cd my-app
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Run Craft Setup
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
npm install
|
|
63
|
+
node craft key:generate
|
|
64
|
+
node craft generate
|
|
65
|
+
node craft db:migrate
|
|
66
|
+
node craft dev
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Available Craft Commands
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
node craft help
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Project Structure
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
my-app/
|
|
81
|
+
āāā craft/
|
|
82
|
+
āāā src/
|
|
83
|
+
ā āāā apidocs/
|
|
84
|
+
ā āāā config/
|
|
85
|
+
ā āāā controllers/
|
|
86
|
+
ā āāā middleware/
|
|
87
|
+
ā āāā repositories/
|
|
88
|
+
ā āāā dtos/
|
|
89
|
+
ā āāā routes/
|
|
90
|
+
ā āāā services/
|
|
91
|
+
ā āāā types/
|
|
92
|
+
ā āāā utils/
|
|
93
|
+
ā āāā validations/
|
|
94
|
+
ā āāā main.ts
|
|
95
|
+
āāā test/
|
|
96
|
+
āāā logs/
|
|
97
|
+
āāā docker-compose.yml
|
|
98
|
+
āāā Dockerfile
|
|
99
|
+
āāā .env
|
|
100
|
+
āāā .env.example
|
|
101
|
+
āāā prisma/
|
|
102
|
+
āāā .gitignore
|
|
103
|
+
āāā babel.config.json
|
|
104
|
+
āāā craft.js
|
|
105
|
+
āāā nodemon.json
|
|
106
|
+
āāā package.json
|
|
107
|
+
āāā package-lock.json
|
|
108
|
+
āāā tsconfig.json
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Scripts
|
|
114
|
+
|
|
115
|
+
| Command | Description |
|
|
116
|
+
| ----------------------- | ------------------------------ |
|
|
117
|
+
| `craft start` | Start production server |
|
|
118
|
+
| `craft dev` | Run in development mode |
|
|
119
|
+
| `craft build` | Build for production |
|
|
120
|
+
| `craft test` | Run Jest tests |
|
|
121
|
+
| `craft db:generate` | Generate Prisma client |
|
|
122
|
+
| `craft db:migrate` | Run Prisma migrations |
|
|
123
|
+
| `craft db:reset` | Run Prisma migrations refresh |
|
|
124
|
+
| `craft key:generate` | Generate secret keys |
|
|
125
|
+
| `craft make:controller` | Make Controller File |
|
|
126
|
+
| `craft make:command` | Make Command File |
|
|
127
|
+
| `craft make:middleware` | Make Middleware File |
|
|
128
|
+
| `craft make:repository` | Make repository File |
|
|
129
|
+
| `craft make:dto` | Make Data Transfer Object File |
|
|
130
|
+
| `craft make:route` | Make Route File |
|
|
131
|
+
| `craft make:service` | Make Service File |
|
|
132
|
+
| `craft make:test` | Make Test case |
|
|
133
|
+
| `craft make:utils` | Make Utils |
|
|
134
|
+
| `craft make:validation` | Make Validation |
|
|
135
|
+
| `craft make:view` | Make View |
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
Made by [@muhammadisa-n](https://github.com/muhammadisa-n)
|
package/bin/index.js
CHANGED
|
@@ -1,158 +1,158 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
const fs = require("fs");
|
|
4
|
-
const path = require("path");
|
|
5
|
-
const { spawnSync } = require("child_process");
|
|
6
|
-
const readline = require("readline");
|
|
7
|
-
|
|
8
|
-
const rl = readline.createInterface({
|
|
9
|
-
input: process.stdin,
|
|
10
|
-
output: process.stdout,
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
const ask = (question) => {
|
|
14
|
-
return new Promise((resolve) => {
|
|
15
|
-
rl.question(question, (answer) => resolve(answer.trim()));
|
|
16
|
-
});
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
(async () => {
|
|
20
|
-
console.log("š Welcome to CraftJS Project Creator!");
|
|
21
|
-
|
|
22
|
-
let projectName = process.argv[2];
|
|
23
|
-
|
|
24
|
-
if (!projectName) {
|
|
25
|
-
projectName = await ask("š¦ Enter your project name: ");
|
|
26
|
-
while (!projectName || !/^[a-zA-Z0-9-_]+$/.test(projectName)) {
|
|
27
|
-
console.log(
|
|
28
|
-
"ā Invalid project name. Use only letters, numbers, - and _."
|
|
29
|
-
);
|
|
30
|
-
projectName = await ask("š¦ Enter your project name: ");
|
|
31
|
-
}
|
|
32
|
-
} else {
|
|
33
|
-
if (!/^[a-zA-Z0-9-_]+$/.test(projectName)) {
|
|
34
|
-
console.error(
|
|
35
|
-
"ā Project name can only contain letters, numbers, dashes (-), and underscores (_)."
|
|
36
|
-
);
|
|
37
|
-
rl.close();
|
|
38
|
-
process.exit(1);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const targetPath = path.resolve(process.cwd(), projectName);
|
|
43
|
-
const templatePath = path.join(__dirname, "..", "template");
|
|
44
|
-
|
|
45
|
-
if (fs.existsSync(targetPath)) {
|
|
46
|
-
console.error(`ā Folder "${projectName}" already exists.`);
|
|
47
|
-
rl.close();
|
|
48
|
-
process.exit(1);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const copyRecursiveSync = (src, dest) => {
|
|
52
|
-
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
53
|
-
fs.mkdirSync(dest, { recursive: true });
|
|
54
|
-
|
|
55
|
-
for (let entry of entries) {
|
|
56
|
-
const srcPath = path.join(src, entry.name);
|
|
57
|
-
const destPath = path.join(dest, entry.name);
|
|
58
|
-
if (entry.isDirectory()) {
|
|
59
|
-
copyRecursiveSync(srcPath, destPath);
|
|
60
|
-
} else {
|
|
61
|
-
fs.copyFileSync(srcPath, destPath);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
console.log(`\nš§ Creating project in ./${projectName}...`);
|
|
67
|
-
copyRecursiveSync(templatePath, targetPath);
|
|
68
|
-
|
|
69
|
-
const packageJsonPath = path.join(targetPath, "package.json");
|
|
70
|
-
if (fs.existsSync(packageJsonPath)) {
|
|
71
|
-
const pkg = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
|
|
72
|
-
pkg.name = projectName;
|
|
73
|
-
fs.writeFileSync(packageJsonPath, JSON.stringify(pkg, null, 2));
|
|
74
|
-
console.log(`š¦ Updated package.json name to "${projectName}"`);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
const envContent = `APP_NAME="${projectName}"
|
|
78
|
-
APP_SECRET=
|
|
79
|
-
NODE_ENV="development"
|
|
80
|
-
TZ="Asia/Jakarta"
|
|
81
|
-
DATETIME_FORMAT="dd-MM-yyyy HH:mm:ss"
|
|
82
|
-
DATABASE_URL="mysql://root:@localhost:3306/${projectName}"
|
|
83
|
-
BASE_URL="http://localhost:3000"
|
|
84
|
-
BASE_API_URL="http://localhost:3000/api"
|
|
85
|
-
PORT=3000
|
|
86
|
-
JWT_SECRET=
|
|
87
|
-
`;
|
|
88
|
-
|
|
89
|
-
const envExampleContent = envContent.replace(/=.*/g, "=");
|
|
90
|
-
|
|
91
|
-
const sourceReadmePath = path.join(__dirname, "..", "README.md");
|
|
92
|
-
const targetReadmePath = path.join(targetPath, "README.md");
|
|
93
|
-
|
|
94
|
-
if (fs.existsSync(sourceReadmePath)) {
|
|
95
|
-
fs.copyFileSync(sourceReadmePath, targetReadmePath);
|
|
96
|
-
console.log("š Copied README.md...");
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
console.log("š Generating .env and .env.example...");
|
|
100
|
-
fs.writeFileSync(path.join(targetPath, ".env"), envContent);
|
|
101
|
-
fs.writeFileSync(path.join(targetPath, ".env.example"), envExampleContent);
|
|
102
|
-
|
|
103
|
-
console.log("š§ Initializing git repository...");
|
|
104
|
-
const gitInit = spawnSync("git", ["init"], {
|
|
105
|
-
cwd: targetPath,
|
|
106
|
-
stdio: "inherit",
|
|
107
|
-
shell: true,
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
if (gitInit.status !== 0) {
|
|
111
|
-
console.warn("ā ļø Git initialization failed.");
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
const gitignorePath = path.join(targetPath, ".gitignore");
|
|
115
|
-
if (!fs.existsSync(gitignorePath)) {
|
|
116
|
-
fs.writeFileSync(
|
|
117
|
-
gitignorePath,
|
|
118
|
-
`node_modules
|
|
119
|
-
.env
|
|
120
|
-
dist
|
|
121
|
-
`
|
|
122
|
-
);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
const installNow = await ask(
|
|
126
|
-
"š„ Do you want to install dependencies now? (yes/no): "
|
|
127
|
-
);
|
|
128
|
-
if (installNow.toLowerCase() === "yes" || installNow.toLowerCase() === "y") {
|
|
129
|
-
console.log("š¦ Installing dependencies...");
|
|
130
|
-
const npmInstall = spawnSync("npm", ["install"], {
|
|
131
|
-
cwd: targetPath,
|
|
132
|
-
stdio: "inherit",
|
|
133
|
-
shell: true,
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
if (npmInstall.status !== 0) {
|
|
137
|
-
console.warn("ā ļø npm install failed.");
|
|
138
|
-
console.log("\nā
Done!");
|
|
139
|
-
console.log(
|
|
140
|
-
`\nNext steps:\n cd ${projectName}\n npm install\n node craft key:generate\n node craft db:generate\n node craft db:migrate\n node craft dev`
|
|
141
|
-
);
|
|
142
|
-
} else {
|
|
143
|
-
console.log("ā
Dependencies installed successfully.");
|
|
144
|
-
console.log("\nā
Done!");
|
|
145
|
-
console.log(
|
|
146
|
-
`\nNext steps:\n cd ${projectName}\n node craft key:generate\n node craft db:generate\n node craft db:migrate\n node craft dev`
|
|
147
|
-
);
|
|
148
|
-
}
|
|
149
|
-
} else {
|
|
150
|
-
console.log("ā¹ļø Skipping dependency installation.");
|
|
151
|
-
console.log("\nā
Done!");
|
|
152
|
-
console.log(
|
|
153
|
-
`\nNext steps:\n cd ${projectName}\n npm install\n node craft key:generate\n node craft db:generate\n node craft db:migrate\n node craft dev`
|
|
154
|
-
);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
rl.close();
|
|
158
|
-
})();
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require("fs");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
const { spawnSync } = require("child_process");
|
|
6
|
+
const readline = require("readline");
|
|
7
|
+
|
|
8
|
+
const rl = readline.createInterface({
|
|
9
|
+
input: process.stdin,
|
|
10
|
+
output: process.stdout,
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const ask = (question) => {
|
|
14
|
+
return new Promise((resolve) => {
|
|
15
|
+
rl.question(question, (answer) => resolve(answer.trim()));
|
|
16
|
+
});
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
(async () => {
|
|
20
|
+
console.log("š Welcome to CraftJS Project Creator!");
|
|
21
|
+
|
|
22
|
+
let projectName = process.argv[2];
|
|
23
|
+
|
|
24
|
+
if (!projectName) {
|
|
25
|
+
projectName = await ask("š¦ Enter your project name: ");
|
|
26
|
+
while (!projectName || !/^[a-zA-Z0-9-_]+$/.test(projectName)) {
|
|
27
|
+
console.log(
|
|
28
|
+
"ā Invalid project name. Use only letters, numbers, - and _."
|
|
29
|
+
);
|
|
30
|
+
projectName = await ask("š¦ Enter your project name: ");
|
|
31
|
+
}
|
|
32
|
+
} else {
|
|
33
|
+
if (!/^[a-zA-Z0-9-_]+$/.test(projectName)) {
|
|
34
|
+
console.error(
|
|
35
|
+
"ā Project name can only contain letters, numbers, dashes (-), and underscores (_)."
|
|
36
|
+
);
|
|
37
|
+
rl.close();
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const targetPath = path.resolve(process.cwd(), projectName);
|
|
43
|
+
const templatePath = path.join(__dirname, "..", "template");
|
|
44
|
+
|
|
45
|
+
if (fs.existsSync(targetPath)) {
|
|
46
|
+
console.error(`ā Folder "${projectName}" already exists.`);
|
|
47
|
+
rl.close();
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const copyRecursiveSync = (src, dest) => {
|
|
52
|
+
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
53
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
54
|
+
|
|
55
|
+
for (let entry of entries) {
|
|
56
|
+
const srcPath = path.join(src, entry.name);
|
|
57
|
+
const destPath = path.join(dest, entry.name);
|
|
58
|
+
if (entry.isDirectory()) {
|
|
59
|
+
copyRecursiveSync(srcPath, destPath);
|
|
60
|
+
} else {
|
|
61
|
+
fs.copyFileSync(srcPath, destPath);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
console.log(`\nš§ Creating project in ./${projectName}...`);
|
|
67
|
+
copyRecursiveSync(templatePath, targetPath);
|
|
68
|
+
|
|
69
|
+
const packageJsonPath = path.join(targetPath, "package.json");
|
|
70
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
71
|
+
const pkg = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
|
|
72
|
+
pkg.name = projectName;
|
|
73
|
+
fs.writeFileSync(packageJsonPath, JSON.stringify(pkg, null, 2));
|
|
74
|
+
console.log(`š¦ Updated package.json name to "${projectName}"`);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const envContent = `APP_NAME="${projectName}"
|
|
78
|
+
APP_SECRET=
|
|
79
|
+
NODE_ENV="development"
|
|
80
|
+
TZ="Asia/Jakarta"
|
|
81
|
+
DATETIME_FORMAT="dd-MM-yyyy HH:mm:ss"
|
|
82
|
+
DATABASE_URL="mysql://root:@localhost:3306/${projectName}"
|
|
83
|
+
BASE_URL="http://localhost:3000"
|
|
84
|
+
BASE_API_URL="http://localhost:3000/api"
|
|
85
|
+
PORT=3000
|
|
86
|
+
JWT_SECRET=
|
|
87
|
+
`;
|
|
88
|
+
|
|
89
|
+
const envExampleContent = envContent.replace(/=.*/g, "=");
|
|
90
|
+
|
|
91
|
+
const sourceReadmePath = path.join(__dirname, "..", "README.md");
|
|
92
|
+
const targetReadmePath = path.join(targetPath, "README.md");
|
|
93
|
+
|
|
94
|
+
if (fs.existsSync(sourceReadmePath)) {
|
|
95
|
+
fs.copyFileSync(sourceReadmePath, targetReadmePath);
|
|
96
|
+
console.log("š Copied README.md...");
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
console.log("š Generating .env and .env.example...");
|
|
100
|
+
fs.writeFileSync(path.join(targetPath, ".env"), envContent);
|
|
101
|
+
fs.writeFileSync(path.join(targetPath, ".env.example"), envExampleContent);
|
|
102
|
+
|
|
103
|
+
console.log("š§ Initializing git repository...");
|
|
104
|
+
const gitInit = spawnSync("git", ["init"], {
|
|
105
|
+
cwd: targetPath,
|
|
106
|
+
stdio: "inherit",
|
|
107
|
+
shell: true,
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
if (gitInit.status !== 0) {
|
|
111
|
+
console.warn("ā ļø Git initialization failed.");
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const gitignorePath = path.join(targetPath, ".gitignore");
|
|
115
|
+
if (!fs.existsSync(gitignorePath)) {
|
|
116
|
+
fs.writeFileSync(
|
|
117
|
+
gitignorePath,
|
|
118
|
+
`node_modules
|
|
119
|
+
.env
|
|
120
|
+
dist
|
|
121
|
+
`
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const installNow = await ask(
|
|
126
|
+
"š„ Do you want to install dependencies now? (yes/no): "
|
|
127
|
+
);
|
|
128
|
+
if (installNow.toLowerCase() === "yes" || installNow.toLowerCase() === "y") {
|
|
129
|
+
console.log("š¦ Installing dependencies...");
|
|
130
|
+
const npmInstall = spawnSync("npm", ["install"], {
|
|
131
|
+
cwd: targetPath,
|
|
132
|
+
stdio: "inherit",
|
|
133
|
+
shell: true,
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
if (npmInstall.status !== 0) {
|
|
137
|
+
console.warn("ā ļø npm install failed.");
|
|
138
|
+
console.log("\nā
Done!");
|
|
139
|
+
console.log(
|
|
140
|
+
`\nNext steps:\n cd ${projectName}\n npm install\n node craft key:generate\n node craft db:generate\n node craft db:migrate\n node craft dev`
|
|
141
|
+
);
|
|
142
|
+
} else {
|
|
143
|
+
console.log("ā
Dependencies installed successfully.");
|
|
144
|
+
console.log("\nā
Done!");
|
|
145
|
+
console.log(
|
|
146
|
+
`\nNext steps:\n cd ${projectName}\n node craft key:generate\n node craft db:generate\n node craft db:migrate\n node craft dev`
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
} else {
|
|
150
|
+
console.log("ā¹ļø Skipping dependency installation.");
|
|
151
|
+
console.log("\nā
Done!");
|
|
152
|
+
console.log(
|
|
153
|
+
`\nNext steps:\n cd ${projectName}\n npm install\n node craft key:generate\n node craft db:generate\n node craft db:migrate\n node craft dev`
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
rl.close();
|
|
158
|
+
})();
|
package/package.json
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "create-craftjs",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "A starter kit backend framework powered by Express, TypeScript, EJS Engine, and Prisma ā designed for rapid development, simplicity, and scalability.",
|
|
5
|
-
"bin": {
|
|
6
|
-
"create-craftjs": "bin/index.js"
|
|
7
|
-
},
|
|
8
|
-
"author": "Muhammad Isa Nuruddin",
|
|
9
|
-
"homepage": "https://github.com/muhammadisa-n/CraftJS#readme",
|
|
10
|
-
"bugs": {
|
|
11
|
-
"url": "https://github.com/muhammadisa-n/CraftJS/issues"
|
|
12
|
-
},
|
|
13
|
-
"repository": {
|
|
14
|
-
"type": "git",
|
|
15
|
-
"url": "git+https://github.com/muhammadisa-n/CraftJS.git"
|
|
16
|
-
},
|
|
17
|
-
"license": "UNLICENSED",
|
|
18
|
-
"keywords": [
|
|
19
|
-
"express",
|
|
20
|
-
"typescript",
|
|
21
|
-
"prisma",
|
|
22
|
-
"api"
|
|
23
|
-
]
|
|
24
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "create-craftjs",
|
|
3
|
+
"version": "1.0.6",
|
|
4
|
+
"description": "A starter kit backend framework powered by Express, TypeScript, EJS Engine, and Prisma ā designed for rapid development, simplicity, and scalability.",
|
|
5
|
+
"bin": {
|
|
6
|
+
"create-craftjs": "bin/index.js"
|
|
7
|
+
},
|
|
8
|
+
"author": "Muhammad Isa Nuruddin",
|
|
9
|
+
"homepage": "https://github.com/muhammadisa-n/CraftJS#readme",
|
|
10
|
+
"bugs": {
|
|
11
|
+
"url": "https://github.com/muhammadisa-n/CraftJS/issues"
|
|
12
|
+
},
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "git+https://github.com/muhammadisa-n/CraftJS.git"
|
|
16
|
+
},
|
|
17
|
+
"license": "UNLICENSED",
|
|
18
|
+
"keywords": [
|
|
19
|
+
"express",
|
|
20
|
+
"typescript",
|
|
21
|
+
"prisma",
|
|
22
|
+
"api"
|
|
23
|
+
]
|
|
24
|
+
}
|