better-ts-stack 1.1.4 → 2.0.1

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 (129) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +113 -82
  3. package/dist/args.js +90 -0
  4. package/dist/builder/buildPlanner.js +71 -0
  5. package/dist/builder/configGenerator.js +19 -10
  6. package/dist/builder/dependencyInstaller.js +8 -15
  7. package/dist/builder/fileProcessor.js +47 -44
  8. package/dist/builder/gitInitializer.js +21 -35
  9. package/dist/builder/index.js +33 -91
  10. package/dist/builder/moduleSelector.js +11 -16
  11. package/dist/builder/templateContext.js +6 -27
  12. package/dist/index.js +47 -21
  13. package/dist/modules/registry.js +4 -6
  14. package/dist/output/nextSteps.js +10 -20
  15. package/dist/prompts/index.js +22 -59
  16. package/dist/prompts/stack.js +85 -71
  17. package/dist/types/index.js +47 -41
  18. package/dist/ui/index.js +18 -0
  19. package/dist/ui/messages.js +124 -0
  20. package/dist/ui/prompts.js +70 -0
  21. package/dist/ui/theme.js +23 -0
  22. package/dist/validators/index.js +15 -40
  23. package/package.json +71 -66
  24. package/templates/backend/express/.prettierrc +2 -2
  25. package/templates/backend/express/config.json +40 -44
  26. package/templates/backend/express/src/{index.ts → index.ts.hbs} +75 -76
  27. package/templates/backend/nestjs/.prettierignore +52 -0
  28. package/templates/backend/nestjs/.prettierrc +16 -0
  29. package/templates/backend/nestjs/config.json +41 -0
  30. package/templates/backend/nestjs/eslint.config.mjs +40 -0
  31. package/templates/backend/nestjs/gitignore +36 -0
  32. package/templates/backend/nestjs/nest-cli.json +9 -0
  33. package/templates/backend/nestjs/src/app.module.ts.hbs +34 -0
  34. package/templates/backend/nestjs/src/health/health.controller.ts +12 -0
  35. package/templates/backend/nestjs/src/main.ts +23 -0
  36. package/templates/backend/nestjs/tsconfig.eslint.json +9 -0
  37. package/templates/backend/nestjs/tsconfig.json +25 -0
  38. package/templates/frontend/nextjs/app/layout.tsx +13 -13
  39. package/templates/frontend/nextjs/app/page.tsx.hbs +97 -97
  40. package/templates/frontend/nextjs/components/ui/button.tsx +51 -51
  41. package/templates/frontend/nextjs/components/ui/card.tsx +60 -60
  42. package/templates/frontend/nextjs/components/ui/field.tsx +67 -67
  43. package/templates/frontend/nextjs/components/ui/input.tsx +18 -18
  44. package/templates/frontend/nextjs/config.json +37 -38
  45. package/templates/frontend/nextjs/eslint.config.mjs +11 -11
  46. package/templates/frontend/nextjs/next.config.ts.hbs +12 -12
  47. package/templates/frontend/tanstack/config.json +45 -48
  48. package/templates/modules/auth/express/config.json +20 -26
  49. package/templates/modules/auth/express/src/controllers/authController.ts.hbs +43 -57
  50. package/templates/modules/auth/nestjs/config.json +20 -0
  51. package/templates/modules/auth/nestjs/src/auth/auth.controller.ts +46 -0
  52. package/templates/modules/auth/nestjs/src/auth/auth.guard.ts +36 -0
  53. package/templates/modules/auth/nestjs/src/auth/auth.module.ts.hbs +22 -0
  54. package/templates/modules/auth/nestjs/src/auth/auth.schemas.ts +35 -0
  55. package/templates/modules/auth/nestjs/src/auth/auth.service.ts +70 -0
  56. package/templates/modules/auth/nestjs/src/auth/jwt.ts +27 -0
  57. package/templates/modules/auth/nestjs/src/auth/users.service.ts.hbs +144 -0
  58. package/templates/modules/auth/nestjs/src/auth/zod-validation.pipe.ts +16 -0
  59. package/templates/modules/auth/nextjs/config.json +18 -31
  60. package/templates/modules/auth/tanstack/config.json +2 -16
  61. package/templates/modules/docker/Dockerfile.hbs +135 -133
  62. package/templates/modules/docker/config.json +15 -19
  63. package/templates/modules/drizzle/express/config.json +26 -27
  64. package/templates/modules/drizzle/nestjs/config.json +26 -0
  65. package/templates/modules/drizzle/nestjs/drizzle.config.ts +13 -0
  66. package/templates/modules/drizzle/nestjs/src/database/database.module.ts +30 -0
  67. package/templates/modules/drizzle/nestjs/src/database/schema.ts +10 -0
  68. package/templates/modules/drizzle/nextjs/config.json +26 -29
  69. package/templates/modules/drizzle/tanstack/config.json +5 -5
  70. package/templates/modules/mongoose/express/config.json +15 -16
  71. package/templates/modules/mongoose/nestjs/config.json +15 -0
  72. package/templates/modules/mongoose/nestjs/src/users/user.schema.ts +21 -0
  73. package/templates/modules/mongoose/nextjs/config.json +15 -16
  74. package/templates/modules/mongoose/tanstack/config.json +16 -17
  75. package/templates/modules/prisma/express/config.json +27 -28
  76. package/templates/modules/prisma/nestjs/config.json +27 -0
  77. package/templates/modules/prisma/nestjs/prisma/schema.prisma +23 -0
  78. package/templates/modules/prisma/nestjs/prisma.config.ts +12 -0
  79. package/templates/modules/prisma/nestjs/src/prisma/prisma.module.ts +11 -0
  80. package/templates/modules/prisma/nestjs/src/prisma/prisma.service.ts +17 -0
  81. package/templates/modules/prisma/nextjs/config.json +28 -29
  82. package/templates/modules/prisma/tanstack/config.json +5 -6
  83. package/dist/builder/configGenerator.d.ts +0 -7
  84. package/dist/builder/configGenerator.d.ts.map +0 -1
  85. package/dist/builder/configGenerator.js.map +0 -1
  86. package/dist/builder/dependencyInstaller.d.ts +0 -3
  87. package/dist/builder/dependencyInstaller.d.ts.map +0 -1
  88. package/dist/builder/dependencyInstaller.js.map +0 -1
  89. package/dist/builder/fileProcessor.d.ts +0 -6
  90. package/dist/builder/fileProcessor.d.ts.map +0 -1
  91. package/dist/builder/fileProcessor.js.map +0 -1
  92. package/dist/builder/gitInitializer.d.ts +0 -2
  93. package/dist/builder/gitInitializer.d.ts.map +0 -1
  94. package/dist/builder/gitInitializer.js.map +0 -1
  95. package/dist/builder/index.d.ts +0 -3
  96. package/dist/builder/index.d.ts.map +0 -1
  97. package/dist/builder/index.js.map +0 -1
  98. package/dist/builder/moduleSelector.d.ts +0 -9
  99. package/dist/builder/moduleSelector.d.ts.map +0 -1
  100. package/dist/builder/moduleSelector.js.map +0 -1
  101. package/dist/builder/templateContext.d.ts +0 -21
  102. package/dist/builder/templateContext.d.ts.map +0 -1
  103. package/dist/builder/templateContext.js.map +0 -1
  104. package/dist/index.d.ts +0 -2
  105. package/dist/index.d.ts.map +0 -1
  106. package/dist/index.js.map +0 -1
  107. package/dist/intro.d.ts +0 -2
  108. package/dist/intro.d.ts.map +0 -1
  109. package/dist/intro.js +0 -27
  110. package/dist/intro.js.map +0 -1
  111. package/dist/modules/registry.d.ts +0 -6
  112. package/dist/modules/registry.d.ts.map +0 -1
  113. package/dist/modules/registry.js.map +0 -1
  114. package/dist/output/nextSteps.d.ts +0 -4
  115. package/dist/output/nextSteps.d.ts.map +0 -1
  116. package/dist/output/nextSteps.js.map +0 -1
  117. package/dist/prompts/index.d.ts +0 -4
  118. package/dist/prompts/index.d.ts.map +0 -1
  119. package/dist/prompts/index.js.map +0 -1
  120. package/dist/prompts/stack.d.ts +0 -3
  121. package/dist/prompts/stack.d.ts.map +0 -1
  122. package/dist/prompts/stack.js.map +0 -1
  123. package/dist/types/index.d.ts +0 -159
  124. package/dist/types/index.d.ts.map +0 -1
  125. package/dist/types/index.js.map +0 -1
  126. package/dist/validators/index.d.ts +0 -5
  127. package/dist/validators/index.d.ts.map +0 -1
  128. package/dist/validators/index.js.map +0 -1
  129. package/templates/backend/express/.eslintrc.js +0 -24
package/package.json CHANGED
@@ -1,66 +1,71 @@
1
- {
2
- "name": "better-ts-stack",
3
- "version": "1.1.4",
4
- "description": "A powerful CLI tool that generates fully configured TypeScript projects with backend, frontend, database integration, Docker support, and more--all through an interactive setup.",
5
- "keywords": [
6
- "cli",
7
- "builder",
8
- "backend",
9
- "typescript",
10
- "express",
11
- "prisma",
12
- "template"
13
- ],
14
- "homepage": "https://better-ts-stack.abdullahtech.me",
15
- "bugs": {
16
- "url": "https://github.com/Abdullah-dev0/better-ts-stack/issues"
17
- },
18
- "repository": {
19
- "type": "git",
20
- "url": "git+https://github.com/Abdullah-dev0/better-ts-stack.git"
21
- },
22
- "license": "MIT",
23
- "author": "Abdullah",
24
- "type": "commonjs",
25
- "main": "dist/index.js",
26
- "bin": {
27
- "better-ts-stack": "dist/index.js"
28
- },
29
- "files": [
30
- "dist",
31
- "templates"
32
- ],
33
- "scripts": {
34
- "dev": "tsx src/index.ts",
35
- "build": "tsc",
36
- "postbuild": "node -e \"const fs=require('fs');const p='dist/index.js';fs.writeFileSync(p,'#!/usr/bin/env node\\n'+fs.readFileSync(p,'utf8'))\"",
37
- "prepack": "npm run build",
38
- "start": "node dist/index.js",
39
- "lint": "eslint src",
40
- "lint:fix": "eslint src --fix",
41
- "format": "prettier --write \"**/*.{ts,tsx,js,jsx,json,md,mdx,css}\"",
42
- "format:check": "prettier --check \"**/*.{ts,tsx,js,jsx,json,md,mdx,css}\"",
43
- "type:check": "tsc --noEmit"
44
- },
45
- "dependencies": {
46
- "@clack/prompts": "^1.7.0",
47
- "consola": "^3.4.2",
48
- "fs-extra": "^11.4.0",
49
- "handlebars": "^4.7.9",
50
- "zod": "^4.5.4"
51
- },
52
- "devDependencies": {
53
- "@better-ts-stack/eslint-config": "*",
54
- "@better-ts-stack/prettier-config": "*",
55
- "@types/fs-extra": "^11.0.4",
56
- "@types/node": "^24.13.3",
57
- "eslint": "^10.10.0",
58
- "prettier": "^3.9.6",
59
- "tsx": "^4.23.13",
60
- "typescript": "^6.0.3"
61
- },
62
- "engines": {
63
- "node": ">=24.0.0"
64
- },
65
- "prettier": "@better-ts-stack/prettier-config"
66
- }
1
+ {
2
+ "name": "better-ts-stack",
3
+ "version": "2.0.1",
4
+ "description": "A CLI that scaffolds Express, NestJS, Next.js, and TanStack Start projects with a database, authentication, and Docker already set up.",
5
+ "keywords": [
6
+ "cli",
7
+ "builder",
8
+ "backend",
9
+ "typescript",
10
+ "express",
11
+ "nestjs",
12
+ "nextjs",
13
+ "tanstack-start",
14
+ "prisma",
15
+ "drizzle",
16
+ "mongoose",
17
+ "template"
18
+ ],
19
+ "homepage": "https://better-ts-stack.abdullahtech.me",
20
+ "bugs": {
21
+ "url": "https://github.com/Abdullah-dev0/better-ts-stack/issues"
22
+ },
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "git+https://github.com/Abdullah-dev0/better-ts-stack.git"
26
+ },
27
+ "license": "MIT",
28
+ "author": "Abdullah",
29
+ "type": "commonjs",
30
+ "main": "dist/index.js",
31
+ "bin": {
32
+ "better-ts-stack": "dist/index.js"
33
+ },
34
+ "files": [
35
+ "dist",
36
+ "templates"
37
+ ],
38
+ "scripts": {
39
+ "dev": "tsx src/index.ts",
40
+ "prebuild": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"",
41
+ "build": "tsc",
42
+ "postbuild": "node -e \"const fs=require('fs');const p='dist/index.js';fs.writeFileSync(p,'#!/usr/bin/env node\\n'+fs.readFileSync(p,'utf8'))\"",
43
+ "prepack": "npm run build",
44
+ "start": "node dist/index.js",
45
+ "lint": "eslint src",
46
+ "lint:fix": "eslint src --fix",
47
+ "format": "prettier --write \"**/*.{ts,tsx,js,jsx,json,md,mdx,css}\"",
48
+ "format:check": "prettier --check \"**/*.{ts,tsx,js,jsx,json,md,mdx,css}\"",
49
+ "type:check": "tsc --noEmit"
50
+ },
51
+ "dependencies": {
52
+ "@clack/core": "^1.4.3",
53
+ "fs-extra": "^11.4.0",
54
+ "handlebars": "^4.7.9",
55
+ "zod": "^4.5.4"
56
+ },
57
+ "devDependencies": {
58
+ "@better-ts-stack/eslint-config": "*",
59
+ "@better-ts-stack/prettier-config": "*",
60
+ "@types/fs-extra": "^11.0.4",
61
+ "@types/node": "^24.13.3",
62
+ "eslint": "^10.10.0",
63
+ "prettier": "^3.9.6",
64
+ "tsx": "^4.23.13",
65
+ "typescript": "^6.0.3"
66
+ },
67
+ "engines": {
68
+ "node": ">=24.0.0"
69
+ },
70
+ "prettier": "@better-ts-stack/prettier-config"
71
+ }
@@ -7,8 +7,8 @@
7
7
  "useTabs": false,
8
8
  "arrowParens": "always",
9
9
  "endOfLine": "lf",
10
- "plugins": ["@trivago/prettier-plugin-sort-imports", "prettier-plugin-tailwindcss"],
11
- "importOrder": ["^react", "^next", "<THIRD_PARTY_MODULES>", "^@repo/(.*)$", "^@/(.*)$", "^[./]"],
10
+ "plugins": ["@trivago/prettier-plugin-sort-imports"],
11
+ "importOrder": ["<THIRD_PARTY_MODULES>", "^[./]"],
12
12
  "importOrderSeparation": true,
13
13
  "importOrderSortSpecifiers": true,
14
14
  "importOrderGroupNamespaceSpecifiers": true,
@@ -1,44 +1,40 @@
1
- {
2
- "id": "express",
3
- "name": "Express Base",
4
- "description": "Base Express server with TypeScript, middleware, and best practices",
5
- "type": "base",
6
- "scripts": {
7
- "dev": "cross-env NODE_ENV=development {{#if (eq packageManager 'bun')}}bun --watch src/index.ts{{else}}tsx watch src/index.ts{{/if}}",
8
- "build": "tsc",
9
- "start": "cross-env NODE_ENV=production {{runner}} dist/index.js",
10
- "lint": "eslint src",
11
- "lint:fix": "eslint src --fix",
12
- "format": "prettier --write \"src/**/*.ts\"",
13
- "type:check": "tsc --noEmit"
14
- },
15
- "dependencies": {
16
- "express": "^5.2.1",
17
- "dotenv": "^17.4.2",
18
- "cors": "^2.8.6",
19
- "cross-env": "^10.1.0",
20
- "helmet": "^8.3.0",
21
- "morgan": "^1.12.0"
22
- },
23
- "devDependencies": {
24
- "@eslint/js": "^10.0.1",
25
- "@trivago/prettier-plugin-sort-imports": "^6.0.2",
26
- "@types/cors": "^2.8.19",
27
- "@types/express": "^5.0.6",
28
- "@types/morgan": "^1.9.10",
29
- "@types/node": "^24.13.3",
30
- "eslint": "^10.10.0",
31
- "eslint-config-prettier": "^10.1.8",
32
- "prettier": "^3.9.6",
33
- "prettier-plugin-tailwindcss": "^0.8.1",
34
- "tsx": "^4.23.13",
35
- "typescript": "^6.0.3",
36
- "typescript-eslint": "^8.69.0"
37
- },
38
- "envVars": {
39
- "PORT": "3000"
40
- },
41
- "templateFiles": [
42
- "src/index.ts"
43
- ]
44
- }
1
+ {
2
+ "id": "express",
3
+ "name": "Express Base",
4
+ "description": "Base Express server with TypeScript, security headers, and a health check",
5
+ "type": "base",
6
+ "scripts": {
7
+ "dev": "cross-env NODE_ENV=development {{#if (eq packageManager 'bun')}}bun --watch src/index.ts{{else}}tsx watch src/index.ts{{/if}}",
8
+ "build": "tsc",
9
+ "start": "cross-env NODE_ENV=production {{runner}} dist/index.js",
10
+ "lint": "eslint src",
11
+ "lint:fix": "eslint src --fix",
12
+ "format": "prettier --write \"src/**/*.ts\"",
13
+ "type:check": "tsc --noEmit"
14
+ },
15
+ "dependencies": {
16
+ "express": "^5.2.1",
17
+ "dotenv": "^17.4.2",
18
+ "cors": "^2.8.6",
19
+ "cross-env": "^10.1.0",
20
+ "helmet": "^8.3.0",
21
+ "morgan": "^1.12.0"
22
+ },
23
+ "devDependencies": {
24
+ "@eslint/js": "^10.0.1",
25
+ "@trivago/prettier-plugin-sort-imports": "^6.0.2",
26
+ "@types/cors": "^2.8.19",
27
+ "@types/express": "^5.0.6",
28
+ "@types/morgan": "^1.9.10",
29
+ "@types/node": "^24.13.3",
30
+ "eslint": "^10.10.0",
31
+ "eslint-config-prettier": "^10.1.8",
32
+ "prettier": "^3.9.6",
33
+ "tsx": "^4.23.13",
34
+ "typescript": "^6.0.3",
35
+ "typescript-eslint": "^8.69.0"
36
+ },
37
+ "envVars": {
38
+ "PORT": "3000"
39
+ }
40
+ }
@@ -1,76 +1,75 @@
1
- import 'dotenv/config';
2
- import express, { Express, Request, Response, NextFunction } from 'express';
3
- import cors from 'cors';
4
- import helmet from 'helmet';
5
- import morgan from 'morgan';
6
- {{#if (eq database 'mongoose')}}
7
- import { connectDB } from './lib/db';
8
- {{/if}}
9
- import healthRouter from './routes/health';
10
- {{#if useAuth}}
11
- import authRouter from './routes/auth';
12
- {{/if}}
13
-
14
-
15
-
16
- const app: Express = express();
17
- const port = process.env.PORT || 3000;
18
-
19
- // Middleware
20
- app.use(helmet());
21
- app.use(cors());
22
- app.use(morgan('dev'));
23
- app.use(express.json());
24
- app.use(express.urlencoded({ extended: true }));
25
-
26
- // Routes
27
- app.use('/health', healthRouter);
28
- {{#if useAuth}}
29
- app.use('/auth', authRouter);
30
- {{/if}}
31
-
32
- // 404 handler
33
- app.use((_req: Request, res: Response) => {
34
- res.status(404).json({ error: 'Not Found' });
35
- });
36
-
37
- // Error handler
38
- app.use(
39
- (
40
- err: Error & { status?: number; statusCode?: number; expose?: boolean },
41
- _req: Request,
42
- res: Response,
43
- _next: NextFunction,
44
- ) => {
45
- // Middleware such as express.json() sets 4xx statuses (bad JSON, body too large)
46
- const status = err.status ?? err.statusCode ?? 500;
47
-
48
- if (status >= 400 && status < 500) {
49
- res.status(status).json({ error: err.expose ? err.message : 'Bad Request' });
50
- return;
51
- }
52
-
53
- console.error(err.stack);
54
- res.status(500).json({ error: 'Internal Server Error' });
55
- },
56
- );
57
-
58
- {{#if (eq database 'mongoose')}}
59
- void awaitDatabase().catch((error: unknown) => {
60
- console.error(error);
61
- process.exitCode = 1;
62
- });
63
- async function awaitDatabase(): Promise<void> {
64
- await connectDB();
65
- app.listen(port);
66
- }
67
- {{else}}
68
- app.listen(port, () => {
69
- console.log(`Server is running on http://localhost:${port}
70
- Health: http://localhost:${port}/health
71
- `);
72
- });
73
-
74
- {{/if}}
75
-
76
- export default app;
1
+ import "dotenv/config";
2
+ import express, { Express, Request, Response, NextFunction } from "express";
3
+ import cors from "cors";
4
+ import helmet from "helmet";
5
+ import morgan from "morgan";
6
+ {{#if (eq database 'mongoose')}}
7
+ import { connectDB } from "./lib/db";
8
+ {{/if}}
9
+ import healthRouter from "./routes/health";
10
+ {{#if useAuth}}
11
+ import authRouter from "./routes/auth";
12
+ {{/if}}
13
+
14
+ const app: Express = express();
15
+ const port = process.env.PORT || 3000;
16
+
17
+ // Middleware
18
+ app.use(helmet());
19
+ app.use(cors());
20
+ app.use(morgan("dev"));
21
+ app.use(express.json());
22
+ app.use(express.urlencoded({ extended: true }));
23
+
24
+ // Routes
25
+ app.use("/health", healthRouter);
26
+ {{#if useAuth}}
27
+ app.use("/auth", authRouter);
28
+ {{/if}}
29
+
30
+ // 404 handler
31
+ app.use((_req: Request, res: Response) => {
32
+ res.status(404).json({ error: "Not Found" });
33
+ });
34
+
35
+ // Error handler
36
+ app.use(
37
+ (
38
+ err: Error & { status?: number; statusCode?: number; expose?: boolean },
39
+ _req: Request,
40
+ res: Response,
41
+ _next: NextFunction,
42
+ ) => {
43
+ // Middleware such as express.json() sets 4xx statuses (bad JSON, body too large)
44
+ const status = err.status ?? err.statusCode ?? 500;
45
+
46
+ if (status >= 400 && status < 500) {
47
+ res.status(status).json({ error: err.expose ? err.message : "Bad Request" });
48
+ return;
49
+ }
50
+
51
+ console.error(err.stack);
52
+ res.status(500).json({ error: "Internal Server Error" });
53
+ },
54
+ );
55
+
56
+ function listen(): void {
57
+ app.listen(port, () => {
58
+ console.log(`Server is running on http://localhost:${port}
59
+ Health: http://localhost:${port}/health
60
+ `);
61
+ });
62
+ }
63
+
64
+ {{#if (eq database 'mongoose')}}
65
+ void connectDB()
66
+ .then(listen)
67
+ .catch((error: unknown) => {
68
+ console.error(error);
69
+ process.exitCode = 1;
70
+ });
71
+ {{else}}
72
+ listen();
73
+ {{/if}}
74
+
75
+ export default app;
@@ -0,0 +1,52 @@
1
+ # Dependencies
2
+ node_modules
3
+ **/node_modules
4
+
5
+ # Build outputs
6
+ .next
7
+ out
8
+ dist
9
+ build
10
+ **/dist
11
+ **/.next
12
+ **/out
13
+ **/build
14
+
15
+ # Generated files
16
+ *.min.js
17
+ *.min.css
18
+ coverage
19
+ .nyc_output
20
+
21
+ # Lock files
22
+ package-lock.json
23
+ yarn.lock
24
+ pnpm-lock.yaml
25
+ bun.lock
26
+
27
+ # Logs
28
+ *.log
29
+ npm-debug.log*
30
+ yarn-debug.log*
31
+ yarn-error.log*
32
+
33
+ # Environment files
34
+ .env
35
+ .env.local
36
+ .env.*.local
37
+
38
+ # IDE
39
+ .vscode
40
+ .idea
41
+ *.swp
42
+ *.swo
43
+ *~
44
+
45
+ # OS
46
+ .DS_Store
47
+ Thumbs.db
48
+
49
+ # Templates (do not format generated/scaffold content)
50
+ templates
51
+ **/templates/**
52
+ *.hbs
@@ -0,0 +1,16 @@
1
+ {
2
+ "semi": true,
3
+ "trailingComma": "es5",
4
+ "singleQuote": false,
5
+ "printWidth": 80,
6
+ "tabWidth": 2,
7
+ "useTabs": false,
8
+ "arrowParens": "always",
9
+ "endOfLine": "lf",
10
+ "plugins": ["@trivago/prettier-plugin-sort-imports"],
11
+ "importOrder": ["<THIRD_PARTY_MODULES>", "^[./]"],
12
+ "importOrderSeparation": true,
13
+ "importOrderSortSpecifiers": true,
14
+ "importOrderCaseInsensitive": true,
15
+ "importOrderParserPlugins": ["typescript", "decorators-legacy"]
16
+ }
@@ -0,0 +1,41 @@
1
+ {
2
+ "id": "nestjs",
3
+ "name": "NestJS Base",
4
+ "description": "Base NestJS server with TypeScript, security headers, and a health check",
5
+ "type": "base",
6
+ "scripts": {
7
+ "dev": "cross-env NODE_ENV=development nest start --watch",
8
+ "build": "nest build",
9
+ "start": "cross-env NODE_ENV=production {{runner}} dist/main.js",
10
+ "lint": "eslint src",
11
+ "lint:fix": "eslint src --fix",
12
+ "format": "prettier --write \"src/**/*.ts\"",
13
+ "type:check": "tsc --noEmit"
14
+ },
15
+ "dependencies": {
16
+ "@nestjs/common": "^12.1.2",
17
+ "@nestjs/core": "^12.1.2",
18
+ "@nestjs/platform-express": "^12.1.2",
19
+ "cross-env": "^10.1.0",
20
+ "dotenv": "^17.4.2",
21
+ "helmet": "^8.3.0",
22
+ "reflect-metadata": "^0.2.2",
23
+ "rxjs": "^7.8.2"
24
+ },
25
+ "devDependencies": {
26
+ "@eslint/js": "^10.0.1",
27
+ "@nestjs/cli": "^12.0.8",
28
+ "@nestjs/schematics": "^12.0.6",
29
+ "@trivago/prettier-plugin-sort-imports": "^6.0.2",
30
+ "@types/express": "^5.0.6",
31
+ "@types/node": "^24.13.3",
32
+ "eslint": "^10.10.0",
33
+ "eslint-config-prettier": "^10.1.8",
34
+ "prettier": "^3.9.6",
35
+ "typescript": "^6.0.3",
36
+ "typescript-eslint": "^8.69.0"
37
+ },
38
+ "envVars": {
39
+ "PORT": "3000"
40
+ }
41
+ }
@@ -0,0 +1,40 @@
1
+ import eslint from "@eslint/js";
2
+ import path from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import tseslint from "typescript-eslint";
5
+
6
+ const __filename = fileURLToPath(import.meta.url);
7
+ const __dirname = path.dirname(__filename);
8
+
9
+ export default tseslint.config(
10
+ {
11
+ ignores: [
12
+ "dist",
13
+ "node_modules",
14
+ "templates/**/*",
15
+ "bin/**/*",
16
+ "src/generated/**",
17
+ ],
18
+ },
19
+ eslint.configs.recommended,
20
+ ...tseslint.configs.recommended,
21
+ ...tseslint.configs.recommendedTypeChecked,
22
+ {
23
+ languageOptions: {
24
+ parserOptions: {
25
+ project: "./tsconfig.eslint.json",
26
+ tsconfigRootDir: __dirname,
27
+ },
28
+ },
29
+ rules: {
30
+ "@typescript-eslint/explicit-function-return-type": "off",
31
+ "@typescript-eslint/no-explicit-any": "warn",
32
+ "@typescript-eslint/no-unused-vars": [
33
+ "error",
34
+ { argsIgnorePattern: "^_" },
35
+ ],
36
+ "@typescript-eslint/no-floating-promises": "error",
37
+ "no-console": "off",
38
+ },
39
+ }
40
+ );
@@ -0,0 +1,36 @@
1
+ # Dependencies
2
+ node_modules/
3
+
4
+ # Build output
5
+ dist/
6
+ build/
7
+
8
+ # Environment variables
9
+ .env
10
+ .env.local
11
+ .env.*.local
12
+
13
+ # Logs
14
+ logs/
15
+ *.log
16
+ npm-debug.log*
17
+ yarn-debug.log*
18
+ yarn-error.log*
19
+
20
+ # IDE
21
+ .vscode/
22
+ .idea/
23
+ *.swp
24
+ *.swo
25
+ *~
26
+
27
+ # OS
28
+ .DS_Store
29
+ Thumbs.db
30
+
31
+ # Testing
32
+ coverage/
33
+ .nyc_output/
34
+
35
+ # Misc
36
+ *.tsbuildinfo
@@ -0,0 +1,9 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/nest-cli",
3
+ "collection": "@nestjs/schematics",
4
+ "sourceRoot": "src",
5
+ "compilerOptions": {
6
+ "deleteOutDir": true,
7
+ "tsConfigPath": "tsconfig.json"
8
+ }
9
+ }
@@ -0,0 +1,34 @@
1
+ import { Module } from "@nestjs/common";
2
+ {{#if (eq database 'mongoose')}}
3
+ import { MongooseModule } from "@nestjs/mongoose";
4
+ {{/if}}
5
+
6
+ {{#if useAuth}}
7
+ import { AuthModule } from "./auth/auth.module.js";
8
+ {{/if}}
9
+ {{#if (eq database 'drizzle')}}
10
+ import { DatabaseModule } from "./database/database.module.js";
11
+ {{/if}}
12
+ import { HealthController } from "./health/health.controller.js";
13
+ {{#if (eq database 'prisma')}}
14
+ import { PrismaModule } from "./prisma/prisma.module.js";
15
+ {{/if}}
16
+
17
+ @Module({
18
+ imports: [
19
+ {{#if (eq database 'prisma')}}
20
+ PrismaModule,
21
+ {{/if}}
22
+ {{#if (eq database 'drizzle')}}
23
+ DatabaseModule,
24
+ {{/if}}
25
+ {{#if (eq database 'mongoose')}}
26
+ MongooseModule.forRoot(process.env.MONGODB_URI!),
27
+ {{/if}}
28
+ {{#if useAuth}}
29
+ AuthModule,
30
+ {{/if}}
31
+ ],
32
+ controllers: [HealthController],
33
+ })
34
+ export class AppModule {}
@@ -0,0 +1,12 @@
1
+ import { Controller, Get } from "@nestjs/common";
2
+
3
+ @Controller("health")
4
+ export class HealthController {
5
+ @Get()
6
+ check(): { status: string; timestamp: string } {
7
+ return {
8
+ status: "ok",
9
+ timestamp: new Date().toISOString(),
10
+ };
11
+ }
12
+ }
@@ -0,0 +1,23 @@
1
+ import { NestFactory } from "@nestjs/core";
2
+ // Loads .env before app.module.js reads process.env
3
+ import "dotenv/config";
4
+ import helmet from "helmet";
5
+
6
+ import { AppModule } from "./app.module.js";
7
+
8
+ async function bootstrap(): Promise<void> {
9
+ const app = await NestFactory.create(AppModule);
10
+ const port = process.env.PORT ?? 3000;
11
+
12
+ app.use(helmet());
13
+ app.enableCors();
14
+ // Lets modules close database connections when the process is stopped
15
+ app.enableShutdownHooks();
16
+
17
+ await app.listen(port);
18
+ console.log(`Server is running on http://localhost:${port}
19
+ Health: http://localhost:${port}/health
20
+ `);
21
+ }
22
+
23
+ void bootstrap();