kontas-express 1.0.1 → 1.0.3
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/dist/index.js +3 -0
- package/package.json +13 -4
- package/index.js +0 -1
- package/jsconfig.json +0 -27
- package/templates/files/config/mongodb-config.js +0 -45
- package/templates/files/config/mongodb-json.js +0 -14
- package/templates/files/error-handler.js +0 -54
- package/templates/files/home-controller.js +0 -7
- package/templates/files/index.js +0 -129
- package/templates/files/model-seeder.js +0 -43
- package/templates/files/repository.js +0 -47
- package/templates/files/route-controller.js +0 -53
- package/templates/files/schema.js +0 -53
- package/templates/files/seeder-index.js +0 -62
- package/templates/files/service.js +0 -103
- package/templates/files/user/auth-service.js +0 -72
- package/templates/files/user/controller.js +0 -21
- package/templates/files/user/id-controller.js +0 -32
- package/templates/files/user/register-controller.js +0 -11
- package/templates/files/user/repository.js +0 -59
- package/templates/files/user/seeder.js +0 -33
- package/templates/files/user/service.js +0 -173
- package/templates/files/user/sessions-controller.js +0 -24
- package/templates/files/utils/bcrypt.js +0 -15
- package/templates/files/utils/jwt.js +0 -33
- package/templates/index.js +0 -60
package/dist/index.js
ADDED
package/package.json
CHANGED
@@ -1,13 +1,22 @@
|
|
1
1
|
{
|
2
2
|
"name": "kontas-express",
|
3
|
-
"version": "1.0.
|
4
|
-
"main": "index.js",
|
3
|
+
"version": "1.0.3",
|
4
|
+
"main": "dist/index.js",
|
5
5
|
"scripts": {
|
6
|
-
"
|
6
|
+
"build": "bun build ./index.js --outdir ./dist --target bun",
|
7
|
+
"prepublishOnly": "bun run build"
|
7
8
|
},
|
9
|
+
"files": [
|
10
|
+
"dist"
|
11
|
+
],
|
12
|
+
"keywords": [
|
13
|
+
"kontas",
|
14
|
+
"express",
|
15
|
+
"framework"
|
16
|
+
],
|
8
17
|
"author": "Hens MSN",
|
9
18
|
"license": "ISC",
|
10
|
-
"description": "",
|
19
|
+
"description": "Kontas Express Framework",
|
11
20
|
"devDependencies": {
|
12
21
|
"@types/bun": "latest"
|
13
22
|
},
|
package/index.js
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
export { default as templates } from './templates/index.js'
|
package/jsconfig.json
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
{
|
2
|
-
"compilerOptions": {
|
3
|
-
// Enable latest features
|
4
|
-
"lib": ["ESNext", "DOM"],
|
5
|
-
"target": "ESNext",
|
6
|
-
"module": "ESNext",
|
7
|
-
"moduleDetection": "force",
|
8
|
-
"jsx": "react-jsx",
|
9
|
-
"allowJs": true,
|
10
|
-
|
11
|
-
// Bundler mode
|
12
|
-
"moduleResolution": "bundler",
|
13
|
-
"allowImportingTsExtensions": true,
|
14
|
-
"verbatimModuleSyntax": true,
|
15
|
-
"noEmit": true,
|
16
|
-
|
17
|
-
// Best practices
|
18
|
-
"strict": true,
|
19
|
-
"skipLibCheck": true,
|
20
|
-
"noFallthroughCasesInSwitch": true,
|
21
|
-
|
22
|
-
// Some stricter flags (disabled by default)
|
23
|
-
"noUnusedLocals": false,
|
24
|
-
"noUnusedParameters": false,
|
25
|
-
"noPropertyAccessFromIndexSignature": false
|
26
|
-
}
|
27
|
-
}
|
@@ -1,45 +0,0 @@
|
|
1
|
-
export default `import { MongoClient } from "mongodb"
|
2
|
-
import config from "./mongodb.json"
|
3
|
-
|
4
|
-
// Mendapatkan environment yang sedang berjalan (default: development)
|
5
|
-
const env = process.env.NODE_ENV || "development"
|
6
|
-
const { uri: configUri, name } = config[env as keyof typeof config]
|
7
|
-
|
8
|
-
// Menggunakan URI dari environment variable jika tersedia, jika tidak menggunakan dari config
|
9
|
-
const uri = process.env.MONGODB_URI || configUri
|
10
|
-
|
11
|
-
// Inisialisasi MongoDB Client
|
12
|
-
const client = new MongoClient(uri)
|
13
|
-
|
14
|
-
/**
|
15
|
-
* Membuat koneksi ke MongoDB
|
16
|
-
* @throws {Error} Jika koneksi gagal
|
17
|
-
*/
|
18
|
-
export async function connect() {
|
19
|
-
try {
|
20
|
-
await client.connect()
|
21
|
-
// console.log("✅ Berhasil terhubung ke MongoDB")
|
22
|
-
} catch (error) {
|
23
|
-
console.error("❌ Gagal terhubung ke MongoDB:", error)
|
24
|
-
await client.close() // Menutup koneksi jika terjadi kegagalan
|
25
|
-
throw error // Re-throw error untuk handling di level aplikasi
|
26
|
-
}
|
27
|
-
}
|
28
|
-
|
29
|
-
/**
|
30
|
-
* Mendapatkan instance database
|
31
|
-
* @returns {Promise<Db>} Instance database MongoDB
|
32
|
-
*/
|
33
|
-
export async function getDb() {
|
34
|
-
return client.db(name)
|
35
|
-
}
|
36
|
-
|
37
|
-
/**
|
38
|
-
* Mendapatkan collection dari database
|
39
|
-
* @param {string} collectionName - Nama collection yang ingin diakses
|
40
|
-
* @returns {Promise<Collection>} Instance collection MongoDB
|
41
|
-
*/
|
42
|
-
export async function getCollection(collectionName: string) {
|
43
|
-
const db = await getDb()
|
44
|
-
return db.collection(collectionName)
|
45
|
-
}`
|
@@ -1,54 +0,0 @@
|
|
1
|
-
export default `import type { Request, Response, NextFunction } from 'express'
|
2
|
-
import { z } from 'zod'
|
3
|
-
|
4
|
-
export const errorHandler = (
|
5
|
-
err: Error,
|
6
|
-
req: Request,
|
7
|
-
res: Response,
|
8
|
-
next: NextFunction
|
9
|
-
): void => {
|
10
|
-
// console.error('🔥 Error:', err)
|
11
|
-
|
12
|
-
// Zod validation errors
|
13
|
-
if (err instanceof z.ZodError) {
|
14
|
-
res.status(422).json({
|
15
|
-
success: false,
|
16
|
-
status: 422,
|
17
|
-
error: err.issues.map(issue => ({
|
18
|
-
field: issue.path.join('.'),
|
19
|
-
message: issue.message
|
20
|
-
}))
|
21
|
-
})
|
22
|
-
return
|
23
|
-
}
|
24
|
-
|
25
|
-
// Known errors
|
26
|
-
if (err instanceof Error) {
|
27
|
-
let status = 400
|
28
|
-
let message = err.message
|
29
|
-
|
30
|
-
if (err.message.includes('not found')) {
|
31
|
-
status = 404
|
32
|
-
} else if (err.message.includes('unauthorized')) {
|
33
|
-
status = 401
|
34
|
-
} else if (err.message.includes('forbidden')) {
|
35
|
-
status = 403
|
36
|
-
} else if (err.message.includes('already exists')) {
|
37
|
-
status = 409
|
38
|
-
}
|
39
|
-
|
40
|
-
res.status(status).json({
|
41
|
-
success: false,
|
42
|
-
status,
|
43
|
-
error: message
|
44
|
-
})
|
45
|
-
return
|
46
|
-
}
|
47
|
-
|
48
|
-
// Unknown errors
|
49
|
-
res.status(500).json({
|
50
|
-
success: false,
|
51
|
-
status: 500,
|
52
|
-
error: 'Internal Server Error'
|
53
|
-
})
|
54
|
-
}`
|
package/templates/files/index.js
DELETED
@@ -1,129 +0,0 @@
|
|
1
|
-
export default `import dotenv from 'dotenv'
|
2
|
-
import express from 'express'
|
3
|
-
import { XRoutes, XMiddleware } from 'kontas-xroutes'
|
4
|
-
import { connect } from '@config/mongodb'
|
5
|
-
|
6
|
-
// Load environment variables
|
7
|
-
dotenv.config()
|
8
|
-
|
9
|
-
/*
|
10
|
-
* 📚 Tutorial Express + XRoutes:
|
11
|
-
*
|
12
|
-
* 🔥 XRoutes Features:
|
13
|
-
* - Auto-routing dari folder structure (mirip NextJS)
|
14
|
-
* - Wajib pake nama controller.ts (bkn route.ts)
|
15
|
-
* - Support middleware per route/global
|
16
|
-
* - Compatible dgn Express & Bun
|
17
|
-
*
|
18
|
-
* 📁 Struktur Route:
|
19
|
-
* src/
|
20
|
-
* ├─ products/
|
21
|
-
* │ ├─ [id]/
|
22
|
-
* │ │ └─ controller.ts => /products/:id
|
23
|
-
* │ └─ controller.ts => /products
|
24
|
-
* ├─ users/
|
25
|
-
* │ ├─ [id]/
|
26
|
-
* │ │ └─ controller.ts => /users/:id
|
27
|
-
* │ └─ controller.ts => /users
|
28
|
-
* └─ auth/
|
29
|
-
* └─ controller.ts => /auth
|
30
|
-
*
|
31
|
-
* 🔐 Route Middleware Examples:
|
32
|
-
* - '/products/*': Semua route /products
|
33
|
-
* - '/users': Exact route /users
|
34
|
-
* - '/users/*': Route yg ada /users/ didalamnya
|
35
|
-
*/
|
36
|
-
|
37
|
-
const app = express()
|
38
|
-
const port = process.env.PORT || 3000
|
39
|
-
|
40
|
-
/*
|
41
|
-
* 🛠️ Content-Length Fix untuk Bun:
|
42
|
-
* Reset content-length pada:
|
43
|
-
* 1. GET requests
|
44
|
-
* 2. OPTIONS (CORS)
|
45
|
-
* 3. Non-JSON requests
|
46
|
-
*/
|
47
|
-
app.use((req, res, next) => {
|
48
|
-
if (
|
49
|
-
req.method === 'GET' ||
|
50
|
-
req.method === 'OPTIONS' ||
|
51
|
-
!req.is('application/json')
|
52
|
-
) {
|
53
|
-
req.headers['content-length'] = undefined;
|
54
|
-
}
|
55
|
-
next();
|
56
|
-
});
|
57
|
-
|
58
|
-
// Basic middleware
|
59
|
-
app.use(express.json())
|
60
|
-
app.use(express.urlencoded({ extended: true }))
|
61
|
-
|
62
|
-
// Setup simple logging middleware
|
63
|
-
XMiddleware.setup({
|
64
|
-
// Global middleware
|
65
|
-
global: [
|
66
|
-
async (req, res, next) => {
|
67
|
-
console.log(\`🚀 \${req.method} \${req.path}\`)
|
68
|
-
next()
|
69
|
-
}
|
70
|
-
],
|
71
|
-
|
72
|
-
// Route specific middleware
|
73
|
-
/*
|
74
|
-
routes: {
|
75
|
-
'/products/*': [
|
76
|
-
async (req, res, next) => {
|
77
|
-
console.log('📦 Products Route accessed')
|
78
|
-
next()
|
79
|
-
}
|
80
|
-
],
|
81
|
-
|
82
|
-
'/users': [
|
83
|
-
async (req, res, next) => {
|
84
|
-
console.log('👥 Users Route accessed!')
|
85
|
-
next()
|
86
|
-
}
|
87
|
-
],
|
88
|
-
|
89
|
-
'/users/*': [
|
90
|
-
async (req, res, next) => {
|
91
|
-
console.log('👤 User Detail Route accessed!')
|
92
|
-
next()
|
93
|
-
}
|
94
|
-
]
|
95
|
-
}
|
96
|
-
*/
|
97
|
-
|
98
|
-
// Jika pakai middleware dari file lain
|
99
|
-
// Import dulu middlewarenya di paling atas
|
100
|
-
/*
|
101
|
-
routes: {
|
102
|
-
'/products/*': [
|
103
|
-
authMiddleware,
|
104
|
-
loggerMiddleware,
|
105
|
-
multerMiddleware
|
106
|
-
]
|
107
|
-
}
|
108
|
-
*/
|
109
|
-
})
|
110
|
-
|
111
|
-
// Start server dgn auto-routing
|
112
|
-
await XRoutes.createServer(app, { dir: 'src' })
|
113
|
-
|
114
|
-
// Test MongoDB connection before starting server
|
115
|
-
let isMongoConnected = false
|
116
|
-
try {
|
117
|
-
await connect()
|
118
|
-
isMongoConnected = true
|
119
|
-
} catch (error: unknown) {
|
120
|
-
console.error('❌ MongoDB Connection Error:', (error as Error).message)
|
121
|
-
}
|
122
|
-
|
123
|
-
app.listen(port, () => {
|
124
|
-
console.log(\`🚀 Server is running on:
|
125
|
-
- Port: http://localhost:\${port}
|
126
|
-
- Environment: \${process.env.NODE_ENV || 'development'}
|
127
|
-
- MongoDB: \${isMongoConnected ? 'Connected' : 'Failed to connect'}\`)
|
128
|
-
})
|
129
|
-
`
|
@@ -1,43 +0,0 @@
|
|
1
|
-
export default `import fs from "fs/promises";
|
2
|
-
import { getCollection } from "@config/mongodb";
|
3
|
-
import { ObjectId } from "mongodb";
|
4
|
-
import type { {{MODEL}} } from "@modules/{{MODEL_LC}}/{{MODEL_LC}}.schema";
|
5
|
-
|
6
|
-
/*
|
7
|
-
* 📚 Tutorial Model Seeder:
|
8
|
-
* 1. Template ini bikin seeder utk masing2 model
|
9
|
-
* 2. Dia baca data dari file JSON di src/data/
|
10
|
-
* 3. Nambahin field yg dibutuhin kyk _id, createdAt, updatedAt
|
11
|
-
* 4. Masukin data ke MongoDB
|
12
|
-
*/
|
13
|
-
|
14
|
-
const collectionName = "{{MODEL_PLURAL}}"
|
15
|
-
|
16
|
-
export const seed{{MODEL_PLURAL}} = async () => {
|
17
|
-
/*
|
18
|
-
* 🔄 Langkah2 Seeding:
|
19
|
-
* 1. Ambil referensi collection
|
20
|
-
* 2. Baca data JSON
|
21
|
-
* 3. Ubah data (tambahin ID & timestamp)
|
22
|
-
* 4. Masukin ke database
|
23
|
-
*/
|
24
|
-
try {
|
25
|
-
const {{MODEL_LC}}Collection = await getCollection(collectionName);
|
26
|
-
|
27
|
-
const {{MODEL_LC_PLURAL}} = JSON.parse(
|
28
|
-
await fs.readFile("./src/data/{{MODEL_LC_PLURAL}}.json", "utf-8")
|
29
|
-
);
|
30
|
-
|
31
|
-
{{MODEL_LC_PLURAL}}.map((el: {{MODEL}}) => {
|
32
|
-
el._id = new ObjectId();
|
33
|
-
el.createdAt = new Date();
|
34
|
-
el.updatedAt = new Date();
|
35
|
-
return el;
|
36
|
-
});
|
37
|
-
|
38
|
-
await {{MODEL_LC}}Collection.insertMany({{MODEL_LC_PLURAL}});
|
39
|
-
console.log("{{MODEL}} seeding completed successfully.");
|
40
|
-
} catch (error) {
|
41
|
-
console.error("Error seeding {{MODEL_LC_PLURAL}}:", error);
|
42
|
-
}
|
43
|
-
}`
|
@@ -1,47 +0,0 @@
|
|
1
|
-
export default `import { getCollection } from "../../config/mongodb"
|
2
|
-
import { ObjectId } from "mongodb"
|
3
|
-
|
4
|
-
import type {
|
5
|
-
Create{{MODEL}},
|
6
|
-
{{MODEL}},
|
7
|
-
{{MODEL}}Id,
|
8
|
-
Update{{MODEL}}
|
9
|
-
} from "./{{MODEL_LC}}.schema"
|
10
|
-
|
11
|
-
const {{MODEL_LC_PLURAL}} = await getCollection("{{MODEL_PLURAL}}")
|
12
|
-
|
13
|
-
export const {{MODEL_LC}}Repository = {
|
14
|
-
|
15
|
-
create: async (data: Create{{MODEL}}) => {
|
16
|
-
const result = await {{MODEL_LC_PLURAL}}.insertOne({
|
17
|
-
...data,
|
18
|
-
createdAt: new Date(),
|
19
|
-
updatedAt: new Date()
|
20
|
-
})
|
21
|
-
return { _id: result.insertedId, ...data } as {{MODEL}}
|
22
|
-
},
|
23
|
-
|
24
|
-
findAll: async () => {
|
25
|
-
return await {{MODEL_LC_PLURAL}}.find().toArray() as {{MODEL}}[]
|
26
|
-
},
|
27
|
-
|
28
|
-
findById: async ({ id }: {{MODEL}}Id) => {
|
29
|
-
return await {{MODEL_LC_PLURAL}}.findOne(
|
30
|
-
{ _id: new ObjectId(id) }
|
31
|
-
) as {{MODEL}} | null
|
32
|
-
},
|
33
|
-
|
34
|
-
update: async ({ id }: {{MODEL}}Id, data: Update{{MODEL}}) => {
|
35
|
-
return await {{MODEL_LC_PLURAL}}.findOneAndUpdate(
|
36
|
-
{ _id: new ObjectId(id) },
|
37
|
-
{ $set: { ...data, updatedAt: new Date() } },
|
38
|
-
{ returnDocument: "after" }
|
39
|
-
)
|
40
|
-
},
|
41
|
-
|
42
|
-
delete: async ({ id }: {{MODEL}}Id) => {
|
43
|
-
return await {{MODEL_LC_PLURAL}}.findOneAndDelete(
|
44
|
-
{ _id: new ObjectId(id) }
|
45
|
-
)
|
46
|
-
}
|
47
|
-
}`
|
@@ -1,53 +0,0 @@
|
|
1
|
-
export const routeController = (MODEL, MODEL_PLURAL, MODEL_LC_PLURAL) => `import type { Request, Response, NextFunction } from 'express'
|
2
|
-
import { ${MODEL}Service } from "@modules/${MODEL.toLowerCase()}/${MODEL.toLowerCase()}.service"
|
3
|
-
|
4
|
-
export async function GET(req: Request, res: Response, next: NextFunction) {
|
5
|
-
try {
|
6
|
-
const ${MODEL_LC_PLURAL} = await ${MODEL}Service.getAll${MODEL_PLURAL}()
|
7
|
-
res.status(${MODEL_LC_PLURAL}.status).json(${MODEL_LC_PLURAL})
|
8
|
-
} catch (error) {
|
9
|
-
next(error)
|
10
|
-
}
|
11
|
-
}
|
12
|
-
|
13
|
-
export async function POST(req: Request, res: Response, next: NextFunction) {
|
14
|
-
try {
|
15
|
-
const ${MODEL.toLowerCase()} = await ${MODEL}Service.create${MODEL}(req.body)
|
16
|
-
res.status(${MODEL.toLowerCase()}.status).json(${MODEL.toLowerCase()})
|
17
|
-
} catch (error) {
|
18
|
-
next(error)
|
19
|
-
}
|
20
|
-
}`
|
21
|
-
|
22
|
-
export const routeIdController = (MODEL) => `import type { Request, Response, NextFunction } from 'express'
|
23
|
-
import { ${MODEL}Service } from "@modules/${MODEL.toLowerCase()}/${MODEL.toLowerCase()}.service"
|
24
|
-
|
25
|
-
export async function GET(req: Request, res: Response, next: NextFunction) {
|
26
|
-
try {
|
27
|
-
const { id } = req.params
|
28
|
-
const ${MODEL.toLowerCase()} = await ${MODEL}Service.get${MODEL}ById({ id })
|
29
|
-
res.status(${MODEL.toLowerCase()}.status).json(${MODEL.toLowerCase()})
|
30
|
-
} catch (error) {
|
31
|
-
next(error)
|
32
|
-
}
|
33
|
-
}
|
34
|
-
|
35
|
-
export async function PUT(req: Request, res: Response, next: NextFunction) {
|
36
|
-
try {
|
37
|
-
const { id } = req.params
|
38
|
-
const ${MODEL.toLowerCase()} = await ${MODEL}Service.update${MODEL}({ id }, req.body)
|
39
|
-
res.status(${MODEL.toLowerCase()}.status).json(${MODEL.toLowerCase()})
|
40
|
-
} catch (error) {
|
41
|
-
next(error)
|
42
|
-
}
|
43
|
-
}
|
44
|
-
|
45
|
-
export async function DELETE(req: Request, res: Response, next: NextFunction) {
|
46
|
-
try {
|
47
|
-
const { id } = req.params
|
48
|
-
const ${MODEL.toLowerCase()} = await ${MODEL}Service.delete${MODEL}({ id })
|
49
|
-
res.status(${MODEL.toLowerCase()}.status).json(${MODEL.toLowerCase()})
|
50
|
-
} catch (error) {
|
51
|
-
next(error)
|
52
|
-
}
|
53
|
-
}`
|
@@ -1,53 +0,0 @@
|
|
1
|
-
export default `import { z } from "zod"
|
2
|
-
import { ObjectId } from "mongodb"
|
3
|
-
|
4
|
-
/*
|
5
|
-
* 📚 Quick Zod Guide:
|
6
|
-
*
|
7
|
-
* Contoh validasi dgn message:
|
8
|
-
* const userSchema = z.object({
|
9
|
-
* name: z.string().min(2, "Minimal 2 karakter"),
|
10
|
-
* email: z.string().email("Email tidak valid"),
|
11
|
-
* age: z.number().min(17, "Minimal umur 17 tahun")
|
12
|
-
* })
|
13
|
-
*/
|
14
|
-
|
15
|
-
// Base schema yg shared di semua operations
|
16
|
-
const {{MODEL}}BaseSchema = z.object({
|
17
|
-
{{FIELDS}}
|
18
|
-
})
|
19
|
-
|
20
|
-
const WithIdSchema = z.object({
|
21
|
-
_id: z.instanceof(ObjectId)
|
22
|
-
})
|
23
|
-
|
24
|
-
const TimestampSchema = z.object({
|
25
|
-
createdAt: z.date(),
|
26
|
-
updatedAt: z.date()
|
27
|
-
})
|
28
|
-
|
29
|
-
const {{MODEL}}IdSchema = z.object({
|
30
|
-
id: z.string().regex(/^[0-9a-fA-F]{24}$/)
|
31
|
-
})
|
32
|
-
|
33
|
-
const Create{{MODEL}}Schema = {{MODEL}}BaseSchema
|
34
|
-
|
35
|
-
const {{MODEL}}Schema = {{MODEL}}BaseSchema
|
36
|
-
.merge(WithIdSchema)
|
37
|
-
.merge(TimestampSchema)
|
38
|
-
|
39
|
-
const Update{{MODEL}}Schema = {{MODEL}}BaseSchema.partial()
|
40
|
-
|
41
|
-
// Export types
|
42
|
-
export type Create{{MODEL}} = z.infer<typeof Create{{MODEL}}Schema>
|
43
|
-
export type {{MODEL}} = z.infer<typeof {{MODEL}}Schema>
|
44
|
-
export type Update{{MODEL}} = z.infer<typeof Update{{MODEL}}Schema>
|
45
|
-
export type {{MODEL}}Id = z.infer<typeof {{MODEL}}IdSchema>
|
46
|
-
|
47
|
-
// Export schemas
|
48
|
-
export {
|
49
|
-
Create{{MODEL}}Schema,
|
50
|
-
{{MODEL}}Schema,
|
51
|
-
Update{{MODEL}}Schema,
|
52
|
-
{{MODEL}}IdSchema
|
53
|
-
}`
|
@@ -1,62 +0,0 @@
|
|
1
|
-
export default `import { connect, getDb } from "@config/mongodb";
|
2
|
-
{{IMPORTS}}
|
3
|
-
|
4
|
-
/*
|
5
|
-
* 📚 Tutorial: Proses Seeding
|
6
|
-
* 1. File ini adalah seeder utama yg ngatur semua operasi seeding
|
7
|
-
* 2. Pertama, dia bakal drop collection yg udh ada biar datanya bersih
|
8
|
-
* 3. Trus jalanin semua seeder secara bersamaan pake Promise.all
|
9
|
-
*/
|
10
|
-
|
11
|
-
async function dropCollections() {
|
12
|
-
/*
|
13
|
-
* 🔍 Gmn cara kerja dropCollections:
|
14
|
-
* - Dapetin koneksi database
|
15
|
-
* - Coba drop tiap collection
|
16
|
-
* - Handle kasus klo collection blm ada
|
17
|
-
*/
|
18
|
-
try {
|
19
|
-
const db = await getDb();
|
20
|
-
|
21
|
-
const collections = [{{COLLECTIONS}}];
|
22
|
-
|
23
|
-
for (const collectionName of collections) {
|
24
|
-
try {
|
25
|
-
await db.collection(collectionName).drop();
|
26
|
-
} catch {
|
27
|
-
console.log(\`⚠️ \${collectionName} collection not found, skipping...\`);
|
28
|
-
}
|
29
|
-
}
|
30
|
-
|
31
|
-
console.log("✨ Successfully dropped all collections!");
|
32
|
-
} catch (error) {
|
33
|
-
console.error("❌ Failed to drop collections:", error);
|
34
|
-
throw error;
|
35
|
-
}
|
36
|
-
}
|
37
|
-
|
38
|
-
async function seed() {
|
39
|
-
/*
|
40
|
-
* 🌱 Langkah2 Proses Seeding:
|
41
|
-
* 1. Konek ke MongoDB
|
42
|
-
* 2. Drop collection yg udh ada
|
43
|
-
* 3. Jalanin semua seeder barengan
|
44
|
-
* 4. Exit process klo udh selesai
|
45
|
-
*/
|
46
|
-
try {
|
47
|
-
await connect();
|
48
|
-
await dropCollections();
|
49
|
-
|
50
|
-
await Promise.all([
|
51
|
-
{{SEEDERS}}
|
52
|
-
]);
|
53
|
-
|
54
|
-
console.log("🌱 Seeding completed successfully!");
|
55
|
-
} catch (error) {
|
56
|
-
console.error("❌ Seeding failed:", error);
|
57
|
-
} finally {
|
58
|
-
process.exit(0);
|
59
|
-
}
|
60
|
-
}
|
61
|
-
|
62
|
-
seed();`
|
@@ -1,103 +0,0 @@
|
|
1
|
-
export default `import { {{MODEL_LC}}Repository } from "./{{MODEL_LC}}.repository"
|
2
|
-
import type { Create{{MODEL}}, {{MODEL}}Id, Update{{MODEL}} } from "./{{MODEL_LC}}.schema"
|
3
|
-
import { Create{{MODEL}}Schema, {{MODEL}}IdSchema, Update{{MODEL}}Schema } from "./{{MODEL_LC}}.schema"
|
4
|
-
|
5
|
-
export class {{MODEL}}Service {
|
6
|
-
|
7
|
-
static async create{{MODEL}}({{MODEL_LC}}: Create{{MODEL}}) {
|
8
|
-
try {
|
9
|
-
const validated = Create{{MODEL}}Schema.parse({{MODEL_LC}})
|
10
|
-
const result = await {{MODEL_LC}}Repository.create(validated)
|
11
|
-
|
12
|
-
return {
|
13
|
-
success: true,
|
14
|
-
status: 201,
|
15
|
-
data: result
|
16
|
-
}
|
17
|
-
|
18
|
-
} catch (error) {
|
19
|
-
throw error
|
20
|
-
}
|
21
|
-
}
|
22
|
-
|
23
|
-
static async getAll{{MODEL_PLURAL}}() {
|
24
|
-
try {
|
25
|
-
const {{MODEL_LC_PLURAL}} = await {{MODEL_LC}}Repository.findAll()
|
26
|
-
|
27
|
-
if ({{MODEL_LC_PLURAL}}.length === 0) {
|
28
|
-
throw new Error("No {{MODEL_LC_PLURAL}} found")
|
29
|
-
}
|
30
|
-
|
31
|
-
return {
|
32
|
-
success: true,
|
33
|
-
status: 200,
|
34
|
-
data: {{MODEL_LC_PLURAL}}
|
35
|
-
}
|
36
|
-
|
37
|
-
} catch (error) {
|
38
|
-
throw error
|
39
|
-
}
|
40
|
-
}
|
41
|
-
|
42
|
-
static async get{{MODEL}}ById(params: {{MODEL}}Id) {
|
43
|
-
try {
|
44
|
-
const { id } = {{MODEL}}IdSchema.parse(params)
|
45
|
-
const {{MODEL_LC}} = await {{MODEL_LC}}Repository.findById({ id })
|
46
|
-
|
47
|
-
if (!{{MODEL_LC}}) {
|
48
|
-
throw new Error("{{MODEL}} not found")
|
49
|
-
}
|
50
|
-
|
51
|
-
return {
|
52
|
-
success: true,
|
53
|
-
status: 200,
|
54
|
-
data: {{MODEL_LC}}
|
55
|
-
}
|
56
|
-
|
57
|
-
} catch (error) {
|
58
|
-
throw error
|
59
|
-
}
|
60
|
-
}
|
61
|
-
|
62
|
-
static async update{{MODEL}}(params: {{MODEL}}Id, data: Update{{MODEL}}) {
|
63
|
-
try {
|
64
|
-
const { id } = {{MODEL}}IdSchema.parse(params)
|
65
|
-
const validated = Update{{MODEL}}Schema.parse(data)
|
66
|
-
|
67
|
-
const result = await {{MODEL_LC}}Repository.update({ id }, validated)
|
68
|
-
|
69
|
-
if (!result) {
|
70
|
-
throw new Error("{{MODEL}} not found")
|
71
|
-
}
|
72
|
-
|
73
|
-
return {
|
74
|
-
success: true,
|
75
|
-
status: 200,
|
76
|
-
data: result
|
77
|
-
}
|
78
|
-
|
79
|
-
} catch (error) {
|
80
|
-
throw error
|
81
|
-
}
|
82
|
-
}
|
83
|
-
|
84
|
-
static async delete{{MODEL}}(params: {{MODEL}}Id) {
|
85
|
-
try {
|
86
|
-
const { id } = {{MODEL}}IdSchema.parse(params)
|
87
|
-
const result = await {{MODEL_LC}}Repository.delete({ id })
|
88
|
-
|
89
|
-
if (!result) {
|
90
|
-
throw new Error("{{MODEL}} not found")
|
91
|
-
}
|
92
|
-
|
93
|
-
return {
|
94
|
-
success: true,
|
95
|
-
status: 200,
|
96
|
-
data: result
|
97
|
-
}
|
98
|
-
|
99
|
-
} catch (error) {
|
100
|
-
throw error
|
101
|
-
}
|
102
|
-
}
|
103
|
-
}`
|
@@ -1,72 +0,0 @@
|
|
1
|
-
export default `import { {{MODEL_LC}}Repository } from "./{{MODEL_LC}}.repository"
|
2
|
-
import type { Create{{MODEL}} } from "./{{MODEL_LC}}.schema"
|
3
|
-
import { Create{{MODEL}}Schema } from "./{{MODEL_LC}}.schema"
|
4
|
-
import { hash, compare } from "@utils/bcrypt"
|
5
|
-
import { createToken } from "@utils/jwt"
|
6
|
-
|
7
|
-
export class Auth{{MODEL}}Service {
|
8
|
-
static async login(email: string, password: string) {
|
9
|
-
try {
|
10
|
-
const user = await {{MODEL_LC}}Repository.findByEmail(email)
|
11
|
-
|
12
|
-
if (!user) {
|
13
|
-
throw new Error("Invalid credentials")
|
14
|
-
}
|
15
|
-
|
16
|
-
const isValidPassword = await compare(password, user.password)
|
17
|
-
|
18
|
-
if (!isValidPassword) {
|
19
|
-
throw new Error("Invalid credentials")
|
20
|
-
}
|
21
|
-
|
22
|
-
const token = await createToken({
|
23
|
-
userId: user._id.toString(),
|
24
|
-
email: user.email
|
25
|
-
})
|
26
|
-
|
27
|
-
// Remove password from response
|
28
|
-
const { password: _, ...userWithoutPassword } = user
|
29
|
-
|
30
|
-
return {
|
31
|
-
success: true,
|
32
|
-
status: 200,
|
33
|
-
data: { user: userWithoutPassword, token }
|
34
|
-
}
|
35
|
-
} catch (error) {
|
36
|
-
throw error
|
37
|
-
}
|
38
|
-
}
|
39
|
-
|
40
|
-
static async register(data: Create{{MODEL}}) {
|
41
|
-
try {
|
42
|
-
const validated = Create{{MODEL}}Schema.parse(data)
|
43
|
-
|
44
|
-
// Check if email already exists
|
45
|
-
const existing = await {{MODEL_LC}}Repository.findByEmail(validated.email)
|
46
|
-
if (existing) {
|
47
|
-
throw new Error("Email already registered")
|
48
|
-
}
|
49
|
-
|
50
|
-
// Hash password
|
51
|
-
validated.password = await hash(validated.password)
|
52
|
-
|
53
|
-
const result = await {{MODEL_LC}}Repository.create(validated)
|
54
|
-
const token = await createToken({
|
55
|
-
userId: result._id.toString(),
|
56
|
-
email: result.email
|
57
|
-
})
|
58
|
-
|
59
|
-
// Remove password from response
|
60
|
-
const { password: _, ...userWithoutPassword } = result
|
61
|
-
|
62
|
-
return {
|
63
|
-
success: true,
|
64
|
-
status: 201,
|
65
|
-
data: { user: userWithoutPassword, token }
|
66
|
-
}
|
67
|
-
|
68
|
-
} catch (error) {
|
69
|
-
throw error
|
70
|
-
}
|
71
|
-
}
|
72
|
-
}`
|
@@ -1,21 +0,0 @@
|
|
1
|
-
export default `import type { Request, Response, NextFunction } from 'express'
|
2
|
-
import { {{MODEL}}Service } from "@modules/{{MODEL_LC}}/{{MODEL_LC}}.service"
|
3
|
-
|
4
|
-
export async function GET(req: Request, res: Response, next: NextFunction) {
|
5
|
-
try {
|
6
|
-
const result = await {{MODEL}}Service.getAll{{MODEL}}s()
|
7
|
-
res.status(result.status).json(result)
|
8
|
-
} catch (error) {
|
9
|
-
next(error)
|
10
|
-
}
|
11
|
-
}
|
12
|
-
|
13
|
-
// Create user (admin only)
|
14
|
-
export async function POST(req: Request, res: Response, next: NextFunction) {
|
15
|
-
try {
|
16
|
-
const result = await {{MODEL}}Service.create{{MODEL}}(req.body)
|
17
|
-
res.status(result.status).json(result)
|
18
|
-
} catch (error) {
|
19
|
-
next(error)
|
20
|
-
}
|
21
|
-
}`
|
@@ -1,32 +0,0 @@
|
|
1
|
-
export default `import type { Request, Response, NextFunction } from 'express'
|
2
|
-
import { {{MODEL}}Service } from "@modules/{{MODEL_LC}}/{{MODEL_LC}}.service"
|
3
|
-
|
4
|
-
export async function GET(req: Request, res: Response, next: NextFunction) {
|
5
|
-
try {
|
6
|
-
const { id } = req.params
|
7
|
-
const result = await {{MODEL}}Service.get{{MODEL}}ById({ id })
|
8
|
-
res.status(result.status).json(result)
|
9
|
-
} catch (error) {
|
10
|
-
next(error)
|
11
|
-
}
|
12
|
-
}
|
13
|
-
|
14
|
-
export async function PUT(req: Request, res: Response, next: NextFunction) {
|
15
|
-
try {
|
16
|
-
const { id } = req.params
|
17
|
-
const result = await {{MODEL}}Service.update{{MODEL}}({ id }, req.body)
|
18
|
-
res.status(result.status).json(result)
|
19
|
-
} catch (error) {
|
20
|
-
next(error)
|
21
|
-
}
|
22
|
-
}
|
23
|
-
|
24
|
-
export async function DELETE(req: Request, res: Response, next: NextFunction) {
|
25
|
-
try {
|
26
|
-
const { id } = req.params
|
27
|
-
const result = await {{MODEL}}Service.delete{{MODEL}}({ id })
|
28
|
-
res.status(result.status).json(result)
|
29
|
-
} catch (error) {
|
30
|
-
next(error)
|
31
|
-
}
|
32
|
-
}`
|
@@ -1,11 +0,0 @@
|
|
1
|
-
export default `import type { Request, Response, NextFunction } from 'express'
|
2
|
-
import { Auth{{MODEL}}Service } from "@modules/{{MODEL_LC}}/auth.service"
|
3
|
-
|
4
|
-
export async function POST(req: Request, res: Response, next: NextFunction) {
|
5
|
-
try {
|
6
|
-
const result = await Auth{{MODEL}}Service.register(req.body)
|
7
|
-
res.status(result.status).json(result)
|
8
|
-
} catch (error) {
|
9
|
-
next(error)
|
10
|
-
}
|
11
|
-
}`
|
@@ -1,59 +0,0 @@
|
|
1
|
-
export default `import { getCollection } from "../../config/mongodb"
|
2
|
-
import { ObjectId } from "mongodb"
|
3
|
-
|
4
|
-
import type {
|
5
|
-
Create{{MODEL}},
|
6
|
-
{{MODEL}},
|
7
|
-
{{MODEL}}Id,
|
8
|
-
Update{{MODEL}}
|
9
|
-
} from "./{{MODEL_LC}}.schema"
|
10
|
-
|
11
|
-
const {{MODEL_LC}}s = await getCollection("{{MODEL}}s")
|
12
|
-
|
13
|
-
export const {{MODEL_LC}}Repository = {
|
14
|
-
|
15
|
-
create: async (data: Create{{MODEL}}) => {
|
16
|
-
const result = await {{MODEL_LC}}s.insertOne({
|
17
|
-
...data,
|
18
|
-
createdAt: new Date(),
|
19
|
-
updatedAt: new Date()
|
20
|
-
})
|
21
|
-
return { _id: result.insertedId, ...data } as {{MODEL}}
|
22
|
-
},
|
23
|
-
|
24
|
-
findAll: async () => {
|
25
|
-
return await {{MODEL_LC}}s.find({}, { projection: { password: 0 } }).toArray() as {{MODEL}}[]
|
26
|
-
},
|
27
|
-
|
28
|
-
findById: async ({ id }: {{MODEL}}Id) => {
|
29
|
-
return await {{MODEL_LC}}s.findOne(
|
30
|
-
{ _id: new ObjectId(id) },
|
31
|
-
{ projection: { password: 0 } }
|
32
|
-
) as {{MODEL}} | null
|
33
|
-
},
|
34
|
-
|
35
|
-
// Khusus User: findByEmail (tetap include password utk login)
|
36
|
-
findByEmail: async (email: string) => {
|
37
|
-
return await {{MODEL_LC}}s.findOne({ email }) as {{MODEL}} | null
|
38
|
-
},
|
39
|
-
|
40
|
-
update: async ({ id }: {{MODEL}}Id, data: Update{{MODEL}}) => {
|
41
|
-
const result = await {{MODEL_LC}}s.findOneAndUpdate(
|
42
|
-
{ _id: new ObjectId(id) },
|
43
|
-
{ $set: { ...data, updatedAt: new Date() } },
|
44
|
-
{
|
45
|
-
returnDocument: "after",
|
46
|
-
projection: { password: 0 }
|
47
|
-
}
|
48
|
-
)
|
49
|
-
return result
|
50
|
-
},
|
51
|
-
|
52
|
-
delete: async ({ id }: {{MODEL}}Id) => {
|
53
|
-
const result = await {{MODEL_LC}}s.findOneAndDelete(
|
54
|
-
{ _id: new ObjectId(id) },
|
55
|
-
{ projection: { password: 0 } }
|
56
|
-
)
|
57
|
-
return result
|
58
|
-
}
|
59
|
-
}`
|
@@ -1,33 +0,0 @@
|
|
1
|
-
export default `import fs from "fs/promises"
|
2
|
-
import { getCollection } from "@config/mongodb"
|
3
|
-
import { ObjectId } from "mongodb"
|
4
|
-
import type { User } from "@modules/user/user.schema"
|
5
|
-
import { hash } from "@utils/bcrypt"
|
6
|
-
|
7
|
-
const collectionName = "Users"
|
8
|
-
|
9
|
-
export const seedUsers = async () => {
|
10
|
-
try {
|
11
|
-
const userCollection = await getCollection(collectionName)
|
12
|
-
|
13
|
-
const users = JSON.parse(
|
14
|
-
await fs.readFile("./src/data/users.json", "utf-8")
|
15
|
-
)
|
16
|
-
|
17
|
-
// Hash passwords before inserting
|
18
|
-
const usersWithHashedPasswords = await Promise.all(
|
19
|
-
users.map(async (el: User) => {
|
20
|
-
el._id = new ObjectId()
|
21
|
-
el.password = await hash(el.password)
|
22
|
-
el.createdAt = new Date()
|
23
|
-
el.updatedAt = new Date()
|
24
|
-
return el
|
25
|
-
})
|
26
|
-
)
|
27
|
-
|
28
|
-
await userCollection.insertMany(usersWithHashedPasswords)
|
29
|
-
console.log("User seeding completed successfully.")
|
30
|
-
} catch (error) {
|
31
|
-
console.error("Error seeding users:", error)
|
32
|
-
}
|
33
|
-
}`
|
@@ -1,173 +0,0 @@
|
|
1
|
-
export default `import { {{MODEL_LC}}Repository } from "./{{MODEL_LC}}.repository"
|
2
|
-
import type { Create{{MODEL}}, {{MODEL}}Id, Update{{MODEL}} } from "./{{MODEL_LC}}.schema"
|
3
|
-
import { Create{{MODEL}}Schema, {{MODEL}}IdSchema, Update{{MODEL}}Schema } from "./{{MODEL_LC}}.schema"
|
4
|
-
import { hash, compare } from "@utils/bcrypt"
|
5
|
-
import { createToken } from "@utils/jwt"
|
6
|
-
|
7
|
-
export class {{MODEL}}Service {
|
8
|
-
static async create{{MODEL}}({{MODEL_LC}}: Create{{MODEL}}) {
|
9
|
-
try {
|
10
|
-
const validated = Create{{MODEL}}Schema.parse({{MODEL_LC}})
|
11
|
-
|
12
|
-
// Hash password before saving
|
13
|
-
validated.password = await hash(validated.password)
|
14
|
-
|
15
|
-
const result = await {{MODEL_LC}}Repository.create(validated)
|
16
|
-
|
17
|
-
return {
|
18
|
-
success: true,
|
19
|
-
status: 201,
|
20
|
-
data: result
|
21
|
-
}
|
22
|
-
|
23
|
-
} catch (error) {
|
24
|
-
throw error
|
25
|
-
}
|
26
|
-
}
|
27
|
-
|
28
|
-
static async getAll{{MODEL}}s() {
|
29
|
-
try {
|
30
|
-
const {{MODEL_LC}}s = await {{MODEL_LC}}Repository.findAll()
|
31
|
-
|
32
|
-
if ({{MODEL_LC}}s.length === 0) {
|
33
|
-
throw new Error("No {{MODEL_LC}}s found")
|
34
|
-
}
|
35
|
-
|
36
|
-
return {
|
37
|
-
success: true,
|
38
|
-
status: 200,
|
39
|
-
data: {{MODEL_LC}}s
|
40
|
-
}
|
41
|
-
|
42
|
-
} catch (error) {
|
43
|
-
throw error
|
44
|
-
}
|
45
|
-
}
|
46
|
-
|
47
|
-
static async get{{MODEL}}ById(params: {{MODEL}}Id) {
|
48
|
-
try {
|
49
|
-
const { id } = {{MODEL}}IdSchema.parse(params)
|
50
|
-
const {{MODEL_LC}} = await {{MODEL_LC}}Repository.findById({ id })
|
51
|
-
|
52
|
-
if (!{{MODEL_LC}}) {
|
53
|
-
throw new Error("{{MODEL}} not found")
|
54
|
-
}
|
55
|
-
|
56
|
-
return {
|
57
|
-
success: true,
|
58
|
-
status: 200,
|
59
|
-
data: {{MODEL_LC}}
|
60
|
-
}
|
61
|
-
|
62
|
-
} catch (error) {
|
63
|
-
throw error
|
64
|
-
}
|
65
|
-
}
|
66
|
-
|
67
|
-
static async update{{MODEL}}(params: {{MODEL}}Id, data: Update{{MODEL}}) {
|
68
|
-
try {
|
69
|
-
const { id } = {{MODEL}}IdSchema.parse(params)
|
70
|
-
const validated = Update{{MODEL}}Schema.parse(data)
|
71
|
-
|
72
|
-
// Hash password if it's being updated
|
73
|
-
if (validated.password) {
|
74
|
-
validated.password = await hash(validated.password)
|
75
|
-
}
|
76
|
-
|
77
|
-
const result = await {{MODEL_LC}}Repository.update({ id }, validated)
|
78
|
-
|
79
|
-
if (!result) {
|
80
|
-
throw new Error("{{MODEL}} not found")
|
81
|
-
}
|
82
|
-
|
83
|
-
return {
|
84
|
-
success: true,
|
85
|
-
status: 200,
|
86
|
-
data: result
|
87
|
-
}
|
88
|
-
|
89
|
-
} catch (error) {
|
90
|
-
throw error
|
91
|
-
}
|
92
|
-
}
|
93
|
-
|
94
|
-
static async delete{{MODEL}}(params: {{MODEL}}Id) {
|
95
|
-
try {
|
96
|
-
const { id } = {{MODEL}}IdSchema.parse(params)
|
97
|
-
const result = await {{MODEL_LC}}Repository.delete({ id })
|
98
|
-
|
99
|
-
if (!result) {
|
100
|
-
throw new Error("{{MODEL}} not found")
|
101
|
-
}
|
102
|
-
|
103
|
-
return {
|
104
|
-
success: true,
|
105
|
-
status: 200,
|
106
|
-
data: result
|
107
|
-
}
|
108
|
-
|
109
|
-
} catch (error) {
|
110
|
-
throw error
|
111
|
-
}
|
112
|
-
}
|
113
|
-
|
114
|
-
// Auth methods
|
115
|
-
static async login(email: string, password: string) {
|
116
|
-
try {
|
117
|
-
const user = await {{MODEL_LC}}Repository.findByEmail(email)
|
118
|
-
|
119
|
-
if (!user) {
|
120
|
-
throw new Error("Invalid credentials")
|
121
|
-
}
|
122
|
-
|
123
|
-
const isValidPassword = await compare(password, user.password)
|
124
|
-
|
125
|
-
if (!isValidPassword) {
|
126
|
-
throw new Error("Invalid credentials")
|
127
|
-
}
|
128
|
-
|
129
|
-
const token = await createToken({
|
130
|
-
userId: user._id.toString(),
|
131
|
-
email: user.email
|
132
|
-
})
|
133
|
-
|
134
|
-
return {
|
135
|
-
success: true,
|
136
|
-
status: 200,
|
137
|
-
data: { user, token }
|
138
|
-
}
|
139
|
-
} catch (error) {
|
140
|
-
throw error
|
141
|
-
}
|
142
|
-
}
|
143
|
-
|
144
|
-
static async register(data: Create{{MODEL}}) {
|
145
|
-
try {
|
146
|
-
const validated = Create{{MODEL}}Schema.parse(data)
|
147
|
-
|
148
|
-
// Check if email already exists
|
149
|
-
const existing = await {{MODEL_LC}}Repository.findByEmail(validated.email)
|
150
|
-
if (existing) {
|
151
|
-
throw new Error("Email already registered")
|
152
|
-
}
|
153
|
-
|
154
|
-
// Hash password
|
155
|
-
validated.password = await hash(validated.password)
|
156
|
-
|
157
|
-
const result = await {{MODEL_LC}}Repository.create(validated)
|
158
|
-
const token = await createToken({
|
159
|
-
userId: result._id.toString(),
|
160
|
-
email: result.email
|
161
|
-
})
|
162
|
-
|
163
|
-
return {
|
164
|
-
success: true,
|
165
|
-
status: 201,
|
166
|
-
data: { user: result, token }
|
167
|
-
}
|
168
|
-
|
169
|
-
} catch (error) {
|
170
|
-
throw error
|
171
|
-
}
|
172
|
-
}
|
173
|
-
}`
|
@@ -1,24 +0,0 @@
|
|
1
|
-
export default `import type { Request, Response, NextFunction } from 'express'
|
2
|
-
import { Auth{{MODEL}}Service } from "@modules/{{MODEL_LC}}/auth.service"
|
3
|
-
|
4
|
-
export async function POST(req: Request, res: Response, next: NextFunction) {
|
5
|
-
try {
|
6
|
-
const { email, password } = req.body
|
7
|
-
const result = await Auth{{MODEL}}Service.login(email, password)
|
8
|
-
res.status(result.status).json(result)
|
9
|
-
} catch (error) {
|
10
|
-
next(error)
|
11
|
-
}
|
12
|
-
}
|
13
|
-
|
14
|
-
export async function DELETE(req: Request, res: Response, next: NextFunction) {
|
15
|
-
try {
|
16
|
-
// Handle logout (invalidate token, clear cookie etc)
|
17
|
-
res.status(200).json({
|
18
|
-
success: true,
|
19
|
-
message: "Logged out successfully"
|
20
|
-
})
|
21
|
-
} catch (error) {
|
22
|
-
next(error)
|
23
|
-
}
|
24
|
-
}`
|
@@ -1,15 +0,0 @@
|
|
1
|
-
export default `import bcrypt from "bcryptjs"
|
2
|
-
|
3
|
-
export const hash = async (
|
4
|
-
password: string,
|
5
|
-
saltRounds: number = 10
|
6
|
-
): Promise<string> => {
|
7
|
-
return await bcrypt.hash(password, saltRounds)
|
8
|
-
}
|
9
|
-
|
10
|
-
export const compare = async (
|
11
|
-
password: string,
|
12
|
-
hash: string
|
13
|
-
): Promise<boolean> => {
|
14
|
-
return await bcrypt.compare(password, hash)
|
15
|
-
}`
|
@@ -1,33 +0,0 @@
|
|
1
|
-
export default `import jwt from "jsonwebtoken"
|
2
|
-
|
3
|
-
interface TokenPayload {
|
4
|
-
userId: string
|
5
|
-
email: string
|
6
|
-
role?: string
|
7
|
-
}
|
8
|
-
|
9
|
-
const JWT_SECRET = process.env.JWT_SECRET || "your-secret-key"
|
10
|
-
const JWT_EXPIRES_IN = "24h"
|
11
|
-
|
12
|
-
export const createToken = async (payload: TokenPayload): Promise<string> => {
|
13
|
-
return new Promise((resolve, reject) => {
|
14
|
-
jwt.sign(
|
15
|
-
payload,
|
16
|
-
JWT_SECRET,
|
17
|
-
{ expiresIn: JWT_EXPIRES_IN },
|
18
|
-
(error, token) => {
|
19
|
-
if (error) reject(error)
|
20
|
-
resolve(token as string)
|
21
|
-
}
|
22
|
-
)
|
23
|
-
})
|
24
|
-
}
|
25
|
-
|
26
|
-
export const verifyToken = async (token: string): Promise<TokenPayload> => {
|
27
|
-
return new Promise((resolve, reject) => {
|
28
|
-
jwt.verify(token, JWT_SECRET, (error, decoded) => {
|
29
|
-
if (error) reject(error)
|
30
|
-
resolve(decoded as TokenPayload)
|
31
|
-
})
|
32
|
-
})
|
33
|
-
}`
|
package/templates/index.js
DELETED
@@ -1,60 +0,0 @@
|
|
1
|
-
import repository from './files/repository.js'
|
2
|
-
import schema from './files/schema.js'
|
3
|
-
import service from './files/service.js'
|
4
|
-
import rootIndex from './files/index.js'
|
5
|
-
import homeController from './files/home-controller.js'
|
6
|
-
import mongodbConfig from './files/config/mongodb-config.js'
|
7
|
-
import mongodbJson from './files/config/mongodb-json.js'
|
8
|
-
import seederIndex from './files/seeder-index.js'
|
9
|
-
import modelSeeder from './files/model-seeder.js'
|
10
|
-
import errorHandler from './files/error-handler.js'
|
11
|
-
import { routeController, routeIdController } from './files/route-controller.js'
|
12
|
-
|
13
|
-
// User specific templates
|
14
|
-
import bcryptUtil from './files/utils/bcrypt.js'
|
15
|
-
import jwtUtil from './files/utils/jwt.js'
|
16
|
-
import userRepository from './files/user/repository.js'
|
17
|
-
import userService from './files/user/service.js'
|
18
|
-
import userController from './files/user/controller.js'
|
19
|
-
import userIdController from './files/user/id-controller.js'
|
20
|
-
import userSessionsController from './files/user/sessions-controller.js'
|
21
|
-
import userRegisterController from './files/user/register-controller.js'
|
22
|
-
import userSeeder from './files/user/seeder.js'
|
23
|
-
import userAuthService from './files/user/auth-service.js'
|
24
|
-
|
25
|
-
const gitignoreContent = `node_modules
|
26
|
-
.env
|
27
|
-
.DS_Store
|
28
|
-
dist
|
29
|
-
.turbo`
|
30
|
-
|
31
|
-
const templates = {
|
32
|
-
// Standard templates
|
33
|
-
repository,
|
34
|
-
schema,
|
35
|
-
service,
|
36
|
-
rootIndex,
|
37
|
-
homeController,
|
38
|
-
mongodbConfig,
|
39
|
-
mongodbJson,
|
40
|
-
gitignore: gitignoreContent,
|
41
|
-
seederIndex,
|
42
|
-
modelSeeder,
|
43
|
-
errorHandler,
|
44
|
-
routeController,
|
45
|
-
routeIdController,
|
46
|
-
|
47
|
-
// User specific templates
|
48
|
-
bcryptUtil,
|
49
|
-
jwtUtil,
|
50
|
-
userRepository,
|
51
|
-
userService,
|
52
|
-
userController,
|
53
|
-
userIdController,
|
54
|
-
userSessionsController,
|
55
|
-
userRegisterController,
|
56
|
-
userSeeder,
|
57
|
-
userAuthService
|
58
|
-
}
|
59
|
-
|
60
|
-
export default templates
|