crypt-express-app 1.0.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.
@@ -0,0 +1,147 @@
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
+ });
@@ -0,0 +1,208 @@
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", "utils");
6
+
7
+ if (!fs.existsSync(basePath)) {
8
+ fs.mkdirSync(basePath, { recursive: true });
9
+ }
10
+
11
+ /* ================= redis.ts ================= */
12
+ const redisContent = `
13
+ import { createClient, RedisClientType } from "redis";
14
+ import { CONSTS } from "./consts";
15
+
16
+ let redis: RedisClientType = createClient({
17
+ url: CONSTS.REDIS_URL,
18
+ });
19
+
20
+ redis.on("connect", () => {
21
+ console.log("✅ Redis Connected");
22
+ });
23
+
24
+ redis.on("error", (err) => {
25
+ console.error("❌ Redis Error", err);
26
+ });
27
+
28
+ export const connectRedis = async () => {
29
+ if (!redis.isOpen) {
30
+ await redis.connect();
31
+ }
32
+ };
33
+
34
+ export class CacheService {
35
+ async set(key: string, value: any, ttl?: number) {
36
+ const stringValue = JSON.stringify(value);
37
+ ttl ? await redis.set(key, stringValue, { EX: ttl }) : await redis.set(key, stringValue);
38
+ }
39
+
40
+ async get<T>(key: string): Promise<T | null> {
41
+ const data = await redis.get(key);
42
+ return data ? JSON.parse(data) : null;
43
+ }
44
+
45
+ async del(key: string) {
46
+ await redis.del(key);
47
+ }
48
+ }
49
+
50
+ export const cacheService = new CacheService();
51
+ export default redis;
52
+ `;
53
+
54
+ fs.writeFileSync(path.join(basePath, "redis.ts"), redisContent.trim());
55
+
56
+ /* ================= cache.ts ================= */
57
+ const cacheContent = `
58
+ interface CachedSecret {
59
+ value: string;
60
+ expiresAt: number;
61
+ }
62
+
63
+ const realmSecretCache = new Map<string, CachedSecret>();
64
+ const DEFAULT_TTL_MS = 5 * 60 * 1000;
65
+
66
+ export const getCachedSecret = (realmId: string) => {
67
+ const cached = realmSecretCache.get(realmId);
68
+ if (!cached || cached.expiresAt < Date.now()) {
69
+ realmSecretCache.delete(realmId);
70
+ return null;
71
+ }
72
+ return cached.value;
73
+ };
74
+
75
+ export const setCachedSecret = (realmId: string, secret: string, ttlMs = DEFAULT_TTL_MS) => {
76
+ realmSecretCache.set(realmId, {
77
+ value: secret,
78
+ expiresAt: Date.now() + ttlMs,
79
+ });
80
+ };
81
+
82
+ export const invalidateSecret = (realmId: string) => {
83
+ realmSecretCache.delete(realmId);
84
+ };
85
+ `;
86
+
87
+ fs.writeFileSync(path.join(basePath, "cache.ts"), cacheContent.trim());
88
+
89
+ /* ================= redis.dto.ts ================= */
90
+ const redisDtoContent = `
91
+ export interface CachedUserProfilePermissionDto {
92
+ userId: string;
93
+ username: string;
94
+ email: string;
95
+ realm: {
96
+ realmId: string;
97
+ name: string;
98
+ };
99
+ roles: string[];
100
+ permissions: string[];
101
+ }
102
+ `;
103
+
104
+ fs.writeFileSync(path.join(basePath, "redis.dto.ts"), redisDtoContent.trim());
105
+
106
+ /* ================= logger.ts ================= */
107
+ const loggerContent = `
108
+ import winston from "winston";
109
+
110
+ const logger = winston.createLogger({
111
+ level: "info",
112
+ format: winston.format.combine(
113
+ winston.format.colorize(),
114
+ winston.format.timestamp(),
115
+ winston.format.printf(({ timestamp, level, message }) => \`[\${timestamp}] \${level}: \${message}\`)
116
+ ),
117
+ transports: [new winston.transports.Console()],
118
+ });
119
+
120
+ export default logger;
121
+ `;
122
+
123
+ fs.writeFileSync(path.join(basePath, "logger.ts"), loggerContent.trim());
124
+
125
+ /* ================= bootstrap.ts ================= */
126
+ const bootstrapContent = `
127
+ import prisma from "../prisma/client";
128
+ import logger from "./logger";
129
+
130
+ async function bootstrapSystem() {
131
+ // optional: seed data or migrations
132
+ console.log("🚀 System bootstrap complete");
133
+ }
134
+
135
+ export async function wipeAllTables() {
136
+ try {
137
+ await prisma.$executeRawUnsafe(\`TRUNCATE TABLE "User" CASCADE;\`);
138
+ logger.info("✅ All tables wiped successfully");
139
+ } catch (error) {
140
+ logger.error(error);
141
+ }
142
+ }
143
+
144
+ export default bootstrapSystem;
145
+ `;
146
+
147
+ fs.writeFileSync(path.join(basePath, "bootstrap.ts"), bootstrapContent.trim());
148
+
149
+ /* ================= consts.ts ================= */
150
+ const constsContent = `
151
+ export const CONSTS = {
152
+ REDIS_URL: process.env.REDIS_URL || "redis://localhost:6379",
153
+ };
154
+
155
+ export enum ActionsType {
156
+ CREATE = "CREATE",
157
+ READ = "READ",
158
+ READ_ALL = "READ_ALL",
159
+ UPDATE = "UPDATE",
160
+ DELETE = "DELETE",
161
+ }
162
+
163
+ export enum Resource {
164
+ COMMON = "COMMON",
165
+ }
166
+
167
+ export enum ResourceType {
168
+ API_ENDPOINT = "API_ENDPOINT",
169
+ UI_PAGE = "UI_PAGE",
170
+ FILE = "FILE",
171
+ SERVICE = "SERVICE",
172
+ DATASET = "DATASET",
173
+ }
174
+ `;
175
+
176
+ fs.writeFileSync(path.join(basePath, "consts.ts"), constsContent.trim());
177
+
178
+ /* ================= swagger.ts ================= */
179
+ const swaggerContent = `
180
+ import swaggerJsdoc from "swagger-jsdoc";
181
+
182
+ export const swaggerSpec = swaggerJsdoc({
183
+ definition: {
184
+ openapi: "3.0.0",
185
+ info: {
186
+ title: "Express REST API",
187
+ version: "1.0.0",
188
+ description: "RESTful API with Express + TypeScript + Swagger",
189
+ },
190
+ components: {
191
+ securitySchemes: {
192
+ bearerAuth: {
193
+ type: "http",
194
+ scheme: "bearer",
195
+ bearerFormat: "JWT",
196
+ },
197
+ },
198
+ },
199
+ security: [{ bearerAuth: [] }],
200
+ servers: [{ url: "http://localhost:3000" }],
201
+ },
202
+ apis: ["./src/**/*.routes.ts", "./src/**/*.dto.ts"],
203
+ });
204
+ `;
205
+
206
+ fs.writeFileSync(path.join(basePath, "swagger.ts"), swaggerContent.trim());
207
+
208
+ console.log("✅ Utils files generated successfully inside src/utils");
@@ -0,0 +1,26 @@
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", "prisma");
6
+
7
+ if (!fs.existsSync(basePath)) {
8
+ fs.mkdirSync(basePath, { recursive: true });
9
+ }
10
+
11
+ const clientContent = `
12
+ import { PrismaClient } from "@prisma/client";
13
+ import { PrismaPg } from "@prisma/adapter-pg";
14
+ import "dotenv/config";
15
+
16
+ const connectionString = process.env.DATABASE_URL;
17
+
18
+ const adapter = new PrismaPg({ connectionString });
19
+ const prisma = new PrismaClient({ adapter });
20
+
21
+ export default prisma;
22
+ `;
23
+
24
+ fs.writeFileSync(path.join(basePath, "client.ts"), clientContent.trim());
25
+
26
+ console.log(`✅ Prisma client generated successfully at ${basePath}`);
package/tsconfig.json ADDED
@@ -0,0 +1,10 @@
1
+ {
2
+ "compilerOptions": {
3
+ "outDir": "dist",
4
+ "module": "ESNext",
5
+ "target": "ES2020",
6
+ "moduleResolution": "Node",
7
+ "esModuleInterop": true
8
+ },
9
+ "include": ["index.ts", "scripts"]
10
+ }