@ifecodes/backend-template 1.0.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/README.md +288 -0
- package/bin/cli.js +249 -0
- package/bin/lib/microservice-config.js +89 -0
- package/bin/lib/prompts.js +159 -0
- package/bin/lib/readme-generator.js +245 -0
- package/bin/lib/service-setup.js +316 -0
- package/package.json +52 -0
- package/template/base/.env.example +5 -0
- package/template/base/.eslintrc.json +17 -0
- package/template/base/.husky/pre-commit +13 -0
- package/template/base/.prettierignore +47 -0
- package/template/base/.prettierrc +7 -0
- package/template/base/eslint.config.js +33 -0
- package/template/base/package.json +32 -0
- package/template/base/src/app.ts +9 -0
- package/template/base/src/config/db.ts +4 -0
- package/template/base/src/config/env.ts +9 -0
- package/template/base/src/config/index.ts +2 -0
- package/template/base/src/middlewares/index.ts +3 -0
- package/template/base/src/middlewares/method-not-allowed.middleware.ts +17 -0
- package/template/base/src/middlewares/not-found.middleware.ts +8 -0
- package/template/base/src/middlewares/root.middleware.ts +14 -0
- package/template/base/src/modules/index.ts +8 -0
- package/template/base/src/modules/v1/health/health.controller.ts +18 -0
- package/template/base/src/modules/v1/health/health.route.ts +9 -0
- package/template/base/src/modules/v1/health/index.ts +1 -0
- package/template/base/src/modules/v1/index.ts +8 -0
- package/template/base/src/routes.ts +15 -0
- package/template/base/src/server.ts +11 -0
- package/template/base/src/utils/http-error.ts +47 -0
- package/template/base/src/utils/index.ts +11 -0
- package/template/base/src/utils/logger.ts +34 -0
- package/template/base/tsconfig.json +22 -0
- package/template/features/auth/argon2/inject.js +25 -0
- package/template/features/auth/base/inject.js +89 -0
- package/template/features/auth/bcrypt/inject.js +18 -0
- package/template/features/auth/models/index.ts +1 -0
- package/template/features/auth/models/user.model.ts +28 -0
- package/template/features/auth/modules/auth.controller.ts +20 -0
- package/template/features/auth/modules/auth.routes.ts +11 -0
- package/template/features/auth/modules/auth.service.ts +38 -0
- package/template/features/auth/modules/index.ts +1 -0
- package/template/features/auth/utils/hash.ts +20 -0
- package/template/features/auth/utils/jwt.ts +15 -0
- package/template/features/cors/inject.js +9 -0
- package/template/features/helmet/inject.js +3 -0
- package/template/features/morgan/inject.js +3 -0
- package/template/features/rate-limit/inject.js +3 -0
- package/template/gateway/app.ts +26 -0
- package/template/gateway/inject.js +27 -0
- package/template/gateway/server.ts +19 -0
- package/template/microservice/docker/Dockerfile +5 -0
- package/template/microservice/docker/docker-compose.yml +6 -0
- package/template/microservice/nodocker/pm2.config.js +3 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import prompts from "prompts";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
|
|
5
|
+
export const getProjectConfig = async () => {
|
|
6
|
+
// Check if running in CI or non-interactive mode
|
|
7
|
+
const isCI = process.env.CI === 'true' || !process.stdin.isTTY;
|
|
8
|
+
|
|
9
|
+
// Check if we're in an existing microservice project
|
|
10
|
+
const isInMicroserviceProject = fs.existsSync(
|
|
11
|
+
path.join(process.cwd(), "services")
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
// Parse command line arguments
|
|
15
|
+
const args = process.argv.slice(2);
|
|
16
|
+
|
|
17
|
+
// Separate project name parts from project type
|
|
18
|
+
// Look for "microservice", "monolith", "micro", or "mono" in args
|
|
19
|
+
let cliName = null;
|
|
20
|
+
let cliProjectType = null;
|
|
21
|
+
|
|
22
|
+
const projectTypeKeywords = ["microservice", "monolith", "micro", "mono"];
|
|
23
|
+
const projectTypeIndex = args.findIndex(arg =>
|
|
24
|
+
projectTypeKeywords.includes(arg.toLowerCase())
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
if (projectTypeIndex !== -1) {
|
|
28
|
+
// Everything before the type keyword is the project name
|
|
29
|
+
cliName = args.slice(0, projectTypeIndex).join("-");
|
|
30
|
+
const typeArg = args[projectTypeIndex].toLowerCase();
|
|
31
|
+
cliProjectType = typeArg === "micro" || typeArg === "microservice"
|
|
32
|
+
? "microservice"
|
|
33
|
+
: "monolith";
|
|
34
|
+
} else if (args.length > 0) {
|
|
35
|
+
// If no type keyword found, treat all args as project name
|
|
36
|
+
cliName = args.join("-");
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Pre-fill values from CLI args if provided
|
|
40
|
+
const hasCliArgs = cliName && !isInMicroserviceProject;
|
|
41
|
+
|
|
42
|
+
const res = await prompts(
|
|
43
|
+
[
|
|
44
|
+
{
|
|
45
|
+
type: isInMicroserviceProject || hasCliArgs || isCI ? null : "text",
|
|
46
|
+
name: "name",
|
|
47
|
+
message: "Project name",
|
|
48
|
+
initial: "my-backend",
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
type: isInMicroserviceProject || (hasCliArgs && cliProjectType) || isCI ? null : "select",
|
|
52
|
+
name: "projectType",
|
|
53
|
+
message: "Project type",
|
|
54
|
+
choices: [
|
|
55
|
+
{ title: "Monolith API", value: "monolith" },
|
|
56
|
+
{ title: "Microservice", value: "microservice" },
|
|
57
|
+
],
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
type: (prev, values) =>
|
|
61
|
+
isInMicroserviceProject || isCI
|
|
62
|
+
? null
|
|
63
|
+
: prev === "microservice"
|
|
64
|
+
? "select"
|
|
65
|
+
: null,
|
|
66
|
+
name: "mode",
|
|
67
|
+
message: "Microservice setup",
|
|
68
|
+
choices: [
|
|
69
|
+
{ title: "With Docker", value: "docker" },
|
|
70
|
+
{ title: "Without Docker", value: "nodocker" },
|
|
71
|
+
],
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
type: isInMicroserviceProject ? "text" : isCI ? null : "multiselect",
|
|
75
|
+
name: isInMicroserviceProject ? "serviceName" : "features",
|
|
76
|
+
message: isInMicroserviceProject
|
|
77
|
+
? "New service name (e.g., user-service, order-service)"
|
|
78
|
+
: "Select features",
|
|
79
|
+
choices: isInMicroserviceProject
|
|
80
|
+
? undefined
|
|
81
|
+
: [
|
|
82
|
+
{ title: "CORS", value: "cors" },
|
|
83
|
+
{ title: "Rate Limiter", value: "rate-limit" },
|
|
84
|
+
{ title: "Helmet", value: "helmet" },
|
|
85
|
+
{ title: "Morgan (HTTP logger)", value: "morgan" },
|
|
86
|
+
],
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
type: isCI ? null : "toggle",
|
|
90
|
+
name: "auth",
|
|
91
|
+
message: isInMicroserviceProject
|
|
92
|
+
? "Include authentication in this service?"
|
|
93
|
+
: "Include authentication system?",
|
|
94
|
+
initial: true,
|
|
95
|
+
active: "yes",
|
|
96
|
+
inactive: "no",
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
type: isInMicroserviceProject && !isCI ? "multiselect" : null,
|
|
100
|
+
name: "features",
|
|
101
|
+
message: "Select features for this service",
|
|
102
|
+
choices: [
|
|
103
|
+
{ title: "Rate Limiter", value: "rate-limit" },
|
|
104
|
+
{ title: "Helmet", value: "helmet" },
|
|
105
|
+
{ title: "Morgan (HTTP logger)", value: "morgan" },
|
|
106
|
+
{ title: "CORS", value: "cors" },
|
|
107
|
+
],
|
|
108
|
+
},
|
|
109
|
+
]);
|
|
110
|
+
|
|
111
|
+
// Set defaults for CI/non-interactive mode
|
|
112
|
+
if (isCI) {
|
|
113
|
+
res.features = res.features || [];
|
|
114
|
+
res.auth = res.auth ?? false;
|
|
115
|
+
res.mode = res.mode || "docker"; // Default to docker in CI
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Merge CLI args with prompted responses
|
|
119
|
+
if (hasCliArgs) {
|
|
120
|
+
res.name = cliName;
|
|
121
|
+
if (cliProjectType) {
|
|
122
|
+
res.projectType = cliProjectType;
|
|
123
|
+
} else {
|
|
124
|
+
// If no project type in CLI, default to monolith
|
|
125
|
+
res.projectType = res.projectType || "monolith";
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
let sanitizedName, target, isExistingProject, mode;
|
|
130
|
+
|
|
131
|
+
if (isInMicroserviceProject) {
|
|
132
|
+
// We're adding to an existing project
|
|
133
|
+
target = process.cwd();
|
|
134
|
+
sanitizedName = path.basename(target);
|
|
135
|
+
isExistingProject = true;
|
|
136
|
+
|
|
137
|
+
// Detect mode from existing files
|
|
138
|
+
mode = fs.existsSync(path.join(target, "docker-compose.yml"))
|
|
139
|
+
? "docker"
|
|
140
|
+
: "nodocker";
|
|
141
|
+
|
|
142
|
+
console.log(`\n📁 Detected existing microservice project: ${sanitizedName}`);
|
|
143
|
+
console.log(`Mode: ${mode}\n`);
|
|
144
|
+
} else {
|
|
145
|
+
sanitizedName = res.name.replace(/\s+/g, "-");
|
|
146
|
+
target = path.resolve(process.cwd(), sanitizedName);
|
|
147
|
+
isExistingProject = fs.existsSync(target);
|
|
148
|
+
mode = res.mode;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return {
|
|
152
|
+
...res,
|
|
153
|
+
sanitizedName,
|
|
154
|
+
target,
|
|
155
|
+
isExistingProject,
|
|
156
|
+
mode,
|
|
157
|
+
isInMicroserviceProject,
|
|
158
|
+
};
|
|
159
|
+
};
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
|
|
4
|
+
export const generateReadme = (config, serviceName = null) => {
|
|
5
|
+
const { projectType, mode, features = [], auth, sanitizedName } = config;
|
|
6
|
+
const isMonolith = projectType === "monolith";
|
|
7
|
+
const isMicroservice = projectType === "microservice";
|
|
8
|
+
|
|
9
|
+
let readme = `# ${serviceName || sanitizedName}\n\n`;
|
|
10
|
+
|
|
11
|
+
// Description
|
|
12
|
+
if (isMicroservice && serviceName) {
|
|
13
|
+
readme += `A microservice for ${sanitizedName}.\n\n`;
|
|
14
|
+
} else if (isMicroservice) {
|
|
15
|
+
readme += `A microservices-based backend application.\n\n`;
|
|
16
|
+
} else {
|
|
17
|
+
readme += `A monolithic backend API application.\n\n`;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Architecture
|
|
21
|
+
readme += `## Architecture\n\n`;
|
|
22
|
+
if (isMicroservice) {
|
|
23
|
+
readme += `- **Type**: Microservice\n`;
|
|
24
|
+
readme += `- **Deployment**: ${mode === "docker" ? "Docker" : "PM2"}\n`;
|
|
25
|
+
readme += `- **Gateway**: Port 4000 (main entry point)\n`;
|
|
26
|
+
readme += `- **Services**:\n`;
|
|
27
|
+
readme += ` - Gateway (port 4000)\n`;
|
|
28
|
+
readme += ` - Health Service (port 4001)\n`;
|
|
29
|
+
if (auth) readme += ` - Auth Service (port 4002)\n`;
|
|
30
|
+
readme += `\n`;
|
|
31
|
+
} else {
|
|
32
|
+
readme += `- **Type**: Monolith API\n`;
|
|
33
|
+
readme += `- **Port**: 4000 (default)\n\n`;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Tech Stack
|
|
37
|
+
readme += `## Tech Stack\n\n`;
|
|
38
|
+
readme += `- **Runtime**: Node.js\n`;
|
|
39
|
+
readme += `- **Language**: TypeScript\n`;
|
|
40
|
+
readme += `- **Framework**: Express.js\n`;
|
|
41
|
+
if (auth) readme += `- **Database**: MongoDB (Mongoose)\n`;
|
|
42
|
+
|
|
43
|
+
if (features.length > 0 || auth) {
|
|
44
|
+
readme += `- **Features**:\n`;
|
|
45
|
+
if (features.includes("cors")) readme += ` - CORS\n`;
|
|
46
|
+
if (features.includes("helmet")) readme += ` - Helmet (Security headers)\n`;
|
|
47
|
+
if (features.includes("rate-limit")) readme += ` - Rate Limiting\n`;
|
|
48
|
+
if (features.includes("morgan")) readme += ` - Morgan (HTTP logging)\n`;
|
|
49
|
+
if (auth) readme += ` - Authentication (JWT)\n`;
|
|
50
|
+
}
|
|
51
|
+
readme += `\n`;
|
|
52
|
+
|
|
53
|
+
// Getting Started
|
|
54
|
+
readme += `## Getting Started\n\n`;
|
|
55
|
+
readme += `### Prerequisites\n\n`;
|
|
56
|
+
readme += `- Node.js (v18 or higher)\n`;
|
|
57
|
+
readme += `- npm or yarn\n`;
|
|
58
|
+
if (auth) readme += `- MongoDB\n`;
|
|
59
|
+
if (isMicroservice && mode === "docker") readme += `- Docker & Docker Compose\n`;
|
|
60
|
+
if (isMicroservice && mode === "nodocker") readme += `- PM2 (\`npm install -g pm2\`)\n`;
|
|
61
|
+
readme += `\n`;
|
|
62
|
+
|
|
63
|
+
// Installation
|
|
64
|
+
readme += `### Installation\n\n`;
|
|
65
|
+
readme += `1. Clone the repository\n`;
|
|
66
|
+
readme += `\`\`\`bash\n`;
|
|
67
|
+
readme += `cd ${sanitizedName}\n`;
|
|
68
|
+
readme += `\`\`\`\n\n`;
|
|
69
|
+
|
|
70
|
+
if (isMicroservice) {
|
|
71
|
+
readme += `2. Install dependencies for all services\n`;
|
|
72
|
+
readme += `\`\`\`bash\n`;
|
|
73
|
+
readme += `# Install root dependencies (Husky)\n`;
|
|
74
|
+
readme += `npm install\n\n`;
|
|
75
|
+
readme += `# Install dependencies for each service\n`;
|
|
76
|
+
readme += `cd services/gateway && npm install && cd ../..\n`;
|
|
77
|
+
readme += `cd services/health-service && npm install && cd ../..\n`;
|
|
78
|
+
if (auth) readme += `cd services/auth-service && npm install && cd ../..\n`;
|
|
79
|
+
readme += `\`\`\`\n\n`;
|
|
80
|
+
} else {
|
|
81
|
+
readme += `2. Install dependencies\n`;
|
|
82
|
+
readme += `\`\`\`bash\n`;
|
|
83
|
+
readme += `npm install\n`;
|
|
84
|
+
readme += `\`\`\`\n\n`;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Environment Variables
|
|
88
|
+
readme += `3. Set up environment variables\n`;
|
|
89
|
+
readme += `\`\`\`bash\n`;
|
|
90
|
+
if (isMicroservice) {
|
|
91
|
+
readme += `# Copy .env.example to .env in each service\n`;
|
|
92
|
+
readme += `cp services/gateway/.env.example services/gateway/.env\n`;
|
|
93
|
+
readme += `cp services/health-service/.env.example services/health-service/.env\n`;
|
|
94
|
+
if (auth) readme += `cp services/auth-service/.env.example services/auth-service/.env\n`;
|
|
95
|
+
} else {
|
|
96
|
+
readme += `cp .env.example .env\n`;
|
|
97
|
+
}
|
|
98
|
+
readme += `\`\`\`\n\n`;
|
|
99
|
+
|
|
100
|
+
if (auth) {
|
|
101
|
+
readme += `4. Configure your MongoDB connection and JWT secret in the \`.env\` file${isMicroservice ? "s" : ""}\n\n`;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Running the Application
|
|
105
|
+
readme += `## Running the Application\n\n`;
|
|
106
|
+
|
|
107
|
+
if (isMicroservice && mode === "docker") {
|
|
108
|
+
readme += `### With Docker\n\n`;
|
|
109
|
+
readme += `\`\`\`bash\n`;
|
|
110
|
+
readme += `# Start all services\n`;
|
|
111
|
+
readme += `docker-compose up\n\n`;
|
|
112
|
+
readme += `# Start in detached mode\n`;
|
|
113
|
+
readme += `docker-compose up -d\n\n`;
|
|
114
|
+
readme += `# Stop all services\n`;
|
|
115
|
+
readme += `docker-compose down\n`;
|
|
116
|
+
readme += `\`\`\`\n\n`;
|
|
117
|
+
} else if (isMicroservice && mode === "nodocker") {
|
|
118
|
+
readme += `### With PM2\n\n`;
|
|
119
|
+
readme += `\`\`\`bash\n`;
|
|
120
|
+
readme += `# Start all services\n`;
|
|
121
|
+
readme += `pm2 start pm2.config.js\n\n`;
|
|
122
|
+
readme += `# View logs\n`;
|
|
123
|
+
readme += `pm2 logs\n\n`;
|
|
124
|
+
readme += `# Stop all services\n`;
|
|
125
|
+
readme += `pm2 stop all\n\n`;
|
|
126
|
+
readme += `# Delete all services\n`;
|
|
127
|
+
readme += `pm2 delete all\n`;
|
|
128
|
+
readme += `\`\`\`\n\n`;
|
|
129
|
+
} else {
|
|
130
|
+
readme += `### Development\n\n`;
|
|
131
|
+
readme += `\`\`\`bash\n`;
|
|
132
|
+
readme += `npm run dev\n`;
|
|
133
|
+
readme += `\`\`\`\n\n`;
|
|
134
|
+
readme += `### Production\n\n`;
|
|
135
|
+
readme += `\`\`\`bash\n`;
|
|
136
|
+
readme += `npm run build\n`;
|
|
137
|
+
readme += `npm start\n`;
|
|
138
|
+
readme += `\`\`\`\n\n`;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// API Endpoints
|
|
142
|
+
readme += `## API Endpoints\n\n`;
|
|
143
|
+
|
|
144
|
+
if (isMicroservice) {
|
|
145
|
+
readme += `All requests go through the API Gateway at \`http://localhost:4000\`\n\n`;
|
|
146
|
+
readme += `### Health Service\n`;
|
|
147
|
+
readme += `- **GET** \`/health\` - Health check\n\n`;
|
|
148
|
+
|
|
149
|
+
if (auth) {
|
|
150
|
+
readme += `### Auth Service\n`;
|
|
151
|
+
readme += `- **POST** \`/auth/register\` - Register a new user\n`;
|
|
152
|
+
readme += `- **POST** \`/auth/login\` - Login user\n\n`;
|
|
153
|
+
}
|
|
154
|
+
} else {
|
|
155
|
+
readme += `Base URL: \`http://localhost:4000\`\n\n`;
|
|
156
|
+
readme += `- **GET** \`/\` - Root endpoint (API info)\n`;
|
|
157
|
+
readme += `- **GET** \`/v1/health\` - Health check\n\n`;
|
|
158
|
+
|
|
159
|
+
if (auth) {
|
|
160
|
+
readme += `### Authentication\n`;
|
|
161
|
+
readme += `- **POST** \`/v1/auth/register\` - Register a new user\n`;
|
|
162
|
+
readme += `- **POST** \`/v1/auth/login\` - Login user\n\n`;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Project Structure
|
|
167
|
+
readme += `## Project Structure\n\n`;
|
|
168
|
+
readme += `\`\`\`\n`;
|
|
169
|
+
|
|
170
|
+
if (isMicroservice) {
|
|
171
|
+
readme += `${sanitizedName}/\n`;
|
|
172
|
+
readme += `├── shared/ # Shared utilities across services\n`;
|
|
173
|
+
readme += `│ ├── config/ # Database, environment configs\n`;
|
|
174
|
+
readme += `│ └── utils/ # Logger, error handlers\n`;
|
|
175
|
+
readme += `├── services/\n`;
|
|
176
|
+
readme += `│ ├── gateway/ # API Gateway (port 4000)\n`;
|
|
177
|
+
readme += `│ ├── health-service/ # Health checks (port 4001)\n`;
|
|
178
|
+
if (auth) readme += `│ └── auth-service/ # Authentication (port 4002)\n`;
|
|
179
|
+
else readme += `│ └── ...\n`;
|
|
180
|
+
readme += `├── ${mode === "docker" ? "docker-compose.yml" : "pm2.config.js"}\n`;
|
|
181
|
+
readme += `├── .husky/ # Git hooks\n`;
|
|
182
|
+
readme += `└── package.json # Root package.json\n`;
|
|
183
|
+
} else {
|
|
184
|
+
readme += `${sanitizedName}/\n`;
|
|
185
|
+
readme += `├── src/\n`;
|
|
186
|
+
readme += `│ ├── config/ # Configuration files\n`;
|
|
187
|
+
readme += `│ ├── middlewares/ # Custom middlewares\n`;
|
|
188
|
+
readme += `│ ├── modules/ # Feature modules\n`;
|
|
189
|
+
readme += `│ │ └── v1/ # API version 1\n`;
|
|
190
|
+
if (auth) readme += `│ │ ├── auth/ # Auth module\n`;
|
|
191
|
+
readme += `│ │ └── health/ # Health check\n`;
|
|
192
|
+
if (auth) readme += `│ ├── models/ # Database models\n`;
|
|
193
|
+
readme += `│ ├── utils/ # Utility functions\n`;
|
|
194
|
+
readme += `│ ├── app.ts # Express app setup\n`;
|
|
195
|
+
readme += `│ ├── routes.ts # Route definitions\n`;
|
|
196
|
+
readme += `│ └── server.ts # Server entry point\n`;
|
|
197
|
+
readme += `├── .husky/ # Git hooks\n`;
|
|
198
|
+
readme += `├── package.json\n`;
|
|
199
|
+
readme += `└── tsconfig.json\n`;
|
|
200
|
+
}
|
|
201
|
+
readme += `\`\`\`\n\n`;
|
|
202
|
+
|
|
203
|
+
// Scripts
|
|
204
|
+
readme += `## Available Scripts\n\n`;
|
|
205
|
+
if (isMicroservice) {
|
|
206
|
+
if (mode === "docker") {
|
|
207
|
+
readme += `- \`docker-compose up\` - Start all services\n`;
|
|
208
|
+
readme += `- \`docker-compose down\` - Stop all services\n`;
|
|
209
|
+
readme += `- \`docker-compose logs -f [service-name]\` - View service logs\n`;
|
|
210
|
+
} else {
|
|
211
|
+
readme += `- \`pm2 start pm2.config.js\` - Start all services\n`;
|
|
212
|
+
readme += `- \`pm2 logs\` - View all service logs\n`;
|
|
213
|
+
readme += `- \`pm2 monit\` - Monitor services\n`;
|
|
214
|
+
readme += `- \`pm2 stop all\` - Stop all services\n`;
|
|
215
|
+
}
|
|
216
|
+
} else {
|
|
217
|
+
readme += `- \`npm run dev\` - Start development server with hot reload\n`;
|
|
218
|
+
readme += `- \`npm run build\` - Build for production\n`;
|
|
219
|
+
readme += `- \`npm start\` - Start production server\n`;
|
|
220
|
+
readme += `- \`npm run lint\` - Run ESLint\n`;
|
|
221
|
+
readme += `- \`npm run format\` - Run Prettier\n`;
|
|
222
|
+
}
|
|
223
|
+
readme += `\n`;
|
|
224
|
+
|
|
225
|
+
// Environment Variables
|
|
226
|
+
readme += `## Environment Variables\n\n`;
|
|
227
|
+
readme += `| Variable | Description | Default |\n`;
|
|
228
|
+
readme += `|----------|-------------|---------||\n`;
|
|
229
|
+
readme += `| \`PORT\` | Server port | \`4000\` |\n`;
|
|
230
|
+
readme += `| \`NODE_ENV\` | Environment | \`development\` |\n`;
|
|
231
|
+
if (features.includes("cors")) {
|
|
232
|
+
readme += `| \`ALLOWED_ORIGIN\` | CORS allowed origin | \`http://localhost:3000\` |\n`;
|
|
233
|
+
}
|
|
234
|
+
if (auth) {
|
|
235
|
+
readme += `| \`MONGO_URI\` | MongoDB connection string | - |\n`;
|
|
236
|
+
readme += `| \`JWT_SECRET\` | JWT secret key | - |\n`;
|
|
237
|
+
}
|
|
238
|
+
readme += `\n`;
|
|
239
|
+
|
|
240
|
+
// License
|
|
241
|
+
readme += `## License\n\n`;
|
|
242
|
+
readme += `MIT\n`;
|
|
243
|
+
|
|
244
|
+
return readme;
|
|
245
|
+
};
|