create-enterprise-backend 0.1.1 ā 0.1.2
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 +129 -53
- package/core/install.js +4 -1
- package/core/run.js +10 -5
- package/core/scaffold.js +21 -11
- package/package.json +1 -1
- package/templates/express/mongo/.env.example +3 -0
- package/templates/fastify/mongo/.env.example +3 -0
- package/templates/fastify/supabase/.env.example +4 -0
package/README.md
CHANGED
|
@@ -1,89 +1,165 @@
|
|
|
1
|
-
# Create Enterprise Backend
|
|
1
|
+
# š Create Enterprise Backend
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Create Enterprise Backend is a modern CLI tool to scaffold production-ready backend applications using Express or Fastify with MongoDB or Supabase, following enterprise best practices.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
ā” Zero setup. Secure defaults. Scalable structure.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
- **Databases**: Support for MongoDB or Supabase
|
|
9
|
-
- **Authentication**: Pre-configured JWT authentication modules
|
|
10
|
-
- **Middleware**: Built-in error handling, database guards, and JWT guards
|
|
11
|
-
- **Project Structure**: Organized modular architecture for scalability
|
|
7
|
+
## ⨠Features
|
|
12
8
|
|
|
13
|
-
|
|
9
|
+
### š Frameworks
|
|
10
|
+
- Express
|
|
11
|
+
- Fastify
|
|
14
12
|
|
|
15
|
-
|
|
13
|
+
### š Databases
|
|
14
|
+
- MongoDB (Mongoose)
|
|
15
|
+
- Supabase (Postgres + Auth)
|
|
16
16
|
|
|
17
|
+
### š Authentication Ready
|
|
18
|
+
- JWT-based auth
|
|
19
|
+
- Auth guards & middleware
|
|
20
|
+
- Safe handling when DB/env is missing
|
|
21
|
+
|
|
22
|
+
### š§± Enterprise Architecture
|
|
23
|
+
- Modular structure
|
|
24
|
+
- Controllers / Services / Routes
|
|
25
|
+
- Centralized error handling
|
|
26
|
+
- Environment-based config
|
|
27
|
+
|
|
28
|
+
### š Developer Experience
|
|
29
|
+
- Nodemon preconfigured
|
|
30
|
+
- Clean logging
|
|
31
|
+
- Safe defaults (no crash if DB not configured)
|
|
32
|
+
|
|
33
|
+
## š¦ Installation & Usage
|
|
34
|
+
|
|
35
|
+
You don't need to install anything globally.
|
|
36
|
+
|
|
37
|
+
**Create a new backend project**
|
|
17
38
|
```bash
|
|
18
|
-
|
|
39
|
+
npx create-enterprise-backend my-backend
|
|
19
40
|
```
|
|
20
41
|
|
|
21
|
-
|
|
22
|
-
|
|
42
|
+
**or inside the current folder:**
|
|
23
43
|
```bash
|
|
24
|
-
npx create-enterprise-backend
|
|
44
|
+
npx create-enterprise-backend .
|
|
25
45
|
```
|
|
26
46
|
|
|
27
|
-
##
|
|
47
|
+
## š§ Interactive Setup
|
|
28
48
|
|
|
29
|
-
|
|
49
|
+
The CLI will guide you through:
|
|
50
|
+
- Framework selection (Express / Fastify)
|
|
51
|
+
- Database selection (MongoDB / Supabase)
|
|
52
|
+
- Dependency installation (Install now or later)
|
|
30
53
|
|
|
54
|
+
## š Project Structure (Example)
|
|
55
|
+
```
|
|
56
|
+
src/
|
|
57
|
+
āāā app.js
|
|
58
|
+
āāā server.js
|
|
59
|
+
āāā routes.js
|
|
60
|
+
āāā config/
|
|
61
|
+
ā āāā env.js
|
|
62
|
+
ā āāā db.js # Mongo
|
|
63
|
+
ā āāā supabase.js # Supabase
|
|
64
|
+
āāā modules/
|
|
65
|
+
ā āāā auth/
|
|
66
|
+
ā āāā auth.controller.js
|
|
67
|
+
ā āāā auth.routes.js
|
|
68
|
+
ā āāā auth.service.js
|
|
69
|
+
ā āāā auth.schema.js
|
|
70
|
+
ā āāā user.model.js
|
|
71
|
+
āāā middlewares/
|
|
72
|
+
āāā services/
|
|
73
|
+
āāā utils/
|
|
74
|
+
āāā error-handler.js
|
|
75
|
+
āāā jwt-guard.js
|
|
76
|
+
āāā db-guard.js
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## ā¶ļø Running the Server
|
|
31
80
|
```bash
|
|
32
|
-
|
|
81
|
+
npm run dev
|
|
33
82
|
```
|
|
34
83
|
|
|
35
|
-
|
|
84
|
+
**Output example:**
|
|
85
|
+
```
|
|
86
|
+
ā ļø Supabase public client disabled (missing env vars)
|
|
87
|
+
ā ļø Supabase admin client disabled (missing env vars)
|
|
88
|
+
š Server running at http://localhost:5000
|
|
89
|
+
```
|
|
36
90
|
|
|
37
|
-
|
|
38
|
-
- **Framework**: Select Express or Fastify
|
|
39
|
-
- **Database**: Choose MongoDB or Supabase
|
|
40
|
-
- **Install Dependencies**: Option to install npm packages immediately
|
|
91
|
+
This is intentional and safe ā the app won't crash if env vars are missing.
|
|
41
92
|
|
|
42
|
-
|
|
93
|
+
## š Environment Variables
|
|
43
94
|
|
|
44
|
-
|
|
45
|
-
|
|
95
|
+
### MongoDB
|
|
96
|
+
```
|
|
97
|
+
PORT=5000
|
|
98
|
+
MONGO_URI=mongodb://localhost:27017/myapp
|
|
99
|
+
JWT_SECRET=supersecret
|
|
46
100
|
```
|
|
47
101
|
|
|
48
|
-
|
|
102
|
+
### Supabase
|
|
103
|
+
```
|
|
104
|
+
PORT=5000
|
|
105
|
+
SUPABASE_URL=https://xxxx.supabase.co
|
|
106
|
+
SUPABASE_ANON_KEY=public-key
|
|
107
|
+
SUPABASE_SERVICE_ROLE_KEY=service-role-key
|
|
108
|
+
JWT_SECRET=supersecret
|
|
109
|
+
```
|
|
49
110
|
|
|
50
|
-
##
|
|
111
|
+
## š” Database Safety (Enterprise Behavior)
|
|
51
112
|
|
|
52
|
-
|
|
113
|
+
- If DB is not connected, DB-dependent routes are automatically blocked
|
|
114
|
+
- The server never crashes due to missing DB or env variables
|
|
115
|
+
- Clear warnings are logged instead
|
|
53
116
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
117
|
+
## š§Ŗ Health Check
|
|
118
|
+
```
|
|
119
|
+
GET /health
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**Response:**
|
|
123
|
+
```json
|
|
124
|
+
{
|
|
125
|
+
"status": "ok"
|
|
126
|
+
}
|
|
127
|
+
```
|
|
62
128
|
|
|
63
|
-
##
|
|
129
|
+
## š Node Version
|
|
130
|
+
- Node.js ā„ 18
|
|
64
131
|
|
|
65
|
-
|
|
132
|
+
## š§ Philosophy
|
|
66
133
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
134
|
+
This tool is built for:
|
|
135
|
+
- SaaS backends
|
|
136
|
+
- Admin dashboards
|
|
137
|
+
- APIs at scale
|
|
138
|
+
- Teams that care about structure & safety
|
|
71
139
|
|
|
72
|
-
|
|
73
|
-
```bash
|
|
74
|
-
npm run dev
|
|
75
|
-
```
|
|
140
|
+
It's meant to be extended, not locked.
|
|
76
141
|
|
|
77
|
-
|
|
142
|
+
## š£ Roadmap
|
|
143
|
+
- PostgreSQL & MySQL templates
|
|
144
|
+
- Docker & CI templates
|
|
145
|
+
- CLI flags (--yes, --framework, --db)
|
|
146
|
+
- Prisma / Drizzle support
|
|
147
|
+
- RBAC & multi-tenant auth
|
|
78
148
|
|
|
79
|
-
##
|
|
149
|
+
## š¤ Contributing
|
|
80
150
|
|
|
81
|
-
|
|
151
|
+
Contributions are welcome!
|
|
152
|
+
- Fork the repo
|
|
153
|
+
- Create a feature branch
|
|
154
|
+
- Submit a PR
|
|
82
155
|
|
|
83
|
-
##
|
|
156
|
+
## š License
|
|
84
157
|
|
|
85
|
-
|
|
158
|
+
MIT Ā© Imad Hussain Khan
|
|
86
159
|
|
|
87
|
-
##
|
|
160
|
+
## ā Support
|
|
88
161
|
|
|
89
|
-
|
|
162
|
+
If this tool helped you:
|
|
163
|
+
- ā Star the repo
|
|
164
|
+
- š Report issues
|
|
165
|
+
- š” Suggest features
|
package/core/install.js
CHANGED
package/core/run.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import path from "path";
|
|
2
|
+
import fs from "fs-extra";
|
|
2
3
|
import prompts from "prompts";
|
|
3
4
|
import chalk from "chalk";
|
|
4
5
|
import { generateProject } from "./scaffold.js";
|
|
@@ -15,8 +16,7 @@ export async function run() {
|
|
|
15
16
|
type: projectNameArg ? null : "text",
|
|
16
17
|
name: "projectName",
|
|
17
18
|
message: "Project name?",
|
|
18
|
-
validate: (
|
|
19
|
-
v?.trim()?.length ? true : "Project name is required"
|
|
19
|
+
validate: v => v?.trim()?.length ? true : "Project name is required"
|
|
20
20
|
},
|
|
21
21
|
{
|
|
22
22
|
type: "select",
|
|
@@ -54,7 +54,6 @@ export async function run() {
|
|
|
54
54
|
);
|
|
55
55
|
|
|
56
56
|
const projectName = (projectNameArg || answers.projectName).trim();
|
|
57
|
-
const { framework, database } = answers;
|
|
58
57
|
|
|
59
58
|
const targetDir =
|
|
60
59
|
projectName === "." || projectName === "./"
|
|
@@ -64,12 +63,18 @@ export async function run() {
|
|
|
64
63
|
console.log(chalk.gray("\nš¦ Generating project..."));
|
|
65
64
|
|
|
66
65
|
await generateProject({
|
|
67
|
-
framework,
|
|
68
|
-
database,
|
|
66
|
+
framework: answers.framework,
|
|
67
|
+
database: answers.database,
|
|
69
68
|
targetDir,
|
|
70
69
|
projectName
|
|
71
70
|
});
|
|
72
71
|
|
|
72
|
+
// š SAFETY CHECK
|
|
73
|
+
const pkgPath = path.join(targetDir, "package.json");
|
|
74
|
+
if (!(await fs.pathExists(pkgPath))) {
|
|
75
|
+
throw new Error("package.json not found. Scaffolding failed.");
|
|
76
|
+
}
|
|
77
|
+
|
|
73
78
|
if (answers.install) {
|
|
74
79
|
console.log(chalk.gray("\nš„ Installing dependencies..."));
|
|
75
80
|
await installDeps({ targetDir });
|
package/core/scaffold.js
CHANGED
|
@@ -19,8 +19,8 @@ export async function generateProject({
|
|
|
19
19
|
projectName
|
|
20
20
|
}) {
|
|
21
21
|
const root = getPackageRoot();
|
|
22
|
-
|
|
23
22
|
const dbFolder = DB_MAP[database];
|
|
23
|
+
|
|
24
24
|
if (!dbFolder) {
|
|
25
25
|
throw new Error(`Unsupported database: ${database}`);
|
|
26
26
|
}
|
|
@@ -31,19 +31,29 @@ export async function generateProject({
|
|
|
31
31
|
throw new Error(`Template not found: ${framework}/${dbFolder}`);
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
const isCurrentDir =
|
|
35
|
-
projectName === "." || projectName === "./";
|
|
36
|
-
|
|
37
|
-
if (!isCurrentDir && (await fs.pathExists(targetDir))) {
|
|
38
|
-
throw new Error(`Target folder already exists: ${projectName}`);
|
|
39
|
-
}
|
|
34
|
+
const isCurrentDir = projectName === "." || projectName === "./";
|
|
40
35
|
|
|
41
36
|
await fs.ensureDir(targetDir);
|
|
42
37
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
38
|
+
// š EMPTY DIRECTORY CHECK (CRITICAL)
|
|
39
|
+
if (isCurrentDir) {
|
|
40
|
+
const entries = await fs.readdir(targetDir);
|
|
41
|
+
const allowed = [".git", ".gitignore", ".DS_Store"];
|
|
42
|
+
|
|
43
|
+
const unsafe = entries.filter(e => !allowed.includes(e));
|
|
44
|
+
if (unsafe.length > 0) {
|
|
45
|
+
throw new Error(
|
|
46
|
+
"Current directory is not empty. Please use an empty folder."
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
} else {
|
|
50
|
+
if ((await fs.pathExists(targetDir)) && (await fs.readdir(targetDir)).length) {
|
|
51
|
+
throw new Error(`Target folder already exists: ${projectName}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// ā
SAFE COPY
|
|
56
|
+
await fs.copy(templateDir, targetDir);
|
|
47
57
|
|
|
48
58
|
// Rename package.json only when not using "."
|
|
49
59
|
const pkgPath = path.join(targetDir, "package.json");
|
package/package.json
CHANGED