kybernus 2.0.10 → 2.1.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.
- package/node_modules/{@isaacs/balanced-match → balanced-match}/README.md +7 -10
- package/node_modules/{@isaacs/balanced-match → balanced-match}/package.json +5 -16
- package/node_modules/{@isaacs/brace-expansion → brace-expansion}/README.md +2 -5
- package/node_modules/{@isaacs/brace-expansion → brace-expansion}/dist/commonjs/index.js +1 -1
- package/node_modules/{@isaacs/brace-expansion → brace-expansion}/dist/commonjs/index.js.map +1 -1
- package/node_modules/{@isaacs/brace-expansion → brace-expansion}/dist/esm/index.js +1 -1
- package/node_modules/{@isaacs/brace-expansion → brace-expansion}/dist/esm/index.js.map +1 -1
- package/node_modules/{@isaacs/brace-expansion → brace-expansion}/package.json +9 -5
- package/node_modules/glob/dist/commonjs/glob.d.ts +8 -0
- package/node_modules/glob/dist/commonjs/glob.d.ts.map +1 -1
- package/node_modules/glob/dist/commonjs/glob.js +2 -1
- package/node_modules/glob/dist/commonjs/glob.js.map +1 -1
- package/node_modules/glob/dist/commonjs/index.min.js +4 -0
- package/node_modules/glob/dist/commonjs/index.min.js.map +7 -0
- package/node_modules/glob/dist/commonjs/pattern.d.ts +3 -0
- package/node_modules/glob/dist/commonjs/pattern.d.ts.map +1 -1
- package/node_modules/glob/dist/commonjs/pattern.js +4 -0
- package/node_modules/glob/dist/commonjs/pattern.js.map +1 -1
- package/node_modules/glob/dist/esm/glob.d.ts +8 -0
- package/node_modules/glob/dist/esm/glob.d.ts.map +1 -1
- package/node_modules/glob/dist/esm/glob.js +2 -1
- package/node_modules/glob/dist/esm/glob.js.map +1 -1
- package/node_modules/glob/dist/esm/index.min.js +4 -0
- package/node_modules/glob/dist/esm/index.min.js.map +7 -0
- package/node_modules/glob/dist/esm/pattern.d.ts +3 -0
- package/node_modules/glob/dist/esm/pattern.d.ts.map +1 -1
- package/node_modules/glob/dist/esm/pattern.js +4 -0
- package/node_modules/glob/dist/esm/pattern.js.map +1 -1
- package/node_modules/glob/package.json +30 -10
- package/node_modules/lru-cache/package.json +7 -7
- package/node_modules/minimatch/README.md +3 -1
- package/node_modules/minimatch/dist/commonjs/ast.d.ts.map +1 -1
- package/node_modules/minimatch/dist/commonjs/ast.js +37 -27
- package/node_modules/minimatch/dist/commonjs/ast.js.map +1 -1
- package/node_modules/minimatch/dist/commonjs/brace-expressions.d.ts.map +1 -1
- package/node_modules/minimatch/dist/commonjs/brace-expressions.js +2 -4
- package/node_modules/minimatch/dist/commonjs/brace-expressions.js.map +1 -1
- package/node_modules/minimatch/dist/commonjs/escape.js +4 -4
- package/node_modules/minimatch/dist/commonjs/escape.js.map +1 -1
- package/node_modules/minimatch/dist/commonjs/index.d.ts +50 -0
- package/node_modules/minimatch/dist/commonjs/index.d.ts.map +1 -1
- package/node_modules/minimatch/dist/commonjs/index.js +37 -31
- package/node_modules/minimatch/dist/commonjs/index.js.map +1 -1
- package/node_modules/minimatch/dist/commonjs/unescape.js +4 -4
- package/node_modules/minimatch/dist/commonjs/unescape.js.map +1 -1
- package/node_modules/minimatch/dist/esm/ast.d.ts.map +1 -1
- package/node_modules/minimatch/dist/esm/ast.js +37 -27
- package/node_modules/minimatch/dist/esm/ast.js.map +1 -1
- package/node_modules/minimatch/dist/esm/brace-expressions.d.ts.map +1 -1
- package/node_modules/minimatch/dist/esm/brace-expressions.js +2 -4
- package/node_modules/minimatch/dist/esm/brace-expressions.js.map +1 -1
- package/node_modules/minimatch/dist/esm/escape.js +4 -4
- package/node_modules/minimatch/dist/esm/escape.js.map +1 -1
- package/node_modules/minimatch/dist/esm/index.d.ts +50 -0
- package/node_modules/minimatch/dist/esm/index.d.ts.map +1 -1
- package/node_modules/minimatch/dist/esm/index.js +37 -31
- package/node_modules/minimatch/dist/esm/index.js.map +1 -1
- package/node_modules/minimatch/dist/esm/unescape.js +4 -4
- package/node_modules/minimatch/dist/esm/unescape.js.map +1 -1
- package/node_modules/minimatch/package.json +3 -3
- package/node_modules/minipass/LICENSE.md +55 -0
- package/node_modules/minipass/dist/commonjs/index.d.ts +12 -16
- package/node_modules/minipass/dist/commonjs/index.d.ts.map +1 -1
- package/node_modules/minipass/dist/commonjs/index.js +13 -3
- package/node_modules/minipass/dist/commonjs/index.js.map +1 -1
- package/node_modules/minipass/dist/esm/index.d.ts +12 -16
- package/node_modules/minipass/dist/esm/index.d.ts.map +1 -1
- package/node_modules/minipass/dist/esm/index.js +3 -1
- package/node_modules/minipass/dist/esm/index.js.map +1 -1
- package/node_modules/minipass/package.json +9 -14
- package/node_modules/rimraf/README.md +29 -0
- package/node_modules/rimraf/dist/commonjs/fs.d.ts +9 -8
- package/node_modules/rimraf/dist/commonjs/fs.d.ts.map +1 -1
- package/node_modules/rimraf/dist/commonjs/index.d.ts.map +1 -1
- package/node_modules/rimraf/dist/commonjs/index.js +9 -3
- package/node_modules/rimraf/dist/commonjs/index.js.map +1 -1
- package/node_modules/rimraf/dist/commonjs/opt-arg.d.ts.map +1 -1
- package/node_modules/rimraf/dist/commonjs/opt-arg.js +2 -1
- package/node_modules/rimraf/dist/commonjs/opt-arg.js.map +1 -1
- package/node_modules/rimraf/dist/commonjs/path-arg.d.ts.map +1 -1
- package/node_modules/rimraf/dist/commonjs/path-arg.js +2 -1
- package/node_modules/rimraf/dist/commonjs/path-arg.js.map +1 -1
- package/node_modules/rimraf/dist/commonjs/readdir-or-error.d.ts +2 -2
- package/node_modules/rimraf/dist/commonjs/readdir-or-error.d.ts.map +1 -1
- package/node_modules/rimraf/dist/commonjs/rimraf-move-remove.d.ts.map +1 -1
- package/node_modules/rimraf/dist/commonjs/rimraf-move-remove.js.map +1 -1
- package/node_modules/rimraf/dist/commonjs/rimraf-posix.d.ts.map +1 -1
- package/node_modules/rimraf/dist/commonjs/rimraf-posix.js +1 -2
- package/node_modules/rimraf/dist/commonjs/rimraf-posix.js.map +1 -1
- package/node_modules/rimraf/dist/commonjs/rimraf-windows.d.ts.map +1 -1
- package/node_modules/rimraf/dist/commonjs/rimraf-windows.js.map +1 -1
- package/node_modules/rimraf/dist/esm/bin.mjs.map +1 -1
- package/node_modules/rimraf/dist/esm/fs.d.ts +9 -8
- package/node_modules/rimraf/dist/esm/fs.d.ts.map +1 -1
- package/node_modules/rimraf/dist/esm/index.d.ts.map +1 -1
- package/node_modules/rimraf/dist/esm/index.js +10 -4
- package/node_modules/rimraf/dist/esm/index.js.map +1 -1
- package/node_modules/rimraf/dist/esm/opt-arg.d.ts.map +1 -1
- package/node_modules/rimraf/dist/esm/opt-arg.js +2 -1
- package/node_modules/rimraf/dist/esm/opt-arg.js.map +1 -1
- package/node_modules/rimraf/dist/esm/path-arg.d.ts.map +1 -1
- package/node_modules/rimraf/dist/esm/path-arg.js +2 -1
- package/node_modules/rimraf/dist/esm/path-arg.js.map +1 -1
- package/node_modules/rimraf/dist/esm/readdir-or-error.d.ts +2 -2
- package/node_modules/rimraf/dist/esm/readdir-or-error.d.ts.map +1 -1
- package/node_modules/rimraf/dist/esm/rimraf-move-remove.d.ts.map +1 -1
- package/node_modules/rimraf/dist/esm/rimraf-move-remove.js +1 -1
- package/node_modules/rimraf/dist/esm/rimraf-move-remove.js.map +1 -1
- package/node_modules/rimraf/dist/esm/rimraf-posix.d.ts.map +1 -1
- package/node_modules/rimraf/dist/esm/rimraf-posix.js +1 -2
- package/node_modules/rimraf/dist/esm/rimraf-posix.js.map +1 -1
- package/node_modules/rimraf/dist/esm/rimraf-windows.d.ts.map +1 -1
- package/node_modules/rimraf/dist/esm/rimraf-windows.js +1 -1
- package/node_modules/rimraf/dist/esm/rimraf-windows.js.map +1 -1
- package/node_modules/rimraf/package.json +4 -19
- package/package.json +1 -1
- package/templates/java-spring/clean/src/main/java/{{packagePath}}/infrastructure/persistence/PostgresUserRepository.java.hbs +40 -0
- package/templates/java-spring/clean/src/main/resources/application.properties.hbs +18 -0
- package/templates/java-spring/hexagonal/src/main/java/{{packagePath}}/{infrastructure/web/controller → adapters/inbound/web}/AuthController.java.hbs +4 -5
- package/templates/java-spring/hexagonal/src/main/java/{{packagePath}}/adapters/outbound/persistence/JpaUserAdapter.java.hbs +40 -0
- package/templates/java-spring/hexagonal/src/main/java/{{packagePath}}/adapters/outbound/persistence/entity/UserEntity.java.hbs +61 -0
- package/templates/java-spring/hexagonal/src/main/java/{{packagePath}}/adapters/outbound/persistence/repository/JpaUserRepository.java.hbs +11 -0
- package/templates/java-spring/hexagonal/src/main/java/{{packagePath}}/{infrastructure/security/SecurityAdapters.java.hbs → adapters/outbound/security/SecurityAdapter.java.hbs} +14 -14
- package/templates/java-spring/hexagonal/src/main/java/{{packagePath}}/{domain/entity → core/domain}/User.java.hbs +2 -2
- package/templates/java-spring/hexagonal/src/main/java/{{packagePath}}/{domain/usecase → core/ports/inbound}/LoginUserUseCase.java.hbs +8 -8
- package/templates/java-spring/hexagonal/src/main/java/{{packagePath}}/{domain/usecase → core/ports/inbound}/RegisterUserUseCase.java.hbs +7 -8
- package/templates/java-spring/hexagonal/src/main/java/{{packagePath}}/{domain/repository → core/ports/outbound}/UserRepository.java.hbs +4 -4
- package/templates/java-spring/hexagonal/src/main/java/{{packagePath}}/{application → core}/service/AuthService.java.hbs +9 -9
- package/templates/java-spring/hexagonal/src/main/java/{{packagePath}}/{{projectNamePascalCase}}Application.java.hbs +2 -2
- package/templates/java-spring/hexagonal/src/main/resources/application.properties.hbs +18 -0
- package/templates/nestjs/clean/package.json.hbs +9 -3
- package/templates/nestjs/clean/prisma/schema.prisma.hbs +20 -0
- package/templates/nestjs/clean/src/app.module.ts.hbs +17 -0
- package/templates/nestjs/clean/src/auth.module.ts.hbs +12 -10
- package/templates/nestjs/clean/src/infrastructure/database/prisma.service.ts.hbs +13 -0
- package/templates/nestjs/clean/src/infrastructure/database/repositories/prisma.user.repository.ts.hbs +32 -0
- package/templates/nestjs/clean/src/main.ts.hbs +11 -0
- package/templates/nestjs/hexagonal/package.json.hbs +9 -3
- package/templates/nestjs/hexagonal/prisma/schema.prisma +20 -0
- package/templates/nestjs/hexagonal/src/adapters/outbound/persistence/prisma.service.ts.hbs +13 -0
- package/templates/nestjs/hexagonal/src/adapters/outbound/persistence/prisma.user.adapter.ts.hbs +32 -0
- package/templates/nestjs/hexagonal/src/app.module.ts.hbs +17 -0
- package/templates/nestjs/hexagonal/src/auth.module.ts.hbs +15 -13
- package/templates/nestjs/hexagonal/src/main.ts.hbs +11 -0
- package/templates/nextjs/mvc/package.json.hbs +35 -32
- package/templates/nextjs/mvc/prisma/schema.prisma.hbs +12 -9
- package/templates/nextjs/mvc/src/lib/db.ts +15 -0
- package/templates/nodejs-express/clean/docker-compose.yml.hbs +5 -6
- package/templates/nodejs-express/clean/package.json.hbs +14 -8
- package/templates/nodejs-express/clean/prisma/schema.prisma +20 -0
- package/templates/nodejs-express/clean/src/config/index.ts +27 -0
- package/templates/nodejs-express/clean/src/index.ts.hbs +20 -24
- package/templates/nodejs-express/clean/src/infrastructure/database/PrismaUserRepository.ts.hbs +61 -0
- package/templates/nodejs-express/clean/src/infrastructure/database/prisma.ts.hbs +5 -0
- package/templates/nodejs-express/clean/src/infrastructure/http/controllers/AuthController.ts.hbs +24 -40
- package/templates/nodejs-express/clean/src/infrastructure/http/middlewares/errorHandler.ts +24 -0
- package/templates/nodejs-express/clean/tsconfig.json.hbs +8 -17
- package/templates/nodejs-express/hexagonal/docker-compose.yml.hbs +5 -6
- package/templates/nodejs-express/hexagonal/package.json.hbs +14 -8
- package/templates/nodejs-express/hexagonal/prisma/schema.prisma +20 -0
- package/templates/nodejs-express/hexagonal/src/adapters/inbound/http/AuthController.ts.hbs +29 -44
- package/templates/nodejs-express/hexagonal/src/adapters/inbound/http/middlewares/errorHandler.ts +24 -0
- package/templates/nodejs-express/hexagonal/src/adapters/outbound/persistence/PrismaUserAdapter.ts.hbs +61 -0
- package/templates/nodejs-express/hexagonal/src/adapters/outbound/persistence/prisma.ts +5 -0
- package/templates/nodejs-express/hexagonal/src/config/index.ts +27 -0
- package/templates/nodejs-express/hexagonal/src/index.ts.hbs +24 -27
- package/templates/nodejs-express/hexagonal/tsconfig.json.hbs +8 -17
- package/templates/python-fastapi/clean/app/application/services/__init__.py +0 -0
- package/templates/python-fastapi/clean/app/application/services/user_service.py.hbs +20 -0
- package/templates/python-fastapi/clean/app/config.py.hbs +24 -0
- package/templates/python-fastapi/clean/app/infrastructure/database/models.py.hbs +24 -0
- package/templates/python-fastapi/clean/app/infrastructure/database/postgres_repository.py.hbs +62 -0
- package/templates/python-fastapi/clean/app/infrastructure/database/session.py.hbs +27 -0
- package/templates/python-fastapi/clean/app/infrastructure/http/auth_controller.py.hbs +14 -8
- package/templates/python-fastapi/clean/app/main.py.hbs +25 -3
- package/templates/python-fastapi/clean/requirements.txt.hbs +3 -1
- package/templates/python-fastapi/hexagonal/app/adapters/inbound/http_adapter.py.hbs +41 -17
- package/templates/python-fastapi/hexagonal/app/adapters/outbound/postgres_user_repository.py.hbs +50 -0
- package/templates/python-fastapi/hexagonal/app/config.py.hbs +20 -0
- package/templates/python-fastapi/hexagonal/app/infrastructure/database/models.py.hbs +24 -0
- package/templates/python-fastapi/hexagonal/app/infrastructure/database/session.py.hbs +20 -0
- package/templates/python-fastapi/hexagonal/app/main.py.hbs +22 -14
- package/templates/python-fastapi/hexagonal/requirements.txt.hbs +3 -1
- package/node_modules/minipass/LICENSE +0 -15
- package/templates/java-spring/clean/src/main/java/{{packagePath}}/infrastructure/persistence/InMemoryUserRepository.java.hbs +0 -41
- package/templates/java-spring/hexagonal/src/main/java/{{packagePath}}/infrastructure/persistence/InMemoryUserRepository.java.hbs +0 -41
- package/templates/nestjs/clean/src/infrastructure/database/in-memory.repository.ts.hbs +0 -17
- package/templates/nodejs-express/clean/src/infrastructure/database/InMemoryUserRepository.ts.hbs +0 -46
- package/templates/nodejs-express/hexagonal/src/adapters/outbound/persistence/InMemoryUserAdapter.ts.hbs +0 -38
- /package/node_modules/{@isaacs/balanced-match → balanced-match}/LICENSE.md +0 -0
- /package/node_modules/{@isaacs/balanced-match → balanced-match}/dist/commonjs/index.d.ts +0 -0
- /package/node_modules/{@isaacs/balanced-match → balanced-match}/dist/commonjs/index.d.ts.map +0 -0
- /package/node_modules/{@isaacs/balanced-match → balanced-match}/dist/commonjs/index.js +0 -0
- /package/node_modules/{@isaacs/balanced-match → balanced-match}/dist/commonjs/index.js.map +0 -0
- /package/node_modules/{@isaacs/balanced-match → balanced-match}/dist/commonjs/package.json +0 -0
- /package/node_modules/{@isaacs/balanced-match → balanced-match}/dist/esm/index.d.ts +0 -0
- /package/node_modules/{@isaacs/balanced-match → balanced-match}/dist/esm/index.d.ts.map +0 -0
- /package/node_modules/{@isaacs/balanced-match → balanced-match}/dist/esm/index.js +0 -0
- /package/node_modules/{@isaacs/balanced-match → balanced-match}/dist/esm/index.js.map +0 -0
- /package/node_modules/{@isaacs/balanced-match → balanced-match}/dist/esm/package.json +0 -0
- /package/node_modules/{@isaacs/brace-expansion → brace-expansion}/LICENSE +0 -0
- /package/node_modules/{@isaacs/brace-expansion → brace-expansion}/dist/commonjs/index.d.ts +0 -0
- /package/node_modules/{@isaacs/brace-expansion → brace-expansion}/dist/commonjs/index.d.ts.map +0 -0
- /package/node_modules/{@isaacs/brace-expansion → brace-expansion}/dist/commonjs/package.json +0 -0
- /package/node_modules/{@isaacs/brace-expansion → brace-expansion}/dist/esm/index.d.ts +0 -0
- /package/node_modules/{@isaacs/brace-expansion → brace-expansion}/dist/esm/index.d.ts.map +0 -0
- /package/node_modules/{@isaacs/brace-expansion → brace-expansion}/dist/esm/package.json +0 -0
- /package/templates/python-fastapi/hexagonal/app/core/{ports.py.hbs → ports/ports.py.hbs} +0 -0
|
@@ -9,16 +9,18 @@
|
|
|
9
9
|
"start": "node dist/index.js",
|
|
10
10
|
"lint": "eslint src --ext .ts",
|
|
11
11
|
"format": "prettier --write \"src/**/*.ts\"",
|
|
12
|
-
"test": "jest"
|
|
12
|
+
"test": "jest",
|
|
13
|
+
"migrate:dev": "prisma migrate dev",
|
|
14
|
+
"migrate:deploy": "prisma migrate deploy",
|
|
15
|
+
"generate": "prisma generate"
|
|
13
16
|
},
|
|
14
17
|
"keywords": [
|
|
15
18
|
"express",
|
|
16
19
|
"api",
|
|
17
20
|
"typescript",
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"auth"
|
|
21
|
+
"clean-architecture",
|
|
22
|
+
"prisma",
|
|
23
|
+
"zod"
|
|
22
24
|
],
|
|
23
25
|
"author": "",
|
|
24
26
|
"license": "MIT",
|
|
@@ -30,7 +32,10 @@
|
|
|
30
32
|
"morgan": "^1.10.0",
|
|
31
33
|
"jsonwebtoken": "^9.0.2",
|
|
32
34
|
"bcryptjs": "^2.4.3",
|
|
33
|
-
"stripe": "^14.14.0"
|
|
35
|
+
"stripe": "^14.14.0",
|
|
36
|
+
"zod": "^3.22.4",
|
|
37
|
+
"express-async-errors": "^3.1.1",
|
|
38
|
+
"@prisma/client": "^5.10.2"
|
|
34
39
|
},
|
|
35
40
|
"devDependencies": {
|
|
36
41
|
"@types/express": "^4.17.21",
|
|
@@ -47,9 +52,10 @@
|
|
|
47
52
|
"@typescript-eslint/parser": "^6.21.0",
|
|
48
53
|
"prettier": "^3.2.5",
|
|
49
54
|
"jest": "^29.7.0",
|
|
50
|
-
"@types/jest": "^29.5.12"
|
|
55
|
+
"@types/jest": "^29.5.12",
|
|
56
|
+
"prisma": "^5.10.2"
|
|
51
57
|
},
|
|
52
58
|
"engines": {
|
|
53
59
|
"node": ">=18.0.0"
|
|
54
60
|
}
|
|
55
|
-
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
generator client {
|
|
2
|
+
provider = "prisma-client-js"
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
datasource db {
|
|
6
|
+
provider = "postgresql"
|
|
7
|
+
url = env("DATABASE_URL")
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
model User {
|
|
11
|
+
id String @id @default(uuid())
|
|
12
|
+
email String @unique
|
|
13
|
+
name String
|
|
14
|
+
password String
|
|
15
|
+
stripeCustomerId String? @map("stripe_customer_id")
|
|
16
|
+
createdAt DateTime @default(now()) @map("created_at")
|
|
17
|
+
updatedAt DateTime @updatedAt @map("updated_at")
|
|
18
|
+
|
|
19
|
+
@@map("users")
|
|
20
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import dotenv from 'dotenv';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
|
|
4
|
+
dotenv.config();
|
|
5
|
+
|
|
6
|
+
const envSchema = z.object({
|
|
7
|
+
NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),
|
|
8
|
+
PORT: z.string().default('3000'),
|
|
9
|
+
DATABASE_URL: z.string(),
|
|
10
|
+
JWT_SECRET: z.string().min(10),
|
|
11
|
+
STRIPE_SECRET_KEY: z.string().optional(),
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
const _env = envSchema.safeParse(process.env);
|
|
15
|
+
|
|
16
|
+
if (!_env.success) {
|
|
17
|
+
console.error('❌ Invalid environment variables:', _env.error.format());
|
|
18
|
+
throw new Error('Invalid environment variables');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const config = {
|
|
22
|
+
env: _env.data.NODE_ENV,
|
|
23
|
+
port: parseInt(_env.data.PORT, 10),
|
|
24
|
+
databaseUrl: _env.data.DATABASE_URL,
|
|
25
|
+
jwtSecret: _env.data.JWT_SECRET,
|
|
26
|
+
stripeSecretKey: _env.data.STRIPE_SECRET_KEY,
|
|
27
|
+
};
|
|
@@ -1,40 +1,36 @@
|
|
|
1
|
+
import 'express-async-errors';
|
|
1
2
|
import express from 'express';
|
|
2
3
|
import cors from 'cors';
|
|
3
4
|
import helmet from 'helmet';
|
|
4
5
|
import morgan from 'morgan';
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
import
|
|
8
|
-
|
|
9
|
-
dotenv.config();
|
|
6
|
+
import { config } from './config';
|
|
7
|
+
import { PrismaUserRepository } from './infrastructure/database/PrismaUserRepository';
|
|
8
|
+
import { AuthController } from './infrastructure/http/controllers/AuthController';
|
|
9
|
+
import { errorHandler } from './infrastructure/http/middlewares/errorHandler';
|
|
10
10
|
|
|
11
11
|
const app = express();
|
|
12
12
|
|
|
13
|
-
//
|
|
14
|
-
app.use(
|
|
13
|
+
// Middlewares
|
|
14
|
+
app.use(express.json());
|
|
15
15
|
app.use(cors());
|
|
16
|
+
app.use(helmet());
|
|
16
17
|
app.use(morgan('dev'));
|
|
17
18
|
|
|
18
|
-
//
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
// Health check
|
|
23
|
-
app.get('/health', (_, res) => res.json({ status: 'ok' }));
|
|
19
|
+
// Dependency Injection
|
|
20
|
+
const userRepository = new PrismaUserRepository();
|
|
21
|
+
const authController = new AuthController(userRepository);
|
|
24
22
|
|
|
25
23
|
// Routes
|
|
26
|
-
app.
|
|
24
|
+
app.post('/api/auth/register', authController.register);
|
|
25
|
+
app.post('/api/auth/login', authController.login);
|
|
27
26
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
console.error(err.stack);
|
|
31
|
-
res.status(500).json({ error: 'Internal server error' });
|
|
27
|
+
app.get('/health', (req, res) => {
|
|
28
|
+
res.json({ status: 'ok', architecture: 'clean' });
|
|
32
29
|
});
|
|
33
30
|
|
|
34
|
-
|
|
31
|
+
// Error Handler
|
|
32
|
+
app.use(errorHandler);
|
|
35
33
|
|
|
36
|
-
app.listen(
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
console.log(`🔗 Health check: http://localhost:${PORT}/health`);
|
|
40
|
-
});
|
|
34
|
+
app.listen(config.port, () => {
|
|
35
|
+
console.log(`🚀 Server running on port ${config.port}`);
|
|
36
|
+
});
|
package/templates/nodejs-express/clean/src/infrastructure/database/PrismaUserRepository.ts.hbs
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { IUserRepository } from '../../domain/repositories/IUserRepository';
|
|
2
|
+
import { User } from '../../domain/entities/User';
|
|
3
|
+
import { prisma } from './prisma';
|
|
4
|
+
|
|
5
|
+
export class PrismaUserRepository implements IUserRepository {
|
|
6
|
+
async findById(id: string): Promise<User | null> {
|
|
7
|
+
const user = await prisma.user.findUnique({ where: { id } });
|
|
8
|
+
if (!user) return null;
|
|
9
|
+
return User.restore({
|
|
10
|
+
id: user.id,
|
|
11
|
+
email: user.email,
|
|
12
|
+
name: user.name,
|
|
13
|
+
password: user.password,
|
|
14
|
+
stripeCustomerId: user.stripeCustomerId,
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async findByEmail(email: string): Promise<User | null> {
|
|
19
|
+
const user = await prisma.user.findUnique({ where: { email } });
|
|
20
|
+
if (!user) return null;
|
|
21
|
+
return User.restore({
|
|
22
|
+
id: user.id,
|
|
23
|
+
email: user.email,
|
|
24
|
+
name: user.name,
|
|
25
|
+
password: user.password,
|
|
26
|
+
stripeCustomerId: user.stripeCustomerId,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async save(user: User): Promise<User> {
|
|
31
|
+
const data = {
|
|
32
|
+
id: user.id,
|
|
33
|
+
email: user.email,
|
|
34
|
+
name: user.name,
|
|
35
|
+
password: user.password,
|
|
36
|
+
stripeCustomerId: user.stripeCustomerId,
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const savedUser = await prisma.user.upsert({
|
|
40
|
+
where: { id: user.id || '' },
|
|
41
|
+
update: { ...data },
|
|
42
|
+
create: { ...data },
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
return User.restore({
|
|
46
|
+
id: savedUser.id,
|
|
47
|
+
email: savedUser.email,
|
|
48
|
+
name: savedUser.name,
|
|
49
|
+
password: savedUser.password,
|
|
50
|
+
stripeCustomerId: savedUser.stripeCustomerId,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async update(user: User): Promise<User> {
|
|
55
|
+
return this.save(user);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async delete(id: string): Promise<void> {
|
|
59
|
+
await prisma.user.delete({ where: { id } });
|
|
60
|
+
}
|
|
61
|
+
}
|
package/templates/nodejs-express/clean/src/infrastructure/http/controllers/AuthController.ts.hbs
CHANGED
|
@@ -1,45 +1,29 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { jwtTokenGenerator } from '../../providers/TokenGenerator';
|
|
6
|
-
import { authMiddleware, AuthRequest } from '../middlewares/AuthMiddleware';
|
|
1
|
+
import { Request, Response } from 'express';
|
|
2
|
+
import { RegisterUserUseCase } from '../../../domain/usecases/RegisterUserUseCase';
|
|
3
|
+
import { LoginUserUseCase } from '../../../domain/usecases/LoginUserUseCase';
|
|
4
|
+
import { z } from 'zod';
|
|
7
5
|
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const authService = new AuthService(userRepository, bcryptPasswordHasher, jwtTokenGenerator);
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* @route POST /api/auth/register
|
|
16
|
-
*/
|
|
17
|
-
router.post('/register', async (req: Request, res: Response) => {
|
|
18
|
-
try {
|
|
19
|
-
const result = await authService.register(req.body);
|
|
20
|
-
res.status(201).json(result);
|
|
21
|
-
} catch (error: any) {
|
|
22
|
-
res.status(400).json({ error: error.message });
|
|
23
|
-
}
|
|
6
|
+
const registerSchema = z.object({
|
|
7
|
+
email: z.string().email(),
|
|
8
|
+
name: z.string().min(2),
|
|
9
|
+
password: z.string().min(6),
|
|
24
10
|
});
|
|
25
11
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const result = await authService.login(req.body);
|
|
32
|
-
res.json(result);
|
|
33
|
-
} catch (error: any) {
|
|
34
|
-
res.status(401).json({ error: error.message });
|
|
35
|
-
}
|
|
36
|
-
});
|
|
12
|
+
export class AuthController {
|
|
13
|
+
constructor(
|
|
14
|
+
private registerUseCase: RegisterUserUseCase,
|
|
15
|
+
private loginUseCase: LoginUserUseCase
|
|
16
|
+
) {}
|
|
37
17
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
});
|
|
18
|
+
register = async (req: Request, res: Response) => {
|
|
19
|
+
const { email, name, password } = registerSchema.parse(req.body);
|
|
20
|
+
const result = await this.registerUseCase.execute({ email, name, password });
|
|
21
|
+
res.status(201).json(result);
|
|
22
|
+
};
|
|
44
23
|
|
|
45
|
-
|
|
24
|
+
login = async (req: Request, res: Response) => {
|
|
25
|
+
const { email, password } = req.body;
|
|
26
|
+
const result = await this.loginUseCase.execute({ email, password });
|
|
27
|
+
res.json(result);
|
|
28
|
+
};
|
|
29
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Request, Response, NextFunction } from 'express';
|
|
2
|
+
import { ZodError } from 'zod';
|
|
3
|
+
|
|
4
|
+
export function errorHandler(
|
|
5
|
+
err: Error,
|
|
6
|
+
req: Request,
|
|
7
|
+
res: Response,
|
|
8
|
+
next: NextFunction
|
|
9
|
+
) {
|
|
10
|
+
console.error(err);
|
|
11
|
+
|
|
12
|
+
if (err instanceof ZodError) {
|
|
13
|
+
return res.status(400).json({
|
|
14
|
+
error: 'Validation Error',
|
|
15
|
+
details: err.format(),
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (err.message === 'User already exists' || err.message === 'Invalid credentials') {
|
|
20
|
+
return res.status(400).json({ error: err.message });
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
res.status(500).json({ error: 'Internal Server Error' });
|
|
24
|
+
}
|
|
@@ -1,27 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"compilerOptions": {
|
|
3
|
-
"target": "
|
|
3
|
+
"target": "es2020",
|
|
4
4
|
"module": "commonjs",
|
|
5
|
-
"lib": [
|
|
6
|
-
"ES2022"
|
|
7
|
-
],
|
|
5
|
+
"lib": ["es2020"],
|
|
8
6
|
"outDir": "./dist",
|
|
9
7
|
"rootDir": "./src",
|
|
10
8
|
"strict": true,
|
|
11
9
|
"esModuleInterop": true,
|
|
12
10
|
"skipLibCheck": true,
|
|
13
11
|
"forceConsistentCasingInFileNames": true,
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"node"
|
|
18
|
-
]
|
|
12
|
+
"experimentalDecorators": true,
|
|
13
|
+
"emitDecoratorMetadata": true,
|
|
14
|
+
"resolveJsonModule": true
|
|
19
15
|
},
|
|
20
|
-
"include": [
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
"exclude": [
|
|
24
|
-
"node_modules",
|
|
25
|
-
"dist"
|
|
26
|
-
]
|
|
27
|
-
}
|
|
16
|
+
"include": ["src/**/*"],
|
|
17
|
+
"exclude": ["node_modules", "**/*.spec.ts", "**/*.test.ts"]
|
|
18
|
+
}
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
version: '3.8'
|
|
2
2
|
|
|
3
3
|
services:
|
|
4
|
-
|
|
4
|
+
db:
|
|
5
5
|
image: postgres:15-alpine
|
|
6
|
-
|
|
6
|
+
restart: always
|
|
7
7
|
environment:
|
|
8
8
|
POSTGRES_USER: postgres
|
|
9
|
-
POSTGRES_PASSWORD:
|
|
10
|
-
POSTGRES_DB: {{
|
|
9
|
+
POSTGRES_PASSWORD: password
|
|
10
|
+
POSTGRES_DB: {{kebabCase projectName}}_db
|
|
11
11
|
ports:
|
|
12
|
-
-
|
|
12
|
+
- '5432:5432'
|
|
13
13
|
volumes:
|
|
14
14
|
- postgres_data:/var/lib/postgresql/data
|
|
15
|
-
restart: unless-stopped
|
|
16
15
|
|
|
17
16
|
volumes:
|
|
18
17
|
postgres_data:
|
|
@@ -9,16 +9,18 @@
|
|
|
9
9
|
"start": "node dist/index.js",
|
|
10
10
|
"lint": "eslint src --ext .ts",
|
|
11
11
|
"format": "prettier --write \"src/**/*.ts\"",
|
|
12
|
-
"test": "jest"
|
|
12
|
+
"test": "jest",
|
|
13
|
+
"migrate:dev": "prisma migrate dev",
|
|
14
|
+
"migrate:deploy": "prisma migrate deploy",
|
|
15
|
+
"generate": "prisma generate"
|
|
13
16
|
},
|
|
14
17
|
"keywords": [
|
|
15
18
|
"express",
|
|
16
19
|
"api",
|
|
17
20
|
"typescript",
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"auth"
|
|
21
|
+
"hexagonal-architecture",
|
|
22
|
+
"prisma",
|
|
23
|
+
"zod"
|
|
22
24
|
],
|
|
23
25
|
"author": "",
|
|
24
26
|
"license": "MIT",
|
|
@@ -30,7 +32,10 @@
|
|
|
30
32
|
"morgan": "^1.10.0",
|
|
31
33
|
"jsonwebtoken": "^9.0.2",
|
|
32
34
|
"bcryptjs": "^2.4.3",
|
|
33
|
-
"stripe": "^14.14.0"
|
|
35
|
+
"stripe": "^14.14.0",
|
|
36
|
+
"zod": "^3.22.4",
|
|
37
|
+
"express-async-errors": "^3.1.1",
|
|
38
|
+
"@prisma/client": "^5.10.2"
|
|
34
39
|
},
|
|
35
40
|
"devDependencies": {
|
|
36
41
|
"@types/express": "^4.17.21",
|
|
@@ -47,9 +52,10 @@
|
|
|
47
52
|
"@typescript-eslint/parser": "^6.21.0",
|
|
48
53
|
"prettier": "^3.2.5",
|
|
49
54
|
"jest": "^29.7.0",
|
|
50
|
-
"@types/jest": "^29.5.12"
|
|
55
|
+
"@types/jest": "^29.5.12",
|
|
56
|
+
"prisma": "^5.10.2"
|
|
51
57
|
},
|
|
52
58
|
"engines": {
|
|
53
59
|
"node": ">=18.0.0"
|
|
54
60
|
}
|
|
55
|
-
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
generator client {
|
|
2
|
+
provider = "prisma-client-js"
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
datasource db {
|
|
6
|
+
provider = "postgresql"
|
|
7
|
+
url = env("DATABASE_URL")
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
model User {
|
|
11
|
+
id String @id @default(uuid())
|
|
12
|
+
email String @unique
|
|
13
|
+
name String
|
|
14
|
+
password String
|
|
15
|
+
stripeCustomerId String? @map("stripe_customer_id")
|
|
16
|
+
createdAt DateTime @default(now()) @map("created_at")
|
|
17
|
+
updatedAt DateTime @updatedAt @map("updated_at")
|
|
18
|
+
|
|
19
|
+
@@map("users")
|
|
20
|
+
}
|
|
@@ -1,48 +1,33 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { Request, Response, NextFunction } from 'express';
|
|
2
|
+
import { IAuthService } from '../../../core/ports/inbound/IAuthService';
|
|
3
|
+
import { z } from 'zod';
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const router = Router();
|
|
5
|
+
const registerSchema = z.object({
|
|
6
|
+
email: z.string().email(),
|
|
7
|
+
name: z.string().min(2),
|
|
8
|
+
password: z.string().min(6),
|
|
9
|
+
});
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const { email, name, password } = req.body;
|
|
14
|
-
const result = await authService.register(email, name, password);
|
|
15
|
-
res.status(201).json({
|
|
16
|
-
token: result.token,
|
|
17
|
-
user: { id: result.user.id, email: result.user.email, name: result.user.name },
|
|
18
|
-
});
|
|
19
|
-
} catch (error: any) {
|
|
20
|
-
res.status(400).json({ error: error.message });
|
|
21
|
-
}
|
|
22
|
-
});
|
|
11
|
+
export class AuthController {
|
|
12
|
+
constructor(private authService: IAuthService) {}
|
|
23
13
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
res.status(401).json({ error: error.message });
|
|
34
|
-
}
|
|
35
|
-
});
|
|
14
|
+
register = async (req: Request, res: Response, next: NextFunction) => {
|
|
15
|
+
try {
|
|
16
|
+
const { email, name, password } = registerSchema.parse(req.body);
|
|
17
|
+
const result = await this.authService.register(email, name, password);
|
|
18
|
+
res.status(201).json(result);
|
|
19
|
+
} catch (error) {
|
|
20
|
+
next(error);
|
|
21
|
+
}
|
|
22
|
+
};
|
|
36
23
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
return router;
|
|
48
|
-
}
|
|
24
|
+
login = async (req: Request, res: Response, next: NextFunction) => {
|
|
25
|
+
try {
|
|
26
|
+
const { email, password } = req.body;
|
|
27
|
+
const result = await this.authService.login(email, password);
|
|
28
|
+
res.json(result);
|
|
29
|
+
} catch (error) {
|
|
30
|
+
next(error);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
}
|
package/templates/nodejs-express/hexagonal/src/adapters/inbound/http/middlewares/errorHandler.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Request, Response, NextFunction } from 'express';
|
|
2
|
+
import { ZodError } from 'zod';
|
|
3
|
+
|
|
4
|
+
export function errorHandler(
|
|
5
|
+
err: Error,
|
|
6
|
+
req: Request,
|
|
7
|
+
res: Response,
|
|
8
|
+
next: NextFunction
|
|
9
|
+
) {
|
|
10
|
+
console.error(err);
|
|
11
|
+
|
|
12
|
+
if (err instanceof ZodError) {
|
|
13
|
+
return res.status(400).json({
|
|
14
|
+
error: 'Validation Error',
|
|
15
|
+
details: err.format(),
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (err.message === 'User already exists' || err.message === 'Invalid credentials') {
|
|
20
|
+
return res.status(400).json({ error: err.message });
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
res.status(500).json({ error: 'Internal Server Error' });
|
|
24
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { User } from '../../../core/domain/entities/User';
|
|
2
|
+
import { IUserRepositoryPort } from '../../../core/ports/outbound/IUserRepositoryPort';
|
|
3
|
+
import { prisma } from './prisma';
|
|
4
|
+
|
|
5
|
+
export class PrismaUserAdapter implements IUserRepositoryPort {
|
|
6
|
+
async findById(id: string): Promise<User | null> {
|
|
7
|
+
const user = await prisma.user.findUnique({ where: { id } });
|
|
8
|
+
if (!user) return null;
|
|
9
|
+
return User.restore({
|
|
10
|
+
id: user.id,
|
|
11
|
+
email: user.email,
|
|
12
|
+
name: user.name,
|
|
13
|
+
password: user.password,
|
|
14
|
+
stripeCustomerId: user.stripeCustomerId,
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async findByEmail(email: string): Promise<User | null> {
|
|
19
|
+
const user = await prisma.user.findUnique({ where: { email } });
|
|
20
|
+
if (!user) return null;
|
|
21
|
+
return User.restore({
|
|
22
|
+
id: user.id,
|
|
23
|
+
email: user.email,
|
|
24
|
+
name: user.name,
|
|
25
|
+
password: user.password,
|
|
26
|
+
stripeCustomerId: user.stripeCustomerId,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async save(user: User): Promise<User> {
|
|
31
|
+
const data = {
|
|
32
|
+
id: user.id,
|
|
33
|
+
email: user.email,
|
|
34
|
+
name: user.name,
|
|
35
|
+
password: user.password,
|
|
36
|
+
stripeCustomerId: user.stripeCustomerId,
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const savedUser = await prisma.user.upsert({
|
|
40
|
+
where: { id: user.id || '' },
|
|
41
|
+
update: { ...data },
|
|
42
|
+
create: { ...data },
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
return User.restore({
|
|
46
|
+
id: savedUser.id,
|
|
47
|
+
email: savedUser.email,
|
|
48
|
+
name: savedUser.name,
|
|
49
|
+
password: savedUser.password,
|
|
50
|
+
stripeCustomerId: savedUser.stripeCustomerId,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async update(user: User): Promise<User> {
|
|
55
|
+
return this.save(user);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async delete(id: string): Promise<void> {
|
|
59
|
+
await prisma.user.delete({ where: { id } });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import dotenv from 'dotenv';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
|
|
4
|
+
dotenv.config();
|
|
5
|
+
|
|
6
|
+
const envSchema = z.object({
|
|
7
|
+
NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),
|
|
8
|
+
PORT: z.string().default('3000'),
|
|
9
|
+
DATABASE_URL: z.string(),
|
|
10
|
+
JWT_SECRET: z.string().min(10),
|
|
11
|
+
STRIPE_SECRET_KEY: z.string().optional(),
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
const _env = envSchema.safeParse(process.env);
|
|
15
|
+
|
|
16
|
+
if (!_env.success) {
|
|
17
|
+
console.error('❌ Invalid environment variables:', _env.error.format());
|
|
18
|
+
throw new Error('Invalid environment variables');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const config = {
|
|
22
|
+
env: _env.data.NODE_ENV,
|
|
23
|
+
port: parseInt(_env.data.PORT, 10),
|
|
24
|
+
databaseUrl: _env.data.DATABASE_URL,
|
|
25
|
+
jwtSecret: _env.data.JWT_SECRET,
|
|
26
|
+
stripeSecretKey: _env.data.STRIPE_SECRET_KEY,
|
|
27
|
+
};
|