appinit-templates 1.0.1 → 1.0.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.
Files changed (2) hide show
  1. package/docs.generated.mjs +302 -0
  2. package/package.json +10 -3
@@ -0,0 +1,302 @@
1
+ // Auto-generated by packages/templates/scripts/generate-docs.mjs
2
+ export const templateDocsManifest = {
3
+ "languages": {
4
+ "typescript": [
5
+ {
6
+ "id": "rest_api",
7
+ "title": "REST API",
8
+ "files": [
9
+ {
10
+ "path": "base/typescript/src/config/db.ts.ejs",
11
+ "name": "db.ts.ejs",
12
+ "targetPath": "src/config/db.ts"
13
+ },
14
+ {
15
+ "path": "base/typescript/src/config/env.ts.ejs",
16
+ "name": "env.ts.ejs",
17
+ "targetPath": "src/config/env.ts"
18
+ },
19
+ {
20
+ "path": "base/typescript/src/controllers/health.controller.ts.ejs",
21
+ "name": "health.controller.ts.ejs",
22
+ "targetPath": "src/controllers/health.controller.ts"
23
+ },
24
+ {
25
+ "path": "base/typescript/src/index.ts.ejs",
26
+ "name": "index.ts.ejs",
27
+ "targetPath": "src/index.ts"
28
+ },
29
+ {
30
+ "path": "base/typescript/src/middleware/errorHandler.ts.ejs",
31
+ "name": "errorHandler.ts.ejs",
32
+ "targetPath": "src/middleware/errorHandler.ts"
33
+ },
34
+ {
35
+ "path": "base/typescript/src/routes/health.routes.ts.ejs",
36
+ "name": "health.routes.ts.ejs",
37
+ "targetPath": "src/routes/health.routes.ts"
38
+ },
39
+ {
40
+ "path": "base/typescript/src/routes/index.ts.ejs",
41
+ "name": "index.ts.ejs",
42
+ "targetPath": "src/routes/index.ts"
43
+ },
44
+ {
45
+ "path": "base/typescript/src/utils/ApiError.ts.ejs",
46
+ "name": "ApiError.ts.ejs",
47
+ "targetPath": "src/utils/ApiError.ts"
48
+ },
49
+ {
50
+ "path": "base/typescript/src/utils/logger.ts.ejs",
51
+ "name": "logger.ts.ejs",
52
+ "targetPath": "src/utils/logger.ts"
53
+ }
54
+ ]
55
+ },
56
+ {
57
+ "id": "configuration",
58
+ "title": "Configuration Files",
59
+ "files": [
60
+ {
61
+ "path": "base/typescript/.prettierrc.ejs",
62
+ "name": ".prettierrc.ejs",
63
+ "targetPath": ".prettierrc"
64
+ },
65
+ {
66
+ "path": "base/typescript/eslint.config.js.ejs",
67
+ "name": "eslint.config.js.ejs",
68
+ "targetPath": "eslint.config.js"
69
+ },
70
+ {
71
+ "path": "base/typescript/Readme.md.ejs",
72
+ "name": "Readme.md.ejs",
73
+ "targetPath": "Readme.md"
74
+ }
75
+ ]
76
+ },
77
+ {
78
+ "id": "common",
79
+ "title": "Common Files",
80
+ "files": [
81
+ {
82
+ "path": "base/common/,gitignore.ejs",
83
+ "name": ",gitignore.ejs",
84
+ "targetPath": ".gitignore"
85
+ },
86
+ {
87
+ "path": "base/common/env.ejs",
88
+ "name": "env.ejs",
89
+ "targetPath": ".env"
90
+ }
91
+ ]
92
+ },
93
+ {
94
+ "id": "websocket_ws",
95
+ "title": "WebSocket (ws)",
96
+ "files": [
97
+ {
98
+ "path": "base/websockets/ws/typescript/index.ts.ejs",
99
+ "name": "index.ts.ejs",
100
+ "targetPath": "src/index.ts"
101
+ }
102
+ ]
103
+ },
104
+ {
105
+ "id": "websocket_socketio",
106
+ "title": "WebSocket (socket.io)",
107
+ "files": [
108
+ {
109
+ "path": "base/websockets/socket.io/typescript/index.ts.ejs",
110
+ "name": "index.ts.ejs",
111
+ "targetPath": "src/index.ts"
112
+ }
113
+ ]
114
+ },
115
+ {
116
+ "id": "docker",
117
+ "title": "Docker",
118
+ "files": [
119
+ {
120
+ "path": "features/docker/base/typescript/Dockerfile.ejs",
121
+ "name": "Dockerfile.ejs",
122
+ "targetPath": "Dockerfile"
123
+ }
124
+ ]
125
+ }
126
+ ],
127
+ "javascript": [
128
+ {
129
+ "id": "rest_api",
130
+ "title": "REST API",
131
+ "files": [
132
+ {
133
+ "path": "base/javascript/src/config/db.js.ejs",
134
+ "name": "db.js.ejs",
135
+ "targetPath": "src/config/db.js"
136
+ },
137
+ {
138
+ "path": "base/javascript/src/config/env.js.ejs",
139
+ "name": "env.js.ejs",
140
+ "targetPath": "src/config/env.js"
141
+ },
142
+ {
143
+ "path": "base/javascript/src/controllers/health.controller.js.ejs",
144
+ "name": "health.controller.js.ejs",
145
+ "targetPath": "src/controllers/health.controller.js"
146
+ },
147
+ {
148
+ "path": "base/javascript/src/index.js.ejs",
149
+ "name": "index.js.ejs",
150
+ "targetPath": "index.js"
151
+ },
152
+ {
153
+ "path": "base/javascript/src/middleware/asyncHandler.js.ejs",
154
+ "name": "asyncHandler.js.ejs",
155
+ "targetPath": "src/middleware/asyncHandler.js"
156
+ },
157
+ {
158
+ "path": "base/javascript/src/middleware/errorHandler.js.ejs",
159
+ "name": "errorHandler.js.ejs",
160
+ "targetPath": "src/middleware/errorHandler.js"
161
+ },
162
+ {
163
+ "path": "base/javascript/src/routes/health.routes.js.ejs",
164
+ "name": "health.routes.js.ejs",
165
+ "targetPath": "src/routes/health.routes.js"
166
+ },
167
+ {
168
+ "path": "base/javascript/src/routes/index.js.ejs",
169
+ "name": "index.js.ejs",
170
+ "targetPath": "src/routes/index.js"
171
+ },
172
+ {
173
+ "path": "base/javascript/src/utils/ApiError.js.ejs",
174
+ "name": "ApiError.js.ejs",
175
+ "targetPath": "src/utils/ApiError.js"
176
+ },
177
+ {
178
+ "path": "base/javascript/src/utils/logger.js.ejs",
179
+ "name": "logger.js.ejs",
180
+ "targetPath": "src/utils/logger.js"
181
+ }
182
+ ]
183
+ },
184
+ {
185
+ "id": "configuration",
186
+ "title": "Configuration Files",
187
+ "files": [
188
+ {
189
+ "path": "base/javascript/.prettierrc.ejs",
190
+ "name": ".prettierrc.ejs",
191
+ "targetPath": ".prettierrc"
192
+ },
193
+ {
194
+ "path": "base/javascript/eslint.config.js.ejs",
195
+ "name": "eslint.config.js.ejs",
196
+ "targetPath": "eslint.config.js"
197
+ },
198
+ {
199
+ "path": "base/javascript/Readme.md.ejs",
200
+ "name": "Readme.md.ejs",
201
+ "targetPath": "Readme.md"
202
+ }
203
+ ]
204
+ },
205
+ {
206
+ "id": "common",
207
+ "title": "Common Files",
208
+ "files": [
209
+ {
210
+ "path": "base/common/,gitignore.ejs",
211
+ "name": ",gitignore.ejs",
212
+ "targetPath": ".gitignore"
213
+ },
214
+ {
215
+ "path": "base/common/env.ejs",
216
+ "name": "env.ejs",
217
+ "targetPath": ".env"
218
+ }
219
+ ]
220
+ },
221
+ {
222
+ "id": "websocket_ws",
223
+ "title": "WebSocket (ws)",
224
+ "files": [
225
+ {
226
+ "path": "base/websockets/ws/javascript/index.js.ejs",
227
+ "name": "index.js.ejs",
228
+ "targetPath": "index.js"
229
+ }
230
+ ]
231
+ },
232
+ {
233
+ "id": "websocket_socketio",
234
+ "title": "WebSocket (socket.io)",
235
+ "files": [
236
+ {
237
+ "path": "base/websockets/socket.io/javascript/index.js.ejs",
238
+ "name": "index.js.ejs",
239
+ "targetPath": "index.js"
240
+ }
241
+ ]
242
+ },
243
+ {
244
+ "id": "docker",
245
+ "title": "Docker",
246
+ "files": [
247
+ {
248
+ "path": "features/docker/base/javascript/Dockerfile.ejs",
249
+ "name": "Dockerfile.ejs",
250
+ "targetPath": "Dockerfile"
251
+ }
252
+ ]
253
+ }
254
+ ]
255
+ }
256
+ };
257
+
258
+ export const templateDocsSources = {
259
+ "base/common/,gitignore.ejs": "# Dependencies\nnode_modules/\njspm_packages/\n\n# Debug logs\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# Environment variables (CRITICAL)\n.env\n.env.local\n.env.test\n\n# Build outputs\ndist/\nbuild/\nout/\n.next/\n\n# IDEs\n.vscode/\n.idea/\n*.swp\n\n# OS files\n.DS_Store\nThumbs.db\n\n<%_ if (database === 'postgresql_prisma') { _%>\n# Prisma generated client\nsrc/generated/prisma\n<%_ } _%>\n",
260
+ "base/common/.prettierrc.ejs": "{\n \"semi\": true,\n \"singleQuote\": false,\n \"trailingComma\": \"all\"\n}\n",
261
+ "base/common/db.ejs": "<%_ if (database === 'mongo') { _%>\nimport mongoose from 'mongoose';\n\nconst connectDb = async () => {\n try {\n if (mongoose.connection.readyState >= 1) return;\n const conn = await mongoose.connect(process.env.MONGODB_URI);\n console.log(`MongoDB Connected: ${conn.connection.host}`);\n } catch (error) {\n console.error(`MongoDB Connection Error: ${error instanceof Error ? error.message : error}`);\n process.exit(1);\n }\n};\n\nexport default connectDb;\n\n<%_ } else if (database === 'postgresql_prisma') { _%>\nimport { PrismaClient } from '@prisma/client';\n\n// Singleton to prevent connection exhaustion in dev\nconst prisma = global.prisma || new PrismaClient();\n\nif (process.env.NODE_ENV !== 'production') {\n global.prisma = prisma;\n}\n\nconst connectDb = async () => {\n await prisma.$connect();\n};\n\nexport { prisma, connectDb };\nexport default prisma;\n<%_ } _%>\n",
262
+ "base/common/env.ejs": "PORT = 3000\nNODE_ENV = development\nJWT_SECRET=your-super-secret-jwt-key-change-this-in-production\nJWT_EXPIRES_IN=7d\n",
263
+ "base/common/src/middleware/asyncHandler.ejs": "export const asyncHandler = (requestHandler) => {\n return (req, res, next) => {\n Promise.resolve(requestHandler(req, res)).catch(next);\n };\n};\n",
264
+ "base/common/src/routes/health.routes.ejs": "import { Router } from \"express\";\n<%_ if (language === \"ts\") { _%>\nimport { getHealth } from \"../controllers/health.controller\";\n<%_ } else { _%>\nimport { getHealth } from \"../controllers/health.controller.js\";\n<%_ } _%>\n\nconst router = Router();\n\nrouter.get(\"/\", getHealth);\n\nexport default router;\n",
265
+ "base/common/src/routes/index.ejs": "import { Router } from \"express\";\n<%_ if (language === \"ts\") { _%>\nimport healthRoutes from \"./health.routes\";\n<%_ } else { _%>\nimport healthRoutes from \"./health.routes.js\";\n<%_ } _%>\n\nconst router = Router();\n\nrouter.use(\"/health\", healthRoutes);\n\nexport default router;\n",
266
+ "base/common/src/utils/ApiError.ejs": "class ApiError extends Error {\n constructor(statusCode, message) {\n super(message);\n this.statusCode = statusCode;\n this.success = false;\n }\n}\n\nexport default ApiError;\n",
267
+ "base/common/src/utils/logger.ejs": "import pino from \"pino\";\n<%_ if (language === \"js\") { _%>\nimport { config } from \"../config/env.js\";\n<%_ } else { _%>\nimport { config } from \"../config/env\";\n<%_ } _%>\n\nconst logger =\n config.nodeEnv === \"development\"\n ? pino(\n { level: \"debug\" },\n pino.transport({\n target: \"pino-pretty\",\n options: {\n colorize: true,\n ignore: \"pid,hostname\",\n translateTime: \"SYS:standard\",\n },\n }),\n )\n : pino({ level: \"info\" });\n\nexport { logger };\n\n\n",
268
+ "base/javascript/.prettierrc.ejs": "<%- await include(\"../common/.prettierrc.ejs\") %>\n",
269
+ "base/javascript/Readme.md.ejs": "# <%= name %>\n\nProduction-ready Node.js backend starter generated by AppInit.\n\n## Template\n<%_ if (template.includes(\"websocket\")) { _%>\n- Type: WebSocket + REST API\n- WebSocket engine: <%= websocket_package %>\n<%_ } else { _%>\n- Type: REST API\n<%_ } _%>\n- Language: JavaScript (ESM)\n<%_ if (database === \"mongo\") { _%>\n- Database: MongoDB (Mongoose)\n<%_ } else if (database === \"postgresql_prisma\") { _%>\n- Database: PostgreSQL (Prisma)\n<%_ } else { _%>\n- Database: None\n<%_ } _%>\n\n## Included Packages\n- express\n- dotenv\n- cors\n- helmet\n- jsonwebtoken\n- zod\n- pino\n- pino-http\n- pino-pretty\n<%_ if (template.includes(\"websocket\")) { _%>\n- <%= websocket_package %>\n<%_ } _%>\n<%_ if (database === \"mongo\") { _%>\n- mongoose\n<%_ } else if (database === \"postgresql_prisma\") { _%>\n- @prisma/client\n- prisma\n<%_ } _%>\n- nodemon\n- eslint\n- prettier\n\n## Boilerplate Structure\n```txt\n.\n|-- .env\n|-- .gitignore\n|-- eslint.config.js\n<%_ if (Dockerfile) { _%>\n|-- Dockerfile\n<%_ } _%>\n|-- index.js\n|-- package.json\n|-- src\n| |-- config\n| | |-- env.js\n| | `-- db.js\n| |-- controllers\n| | `-- health.controller.js\n| |-- middleware\n| | |-- asyncHandler.js\n| | `-- errorHandler.js\n| |-- routes\n| | |-- index.js\n| | `-- health.routes.js\n| `-- utils\n| |-- ApiError.js\n| `-- logger.js\n`-- Readme\n```\n\n## Quick Start\n```bash\nnpm run dev\n```\n\nServer default: `http://localhost:3000` \nHealth route: `GET /api/health`\n\n## Environment Variables\nBase variables:\n- `PORT`\n- `NODE_ENV`\n- `JWT_SECRET`\n- `JWT_EXPIRES_IN`\n<%_ if (database === \"mongo\") { _%>\n- `MONGODB_URI` (required for MongoDB)\n<%_ } else if (database === \"postgresql_prisma\") { _%>\n- `DATABASE_URL` (required for PostgreSQL + Prisma)\n<%_ } _%>\n\nUpdate `.env` before running in production.\n\n## Database Notes\n<%_ if (database === \"mongo\") { _%>\n- `src/config/db.js` includes a `connectDb` helper using Mongoose.\n- Add your Mongo connection string in `.env` as `MONGODB_URI`.\n- Call `connectDb()` during app bootstrap if your flow requires explicit DB connection startup.\n<%_ } else if (database === \"postgresql_prisma\") { _%>\n- Prisma is initialized when the project is generated.\n- Set `DATABASE_URL` in `.env`.\n- Generate/apply schema as needed:\n```bash\nnpx prisma generate\nnpx prisma migrate dev\n```\n<%_ } else { _%>\n- No database package is enabled.\n- You can add one later by installing your preferred client/ORM and updating `src/config/db.js`.\n<%_ } _%>\n\n<%_ if (template.includes(\"websocket\")) { _%>\n## WebSocket Notes\n- HTTP and WebSocket share the same server instance.\n<%_ if (websocket_package === \"socket.io\") { _%>\n- Socket.io server is configured in `index.js`.\n- Starter event flow includes a ping/pong example.\n- Use Socket.io client for browser/app connections.\n<%_ } else { _%>\n- `ws` server is configured in `index.js`.\n- Messages are expected in JSON format.\n- Starter flow includes ping handling and basic socket error/close behavior.\n<%_ } _%>\n<%_ } _%>\n\n<%_ if (Dockerfile) { _%>\n## Dockerfile\n- A Dockerfile is generated in the project root.\n- Basic usage:\n```bash\ndocker build -t <%= name %> .\ndocker run --env-file .env -p 3000:3000 <%= name %>\n```\n<%_ } _%>\n",
270
+ "base/javascript/eslint.config.js.ejs": "import js from \"@eslint/js\";\n\nexport default [\n js.configs.recommended,\n {\n files: [\"**/*.js\"],\n languageOptions: {\n ecmaVersion: 2022,\n sourceType: \"module\",\n globals: {\n console: \"readonly\",\n process: \"readonly\",\n },\n },\n rules: {\n \"no-console\": \"off\",\n \"no-unused-vars\": [\n \"warn\",\n {\n argsIgnorePattern: \"^_\",\n varsIgnorePattern: \"^_\",\n },\n ],\n },\n },\n];\n",
271
+ "base/javascript/src/config/db.js.ejs": "<%_ if (database === 'mongo') { _%>\nimport mongoose from \"mongoose\";\n\nconst connectDb = async () => {\n try {\n if (mongoose.connection.readyState >= 1) return;\n const conn = await mongoose.connect(process.env.MONGODB_URI);\n console.log(`MongoDB Connected: ${conn.connection.host}`);\n } catch (error) {\n console.error(\n `MongoDB Connection Error: ${error instanceof Error ? error.message : error}`\n );\n process.exit(1);\n }\n};\n\nexport default connectDb;\n<%_ } else if (database === 'postgresql_prisma') { _%>\nimport { PrismaClient } from \"@prisma/client\";\n\nconst prisma = global.prisma || new PrismaClient();\n\nif (process.env.NODE_ENV !== \"production\") {\n global.prisma = prisma;\n}\n\nconst connectDb = async () => {\n await prisma.$connect();\n console.log(\"PostgreSQL Connected\");\n};\n\nexport { prisma, connectDb };\nexport default prisma;\n<%_ } _%>\n",
272
+ "base/javascript/src/config/env.js.ejs": "import dotenv from \"dotenv\";\nimport { z } from \"zod\";\n\ndotenv.config();\n\nconst envSchema = z.object({\n NODE_ENV: z.enum([\"development\", \"production\", \"test\"]).default(\"development\"),\n PORT: z.coerce.number().default(3000),\n <%_ if (database === 'mongo') { _%>\n MONGODB_URI: z.string().min(1, \"MongoDB URI is required\"),\n <%_ } else if (database === 'postgresql_prisma') { _%>\n DATABASE_URL: z.string().min(1, \"Database URL is required\"),\n <%_ } _%>\n JWT_SECRET: z.string().min(1, \"JWT secret is required\"),\n JWT_EXPIRES_IN: z.string().default(\"7d\"),\n});\n\nconst parsed = envSchema.safeParse(process.env);\n\nif (!parsed.success) {\n console.error(\"Invalid environment variables:\", parsed.error.format());\n process.exit(1);\n}\n\nexport const config = {\n nodeEnv: parsed.data.NODE_ENV,\n port: parsed.data.PORT,\n <%_ if (database === 'mongo') { _%>\n mongoUri: parsed.data.MONGODB_URI,\n <%_ } else if (database === 'postgresql_prisma') { _%>\n databaseUrl: parsed.data.DATABASE_URL,\n <%_ } _%>\n jwt: {\n secret: parsed.data.JWT_SECRET,\n expiresIn: parsed.data.JWT_EXPIRES_IN,\n },\n};\n",
273
+ "base/javascript/src/controllers/health.controller.js.ejs": "import { asyncHandler } from \"../middleware/asyncHandler.js\";\n<%_ if (database === 'mongo') { _%>\nimport mongoose from \"mongoose\";\n<%_ } else if (database === 'postgresql_prisma') { _%>\nimport prisma from \"../config/db.js\";\n<%_ } _%>\n\nexport const getHealth = asyncHandler(async (req, res) => {\n const uptime = process.uptime();\n <%_ if (database === 'none') { _%>\n const dbStatus = \"disconnected\";\n const isHealthy = true;\n <%_ } else { _%>\n let dbStatus = \"disconnected\";\n\n <%_ if (database === 'mongo') { _%>\n dbStatus = mongoose.connection.readyState === 1 ? \"connected\" : \"disconnected\";\n \n <%_ } else if (database === 'postgresql_prisma') { _%>\n try {\n await prisma.$queryRaw`SELECT 1`;\n dbStatus = \"connected\";\n } catch (e) {\n dbStatus = \"error\";\n }\n <%_ } _%>\n\n const isHealthy = dbStatus === \"connected\";\n <%_ } _%>\n\n res.status(isHealthy ? 200 : 503).json({\n success: true,\n data: {\n status: \"ok\",\n timestamp: new Date().toISOString(),\n uptime: `${Math.floor(uptime)}s`,\n database: dbStatus,\n },\n });\n});\n",
274
+ "base/javascript/src/index.js.ejs": "// javascript index file\nimport express from \"express\";\nimport helmet from \"helmet\";\nimport cors from \"cors\";\nimport routes from \"./src/routes/index.js\";\nimport errorHandler from \"./src/middleware/errorHandler.js\";\nimport { logger } from \"./src/utils/logger.js\";\nimport { config } from \"./src/config/env.js\";\n\n<%_ if (database === 'postgresql_prisma') { _%>\n// Prisma note: in prisma/schema.prisma use:\n// provider = \"prisma-client-js\"\n// output = \"../generated/prisma\"\n<%_ } _%>\n\nconst app = express();\nconst port = config.port;\n\napp.use(express.json());\napp.use(helmet());\napp.use(cors());\napp.use(express.urlencoded({ extended: true }));\n\n// Call connectDb() from ./src/config/db.js to connect to your database and also update the env vars with database url\n\n// logger middleware\napp.use((req, res, next) => {\n logger.info({\n method: req.method,\n path: req.path,\n ip: req.ip,\n });\n next();\n});\n\napp.use(\"/api\", routes);\n\napp.use(errorHandler);\n\napp.listen(port, () => {\n logger.info(`Server running on port ${port}`);\n logger.info(`Environment: ${config.nodeEnv}`);\n});\n\nprocess.on(\"SIGINT\", () => {\n console.log(\"SIGINT received, forcefully stopping the server\");\n process.exit(0);\n});\nprocess.on(\"SIGTERM\", () => {\n console.log(\"SIGTERM received, gracefully stopping the server\");\n process.exit(0);\n});\n\nexport default app;\n",
275
+ "base/javascript/src/middleware/asyncHandler.js.ejs": "<%- await include(\"../../../common/src/middleware/asyncHandler.ejs\") %>\n",
276
+ "base/javascript/src/middleware/errorHandler.js.ejs": "const errorHandler = (err,req,res,next)=>{\n const statusCode = err.statusCode || 500;\n const message = err.message || \"Internal Server Error\";\n\n res.status(statusCode).json({\n success: false,\n message: message,\n });\n}\n\nexport default errorHandler;",
277
+ "base/javascript/src/routes/health.routes.js.ejs": "<%- await include(\"../../../common/src/routes/health.routes.ejs\") %>\n",
278
+ "base/javascript/src/routes/index.js.ejs": "<%_ if (database === 'postgresql_prisma') { _%>\n// Prisma note: in prisma/schema.prisma use:\n// provider = \"prisma-client-js\"\n// output = \"../generated/prisma\"\n<%_ } _%>\n\n<%- await include(\"../../../common/src/routes/index.ejs\") %>\n",
279
+ "base/javascript/src/utils/ApiError.js.ejs": "<%- await include(\"../../../common/src/utils/ApiError.ejs\") %>\n",
280
+ "base/javascript/src/utils/logger.js.ejs": "<%- await include(\"../../../common/src/utils/logger.ejs\") %>\n",
281
+ "base/typescript/.prettierrc.ejs": "<%- await include(\"../common/.prettierrc.ejs\") %>\n",
282
+ "base/typescript/Readme.md.ejs": "# <%= name %>\n\nProduction-ready Node.js backend starter generated by AppInit.\n\n## Template\n<%_ if (template.includes(\"websocket\")) { _%>\n- Type: WebSocket + REST API\n- WebSocket engine: <%= websocket_package %>\n<%_ } else { _%>\n- Type: REST API\n<%_ } _%>\n- Language: TypeScript\n<%_ if (database === \"mongo\") { _%>\n- Database: MongoDB (Mongoose)\n<%_ } else if (database === \"postgresql_prisma\") { _%>\n- Database: PostgreSQL (Prisma)\n<%_ } else { _%>\n- Database: None\n<%_ } _%>\n\n## Included Packages\n- express\n- dotenv\n- cors\n- helmet\n- jsonwebtoken\n- zod\n- pino\n- pino-http\n- pino-pretty\n<%_ if (template.includes(\"websocket\")) { _%>\n- <%= websocket_package %>\n<%_ } _%>\n<%_ if (database === \"mongo\") { _%>\n- mongoose\n<%_ } else if (database === \"postgresql_prisma\") { _%>\n- @prisma/client\n- prisma\n<%_ } _%>\n- typescript\n- ts-node\n- nodemon\n- eslint\n- prettier\n\n## Boilerplate Structure\n```txt\n.\n|-- .env\n|-- .gitignore\n|-- eslint.config.js\n<%_ if (Dockerfile) { _%>\n|-- Dockerfile\n<%_ } _%>\n|-- package.json\n|-- tsconfig.json\n|-- src\n| |-- index.ts\n| |-- config\n| | |-- env.ts\n| | `-- db.ts\n| |-- controllers\n| | `-- health.controller.ts\n| |-- middleware\n| | `-- errorHandler.ts\n| |-- routes\n| | |-- index.ts\n| | `-- health.routes.ts\n| `-- utils\n| |-- ApiError.ts\n| `-- logger.ts\n`-- Readme\n```\n\n## Quick Start\n```bash\nnpm run dev\n```\n\nServer default: `http://localhost:3000` \nHealth route: `GET /api/health`\n\n## Environment Variables\nBase variables:\n- `PORT`\n- `NODE_ENV`\n- `JWT_SECRET`\n- `JWT_EXPIRES_IN`\n<%_ if (database === \"mongo\") { _%>\n- `MONGODB_URI` (required for MongoDB)\n<%_ } else if (database === \"postgresql_prisma\") { _%>\n- `DATABASE_URL` (required for PostgreSQL + Prisma)\n<%_ } _%>\n\nUpdate `.env` before running in production.\n\n## Database Notes\n<%_ if (database === \"mongo\") { _%>\n- `src/config/db.ts` includes a `connectDb` helper using Mongoose.\n- Add your Mongo connection string in `.env` as `MONGODB_URI`.\n- Call `connectDb()` during app bootstrap if your flow requires explicit DB connection startup.\n<%_ } else if (database === \"postgresql_prisma\") { _%>\n- Prisma is initialized when the project is generated.\n- Set `DATABASE_URL` in `.env`.\n- Generate/apply schema as needed:\n```bash\nnpx prisma generate\nnpx prisma migrate dev\n```\n<%_ } else { _%>\n- No database package is enabled.\n- You can add one later by installing your preferred client/ORM and updating `src/config/db.ts`.\n<%_ } _%>\n\n<%_ if (template.includes(\"websocket\")) { _%>\n## WebSocket Notes\n- HTTP and WebSocket share the same server instance.\n<%_ if (websocket_package === \"socket.io\") { _%>\n- Socket.io server is configured in `src/index.ts`.\n- Starter event flow includes a ping/pong example.\n- Use Socket.io client for browser/app connections.\n<%_ } else { _%>\n- `ws` server is configured in `src/index.ts`.\n- Messages are expected in JSON format.\n- Starter flow includes ping handling and basic socket error/close behavior.\n<%_ } _%>\n<%_ } _%>\n\n## Scripts\n- `npm run dev`: Run in development mode with `ts-node`.\n- `npm run build`: Build TypeScript output.\n\n<%_ if (Dockerfile) { _%>\n## Dockerfile\n- A Dockerfile is generated in the project root.\n- Basic usage:\n```bash\ndocker build -t <%= name %> .\ndocker run --env-file .env -p 3000:3000 <%= name %>\n```\n<%_ } _%>\n",
283
+ "base/typescript/eslint.config.js.ejs": "import js from \"@eslint/js\";\nimport tseslint from \"typescript-eslint\";\n\nexport default tseslint.config(\n js.configs.recommended,\n ...tseslint.configs.recommended,\n {\n files: [\"**/*.ts\"],\n languageOptions: {\n ecmaVersion: 2022,\n sourceType: \"module\",\n parser: tseslint.parser,\n parserOptions: {\n project: \"./tsconfig.json\",\n },\n },\n rules: {\n \"@typescript-eslint/no-explicit-any\": \"warn\",\n \"@typescript-eslint/no-unused-vars\": [\n \"warn\",\n {\n argsIgnorePattern: \"^_\",\n varsIgnorePattern: \"^_\",\n },\n ],\n \"no-console\": \"off\",\n },\n },\n);\n",
284
+ "base/typescript/src/config/db.ts.ejs": "<%_ if (database === 'mongo') { _%>\nimport mongoose from \"mongoose\";\n\nconst connectDb = async (): Promise<void> => {\n try {\n if (mongoose.connection.readyState >= 1) return;\n const conn = await mongoose.connect(process.env.MONGODB_URI);\n console.log(`MongoDB Connected: ${conn.connection.host}`);\n } catch (error) {\n console.error(\n `MongoDB Connection Error: ${error instanceof Error ? error.message : error}`\n );\n process.exit(1);\n }\n};\n\nexport default connectDb;\n<%_ } else if (database === 'postgresql_prisma') { _%>\nimport { PrismaClient } from \"../../generated/prisma/client\";\n\ndeclare global {\n var prisma: PrismaClient | undefined;\n}\n\nconst prisma = global.prisma ?? new PrismaClient();\n\nif (process.env.NODE_ENV !== \"production\") {\n global.prisma = prisma;\n}\n\nconst connectDb = async (): Promise<void> => {\n await prisma.$connect();\n console.log(\"PostgreSQL Connected\");\n};\n\nexport { prisma, connectDb };\nexport default prisma;\n<%_ } _%>\n",
285
+ "base/typescript/src/config/env.ts.ejs": "import dotenv from \"dotenv\";\nimport { z } from \"zod\";\n\ndotenv.config();\n\nconst envSchema = z.object({\n NODE_ENV: z.enum([\"development\", \"production\", \"test\"]).default(\"development\"),\n PORT: z.coerce.number().default(3000),\n <%_ if (database === 'mongo') { _%>\n MONGODB_URI: z.string().min(1, \"MongoDB URI is required\"),\n <%_ } else if (database === 'postgresql_prisma') { _%>\n DATABASE_URL: z.string().min(1, \"Database URL is required\"),\n <%_ } _%>\n JWT_SECRET: z.string().min(1, \"JWT secret is required\"),\n JWT_EXPIRES_IN: z.string().default(\"7d\"),\n});\n\nconst parsed = envSchema.safeParse(process.env);\n\nif (!parsed.success) {\n console.error(\"Invalid environment variables:\", parsed.error.format());\n process.exit(1);\n}\n\nexport const config = {\n nodeEnv: parsed.data.NODE_ENV,\n port: parsed.data.PORT,\n <%_ if (database === 'mongo') { _%>\n mongoUri: parsed.data.MONGODB_URI,\n <%_ } else if (database === 'postgresql_prisma') { _%>\n databaseUrl: parsed.data.DATABASE_URL,\n <%_ } _%>\n jwt: {\n secret: parsed.data.JWT_SECRET,\n expiresIn: parsed.data.JWT_EXPIRES_IN,\n },\n};\n",
286
+ "base/typescript/src/controllers/health.controller.ts.ejs": "import type { Request, Response, NextFunction } from \"express\";\n<%_ if (database === 'mongo') { _%>\nimport mongoose from \"mongoose\";\n<%_ } else if (database === 'postgresql_prisma') { _%>\nimport prisma from \"../config/db\";\n<%_ } _%>\n\n/**\n * Health Check Controller\n * Checks the status of the server and the <%= database %> connection\n */\nexport const getHealth = async (_req: Request, res: Response, next: NextFunction): Promise<void> => {\n try {\n const uptime = process.uptime();\n <%_ if (database === 'none') { _%>\n const dbStatus: \"disconnected\" = \"disconnected\";\n const isHealthy = true;\n <%_ } else { _%>\n let dbStatus: \"connected\" | \"disconnected\" | \"error\" = \"disconnected\";\n\n <%_ if (database === 'mongo') { _%>\n // Check Mongoose connection state (1 = connected)\n dbStatus = mongoose.connection.readyState === 1 ? \"connected\" : \"disconnected\";\n \n <%_ } else if (database === 'postgresql_prisma') { _%>\n try {\n await prisma.$queryRaw`SELECT 1`;\n dbStatus = \"connected\";\n } catch (error) {\n dbStatus = \"error\";\n }\n <%_ } _%>\n\n const isHealthy = dbStatus === \"connected\";\n <%_ } _%>\n\n res.status(isHealthy ? 200 : 503).json({\n success: true,\n data: {\n status: \"ok\",\n timestamp: new Date().toISOString(),\n uptime: `${Math.floor(uptime)}s`,\n database: dbStatus,\n },\n });\n } catch (error) {\n // Since we removed asyncHandler, we manually pass the error to the global handler\n next(error);\n }\n};\n",
287
+ "base/typescript/src/index.ts.ejs": "// typescript index file\nimport express, { type Request, type Response, type NextFunction } from \"express\";\nimport helmet from \"helmet\";\nimport cors from \"cors\";\nimport routes from \"./routes/index\";\nimport errorHandler from \"./middleware/errorHandler\";\nimport { logger } from \"./utils/logger\";\nimport { config } from \"./config/env\";\n\n<%_ if (database === 'postgresql_prisma') { _%>\n// Prisma note: in prisma/schema.prisma use:\n// provider = \"prisma-client-js\"\n// output = \"../../generated/prisma\"\n<%_ } _%>\n\nconst app = express();\nconst port = config.port;\n\napp.use(express.json());\napp.use(helmet());\napp.use(cors());\napp.use(express.urlencoded({ extended: true }));\n\n// Call connectDb() from ./config/db to connect to your database.\n\n// logger middleware\napp.use((req: Request, res: Response, next: NextFunction) => {\n logger.info({\n ip: req.ip,\n method: req.method,\n path: req.path,\n });\n next();\n});\n\napp.use(\"/api\", routes);\n\napp.use(errorHandler);\n\napp.listen(port, () => {\n logger.info(`Server running on port ${port}`);\n logger.info(`Environment: ${config.nodeEnv}`);\n});\n\nprocess.on(\"SIGINT\", () => {\n console.log(\"SIGINT received, forcefully stopping the server\");\n process.exit(0);\n});\nprocess.on(\"SIGTERM\", () => {\n console.log(\"SIGTERM received, gracefully stopping the server\");\n process.exit(0);\n});\n\nexport default app;\n",
288
+ "base/typescript/src/middleware/errorHandler.ts.ejs": "import type { NextFunction, Request, Response } from \"express\";\nimport ApiError from \"../utils/ApiError\";\n\ntype ErrorWithStatus = ApiError | (Error & { statusCode?: number });\n\nconst errorHandler = (\n err: ErrorWithStatus,\n _req: Request,\n res: Response,\n _next: NextFunction,\n) => {\n const statusCode = err.statusCode || 500;\n const message = err.message || \"Internal Server Error\";\n\n res.status(statusCode).json({\n success: false,\n message: message,\n });\n};\nexport default errorHandler;\n",
289
+ "base/typescript/src/routes/health.routes.ts.ejs": "<%- await include(\"../../../common/src/routes/health.routes.ejs\") %>\n",
290
+ "base/typescript/src/routes/index.ts.ejs": "<%_ if (database === 'postgresql_prisma') { _%>\n// Prisma note: in prisma/schema.prisma use:\n// provider = \"prisma-client-js\"\n// output = \"../generated/prisma\"\n<%_ } _%>\n\n<%- await include(\"../../../common/src/routes/index.ejs\") %>\n",
291
+ "base/typescript/src/utils/ApiError.ts.ejs": "class ApiError extends Error {\n statusCode: number;\n success: boolean;\n\n constructor(statusCode: number, message: string) {\n super(message);\n this.statusCode = statusCode;\n this.success = false;\n }\n}\n\nexport default ApiError;\n",
292
+ "base/typescript/src/utils/logger.ts.ejs": "<%- await include(\"../../../common/src/utils/logger.ejs\") %>\n",
293
+ "base/websockets/socket.io/javascript/index.js.ejs": "import express from \"express\";\nimport helmet from \"helmet\";\nimport cors from \"cors\";\nimport { createServer } from \"http\";\nimport { Server } from \"socket.io\";\nimport routes from \"./src/routes/index.js\";\nimport errorHandler from \"./src/middleware/errorHandler.js\";\nimport { logger } from \"./src/utils/logger.js\";\nimport { config } from \"./src/config/env.js\";\n\n<%_ if (database === 'postgresql_prisma') { _%>\n// Prisma note: in prisma/schema.prisma use:\n// provider = \"prisma-client-js\"\n// output = \"../generated/prisma\"\n<%_ } _%>\n\nconst app = express();\nconst port = config.port;\n\n// 1. Create the HTTP Server\nconst http_server = createServer(app);\n\n// 2. Initialize Socket.io on the HTTP Server\nconst socket_io_server = new Server(http_server, {\n cors: {\n origin: \"*\", \n }\n});\n\n// Middleware\napp.use(express.json());\napp.use(helmet());\napp.use(cors());\napp.use(express.urlencoded({ extended: true }));\n\napp.use((req, res, next) => {\n logger.info({\n method: req.method,\n path: req.path,\n ip: req.ip,\n });\n next();\n});\n\n// Routes\napp.use(\"/api\", routes);\napp.use(errorHandler);\n\n// 3. Socket.io Event Handling\nsocket_io_server.on(\"connection\", (socket) => {\n console.log(`Client connected: ${socket.id}`);\n\n // 'data' is already an object here—no JSON.parse needed\n socket.on(\"message\", (data) => {\n if (data.type === \"ping\") {\n // No JSON.stringify needed\n socket.send({ type: \"pong\" });\n }\n });\n\n socket.on(\"disconnect\", () => {\n console.log(`Client disconnected: ${socket.id}`);\n });\n\n socket.on(\"error\", (err) => {\n console.error(\"Socket Error:\", err);\n });\n});\n\n// 4. Start the server using http_server\nhttp_server.listen(port, () => {\n logger.info(`Server running on port ${port}`);\n logger.info(`Environment: ${config.nodeEnv}`);\n});\n\n// Graceful Shutdown\nconst shutdown = () => {\n console.log(\"Stopping server...\");\n http_server.close(() => {\n process.exit(0);\n });\n};\n\nprocess.on(\"SIGINT\", shutdown);\nprocess.on(\"SIGTERM\", shutdown);\n\nexport default http_server;\n",
294
+ "base/websockets/socket.io/typescript/index.ts.ejs": "// typescript index file with a socket.io server\nimport express, { type Request, type Response, type NextFunction } from \"express\";\nimport helmet from \"helmet\";\nimport cors from \"cors\";\nimport routes from \"./routes/index\";\nimport errorHandler from \"./middleware/errorHandler\";\nimport { logger } from \"./utils/logger\";\nimport { config } from \"./config/env\";\nimport { createServer } from \"http\";\nimport { Server } from \"socket.io\";\n\n<%_ if (database === 'postgresql_prisma') { _%>\n// Prisma note: in prisma/schema.prisma use:\n// provider = \"prisma-client-js\"\n// output = \"../generated/prisma\"\n<%_ } _%>\n\nconst app = express();\nconst port = config.port;\nconst http_server = createServer(app);\nconst socket_io_server = new Server(http_server, {\n cors: {\n origin: \"*\", \n }\n});\n\napp.use(express.json());\napp.use(helmet());\napp.use(cors());\napp.use(express.urlencoded({ extended: true }));\n\n// logger middleware\napp.use((req: Request, res: Response, next: NextFunction) => {\n logger.info({\n ip: req.ip,\n method: req.method,\n path: req.path,\n });\n next();\n});\n\napp.use(\"/api\", routes);\n\napp.use(errorHandler);\n\nhttp_server.listen(port, () => {\n logger.info(`Server running on port ${port}`);\n logger.info(`Environment: ${config.nodeEnv}`);\n});\n\nsocket_io_server.on(\"connection\", (socket) => {\n logger.info(`Client connected: ${socket.id}`);\n\n // Socket.io auto-parses incoming JSON into an object\n socket.on(\"message\", (data) => {\n if (data.type === \"ping\") {\n // Socket.io auto-stringifies outgoing objects\n socket.emit(\"message\", { type: \"pong\" });\n }\n });\n\n socket.on(\"error\", (err) => {\n logger.error(`Socket error: ${err.message}`);\n });\n\n socket.on(\"disconnect\", (reason) => {\n logger.info(`Client disconnected: ${socket.id} (Reason: ${reason})`);\n });\n});\n\nprocess.on(\"SIGINT\", () => {\n console.log(\"SIGINT received, forcefully stopping the server\");\n process.exit(0);\n});\nprocess.on(\"SIGTERM\", () => {\n console.log(\"SIGTERM received, gracefully stopping the server\");\n process.exit(0);\n});\n\n\nexport default http_server;\n",
295
+ "base/websockets/ws/javascript/index.js.ejs": "// javascript index file with WebSocketServer\nimport express from \"express\";\nimport helmet from \"helmet\";\nimport cors from \"cors\";\nimport router from \"./src/routes/index.js\";\nimport errorHandler from \"./src/middleware/errorHandler.js\";\nimport { logger } from \"./src/utils/logger.js\";\nimport { config } from \"./src/config/env.js\";\nimport { createServer } from \"http\";\nimport { WebSocketServer } from \"ws\";\n\n<%_ if (database === 'postgresql_prisma') { _%>\n// Prisma note: in prisma/schema.prisma use:\n// provider = \"prisma-client-js\"\n// output = \"../generated/prisma\"\n<%_ } _%>\n\nconst app = express();\nconst port = config.port;\nconst http_server = createServer(app);\nconst wss = new WebSocketServer({ server: http_server });\n\napp.use(express.json());\napp.use(helmet());\napp.use(cors());\napp.use(express.urlencoded({ extended: true }));\n// Call connectDb() from ./src/config/db.js to connect to your database and also update the env vars with database url\n\n// logger middleware\napp.use((req, res, next) => {\n logger.info({\n method: req.method,\n path: req.path,\n ip: req.ip,\n });\n next();\n});\n\napp.use(\"/api\", router);\n\napp.use(errorHandler);\n\nhttp_server.listen(port, () => {\n logger.info(`Server running on port ${port}`);\n logger.info(`Environment: ${config.nodeEnv}`);\n});\n\nprocess.on(\"SIGINT\", () => {\n console.log(\"SIGINT received, forcefully stopping the server\");\n process.exit(0);\n});\nprocess.on(\"SIGTERM\", () => {\n console.log(\"SIGTERM received, gracefully stopping the server\");\n process.exit(0);\n});\n\nwss.on(\"connection\", (socket) => {\n socket.on(\"message\", (data) => {\n const message = data.toString();\n try {\n const msg = JSON.parse(message);\n if (msg.type === \"ping\") {\n socket.send(\n JSON.stringify({\n type: \"Pong\",\n }),\n );\n return;\n }\n } catch (error) {\n socket.send(\n JSON.stringify({\n type: \"error\",\n message:\n \"incorrect format for sending message, Only use Json for messages\",\n }),\n );\n socket.close();\n return;\n }\n });\n socket.on(\"error\", console.error);\n socket.on(\"close\", () => console.log(`client disconnected`));\n});\n\nexport default http_server;\n",
296
+ "base/websockets/ws/typescript/index.ts.ejs": "// typescript index file with a websocket server\nimport express, { type Request, type Response, type NextFunction } from \"express\";\nimport helmet from \"helmet\";\nimport cors from \"cors\";\nimport routes from \"./routes/index\";\nimport errorHandler from \"./middleware/errorHandler\";\nimport { logger } from \"./utils/logger\";\nimport { config } from \"./config/env\";\nimport { createServer } from \"http\";\nimport { WebSocketServer } from \"ws\";\n\n<%_ if (database === 'postgresql_prisma') { _%>\n// Prisma note: in prisma/schema.prisma use:\n// provider = \"prisma-client-js\"\n// output = \"../generated/prisma\"\n<%_ } _%>\n\nconst app = express();\nconst port = config.port;\nconst http_server = createServer(app);\nconst wss = new WebSocketServer({ server: http_server });\napp.use(express.json());\napp.use(helmet());\napp.use(cors());\napp.use(express.urlencoded({ extended: true }));\n\n// logger middleware\napp.use((req: Request, res: Response, next: NextFunction) => {\n logger.info({\n ip: req.ip,\n method: req.method,\n path: req.path,\n });\n next();\n});\n\napp.use(\"/api\", routes);\n\napp.use(errorHandler);\n\nhttp_server.listen(port, () => {\n logger.info(`Server running on port ${port}`);\n logger.info(`Environment: ${config.nodeEnv}`);\n});\n\nwss.on(\"connection\", (socket) => {\n console.log(\"Client connected\");\n // Basic Error Handling for the socket\n socket.on(\"error\", console.error);\n socket.on(\"message\", (message: string) => {\n try {\n const msg = JSON.parse(message);\n if (msg.type === \"ping\") {\n socket.send(\n JSON.stringify({\n type: \"pong\",\n }),\n );\n return; \n }\n } catch (error) {\n socket.send(\n JSON.stringify({\n type: \"error\",\n message:\n \"Incorrect format for sending message, Only use Json_Format for sending messages\",\n }),\n );\n socket.close();\n console.log(error);\n }\n });\n socket.on(\"close\", () => {\n console.log(\"Client Disconnected\");\n });\n});\n\nprocess.on(\"SIGINT\", () => {\n console.log(\"SIGINT received, forcefully stopping the server\");\n process.exit(0);\n});\nprocess.on(\"SIGTERM\", () => {\n console.log(\"SIGTERM received, gracefully stopping the server\");\n process.exit(0);\n});\n\n\nexport default http_server;\n",
297
+ "docs.generated.mjs": "// Auto-generated by packages/templates/scripts/generate-docs.mjs\nexport const templateDocsManifest = {\n \"languages\": {\n \"typescript\": [\n {\n \"id\": \"rest_api\",\n \"title\": \"REST API\",\n \"files\": [\n {\n \"path\": \"base/typescript/.prettierrc.ejs\",\n \"name\": \".prettierrc.ejs\",\n \"targetPath\": \".prettierrc\"\n },\n {\n \"path\": \"base/typescript/eslint.config.js.ejs\",\n \"name\": \"eslint.config.js.ejs\",\n \"targetPath\": \"eslint.config.js\"\n },\n {\n \"path\": \"base/typescript/Readme.md.ejs\",\n \"name\": \"Readme.md.ejs\",\n \"targetPath\": \"Readme.md\"\n },\n {\n \"path\": \"base/typescript/src/config/db.ts.ejs\",\n \"name\": \"db.ts.ejs\",\n \"targetPath\": \"src/config/db.ts\"\n },\n {\n \"path\": \"base/typescript/src/config/env.ts.ejs\",\n \"name\": \"env.ts.ejs\",\n \"targetPath\": \"src/config/env.ts\"\n },\n {\n \"path\": \"base/typescript/src/controllers/health.controller.ts.ejs\",\n \"name\": \"health.controller.ts.ejs\",\n \"targetPath\": \"src/controllers/health.controller.ts\"\n },\n {\n \"path\": \"base/typescript/src/index.ts.ejs\",\n \"name\": \"index.ts.ejs\",\n \"targetPath\": \"src/index.ts\"\n },\n {\n \"path\": \"base/typescript/src/middleware/errorHandler.ts.ejs\",\n \"name\": \"errorHandler.ts.ejs\",\n \"targetPath\": \"src/middleware/errorHandler.ts\"\n },\n {\n \"path\": \"base/typescript/src/routes/health.routes.ts.ejs\",\n \"name\": \"health.routes.ts.ejs\",\n \"targetPath\": \"src/routes/health.routes.ts\"\n },\n {\n \"path\": \"base/typescript/src/routes/index.ts.ejs\",\n \"name\": \"index.ts.ejs\",\n \"targetPath\": \"src/routes/index.ts\"\n },\n {\n \"path\": \"base/typescript/src/utils/ApiError.ts.ejs\",\n \"name\": \"ApiError.ts.ejs\",\n \"targetPath\": \"src/utils/ApiError.ts\"\n },\n {\n \"path\": \"base/typescript/src/utils/logger.ts.ejs\",\n \"name\": \"logger.ts.ejs\",\n \"targetPath\": \"src/utils/logger.ts\"\n }\n ]\n },\n {\n \"id\": \"common\",\n \"title\": \"Common Files\",\n \"files\": [\n {\n \"path\": \"base/common/,gitignore.ejs\",\n \"name\": \",gitignore.ejs\",\n \"targetPath\": \".gitignore\"\n },\n {\n \"path\": \"base/common/env.ejs\",\n \"name\": \"env.ejs\",\n \"targetPath\": \".env\"\n }\n ]\n },\n {\n \"id\": \"websocket_ws\",\n \"title\": \"WebSocket (ws)\",\n \"files\": [\n {\n \"path\": \"base/websockets/ws/typescript/index.ts.ejs\",\n \"name\": \"index.ts.ejs\",\n \"targetPath\": \"src/index.ts\"\n }\n ]\n },\n {\n \"id\": \"websocket_socketio\",\n \"title\": \"WebSocket (socket.io)\",\n \"files\": [\n {\n \"path\": \"base/websockets/socket.io/typescript/index.ts.ejs\",\n \"name\": \"index.ts.ejs\",\n \"targetPath\": \"src/index.ts\"\n }\n ]\n },\n {\n \"id\": \"docker\",\n \"title\": \"Docker\",\n \"files\": [\n {\n \"path\": \"features/docker/base/typescript/Dockerfile.ejs\",\n \"name\": \"Dockerfile.ejs\",\n \"targetPath\": \"Dockerfile\"\n }\n ]\n }\n ],\n \"javascript\": [\n {\n \"id\": \"rest_api\",\n \"title\": \"REST API\",\n \"files\": [\n {\n \"path\": \"base/javascript/.prettierrc.ejs\",\n \"name\": \".prettierrc.ejs\",\n \"targetPath\": \".prettierrc\"\n },\n {\n \"path\": \"base/javascript/eslint.config.js.ejs\",\n \"name\": \"eslint.config.js.ejs\",\n \"targetPath\": \"eslint.config.js\"\n },\n {\n \"path\": \"base/javascript/Readme.md.ejs\",\n \"name\": \"Readme.md.ejs\",\n \"targetPath\": \"Readme.md\"\n },\n {\n \"path\": \"base/javascript/src/config/db.js.ejs\",\n \"name\": \"db.js.ejs\",\n \"targetPath\": \"src/config/db.js\"\n },\n {\n \"path\": \"base/javascript/src/config/env.js.ejs\",\n \"name\": \"env.js.ejs\",\n \"targetPath\": \"src/config/env.js\"\n },\n {\n \"path\": \"base/javascript/src/controllers/health.controller.js.ejs\",\n \"name\": \"health.controller.js.ejs\",\n \"targetPath\": \"src/controllers/health.controller.js\"\n },\n {\n \"path\": \"base/javascript/src/index.js.ejs\",\n \"name\": \"index.js.ejs\",\n \"targetPath\": \"index.js\"\n },\n {\n \"path\": \"base/javascript/src/middleware/asyncHandler.js.ejs\",\n \"name\": \"asyncHandler.js.ejs\",\n \"targetPath\": \"src/middleware/asyncHandler.js\"\n },\n {\n \"path\": \"base/javascript/src/middleware/errorHandler.js.ejs\",\n \"name\": \"errorHandler.js.ejs\",\n \"targetPath\": \"src/middleware/errorHandler.js\"\n },\n {\n \"path\": \"base/javascript/src/routes/health.routes.js.ejs\",\n \"name\": \"health.routes.js.ejs\",\n \"targetPath\": \"src/routes/health.routes.js\"\n },\n {\n \"path\": \"base/javascript/src/routes/index.js.ejs\",\n \"name\": \"index.js.ejs\",\n \"targetPath\": \"src/routes/index.js\"\n },\n {\n \"path\": \"base/javascript/src/utils/ApiError.js.ejs\",\n \"name\": \"ApiError.js.ejs\",\n \"targetPath\": \"src/utils/ApiError.js\"\n },\n {\n \"path\": \"base/javascript/src/utils/logger.js.ejs\",\n \"name\": \"logger.js.ejs\",\n \"targetPath\": \"src/utils/logger.js\"\n }\n ]\n },\n {\n \"id\": \"common\",\n \"title\": \"Common Files\",\n \"files\": [\n {\n \"path\": \"base/common/,gitignore.ejs\",\n \"name\": \",gitignore.ejs\",\n \"targetPath\": \".gitignore\"\n },\n {\n \"path\": \"base/common/env.ejs\",\n \"name\": \"env.ejs\",\n \"targetPath\": \".env\"\n }\n ]\n },\n {\n \"id\": \"websocket_ws\",\n \"title\": \"WebSocket (ws)\",\n \"files\": [\n {\n \"path\": \"base/websockets/ws/javascript/index.js.ejs\",\n \"name\": \"index.js.ejs\",\n \"targetPath\": \"index.js\"\n }\n ]\n },\n {\n \"id\": \"websocket_socketio\",\n \"title\": \"WebSocket (socket.io)\",\n \"files\": [\n {\n \"path\": \"base/websockets/socket.io/javascript/index.js.ejs\",\n \"name\": \"index.js.ejs\",\n \"targetPath\": \"index.js\"\n }\n ]\n },\n {\n \"id\": \"docker\",\n \"title\": \"Docker\",\n \"files\": [\n {\n \"path\": \"features/docker/base/javascript/Dockerfile.ejs\",\n \"name\": \"Dockerfile.ejs\",\n \"targetPath\": \"Dockerfile\"\n }\n ]\n }\n ]\n }\n};\n\nexport const templateDocsSources = {\n \"base/common/,gitignore.ejs\": \"# Dependencies\\nnode_modules/\\njspm_packages/\\n\\n# Debug logs\\nnpm-debug.log*\\nyarn-debug.log*\\nyarn-error.log*\\n\\n# Environment variables (CRITICAL)\\n.env\\n.env.local\\n.env.test\\n\\n# Build outputs\\ndist/\\nbuild/\\nout/\\n.next/\\n\\n# IDEs\\n.vscode/\\n.idea/\\n*.swp\\n\\n# OS files\\n.DS_Store\\nThumbs.db\\n\\n<%_ if (database === 'postgresql_prisma') { _%>\\n# Prisma generated client\\nsrc/generated/prisma\\n<%_ } _%>\\n\",\n \"base/common/.prettierrc.ejs\": \"{\\n \\\"semi\\\": true,\\n \\\"singleQuote\\\": false,\\n \\\"trailingComma\\\": \\\"all\\\"\\n}\\n\",\n \"base/common/db.ejs\": \"<%_ if (database === 'mongo') { _%>\\nimport mongoose from 'mongoose';\\n\\nconst connectDb = async () => {\\n try {\\n if (mongoose.connection.readyState >= 1) return;\\n const conn = await mongoose.connect(process.env.MONGODB_URI);\\n console.log(`MongoDB Connected: ${conn.connection.host}`);\\n } catch (error) {\\n console.error(`MongoDB Connection Error: ${error instanceof Error ? error.message : error}`);\\n process.exit(1);\\n }\\n};\\n\\nexport default connectDb;\\n\\n<%_ } else if (database === 'postgresql_prisma') { _%>\\nimport { PrismaClient } from '@prisma/client';\\n\\n// Singleton to prevent connection exhaustion in dev\\nconst prisma = global.prisma || new PrismaClient();\\n\\nif (process.env.NODE_ENV !== 'production') {\\n global.prisma = prisma;\\n}\\n\\nconst connectDb = async () => {\\n await prisma.$connect();\\n};\\n\\nexport { prisma, connectDb };\\nexport default prisma;\\n<%_ } _%>\\n\",\n \"base/common/env.ejs\": \"PORT = 3000\\nNODE_ENV = development\\nJWT_SECRET=your-super-secret-jwt-key-change-this-in-production\\nJWT_EXPIRES_IN=7d\\n\",\n \"base/common/src/middleware/asyncHandler.ejs\": \"export const asyncHandler = (requestHandler) => {\\n return (req, res, next) => {\\n Promise.resolve(requestHandler(req, res)).catch(next);\\n };\\n};\\n\",\n \"base/common/src/routes/health.routes.ejs\": \"import { Router } from \\\"express\\\";\\n<%_ if (language === \\\"ts\\\") { _%>\\nimport { getHealth } from \\\"../controllers/health.controller\\\";\\n<%_ } else { _%>\\nimport { getHealth } from \\\"../controllers/health.controller.js\\\";\\n<%_ } _%>\\n\\nconst router = Router();\\n\\nrouter.get(\\\"/\\\", getHealth);\\n\\nexport default router;\\n\",\n \"base/common/src/routes/index.ejs\": \"import { Router } from \\\"express\\\";\\n<%_ if (language === \\\"ts\\\") { _%>\\nimport healthRoutes from \\\"./health.routes\\\";\\n<%_ } else { _%>\\nimport healthRoutes from \\\"./health.routes.js\\\";\\n<%_ } _%>\\n\\nconst router = Router();\\n\\nrouter.use(\\\"/health\\\", healthRoutes);\\n\\nexport default router;\\n\",\n \"base/common/src/utils/ApiError.ejs\": \"class ApiError extends Error {\\n constructor(statusCode, message) {\\n super(message);\\n this.statusCode = statusCode;\\n this.success = false;\\n }\\n}\\n\\nexport default ApiError;\\n\",\n \"base/common/src/utils/logger.ejs\": \"import pino from \\\"pino\\\";\\n<%_ if (language === \\\"js\\\") { _%>\\nimport { config } from \\\"../config/env.js\\\";\\n<%_ } else { _%>\\nimport { config } from \\\"../config/env\\\";\\n<%_ } _%>\\n\\nconst logger =\\n config.nodeEnv === \\\"development\\\"\\n ? pino(\\n { level: \\\"debug\\\" },\\n pino.transport({\\n target: \\\"pino-pretty\\\",\\n options: {\\n colorize: true,\\n ignore: \\\"pid,hostname\\\",\\n translateTime: \\\"SYS:standard\\\",\\n },\\n }),\\n )\\n : pino({ level: \\\"info\\\" });\\n\\nexport { logger };\\n\\n\\n\",\n \"base/javascript/.prettierrc.ejs\": \"<%- await include(\\\"../common/.prettierrc.ejs\\\") %>\\n\",\n \"base/javascript/Readme.md.ejs\": \"# <%= name %>\\n\\nProduction-ready Node.js backend starter generated by AppInit.\\n\\n## Template\\n<%_ if (template.includes(\\\"websocket\\\")) { _%>\\n- Type: WebSocket + REST API\\n- WebSocket engine: <%= websocket_package %>\\n<%_ } else { _%>\\n- Type: REST API\\n<%_ } _%>\\n- Language: JavaScript (ESM)\\n<%_ if (database === \\\"mongo\\\") { _%>\\n- Database: MongoDB (Mongoose)\\n<%_ } else if (database === \\\"postgresql_prisma\\\") { _%>\\n- Database: PostgreSQL (Prisma)\\n<%_ } else { _%>\\n- Database: None\\n<%_ } _%>\\n\\n## Included Packages\\n- express\\n- dotenv\\n- cors\\n- helmet\\n- jsonwebtoken\\n- zod\\n- pino\\n- pino-http\\n- pino-pretty\\n<%_ if (template.includes(\\\"websocket\\\")) { _%>\\n- <%= websocket_package %>\\n<%_ } _%>\\n<%_ if (database === \\\"mongo\\\") { _%>\\n- mongoose\\n<%_ } else if (database === \\\"postgresql_prisma\\\") { _%>\\n- @prisma/client\\n- prisma\\n<%_ } _%>\\n- nodemon\\n- eslint\\n- prettier\\n\\n## Boilerplate Structure\\n```txt\\n.\\n|-- .env\\n|-- .gitignore\\n|-- eslint.config.js\\n<%_ if (Dockerfile) { _%>\\n|-- Dockerfile\\n<%_ } _%>\\n|-- index.js\\n|-- package.json\\n|-- src\\n| |-- config\\n| | |-- env.js\\n| | `-- db.js\\n| |-- controllers\\n| | `-- health.controller.js\\n| |-- middleware\\n| | |-- asyncHandler.js\\n| | `-- errorHandler.js\\n| |-- routes\\n| | |-- index.js\\n| | `-- health.routes.js\\n| `-- utils\\n| |-- ApiError.js\\n| `-- logger.js\\n`-- Readme\\n```\\n\\n## Quick Start\\n```bash\\nnpm run dev\\n```\\n\\nServer default: `http://localhost:3000` \\nHealth route: `GET /api/health`\\n\\n## Environment Variables\\nBase variables:\\n- `PORT`\\n- `NODE_ENV`\\n- `JWT_SECRET`\\n- `JWT_EXPIRES_IN`\\n<%_ if (database === \\\"mongo\\\") { _%>\\n- `MONGODB_URI` (required for MongoDB)\\n<%_ } else if (database === \\\"postgresql_prisma\\\") { _%>\\n- `DATABASE_URL` (required for PostgreSQL + Prisma)\\n<%_ } _%>\\n\\nUpdate `.env` before running in production.\\n\\n## Database Notes\\n<%_ if (database === \\\"mongo\\\") { _%>\\n- `src/config/db.js` includes a `connectDb` helper using Mongoose.\\n- Add your Mongo connection string in `.env` as `MONGODB_URI`.\\n- Call `connectDb()` during app bootstrap if your flow requires explicit DB connection startup.\\n<%_ } else if (database === \\\"postgresql_prisma\\\") { _%>\\n- Prisma is initialized when the project is generated.\\n- Set `DATABASE_URL` in `.env`.\\n- Generate/apply schema as needed:\\n```bash\\nnpx prisma generate\\nnpx prisma migrate dev\\n```\\n<%_ } else { _%>\\n- No database package is enabled.\\n- You can add one later by installing your preferred client/ORM and updating `src/config/db.js`.\\n<%_ } _%>\\n\\n<%_ if (template.includes(\\\"websocket\\\")) { _%>\\n## WebSocket Notes\\n- HTTP and WebSocket share the same server instance.\\n<%_ if (websocket_package === \\\"socket.io\\\") { _%>\\n- Socket.io server is configured in `index.js`.\\n- Starter event flow includes a ping/pong example.\\n- Use Socket.io client for browser/app connections.\\n<%_ } else { _%>\\n- `ws` server is configured in `index.js`.\\n- Messages are expected in JSON format.\\n- Starter flow includes ping handling and basic socket error/close behavior.\\n<%_ } _%>\\n<%_ } _%>\\n\\n<%_ if (Dockerfile) { _%>\\n## Dockerfile\\n- A Dockerfile is generated in the project root.\\n- Basic usage:\\n```bash\\ndocker build -t <%= name %> .\\ndocker run --env-file .env -p 3000:3000 <%= name %>\\n```\\n<%_ } _%>\\n\",\n \"base/javascript/eslint.config.js.ejs\": \"import js from \\\"@eslint/js\\\";\\n\\nexport default [\\n js.configs.recommended,\\n {\\n files: [\\\"**/*.js\\\"],\\n languageOptions: {\\n ecmaVersion: 2022,\\n sourceType: \\\"module\\\",\\n globals: {\\n console: \\\"readonly\\\",\\n process: \\\"readonly\\\",\\n },\\n },\\n rules: {\\n \\\"no-console\\\": \\\"off\\\",\\n \\\"no-unused-vars\\\": [\\n \\\"warn\\\",\\n {\\n argsIgnorePattern: \\\"^_\\\",\\n varsIgnorePattern: \\\"^_\\\",\\n },\\n ],\\n },\\n },\\n];\\n\",\n \"base/javascript/src/config/db.js.ejs\": \"<%_ if (database === 'mongo') { _%>\\nimport mongoose from \\\"mongoose\\\";\\n\\nconst connectDb = async () => {\\n try {\\n if (mongoose.connection.readyState >= 1) return;\\n const conn = await mongoose.connect(process.env.MONGODB_URI);\\n console.log(`MongoDB Connected: ${conn.connection.host}`);\\n } catch (error) {\\n console.error(\\n `MongoDB Connection Error: ${error instanceof Error ? error.message : error}`\\n );\\n process.exit(1);\\n }\\n};\\n\\nexport default connectDb;\\n<%_ } else if (database === 'postgresql_prisma') { _%>\\nimport { PrismaClient } from \\\"@prisma/client\\\";\\n\\nconst prisma = global.prisma || new PrismaClient();\\n\\nif (process.env.NODE_ENV !== \\\"production\\\") {\\n global.prisma = prisma;\\n}\\n\\nconst connectDb = async () => {\\n await prisma.$connect();\\n console.log(\\\"PostgreSQL Connected\\\");\\n};\\n\\nexport { prisma, connectDb };\\nexport default prisma;\\n<%_ } _%>\\n\",\n \"base/javascript/src/config/env.js.ejs\": \"import dotenv from \\\"dotenv\\\";\\nimport { z } from \\\"zod\\\";\\n\\ndotenv.config();\\n\\nconst envSchema = z.object({\\n NODE_ENV: z.enum([\\\"development\\\", \\\"production\\\", \\\"test\\\"]).default(\\\"development\\\"),\\n PORT: z.coerce.number().default(3000),\\n <%_ if (database === 'mongo') { _%>\\n MONGODB_URI: z.string().min(1, \\\"MongoDB URI is required\\\"),\\n <%_ } else if (database === 'postgresql_prisma') { _%>\\n DATABASE_URL: z.string().min(1, \\\"Database URL is required\\\"),\\n <%_ } _%>\\n JWT_SECRET: z.string().min(1, \\\"JWT secret is required\\\"),\\n JWT_EXPIRES_IN: z.string().default(\\\"7d\\\"),\\n});\\n\\nconst parsed = envSchema.safeParse(process.env);\\n\\nif (!parsed.success) {\\n console.error(\\\"Invalid environment variables:\\\", parsed.error.format());\\n process.exit(1);\\n}\\n\\nexport const config = {\\n nodeEnv: parsed.data.NODE_ENV,\\n port: parsed.data.PORT,\\n <%_ if (database === 'mongo') { _%>\\n mongoUri: parsed.data.MONGODB_URI,\\n <%_ } else if (database === 'postgresql_prisma') { _%>\\n databaseUrl: parsed.data.DATABASE_URL,\\n <%_ } _%>\\n jwt: {\\n secret: parsed.data.JWT_SECRET,\\n expiresIn: parsed.data.JWT_EXPIRES_IN,\\n },\\n};\\n\",\n \"base/javascript/src/controllers/health.controller.js.ejs\": \"import { asyncHandler } from \\\"../middleware/asyncHandler.js\\\";\\n<%_ if (database === 'mongo') { _%>\\nimport mongoose from \\\"mongoose\\\";\\n<%_ } else if (database === 'postgresql_prisma') { _%>\\nimport prisma from \\\"../config/db.js\\\";\\n<%_ } _%>\\n\\nexport const getHealth = asyncHandler(async (req, res) => {\\n const uptime = process.uptime();\\n <%_ if (database === 'none') { _%>\\n const dbStatus = \\\"disconnected\\\";\\n const isHealthy = true;\\n <%_ } else { _%>\\n let dbStatus = \\\"disconnected\\\";\\n\\n <%_ if (database === 'mongo') { _%>\\n dbStatus = mongoose.connection.readyState === 1 ? \\\"connected\\\" : \\\"disconnected\\\";\\n \\n <%_ } else if (database === 'postgresql_prisma') { _%>\\n try {\\n await prisma.$queryRaw`SELECT 1`;\\n dbStatus = \\\"connected\\\";\\n } catch (e) {\\n dbStatus = \\\"error\\\";\\n }\\n <%_ } _%>\\n\\n const isHealthy = dbStatus === \\\"connected\\\";\\n <%_ } _%>\\n\\n res.status(isHealthy ? 200 : 503).json({\\n success: true,\\n data: {\\n status: \\\"ok\\\",\\n timestamp: new Date().toISOString(),\\n uptime: `${Math.floor(uptime)}s`,\\n database: dbStatus,\\n },\\n });\\n});\\n\",\n \"base/javascript/src/index.js.ejs\": \"// javascript index file\\nimport express from \\\"express\\\";\\nimport helmet from \\\"helmet\\\";\\nimport cors from \\\"cors\\\";\\nimport routes from \\\"./src/routes/index.js\\\";\\nimport errorHandler from \\\"./src/middleware/errorHandler.js\\\";\\nimport { logger } from \\\"./src/utils/logger.js\\\";\\nimport { config } from \\\"./src/config/env.js\\\";\\n\\n<%_ if (database === 'postgresql_prisma') { _%>\\n// Prisma note: in prisma/schema.prisma use:\\n// provider = \\\"prisma-client-js\\\"\\n// output = \\\"../generated/prisma\\\"\\n<%_ } _%>\\n\\nconst app = express();\\nconst port = config.port;\\n\\napp.use(express.json());\\napp.use(helmet());\\napp.use(cors());\\napp.use(express.urlencoded({ extended: true }));\\n\\n// Call connectDb() from ./src/config/db.js to connect to your database and also update the env vars with database url\\n\\n// logger middleware\\napp.use((req, res, next) => {\\n logger.info({\\n method: req.method,\\n path: req.path,\\n ip: req.ip,\\n });\\n next();\\n});\\n\\napp.use(\\\"/api\\\", routes);\\n\\napp.use(errorHandler);\\n\\napp.listen(port, () => {\\n logger.info(`Server running on port ${port}`);\\n logger.info(`Environment: ${config.nodeEnv}`);\\n});\\n\\nprocess.on(\\\"SIGINT\\\", () => {\\n console.log(\\\"SIGINT received, forcefully stopping the server\\\");\\n process.exit(0);\\n});\\nprocess.on(\\\"SIGTERM\\\", () => {\\n console.log(\\\"SIGTERM received, gracefully stopping the server\\\");\\n process.exit(0);\\n});\\n\\nexport default app;\\n\",\n \"base/javascript/src/middleware/asyncHandler.js.ejs\": \"<%- await include(\\\"../../../common/src/middleware/asyncHandler.ejs\\\") %>\\n\",\n \"base/javascript/src/middleware/errorHandler.js.ejs\": \"const errorHandler = (err,req,res,next)=>{\\n const statusCode = err.statusCode || 500;\\n const message = err.message || \\\"Internal Server Error\\\";\\n\\n res.status(statusCode).json({\\n success: false,\\n message: message,\\n });\\n}\\n\\nexport default errorHandler;\",\n \"base/javascript/src/routes/health.routes.js.ejs\": \"<%- await include(\\\"../../../common/src/routes/health.routes.ejs\\\") %>\\n\",\n \"base/javascript/src/routes/index.js.ejs\": \"<%_ if (database === 'postgresql_prisma') { _%>\\n// Prisma note: in prisma/schema.prisma use:\\n// provider = \\\"prisma-client-js\\\"\\n// output = \\\"../generated/prisma\\\"\\n<%_ } _%>\\n\\n<%- await include(\\\"../../../common/src/routes/index.ejs\\\") %>\\n\",\n \"base/javascript/src/utils/ApiError.js.ejs\": \"<%- await include(\\\"../../../common/src/utils/ApiError.ejs\\\") %>\\n\",\n \"base/javascript/src/utils/logger.js.ejs\": \"<%- await include(\\\"../../../common/src/utils/logger.ejs\\\") %>\\n\",\n \"base/typescript/.prettierrc.ejs\": \"<%- await include(\\\"../common/.prettierrc.ejs\\\") %>\\n\",\n \"base/typescript/Readme.md.ejs\": \"# <%= name %>\\n\\nProduction-ready Node.js backend starter generated by AppInit.\\n\\n## Template\\n<%_ if (template.includes(\\\"websocket\\\")) { _%>\\n- Type: WebSocket + REST API\\n- WebSocket engine: <%= websocket_package %>\\n<%_ } else { _%>\\n- Type: REST API\\n<%_ } _%>\\n- Language: TypeScript\\n<%_ if (database === \\\"mongo\\\") { _%>\\n- Database: MongoDB (Mongoose)\\n<%_ } else if (database === \\\"postgresql_prisma\\\") { _%>\\n- Database: PostgreSQL (Prisma)\\n<%_ } else { _%>\\n- Database: None\\n<%_ } _%>\\n\\n## Included Packages\\n- express\\n- dotenv\\n- cors\\n- helmet\\n- jsonwebtoken\\n- zod\\n- pino\\n- pino-http\\n- pino-pretty\\n<%_ if (template.includes(\\\"websocket\\\")) { _%>\\n- <%= websocket_package %>\\n<%_ } _%>\\n<%_ if (database === \\\"mongo\\\") { _%>\\n- mongoose\\n<%_ } else if (database === \\\"postgresql_prisma\\\") { _%>\\n- @prisma/client\\n- prisma\\n<%_ } _%>\\n- typescript\\n- ts-node\\n- nodemon\\n- eslint\\n- prettier\\n\\n## Boilerplate Structure\\n```txt\\n.\\n|-- .env\\n|-- .gitignore\\n|-- eslint.config.js\\n<%_ if (Dockerfile) { _%>\\n|-- Dockerfile\\n<%_ } _%>\\n|-- package.json\\n|-- tsconfig.json\\n|-- src\\n| |-- index.ts\\n| |-- config\\n| | |-- env.ts\\n| | `-- db.ts\\n| |-- controllers\\n| | `-- health.controller.ts\\n| |-- middleware\\n| | `-- errorHandler.ts\\n| |-- routes\\n| | |-- index.ts\\n| | `-- health.routes.ts\\n| `-- utils\\n| |-- ApiError.ts\\n| `-- logger.ts\\n`-- Readme\\n```\\n\\n## Quick Start\\n```bash\\nnpm run dev\\n```\\n\\nServer default: `http://localhost:3000` \\nHealth route: `GET /api/health`\\n\\n## Environment Variables\\nBase variables:\\n- `PORT`\\n- `NODE_ENV`\\n- `JWT_SECRET`\\n- `JWT_EXPIRES_IN`\\n<%_ if (database === \\\"mongo\\\") { _%>\\n- `MONGODB_URI` (required for MongoDB)\\n<%_ } else if (database === \\\"postgresql_prisma\\\") { _%>\\n- `DATABASE_URL` (required for PostgreSQL + Prisma)\\n<%_ } _%>\\n\\nUpdate `.env` before running in production.\\n\\n## Database Notes\\n<%_ if (database === \\\"mongo\\\") { _%>\\n- `src/config/db.ts` includes a `connectDb` helper using Mongoose.\\n- Add your Mongo connection string in `.env` as `MONGODB_URI`.\\n- Call `connectDb()` during app bootstrap if your flow requires explicit DB connection startup.\\n<%_ } else if (database === \\\"postgresql_prisma\\\") { _%>\\n- Prisma is initialized when the project is generated.\\n- Set `DATABASE_URL` in `.env`.\\n- Generate/apply schema as needed:\\n```bash\\nnpx prisma generate\\nnpx prisma migrate dev\\n```\\n<%_ } else { _%>\\n- No database package is enabled.\\n- You can add one later by installing your preferred client/ORM and updating `src/config/db.ts`.\\n<%_ } _%>\\n\\n<%_ if (template.includes(\\\"websocket\\\")) { _%>\\n## WebSocket Notes\\n- HTTP and WebSocket share the same server instance.\\n<%_ if (websocket_package === \\\"socket.io\\\") { _%>\\n- Socket.io server is configured in `src/index.ts`.\\n- Starter event flow includes a ping/pong example.\\n- Use Socket.io client for browser/app connections.\\n<%_ } else { _%>\\n- `ws` server is configured in `src/index.ts`.\\n- Messages are expected in JSON format.\\n- Starter flow includes ping handling and basic socket error/close behavior.\\n<%_ } _%>\\n<%_ } _%>\\n\\n## Scripts\\n- `npm run dev`: Run in development mode with `ts-node`.\\n- `npm run build`: Build TypeScript output.\\n\\n<%_ if (Dockerfile) { _%>\\n## Dockerfile\\n- A Dockerfile is generated in the project root.\\n- Basic usage:\\n```bash\\ndocker build -t <%= name %> .\\ndocker run --env-file .env -p 3000:3000 <%= name %>\\n```\\n<%_ } _%>\\n\",\n \"base/typescript/eslint.config.js.ejs\": \"import js from \\\"@eslint/js\\\";\\nimport tseslint from \\\"typescript-eslint\\\";\\n\\nexport default tseslint.config(\\n js.configs.recommended,\\n ...tseslint.configs.recommended,\\n {\\n files: [\\\"**/*.ts\\\"],\\n languageOptions: {\\n ecmaVersion: 2022,\\n sourceType: \\\"module\\\",\\n parser: tseslint.parser,\\n parserOptions: {\\n project: \\\"./tsconfig.json\\\",\\n },\\n },\\n rules: {\\n \\\"@typescript-eslint/no-explicit-any\\\": \\\"warn\\\",\\n \\\"@typescript-eslint/no-unused-vars\\\": [\\n \\\"warn\\\",\\n {\\n argsIgnorePattern: \\\"^_\\\",\\n varsIgnorePattern: \\\"^_\\\",\\n },\\n ],\\n \\\"no-console\\\": \\\"off\\\",\\n },\\n },\\n);\\n\",\n \"base/typescript/src/config/db.ts.ejs\": \"<%_ if (database === 'mongo') { _%>\\nimport mongoose from \\\"mongoose\\\";\\n\\nconst connectDb = async (): Promise<void> => {\\n try {\\n if (mongoose.connection.readyState >= 1) return;\\n const conn = await mongoose.connect(process.env.MONGODB_URI);\\n console.log(`MongoDB Connected: ${conn.connection.host}`);\\n } catch (error) {\\n console.error(\\n `MongoDB Connection Error: ${error instanceof Error ? error.message : error}`\\n );\\n process.exit(1);\\n }\\n};\\n\\nexport default connectDb;\\n<%_ } else if (database === 'postgresql_prisma') { _%>\\nimport { PrismaClient } from \\\"../../generated/prisma/client\\\";\\n\\ndeclare global {\\n var prisma: PrismaClient | undefined;\\n}\\n\\nconst prisma = global.prisma ?? new PrismaClient();\\n\\nif (process.env.NODE_ENV !== \\\"production\\\") {\\n global.prisma = prisma;\\n}\\n\\nconst connectDb = async (): Promise<void> => {\\n await prisma.$connect();\\n console.log(\\\"PostgreSQL Connected\\\");\\n};\\n\\nexport { prisma, connectDb };\\nexport default prisma;\\n<%_ } _%>\\n\",\n \"base/typescript/src/config/env.ts.ejs\": \"import dotenv from \\\"dotenv\\\";\\nimport { z } from \\\"zod\\\";\\n\\ndotenv.config();\\n\\nconst envSchema = z.object({\\n NODE_ENV: z.enum([\\\"development\\\", \\\"production\\\", \\\"test\\\"]).default(\\\"development\\\"),\\n PORT: z.coerce.number().default(3000),\\n <%_ if (database === 'mongo') { _%>\\n MONGODB_URI: z.string().min(1, \\\"MongoDB URI is required\\\"),\\n <%_ } else if (database === 'postgresql_prisma') { _%>\\n DATABASE_URL: z.string().min(1, \\\"Database URL is required\\\"),\\n <%_ } _%>\\n JWT_SECRET: z.string().min(1, \\\"JWT secret is required\\\"),\\n JWT_EXPIRES_IN: z.string().default(\\\"7d\\\"),\\n});\\n\\nconst parsed = envSchema.safeParse(process.env);\\n\\nif (!parsed.success) {\\n console.error(\\\"Invalid environment variables:\\\", parsed.error.format());\\n process.exit(1);\\n}\\n\\nexport const config = {\\n nodeEnv: parsed.data.NODE_ENV,\\n port: parsed.data.PORT,\\n <%_ if (database === 'mongo') { _%>\\n mongoUri: parsed.data.MONGODB_URI,\\n <%_ } else if (database === 'postgresql_prisma') { _%>\\n databaseUrl: parsed.data.DATABASE_URL,\\n <%_ } _%>\\n jwt: {\\n secret: parsed.data.JWT_SECRET,\\n expiresIn: parsed.data.JWT_EXPIRES_IN,\\n },\\n};\\n\",\n \"base/typescript/src/controllers/health.controller.ts.ejs\": \"import type { Request, Response, NextFunction } from \\\"express\\\";\\n<%_ if (database === 'mongo') { _%>\\nimport mongoose from \\\"mongoose\\\";\\n<%_ } else if (database === 'postgresql_prisma') { _%>\\nimport prisma from \\\"../config/db\\\";\\n<%_ } _%>\\n\\n/**\\n * Health Check Controller\\n * Checks the status of the server and the <%= database %> connection\\n */\\nexport const getHealth = async (_req: Request, res: Response, next: NextFunction): Promise<void> => {\\n try {\\n const uptime = process.uptime();\\n <%_ if (database === 'none') { _%>\\n const dbStatus: \\\"disconnected\\\" = \\\"disconnected\\\";\\n const isHealthy = true;\\n <%_ } else { _%>\\n let dbStatus: \\\"connected\\\" | \\\"disconnected\\\" | \\\"error\\\" = \\\"disconnected\\\";\\n\\n <%_ if (database === 'mongo') { _%>\\n // Check Mongoose connection state (1 = connected)\\n dbStatus = mongoose.connection.readyState === 1 ? \\\"connected\\\" : \\\"disconnected\\\";\\n \\n <%_ } else if (database === 'postgresql_prisma') { _%>\\n try {\\n await prisma.$queryRaw`SELECT 1`;\\n dbStatus = \\\"connected\\\";\\n } catch (error) {\\n dbStatus = \\\"error\\\";\\n }\\n <%_ } _%>\\n\\n const isHealthy = dbStatus === \\\"connected\\\";\\n <%_ } _%>\\n\\n res.status(isHealthy ? 200 : 503).json({\\n success: true,\\n data: {\\n status: \\\"ok\\\",\\n timestamp: new Date().toISOString(),\\n uptime: `${Math.floor(uptime)}s`,\\n database: dbStatus,\\n },\\n });\\n } catch (error) {\\n // Since we removed asyncHandler, we manually pass the error to the global handler\\n next(error);\\n }\\n};\\n\",\n \"base/typescript/src/index.ts.ejs\": \"// typescript index file\\nimport express, { type Request, type Response, type NextFunction } from \\\"express\\\";\\nimport helmet from \\\"helmet\\\";\\nimport cors from \\\"cors\\\";\\nimport routes from \\\"./routes/index\\\";\\nimport errorHandler from \\\"./middleware/errorHandler\\\";\\nimport { logger } from \\\"./utils/logger\\\";\\nimport { config } from \\\"./config/env\\\";\\n\\n<%_ if (database === 'postgresql_prisma') { _%>\\n// Prisma note: in prisma/schema.prisma use:\\n// provider = \\\"prisma-client-js\\\"\\n// output = \\\"../../generated/prisma\\\"\\n<%_ } _%>\\n\\nconst app = express();\\nconst port = config.port;\\n\\napp.use(express.json());\\napp.use(helmet());\\napp.use(cors());\\napp.use(express.urlencoded({ extended: true }));\\n\\n// Call connectDb() from ./config/db to connect to your database.\\n\\n// logger middleware\\napp.use((req: Request, res: Response, next: NextFunction) => {\\n logger.info({\\n ip: req.ip,\\n method: req.method,\\n path: req.path,\\n });\\n next();\\n});\\n\\napp.use(\\\"/api\\\", routes);\\n\\napp.use(errorHandler);\\n\\napp.listen(port, () => {\\n logger.info(`Server running on port ${port}`);\\n logger.info(`Environment: ${config.nodeEnv}`);\\n});\\n\\nprocess.on(\\\"SIGINT\\\", () => {\\n console.log(\\\"SIGINT received, forcefully stopping the server\\\");\\n process.exit(0);\\n});\\nprocess.on(\\\"SIGTERM\\\", () => {\\n console.log(\\\"SIGTERM received, gracefully stopping the server\\\");\\n process.exit(0);\\n});\\n\\nexport default app;\\n\",\n \"base/typescript/src/middleware/errorHandler.ts.ejs\": \"import type { NextFunction, Request, Response } from \\\"express\\\";\\nimport ApiError from \\\"../utils/ApiError\\\";\\n\\ntype ErrorWithStatus = ApiError | (Error & { statusCode?: number });\\n\\nconst errorHandler = (\\n err: ErrorWithStatus,\\n _req: Request,\\n res: Response,\\n _next: NextFunction,\\n) => {\\n const statusCode = err.statusCode || 500;\\n const message = err.message || \\\"Internal Server Error\\\";\\n\\n res.status(statusCode).json({\\n success: false,\\n message: message,\\n });\\n};\\nexport default errorHandler;\\n\",\n \"base/typescript/src/routes/health.routes.ts.ejs\": \"<%- await include(\\\"../../../common/src/routes/health.routes.ejs\\\") %>\\n\",\n \"base/typescript/src/routes/index.ts.ejs\": \"<%_ if (database === 'postgresql_prisma') { _%>\\n// Prisma note: in prisma/schema.prisma use:\\n// provider = \\\"prisma-client-js\\\"\\n// output = \\\"../generated/prisma\\\"\\n<%_ } _%>\\n\\n<%- await include(\\\"../../../common/src/routes/index.ejs\\\") %>\\n\",\n \"base/typescript/src/utils/ApiError.ts.ejs\": \"class ApiError extends Error {\\n statusCode: number;\\n success: boolean;\\n\\n constructor(statusCode: number, message: string) {\\n super(message);\\n this.statusCode = statusCode;\\n this.success = false;\\n }\\n}\\n\\nexport default ApiError;\\n\",\n \"base/typescript/src/utils/logger.ts.ejs\": \"<%- await include(\\\"../../../common/src/utils/logger.ejs\\\") %>\\n\",\n \"base/websockets/socket.io/javascript/index.js.ejs\": \"import express from \\\"express\\\";\\nimport helmet from \\\"helmet\\\";\\nimport cors from \\\"cors\\\";\\nimport { createServer } from \\\"http\\\";\\nimport { Server } from \\\"socket.io\\\";\\nimport routes from \\\"./src/routes/index.js\\\";\\nimport errorHandler from \\\"./src/middleware/errorHandler.js\\\";\\nimport { logger } from \\\"./src/utils/logger.js\\\";\\nimport { config } from \\\"./src/config/env.js\\\";\\n\\n<%_ if (database === 'postgresql_prisma') { _%>\\n// Prisma note: in prisma/schema.prisma use:\\n// provider = \\\"prisma-client-js\\\"\\n// output = \\\"../generated/prisma\\\"\\n<%_ } _%>\\n\\nconst app = express();\\nconst port = config.port;\\n\\n// 1. Create the HTTP Server\\nconst http_server = createServer(app);\\n\\n// 2. Initialize Socket.io on the HTTP Server\\nconst socket_io_server = new Server(http_server, {\\n cors: {\\n origin: \\\"*\\\", \\n }\\n});\\n\\n// Middleware\\napp.use(express.json());\\napp.use(helmet());\\napp.use(cors());\\napp.use(express.urlencoded({ extended: true }));\\n\\napp.use((req, res, next) => {\\n logger.info({\\n method: req.method,\\n path: req.path,\\n ip: req.ip,\\n });\\n next();\\n});\\n\\n// Routes\\napp.use(\\\"/api\\\", routes);\\napp.use(errorHandler);\\n\\n// 3. Socket.io Event Handling\\nsocket_io_server.on(\\\"connection\\\", (socket) => {\\n console.log(`Client connected: ${socket.id}`);\\n\\n // 'data' is already an object here—no JSON.parse needed\\n socket.on(\\\"message\\\", (data) => {\\n if (data.type === \\\"ping\\\") {\\n // No JSON.stringify needed\\n socket.send({ type: \\\"pong\\\" });\\n }\\n });\\n\\n socket.on(\\\"disconnect\\\", () => {\\n console.log(`Client disconnected: ${socket.id}`);\\n });\\n\\n socket.on(\\\"error\\\", (err) => {\\n console.error(\\\"Socket Error:\\\", err);\\n });\\n});\\n\\n// 4. Start the server using http_server\\nhttp_server.listen(port, () => {\\n logger.info(`Server running on port ${port}`);\\n logger.info(`Environment: ${config.nodeEnv}`);\\n});\\n\\n// Graceful Shutdown\\nconst shutdown = () => {\\n console.log(\\\"Stopping server...\\\");\\n http_server.close(() => {\\n process.exit(0);\\n });\\n};\\n\\nprocess.on(\\\"SIGINT\\\", shutdown);\\nprocess.on(\\\"SIGTERM\\\", shutdown);\\n\\nexport default http_server;\\n\",\n \"base/websockets/socket.io/typescript/index.ts.ejs\": \"// typescript index file with a socket.io server\\nimport express, { type Request, type Response, type NextFunction } from \\\"express\\\";\\nimport helmet from \\\"helmet\\\";\\nimport cors from \\\"cors\\\";\\nimport routes from \\\"./routes/index\\\";\\nimport errorHandler from \\\"./middleware/errorHandler\\\";\\nimport { logger } from \\\"./utils/logger\\\";\\nimport { config } from \\\"./config/env\\\";\\nimport { createServer } from \\\"http\\\";\\nimport { Server } from \\\"socket.io\\\";\\n\\n<%_ if (database === 'postgresql_prisma') { _%>\\n// Prisma note: in prisma/schema.prisma use:\\n// provider = \\\"prisma-client-js\\\"\\n// output = \\\"../generated/prisma\\\"\\n<%_ } _%>\\n\\nconst app = express();\\nconst port = config.port;\\nconst http_server = createServer(app);\\nconst socket_io_server = new Server(http_server, {\\n cors: {\\n origin: \\\"*\\\", \\n }\\n});\\n\\napp.use(express.json());\\napp.use(helmet());\\napp.use(cors());\\napp.use(express.urlencoded({ extended: true }));\\n\\n// logger middleware\\napp.use((req: Request, res: Response, next: NextFunction) => {\\n logger.info({\\n ip: req.ip,\\n method: req.method,\\n path: req.path,\\n });\\n next();\\n});\\n\\napp.use(\\\"/api\\\", routes);\\n\\napp.use(errorHandler);\\n\\nhttp_server.listen(port, () => {\\n logger.info(`Server running on port ${port}`);\\n logger.info(`Environment: ${config.nodeEnv}`);\\n});\\n\\nsocket_io_server.on(\\\"connection\\\", (socket) => {\\n logger.info(`Client connected: ${socket.id}`);\\n\\n // Socket.io auto-parses incoming JSON into an object\\n socket.on(\\\"message\\\", (data) => {\\n if (data.type === \\\"ping\\\") {\\n // Socket.io auto-stringifies outgoing objects\\n socket.emit(\\\"message\\\", { type: \\\"pong\\\" });\\n }\\n });\\n\\n socket.on(\\\"error\\\", (err) => {\\n logger.error(`Socket error: ${err.message}`);\\n });\\n\\n socket.on(\\\"disconnect\\\", (reason) => {\\n logger.info(`Client disconnected: ${socket.id} (Reason: ${reason})`);\\n });\\n});\\n\\nprocess.on(\\\"SIGINT\\\", () => {\\n console.log(\\\"SIGINT received, forcefully stopping the server\\\");\\n process.exit(0);\\n});\\nprocess.on(\\\"SIGTERM\\\", () => {\\n console.log(\\\"SIGTERM received, gracefully stopping the server\\\");\\n process.exit(0);\\n});\\n\\n\\nexport default http_server;\\n\",\n \"base/websockets/ws/javascript/index.js.ejs\": \"// javascript index file with WebSocketServer\\nimport express from \\\"express\\\";\\nimport helmet from \\\"helmet\\\";\\nimport cors from \\\"cors\\\";\\nimport router from \\\"./src/routes/index.js\\\";\\nimport errorHandler from \\\"./src/middleware/errorHandler.js\\\";\\nimport { logger } from \\\"./src/utils/logger.js\\\";\\nimport { config } from \\\"./src/config/env.js\\\";\\nimport { createServer } from \\\"http\\\";\\nimport { WebSocketServer } from \\\"ws\\\";\\n\\n<%_ if (database === 'postgresql_prisma') { _%>\\n// Prisma note: in prisma/schema.prisma use:\\n// provider = \\\"prisma-client-js\\\"\\n// output = \\\"../generated/prisma\\\"\\n<%_ } _%>\\n\\nconst app = express();\\nconst port = config.port;\\nconst http_server = createServer(app);\\nconst wss = new WebSocketServer({ server: http_server });\\n\\napp.use(express.json());\\napp.use(helmet());\\napp.use(cors());\\napp.use(express.urlencoded({ extended: true }));\\n// Call connectDb() from ./src/config/db.js to connect to your database and also update the env vars with database url\\n\\n// logger middleware\\napp.use((req, res, next) => {\\n logger.info({\\n method: req.method,\\n path: req.path,\\n ip: req.ip,\\n });\\n next();\\n});\\n\\napp.use(\\\"/api\\\", router);\\n\\napp.use(errorHandler);\\n\\nhttp_server.listen(port, () => {\\n logger.info(`Server running on port ${port}`);\\n logger.info(`Environment: ${config.nodeEnv}`);\\n});\\n\\nprocess.on(\\\"SIGINT\\\", () => {\\n console.log(\\\"SIGINT received, forcefully stopping the server\\\");\\n process.exit(0);\\n});\\nprocess.on(\\\"SIGTERM\\\", () => {\\n console.log(\\\"SIGTERM received, gracefully stopping the server\\\");\\n process.exit(0);\\n});\\n\\nwss.on(\\\"connection\\\", (socket) => {\\n socket.on(\\\"message\\\", (data) => {\\n const message = data.toString();\\n try {\\n const msg = JSON.parse(message);\\n if (msg.type === \\\"ping\\\") {\\n socket.send(\\n JSON.stringify({\\n type: \\\"Pong\\\",\\n }),\\n );\\n return;\\n }\\n } catch (error) {\\n socket.send(\\n JSON.stringify({\\n type: \\\"error\\\",\\n message:\\n \\\"incorrect format for sending message, Only use Json for messages\\\",\\n }),\\n );\\n socket.close();\\n return;\\n }\\n });\\n socket.on(\\\"error\\\", console.error);\\n socket.on(\\\"close\\\", () => console.log(`client disconnected`));\\n});\\n\\nexport default http_server;\\n\",\n \"base/websockets/ws/typescript/index.ts.ejs\": \"// typescript index file with a websocket server\\nimport express, { type Request, type Response, type NextFunction } from \\\"express\\\";\\nimport helmet from \\\"helmet\\\";\\nimport cors from \\\"cors\\\";\\nimport routes from \\\"./routes/index\\\";\\nimport errorHandler from \\\"./middleware/errorHandler\\\";\\nimport { logger } from \\\"./utils/logger\\\";\\nimport { config } from \\\"./config/env\\\";\\nimport { createServer } from \\\"http\\\";\\nimport { WebSocketServer } from \\\"ws\\\";\\n\\n<%_ if (database === 'postgresql_prisma') { _%>\\n// Prisma note: in prisma/schema.prisma use:\\n// provider = \\\"prisma-client-js\\\"\\n// output = \\\"../generated/prisma\\\"\\n<%_ } _%>\\n\\nconst app = express();\\nconst port = config.port;\\nconst http_server = createServer(app);\\nconst wss = new WebSocketServer({ server: http_server });\\napp.use(express.json());\\napp.use(helmet());\\napp.use(cors());\\napp.use(express.urlencoded({ extended: true }));\\n\\n// logger middleware\\napp.use((req: Request, res: Response, next: NextFunction) => {\\n logger.info({\\n ip: req.ip,\\n method: req.method,\\n path: req.path,\\n });\\n next();\\n});\\n\\napp.use(\\\"/api\\\", routes);\\n\\napp.use(errorHandler);\\n\\nhttp_server.listen(port, () => {\\n logger.info(`Server running on port ${port}`);\\n logger.info(`Environment: ${config.nodeEnv}`);\\n});\\n\\nwss.on(\\\"connection\\\", (socket) => {\\n console.log(\\\"Client connected\\\");\\n // Basic Error Handling for the socket\\n socket.on(\\\"error\\\", console.error);\\n socket.on(\\\"message\\\", (message: string) => {\\n try {\\n const msg = JSON.parse(message);\\n if (msg.type === \\\"ping\\\") {\\n socket.send(\\n JSON.stringify({\\n type: \\\"pong\\\",\\n }),\\n );\\n return; \\n }\\n } catch (error) {\\n socket.send(\\n JSON.stringify({\\n type: \\\"error\\\",\\n message:\\n \\\"Incorrect format for sending message, Only use Json_Format for sending messages\\\",\\n }),\\n );\\n socket.close();\\n console.log(error);\\n }\\n });\\n socket.on(\\\"close\\\", () => {\\n console.log(\\\"Client Disconnected\\\");\\n });\\n});\\n\\nprocess.on(\\\"SIGINT\\\", () => {\\n console.log(\\\"SIGINT received, forcefully stopping the server\\\");\\n process.exit(0);\\n});\\nprocess.on(\\\"SIGTERM\\\", () => {\\n console.log(\\\"SIGTERM received, gracefully stopping the server\\\");\\n process.exit(0);\\n});\\n\\n\\nexport default http_server;\\n\",\n \"docs.generated.mjs\": \"// Auto-generated by packages/templates/scripts/generate-docs.mjs\\nexport const templateDocsManifest = {\\n \\\"languages\\\": {\\n \\\"typescript\\\": [\\n {\\n \\\"id\\\": \\\"rest_api\\\",\\n \\\"title\\\": \\\"REST API\\\",\\n \\\"files\\\": [\\n {\\n \\\"path\\\": \\\"base/typescript/.prettierrc.ejs\\\",\\n \\\"name\\\": \\\".prettierrc.ejs\\\",\\n \\\"targetPath\\\": \\\"base/typescript/.prettierrc\\\"\\n },\\n {\\n \\\"path\\\": \\\"base/typescript/eslint.config.js.ejs\\\",\\n \\\"name\\\": \\\"eslint.config.js.ejs\\\",\\n \\\"targetPath\\\": \\\"base/typescript/eslint.config.js\\\"\\n },\\n {\\n \\\"path\\\": \\\"base/typescript/Readme.md.ejs\\\",\\n \\\"name\\\": \\\"Readme.md.ejs\\\",\\n \\\"targetPath\\\": \\\"base/typescript/Readme.md\\\"\\n },\\n {\\n \\\"path\\\": \\\"base/typescript/src/config/db.ts.ejs\\\",\\n \\\"name\\\": \\\"db.ts.ejs\\\",\\n \\\"targetPath\\\": \\\"base/typescript/src/config/db.ts\\\"\\n },\\n {\\n \\\"path\\\": \\\"base/typescript/src/config/env.ts.ejs\\\",\\n \\\"name\\\": \\\"env.ts.ejs\\\",\\n \\\"targetPath\\\": \\\"base/typescript/src/config/env.ts\\\"\\n },\\n {\\n \\\"path\\\": \\\"base/typescript/src/controllers/health.controller.ts.ejs\\\",\\n \\\"name\\\": \\\"health.controller.ts.ejs\\\",\\n \\\"targetPath\\\": \\\"base/typescript/src/controllers/health.controller.ts\\\"\\n },\\n {\\n \\\"path\\\": \\\"base/typescript/src/index.ts.ejs\\\",\\n \\\"name\\\": \\\"index.ts.ejs\\\",\\n \\\"targetPath\\\": \\\"base/typescript/src/index.ts\\\"\\n },\\n {\\n \\\"path\\\": \\\"base/typescript/src/middleware/errorHandler.ts.ejs\\\",\\n \\\"name\\\": \\\"errorHandler.ts.ejs\\\",\\n \\\"targetPath\\\": \\\"base/typescript/src/middleware/errorHandler.ts\\\"\\n },\\n {\\n \\\"path\\\": \\\"base/typescript/src/routes/health.routes.ts.ejs\\\",\\n \\\"name\\\": \\\"health.routes.ts.ejs\\\",\\n \\\"targetPath\\\": \\\"base/typescript/src/routes/health.routes.ts\\\"\\n },\\n {\\n \\\"path\\\": \\\"base/typescript/src/routes/index.ts.ejs\\\",\\n \\\"name\\\": \\\"index.ts.ejs\\\",\\n \\\"targetPath\\\": \\\"base/typescript/src/routes/index.ts\\\"\\n },\\n {\\n \\\"path\\\": \\\"base/typescript/src/utils/ApiError.ts.ejs\\\",\\n \\\"name\\\": \\\"ApiError.ts.ejs\\\",\\n \\\"targetPath\\\": \\\"base/typescript/src/utils/ApiError.ts\\\"\\n },\\n {\\n \\\"path\\\": \\\"base/typescript/src/utils/logger.ts.ejs\\\",\\n \\\"name\\\": \\\"logger.ts.ejs\\\",\\n \\\"targetPath\\\": \\\"base/typescript/src/utils/logger.ts\\\"\\n }\\n ]\\n },\\n {\\n \\\"id\\\": \\\"common\\\",\\n \\\"title\\\": \\\"Common Files\\\",\\n \\\"files\\\": [\\n {\\n \\\"path\\\": \\\"base/common/,gitignore.ejs\\\",\\n \\\"name\\\": \\\",gitignore.ejs\\\",\\n \\\"targetPath\\\": \\\"base/common/.gitignore.ejs\\\"\\n },\\n {\\n \\\"path\\\": \\\"base/common/.prettierrc.ejs\\\",\\n \\\"name\\\": \\\".prettierrc.ejs\\\",\\n \\\"targetPath\\\": \\\"base/common/.prettierrc\\\"\\n },\\n {\\n \\\"path\\\": \\\"base/common/db.ejs\\\",\\n \\\"name\\\": \\\"db.ejs\\\",\\n \\\"targetPath\\\": \\\"base/common/db\\\"\\n },\\n {\\n \\\"path\\\": \\\"base/common/env.ejs\\\",\\n \\\"name\\\": \\\"env.ejs\\\",\\n \\\"targetPath\\\": \\\"base/common/env\\\"\\n },\\n {\\n \\\"path\\\": \\\"base/common/src/middleware/asyncHandler.ejs\\\",\\n \\\"name\\\": \\\"asyncHandler.ejs\\\",\\n \\\"targetPath\\\": \\\"base/common/src/middleware/asyncHandler\\\"\\n },\\n {\\n \\\"path\\\": \\\"base/common/src/routes/health.routes.ejs\\\",\\n \\\"name\\\": \\\"health.routes.ejs\\\",\\n \\\"targetPath\\\": \\\"base/common/src/routes/health.routes\\\"\\n },\\n {\\n \\\"path\\\": \\\"base/common/src/routes/index.ejs\\\",\\n \\\"name\\\": \\\"index.ejs\\\",\\n \\\"targetPath\\\": \\\"base/common/src/routes/index\\\"\\n },\\n {\\n \\\"path\\\": \\\"base/common/src/utils/ApiError.ejs\\\",\\n \\\"name\\\": \\\"ApiError.ejs\\\",\\n \\\"targetPath\\\": \\\"base/common/src/utils/ApiError\\\"\\n },\\n {\\n \\\"path\\\": \\\"base/common/src/utils/logger.ejs\\\",\\n \\\"name\\\": \\\"logger.ejs\\\",\\n \\\"targetPath\\\": \\\"base/common/src/utils/logger\\\"\\n }\\n ]\\n },\\n {\\n \\\"id\\\": \\\"websocket_ws\\\",\\n \\\"title\\\": \\\"WebSocket (ws)\\\",\\n \\\"files\\\": [\\n {\\n \\\"path\\\": \\\"base/websockets/ws/typescript/index.ts.ejs\\\",\\n \\\"name\\\": \\\"index.ts.ejs\\\",\\n \\\"targetPath\\\": \\\"base/websockets/ws/typescript/index.ts\\\"\\n }\\n ]\\n },\\n {\\n \\\"id\\\": \\\"websocket_socketio\\\",\\n \\\"title\\\": \\\"WebSocket (socket.io)\\\",\\n \\\"files\\\": [\\n {\\n \\\"path\\\": \\\"base/websockets/socket.io/typescript/index.ts.ejs\\\",\\n \\\"name\\\": \\\"index.ts.ejs\\\",\\n \\\"targetPath\\\": \\\"base/websockets/socket.io/typescript/index.ts\\\"\\n }\\n ]\\n },\\n {\\n \\\"id\\\": \\\"docker\\\",\\n \\\"title\\\": \\\"Docker\\\",\\n \\\"files\\\": [\\n {\\n \\\"path\\\": \\\"features/docker/base/typescript/Dockerfile.ejs\\\",\\n \\\"name\\\": \\\"Dockerfile.ejs\\\",\\n \\\"targetPath\\\": \\\"features/docker/base/typescript/Dockerfile\\\"\\n }\\n ]\\n }\\n ],\\n \\\"javascript\\\": [\\n {\\n \\\"id\\\": \\\"rest_api\\\",\\n \\\"title\\\": \\\"REST API\\\",\\n \\\"files\\\": [\\n {\\n \\\"path\\\": \\\"base/javascript/.prettierrc.ejs\\\",\\n \\\"name\\\": \\\".prettierrc.ejs\\\",\\n \\\"targetPath\\\": \\\"base/javascript/.prettierrc\\\"\\n },\\n {\\n \\\"path\\\": \\\"base/javascript/eslint.config.js.ejs\\\",\\n \\\"name\\\": \\\"eslint.config.js.ejs\\\",\\n \\\"targetPath\\\": \\\"base/javascript/eslint.config.js\\\"\\n },\\n {\\n \\\"path\\\": \\\"base/javascript/Readme.md.ejs\\\",\\n \\\"name\\\": \\\"Readme.md.ejs\\\",\\n \\\"targetPath\\\": \\\"base/javascript/Readme.md\\\"\\n },\\n {\\n \\\"path\\\": \\\"base/javascript/src/config/db.js.ejs\\\",\\n \\\"name\\\": \\\"db.js.ejs\\\",\\n \\\"targetPath\\\": \\\"base/javascript/src/config/db.js\\\"\\n },\\n {\\n \\\"path\\\": \\\"base/javascript/src/config/env.js.ejs\\\",\\n \\\"name\\\": \\\"env.js.ejs\\\",\\n \\\"targetPath\\\": \\\"base/javascript/src/config/env.js\\\"\\n },\\n {\\n \\\"path\\\": \\\"base/javascript/src/controllers/health.controller.js.ejs\\\",\\n \\\"name\\\": \\\"health.controller.js.ejs\\\",\\n \\\"targetPath\\\": \\\"base/javascript/src/controllers/health.controller.js\\\"\\n },\\n {\\n \\\"path\\\": \\\"base/javascript/src/index.js.ejs\\\",\\n \\\"name\\\": \\\"index.js.ejs\\\",\\n \\\"targetPath\\\": \\\"index.js\\\"\\n },\\n {\\n \\\"path\\\": \\\"base/javascript/src/middleware/asyncHandler.js.ejs\\\",\\n \\\"name\\\": \\\"asyncHandler.js.ejs\\\",\\n \\\"targetPath\\\": \\\"base/javascript/src/middleware/asyncHandler.js\\\"\\n },\\n {\\n \\\"path\\\": \\\"base/javascript/src/middleware/errorHandler.js.ejs\\\",\\n \\\"name\\\": \\\"errorHandler.js.ejs\\\",\\n \\\"targetPath\\\": \\\"base/javascript/src/middleware/errorHandler.js\\\"\\n },\\n {\\n \\\"path\\\": \\\"base/javascript/src/routes/health.routes.js.ejs\\\",\\n \\\"name\\\": \\\"health.routes.js.ejs\\\",\\n \\\"targetPath\\\": \\\"base/javascript/src/routes/health.routes.js\\\"\\n },\\n {\\n \\\"path\\\": \\\"base/javascript/src/routes/index.js.ejs\\\",\\n \\\"name\\\": \\\"index.js.ejs\\\",\\n \\\"targetPath\\\": \\\"base/javascript/src/routes/index.js\\\"\\n },\\n {\\n \\\"path\\\": \\\"base/javascript/src/utils/ApiError.js.ejs\\\",\\n \\\"name\\\": \\\"ApiError.js.ejs\\\",\\n \\\"targetPath\\\": \\\"base/javascript/src/utils/ApiError.js\\\"\\n },\\n {\\n \\\"path\\\": \\\"base/javascript/src/utils/logger.js.ejs\\\",\\n \\\"name\\\": \\\"logger.js.ejs\\\",\\n \\\"targetPath\\\": \\\"base/javascript/src/utils/logger.js\\\"\\n }\\n ]\\n },\\n {\\n \\\"id\\\": \\\"common\\\",\\n \\\"title\\\": \\\"Common Files\\\",\\n \\\"files\\\": [\\n {\\n \\\"path\\\": \\\"base/common/,gitignore.ejs\\\",\\n \\\"name\\\": \\\",gitignore.ejs\\\",\\n \\\"targetPath\\\": \\\"base/common/.gitignore.ejs\\\"\\n },\\n {\\n \\\"path\\\": \\\"base/common/.prettierrc.ejs\\\",\\n \\\"name\\\": \\\".prettierrc.ejs\\\",\\n \\\"targetPath\\\": \\\"base/common/.prettierrc\\\"\\n },\\n {\\n \\\"path\\\": \\\"base/common/db.ejs\\\",\\n \\\"name\\\": \\\"db.ejs\\\",\\n \\\"targetPath\\\": \\\"base/common/db\\\"\\n },\\n {\\n \\\"path\\\": \\\"base/common/env.ejs\\\",\\n \\\"name\\\": \\\"env.ejs\\\",\\n \\\"targetPath\\\": \\\"base/common/env\\\"\\n },\\n {\\n \\\"path\\\": \\\"base/common/src/middleware/asyncHandler.ejs\\\",\\n \\\"name\\\": \\\"asyncHandler.ejs\\\",\\n \\\"targetPath\\\": \\\"base/common/src/middleware/asyncHandler\\\"\\n },\\n {\\n \\\"path\\\": \\\"base/common/src/routes/health.routes.ejs\\\",\\n \\\"name\\\": \\\"health.routes.ejs\\\",\\n \\\"targetPath\\\": \\\"base/common/src/routes/health.routes\\\"\\n },\\n {\\n \\\"path\\\": \\\"base/common/src/routes/index.ejs\\\",\\n \\\"name\\\": \\\"index.ejs\\\",\\n \\\"targetPath\\\": \\\"base/common/src/routes/index\\\"\\n },\\n {\\n \\\"path\\\": \\\"base/common/src/utils/ApiError.ejs\\\",\\n \\\"name\\\": \\\"ApiError.ejs\\\",\\n \\\"targetPath\\\": \\\"base/common/src/utils/ApiError\\\"\\n },\\n {\\n \\\"path\\\": \\\"base/common/src/utils/logger.ejs\\\",\\n \\\"name\\\": \\\"logger.ejs\\\",\\n \\\"targetPath\\\": \\\"base/common/src/utils/logger\\\"\\n }\\n ]\\n },\\n {\\n \\\"id\\\": \\\"websocket_ws\\\",\\n \\\"title\\\": \\\"WebSocket (ws)\\\",\\n \\\"files\\\": [\\n {\\n \\\"path\\\": \\\"base/websockets/ws/javascript/index.js.ejs\\\",\\n \\\"name\\\": \\\"index.js.ejs\\\",\\n \\\"targetPath\\\": \\\"base/websockets/ws/javascript/index.js\\\"\\n }\\n ]\\n },\\n {\\n \\\"id\\\": \\\"websocket_socketio\\\",\\n \\\"title\\\": \\\"WebSocket (socket.io)\\\",\\n \\\"files\\\": [\\n {\\n \\\"path\\\": \\\"base/websockets/socket.io/javascript/index.js.ejs\\\",\\n \\\"name\\\": \\\"index.js.ejs\\\",\\n \\\"targetPath\\\": \\\"base/websockets/socket.io/javascript/index.js\\\"\\n }\\n ]\\n },\\n {\\n \\\"id\\\": \\\"docker\\\",\\n \\\"title\\\": \\\"Docker\\\",\\n \\\"files\\\": [\\n {\\n \\\"path\\\": \\\"features/docker/base/javascript/Dockerfile.ejs\\\",\\n \\\"name\\\": \\\"Dockerfile.ejs\\\",\\n \\\"targetPath\\\": \\\"features/docker/base/javascript/Dockerfile\\\"\\n }\\n ]\\n }\\n ]\\n }\\n};\\n\\nexport const templateDocsSources = {\\n \\\"base/common/,gitignore.ejs\\\": \\\"# Dependencies\\\\nnode_modules/\\\\njspm_packages/\\\\n\\\\n# Debug logs\\\\nnpm-debug.log*\\\\nyarn-debug.log*\\\\nyarn-error.log*\\\\n\\\\n# Environment variables (CRITICAL)\\\\n.env\\\\n.env.local\\\\n.env.test\\\\n\\\\n# Build outputs\\\\ndist/\\\\nbuild/\\\\nout/\\\\n.next/\\\\n\\\\n# IDEs\\\\n.vscode/\\\\n.idea/\\\\n*.swp\\\\n\\\\n# OS files\\\\n.DS_Store\\\\nThumbs.db\\\\n\\\\n<%_ if (database === 'postgresql_prisma') { _%>\\\\n# Prisma generated client\\\\nsrc/generated/prisma\\\\n<%_ } _%>\\\\n\\\",\\n \\\"base/common/.prettierrc.ejs\\\": \\\"{\\\\n \\\\\\\"semi\\\\\\\": true,\\\\n \\\\\\\"singleQuote\\\\\\\": false,\\\\n \\\\\\\"trailingComma\\\\\\\": \\\\\\\"all\\\\\\\"\\\\n}\\\\n\\\",\\n \\\"base/common/db.ejs\\\": \\\"<%_ if (database === 'mongo') { _%>\\\\nimport mongoose from 'mongoose';\\\\n\\\\nconst connectDb = async () => {\\\\n try {\\\\n if (mongoose.connection.readyState >= 1) return;\\\\n const conn = await mongoose.connect(process.env.MONGODB_URI);\\\\n console.log(`MongoDB Connected: ${conn.connection.host}`);\\\\n } catch (error) {\\\\n console.error(`MongoDB Connection Error: ${error instanceof Error ? error.message : error}`);\\\\n process.exit(1);\\\\n }\\\\n};\\\\n\\\\nexport default connectDb;\\\\n\\\\n<%_ } else if (database === 'postgresql_prisma') { _%>\\\\nimport { PrismaClient } from '@prisma/client';\\\\n\\\\n// Singleton to prevent connection exhaustion in dev\\\\nconst prisma = global.prisma || new PrismaClient();\\\\n\\\\nif (process.env.NODE_ENV !== 'production') {\\\\n global.prisma = prisma;\\\\n}\\\\n\\\\nconst connectDb = async () => {\\\\n await prisma.$connect();\\\\n};\\\\n\\\\nexport { prisma, connectDb };\\\\nexport default prisma;\\\\n<%_ } _%>\\\\n\\\",\\n \\\"base/common/env.ejs\\\": \\\"PORT = 3000\\\\nNODE_ENV = development\\\\nJWT_SECRET=your-super-secret-jwt-key-change-this-in-production\\\\nJWT_EXPIRES_IN=7d\\\\n\\\",\\n \\\"base/common/src/middleware/asyncHandler.ejs\\\": \\\"export const asyncHandler = (requestHandler) => {\\\\n return (req, res, next) => {\\\\n Promise.resolve(requestHandler(req, res)).catch(next);\\\\n };\\\\n};\\\\n\\\",\\n \\\"base/common/src/routes/health.routes.ejs\\\": \\\"import { Router } from \\\\\\\"express\\\\\\\";\\\\n<%_ if (language === \\\\\\\"ts\\\\\\\") { _%>\\\\nimport { getHealth } from \\\\\\\"../controllers/health.controller\\\\\\\";\\\\n<%_ } else { _%>\\\\nimport { getHealth } from \\\\\\\"../controllers/health.controller.js\\\\\\\";\\\\n<%_ } _%>\\\\n\\\\nconst router = Router();\\\\n\\\\nrouter.get(\\\\\\\"/\\\\\\\", getHealth);\\\\n\\\\nexport default router;\\\\n\\\",\\n \\\"base/common/src/routes/index.ejs\\\": \\\"import { Router } from \\\\\\\"express\\\\\\\";\\\\n<%_ if (language === \\\\\\\"ts\\\\\\\") { _%>\\\\nimport healthRoutes from \\\\\\\"./health.routes\\\\\\\";\\\\n<%_ } else { _%>\\\\nimport healthRoutes from \\\\\\\"./health.routes.js\\\\\\\";\\\\n<%_ } _%>\\\\n\\\\nconst router = Router();\\\\n\\\\nrouter.use(\\\\\\\"/health\\\\\\\", healthRoutes);\\\\n\\\\nexport default router;\\\\n\\\",\\n \\\"base/common/src/utils/ApiError.ejs\\\": \\\"class ApiError extends Error {\\\\n constructor(statusCode, message) {\\\\n super(message);\\\\n this.statusCode = statusCode;\\\\n this.success = false;\\\\n }\\\\n}\\\\n\\\\nexport default ApiError;\\\\n\\\",\\n \\\"base/common/src/utils/logger.ejs\\\": \\\"import pino from \\\\\\\"pino\\\\\\\";\\\\n<%_ if (language === \\\\\\\"js\\\\\\\") { _%>\\\\nimport { config } from \\\\\\\"../config/env.js\\\\\\\";\\\\n<%_ } else { _%>\\\\nimport { config } from \\\\\\\"../config/env\\\\\\\";\\\\n<%_ } _%>\\\\n\\\\nconst logger =\\\\n config.nodeEnv === \\\\\\\"development\\\\\\\"\\\\n ? pino(\\\\n { level: \\\\\\\"debug\\\\\\\" },\\\\n pino.transport({\\\\n target: \\\\\\\"pino-pretty\\\\\\\",\\\\n options: {\\\\n colorize: true,\\\\n ignore: \\\\\\\"pid,hostname\\\\\\\",\\\\n translateTime: \\\\\\\"SYS:standard\\\\\\\",\\\\n },\\\\n }),\\\\n )\\\\n : pino({ level: \\\\\\\"info\\\\\\\" });\\\\n\\\\nexport { logger };\\\\n\\\\n\\\\n\\\",\\n \\\"base/javascript/.prettierrc.ejs\\\": \\\"<%- await include(\\\\\\\"../common/.prettierrc.ejs\\\\\\\") %>\\\\n\\\",\\n \\\"base/javascript/Readme.md.ejs\\\": \\\"# <%= name %>\\\\n\\\\nProduction-ready Node.js backend starter generated by AppInit.\\\\n\\\\n## Template\\\\n<%_ if (template.includes(\\\\\\\"websocket\\\\\\\")) { _%>\\\\n- Type: WebSocket + REST API\\\\n- WebSocket engine: <%= websocket_package %>\\\\n<%_ } else { _%>\\\\n- Type: REST API\\\\n<%_ } _%>\\\\n- Language: JavaScript (ESM)\\\\n<%_ if (database === \\\\\\\"mongo\\\\\\\") { _%>\\\\n- Database: MongoDB (Mongoose)\\\\n<%_ } else if (database === \\\\\\\"postgresql_prisma\\\\\\\") { _%>\\\\n- Database: PostgreSQL (Prisma)\\\\n<%_ } else { _%>\\\\n- Database: None\\\\n<%_ } _%>\\\\n\\\\n## Included Packages\\\\n- express\\\\n- dotenv\\\\n- cors\\\\n- helmet\\\\n- jsonwebtoken\\\\n- zod\\\\n- pino\\\\n- pino-http\\\\n- pino-pretty\\\\n<%_ if (template.includes(\\\\\\\"websocket\\\\\\\")) { _%>\\\\n- <%= websocket_package %>\\\\n<%_ } _%>\\\\n<%_ if (database === \\\\\\\"mongo\\\\\\\") { _%>\\\\n- mongoose\\\\n<%_ } else if (database === \\\\\\\"postgresql_prisma\\\\\\\") { _%>\\\\n- @prisma/client\\\\n- prisma\\\\n<%_ } _%>\\\\n- nodemon\\\\n- eslint\\\\n- prettier\\\\n\\\\n## Boilerplate Structure\\\\n```txt\\\\n.\\\\n|-- .env\\\\n|-- .gitignore\\\\n|-- eslint.config.js\\\\n<%_ if (Dockerfile) { _%>\\\\n|-- Dockerfile\\\\n<%_ } _%>\\\\n|-- index.js\\\\n|-- package.json\\\\n|-- src\\\\n| |-- config\\\\n| | |-- env.js\\\\n| | `-- db.js\\\\n| |-- controllers\\\\n| | `-- health.controller.js\\\\n| |-- middleware\\\\n| | |-- asyncHandler.js\\\\n| | `-- errorHandler.js\\\\n| |-- routes\\\\n| | |-- index.js\\\\n| | `-- health.routes.js\\\\n| `-- utils\\\\n| |-- ApiError.js\\\\n| `-- logger.js\\\\n`-- Readme\\\\n```\\\\n\\\\n## Quick Start\\\\n```bash\\\\nnpm run dev\\\\n```\\\\n\\\\nServer default: `http://localhost:3000` \\\\nHealth route: `GET /api/health`\\\\n\\\\n## Environment Variables\\\\nBase variables:\\\\n- `PORT`\\\\n- `NODE_ENV`\\\\n- `JWT_SECRET`\\\\n- `JWT_EXPIRES_IN`\\\\n<%_ if (database === \\\\\\\"mongo\\\\\\\") { _%>\\\\n- `MONGODB_URI` (required for MongoDB)\\\\n<%_ } else if (database === \\\\\\\"postgresql_prisma\\\\\\\") { _%>\\\\n- `DATABASE_URL` (required for PostgreSQL + Prisma)\\\\n<%_ } _%>\\\\n\\\\nUpdate `.env` before running in production.\\\\n\\\\n## Database Notes\\\\n<%_ if (database === \\\\\\\"mongo\\\\\\\") { _%>\\\\n- `src/config/db.js` includes a `connectDb` helper using Mongoose.\\\\n- Add your Mongo connection string in `.env` as `MONGODB_URI`.\\\\n- Call `connectDb()` during app bootstrap if your flow requires explicit DB connection startup.\\\\n<%_ } else if (database === \\\\\\\"postgresql_prisma\\\\\\\") { _%>\\\\n- Prisma is initialized when the project is generated.\\\\n- Set `DATABASE_URL` in `.env`.\\\\n- Generate/apply schema as needed:\\\\n```bash\\\\nnpx prisma generate\\\\nnpx prisma migrate dev\\\\n```\\\\n<%_ } else { _%>\\\\n- No database package is enabled.\\\\n- You can add one later by installing your preferred client/ORM and updating `src/config/db.js`.\\\\n<%_ } _%>\\\\n\\\\n<%_ if (template.includes(\\\\\\\"websocket\\\\\\\")) { _%>\\\\n## WebSocket Notes\\\\n- HTTP and WebSocket share the same server instance.\\\\n<%_ if (websocket_package === \\\\\\\"socket.io\\\\\\\") { _%>\\\\n- Socket.io server is configured in `index.js`.\\\\n- Starter event flow includes a ping/pong example.\\\\n- Use Socket.io client for browser/app connections.\\\\n<%_ } else { _%>\\\\n- `ws` server is configured in `index.js`.\\\\n- Messages are expected in JSON format.\\\\n- Starter flow includes ping handling and basic socket error/close behavior.\\\\n<%_ } _%>\\\\n<%_ } _%>\\\\n\\\\n<%_ if (Dockerfile) { _%>\\\\n## Dockerfile\\\\n- A Dockerfile is generated in the project root.\\\\n- Basic usage:\\\\n```bash\\\\ndocker build -t <%= name %> .\\\\ndocker run --env-file .env -p 3000:3000 <%= name %>\\\\n```\\\\n<%_ } _%>\\\\n\\\",\\n \\\"base/javascript/eslint.config.js.ejs\\\": \\\"import js from \\\\\\\"@eslint/js\\\\\\\";\\\\n\\\\nexport default [\\\\n js.configs.recommended,\\\\n {\\\\n files: [\\\\\\\"**/*.js\\\\\\\"],\\\\n languageOptions: {\\\\n ecmaVersion: 2022,\\\\n sourceType: \\\\\\\"module\\\\\\\",\\\\n globals: {\\\\n console: \\\\\\\"readonly\\\\\\\",\\\\n process: \\\\\\\"readonly\\\\\\\",\\\\n },\\\\n },\\\\n rules: {\\\\n \\\\\\\"no-console\\\\\\\": \\\\\\\"off\\\\\\\",\\\\n \\\\\\\"no-unused-vars\\\\\\\": [\\\\n \\\\\\\"warn\\\\\\\",\\\\n {\\\\n argsIgnorePattern: \\\\\\\"^_\\\\\\\",\\\\n varsIgnorePattern: \\\\\\\"^_\\\\\\\",\\\\n },\\\\n ],\\\\n },\\\\n },\\\\n];\\\\n\\\",\\n \\\"base/javascript/src/config/db.js.ejs\\\": \\\"<%_ if (database === 'mongo') { _%>\\\\nimport mongoose from \\\\\\\"mongoose\\\\\\\";\\\\n\\\\nconst connectDb = async () => {\\\\n try {\\\\n if (mongoose.connection.readyState >= 1) return;\\\\n const conn = await mongoose.connect(process.env.MONGODB_URI);\\\\n console.log(`MongoDB Connected: ${conn.connection.host}`);\\\\n } catch (error) {\\\\n console.error(\\\\n `MongoDB Connection Error: ${error instanceof Error ? error.message : error}`\\\\n );\\\\n process.exit(1);\\\\n }\\\\n};\\\\n\\\\nexport default connectDb;\\\\n<%_ } else if (database === 'postgresql_prisma') { _%>\\\\nimport { PrismaClient } from \\\\\\\"@prisma/client\\\\\\\";\\\\n\\\\nconst prisma = global.prisma || new PrismaClient();\\\\n\\\\nif (process.env.NODE_ENV !== \\\\\\\"production\\\\\\\") {\\\\n global.prisma = prisma;\\\\n}\\\\n\\\\nconst connectDb = async () => {\\\\n await prisma.$connect();\\\\n console.log(\\\\\\\"PostgreSQL Connected\\\\\\\");\\\\n};\\\\n\\\\nexport { prisma, connectDb };\\\\nexport default prisma;\\\\n<%_ } _%>\\\\n\\\",\\n \\\"base/javascript/src/config/env.js.ejs\\\": \\\"import dotenv from \\\\\\\"dotenv\\\\\\\";\\\\nimport { z } from \\\\\\\"zod\\\\\\\";\\\\n\\\\ndotenv.config();\\\\n\\\\nconst envSchema = z.object({\\\\n NODE_ENV: z.enum([\\\\\\\"development\\\\\\\", \\\\\\\"production\\\\\\\", \\\\\\\"test\\\\\\\"]).default(\\\\\\\"development\\\\\\\"),\\\\n PORT: z.coerce.number().default(3000),\\\\n <%_ if (database === 'mongo') { _%>\\\\n MONGODB_URI: z.string().min(1, \\\\\\\"MongoDB URI is required\\\\\\\"),\\\\n <%_ } else if (database === 'postgresql_prisma') { _%>\\\\n DATABASE_URL: z.string().min(1, \\\\\\\"Database URL is required\\\\\\\"),\\\\n <%_ } _%>\\\\n JWT_SECRET: z.string().min(1, \\\\\\\"JWT secret is required\\\\\\\"),\\\\n JWT_EXPIRES_IN: z.string().default(\\\\\\\"7d\\\\\\\"),\\\\n});\\\\n\\\\nconst parsed = envSchema.safeParse(process.env);\\\\n\\\\nif (!parsed.success) {\\\\n console.error(\\\\\\\"Invalid environment variables:\\\\\\\", parsed.error.format());\\\\n process.exit(1);\\\\n}\\\\n\\\\nexport const config = {\\\\n nodeEnv: parsed.data.NODE_ENV,\\\\n port: parsed.data.PORT,\\\\n <%_ if (database === 'mongo') { _%>\\\\n mongoUri: parsed.data.MONGODB_URI,\\\\n <%_ } else if (database === 'postgresql_prisma') { _%>\\\\n databaseUrl: parsed.data.DATABASE_URL,\\\\n <%_ } _%>\\\\n jwt: {\\\\n secret: parsed.data.JWT_SECRET,\\\\n expiresIn: parsed.data.JWT_EXPIRES_IN,\\\\n },\\\\n};\\\\n\\\",\\n \\\"base/javascript/src/controllers/health.controller.js.ejs\\\": \\\"import { asyncHandler } from \\\\\\\"../middleware/asyncHandler.js\\\\\\\";\\\\n<%_ if (database === 'mongo') { _%>\\\\nimport mongoose from \\\\\\\"mongoose\\\\\\\";\\\\n<%_ } else if (database === 'postgresql_prisma') { _%>\\\\nimport prisma from \\\\\\\"../config/db.js\\\\\\\";\\\\n<%_ } _%>\\\\n\\\\nexport const getHealth = asyncHandler(async (req, res) => {\\\\n const uptime = process.uptime();\\\\n <%_ if (database === 'none') { _%>\\\\n const dbStatus = \\\\\\\"disconnected\\\\\\\";\\\\n const isHealthy = true;\\\\n <%_ } else { _%>\\\\n let dbStatus = \\\\\\\"disconnected\\\\\\\";\\\\n\\\\n <%_ if (database === 'mongo') { _%>\\\\n dbStatus = mongoose.connection.readyState === 1 ? \\\\\\\"connected\\\\\\\" : \\\\\\\"disconnected\\\\\\\";\\\\n \\\\n <%_ } else if (database === 'postgresql_prisma') { _%>\\\\n try {\\\\n await prisma.$queryRaw`SELECT 1`;\\\\n dbStatus = \\\\\\\"connected\\\\\\\";\\\\n } catch (e) {\\\\n dbStatus = \\\\\\\"error\\\\\\\";\\\\n }\\\\n <%_ } _%>\\\\n\\\\n const isHealthy = dbStatus === \\\\\\\"connected\\\\\\\";\\\\n <%_ } _%>\\\\n\\\\n res.status(isHealthy ? 200 : 503).json({\\\\n success: true,\\\\n data: {\\\\n status: \\\\\\\"ok\\\\\\\",\\\\n timestamp: new Date().toISOString(),\\\\n uptime: `${Math.floor(uptime)}s`,\\\\n database: dbStatus,\\\\n },\\\\n });\\\\n});\\\\n\\\",\\n \\\"base/javascript/src/index.js.ejs\\\": \\\"// javascript index file\\\\nimport express from \\\\\\\"express\\\\\\\";\\\\nimport helmet from \\\\\\\"helmet\\\\\\\";\\\\nimport cors from \\\\\\\"cors\\\\\\\";\\\\nimport routes from \\\\\\\"./src/routes/index.js\\\\\\\";\\\\nimport errorHandler from \\\\\\\"./src/middleware/errorHandler.js\\\\\\\";\\\\nimport { logger } from \\\\\\\"./src/utils/logger.js\\\\\\\";\\\\nimport { config } from \\\\\\\"./src/config/env.js\\\\\\\";\\\\n\\\\n<%_ if (database === 'postgresql_prisma') { _%>\\\\n// Prisma note: in prisma/schema.prisma use:\\\\n// provider = \\\\\\\"prisma-client-js\\\\\\\"\\\\n// output = \\\\\\\"../generated/prisma\\\\\\\"\\\\n<%_ } _%>\\\\n\\\\nconst app = express();\\\\nconst port = config.port;\\\\n\\\\napp.use(express.json());\\\\napp.use(helmet());\\\\napp.use(cors());\\\\napp.use(express.urlencoded({ extended: true }));\\\\n\\\\n// Call connectDb() from ./src/config/db.js to connect to your database and also update the env vars with database url\\\\n\\\\n// logger middleware\\\\napp.use((req, res, next) => {\\\\n logger.info({\\\\n method: req.method,\\\\n path: req.path,\\\\n ip: req.ip,\\\\n });\\\\n next();\\\\n});\\\\n\\\\napp.use(\\\\\\\"/api\\\\\\\", routes);\\\\n\\\\napp.use(errorHandler);\\\\n\\\\napp.listen(port, () => {\\\\n logger.info(`Server running on port ${port}`);\\\\n logger.info(`Environment: ${config.nodeEnv}`);\\\\n});\\\\n\\\\nprocess.on(\\\\\\\"SIGINT\\\\\\\", () => {\\\\n console.log(\\\\\\\"SIGINT received, forcefully stopping the server\\\\\\\");\\\\n process.exit(0);\\\\n});\\\\nprocess.on(\\\\\\\"SIGTERM\\\\\\\", () => {\\\\n console.log(\\\\\\\"SIGTERM received, gracefully stopping the server\\\\\\\");\\\\n process.exit(0);\\\\n});\\\\n\\\\nexport default app;\\\\n\\\",\\n \\\"base/javascript/src/middleware/asyncHandler.js.ejs\\\": \\\"<%- await include(\\\\\\\"../../../common/src/middleware/asyncHandler.ejs\\\\\\\") %>\\\\n\\\",\\n \\\"base/javascript/src/middleware/errorHandler.js.ejs\\\": \\\"const errorHandler = (err,req,res,next)=>{\\\\n const statusCode = err.statusCode || 500;\\\\n const message = err.message || \\\\\\\"Internal Server Error\\\\\\\";\\\\n\\\\n res.status(statusCode).json({\\\\n success: false,\\\\n message: message,\\\\n });\\\\n}\\\\n\\\\nexport default errorHandler;\\\",\\n \\\"base/javascript/src/routes/health.routes.js.ejs\\\": \\\"<%- await include(\\\\\\\"../../../common/src/routes/health.routes.ejs\\\\\\\") %>\\\\n\\\",\\n \\\"base/javascript/src/routes/index.js.ejs\\\": \\\"<%_ if (database === 'postgresql_prisma') { _%>\\\\n// Prisma note: in prisma/schema.prisma use:\\\\n// provider = \\\\\\\"prisma-client-js\\\\\\\"\\\\n// output = \\\\\\\"../generated/prisma\\\\\\\"\\\\n<%_ } _%>\\\\n\\\\n<%- await include(\\\\\\\"../../../common/src/routes/index.ejs\\\\\\\") %>\\\\n\\\",\\n \\\"base/javascript/src/utils/ApiError.js.ejs\\\": \\\"<%- await include(\\\\\\\"../../../common/src/utils/ApiError.ejs\\\\\\\") %>\\\\n\\\",\\n \\\"base/javascript/src/utils/logger.js.ejs\\\": \\\"<%- await include(\\\\\\\"../../../common/src/utils/logger.ejs\\\\\\\") %>\\\\n\\\",\\n \\\"base/typescript/.prettierrc.ejs\\\": \\\"<%- await include(\\\\\\\"../common/.prettierrc.ejs\\\\\\\") %>\\\\n\\\",\\n \\\"base/typescript/Readme.md.ejs\\\": \\\"# <%= name %>\\\\n\\\\nProduction-ready Node.js backend starter generated by AppInit.\\\\n\\\\n## Template\\\\n<%_ if (template.includes(\\\\\\\"websocket\\\\\\\")) { _%>\\\\n- Type: WebSocket + REST API\\\\n- WebSocket engine: <%= websocket_package %>\\\\n<%_ } else { _%>\\\\n- Type: REST API\\\\n<%_ } _%>\\\\n- Language: TypeScript\\\\n<%_ if (database === \\\\\\\"mongo\\\\\\\") { _%>\\\\n- Database: MongoDB (Mongoose)\\\\n<%_ } else if (database === \\\\\\\"postgresql_prisma\\\\\\\") { _%>\\\\n- Database: PostgreSQL (Prisma)\\\\n<%_ } else { _%>\\\\n- Database: None\\\\n<%_ } _%>\\\\n\\\\n## Included Packages\\\\n- express\\\\n- dotenv\\\\n- cors\\\\n- helmet\\\\n- jsonwebtoken\\\\n- zod\\\\n- pino\\\\n- pino-http\\\\n- pino-pretty\\\\n<%_ if (template.includes(\\\\\\\"websocket\\\\\\\")) { _%>\\\\n- <%= websocket_package %>\\\\n<%_ } _%>\\\\n<%_ if (database === \\\\\\\"mongo\\\\\\\") { _%>\\\\n- mongoose\\\\n<%_ } else if (database === \\\\\\\"postgresql_prisma\\\\\\\") { _%>\\\\n- @prisma/client\\\\n- prisma\\\\n<%_ } _%>\\\\n- typescript\\\\n- ts-node\\\\n- nodemon\\\\n- eslint\\\\n- prettier\\\\n\\\\n## Boilerplate Structure\\\\n```txt\\\\n.\\\\n|-- .env\\\\n|-- .gitignore\\\\n|-- eslint.config.js\\\\n<%_ if (Dockerfile) { _%>\\\\n|-- Dockerfile\\\\n<%_ } _%>\\\\n|-- package.json\\\\n|-- tsconfig.json\\\\n|-- src\\\\n| |-- index.ts\\\\n| |-- config\\\\n| | |-- env.ts\\\\n| | `-- db.ts\\\\n| |-- controllers\\\\n| | `-- health.controller.ts\\\\n| |-- middleware\\\\n| | `-- errorHandler.ts\\\\n| |-- routes\\\\n| | |-- index.ts\\\\n| | `-- health.routes.ts\\\\n| `-- utils\\\\n| |-- ApiError.ts\\\\n| `-- logger.ts\\\\n`-- Readme\\\\n```\\\\n\\\\n## Quick Start\\\\n```bash\\\\nnpm run dev\\\\n```\\\\n\\\\nServer default: `http://localhost:3000` \\\\nHealth route: `GET /api/health`\\\\n\\\\n## Environment Variables\\\\nBase variables:\\\\n- `PORT`\\\\n- `NODE_ENV`\\\\n- `JWT_SECRET`\\\\n- `JWT_EXPIRES_IN`\\\\n<%_ if (database === \\\\\\\"mongo\\\\\\\") { _%>\\\\n- `MONGODB_URI` (required for MongoDB)\\\\n<%_ } else if (database === \\\\\\\"postgresql_prisma\\\\\\\") { _%>\\\\n- `DATABASE_URL` (required for PostgreSQL + Prisma)\\\\n<%_ } _%>\\\\n\\\\nUpdate `.env` before running in production.\\\\n\\\\n## Database Notes\\\\n<%_ if (database === \\\\\\\"mongo\\\\\\\") { _%>\\\\n- `src/config/db.ts` includes a `connectDb` helper using Mongoose.\\\\n- Add your Mongo connection string in `.env` as `MONGODB_URI`.\\\\n- Call `connectDb()` during app bootstrap if your flow requires explicit DB connection startup.\\\\n<%_ } else if (database === \\\\\\\"postgresql_prisma\\\\\\\") { _%>\\\\n- Prisma is initialized when the project is generated.\\\\n- Set `DATABASE_URL` in `.env`.\\\\n- Generate/apply schema as needed:\\\\n```bash\\\\nnpx prisma generate\\\\nnpx prisma migrate dev\\\\n```\\\\n<%_ } else { _%>\\\\n- No database package is enabled.\\\\n- You can add one later by installing your preferred client/ORM and updating `src/config/db.ts`.\\\\n<%_ } _%>\\\\n\\\\n<%_ if (template.includes(\\\\\\\"websocket\\\\\\\")) { _%>\\\\n## WebSocket Notes\\\\n- HTTP and WebSocket share the same server instance.\\\\n<%_ if (websocket_package === \\\\\\\"socket.io\\\\\\\") { _%>\\\\n- Socket.io server is configured in `src/index.ts`.\\\\n- Starter event flow includes a ping/pong example.\\\\n- Use Socket.io client for browser/app connections.\\\\n<%_ } else { _%>\\\\n- `ws` server is configured in `src/index.ts`.\\\\n- Messages are expected in JSON format.\\\\n- Starter flow includes ping handling and basic socket error/close behavior.\\\\n<%_ } _%>\\\\n<%_ } _%>\\\\n\\\\n## Scripts\\\\n- `npm run dev`: Run in development mode with `ts-node`.\\\\n- `npm run build`: Build TypeScript output.\\\\n\\\\n<%_ if (Dockerfile) { _%>\\\\n## Dockerfile\\\\n- A Dockerfile is generated in the project root.\\\\n- Basic usage:\\\\n```bash\\\\ndocker build -t <%= name %> .\\\\ndocker run --env-file .env -p 3000:3000 <%= name %>\\\\n```\\\\n<%_ } _%>\\\\n\\\",\\n \\\"base/typescript/eslint.config.js.ejs\\\": \\\"import js from \\\\\\\"@eslint/js\\\\\\\";\\\\nimport tseslint from \\\\\\\"typescript-eslint\\\\\\\";\\\\n\\\\nexport default tseslint.config(\\\\n js.configs.recommended,\\\\n ...tseslint.configs.recommended,\\\\n {\\\\n files: [\\\\\\\"**/*.ts\\\\\\\"],\\\\n languageOptions: {\\\\n ecmaVersion: 2022,\\\\n sourceType: \\\\\\\"module\\\\\\\",\\\\n parser: tseslint.parser,\\\\n parserOptions: {\\\\n project: \\\\\\\"./tsconfig.json\\\\\\\",\\\\n },\\\\n },\\\\n rules: {\\\\n \\\\\\\"@typescript-eslint/no-explicit-any\\\\\\\": \\\\\\\"warn\\\\\\\",\\\\n \\\\\\\"@typescript-eslint/no-unused-vars\\\\\\\": [\\\\n \\\\\\\"warn\\\\\\\",\\\\n {\\\\n argsIgnorePattern: \\\\\\\"^_\\\\\\\",\\\\n varsIgnorePattern: \\\\\\\"^_\\\\\\\",\\\\n },\\\\n ],\\\\n \\\\\\\"no-console\\\\\\\": \\\\\\\"off\\\\\\\",\\\\n },\\\\n },\\\\n);\\\\n\\\",\\n \\\"base/typescript/src/config/db.ts.ejs\\\": \\\"<%_ if (database === 'mongo') { _%>\\\\nimport mongoose from \\\\\\\"mongoose\\\\\\\";\\\\n\\\\nconst connectDb = async (): Promise<void> => {\\\\n try {\\\\n if (mongoose.connection.readyState >= 1) return;\\\\n const conn = await mongoose.connect(process.env.MONGODB_URI);\\\\n console.log(`MongoDB Connected: ${conn.connection.host}`);\\\\n } catch (error) {\\\\n console.error(\\\\n `MongoDB Connection Error: ${error instanceof Error ? error.message : error}`\\\\n );\\\\n process.exit(1);\\\\n }\\\\n};\\\\n\\\\nexport default connectDb;\\\\n<%_ } else if (database === 'postgresql_prisma') { _%>\\\\nimport { PrismaClient } from \\\\\\\"../../generated/prisma/client\\\\\\\";\\\\n\\\\ndeclare global {\\\\n var prisma: PrismaClient | undefined;\\\\n}\\\\n\\\\nconst prisma = global.prisma ?? new PrismaClient();\\\\n\\\\nif (process.env.NODE_ENV !== \\\\\\\"production\\\\\\\") {\\\\n global.prisma = prisma;\\\\n}\\\\n\\\\nconst connectDb = async (): Promise<void> => {\\\\n await prisma.$connect();\\\\n console.log(\\\\\\\"PostgreSQL Connected\\\\\\\");\\\\n};\\\\n\\\\nexport { prisma, connectDb };\\\\nexport default prisma;\\\\n<%_ } _%>\\\\n\\\",\\n \\\"base/typescript/src/config/env.ts.ejs\\\": \\\"import dotenv from \\\\\\\"dotenv\\\\\\\";\\\\nimport { z } from \\\\\\\"zod\\\\\\\";\\\\n\\\\ndotenv.config();\\\\n\\\\nconst envSchema = z.object({\\\\n NODE_ENV: z.enum([\\\\\\\"development\\\\\\\", \\\\\\\"production\\\\\\\", \\\\\\\"test\\\\\\\"]).default(\\\\\\\"development\\\\\\\"),\\\\n PORT: z.coerce.number().default(3000),\\\\n <%_ if (database === 'mongo') { _%>\\\\n MONGODB_URI: z.string().min(1, \\\\\\\"MongoDB URI is required\\\\\\\"),\\\\n <%_ } else if (database === 'postgresql_prisma') { _%>\\\\n DATABASE_URL: z.string().min(1, \\\\\\\"Database URL is required\\\\\\\"),\\\\n <%_ } _%>\\\\n JWT_SECRET: z.string().min(1, \\\\\\\"JWT secret is required\\\\\\\"),\\\\n JWT_EXPIRES_IN: z.string().default(\\\\\\\"7d\\\\\\\"),\\\\n});\\\\n\\\\nconst parsed = envSchema.safeParse(process.env);\\\\n\\\\nif (!parsed.success) {\\\\n console.error(\\\\\\\"Invalid environment variables:\\\\\\\", parsed.error.format());\\\\n process.exit(1);\\\\n}\\\\n\\\\nexport const config = {\\\\n nodeEnv: parsed.data.NODE_ENV,\\\\n port: parsed.data.PORT,\\\\n <%_ if (database === 'mongo') { _%>\\\\n mongoUri: parsed.data.MONGODB_URI,\\\\n <%_ } else if (database === 'postgresql_prisma') { _%>\\\\n databaseUrl: parsed.data.DATABASE_URL,\\\\n <%_ } _%>\\\\n jwt: {\\\\n secret: parsed.data.JWT_SECRET,\\\\n expiresIn: parsed.data.JWT_EXPIRES_IN,\\\\n },\\\\n};\\\\n\\\",\\n \\\"base/typescript/src/controllers/health.controller.ts.ejs\\\": \\\"import type { Request, Response, NextFunction } from \\\\\\\"express\\\\\\\";\\\\n<%_ if (database === 'mongo') { _%>\\\\nimport mongoose from \\\\\\\"mongoose\\\\\\\";\\\\n<%_ } else if (database === 'postgresql_prisma') { _%>\\\\nimport prisma from \\\\\\\"../config/db\\\\\\\";\\\\n<%_ } _%>\\\\n\\\\n/**\\\\n * Health Check Controller\\\\n * Checks the status of the server and the <%= database %> connection\\\\n */\\\\nexport const getHealth = async (_req: Request, res: Response, next: NextFunction): Promise<void> => {\\\\n try {\\\\n const uptime = process.uptime();\\\\n <%_ if (database === 'none') { _%>\\\\n const dbStatus: \\\\\\\"disconnected\\\\\\\" = \\\\\\\"disconnected\\\\\\\";\\\\n const isHealthy = true;\\\\n <%_ } else { _%>\\\\n let dbStatus: \\\\\\\"connected\\\\\\\" | \\\\\\\"disconnected\\\\\\\" | \\\\\\\"error\\\\\\\" = \\\\\\\"disconnected\\\\\\\";\\\\n\\\\n <%_ if (database === 'mongo') { _%>\\\\n // Check Mongoose connection state (1 = connected)\\\\n dbStatus = mongoose.connection.readyState === 1 ? \\\\\\\"connected\\\\\\\" : \\\\\\\"disconnected\\\\\\\";\\\\n \\\\n <%_ } else if (database === 'postgresql_prisma') { _%>\\\\n try {\\\\n await prisma.$queryRaw`SELECT 1`;\\\\n dbStatus = \\\\\\\"connected\\\\\\\";\\\\n } catch (error) {\\\\n dbStatus = \\\\\\\"error\\\\\\\";\\\\n }\\\\n <%_ } _%>\\\\n\\\\n const isHealthy = dbStatus === \\\\\\\"connected\\\\\\\";\\\\n <%_ } _%>\\\\n\\\\n res.status(isHealthy ? 200 : 503).json({\\\\n success: true,\\\\n data: {\\\\n status: \\\\\\\"ok\\\\\\\",\\\\n timestamp: new Date().toISOString(),\\\\n uptime: `${Math.floor(uptime)}s`,\\\\n database: dbStatus,\\\\n },\\\\n });\\\\n } catch (error) {\\\\n // Since we removed asyncHandler, we manually pass the error to the global handler\\\\n next(error);\\\\n }\\\\n};\\\\n\\\",\\n \\\"base/typescript/src/index.ts.ejs\\\": \\\"// typescript index file\\\\nimport express, { type Request, type Response, type NextFunction } from \\\\\\\"express\\\\\\\";\\\\nimport helmet from \\\\\\\"helmet\\\\\\\";\\\\nimport cors from \\\\\\\"cors\\\\\\\";\\\\nimport routes from \\\\\\\"./routes/index\\\\\\\";\\\\nimport errorHandler from \\\\\\\"./middleware/errorHandler\\\\\\\";\\\\nimport { logger } from \\\\\\\"./utils/logger\\\\\\\";\\\\nimport { config } from \\\\\\\"./config/env\\\\\\\";\\\\n\\\\n<%_ if (database === 'postgresql_prisma') { _%>\\\\n// Prisma note: in prisma/schema.prisma use:\\\\n// provider = \\\\\\\"prisma-client-js\\\\\\\"\\\\n// output = \\\\\\\"../../generated/prisma\\\\\\\"\\\\n<%_ } _%>\\\\n\\\\nconst app = express();\\\\nconst port = config.port;\\\\n\\\\napp.use(express.json());\\\\napp.use(helmet());\\\\napp.use(cors());\\\\napp.use(express.urlencoded({ extended: true }));\\\\n\\\\n// Call connectDb() from ./config/db to connect to your database.\\\\n\\\\n// logger middleware\\\\napp.use((req: Request, res: Response, next: NextFunction) => {\\\\n logger.info({\\\\n ip: req.ip,\\\\n method: req.method,\\\\n path: req.path,\\\\n });\\\\n next();\\\\n});\\\\n\\\\napp.use(\\\\\\\"/api\\\\\\\", routes);\\\\n\\\\napp.use(errorHandler);\\\\n\\\\napp.listen(port, () => {\\\\n logger.info(`Server running on port ${port}`);\\\\n logger.info(`Environment: ${config.nodeEnv}`);\\\\n});\\\\n\\\\nprocess.on(\\\\\\\"SIGINT\\\\\\\", () => {\\\\n console.log(\\\\\\\"SIGINT received, forcefully stopping the server\\\\\\\");\\\\n process.exit(0);\\\\n});\\\\nprocess.on(\\\\\\\"SIGTERM\\\\\\\", () => {\\\\n console.log(\\\\\\\"SIGTERM received, gracefully stopping the server\\\\\\\");\\\\n process.exit(0);\\\\n});\\\\n\\\\nexport default app;\\\\n\\\",\\n \\\"base/typescript/src/middleware/errorHandler.ts.ejs\\\": \\\"import type { NextFunction, Request, Response } from \\\\\\\"express\\\\\\\";\\\\nimport ApiError from \\\\\\\"../utils/ApiError\\\\\\\";\\\\n\\\\ntype ErrorWithStatus = ApiError | (Error & { statusCode?: number });\\\\n\\\\nconst errorHandler = (\\\\n err: ErrorWithStatus,\\\\n _req: Request,\\\\n res: Response,\\\\n _next: NextFunction,\\\\n) => {\\\\n const statusCode = err.statusCode || 500;\\\\n const message = err.message || \\\\\\\"Internal Server Error\\\\\\\";\\\\n\\\\n res.status(statusCode).json({\\\\n success: false,\\\\n message: message,\\\\n });\\\\n};\\\\nexport default errorHandler;\\\\n\\\",\\n \\\"base/typescript/src/routes/health.routes.ts.ejs\\\": \\\"<%- await include(\\\\\\\"../../../common/src/routes/health.routes.ejs\\\\\\\") %>\\\\n\\\",\\n \\\"base/typescript/src/routes/index.ts.ejs\\\": \\\"<%_ if (database === 'postgresql_prisma') { _%>\\\\n// Prisma note: in prisma/schema.prisma use:\\\\n// provider = \\\\\\\"prisma-client-js\\\\\\\"\\\\n// output = \\\\\\\"../generated/prisma\\\\\\\"\\\\n<%_ } _%>\\\\n\\\\n<%- await include(\\\\\\\"../../../common/src/routes/index.ejs\\\\\\\") %>\\\\n\\\",\\n \\\"base/typescript/src/utils/ApiError.ts.ejs\\\": \\\"class ApiError extends Error {\\\\n statusCode: number;\\\\n success: boolean;\\\\n\\\\n constructor(statusCode: number, message: string) {\\\\n super(message);\\\\n this.statusCode = statusCode;\\\\n this.success = false;\\\\n }\\\\n}\\\\n\\\\nexport default ApiError;\\\\n\\\",\\n \\\"base/typescript/src/utils/logger.ts.ejs\\\": \\\"<%- await include(\\\\\\\"../../../common/src/utils/logger.ejs\\\\\\\") %>\\\\n\\\",\\n \\\"base/websockets/socket.io/javascript/index.js.ejs\\\": \\\"import express from \\\\\\\"express\\\\\\\";\\\\nimport helmet from \\\\\\\"helmet\\\\\\\";\\\\nimport cors from \\\\\\\"cors\\\\\\\";\\\\nimport { createServer } from \\\\\\\"http\\\\\\\";\\\\nimport { Server } from \\\\\\\"socket.io\\\\\\\";\\\\nimport routes from \\\\\\\"./src/routes/index.js\\\\\\\";\\\\nimport errorHandler from \\\\\\\"./src/middleware/errorHandler.js\\\\\\\";\\\\nimport { logger } from \\\\\\\"./src/utils/logger.js\\\\\\\";\\\\nimport { config } from \\\\\\\"./src/config/env.js\\\\\\\";\\\\n\\\\n<%_ if (database === 'postgresql_prisma') { _%>\\\\n// Prisma note: in prisma/schema.prisma use:\\\\n// provider = \\\\\\\"prisma-client-js\\\\\\\"\\\\n// output = \\\\\\\"../generated/prisma\\\\\\\"\\\\n<%_ } _%>\\\\n\\\\nconst app = express();\\\\nconst port = config.port;\\\\n\\\\n// 1. Create the HTTP Server\\\\nconst http_server = createServer(app);\\\\n\\\\n// 2. Initialize Socket.io on the HTTP Server\\\\nconst socket_io_server = new Server(http_server, {\\\\n cors: {\\\\n origin: \\\\\\\"*\\\\\\\", \\\\n }\\\\n});\\\\n\\\\n// Middleware\\\\napp.use(express.json());\\\\napp.use(helmet());\\\\napp.use(cors());\\\\napp.use(express.urlencoded({ extended: true }));\\\\n\\\\napp.use((req, res, next) => {\\\\n logger.info({\\\\n method: req.method,\\\\n path: req.path,\\\\n ip: req.ip,\\\\n });\\\\n next();\\\\n});\\\\n\\\\n// Routes\\\\napp.use(\\\\\\\"/api\\\\\\\", routes);\\\\napp.use(errorHandler);\\\\n\\\\n// 3. Socket.io Event Handling\\\\nsocket_io_server.on(\\\\\\\"connection\\\\\\\", (socket) => {\\\\n console.log(`Client connected: ${socket.id}`);\\\\n\\\\n // 'data' is already an object here—no JSON.parse needed\\\\n socket.on(\\\\\\\"message\\\\\\\", (data) => {\\\\n if (data.type === \\\\\\\"ping\\\\\\\") {\\\\n // No JSON.stringify needed\\\\n socket.send({ type: \\\\\\\"pong\\\\\\\" });\\\\n }\\\\n });\\\\n\\\\n socket.on(\\\\\\\"disconnect\\\\\\\", () => {\\\\n console.log(`Client disconnected: ${socket.id}`);\\\\n });\\\\n\\\\n socket.on(\\\\\\\"error\\\\\\\", (err) => {\\\\n console.error(\\\\\\\"Socket Error:\\\\\\\", err);\\\\n });\\\\n});\\\\n\\\\n// 4. Start the server using http_server\\\\nhttp_server.listen(port, () => {\\\\n logger.info(`Server running on port ${port}`);\\\\n logger.info(`Environment: ${config.nodeEnv}`);\\\\n});\\\\n\\\\n// Graceful Shutdown\\\\nconst shutdown = () => {\\\\n console.log(\\\\\\\"Stopping server...\\\\\\\");\\\\n http_server.close(() => {\\\\n process.exit(0);\\\\n });\\\\n};\\\\n\\\\nprocess.on(\\\\\\\"SIGINT\\\\\\\", shutdown);\\\\nprocess.on(\\\\\\\"SIGTERM\\\\\\\", shutdown);\\\\n\\\\nexport default http_server;\\\\n\\\",\\n \\\"base/websockets/socket.io/typescript/index.ts.ejs\\\": \\\"// typescript index file with a socket.io server\\\\nimport express, { type Request, type Response, type NextFunction } from \\\\\\\"express\\\\\\\";\\\\nimport helmet from \\\\\\\"helmet\\\\\\\";\\\\nimport cors from \\\\\\\"cors\\\\\\\";\\\\nimport routes from \\\\\\\"./routes/index\\\\\\\";\\\\nimport errorHandler from \\\\\\\"./middleware/errorHandler\\\\\\\";\\\\nimport { logger } from \\\\\\\"./utils/logger\\\\\\\";\\\\nimport { config } from \\\\\\\"./config/env\\\\\\\";\\\\nimport { createServer } from \\\\\\\"http\\\\\\\";\\\\nimport { Server } from \\\\\\\"socket.io\\\\\\\";\\\\n\\\\n<%_ if (database === 'postgresql_prisma') { _%>\\\\n// Prisma note: in prisma/schema.prisma use:\\\\n// provider = \\\\\\\"prisma-client-js\\\\\\\"\\\\n// output = \\\\\\\"../generated/prisma\\\\\\\"\\\\n<%_ } _%>\\\\n\\\\nconst app = express();\\\\nconst port = config.port;\\\\nconst http_server = createServer(app);\\\\nconst socket_io_server = new Server(http_server, {\\\\n cors: {\\\\n origin: \\\\\\\"*\\\\\\\", \\\\n }\\\\n});\\\\n\\\\napp.use(express.json());\\\\napp.use(helmet());\\\\napp.use(cors());\\\\napp.use(express.urlencoded({ extended: true }));\\\\n\\\\n// logger middleware\\\\napp.use((req: Request, res: Response, next: NextFunction) => {\\\\n logger.info({\\\\n ip: req.ip,\\\\n method: req.method,\\\\n path: req.path,\\\\n });\\\\n next();\\\\n});\\\\n\\\\napp.use(\\\\\\\"/api\\\\\\\", routes);\\\\n\\\\napp.use(errorHandler);\\\\n\\\\nhttp_server.listen(port, () => {\\\\n logger.info(`Server running on port ${port}`);\\\\n logger.info(`Environment: ${config.nodeEnv}`);\\\\n});\\\\n\\\\nsocket_io_server.on(\\\\\\\"connection\\\\\\\", (socket) => {\\\\n logger.info(`Client connected: ${socket.id}`);\\\\n\\\\n // Socket.io auto-parses incoming JSON into an object\\\\n socket.on(\\\\\\\"message\\\\\\\", (data) => {\\\\n if (data.type === \\\\\\\"ping\\\\\\\") {\\\\n // Socket.io auto-stringifies outgoing objects\\\\n socket.emit(\\\\\\\"message\\\\\\\", { type: \\\\\\\"pong\\\\\\\" });\\\\n }\\\\n });\\\\n\\\\n socket.on(\\\\\\\"error\\\\\\\", (err) => {\\\\n logger.error(`Socket error: ${err.message}`);\\\\n });\\\\n\\\\n socket.on(\\\\\\\"disconnect\\\\\\\", (reason) => {\\\\n logger.info(`Client disconnected: ${socket.id} (Reason: ${reason})`);\\\\n });\\\\n});\\\\n\\\\nprocess.on(\\\\\\\"SIGINT\\\\\\\", () => {\\\\n console.log(\\\\\\\"SIGINT received, forcefully stopping the server\\\\\\\");\\\\n process.exit(0);\\\\n});\\\\nprocess.on(\\\\\\\"SIGTERM\\\\\\\", () => {\\\\n console.log(\\\\\\\"SIGTERM received, gracefully stopping the server\\\\\\\");\\\\n process.exit(0);\\\\n});\\\\n\\\\n\\\\nexport default http_server;\\\\n\\\",\\n \\\"base/websockets/ws/javascript/index.js.ejs\\\": \\\"// javascript index file with WebSocketServer\\\\nimport express from \\\\\\\"express\\\\\\\";\\\\nimport helmet from \\\\\\\"helmet\\\\\\\";\\\\nimport cors from \\\\\\\"cors\\\\\\\";\\\\nimport router from \\\\\\\"./src/routes/index.js\\\\\\\";\\\\nimport errorHandler from \\\\\\\"./src/middleware/errorHandler.js\\\\\\\";\\\\nimport { logger } from \\\\\\\"./src/utils/logger.js\\\\\\\";\\\\nimport { config } from \\\\\\\"./src/config/env.js\\\\\\\";\\\\nimport { createServer } from \\\\\\\"http\\\\\\\";\\\\nimport { WebSocketServer } from \\\\\\\"ws\\\\\\\";\\\\n\\\\n<%_ if (database === 'postgresql_prisma') { _%>\\\\n// Prisma note: in prisma/schema.prisma use:\\\\n// provider = \\\\\\\"prisma-client-js\\\\\\\"\\\\n// output = \\\\\\\"../generated/prisma\\\\\\\"\\\\n<%_ } _%>\\\\n\\\\nconst app = express();\\\\nconst port = config.port;\\\\nconst http_server = createServer(app);\\\\nconst wss = new WebSocketServer({ server: http_server });\\\\n\\\\napp.use(express.json());\\\\napp.use(helmet());\\\\napp.use(cors());\\\\napp.use(express.urlencoded({ extended: true }));\\\\n// Call connectDb() from ./src/config/db.js to connect to your database and also update the env vars with database url\\\\n\\\\n// logger middleware\\\\napp.use((req, res, next) => {\\\\n logger.info({\\\\n method: req.method,\\\\n path: req.path,\\\\n ip: req.ip,\\\\n });\\\\n next();\\\\n});\\\\n\\\\napp.use(\\\\\\\"/api\\\\\\\", router);\\\\n\\\\napp.use(errorHandler);\\\\n\\\\nhttp_server.listen(port, () => {\\\\n logger.info(`Server running on port ${port}`);\\\\n logger.info(`Environment: ${config.nodeEnv}`);\\\\n});\\\\n\\\\nprocess.on(\\\\\\\"SIGINT\\\\\\\", () => {\\\\n console.log(\\\\\\\"SIGINT received, forcefully stopping the server\\\\\\\");\\\\n process.exit(0);\\\\n});\\\\nprocess.on(\\\\\\\"SIGTERM\\\\\\\", () => {\\\\n console.log(\\\\\\\"SIGTERM received, gracefully stopping the server\\\\\\\");\\\\n process.exit(0);\\\\n});\\\\n\\\\nwss.on(\\\\\\\"connection\\\\\\\", (socket) => {\\\\n socket.on(\\\\\\\"message\\\\\\\", (data) => {\\\\n const message = data.toString();\\\\n try {\\\\n const msg = JSON.parse(message);\\\\n if (msg.type === \\\\\\\"ping\\\\\\\") {\\\\n socket.send(\\\\n JSON.stringify({\\\\n type: \\\\\\\"Pong\\\\\\\",\\\\n }),\\\\n );\\\\n return;\\\\n }\\\\n } catch (error) {\\\\n socket.send(\\\\n JSON.stringify({\\\\n type: \\\\\\\"error\\\\\\\",\\\\n message:\\\\n \\\\\\\"incorrect format for sending message, Only use Json for messages\\\\\\\",\\\\n }),\\\\n );\\\\n socket.close();\\\\n return;\\\\n }\\\\n });\\\\n socket.on(\\\\\\\"error\\\\\\\", console.error);\\\\n socket.on(\\\\\\\"close\\\\\\\", () => console.log(`client disconnected`));\\\\n});\\\\n\\\\nexport default http_server;\\\\n\\\",\\n \\\"base/websockets/ws/typescript/index.ts.ejs\\\": \\\"// typescript index file with a websocket server\\\\nimport express, { type Request, type Response, type NextFunction } from \\\\\\\"express\\\\\\\";\\\\nimport helmet from \\\\\\\"helmet\\\\\\\";\\\\nimport cors from \\\\\\\"cors\\\\\\\";\\\\nimport routes from \\\\\\\"./routes/index\\\\\\\";\\\\nimport errorHandler from \\\\\\\"./middleware/errorHandler\\\\\\\";\\\\nimport { logger } from \\\\\\\"./utils/logger\\\\\\\";\\\\nimport { config } from \\\\\\\"./config/env\\\\\\\";\\\\nimport { createServer } from \\\\\\\"http\\\\\\\";\\\\nimport { WebSocketServer } from \\\\\\\"ws\\\\\\\";\\\\n\\\\n<%_ if (database === 'postgresql_prisma') { _%>\\\\n// Prisma note: in prisma/schema.prisma use:\\\\n// provider = \\\\\\\"prisma-client-js\\\\\\\"\\\\n// output = \\\\\\\"../generated/prisma\\\\\\\"\\\\n<%_ } _%>\\\\n\\\\nconst app = express();\\\\nconst port = config.port;\\\\nconst http_server = createServer(app);\\\\nconst wss = new WebSocketServer({ server: http_server });\\\\napp.use(express.json());\\\\napp.use(helmet());\\\\napp.use(cors());\\\\napp.use(express.urlencoded({ extended: true }));\\\\n\\\\n// logger middleware\\\\napp.use((req: Request, res: Response, next: NextFunction) => {\\\\n logger.info({\\\\n ip: req.ip,\\\\n method: req.method,\\\\n path: req.path,\\\\n });\\\\n next();\\\\n});\\\\n\\\\napp.use(\\\\\\\"/api\\\\\\\", routes);\\\\n\\\\napp.use(errorHandler);\\\\n\\\\nhttp_server.listen(port, () => {\\\\n logger.info(`Server running on port ${port}`);\\\\n logger.info(`Environment: ${config.nodeEnv}`);\\\\n});\\\\n\\\\nwss.on(\\\\\\\"connection\\\\\\\", (socket) => {\\\\n console.log(\\\\\\\"Client connected\\\\\\\");\\\\n // Basic Error Handling for the socket\\\\n socket.on(\\\\\\\"error\\\\\\\", console.error);\\\\n socket.on(\\\\\\\"message\\\\\\\", (message: string) => {\\\\n try {\\\\n const msg = JSON.parse(message);\\\\n if (msg.type === \\\\\\\"ping\\\\\\\") {\\\\n socket.send(\\\\n JSON.stringify({\\\\n type: \\\\\\\"pong\\\\\\\",\\\\n }),\\\\n );\\\\n return; \\\\n }\\\\n } catch (error) {\\\\n socket.send(\\\\n JSON.stringify({\\\\n type: \\\\\\\"error\\\\\\\",\\\\n message:\\\\n \\\\\\\"Incorrect format for sending message, Only use Json_Format for sending messages\\\\\\\",\\\\n }),\\\\n );\\\\n socket.close();\\\\n console.log(error);\\\\n }\\\\n });\\\\n socket.on(\\\\\\\"close\\\\\\\", () => {\\\\n console.log(\\\\\\\"Client Disconnected\\\\\\\");\\\\n });\\\\n});\\\\n\\\\nprocess.on(\\\\\\\"SIGINT\\\\\\\", () => {\\\\n console.log(\\\\\\\"SIGINT received, forcefully stopping the server\\\\\\\");\\\\n process.exit(0);\\\\n});\\\\nprocess.on(\\\\\\\"SIGTERM\\\\\\\", () => {\\\\n console.log(\\\\\\\"SIGTERM received, gracefully stopping the server\\\\\\\");\\\\n process.exit(0);\\\\n});\\\\n\\\\n\\\\nexport default http_server;\\\\n\\\",\\n \\\"features/docker/base/javascript/Dockerfile.ejs\\\": \\\"FROM node:22-alpine AS builder\\\\nWORKDIR /app\\\\nCOPY ./package*.json ./\\\\nRUN npm install\\\\nCOPY . .\\\\n\\\\nRUN npm prune --omit=dev \\\\n\\\\nFROM node:22-alpine AS runner\\\\nWORKDIR /app\\\\nENV NODE_ENV=production\\\\n\\\\nCOPY --from=builder /app/package*.json ./\\\\nCOPY --from=builder /app/node_modules ./node_modules\\\\nCOPY --from=builder /app ./\\\\n\\\\nEXPOSE 3000\\\\n\\\\nCMD [ \\\\\\\"node\\\\\\\",\\\\\\\"./index.js\\\\\\\" ]\\\\n\\\",\\n \\\"features/docker/base/typescript/Dockerfile.ejs\\\": \\\"# --- Stage 1: Build Stage ---\\\\nFROM node:22-alpine AS builder\\\\nWORKDIR /app\\\\n\\\\n# 1. Install dependencies first (for better caching)\\\\nCOPY package*.json ./\\\\nRUN npm install\\\\n\\\\n# 2. Copy source and tsconfig\\\\nCOPY . .\\\\n\\\\n# 3. Build the TypeScript code (assumes 'build' script runs 'tsc')\\\\nRUN npm run build\\\\n\\\\n# 4. Prune devDependencies (removes tsc and @types)\\\\nRUN npm prune --production\\\\n\\\\n\\\\n# --- Stage 2: Production Runner ---\\\\nFROM node:22-alpine AS runner\\\\nWORKDIR /app\\\\n\\\\n# Set production environment\\\\nENV NODE_ENV=production\\\\n\\\\n# 1. Copy only the production node_modules from builder\\\\nCOPY --from=builder /app/node_modules ./node_modules\\\\n\\\\n# 2. Copy the compiled JS files (usually from a 'dist' or 'build' folder)\\\\nCOPY --from=builder /app/dist ./dist\\\\n\\\\n# 3. Copy package.json (needed for \\\\\\\"type\\\\\\\": \\\\\\\"module\\\\\\\" and start scripts)\\\\nCOPY --from=builder /app/package*.json ./\\\\n\\\\n# 4. Security: Run as non-root user\\\\nUSER node\\\\n\\\\nEXPOSE 4000\\\\n\\\\n# 5. Run the compiled code\\\\nCMD [\\\\\\\"node\\\\\\\", \\\\\\\"dist/index.js\\\\\\\"]\\\"\\n};\\n\",\n \"features/docker/base/javascript/Dockerfile.ejs\": \"FROM node:22-alpine AS builder\\nWORKDIR /app\\nCOPY ./package*.json ./\\nRUN npm install\\nCOPY . .\\n\\nRUN npm prune --omit=dev \\n\\nFROM node:22-alpine AS runner\\nWORKDIR /app\\nENV NODE_ENV=production\\n\\nCOPY --from=builder /app/package*.json ./\\nCOPY --from=builder /app/node_modules ./node_modules\\nCOPY --from=builder /app ./\\n\\nEXPOSE 3000\\n\\nCMD [ \\\"node\\\",\\\"./index.js\\\" ]\\n\",\n \"features/docker/base/typescript/Dockerfile.ejs\": \"# --- Stage 1: Build Stage ---\\nFROM node:22-alpine AS builder\\nWORKDIR /app\\n\\n# 1. Install dependencies first (for better caching)\\nCOPY package*.json ./\\nRUN npm install\\n\\n# 2. Copy source and tsconfig\\nCOPY . .\\n\\n# 3. Build the TypeScript code (assumes 'build' script runs 'tsc')\\nRUN npm run build\\n\\n# 4. Prune devDependencies (removes tsc and @types)\\nRUN npm prune --production\\n\\n\\n# --- Stage 2: Production Runner ---\\nFROM node:22-alpine AS runner\\nWORKDIR /app\\n\\n# Set production environment\\nENV NODE_ENV=production\\n\\n# 1. Copy only the production node_modules from builder\\nCOPY --from=builder /app/node_modules ./node_modules\\n\\n# 2. Copy the compiled JS files (usually from a 'dist' or 'build' folder)\\nCOPY --from=builder /app/dist ./dist\\n\\n# 3. Copy package.json (needed for \\\"type\\\": \\\"module\\\" and start scripts)\\nCOPY --from=builder /app/package*.json ./\\n\\n# 4. Security: Run as non-root user\\nUSER node\\n\\nEXPOSE 4000\\n\\n# 5. Run the compiled code\\nCMD [\\\"node\\\", \\\"dist/index.js\\\"]\",\n \"package.json\": \"{\\n \\\"name\\\": \\\"appinit-templates\\\",\\n \\\"version\\\": \\\"1.0.1\\\",\\n \\\"type\\\": \\\"module\\\",\\n \\\"exports\\\": {\\n \\\"./docs\\\": \\\"./docs.generated.mjs\\\"\\n },\\n \\\"scripts\\\": {\\n \\\"generate:docs\\\": \\\"node ./scripts/generate-docs.mjs\\\"\\n },\\n \\\"files\\\": [\\n \\\"base\\\",\\n \\\"features\\\",\\n \\\"docs.generated.mjs\\\"\\n ]\\n}\\n\",\n \"scripts/generate-docs.mjs\": \"import { promises as fs } from \\\"node:fs\\\";\\nimport path from \\\"node:path\\\";\\nimport { fileURLToPath } from \\\"node:url\\\";\\n\\nconst __filename = fileURLToPath(import.meta.url);\\nconst __dirname = path.dirname(__filename);\\nconst templatesRoot = path.resolve(__dirname, \\\"..\\\");\\n\\nasync function walk(dir, base) {\\n const entries = await fs.readdir(dir, { withFileTypes: true });\\n const nested = await Promise.all(\\n entries.map(async (entry) => {\\n const full = path.join(dir, entry.name);\\n if (entry.isDirectory()) return walk(full, base);\\n return path.relative(base, full).replace(/\\\\\\\\/g, \\\"/\\\");\\n }),\\n );\\n return nested.flat();\\n}\\n\\nfunction mapRelativeTemplatePathToTarget(relativePath, language) {\\n const isTs = language === \\\"typescript\\\";\\n const parts = relativePath.split(\\\"/\\\").map((part) => {\\n if (part.startsWith(\\\",\\\")) {\\n return `.${part.slice(1)}`;\\n }\\n if (part.endsWith(\\\".ejs\\\")) {\\n return part.replace(/\\\\.ejs$/, \\\"\\\");\\n }\\n return part;\\n });\\n\\n let mapped = parts.join(\\\"/\\\");\\n\\n if (!isTs && relativePath === \\\"src/index.js.ejs\\\") {\\n mapped = \\\"index.js\\\";\\n }\\n\\n if (!isTs && mapped.endsWith(\\\".ts\\\")) {\\n mapped = mapped.replace(/\\\\.ts$/, \\\".js\\\");\\n }\\n\\n return mapped;\\n}\\n\\nconst allFiles = await walk(templatesRoot, templatesRoot);\\nconst sourceEntries = await Promise.all(\\n allFiles.map(async (relPath) => {\\n const absPath = path.join(templatesRoot, relPath);\\n const code = await fs.readFile(absPath, \\\"utf8\\\");\\n return [relPath, code];\\n }),\\n);\\n\\nfunction sorted(paths) {\\n return [...paths].sort((a, b) => a.localeCompare(b));\\n}\\n\\nfunction makeSections(language) {\\n const langDir = language === \\\"typescript\\\" ? \\\"typescript\\\" : \\\"javascript\\\";\\n\\n const baseRoot = `base/${langDir}/`;\\n const baseFiles = sorted(allFiles.filter((f) => f.startsWith(baseRoot) && f.endsWith(\\\".ejs\\\")));\\n\\n const wsRoot = `base/websockets/ws/${langDir}/`;\\n const wsFiles = sorted(allFiles.filter((f) => f.startsWith(wsRoot) && f.endsWith(\\\".ejs\\\")));\\n\\n const ioRoot = `base/websockets/socket.io/${langDir}/`;\\n const ioFiles = sorted(allFiles.filter((f) => f.startsWith(ioRoot) && f.endsWith(\\\".ejs\\\")));\\n\\n const dockerRoot = `features/docker/base/${langDir}/`;\\n const dockerFiles = sorted(allFiles.filter((f) => f.startsWith(dockerRoot) && f.endsWith(\\\".ejs\\\")));\\n\\n const commonFiles = [\\\"base/common/,gitignore.ejs\\\", \\\"base/common/env.ejs\\\"].filter((f) => allFiles.includes(f));\\n\\n const mapFile = (filePath, sectionRoot, forceTarget) => {\\n const relative = sectionRoot ? filePath.slice(sectionRoot.length) : filePath;\\n const targetPath = forceTarget ?? mapRelativeTemplatePathToTarget(relative, language);\\n return {\\n path: filePath,\\n name: filePath.split(\\\"/\\\").at(-1),\\n targetPath,\\n };\\n };\\n\\n return [\\n {\\n id: \\\"rest_api\\\",\\n title: \\\"REST API\\\",\\n files: baseFiles.map((f) => mapFile(f, baseRoot)),\\n },\\n {\\n id: \\\"common\\\",\\n title: \\\"Common Files\\\",\\n files: commonFiles.map((f) => mapFile(f, \\\"\\\", f.includes(\\\",gitignore\\\") ? \\\".gitignore\\\" : \\\".env\\\")),\\n },\\n {\\n id: \\\"websocket_ws\\\",\\n title: \\\"WebSocket (ws)\\\",\\n files: wsFiles.map((f) => {\\n const ext = language === \\\"typescript\\\" ? \\\"ts\\\" : \\\"js\\\";\\n const targetPath = language === \\\"typescript\\\" ? `src/index.${ext}` : `index.${ext}`;\\n return mapFile(f, wsRoot, targetPath);\\n }),\\n },\\n {\\n id: \\\"websocket_socketio\\\",\\n title: \\\"WebSocket (socket.io)\\\",\\n files: ioFiles.map((f) => {\\n const ext = language === \\\"typescript\\\" ? \\\"ts\\\" : \\\"js\\\";\\n const targetPath = language === \\\"typescript\\\" ? `src/index.${ext}` : `index.${ext}`;\\n return mapFile(f, ioRoot, targetPath);\\n }),\\n },\\n {\\n id: \\\"docker\\\",\\n title: \\\"Docker\\\",\\n files: dockerFiles.map((f) => mapFile(f, dockerRoot, \\\"Dockerfile\\\")),\\n },\\n ].filter((section) => section.files.length > 0);\\n}\\n\\nconst manifest = {\\n languages: {\\n typescript: makeSections(\\\"typescript\\\"),\\n javascript: makeSections(\\\"javascript\\\"),\\n },\\n};\\n\\nconst sources = Object.fromEntries(sourceEntries);\\n\\nconst output = `// Auto-generated by packages/templates/scripts/generate-docs.mjs\\\\nexport const templateDocsManifest = ${JSON.stringify(manifest, null, 2)};\\\\n\\\\nexport const templateDocsSources = ${JSON.stringify(sources, null, 2)};\\\\n`;\\n\\nawait fs.writeFile(path.join(templatesRoot, \\\"docs.generated.mjs\\\"), output, \\\"utf8\\\");\\nconsole.log(\\\"Generated docs.generated.mjs\\\");\\n\"\n};\n",
298
+ "features/docker/base/javascript/Dockerfile.ejs": "FROM node:22-alpine AS builder\nWORKDIR /app\nCOPY ./package*.json ./\nRUN npm install\nCOPY . .\n\nRUN npm prune --omit=dev \n\nFROM node:22-alpine AS runner\nWORKDIR /app\nENV NODE_ENV=production\n\nCOPY --from=builder /app/package*.json ./\nCOPY --from=builder /app/node_modules ./node_modules\nCOPY --from=builder /app ./\n\nEXPOSE 3000\n\nCMD [ \"node\",\"./index.js\" ]\n",
299
+ "features/docker/base/typescript/Dockerfile.ejs": "# --- Stage 1: Build Stage ---\nFROM node:22-alpine AS builder\nWORKDIR /app\n\n# 1. Install dependencies first (for better caching)\nCOPY package*.json ./\nRUN npm install\n\n# 2. Copy source and tsconfig\nCOPY . .\n\n# 3. Build the TypeScript code (assumes 'build' script runs 'tsc')\nRUN npm run build\n\n# 4. Prune devDependencies (removes tsc and @types)\nRUN npm prune --production\n\n\n# --- Stage 2: Production Runner ---\nFROM node:22-alpine AS runner\nWORKDIR /app\n\n# Set production environment\nENV NODE_ENV=production\n\n# 1. Copy only the production node_modules from builder\nCOPY --from=builder /app/node_modules ./node_modules\n\n# 2. Copy the compiled JS files (usually from a 'dist' or 'build' folder)\nCOPY --from=builder /app/dist ./dist\n\n# 3. Copy package.json (needed for \"type\": \"module\" and start scripts)\nCOPY --from=builder /app/package*.json ./\n\n# 4. Security: Run as non-root user\nUSER node\n\nEXPOSE 4000\n\n# 5. Run the compiled code\nCMD [\"node\", \"dist/index.js\"]",
300
+ "package.json": "{\n \"name\": \"appinit-templates\",\n \"version\": \"1.0.1\",\n \"type\": \"module\",\n \"exports\": {\n \"./docs\": \"./docs.generated.mjs\"\n },\n \"scripts\": {\n \"generate:docs\": \"node ./scripts/generate-docs.mjs\"\n },\n \"files\": [\n \"base\",\n \"features\",\n \"docs.generated.mjs\"\n ]\n}\n",
301
+ "scripts/generate-docs.mjs": "import { promises as fs } from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\nconst templatesRoot = path.resolve(__dirname, \"..\");\n\nasync function walk(dir, base) {\n const entries = await fs.readdir(dir, { withFileTypes: true });\n const nested = await Promise.all(\n entries.map(async (entry) => {\n const full = path.join(dir, entry.name);\n if (entry.isDirectory()) return walk(full, base);\n return path.relative(base, full).replace(/\\\\/g, \"/\");\n }),\n );\n return nested.flat();\n}\n\nfunction mapRelativeTemplatePathToTarget(relativePath, language) {\n const isTs = language === \"typescript\";\n const parts = relativePath.split(\"/\").map((part) => {\n if (part.startsWith(\",\")) {\n return `.${part.slice(1)}`;\n }\n if (part.endsWith(\".ejs\")) {\n return part.replace(/\\.ejs$/, \"\");\n }\n return part;\n });\n\n let mapped = parts.join(\"/\");\n\n if (!isTs && relativePath === \"src/index.js.ejs\") {\n mapped = \"index.js\";\n }\n\n if (!isTs && mapped.endsWith(\".ts\")) {\n mapped = mapped.replace(/\\.ts$/, \".js\");\n }\n\n return mapped;\n}\n\nconst allFiles = await walk(templatesRoot, templatesRoot);\nconst sourceEntries = await Promise.all(\n allFiles.map(async (relPath) => {\n const absPath = path.join(templatesRoot, relPath);\n const code = await fs.readFile(absPath, \"utf8\");\n return [relPath, code];\n }),\n);\n\nfunction sorted(paths) {\n return [...paths].sort((a, b) => a.localeCompare(b));\n}\n\nfunction makeSections(language) {\n const langDir = language === \"typescript\" ? \"typescript\" : \"javascript\";\n\n const baseRoot = `base/${langDir}/`;\n const baseFiles = sorted(allFiles.filter((f) => f.startsWith(baseRoot) && f.endsWith(\".ejs\")));\n\n const wsRoot = `base/websockets/ws/${langDir}/`;\n const wsFiles = sorted(allFiles.filter((f) => f.startsWith(wsRoot) && f.endsWith(\".ejs\")));\n\n const ioRoot = `base/websockets/socket.io/${langDir}/`;\n const ioFiles = sorted(allFiles.filter((f) => f.startsWith(ioRoot) && f.endsWith(\".ejs\")));\n\n const dockerRoot = `features/docker/base/${langDir}/`;\n const dockerFiles = sorted(allFiles.filter((f) => f.startsWith(dockerRoot) && f.endsWith(\".ejs\")));\n\n const commonFiles = [\"base/common/,gitignore.ejs\", \"base/common/env.ejs\"].filter((f) => allFiles.includes(f));\n\n const mapFile = (filePath, sectionRoot, forceTarget) => {\n const relative = sectionRoot ? filePath.slice(sectionRoot.length) : filePath;\n const targetPath = forceTarget ?? mapRelativeTemplatePathToTarget(relative, language);\n return {\n path: filePath,\n name: filePath.split(\"/\").at(-1),\n targetPath,\n };\n };\n\n // Separate configuration files from code files\n const configFilePatterns = ['.prettierrc', 'eslint.config', 'Readme.md'];\n const isConfigFile = (filePath) => configFilePatterns.some(pattern => filePath.includes(pattern));\n \n const codeFiles = baseFiles.filter(f => !isConfigFile(f));\n const configFiles = baseFiles.filter(f => isConfigFile(f));\n\n return [\n {\n id: \"rest_api\",\n title: \"REST API\",\n files: codeFiles.map((f) => mapFile(f, baseRoot)),\n },\n {\n id: \"configuration\",\n title: \"Configuration Files\",\n files: configFiles.map((f) => mapFile(f, baseRoot)),\n },\n {\n id: \"common\",\n title: \"Common Files\",\n files: commonFiles.map((f) => mapFile(f, \"\", f.includes(\",gitignore\") ? \".gitignore\" : \".env\")),\n },\n {\n id: \"websocket_ws\",\n title: \"WebSocket (ws)\",\n files: wsFiles.map((f) => {\n const ext = language === \"typescript\" ? \"ts\" : \"js\";\n const targetPath = language === \"typescript\" ? `src/index.${ext}` : `index.${ext}`;\n return mapFile(f, wsRoot, targetPath);\n }),\n },\n {\n id: \"websocket_socketio\",\n title: \"WebSocket (socket.io)\",\n files: ioFiles.map((f) => {\n const ext = language === \"typescript\" ? \"ts\" : \"js\";\n const targetPath = language === \"typescript\" ? `src/index.${ext}` : `index.${ext}`;\n return mapFile(f, ioRoot, targetPath);\n }),\n },\n {\n id: \"docker\",\n title: \"Docker\",\n files: dockerFiles.map((f) => mapFile(f, dockerRoot, \"Dockerfile\")),\n },\n ].filter((section) => section.files.length > 0);\n}\n\nconst manifest = {\n languages: {\n typescript: makeSections(\"typescript\"),\n javascript: makeSections(\"javascript\"),\n },\n};\n\nconst sources = Object.fromEntries(sourceEntries);\n\nconst output = `// Auto-generated by packages/templates/scripts/generate-docs.mjs\\nexport const templateDocsManifest = ${JSON.stringify(manifest, null, 2)};\\n\\nexport const templateDocsSources = ${JSON.stringify(sources, null, 2)};\\n`;\n\nawait fs.writeFile(path.join(templatesRoot, \"docs.generated.mjs\"), output, \"utf8\");\nconsole.log(\"Generated docs.generated.mjs\");\n"
302
+ };
package/package.json CHANGED
@@ -1,9 +1,16 @@
1
1
  {
2
2
  "name": "appinit-templates",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "type": "module",
5
+ "exports": {
6
+ "./docs": "./docs.generated.mjs"
7
+ },
5
8
  "files": [
6
9
  "base",
7
- "features"
8
- ]
10
+ "features",
11
+ "docs.generated.mjs"
12
+ ],
13
+ "scripts": {
14
+ "generate:docs": "node ./scripts/generate-docs.mjs"
15
+ }
9
16
  }