crypt-express-app 1.0.0 → 1.3.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.
Potentially problematic release.
This version of crypt-express-app might be problematic. Click here for more details.
- package/README.md +321 -1
- package/{scripts/generate-module.ts → dist/generate-module.js} +24 -81
- package/dist/index.js +122 -17
- package/dist/scripts/generate-app.js +73 -55
- package/dist/scripts/generate-locales.js +22 -26
- package/dist/scripts/generate-middleware.js +69 -67
- package/dist/scripts/generate-module.js +140 -78
- package/dist/scripts/generate-root-files.js +199 -63
- package/dist/scripts/generate-utils.js +811 -46
- package/dist/scripts/setup-prisma.js +14 -13
- package/package.json +10 -5
- package/index.ts +0 -29
- package/scripts/generate-app.ts +0 -104
- package/scripts/generate-locales.ts +0 -36
- package/scripts/generate-middleware.ts +0 -176
- package/scripts/generate-root-files.ts +0 -147
- package/scripts/generate-utils.ts +0 -208
- package/scripts/setup-prisma.ts +0 -26
- package/tsconfig.json +0 -10
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
import * as fs from "fs";
|
|
2
2
|
import * as path from "path";
|
|
3
|
-
|
|
4
|
-
const basePath = path.join(
|
|
5
|
-
if (!fs.existsSync(basePath)) {
|
|
6
|
-
|
|
7
|
-
}
|
|
8
|
-
const clientContent = `
|
|
9
|
-
import { PrismaClient
|
|
10
|
-
import { PrismaPg } from
|
|
3
|
+
export function generatePrismaClient(projectDir) {
|
|
4
|
+
const basePath = path.join(projectDir, "src", "prisma");
|
|
5
|
+
if (!fs.existsSync(basePath)) {
|
|
6
|
+
fs.mkdirSync(basePath, { recursive: true });
|
|
7
|
+
}
|
|
8
|
+
const clientContent = `
|
|
9
|
+
import { PrismaClient} from "@prisma/client"
|
|
10
|
+
import { PrismaPg } from '@prisma/adapter-pg'
|
|
11
11
|
import "dotenv/config";
|
|
12
12
|
|
|
13
|
-
const connectionString = process.env.DATABASE_URL
|
|
13
|
+
const connectionString = process.env.DATABASE_URL
|
|
14
14
|
|
|
15
|
-
const adapter = new PrismaPg({ connectionString })
|
|
16
|
-
const prisma = new PrismaClient({ adapter })
|
|
15
|
+
const adapter = new PrismaPg({ connectionString })
|
|
16
|
+
const prisma = new PrismaClient({ adapter })
|
|
17
17
|
|
|
18
18
|
export default prisma;
|
|
19
19
|
`;
|
|
20
|
-
fs.writeFileSync(path.join(basePath, "client.ts"), clientContent.trim());
|
|
21
|
-
console.log(`✅ Prisma client generated successfully at ${basePath}`);
|
|
20
|
+
fs.writeFileSync(path.join(basePath, "client.ts"), clientContent.trim());
|
|
21
|
+
console.log(`✅ Prisma client generated successfully at ${basePath}`);
|
|
22
|
+
}
|
package/package.json
CHANGED
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "crypt-express-app",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "",
|
|
3
|
+
"version": "1.3.0",
|
|
4
|
+
"description": "Crypt ExpressJS for building expressJS boilerplate on single command.",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"main": "index.js",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"dev": "tsx index.ts",
|
|
9
9
|
"build": "tsc"
|
|
10
10
|
},
|
|
11
11
|
"bin": {
|
|
12
|
-
"crypt-express-app": "index.
|
|
12
|
+
"crypt-express-app": "dist/index.js",
|
|
13
|
+
"generate-module": "dist/generate-module.js"
|
|
13
14
|
},
|
|
14
|
-
"
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"README.md"
|
|
18
|
+
],
|
|
19
|
+
"keywords": ["ExpressJS"],
|
|
15
20
|
"author": "",
|
|
16
21
|
"license": "ISC",
|
|
17
22
|
"packageManager": "pnpm@10.29.3",
|
package/index.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { execSync } from "child_process";
|
|
4
|
-
|
|
5
|
-
const projectName = process.argv[2];
|
|
6
|
-
|
|
7
|
-
if (!projectName) {
|
|
8
|
-
console.error("❌ project-name required");
|
|
9
|
-
console.log("Usage: npx crypt-express-app <project-name>");
|
|
10
|
-
process.exit(1);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
process.env.PROJECT_NAME = projectName;
|
|
14
|
-
|
|
15
|
-
console.log(projectName)
|
|
16
|
-
|
|
17
|
-
function run(cmd: string) {
|
|
18
|
-
execSync(cmd, { stdio: "inherit" });
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// run generators
|
|
22
|
-
// run("tsx scripts/generate-root-files.ts");
|
|
23
|
-
// run("tsx scripts/generate-utils.ts");
|
|
24
|
-
// run("tsx scripts/generate-locales.ts");
|
|
25
|
-
// run("tsx scripts/setup-prisma.ts");
|
|
26
|
-
// run("tsx scripts/generate-middleware.ts");
|
|
27
|
-
// run("tsx scripts/generate-module.ts common");
|
|
28
|
-
|
|
29
|
-
console.log("✅ project generated");
|
package/scripts/generate-app.ts
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
// generate-utils.ts
|
|
2
|
-
import * as fs from "fs";
|
|
3
|
-
import * as path from "path";
|
|
4
|
-
|
|
5
|
-
const basePath = path.join(__dirname, "..");
|
|
6
|
-
|
|
7
|
-
if (!fs.existsSync(basePath)) {
|
|
8
|
-
fs.mkdirSync(basePath, { recursive: true });
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/* ================= redis.ts ================= */
|
|
12
|
-
const appContent = `
|
|
13
|
-
import express, { type Express } from "express";
|
|
14
|
-
import cors from "cors";
|
|
15
|
-
import morgan from "morgan";
|
|
16
|
-
import { json, urlencoded } from "express";
|
|
17
|
-
import i18next from 'i18next';
|
|
18
|
-
import Backend from 'i18next-fs-backend';
|
|
19
|
-
import middleware from 'i18next-http-middleware';
|
|
20
|
-
import path from 'path';
|
|
21
|
-
import { errorMiddleware } from "./middlewares/error.middleware";
|
|
22
|
-
import { loggerMiddleware } from "./middlewares/logger.middleware";
|
|
23
|
-
import swaggerUi from "swagger-ui-express";
|
|
24
|
-
import { swaggerSpec } from "./utils/swagger";
|
|
25
|
-
|
|
26
|
-
export const app: Express = express();
|
|
27
|
-
|
|
28
|
-
// i18n
|
|
29
|
-
i18next
|
|
30
|
-
.use(Backend)
|
|
31
|
-
.use(middleware.LanguageDetector)
|
|
32
|
-
.init({
|
|
33
|
-
fallbackLng: 'en',
|
|
34
|
-
preload: ['en', 'bn'],
|
|
35
|
-
backend: {
|
|
36
|
-
loadPath: path.join(__dirname, 'locales/{{lng}}/translation.json')
|
|
37
|
-
},
|
|
38
|
-
detection: {
|
|
39
|
-
order: ['querystring', 'cookie', 'header'],
|
|
40
|
-
caches: ['cookie']
|
|
41
|
-
}
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
// Middlewares
|
|
45
|
-
app.use(cors());
|
|
46
|
-
app.use(json());
|
|
47
|
-
app.use(urlencoded({ extended: true }));
|
|
48
|
-
app.use(morgan("dev"));
|
|
49
|
-
app.use(middleware.handle(i18next));
|
|
50
|
-
|
|
51
|
-
// Logger middleware should come first
|
|
52
|
-
app.use(loggerMiddleware);
|
|
53
|
-
|
|
54
|
-
// Routes
|
|
55
|
-
app.get('/', (req, res) => {
|
|
56
|
-
res.send(req.t('WELCOME')); // automatically returns text in detected language
|
|
57
|
-
});
|
|
58
|
-
app.use("/api/docs", swaggerUi.serve, swaggerUi.setup(swaggerSpec, {
|
|
59
|
-
swaggerOptions: {
|
|
60
|
-
persistAuthorization: true, // ✅ এটা রাখে token reload-এও
|
|
61
|
-
},
|
|
62
|
-
}));
|
|
63
|
-
|
|
64
|
-
// Error handler
|
|
65
|
-
app.use(errorMiddleware);
|
|
66
|
-
|
|
67
|
-
export default app;
|
|
68
|
-
`;
|
|
69
|
-
fs.writeFileSync(path.join(basePath, "src", "app.ts"), appContent);
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
/* ================= redis.ts ================= */
|
|
74
|
-
const serverContent = `
|
|
75
|
-
import app from "./src/app";
|
|
76
|
-
import bootstrapSystem from "./src/utils/bootstrap";
|
|
77
|
-
import { connectRedis } from "./src/utils/redis";
|
|
78
|
-
|
|
79
|
-
async function startServer() {
|
|
80
|
-
try{
|
|
81
|
-
await bootstrapSystem(); // 🔥 important
|
|
82
|
-
await connectRedis();
|
|
83
|
-
|
|
84
|
-
app.listen(5010, () => {
|
|
85
|
-
console.log("🚀 Server running at http://localhost:3000");
|
|
86
|
-
console.log("📘 Swagger docs at http://localhost:3000/api/docs");
|
|
87
|
-
});
|
|
88
|
-
}catch(error){
|
|
89
|
-
console.log("Error.........\\n\\n")
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
process.on("uncaughtException", (err) => {
|
|
93
|
-
console.error("🔥 Uncaught Exception:", err);
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
process.on("unhandledRejection", (reason) => {
|
|
97
|
-
console.error("🔥 Unhandled Rejection:", reason);
|
|
98
|
-
});
|
|
99
|
-
startServer();
|
|
100
|
-
`;
|
|
101
|
-
fs.writeFileSync(path.join(basePath, "server.ts"), serverContent);
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
console.log("✅ App files generated successfully inside src");
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
// generate-locales.ts
|
|
2
|
-
import * as fs from "fs";
|
|
3
|
-
import * as path from "path";
|
|
4
|
-
|
|
5
|
-
const basePath = path.join(__dirname, "..", "src", "locales");
|
|
6
|
-
|
|
7
|
-
const bnPath = path.join(basePath, "bn");
|
|
8
|
-
const enPath = path.join(basePath, "en");
|
|
9
|
-
|
|
10
|
-
// ফোল্ডার তৈরি
|
|
11
|
-
[basePath, bnPath, enPath].forEach((dir) => {
|
|
12
|
-
if (!fs.existsSync(dir)) {
|
|
13
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
14
|
-
}
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
// বাংলা translation
|
|
18
|
-
const bnContent = `
|
|
19
|
-
{
|
|
20
|
-
"WELCOME": "আমাদের এপিতে স্বাগতম",
|
|
21
|
-
"USER_NOT_FOUND": "ব্যবহারকারী পাওয়া যায়নি"
|
|
22
|
-
}
|
|
23
|
-
`;
|
|
24
|
-
|
|
25
|
-
// ইংরেজি translation
|
|
26
|
-
const enContent = `
|
|
27
|
-
{
|
|
28
|
-
"WELCOME": "Welcome to our API",
|
|
29
|
-
"USER_NOT_FOUND": "User not found"
|
|
30
|
-
}
|
|
31
|
-
`;
|
|
32
|
-
|
|
33
|
-
fs.writeFileSync(path.join(bnPath, "translation.json"), bnContent.trim());
|
|
34
|
-
fs.writeFileSync(path.join(enPath, "translation.json"), enContent.trim());
|
|
35
|
-
|
|
36
|
-
console.log("Locales generated successfully inside src/locales");
|
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
import * as fs from "fs";
|
|
2
|
-
import * as path from "path";
|
|
3
|
-
|
|
4
|
-
const projectRoot = process.cwd();
|
|
5
|
-
const basePath = path.join(projectRoot, "src", "middlewares");
|
|
6
|
-
|
|
7
|
-
if (!fs.existsSync(basePath)) {
|
|
8
|
-
fs.mkdirSync(basePath, { recursive: true });
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/* ================= AUTHORIZATION ================= */
|
|
12
|
-
const authorizationContent = `
|
|
13
|
-
import { Request, Response, NextFunction } from "express";
|
|
14
|
-
import { ResourceType, ActionsType, Resource } from "../utils/consts";
|
|
15
|
-
import { cacheService } from "../utils/redis";
|
|
16
|
-
|
|
17
|
-
export function authorizationMiddleware(authorization: {
|
|
18
|
-
resource: Resource;
|
|
19
|
-
resourceType: ResourceType;
|
|
20
|
-
actions: ActionsType[];
|
|
21
|
-
}) {
|
|
22
|
-
return async (req: Request, res: Response, next: NextFunction) => {
|
|
23
|
-
try {
|
|
24
|
-
const userId = req?.user?.userId;
|
|
25
|
-
if (!userId) {
|
|
26
|
-
return res.status(401).json({ message: "Unauthorized" });
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const cached = await cacheService.get(\`user:\${userId}:permissions\`);
|
|
30
|
-
if (!cached) {
|
|
31
|
-
return res.status(403).json({ message: "Permissions not loaded" });
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const profile = JSON.parse(cached as string);
|
|
35
|
-
const permissions: string[] = profile.permissions || [];
|
|
36
|
-
|
|
37
|
-
const allowed = permissions.some((perm) => {
|
|
38
|
-
const [resName, action, type] = perm.split(":");
|
|
39
|
-
return (
|
|
40
|
-
resName === authorization.resource &&
|
|
41
|
-
type === authorization.resourceType &&
|
|
42
|
-
authorization.actions.includes(action as ActionsType)
|
|
43
|
-
);
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
if (!allowed) {
|
|
47
|
-
return res.status(403).json({ message: "Access denied" });
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
next();
|
|
51
|
-
} catch (error) {
|
|
52
|
-
console.error(error);
|
|
53
|
-
return res.status(500).json({ message: "Authorization error" });
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
};
|
|
57
|
-
`;
|
|
58
|
-
|
|
59
|
-
fs.writeFileSync(path.join(basePath, "authorization.middleware.ts"), authorizationContent.trim());
|
|
60
|
-
|
|
61
|
-
/* ================= AUTH ================= */
|
|
62
|
-
const authContent = `
|
|
63
|
-
import { Request, Response, NextFunction } from "express";
|
|
64
|
-
import jwt from "jsonwebtoken";
|
|
65
|
-
import prisma from "../../prisma/client";
|
|
66
|
-
import { cacheService } from "../utils/redis";
|
|
67
|
-
|
|
68
|
-
interface JwtPayload {
|
|
69
|
-
realmId: string;
|
|
70
|
-
sessionId: string;
|
|
71
|
-
userId: string;
|
|
72
|
-
email: string;
|
|
73
|
-
clientIdInternal: string;
|
|
74
|
-
isMasterRealmUser: boolean;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
declare global {
|
|
78
|
-
namespace Express {
|
|
79
|
-
interface Request {
|
|
80
|
-
user?: JwtPayload;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export const authMiddleware = async (req: Request, res: Response, next: NextFunction) => {
|
|
86
|
-
const authHeader = req.headers.authorization;
|
|
87
|
-
if (!authHeader) return res.status(401).json({ message: "Authorization header missing" });
|
|
88
|
-
|
|
89
|
-
const [scheme, tokenRaw] = authHeader.split(" ");
|
|
90
|
-
if (scheme !== "Bearer" || !tokenRaw) {
|
|
91
|
-
return res.status(401).json({ message: "Invalid Authorization header format" });
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
const token = tokenRaw.replace(/^\"|\"$/g, "");
|
|
95
|
-
|
|
96
|
-
const decodedPayload = jwt.decode(token) as JwtPayload | null;
|
|
97
|
-
if (!decodedPayload || !decodedPayload.realmId) {
|
|
98
|
-
return res.status(401).json({ message: "Invalid token: realmId missing" });
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const realmId = decodedPayload.realmId;
|
|
102
|
-
|
|
103
|
-
const secretKey = \`realm:\${realmId}:secret\`;
|
|
104
|
-
const secret = await cacheService.get(secretKey);
|
|
105
|
-
if (!secret) {
|
|
106
|
-
return res.status(500).json({ message: "JWT secret not configured in Redis" });
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
try {
|
|
110
|
-
const decoded = jwt.verify(token, secret as string, {
|
|
111
|
-
algorithms: ["HS256"],
|
|
112
|
-
}) as JwtPayload & { userId: string; sessionId: string };
|
|
113
|
-
|
|
114
|
-
const session = await prisma.userSession.findUnique({
|
|
115
|
-
where: { userSessionId: decoded.sessionId },
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
if (!session) {
|
|
119
|
-
return res.status(401).json({ message: "Session invalid or logged out" });
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
req.user = decoded;
|
|
123
|
-
next();
|
|
124
|
-
} catch (err: any) {
|
|
125
|
-
if (err.name === "TokenExpiredError") {
|
|
126
|
-
return res.status(401).json({ message: "Token expired" });
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
return res.status(401).json({ message: "Invalid token" });
|
|
130
|
-
}
|
|
131
|
-
};
|
|
132
|
-
`;
|
|
133
|
-
|
|
134
|
-
fs.writeFileSync(path.join(basePath, "auth.middleware.ts"), authContent.trim());
|
|
135
|
-
|
|
136
|
-
/* ================= ERROR ================= */
|
|
137
|
-
const errorContent = `
|
|
138
|
-
import { Request, Response, NextFunction } from "express";
|
|
139
|
-
|
|
140
|
-
export const errorMiddleware = (err: any, req: Request, res: Response, next: NextFunction) => {
|
|
141
|
-
console.error(err);
|
|
142
|
-
|
|
143
|
-
const status = err.status || 500;
|
|
144
|
-
const message = err.message || "Internal Server Error";
|
|
145
|
-
|
|
146
|
-
res.status(status).json({
|
|
147
|
-
success: false,
|
|
148
|
-
status,
|
|
149
|
-
message,
|
|
150
|
-
...(process.env.NODE_ENV === "development" && { stack: err.stack }),
|
|
151
|
-
});
|
|
152
|
-
};
|
|
153
|
-
`;
|
|
154
|
-
|
|
155
|
-
fs.writeFileSync(path.join(basePath, "error.middleware.ts"), errorContent.trim());
|
|
156
|
-
|
|
157
|
-
/* ================= LOGGER ================= */
|
|
158
|
-
const loggerContent = `
|
|
159
|
-
import { Request, Response, NextFunction } from "express";
|
|
160
|
-
import logger from "../utils/logger";
|
|
161
|
-
|
|
162
|
-
export const loggerMiddleware = (req: Request, res: Response, next: NextFunction) => {
|
|
163
|
-
const start = Date.now();
|
|
164
|
-
|
|
165
|
-
res.on("finish", () => {
|
|
166
|
-
const duration = Date.now() - start;
|
|
167
|
-
logger.info(\`[\${new Date().toISOString()}] \${req.method} \${req.originalUrl} \${res.statusCode} - \${duration}ms\`);
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
next();
|
|
171
|
-
};
|
|
172
|
-
`;
|
|
173
|
-
|
|
174
|
-
fs.writeFileSync(path.join(basePath, "logger.middleware.ts"), loggerContent.trim());
|
|
175
|
-
|
|
176
|
-
console.log(`✅ Middleware files generated successfully at ${basePath}`);
|
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
// scripts/generate-root-files.ts
|
|
2
|
-
import * as fs from "fs";
|
|
3
|
-
import * as path from "path";
|
|
4
|
-
import * as readline from "readline";
|
|
5
|
-
|
|
6
|
-
const rl = readline.createInterface({
|
|
7
|
-
input: process.stdin,
|
|
8
|
-
output: process.stdout,
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
rl.question("Enter project name: ", (projectName) => {
|
|
12
|
-
/* ================= tsconfig.json ================= */
|
|
13
|
-
const tsconfig = {
|
|
14
|
-
compilerOptions: {
|
|
15
|
-
module: "nodenext",
|
|
16
|
-
moduleResolution: "nodenext",
|
|
17
|
-
resolvePackageJsonExports: true,
|
|
18
|
-
esModuleInterop: true,
|
|
19
|
-
isolatedModules: true,
|
|
20
|
-
declaration: true,
|
|
21
|
-
removeComments: true,
|
|
22
|
-
emitDecoratorMetadata: true,
|
|
23
|
-
experimentalDecorators: true,
|
|
24
|
-
allowSyntheticDefaultImports: true,
|
|
25
|
-
target: "ES2023",
|
|
26
|
-
sourceMap: true,
|
|
27
|
-
rootDir: ".",
|
|
28
|
-
outDir: "./dist",
|
|
29
|
-
types: ["node"],
|
|
30
|
-
incremental: true,
|
|
31
|
-
skipLibCheck: true,
|
|
32
|
-
strictNullChecks: true,
|
|
33
|
-
forceConsistentCasingInFileNames: true,
|
|
34
|
-
noImplicitAny: false,
|
|
35
|
-
strictBindCallApply: false,
|
|
36
|
-
noFallthroughCasesInSwitch: false,
|
|
37
|
-
},
|
|
38
|
-
include: ["src", "server.ts", "prisma.config.ts"],
|
|
39
|
-
exclude: ["node_modules"],
|
|
40
|
-
assets: ["src/locales"],
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
fs.writeFileSync(
|
|
44
|
-
path.join(process.cwd(), "tsconfig.json"),
|
|
45
|
-
JSON.stringify(tsconfig, null, 2)
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
/* ================= package.json ================= */
|
|
49
|
-
const packageJson = {
|
|
50
|
-
name: projectName.toLowerCase().replace(/\s+/g, "-"),
|
|
51
|
-
version: "1.0.0",
|
|
52
|
-
description: `${projectName} backend.`,
|
|
53
|
-
license: "ISC",
|
|
54
|
-
author: "abir-hosen",
|
|
55
|
-
main: "server.ts",
|
|
56
|
-
scripts: {
|
|
57
|
-
"copy-locales": 'cpx "src/locales/**/*" dist/src/locales',
|
|
58
|
-
dev: "nodemon",
|
|
59
|
-
build: "tsc && npm run copy-locales",
|
|
60
|
-
start: "node dist/server.js",
|
|
61
|
-
"generate-module": "ts-node scripts/generate-module.ts",
|
|
62
|
-
"generate-middlewares": "ts-node scripts/middleware.ts",
|
|
63
|
-
"generate-locales": "ts-node scripts/generate-locales.ts",
|
|
64
|
-
"generate-utils": "ts-node scripts/generate-utils.ts"
|
|
65
|
-
},
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
fs.writeFileSync(
|
|
69
|
-
path.join(process.cwd(), "package.json"),
|
|
70
|
-
JSON.stringify(packageJson, null, 2)
|
|
71
|
-
);
|
|
72
|
-
|
|
73
|
-
/* ================= nodemon.json ================= */
|
|
74
|
-
const nodemon = {
|
|
75
|
-
watch: ["src"],
|
|
76
|
-
ext: "ts",
|
|
77
|
-
ignore: ["dist"],
|
|
78
|
-
exec: "ts-node src/server.ts",
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
fs.writeFileSync(
|
|
82
|
-
path.join(process.cwd(), "nodemon.json"),
|
|
83
|
-
JSON.stringify(nodemon, null, 2)
|
|
84
|
-
);
|
|
85
|
-
|
|
86
|
-
/* ================= .gitignore ================= */
|
|
87
|
-
const gitignore = `
|
|
88
|
-
node_modules
|
|
89
|
-
/src/generated/prisma
|
|
90
|
-
.env
|
|
91
|
-
package-lock.json
|
|
92
|
-
dist
|
|
93
|
-
pnpm-lock.yaml
|
|
94
|
-
/generated/prisma
|
|
95
|
-
`;
|
|
96
|
-
|
|
97
|
-
fs.writeFileSync(path.join(process.cwd(), ".gitignore"), gitignore.trim());
|
|
98
|
-
|
|
99
|
-
/* ================= .prisma ================= */
|
|
100
|
-
const prisma = `
|
|
101
|
-
// This is your Prisma schema file,
|
|
102
|
-
// learn more about it in the docs: https://pris.ly/d/prisma-schema
|
|
103
|
-
|
|
104
|
-
// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
|
|
105
|
-
// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init
|
|
106
|
-
|
|
107
|
-
generator client {
|
|
108
|
-
provider = "prisma-client-js"
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
datasource db {
|
|
112
|
-
provider = "postgresql"
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
model Common {
|
|
116
|
-
commonId String @id @default(uuid())
|
|
117
|
-
name String @unique
|
|
118
|
-
}
|
|
119
|
-
`;
|
|
120
|
-
|
|
121
|
-
fs.writeFileSync(path.join(process.cwd(), "prisma", "schema.prisma"), prisma.trim());
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
/* ================= .prisma ================= */
|
|
125
|
-
const prismaConfig = `
|
|
126
|
-
// This file was generated by Prisma, and assumes you have installed the following:
|
|
127
|
-
// npm install --save-dev prisma dotenv
|
|
128
|
-
import "dotenv/config";
|
|
129
|
-
import { defineConfig } from "prisma/config";
|
|
130
|
-
|
|
131
|
-
export default defineConfig({
|
|
132
|
-
schema: "prisma/schema.prisma",
|
|
133
|
-
migrations: {
|
|
134
|
-
path: "prisma/migrations",
|
|
135
|
-
},
|
|
136
|
-
datasource: {
|
|
137
|
-
url: process.env["DATABASE_URL"],
|
|
138
|
-
},
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
`;
|
|
142
|
-
|
|
143
|
-
fs.writeFileSync(path.join(process.cwd(), "prisma.config.ts"), prismaConfig.trim());
|
|
144
|
-
|
|
145
|
-
console.log(`✅ Root config files generated for project: ${projectName}`);
|
|
146
|
-
rl.close();
|
|
147
|
-
});
|