better-ts-stack 0.1.1 → 1.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -6
- package/dist/builder/configGenerator.d.ts.map +1 -1
- package/dist/builder/configGenerator.js +26 -23
- package/dist/builder/configGenerator.js.map +1 -1
- package/dist/builder/dependencyInstaller.d.ts.map +1 -1
- package/dist/builder/dependencyInstaller.js +1 -10
- package/dist/builder/dependencyInstaller.js.map +1 -1
- package/dist/builder/index.d.ts.map +1 -1
- package/dist/builder/index.js +3 -7
- package/dist/builder/index.js.map +1 -1
- package/dist/builder/templateContext.d.ts +1 -1
- package/dist/builder/templateContext.d.ts.map +1 -1
- package/dist/builder/templateContext.js +0 -2
- package/dist/builder/templateContext.js.map +1 -1
- package/dist/modules/registry.d.ts.map +1 -1
- package/dist/modules/registry.js +2 -5
- package/dist/modules/registry.js.map +1 -1
- package/dist/output/nextSteps.d.ts.map +1 -1
- package/dist/output/nextSteps.js +7 -34
- package/dist/output/nextSteps.js.map +1 -1
- package/dist/prompts/index.d.ts.map +1 -1
- package/dist/prompts/index.js +3 -14
- package/dist/prompts/index.js.map +1 -1
- package/dist/prompts/stack.d.ts +3 -0
- package/dist/prompts/stack.d.ts.map +1 -0
- package/dist/prompts/stack.js +72 -0
- package/dist/prompts/stack.js.map +1 -0
- package/dist/types/index.d.ts +4 -7
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +0 -9
- package/dist/types/index.js.map +1 -1
- package/dist/validators/index.d.ts +1 -1
- package/dist/validators/index.d.ts.map +1 -1
- package/dist/validators/index.js +1 -1
- package/package.json +12 -12
- package/templates/backend/express/config.json +44 -42
- package/templates/backend/express/eslint.config.mjs +40 -31
- package/templates/backend/express/src/index.ts +61 -46
- package/templates/backend/express/src/routes/health.ts +12 -12
- package/templates/backend/express/tsconfig.json +25 -23
- package/templates/frontend/nextjs/config.json +33 -27
- package/templates/frontend/nextjs/eslint.config.mjs +11 -11
- package/templates/frontend/nextjs/proxy.ts.hbs +9 -8
- package/templates/frontend/nextjs/tsconfig.json +34 -21
- package/templates/modules/auth/express/config.json +26 -1
- package/templates/modules/auth/express/src/routes/auth.ts.hbs +1 -1
- package/templates/modules/auth/express/src/services/userStore.ts.hbs +95 -107
- package/templates/modules/auth/nextjs/config.json +6 -6
- package/templates/modules/auth/nextjs/lib/auth.ts.hbs +34 -32
- package/templates/modules/docker/.dockerignore +14 -13
- package/templates/modules/docker/Dockerfile.hbs +80 -70
- package/templates/modules/docker/config.json +19 -16
- package/templates/modules/docker/docker-compose.yml.hbs +9 -9
- package/templates/modules/drizzle/express/config.json +27 -0
- package/templates/modules/drizzle/express/drizzle.config.ts +13 -0
- package/templates/modules/drizzle/express/src/lib/db.ts +13 -0
- package/templates/modules/drizzle/express/src/lib/schema.ts +10 -0
- package/templates/modules/drizzle/nextjs/config.json +27 -19
- package/templates/modules/drizzle/nextjs/lib/db.ts +3 -1
- package/templates/modules/drizzle/nextjs/lib/schema.ts.hbs +84 -84
- package/templates/modules/mongoose/config.json +16 -16
- package/templates/modules/mongoose/src/lib/db.ts.hbs +0 -13
- package/templates/modules/mongoose/src/models/User.ts +48 -47
- package/templates/modules/prisma/express/config.json +27 -21
- package/templates/modules/prisma/express/prisma/schema.prisma +3 -2
- package/templates/modules/prisma/express/prisma.config.ts +12 -13
- package/templates/modules/prisma/express/src/lib/prisma.ts +24 -37
- package/templates/modules/prisma/nextjs/config.json +28 -23
- package/templates/modules/prisma/nextjs/prisma/schema.prisma.hbs +91 -90
- package/dist/prompts/backend/index.d.ts +0 -3
- package/dist/prompts/backend/index.d.ts.map +0 -1
- package/dist/prompts/backend/index.js +0 -128
- package/dist/prompts/backend/index.js.map +0 -1
- package/dist/prompts/frontend/index.d.ts +0 -3
- package/dist/prompts/frontend/index.d.ts.map +0 -1
- package/dist/prompts/frontend/index.js +0 -111
- package/dist/prompts/frontend/index.js.map +0 -1
|
@@ -1,21 +1,34 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2017",
|
|
4
|
-
"lib": ["dom", "dom.iterable", "esnext"],
|
|
5
|
-
"allowJs": true,
|
|
6
|
-
"skipLibCheck": true,
|
|
7
|
-
"strict": true,
|
|
8
|
-
"noEmit": true,
|
|
9
|
-
"esModuleInterop": true,
|
|
10
|
-
"module": "esnext",
|
|
11
|
-
"moduleResolution": "bundler",
|
|
12
|
-
"resolveJsonModule": true,
|
|
13
|
-
"isolatedModules": true,
|
|
14
|
-
"jsx": "react-jsx",
|
|
15
|
-
"incremental": true,
|
|
16
|
-
"plugins": [
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2017",
|
|
4
|
+
"lib": ["dom", "dom.iterable", "esnext"],
|
|
5
|
+
"allowJs": true,
|
|
6
|
+
"skipLibCheck": true,
|
|
7
|
+
"strict": true,
|
|
8
|
+
"noEmit": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"module": "esnext",
|
|
11
|
+
"moduleResolution": "bundler",
|
|
12
|
+
"resolveJsonModule": true,
|
|
13
|
+
"isolatedModules": true,
|
|
14
|
+
"jsx": "react-jsx",
|
|
15
|
+
"incremental": true,
|
|
16
|
+
"plugins": [
|
|
17
|
+
{
|
|
18
|
+
"name": "next"
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"paths": {
|
|
22
|
+
"@/*": ["./*"]
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"include": [
|
|
26
|
+
"next-env.d.ts",
|
|
27
|
+
"**/*.ts",
|
|
28
|
+
"**/*.tsx",
|
|
29
|
+
".next/types/**/*.ts",
|
|
30
|
+
".next/dev/types/**/*.ts",
|
|
31
|
+
"**/*.mts"
|
|
32
|
+
],
|
|
33
|
+
"exclude": ["node_modules"]
|
|
34
|
+
}
|
|
@@ -1 +1,26 @@
|
|
|
1
|
-
{
|
|
1
|
+
{
|
|
2
|
+
"id": "auth",
|
|
3
|
+
"name": "JWT Auth",
|
|
4
|
+
"description": "JWT authentication with bcrypt password hashing",
|
|
5
|
+
"type": "feature",
|
|
6
|
+
"dependencies": {
|
|
7
|
+
"bcrypt": "^6.0.0",
|
|
8
|
+
"jsonwebtoken": "^9.0.3"
|
|
9
|
+
},
|
|
10
|
+
"devDependencies": {
|
|
11
|
+
"@types/bcrypt": "^6.0.0",
|
|
12
|
+
"@types/jsonwebtoken": "^9.0.10"
|
|
13
|
+
},
|
|
14
|
+
"scripts": {},
|
|
15
|
+
"envVars": {
|
|
16
|
+
"JWT_SECRET": "please-change-me",
|
|
17
|
+
"JWT_EXPIRES_IN": "1h"
|
|
18
|
+
},
|
|
19
|
+
"templateFiles": [
|
|
20
|
+
"src/lib/jwt.ts.hbs",
|
|
21
|
+
"src/middleware/requireAuth.ts.hbs",
|
|
22
|
+
"src/services/userStore.ts.hbs",
|
|
23
|
+
"src/routes/auth.ts.hbs",
|
|
24
|
+
"src/controllers/authController.ts.hbs"
|
|
25
|
+
]
|
|
26
|
+
}
|
|
@@ -2,7 +2,7 @@ import { Request, Response, NextFunction, Router } from 'express';
|
|
|
2
2
|
import { login, me, register } from '../controllers/authController';
|
|
3
3
|
import { requireAuth } from '../middleware/requireAuth';
|
|
4
4
|
|
|
5
|
-
const router = Router();
|
|
5
|
+
const router: Router = Router();
|
|
6
6
|
|
|
7
7
|
function asyncHandler(
|
|
8
8
|
fn: (req: Request, res: Response, next: NextFunction) => Promise<void>
|
|
@@ -1,107 +1,95 @@
|
|
|
1
|
-
{{#if (eq database '
|
|
2
|
-
import
|
|
3
|
-
{
|
|
4
|
-
{
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
{{
|
|
9
|
-
|
|
10
|
-
{
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
{{
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
return
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
{{/if}}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
password: data.password,
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
users.push(newUser);
|
|
100
|
-
return newUser;
|
|
101
|
-
{{/if}}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
export function toPublicUser(user: AuthUser): Omit<AuthUser, 'password'> {
|
|
105
|
-
const { id, email, name } = user;
|
|
106
|
-
return { id, email, name };
|
|
107
|
-
}
|
|
1
|
+
{{#if (eq database 'drizzle')}}
|
|
2
|
+
import { eq } from "drizzle-orm";
|
|
3
|
+
import { db } from "../lib/db";
|
|
4
|
+
import { users } from "../lib/schema";
|
|
5
|
+
{{/if}}
|
|
6
|
+
{{#if (eq database 'none')}}
|
|
7
|
+
import crypto from 'crypto';
|
|
8
|
+
{{/if}}
|
|
9
|
+
{{#if (eq database 'prisma')}}
|
|
10
|
+
import { prisma } from '../lib/prisma';
|
|
11
|
+
{{/if}}
|
|
12
|
+
{{#if (eq database 'mongoose')}}
|
|
13
|
+
import UserModel from '../models/User';
|
|
14
|
+
{{/if}}
|
|
15
|
+
|
|
16
|
+
export interface AuthUser {
|
|
17
|
+
id: string;
|
|
18
|
+
email: string;
|
|
19
|
+
name?: string | null;
|
|
20
|
+
password: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface CreateUserInput {
|
|
24
|
+
email: string;
|
|
25
|
+
name?: string | null;
|
|
26
|
+
password: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
{{#if (eq database 'none')}}
|
|
30
|
+
const users: AuthUser[] = [];
|
|
31
|
+
{{/if}}
|
|
32
|
+
|
|
33
|
+
export {{#unless (eq database 'none')}}async {{/unless}}function findUserByEmail(email: string): Promise<AuthUser | null> {
|
|
34
|
+
{{#if (eq database 'drizzle')}}
|
|
35
|
+
const [user] = await db.select().from(users).where(eq(users.email, email)).limit(1);
|
|
36
|
+
return user ?? null;
|
|
37
|
+
{{/if}}
|
|
38
|
+
{{#if (eq database 'prisma')}}
|
|
39
|
+
return await prisma.user.findUnique({ where: { email } });
|
|
40
|
+
{{/if}}
|
|
41
|
+
|
|
42
|
+
{{#if (eq database 'mongoose')}}
|
|
43
|
+
const user = await UserModel.findOne({ email }).exec();
|
|
44
|
+
if (!user) return null;
|
|
45
|
+
return {
|
|
46
|
+
id: String(user._id),
|
|
47
|
+
email: user.email,
|
|
48
|
+
name: user.name,
|
|
49
|
+
password: user.password,
|
|
50
|
+
};
|
|
51
|
+
{{/if}}
|
|
52
|
+
|
|
53
|
+
{{#if (eq database 'none')}}
|
|
54
|
+
const user = users.find((candidate) => candidate.email === email);
|
|
55
|
+
return Promise.resolve(user ?? null);
|
|
56
|
+
{{/if}}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export {{#unless (eq database 'none')}}async {{/unless}}function createUser(data: CreateUserInput): Promise<AuthUser> {
|
|
60
|
+
{{#if (eq database 'drizzle')}}
|
|
61
|
+
const [user] = await db.insert(users).values(data).returning();
|
|
62
|
+
return user;
|
|
63
|
+
{{/if}}
|
|
64
|
+
{{#if (eq database 'prisma')}}
|
|
65
|
+
return await prisma.user.create({ data });
|
|
66
|
+
{{/if}}
|
|
67
|
+
|
|
68
|
+
{{#if (eq database 'mongoose')}}
|
|
69
|
+
const user = await UserModel.create(data);
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
id: String(user._id),
|
|
73
|
+
email: user.email,
|
|
74
|
+
name: user.name,
|
|
75
|
+
password: user.password,
|
|
76
|
+
};
|
|
77
|
+
{{/if}}
|
|
78
|
+
|
|
79
|
+
{{#if (eq database 'none')}}
|
|
80
|
+
const newUser: AuthUser = {
|
|
81
|
+
id: crypto.randomUUID(),
|
|
82
|
+
email: data.email,
|
|
83
|
+
name: data.name,
|
|
84
|
+
password: data.password,
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
users.push(newUser);
|
|
88
|
+
return Promise.resolve(newUser);
|
|
89
|
+
{{/if}}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function toPublicUser(user: AuthUser): Omit<AuthUser, 'password'> {
|
|
93
|
+
const { id, email, name } = user;
|
|
94
|
+
return { id, email, name };
|
|
95
|
+
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
{
|
|
1
|
+
{
|
|
2
2
|
"id": "auth",
|
|
3
3
|
"name": "Better Auth",
|
|
4
4
|
"description": "Better Auth for Next.js with optional Prisma or Drizzle adapter",
|
|
5
5
|
"type": "feature",
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"@hookform/resolvers": "^5.
|
|
8
|
-
"better-auth": "^1.
|
|
9
|
-
"mongodb": "^6.0
|
|
10
|
-
"react-hook-form": "^7.
|
|
11
|
-
"zod": "^4.
|
|
7
|
+
"@hookform/resolvers": "^5.9.1",
|
|
8
|
+
"better-auth": "^1.7.3",
|
|
9
|
+
"mongodb": "^7.6.0",
|
|
10
|
+
"react-hook-form": "^7.87.0",
|
|
11
|
+
"zod": "^4.5.4"
|
|
12
12
|
},
|
|
13
13
|
"devDependencies": {},
|
|
14
14
|
"scripts": {},
|
|
@@ -1,35 +1,37 @@
|
|
|
1
|
-
import { betterAuth } from "better-auth";
|
|
2
|
-
import { nextCookies } from "better-auth/next-js";
|
|
3
|
-
{{#if (eq database 'prisma')}}
|
|
4
|
-
import { prismaAdapter } from "better-auth/adapters/prisma";
|
|
5
|
-
import client from "./prisma";
|
|
6
|
-
{{/if}}
|
|
7
|
-
{{#if (eq database 'drizzle')}}
|
|
8
|
-
import { drizzleAdapter } from "better-auth/adapters/drizzle";
|
|
9
|
-
import { db } from "./db";
|
|
10
|
-
{{/if}}
|
|
11
|
-
{{#if (eq database 'mongoose')}}
|
|
12
|
-
import { mongodbAdapter } from "better-auth/adapters/mongodb";
|
|
13
|
-
import { MongoClient } from "mongodb";
|
|
14
|
-
|
|
15
|
-
const client = new MongoClient(process.env.MONGODB_URI!);
|
|
16
|
-
const db = client.db();
|
|
17
|
-
{{/if}}
|
|
18
|
-
|
|
19
|
-
export const auth = betterAuth({
|
|
20
|
-
{{#if (eq database 'prisma')}}
|
|
21
|
-
database: prismaAdapter(client, { provider: "postgresql" }),
|
|
22
|
-
{{/if}}
|
|
1
|
+
import { betterAuth } from "better-auth";
|
|
2
|
+
import { nextCookies } from "better-auth/next-js";
|
|
3
|
+
{{#if (eq database 'prisma')}}
|
|
4
|
+
import { prismaAdapter } from "better-auth/adapters/prisma";
|
|
5
|
+
import client from "./prisma";
|
|
6
|
+
{{/if}}
|
|
7
|
+
{{#if (eq database 'drizzle')}}
|
|
8
|
+
import { drizzleAdapter } from "better-auth/adapters/drizzle";
|
|
9
|
+
import { db } from "./db";
|
|
10
|
+
{{/if}}
|
|
11
|
+
{{#if (eq database 'mongoose')}}
|
|
12
|
+
import { mongodbAdapter } from "better-auth/adapters/mongodb";
|
|
13
|
+
import { MongoClient } from "mongodb";
|
|
14
|
+
|
|
15
|
+
const client = new MongoClient(process.env.MONGODB_URI!);
|
|
16
|
+
const db = client.db();
|
|
17
|
+
{{/if}}
|
|
18
|
+
|
|
19
|
+
export const auth = betterAuth({
|
|
20
|
+
{{#if (eq database 'prisma')}}
|
|
21
|
+
database: prismaAdapter(client, { provider: "postgresql" }),
|
|
22
|
+
{{/if}}
|
|
23
23
|
{{#if (eq database 'drizzle')}}
|
|
24
24
|
database: drizzleAdapter(db, { provider: "pg" }),
|
|
25
25
|
{{/if}}
|
|
26
|
-
{{#if (eq database 'mongoose')}}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
26
|
+
{{#if (eq database 'mongoose')}}
|
|
27
|
+
// Transactions require a replica set. Create user/session/account/verification
|
|
28
|
+
// collections before the first sign-up; see the database setup documentation.
|
|
29
|
+
database: mongodbAdapter(db, { client }),
|
|
30
|
+
{{/if}}
|
|
31
|
+
emailAndPassword: {
|
|
32
|
+
enabled: true,
|
|
33
|
+
},
|
|
34
|
+
plugins: [nextCookies()],
|
|
35
|
+
secret: process.env.BETTER_AUTH_SECRET,
|
|
36
|
+
baseURL: process.env.BETTER_AUTH_URL,
|
|
37
|
+
});
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
node_modules
|
|
2
|
-
npm-debug.log
|
|
3
|
-
.env
|
|
4
|
-
.
|
|
5
|
-
.
|
|
6
|
-
.
|
|
7
|
-
|
|
8
|
-
.
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
1
|
+
node_modules
|
|
2
|
+
npm-debug.log
|
|
3
|
+
.env*
|
|
4
|
+
.git
|
|
5
|
+
.gitignore
|
|
6
|
+
README.md
|
|
7
|
+
.vscode
|
|
8
|
+
.idea
|
|
9
|
+
dist
|
|
10
|
+
coverage
|
|
11
|
+
.DS_Store
|
|
12
|
+
*.log
|
|
13
|
+
|
|
14
|
+
.next
|
|
@@ -1,71 +1,81 @@
|
|
|
1
|
-
{{#if (eq framework 'nextjs')}}
|
|
2
|
-
# Base stage
|
|
3
|
-
FROM node:
|
|
4
|
-
WORKDIR /app
|
|
5
|
-
RUN apk add --no-cache libc6-compat
|
|
6
|
-
|
|
7
|
-
# Dependencies stage
|
|
8
|
-
FROM base AS deps
|
|
9
|
-
COPY package*.json ./
|
|
10
|
-
RUN if [ -f package-lock.json ]; then npm ci; else npm install; fi
|
|
11
|
-
|
|
12
|
-
# Build stage
|
|
13
|
-
FROM base AS builder
|
|
14
|
-
COPY --from=deps /app/node_modules ./node_modules
|
|
15
|
-
COPY . .
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
#
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
1
|
+
{{#if (eq framework 'nextjs')}}
|
|
2
|
+
# Base stage
|
|
3
|
+
FROM node:24-alpine AS base
|
|
4
|
+
WORKDIR /app
|
|
5
|
+
RUN apk add --no-cache libc6-compat
|
|
6
|
+
|
|
7
|
+
# Dependencies stage
|
|
8
|
+
FROM base AS deps
|
|
9
|
+
COPY package*.json ./
|
|
10
|
+
RUN if [ -f package-lock.json ]; then npm ci; else npm install; fi
|
|
11
|
+
|
|
12
|
+
# Build stage
|
|
13
|
+
FROM base AS builder
|
|
14
|
+
COPY --from=deps /app/node_modules ./node_modules
|
|
15
|
+
COPY . .
|
|
16
|
+
{{#if (eq database 'prisma')}}
|
|
17
|
+
RUN DATABASE_URL="postgresql://postgres:postgres@localhost:5432/postgres" npm run build
|
|
18
|
+
{{else if (eq database 'mongoose')}}
|
|
19
|
+
RUN MONGODB_URI="mongodb://localhost:27017/build" npm run build
|
|
20
|
+
{{else}}
|
|
21
|
+
RUN npm run build
|
|
22
|
+
{{/if}}
|
|
23
|
+
|
|
24
|
+
# Production stage
|
|
25
|
+
FROM node:24-alpine AS runner
|
|
26
|
+
WORKDIR /app
|
|
27
|
+
ENV NODE_ENV=production
|
|
28
|
+
|
|
29
|
+
RUN addgroup --system --gid 1001 nodejs && \
|
|
30
|
+
adduser --system --uid 1001 nextjs
|
|
31
|
+
|
|
32
|
+
COPY --from=builder /app/public ./public
|
|
33
|
+
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
|
34
|
+
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
|
35
|
+
|
|
36
|
+
USER nextjs
|
|
37
|
+
EXPOSE {{port}}
|
|
38
|
+
ENV PORT={{port}} HOSTNAME=0.0.0.0
|
|
39
|
+
|
|
40
|
+
CMD ["node", "server.js"]
|
|
41
|
+
|
|
42
|
+
{{else}}
|
|
43
|
+
# Build stage
|
|
44
|
+
FROM node:24-alpine AS builder
|
|
45
|
+
WORKDIR /app
|
|
46
|
+
|
|
47
|
+
COPY package*.json ./
|
|
48
|
+
RUN if [ -f package-lock.json ]; then npm ci; else npm install; fi
|
|
49
|
+
|
|
50
|
+
COPY . .
|
|
51
|
+
|
|
52
|
+
# Only build if package.json has a build script
|
|
53
|
+
{{#if (eq database 'prisma')}}
|
|
54
|
+
RUN DATABASE_URL="postgresql://postgres:postgres@localhost:5432/postgres" npm run build
|
|
55
|
+
{{else if (eq database 'mongoose')}}
|
|
56
|
+
RUN MONGODB_URI="mongodb://localhost:27017/build" npm run build
|
|
57
|
+
{{else}}
|
|
58
|
+
RUN npm run build
|
|
59
|
+
{{/if}}
|
|
60
|
+
|
|
61
|
+
# Production stage
|
|
62
|
+
FROM node:24-alpine
|
|
63
|
+
WORKDIR /app
|
|
64
|
+
ENV NODE_ENV=production
|
|
65
|
+
|
|
66
|
+
# Create non-root user for security
|
|
67
|
+
RUN addgroup --system --gid 1001 nodejs && \
|
|
68
|
+
adduser --system --uid 1001 expressuser
|
|
69
|
+
|
|
70
|
+
COPY package*.json ./
|
|
71
|
+
RUN if [ -f package-lock.json ]; then npm ci --omit=dev; else npm install --omit=dev; fi
|
|
72
|
+
|
|
73
|
+
# Copy built files (if TypeScript) or source files (if JavaScript)
|
|
74
|
+
COPY --from=builder --chown=expressuser:nodejs /app/dist ./dist
|
|
75
|
+
|
|
76
|
+
USER expressuser
|
|
77
|
+
EXPOSE {{port}}
|
|
78
|
+
ENV PORT={{port}}
|
|
79
|
+
|
|
80
|
+
CMD ["node", "dist/index.js"]
|
|
71
81
|
{{/if}}
|
|
@@ -1,16 +1,19 @@
|
|
|
1
|
-
{
|
|
2
|
-
"id": "docker",
|
|
3
|
-
"name": "Docker",
|
|
4
|
-
"description": "Docker containerization with multi-stage build and docker-compose",
|
|
5
|
-
"type": "feature",
|
|
6
|
-
"dependencies": {},
|
|
7
|
-
"devDependencies": {},
|
|
8
|
-
"scripts": {
|
|
9
|
-
"docker:build": "docker build -t {{projectName}} .",
|
|
10
|
-
"docker:up": "docker
|
|
11
|
-
"docker:down": "docker
|
|
12
|
-
"docker:logs": "docker
|
|
13
|
-
},
|
|
14
|
-
"envVars": {},
|
|
15
|
-
"templateFiles": [
|
|
16
|
-
|
|
1
|
+
{
|
|
2
|
+
"id": "docker",
|
|
3
|
+
"name": "Docker",
|
|
4
|
+
"description": "Docker containerization with multi-stage build and docker-compose",
|
|
5
|
+
"type": "feature",
|
|
6
|
+
"dependencies": {},
|
|
7
|
+
"devDependencies": {},
|
|
8
|
+
"scripts": {
|
|
9
|
+
"docker:build": "docker build -t {{projectName}} .",
|
|
10
|
+
"docker:up": "docker compose up -d",
|
|
11
|
+
"docker:down": "docker compose down",
|
|
12
|
+
"docker:logs": "docker compose logs -f"
|
|
13
|
+
},
|
|
14
|
+
"envVars": {},
|
|
15
|
+
"templateFiles": [
|
|
16
|
+
"docker-compose.yml.hbs",
|
|
17
|
+
"Dockerfile.hbs"
|
|
18
|
+
]
|
|
19
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
-
|
|
8
|
-
environment:
|
|
9
|
-
- NODE_ENV=production
|
|
1
|
+
services:
|
|
2
|
+
{{projectName}}:
|
|
3
|
+
build: .
|
|
4
|
+
ports:
|
|
5
|
+
- "{{port}}:{{port}}"
|
|
6
|
+
env_file:
|
|
7
|
+
- .env
|
|
8
|
+
environment:
|
|
9
|
+
- NODE_ENV=production
|
|
10
10
|
restart: unless-stopped
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "drizzle",
|
|
3
|
+
"name": "Drizzle ORM",
|
|
4
|
+
"description": "Drizzle ORM for Express with PostgreSQL",
|
|
5
|
+
"type": "database",
|
|
6
|
+
"dependencies": {
|
|
7
|
+
"drizzle-orm": "^0.45.2",
|
|
8
|
+
"pg": "^8.23.0",
|
|
9
|
+
"dotenv": "^17.4.2"
|
|
10
|
+
},
|
|
11
|
+
"devDependencies": {
|
|
12
|
+
"drizzle-kit": "^0.31.10",
|
|
13
|
+
"@types/pg": "^8.23.1"
|
|
14
|
+
},
|
|
15
|
+
"scripts": {
|
|
16
|
+
"db:generate": "drizzle-kit generate",
|
|
17
|
+
"db:migrate": "drizzle-kit migrate",
|
|
18
|
+
"db:studio": "drizzle-kit studio"
|
|
19
|
+
},
|
|
20
|
+
"envVars": {
|
|
21
|
+
"DATABASE_URL": "postgresql://user:password@localhost:5432/mydb?schema=public"
|
|
22
|
+
},
|
|
23
|
+
"templateFiles": [],
|
|
24
|
+
"overrides": {
|
|
25
|
+
"esbuild": "^0.28.2"
|
|
26
|
+
}
|
|
27
|
+
}
|