@ifecodes/backend-template 1.0.7 → 1.0.9

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/bin/cli.js CHANGED
@@ -123,21 +123,30 @@ if (isInMicroserviceProject || config.projectType === "microservice") {
123
123
  .filter((f) => fs.statSync(path.join(servicesDir, f)).isDirectory())
124
124
  : servicesToCreate;
125
125
 
126
+ // Track if all installs succeeded for Husky setup
127
+ let allInstallsSucceeded = true;
128
+
126
129
  // Now setup each service with knowledge of all services
127
130
  for (const serviceName of servicesToCreate) {
128
131
  const serviceRoot = path.join(target, "services", serviceName);
129
132
  const shouldIncludeAuth = isInMicroserviceProject
130
133
  ? config.auth
131
134
  : serviceName === "auth-service";
132
- await setupService(
135
+ const result = await setupService(
133
136
  config,
134
137
  serviceName,
135
138
  serviceRoot,
136
139
  shouldIncludeAuth,
137
140
  allServices
138
141
  );
142
+ if (!result.installSucceeded) {
143
+ allInstallsSucceeded = false;
144
+ }
139
145
  }
140
146
 
147
+ // Store for later use
148
+ config.allInstallsSucceeded = allInstallsSucceeded;
149
+
141
150
  if (mode === "docker") {
142
151
  generateDockerCompose(target, allServices);
143
152
  copyDockerfile(target, servicesToCreate);
@@ -165,7 +174,8 @@ if (isInMicroserviceProject || config.projectType === "microservice") {
165
174
  );
166
175
  }
167
176
  } else {
168
- await setupService(config, null, target, true);
177
+ const result = await setupService(config, null, target, true);
178
+ config.installSucceeded = result.installSucceeded;
169
179
  }
170
180
 
171
181
  // Generate README.md
@@ -174,6 +184,28 @@ if (!isInMicroserviceProject) {
174
184
  const readmeContent = generateReadme(config);
175
185
  fs.writeFileSync(path.join(target, "README.md"), readmeContent);
176
186
 
187
+ // Rename gitignore to .gitignore (npm doesn't publish .gitignore files)
188
+ if (config.projectType === "microservice") {
189
+ const servicesDir = path.join(target, "services");
190
+ const allServices = fs.readdirSync(servicesDir).filter((f) =>
191
+ fs.statSync(path.join(servicesDir, f)).isDirectory()
192
+ );
193
+
194
+ for (const service of allServices) {
195
+ const gitignorePath = path.join(servicesDir, service, "gitignore");
196
+ const dotGitignorePath = path.join(servicesDir, service, ".gitignore");
197
+ if (fs.existsSync(gitignorePath)) {
198
+ fs.renameSync(gitignorePath, dotGitignorePath);
199
+ }
200
+ }
201
+ } else {
202
+ const gitignorePath = path.join(target, "gitignore");
203
+ const dotGitignorePath = path.join(target, ".gitignore");
204
+ if (fs.existsSync(gitignorePath)) {
205
+ fs.renameSync(gitignorePath, dotGitignorePath);
206
+ }
207
+ }
208
+
177
209
  // Generate .env from .env.example for each service or root
178
210
  console.log("📄 Setting up environment files...\n");
179
211
  if (config.projectType === "microservice") {
@@ -205,17 +237,20 @@ if (!isInMicroserviceProject) {
205
237
  // Install husky and setup at root level
206
238
  if (config.projectType === "microservice") {
207
239
  console.log("\n📦 Installing Husky at root level...\n");
208
- try {
209
- execSync("npm install", { cwd: target, stdio: "inherit" });
210
- console.log("\n🔧 Setting up Husky...\n");
211
- execSync("npm run prepare", { cwd: target, stdio: "inherit" });
212
- } catch (error) {
213
- console.log("\n⚠️ Husky setup skipped (dependencies not installed)\n");
240
+ if (config.allInstallsSucceeded) {
241
+ try {
242
+ execSync("npm install", { cwd: target, stdio: "inherit" });
243
+ console.log("\n🔧 Setting up Husky...\n");
244
+ execSync("npm run prepare", { cwd: target, stdio: "inherit" });
245
+ } catch (error) {
246
+ console.log("\n⚠️ Husky setup failed\n");
247
+ }
248
+ } else {
249
+ console.log("\n⚠️ Husky setup skipped (run 'npm install && npm run prepare' after fixing service dependencies)\n");
214
250
  }
215
251
  } else if (config.projectType === "monolith") {
216
- // Only setup Husky if node_modules exists (dependencies installed successfully)
217
- const nodeModulesPath = path.join(target, "node_modules");
218
- if (fs.existsSync(nodeModulesPath)) {
252
+ // Only setup Husky if installation succeeded
253
+ if (config.installSucceeded) {
219
254
  console.log("\n🔧 Setting up Husky...\n");
220
255
  try {
221
256
  execSync("npm run prepare", { cwd: target, stdio: "inherit" });
@@ -14,6 +14,7 @@ export const setupService = async (
14
14
  let imports = [];
15
15
  let middlewares = [];
16
16
  let deps = [];
17
+ let devDeps = [];
17
18
  let v1Imports = [];
18
19
  let v1Routes = [];
19
20
 
@@ -61,6 +62,9 @@ export const setupService = async (
61
62
  imports.push(feature.imports);
62
63
  middlewares.push(feature.middleware);
63
64
  deps.push(...feature.deps);
65
+ if (feature.devDeps) {
66
+ devDeps.push(...feature.devDeps);
67
+ }
64
68
  }
65
69
  }
66
70
 
@@ -70,6 +74,9 @@ export const setupService = async (
70
74
  "../../template/features/auth/base/inject.js"
71
75
  );
72
76
  deps.push(...baseAuth.deps);
77
+ if (baseAuth.devDeps) {
78
+ devDeps.push(...baseAuth.devDeps);
79
+ }
73
80
 
74
81
  for (const file in baseAuth.files) {
75
82
  const fullPath = path.join(serviceRoot, file);
@@ -103,6 +110,9 @@ export const setupService = async (
103
110
  `../../template/features/auth/${algo.hasher}/inject.js`
104
111
  );
105
112
  deps.push(...hashFeature.deps);
113
+ if (hashFeature.devDeps) {
114
+ devDeps.push(...hashFeature.devDeps);
115
+ }
106
116
 
107
117
  for (const file in hashFeature.files) {
108
118
  const fullPath = path.join(serviceRoot, file);
@@ -197,8 +207,13 @@ export const setupService = async (
197
207
  "/*__MONGO_URI__*/",
198
208
  'MONGO_URI: process.env.MONGO_URI!,'
199
209
  );
210
+ envContent = envContent.replace(
211
+ "/*__JWT_SECRET__*/",
212
+ 'JWT_SECRET: process.env.JWT_SECRET!,'
213
+ );
200
214
  } else {
201
215
  envContent = envContent.replace("/*__MONGO_URI__*/", "");
216
+ envContent = envContent.replace("/*__JWT_SECRET__*/", "");
202
217
  }
203
218
 
204
219
  fs.writeFileSync(envPath, envContent);
@@ -297,6 +312,8 @@ await connectDB();`
297
312
  `\n📦 Installing dependencies for ${serviceName || "project"}...\n`
298
313
  );
299
314
 
315
+ let installSucceeded = false;
316
+
300
317
  try {
301
318
  if (deps.length) {
302
319
  execSync(`npm install ${deps.join(" ")}`, {
@@ -304,18 +321,34 @@ await connectDB();`
304
321
  stdio: "inherit",
305
322
  });
306
323
  }
324
+ if (devDeps.length) {
325
+ execSync(`npm install -D ${devDeps.join(" ")}`, {
326
+ cwd: serviceRoot,
327
+ stdio: "inherit",
328
+ });
329
+ }
307
330
  execSync("npm install", { cwd: serviceRoot, stdio: "inherit" });
331
+ installSucceeded = true;
332
+
333
+ // Run format after successful install
334
+ console.log("\n🎨 Formatting code...\n");
335
+ try {
336
+ execSync("npm run format", { cwd: serviceRoot, stdio: "inherit" });
337
+ } catch (formatError) {
338
+ console.warn("⚠️ Warning: Code formatting failed. You can run it manually later with: npm run format\n");
339
+ }
308
340
  } catch (error) {
309
341
  console.error("\n⚠️ Warning: Some dependencies failed to install.");
310
342
  console.error("This is usually due to native modules (like argon2) requiring build tools.\n");
311
343
  console.error("💡 Solutions:");
312
344
  console.error(" 1. Install build tools: npm install --global windows-build-tools");
313
345
  console.error(" 2. Or switch to bcrypt (works better on Windows)");
314
- console.error(" 3. Or manually install later: cd " + (serviceName || res.sanitizedName) + " && npm install\n");
346
+ console.error(" 3. Or manually install later: cd " + (serviceName || res.sanitizedName) + " && npm install");
347
+ console.error(" 4. Then run: npm run format\n");
315
348
 
316
349
  // Don't exit - let the project be created anyway
317
350
  console.log("⏭️ Continuing with project creation...\n");
318
351
  }
319
352
 
320
- return deps;
353
+ return { deps, installSucceeded };
321
354
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ifecodes/backend-template",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "Production-ready Express + TypeScript backend generator with optional features and microservice support",
5
5
  "bin": {
6
6
  "ifecodes-template": "bin/cli.js"
@@ -0,0 +1,31 @@
1
+ # Dependencies
2
+ node_modules/
3
+ package-lock.json
4
+
5
+ # Build output
6
+ dist/
7
+
8
+ # Environment variables
9
+ .env
10
+ .env.local
11
+ .env.*.local
12
+
13
+ # Logs
14
+ logs/
15
+ *.log
16
+ npm-debug.log*
17
+ yarn-debug.log*
18
+
19
+ # ESLint
20
+ .eslintcache
21
+
22
+ # OS files
23
+ .DS_Store
24
+ Thumbs.db
25
+
26
+ # IDE
27
+ .vscode/
28
+ .idea/
29
+ *.swp
30
+ *.swo
31
+
@@ -6,4 +6,5 @@ export const ENV = {
6
6
  /*__ALLOWED_ORIGIN__*/
7
7
  NODE_ENV: process.env.NODE_ENV!,
8
8
  /*__MONGO_URI__*/
9
+ /*__JWT_SECRET__*/
9
10
  };
@@ -1,11 +1,19 @@
1
1
  import app from "./app";
2
2
  import { ENV } from "./config";
3
+ import { logger } from "@/utils";
3
4
  /*__DB_IMPORT__*/
4
5
 
5
6
  const PORT = ENV.PORT || 3000;
6
7
 
7
- /*__DB_CONNECT__*/
8
+ const startServer = async () => {
9
+ /*__DB_CONNECT__*/
8
10
 
9
- app.listen(PORT, () => {
10
- console.log(`Server is running on port ${PORT}`);
11
- });
11
+ app.listen(PORT, () => {
12
+ logger.info("Server", `Server is running on port ${PORT}`);
13
+ });
14
+ };
15
+
16
+ startServer().catch((error) => {
17
+ logger.error("Server", "Failed to start server", error as Error);
18
+ process.exit(1);
19
+ });
@@ -84,6 +84,7 @@ export const imports = `import { authRoutes } from "./auth";`;
84
84
 
85
85
  export const middleware = `router.use("/auth", authRoutes);`;
86
86
 
87
- export const deps = ["jsonwebtoken", "@types/jsonwebtoken", "mongoose"];
87
+ export const deps = ["jsonwebtoken", "mongoose"];
88
+ export const devDeps = ["@types/jsonwebtoken"];
88
89
 
89
90
  export const targetFile = "src/modules/v1/index.ts";
@@ -1,5 +1,7 @@
1
1
  export const deps = ["bcrypt"];
2
2
 
3
+ export const devDeps = ["@types/bcrypt"];
4
+
3
5
  export const files = {
4
6
  "src/utils/hash.ts": `
5
7
  import bcrypt from "bcrypt";
@@ -1,5 +1,6 @@
1
- export const deps = ["cors", "@types/cors"];
2
- export const imports = `import cors from "cors";`;
1
+ export const deps = ["cors"];
2
+ export const devDeps = ["@types/cors"];
3
+ export const imports = `import cors from "cors";\nimport { ENV } from "@/config";`;
3
4
  export const middleware = `
4
5
  const corsOptions = {
5
6
  origin: ENV.ALLOWED_ORIGIN,
@@ -1,3 +1,4 @@
1
- export const deps = ["morgan", "@types/morgan"];
1
+ export const deps = ["morgan"];
2
+ export const devDeps = ["@types/morgan"];
2
3
  export const imports = `import morgan from "morgan";`;
3
4
  export const middleware = `app.use(morgan("dev"));`;