@kuldi/create-nestjs 1.0.1 โ 1.1.0
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 +27 -0
- package/package.json +13 -3
- package/src/cli.js +139 -0
- package/template/.editorconfig +12 -0
- package/template/.env.example +23 -0
- package/template/.eslintrc.js +25 -0
- package/template/.prettierrc +8 -0
- package/template/README.md +133 -0
- package/template/nest-cli.json +10 -0
- package/template/package-lock.json +11539 -0
- package/template/package.json +99 -0
- package/template/prisma/migrations/20260625045841_init/migration.sql +73 -0
- package/template/prisma/migrations/migration_lock.toml +3 -0
- package/template/prisma/schema.prisma +75 -0
- package/template/prisma/seeder/data/permission.seed.ts +67 -0
- package/template/prisma/seeder/data/position.seed.ts +21 -0
- package/template/prisma/seeder/data/user.seed.ts +39 -0
- package/template/prisma/seeder/index.ts +56 -0
- package/template/prisma.config.ts +8 -0
- package/template/src/app.module.ts +68 -0
- package/template/src/common/constants/permissions.constant.ts +27 -0
- package/template/src/common/decorators/api-response.decorator.ts +44 -0
- package/template/src/common/decorators/get-user.decorator.ts +11 -0
- package/template/src/common/decorators/permissions.decorator.ts +5 -0
- package/template/src/common/decorators/public.decorator.ts +4 -0
- package/template/src/common/dto/api-response.dto.ts +15 -0
- package/template/src/common/dto/pagination.dto.ts +33 -0
- package/template/src/common/filters/http-exception.filter.ts +54 -0
- package/template/src/common/guards/jwt-auth.guard.ts +32 -0
- package/template/src/common/guards/permissions.guard.ts +53 -0
- package/template/src/common/helpers/function/error-helper.ts +35 -0
- package/template/src/common/interceptors/logging.interceptor.ts +37 -0
- package/template/src/common/interceptors/transform.interceptor.ts +53 -0
- package/template/src/common/prisma/prisma.module.ts +9 -0
- package/template/src/common/prisma/prisma.service.ts +52 -0
- package/template/src/common/utils/password.util.ts +13 -0
- package/template/src/config/app.config.ts +10 -0
- package/template/src/config/database.config.ts +5 -0
- package/template/src/config/env.validation.ts +30 -0
- package/template/src/config/jwt.config.ts +8 -0
- package/template/src/config/swagger.config.ts +6 -0
- package/template/src/main.ts +84 -0
- package/template/src/modules/auth/auth.module.ts +28 -0
- package/template/src/modules/auth/auth.service.ts +173 -0
- package/template/src/modules/auth/controllers/v1/auth.controller.ts +71 -0
- package/template/src/modules/auth/core/dto/auth-response.dto.ts +19 -0
- package/template/src/modules/auth/core/dto/login-response.dto.ts +10 -0
- package/template/src/modules/auth/core/dto/login.dto.ts +15 -0
- package/template/src/modules/auth/core/dto/register.dto.ts +30 -0
- package/template/src/modules/auth/core/interfaces/jwt-payload.interface.ts +7 -0
- package/template/src/modules/auth/core/strategies/jwt.strategy.ts +59 -0
- package/template/src/modules/health/health.controller.ts +29 -0
- package/template/src/modules/health/health.module.ts +7 -0
- package/template/src/modules/users/controllers/v1/users.controller.ts +120 -0
- package/template/src/modules/users/core/dto/change-position.dto.ts +9 -0
- package/template/src/modules/users/core/dto/create-user.dto.ts +35 -0
- package/template/src/modules/users/core/dto/manage-permissions.dto.ts +13 -0
- package/template/src/modules/users/core/dto/update-user.dto.ts +30 -0
- package/template/src/modules/users/core/dto/user-query.dto.ts +22 -0
- package/template/src/modules/users/core/dto/user-response.dto.ts +32 -0
- package/template/src/modules/users/core/entities/user.entity.ts +45 -0
- package/template/src/modules/users/core/helpers/user-transform.helper.ts +31 -0
- package/template/src/modules/users/users.module.ts +10 -0
- package/template/src/modules/users/users.service.ts +344 -0
- package/template/test/app.e2e-spec.ts +40 -0
- package/template/test/jest-e2e.json +9 -0
- package/template/tsconfig.json +30 -0
- package/bin/cli.js +0 -71
package/README.md
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# @kuldi/create-nestjs
|
|
2
|
+
|
|
3
|
+
The official interactive scaffolding tool for Kuli Digital's NestJS Boilerplate.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
To generate a new NestJS project using this boilerplate, simply run:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm create @kuldi/nestjs my-app
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Or, to create it in the current directory:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm create @kuldi/nestjs .
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Features
|
|
20
|
+
|
|
21
|
+
- **Interactive Prompts**: Easily configure your project name and database name.
|
|
22
|
+
- **Auto-Configured Environment**: Automatically generates a `.env` file tailored to your database credentials.
|
|
23
|
+
- **Production Ready**: Scaffolds a full-fledged NestJS architecture with Prisma, Swagger, and JWT Auth out of the box.
|
|
24
|
+
|
|
25
|
+
## License
|
|
26
|
+
|
|
27
|
+
MIT - Kuli Digital
|
package/package.json
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kuldi/create-nestjs",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"type": "module",
|
|
4
5
|
"description": "Scaffolding tool for Kuli Digital NestJS Boilerplate",
|
|
5
|
-
"main": "
|
|
6
|
-
"bin": "
|
|
6
|
+
"main": "src/cli.js",
|
|
7
|
+
"bin": "src/cli.js",
|
|
8
|
+
"files": [
|
|
9
|
+
"src",
|
|
10
|
+
"template"
|
|
11
|
+
],
|
|
7
12
|
"scripts": {
|
|
8
13
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
9
14
|
},
|
|
@@ -22,5 +27,10 @@
|
|
|
22
27
|
"license": "MIT",
|
|
23
28
|
"publishConfig": {
|
|
24
29
|
"access": "public"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"chalk": "^5.6.2",
|
|
33
|
+
"inquirer": "^14.0.2",
|
|
34
|
+
"ora": "^9.4.1"
|
|
25
35
|
}
|
|
26
36
|
}
|
package/src/cli.js
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { execSync } from 'child_process';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import fs from 'fs';
|
|
6
|
+
import inquirer from 'inquirer';
|
|
7
|
+
import ora from 'ora';
|
|
8
|
+
import chalk from 'chalk';
|
|
9
|
+
import { fileURLToPath } from 'url';
|
|
10
|
+
|
|
11
|
+
const currentPath = process.cwd();
|
|
12
|
+
|
|
13
|
+
// Fallback untuk support Node versi di bawah 20.11 yang belum punya import.meta.dirname
|
|
14
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
15
|
+
const __dirname = path.dirname(__filename);
|
|
16
|
+
|
|
17
|
+
async function run() {
|
|
18
|
+
console.log(chalk.cyan.bold('\n๐ Kuli Digital NestJS Boilerplate Generator\n'));
|
|
19
|
+
|
|
20
|
+
const argProjectName = process.argv[2];
|
|
21
|
+
|
|
22
|
+
// 1. Tanya-tanya
|
|
23
|
+
const answers = await inquirer.prompt([
|
|
24
|
+
{
|
|
25
|
+
type: 'input',
|
|
26
|
+
name: 'projectName',
|
|
27
|
+
message: 'Nama Project (atau . untuk folder saat ini):',
|
|
28
|
+
default: argProjectName || 'my-nestjs-app',
|
|
29
|
+
when: !argProjectName,
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
type: 'input',
|
|
33
|
+
name: 'database',
|
|
34
|
+
message: 'Nama Database PostgreSQL:',
|
|
35
|
+
default: 'kulidigital_db',
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
type: 'confirm',
|
|
39
|
+
name: 'skipInstall',
|
|
40
|
+
message: 'Lewati instalasi package (npm install)?',
|
|
41
|
+
default: false,
|
|
42
|
+
},
|
|
43
|
+
]);
|
|
44
|
+
|
|
45
|
+
const projectName = argProjectName || answers.projectName;
|
|
46
|
+
const projectPath = projectName === '.' ? currentPath : path.join(currentPath, projectName);
|
|
47
|
+
|
|
48
|
+
// Mengecek apakah target directory kosong
|
|
49
|
+
if (projectName === '.') {
|
|
50
|
+
const files = fs.readdirSync(currentPath).filter(f => !f.startsWith('.git'));
|
|
51
|
+
if (files.length > 0) {
|
|
52
|
+
console.log(chalk.red('\nโ Folder saat ini tidak kosong! Harap jalankan di folder kosong.\n'));
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// 2. Salin Template
|
|
58
|
+
const copySpinner = ora('Membuat struktur project...').start();
|
|
59
|
+
try {
|
|
60
|
+
const templateDir = path.join(__dirname, '../template');
|
|
61
|
+
|
|
62
|
+
// Copy seluruh isi folder template ke project tujuan
|
|
63
|
+
fs.cpSync(templateDir, projectPath, { recursive: true });
|
|
64
|
+
|
|
65
|
+
// Rename gitignore menjadi .gitignore (krn NPM mengabaikan .gitignore saat publish)
|
|
66
|
+
const gitignorePath = path.join(projectPath, 'gitignore');
|
|
67
|
+
if (fs.existsSync(gitignorePath)) {
|
|
68
|
+
fs.renameSync(gitignorePath, path.join(projectPath, '.gitignore'));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
copySpinner.succeed('Struktur project berhasil dibuat.');
|
|
72
|
+
} catch (error) {
|
|
73
|
+
copySpinner.fail('Gagal menyalin struktur template.');
|
|
74
|
+
console.error(error.message);
|
|
75
|
+
process.exit(1);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Masuk ke folder project
|
|
79
|
+
process.chdir(projectPath);
|
|
80
|
+
|
|
81
|
+
// 3. Setup .env
|
|
82
|
+
const envSpinner = ora('Menyiapkan file .env...').start();
|
|
83
|
+
try {
|
|
84
|
+
const envExamplePath = path.join(projectPath, '.env.example');
|
|
85
|
+
const envPath = path.join(projectPath, '.env');
|
|
86
|
+
|
|
87
|
+
if (fs.existsSync(envExamplePath)) {
|
|
88
|
+
let envContent = fs.readFileSync(envExamplePath, 'utf-8');
|
|
89
|
+
|
|
90
|
+
envContent = envContent.replace(/__DATABASE_NAME__/g, answers.database);
|
|
91
|
+
envContent = envContent.replace(/APP_NAME=my-app/g, `APP_NAME=${projectName === '.' ? path.basename(currentPath) : projectName}`);
|
|
92
|
+
|
|
93
|
+
fs.writeFileSync(envPath, envContent);
|
|
94
|
+
envSpinner.succeed('File .env berhasil dibuat.');
|
|
95
|
+
} else {
|
|
96
|
+
envSpinner.warn('File .env.example tidak ditemukan, lewati setup .env.');
|
|
97
|
+
}
|
|
98
|
+
} catch (error) {
|
|
99
|
+
envSpinner.fail('Gagal menyiapkan file .env.');
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// 4. Inisialisasi Git
|
|
103
|
+
try {
|
|
104
|
+
execSync('git init', { stdio: 'ignore' });
|
|
105
|
+
} catch (e) {
|
|
106
|
+
// Abaikan jika user tidak punya git terinstall
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// 5. Install Dependencies
|
|
110
|
+
if (!answers.skipInstall) {
|
|
111
|
+
const installSpinner = ora(`Menginstal dependencies menggunakan npm... (ini butuh waktu beberapa menit)`).start();
|
|
112
|
+
try {
|
|
113
|
+
execSync(`npm install`, { stdio: 'ignore' });
|
|
114
|
+
installSpinner.succeed('Dependencies berhasil diinstal.');
|
|
115
|
+
} catch (error) {
|
|
116
|
+
installSpinner.fail('Gagal menginstal dependencies.');
|
|
117
|
+
console.log(chalk.yellow('\nKamu bisa menginstalnya secara manual nanti.'));
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// 6. Success Message
|
|
122
|
+
console.log(chalk.green.bold('\nโ
Project Berhasil Dibuat!\n'));
|
|
123
|
+
console.log(chalk.white('Langkah selanjutnya:'));
|
|
124
|
+
|
|
125
|
+
if (projectName !== '.') {
|
|
126
|
+
console.log(chalk.cyan(` cd ${projectName}`));
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (answers.skipInstall) {
|
|
130
|
+
console.log(chalk.cyan(` npm install`));
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
console.log(chalk.cyan(` npx prisma migrate dev`));
|
|
134
|
+
console.log(chalk.cyan(` npx prisma db seed`));
|
|
135
|
+
console.log(chalk.cyan(` npm run start:dev\n`));
|
|
136
|
+
console.log(chalk.gray(`Happy Coding! - Kuli Digital\n`));
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
run();
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Application
|
|
2
|
+
NODE_ENV=development
|
|
3
|
+
PORT=3000
|
|
4
|
+
APP_NAME=my-app
|
|
5
|
+
|
|
6
|
+
# Database
|
|
7
|
+
DATABASE_URL="postgresql://username:password@localhost:5432/__DATABASE_NAME__?schema=public"
|
|
8
|
+
|
|
9
|
+
# JWT
|
|
10
|
+
JWT_SECRET=your-super-secret-jwt-key-change-this-in-production
|
|
11
|
+
JWT_EXPIRATION=7d
|
|
12
|
+
JWT_REFRESH_SECRET=your-super-secret-refresh-key-change-this-in-production
|
|
13
|
+
JWT_REFRESH_EXPIRATION=30d
|
|
14
|
+
|
|
15
|
+
# CORS
|
|
16
|
+
CORS_ORIGIN=http://localhost:3001
|
|
17
|
+
|
|
18
|
+
# API
|
|
19
|
+
API_PREFIX=api
|
|
20
|
+
|
|
21
|
+
# Swagger
|
|
22
|
+
SWAGGER_ENABLED=true
|
|
23
|
+
SWAGGER_PATH=docs
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
parser: '@typescript-eslint/parser',
|
|
3
|
+
parserOptions: {
|
|
4
|
+
project: 'tsconfig.json',
|
|
5
|
+
tsconfigRootDir: __dirname,
|
|
6
|
+
sourceType: 'module',
|
|
7
|
+
},
|
|
8
|
+
plugins: ['@typescript-eslint/eslint-plugin'],
|
|
9
|
+
extends: [
|
|
10
|
+
'plugin:@typescript-eslint/recommended',
|
|
11
|
+
'plugin:prettier/recommended',
|
|
12
|
+
],
|
|
13
|
+
root: true,
|
|
14
|
+
env: {
|
|
15
|
+
node: true,
|
|
16
|
+
jest: true,
|
|
17
|
+
},
|
|
18
|
+
ignorePatterns: ['.eslintrc.js'],
|
|
19
|
+
rules: {
|
|
20
|
+
'@typescript-eslint/interface-name-prefix': 'off',
|
|
21
|
+
'@typescript-eslint/explicit-function-return-type': 'off',
|
|
22
|
+
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
|
23
|
+
'@typescript-eslint/no-explicit-any': 'off',
|
|
24
|
+
},
|
|
25
|
+
};
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# Kuli Digital NestJS Backend
|
|
2
|
+
|
|
3
|
+
Backend application built with NestJS following Kuli Digital standardization manual.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- ๐ JWT Authentication with RBAC
|
|
8
|
+
- ๐ Complete User Management
|
|
9
|
+
- ๐ฏ Permission-based Access Control
|
|
10
|
+
- ๐ Auto-generated Swagger Documentation
|
|
11
|
+
- โ
Input Validation
|
|
12
|
+
- ๐ API Versioning
|
|
13
|
+
- ๐ Structured Logging
|
|
14
|
+
- ๐๏ธ Prisma ORM with PostgreSQL
|
|
15
|
+
- ๐งช Testing Setup (Unit & E2E)
|
|
16
|
+
|
|
17
|
+
## Prerequisites
|
|
18
|
+
|
|
19
|
+
- Node.js >= 18.x
|
|
20
|
+
- PostgreSQL >= 14.x
|
|
21
|
+
- npm/yarn/pnpm
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
```bash
|
|
25
|
+
# Install dependencies
|
|
26
|
+
npm install
|
|
27
|
+
|
|
28
|
+
# Setup environment variables
|
|
29
|
+
cp .env.example .env
|
|
30
|
+
# Edit .env with your database credentials
|
|
31
|
+
|
|
32
|
+
# Generate Prisma Client
|
|
33
|
+
npm run prisma:generate
|
|
34
|
+
|
|
35
|
+
# Run migrations
|
|
36
|
+
npm run prisma:migrate
|
|
37
|
+
|
|
38
|
+
# Seed database
|
|
39
|
+
npm run prisma:seed
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Running the Application
|
|
43
|
+
```bash
|
|
44
|
+
# Development
|
|
45
|
+
npm run start:dev
|
|
46
|
+
|
|
47
|
+
# Production build
|
|
48
|
+
npm run build
|
|
49
|
+
npm run start:prod
|
|
50
|
+
|
|
51
|
+
# Debug mode
|
|
52
|
+
npm run start:debug
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Database Commands
|
|
56
|
+
```bash
|
|
57
|
+
# Generate Prisma Client
|
|
58
|
+
npm run prisma:generate
|
|
59
|
+
|
|
60
|
+
# Create migration
|
|
61
|
+
npm run prisma:migrate
|
|
62
|
+
|
|
63
|
+
# Seed database
|
|
64
|
+
npm run prisma:seed
|
|
65
|
+
|
|
66
|
+
# Open Prisma Studio
|
|
67
|
+
npm run prisma:studio
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Testing
|
|
71
|
+
```bash
|
|
72
|
+
# Unit tests
|
|
73
|
+
npm run test
|
|
74
|
+
|
|
75
|
+
# E2E tests
|
|
76
|
+
npm run test:e2e
|
|
77
|
+
|
|
78
|
+
# Test coverage
|
|
79
|
+
npm run test:cov
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## API Documentation
|
|
83
|
+
|
|
84
|
+
After starting the application, visit:
|
|
85
|
+
- Swagger UI: `http://localhost:3000/api-docs`
|
|
86
|
+
|
|
87
|
+
## Default Users
|
|
88
|
+
|
|
89
|
+
After seeding the database:
|
|
90
|
+
|
|
91
|
+
**Admin User:**
|
|
92
|
+
- Email: `admin@kulidigital.com`
|
|
93
|
+
- Password: `password123`
|
|
94
|
+
- All permissions granted
|
|
95
|
+
|
|
96
|
+
**Member User:**
|
|
97
|
+
- Email: `member@kulidigital.com`
|
|
98
|
+
- Password: `password123`
|
|
99
|
+
- Limited permissions (VIEW_USER only)
|
|
100
|
+
|
|
101
|
+
## Project Structure
|
|
102
|
+
```
|
|
103
|
+
src/
|
|
104
|
+
โโโ common/ # Shared resources
|
|
105
|
+
โ โโโ decorators/ # Custom decorators
|
|
106
|
+
โ โโโ filters/ # Exception filters
|
|
107
|
+
โ โโโ guards/ # Auth & permission guards
|
|
108
|
+
โ โโโ interceptors/ # Logging & transform
|
|
109
|
+
โ โโโ prisma/ # Prisma service
|
|
110
|
+
โ โโโ utils/ # Helper functions
|
|
111
|
+
โโโ config/ # Configuration files
|
|
112
|
+
โโโ modules/ # Feature modules
|
|
113
|
+
โ โโโ auth/ # Authentication
|
|
114
|
+
โ โโโ users/ # User management
|
|
115
|
+
โ โโโ health/ # Health checks
|
|
116
|
+
โโโ app.module.ts # Root module
|
|
117
|
+
โโโ main.ts # Application entry point
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Environment Variables
|
|
121
|
+
|
|
122
|
+
See `.env.example` for all available configuration options.
|
|
123
|
+
|
|
124
|
+
## License
|
|
125
|
+
|
|
126
|
+
Proprietary - Kuli Digital
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### 20.2 .gitkeep for migrations
|
|
130
|
+
|
|
131
|
+
**templates/nestjs-app/prisma/migrations/.gitkeep**
|
|
132
|
+
```
|
|
133
|
+
# This file keeps the migrations directory in git
|