@ifecodes/backend-template 1.1.3 → 1.1.5
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 +39 -18
- package/bin/cli.js +207 -80
- package/bin/lib/microservice-config.js +57 -13
- package/bin/lib/prompts.js +10 -6
- package/bin/lib/readme-generator.js +75 -14
- package/bin/lib/service-setup.js +272 -126
- package/package.json +1 -1
- package/template/base/js/.eslintrc.json +13 -0
- package/template/base/js/.prettierrc +7 -0
- package/template/base/js/eslint.config.js +31 -0
- package/template/base/js/package.json +28 -0
- package/template/base/js/src/app.js +15 -0
- package/template/base/js/src/config/db.js +8 -0
- package/template/base/js/src/config/env.js +14 -0
- package/template/base/js/src/config/index.js +7 -0
- package/template/base/js/src/middlewares/index.js +9 -0
- package/template/base/js/src/middlewares/method-not-allowed.middleware.js +13 -0
- package/template/base/js/src/middlewares/not-found.middleware.js +10 -0
- package/template/base/js/src/middlewares/root.middleware.js +16 -0
- package/template/base/js/src/modules/index.js +8 -0
- package/template/base/js/src/modules/v1/health/health.controller.js +21 -0
- package/template/base/js/src/modules/v1/health/health.route.js +9 -0
- package/template/base/js/src/modules/v1/health/index.js +5 -0
- package/template/base/js/src/modules/v1/index.js +8 -0
- package/template/base/js/src/routes.js +16 -0
- package/template/base/js/src/server.js +18 -0
- package/template/base/js/src/utils/http-error.js +53 -0
- package/template/base/js/src/utils/index.js +22 -0
- package/template/base/js/src/utils/logger.js +67 -0
- package/template/base/ts/.env.example +5 -0
- package/template/base/ts/.husky/pre-commit +13 -0
- package/template/base/ts/.prettierignore +47 -0
- package/template/base/ts/gitignore +31 -0
- package/template/base/ts/src/app.ts +15 -0
- package/template/base/{src → ts/src}/config/env.ts +10 -10
- package/template/base/{src → ts/src}/middlewares/index.ts +3 -3
- package/template/base/{src → ts/src}/middlewares/method-not-allowed.middleware.ts +16 -17
- package/template/base/{src → ts/src}/middlewares/root.middleware.ts +2 -2
- package/template/base/{src → ts/src}/modules/v1/health/health.controller.ts +18 -18
- package/template/base/{src → ts/src}/modules/v1/health/health.route.ts +9 -9
- package/template/base/{src → ts/src}/modules/v1/health/index.ts +1 -1
- package/template/base/{src → ts/src}/modules/v1/index.ts +8 -8
- package/template/base/{src → ts/src}/routes.ts +15 -15
- package/template/base/{src → ts/src}/utils/http-error.ts +45 -45
- package/template/base/{src → ts/src}/utils/logger.ts +23 -0
- package/template/features/auth/argon2/inject.js +29 -4
- package/template/features/auth/base/inject.js +108 -26
- package/template/features/auth/bcrypt/inject.js +25 -5
- package/template/features/auth/models/user.model.js +24 -0
- package/template/features/auth/modules/auth.controller.js +21 -0
- package/template/features/auth/modules/auth.routes.js +10 -0
- package/template/features/auth/modules/auth.service.js +29 -0
- package/template/features/auth/modules/index.js +1 -0
- package/template/features/auth/utils/jwt.js +12 -0
- package/template/features/cors/inject.js +4 -1
- package/template/features/helmet/inject.js +4 -1
- package/template/features/morgan/inject.js +4 -1
- package/template/features/rate-limit/inject.js +4 -1
- package/template/gateway/js/app.js +42 -0
- package/template/gateway/js/inject.js +31 -0
- package/template/gateway/js/server.js +19 -0
- package/template/gateway/{app.ts → ts/app.ts} +19 -3
- package/template/gateway/ts/inject.js +31 -0
- package/template/gateway/{server.ts → ts/server.ts} +3 -3
- package/template/microservice/docker/.dockerignore +10 -0
- package/template/microservice/docker/Dockerfile +2 -1
- package/template/microservice/docker/docker-compose.yml +0 -1
- package/bin/lib/ts-to-js.js +0 -342
- package/template/base/src/app.ts +0 -8
- package/template/gateway/inject.js +0 -27
- /package/template/base/{.env.example → js/.env.example} +0 -0
- /package/template/base/{.husky → js/.husky}/pre-commit +0 -0
- /package/template/base/{.prettierignore → js/.prettierignore} +0 -0
- /package/template/base/{gitignore → js/gitignore} +0 -0
- /package/template/base/{.eslintrc.json → ts/.eslintrc.json} +0 -0
- /package/template/base/{.prettierrc → ts/.prettierrc} +0 -0
- /package/template/base/{eslint.config.js → ts/eslint.config.js} +0 -0
- /package/template/base/{package.json → ts/package.json} +0 -0
- /package/template/base/{src → ts/src}/config/db.ts +0 -0
- /package/template/base/{src → ts/src}/config/index.ts +0 -0
- /package/template/base/{src → ts/src}/middlewares/not-found.middleware.ts +0 -0
- /package/template/base/{src → ts/src}/modules/index.ts +0 -0
- /package/template/base/{src → ts/src}/server.ts +0 -0
- /package/template/base/{src → ts/src}/utils/index.ts +0 -0
- /package/template/base/{tsconfig.json → ts/tsconfig.json} +0 -0
|
@@ -1,11 +1,27 @@
|
|
|
1
1
|
import express, { Request, Response, NextFunction } from "express";
|
|
2
2
|
import { createProxyMiddleware } from "http-proxy-middleware";
|
|
3
|
-
import { logger } from "@/utils";
|
|
3
|
+
import { logger } from "@/shared/utils";
|
|
4
4
|
|
|
5
5
|
const app = express();
|
|
6
6
|
|
|
7
|
+
// Root endpoint
|
|
8
|
+
app.get("/", (_req: Request, res: Response) => {
|
|
9
|
+
logger.info("Gateway", "Root endpoint accessed");
|
|
10
|
+
|
|
11
|
+
res.json({
|
|
12
|
+
status: "ok",
|
|
13
|
+
service: "API Gateway",
|
|
14
|
+
version: "1.0.0",
|
|
15
|
+
endpoints: {
|
|
16
|
+
health: "/health",
|
|
17
|
+
healthService: "/api/v1/health"
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
|
|
7
22
|
// Health check for the gateway itself
|
|
8
23
|
app.get("/health", (_req: Request, res: Response) => {
|
|
24
|
+
logger.info("Gateway", "Health check accessed");
|
|
9
25
|
res.json({ status: "ok", service: "gateway" });
|
|
10
26
|
});
|
|
11
27
|
|
|
@@ -13,12 +29,12 @@ app.get("/health", (_req: Request, res: Response) => {
|
|
|
13
29
|
/*__ROUTES__*/
|
|
14
30
|
|
|
15
31
|
// 404 handler
|
|
16
|
-
app.use((
|
|
32
|
+
app.use((_req: Request, res: Response) => {
|
|
17
33
|
res.status(404).json({ error: "Route not found" });
|
|
18
34
|
});
|
|
19
35
|
|
|
20
36
|
// Error handler
|
|
21
|
-
app.use((err:
|
|
37
|
+
app.use((err: Error, _req: Request, res: Response, next: NextFunction) => {
|
|
22
38
|
logger.error("Gateway error:", err);
|
|
23
39
|
res.status(500).json({ error: "Internal gateway error" });
|
|
24
40
|
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export const gatewayDeps = ["http-proxy-middleware"];
|
|
2
|
+
|
|
3
|
+
export const generateGatewayRoutes = (services, mode = "docker") => {
|
|
4
|
+
const routes = services
|
|
5
|
+
.filter((s) => s !== "gateway")
|
|
6
|
+
.map((service, index) => {
|
|
7
|
+
const port = 4001 + index; // Host port mapping: gateway=4000, services start at 4001
|
|
8
|
+
const routePath = service.replace("-service", "");
|
|
9
|
+
|
|
10
|
+
// Docker: use container name with internal port 4000
|
|
11
|
+
// Non-docker: use localhost with mapped host port
|
|
12
|
+
const host = mode === "docker" ? service : "localhost";
|
|
13
|
+
const targetPort = mode === "docker" ? 4000 : port;
|
|
14
|
+
|
|
15
|
+
return `
|
|
16
|
+
// Proxy to ${service}
|
|
17
|
+
app.use("/api", createProxyMiddleware({
|
|
18
|
+
target: "http://${host}:${targetPort}/api",
|
|
19
|
+
changeOrigin: true,
|
|
20
|
+
on: {
|
|
21
|
+
error: (err, req, res) => {
|
|
22
|
+
logger.error(\`Proxy error for ${service}:\`, err);
|
|
23
|
+
(res as Response).status(503).json({ error: "Service unavailable" });
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
}));`;
|
|
27
|
+
})
|
|
28
|
+
.join("\n");
|
|
29
|
+
|
|
30
|
+
return routes;
|
|
31
|
+
};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import http from "http";
|
|
2
2
|
import app from "./app";
|
|
3
|
-
import { logger } from "@/utils";
|
|
4
|
-
import { ENV } from "@/config";
|
|
3
|
+
import { logger } from "@/shared/utils";
|
|
4
|
+
import { ENV } from "@/shared/config";
|
|
5
5
|
|
|
6
|
-
const PORT = ENV.
|
|
6
|
+
const PORT = ENV.GATEWAY_PORT || 4000;
|
|
7
7
|
|
|
8
8
|
const server = http.createServer(app);
|
|
9
9
|
|
package/bin/lib/ts-to-js.js
DELETED
|
@@ -1,342 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Transform TypeScript files to JavaScript
|
|
3
|
-
* Removes type annotations and converts file extensions
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Strip TypeScript type annotations from code and fix imports for JavaScript
|
|
8
|
-
* @param {string} content - TypeScript file content
|
|
9
|
-
* @returns {string} - JavaScript content
|
|
10
|
-
*/
|
|
11
|
-
export function stripTypeScript(content) {
|
|
12
|
-
let jsContent = content;
|
|
13
|
-
|
|
14
|
-
// Remove type imports
|
|
15
|
-
jsContent = jsContent.replace(/^import\s+type\s+.*?;?\s*$/gm, '');
|
|
16
|
-
|
|
17
|
-
// Remove type-only imports from regular imports
|
|
18
|
-
jsContent = jsContent.replace(/,\s*type\s+\{[^}]+\}/g, '');
|
|
19
|
-
jsContent = jsContent.replace(/import\s+\{[^}]*type\s+[^}]*\}/g, (match) => {
|
|
20
|
-
return match.replace(/,?\s*type\s+\w+/g, '').replace(/\{\s*,/, '{').replace(/,\s*\}/, '}');
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
// Remove imports from express types (Request, Response, NextFunction, etc.)
|
|
24
|
-
jsContent = jsContent.replace(/import\s*\{\s*Request\s*,\s*Response\s*,\s*NextFunction\s*\}\s*from\s*["']express["'];?\s*\n/gm, '');
|
|
25
|
-
jsContent = jsContent.replace(/import\s*\{\s*Request\s*,\s*Response\s*\}\s*from\s*["']express["'];?\s*\n/gm, '');
|
|
26
|
-
jsContent = jsContent.replace(/import\s*\{\s*Response\s*,\s*Request\s*\}\s*from\s*["']express["'];?\s*\n/gm, '');
|
|
27
|
-
jsContent = jsContent.replace(/import\s*\{\s*Request\s*\}\s*from\s*["']express["'];?\s*\n/gm, '');
|
|
28
|
-
jsContent = jsContent.replace(/import\s*\{\s*Response\s*\}\s*from\s*["']express["'];?\s*\n/gm, '');
|
|
29
|
-
jsContent = jsContent.replace(/import\s*\{\s*NextFunction\s*\}\s*from\s*["']express["'];?\s*\n/gm, '');
|
|
30
|
-
|
|
31
|
-
// Remove interface declarations
|
|
32
|
-
// CRITICAL: Must have 'interface' keyword explicitly (not 'const' or other keywords)
|
|
33
|
-
// Single-line interfaces
|
|
34
|
-
jsContent = jsContent.replace(/^export\s+interface\s+\w+(\s+extends\s+[\w,\s]+)?\s*\{[^}]*\}\s*;?\s*$/gm, '');
|
|
35
|
-
jsContent = jsContent.replace(/^interface\s+\w+(\s+extends\s+[\w,\s]+)?\s*\{[^}]*\}\s*;?\s*$/gm, '');
|
|
36
|
-
|
|
37
|
-
// Multi-line interfaces - must have a line break after the interface name/extends before {
|
|
38
|
-
// This prevents matching regular object literals
|
|
39
|
-
jsContent = jsContent.replace(/^export\s+interface\s+\w+(\s+extends\s+[\w,\s<>]+)?\s*\{[\s\S]*?^}/gm, '');
|
|
40
|
-
jsContent = jsContent.replace(/^interface\s+\w+(\s+extends\s+[\w,\s<>]+)?\s*\{[\s\S]*?^}/gm, '');
|
|
41
|
-
|
|
42
|
-
// Remove type aliases
|
|
43
|
-
jsContent = jsContent.replace(/^export\s+type\s+\w+\s*=\s*[^;]+;\s*$/gm, '');
|
|
44
|
-
jsContent = jsContent.replace(/^type\s+\w+\s*=\s*[^;]+;\s*$/gm, '');
|
|
45
|
-
|
|
46
|
-
// Remove class property type annotations: public/private/protected status: number;
|
|
47
|
-
// CRITICAL: Only match single-line class properties (use [^\n;=]+ instead of [^;=]+)
|
|
48
|
-
jsContent = jsContent.replace(/^\s*(public|private|protected)?\s+(\w+)\s*:\s*[^\n;=]+;/gm, '');
|
|
49
|
-
|
|
50
|
-
// Remove visibility modifiers and types from constructor parameters
|
|
51
|
-
jsContent = jsContent.replace(/constructor\s*\(\s*([^)]*)\)\s*\{/g, (match, params) => {
|
|
52
|
-
if (!params.trim()) return 'constructor() {';
|
|
53
|
-
const cleanParams = params
|
|
54
|
-
.split(',')
|
|
55
|
-
.map(p => {
|
|
56
|
-
// Remove visibility modifiers
|
|
57
|
-
let cleaned = p.replace(/^\s*(public|private|protected)\s+/, '');
|
|
58
|
-
// Remove type annotation (everything after :)
|
|
59
|
-
cleaned = cleaned.replace(/:\s*[^=,]+/, '');
|
|
60
|
-
return cleaned.trim();
|
|
61
|
-
})
|
|
62
|
-
.filter(p => p)
|
|
63
|
-
.join(', ');
|
|
64
|
-
return `constructor(${cleanParams}) {`;
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
// Remove ! non-null assertions FIRST (before other transformations)
|
|
68
|
-
// Only remove ! that appears after identifiers, closing brackets, or closing parentheses
|
|
69
|
-
// Be very conservative to avoid breaking other syntax
|
|
70
|
-
jsContent = jsContent.replace(/([a-zA-Z0-9_\])])!/g, '$1');
|
|
71
|
-
|
|
72
|
-
// Remove function parameter types - IMPROVED VERSION
|
|
73
|
-
// Handle spread parameters: ...args: Type[] => ...args
|
|
74
|
-
jsContent = jsContent.replace(/(\.\.\.\s*\w+)\s*:\s*[^,)]+/g, '$1');
|
|
75
|
-
|
|
76
|
-
// Handle regular parameters with more precision
|
|
77
|
-
// Strategy: Clean type annotations from parameter lists while avoiding object literals in function CALLS
|
|
78
|
-
|
|
79
|
-
// 1. Function declarations: function name(params) {
|
|
80
|
-
jsContent = jsContent.replace(/function\s+\w+\s*\(([^)]*)\)/g, (match, params) => {
|
|
81
|
-
if (!params.includes(':')) return match;
|
|
82
|
-
// Skip if it has object literals (look for : followed by value, not type)
|
|
83
|
-
// Object literals have patterns like {key: value} while types have param: Type
|
|
84
|
-
const cleaned = params.split(',').map(p => p.replace(/:\s*[^,=)]+(?=[,)]|$)/, '')).join(',');
|
|
85
|
-
return match.replace(params, cleaned);
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
// 2. Arrow functions: (params) => or (params) => {
|
|
89
|
-
// Be more specific: only skip if we see actual object literal patterns {key:value}
|
|
90
|
-
jsContent = jsContent.replace(/\(([^)]+)\)\s*=>/g, (match, params) => {
|
|
91
|
-
if (!params.includes(':')) return match;
|
|
92
|
-
|
|
93
|
-
// Check if this looks like an object literal: has both { and } with content between
|
|
94
|
-
if (/\{[^}]+\}/.test(params)) return match;
|
|
95
|
-
|
|
96
|
-
const cleaned = params.split(',').map(p => p.replace(/:\s*[^,=)]+(?=[,)]|$)/, '')).join(',');
|
|
97
|
-
return `(${cleaned}) =>`;
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
// 3. Method definitions in classes/objects: methodName(params) {
|
|
101
|
-
jsContent = jsContent.replace(/(\w+)\s*\(([^)]*)\)\s*\{/g, (match, name, params) => {
|
|
102
|
-
if (!params.includes(':')) return match;
|
|
103
|
-
// Skip if it looks like object destructuring in params
|
|
104
|
-
if (/\{[^}]+\}/.test(params)) return match;
|
|
105
|
-
const cleaned = params.split(',').map(p => p.replace(/:\s*[^,=)]+(?=[,)]|$)/, '')).join(',');
|
|
106
|
-
return `${name}(${cleaned}) {`;
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
// Remove return type annotations - IMPROVED VERSION
|
|
110
|
-
// Match ): Type => but only consume the type part
|
|
111
|
-
jsContent = jsContent.replace(/\)\s*:\s*[^{=>]+(\s*=>)/g, ')$1');
|
|
112
|
-
jsContent = jsContent.replace(/\)\s*:\s*[^{=>]+(\s*\{)/g, ')$1');
|
|
113
|
-
|
|
114
|
-
// Remove function parameter types in function declarations
|
|
115
|
-
jsContent = jsContent.replace(/function\s+(\w+)\s*:\s*[^=]+/g, 'function $1');
|
|
116
|
-
|
|
117
|
-
// Remove as type assertions (including 'as const')
|
|
118
|
-
jsContent = jsContent.replace(/\s+as\s+(const|any|unknown|readonly|\w+)/g, '');
|
|
119
|
-
|
|
120
|
-
// Remove satisfies operators
|
|
121
|
-
jsContent = jsContent.replace(/\s+satisfies\s+[^;,\n]+/g, '');
|
|
122
|
-
|
|
123
|
-
// Remove angle bracket type assertions: <Type>value => value (but not JSX)
|
|
124
|
-
jsContent = jsContent.replace(/<[\w\[\]]+>(?=[^<]*[^>])/g, '');
|
|
125
|
-
|
|
126
|
-
// Remove optional property markers: property?: Type => property
|
|
127
|
-
jsContent = jsContent.replace(/(\w+)\?\s*:/g, '$1:');
|
|
128
|
-
|
|
129
|
-
// Remove generic type parameters from class/function declarations
|
|
130
|
-
jsContent = jsContent.replace(/(class|function|interface)\s+(\w+)\s*<[^>]+>/g, '$1 $2');
|
|
131
|
-
|
|
132
|
-
// Remove enum declarations (convert to object)
|
|
133
|
-
jsContent = jsContent.replace(/enum\s+(\w+)\s*\{([^}]+)\}/g, (match, name, body) => {
|
|
134
|
-
const entries = body.split(',').map(e => e.trim()).filter(Boolean);
|
|
135
|
-
const obj = entries.map(e => {
|
|
136
|
-
const [key, value] = e.split('=').map(s => s.trim());
|
|
137
|
-
return value ? ` ${key}: ${value}` : ` ${key}: "${key}"`;
|
|
138
|
-
}).join(',\n');
|
|
139
|
-
return `const ${name} = {\n${obj}\n}`;
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
// Fix import paths for Node.js ESM
|
|
143
|
-
// 1. Replace TypeScript alias @/ with Node.js native #/
|
|
144
|
-
jsContent = jsContent.replace(/from\s+["']@\//g, 'from "#/');
|
|
145
|
-
jsContent = jsContent.replace(/import\s*\(\s*["']@\//g, 'import("#/');
|
|
146
|
-
jsContent = jsContent.replace(/require\s*\(\s*["']@\//g, 'require("#/');
|
|
147
|
-
|
|
148
|
-
// 2. Add .js extension to #/ imports (they're now pointing to .js files)
|
|
149
|
-
jsContent = jsContent.replace(/from\s+["']#\/([^"']+)["']/g, (match, path) => {
|
|
150
|
-
// Don't add .js if it already has an extension or is a directory import
|
|
151
|
-
if (path.endsWith('.js') || path.endsWith('.json') || path.endsWith('/')) {
|
|
152
|
-
return match;
|
|
153
|
-
}
|
|
154
|
-
return `from "#/${path}.js"`;
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
// 3. Add .js extension to relative imports
|
|
158
|
-
jsContent = jsContent.replace(/from\s+["'](\.\.?\/[^"']+)["']/g, (match, path) => {
|
|
159
|
-
// Don't add .js if it already has an extension
|
|
160
|
-
if (path.match(/\.\w+$/)) {
|
|
161
|
-
return match;
|
|
162
|
-
}
|
|
163
|
-
return `from "${path}.js"`;
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
// Remove multiple consecutive blank lines
|
|
167
|
-
jsContent = jsContent.replace(/\n\s*\n\s*\n/g, '\n\n');
|
|
168
|
-
|
|
169
|
-
return jsContent;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* Get JavaScript package.json scripts
|
|
174
|
-
* @returns {Object} - Scripts for JavaScript project
|
|
175
|
-
*/
|
|
176
|
-
export function getJavaScriptScripts() {
|
|
177
|
-
return {
|
|
178
|
-
dev: "nodemon --exec node src/server.js",
|
|
179
|
-
start: "node src/server.js",
|
|
180
|
-
lint: 'eslint "src/**/*.js"',
|
|
181
|
-
format: 'prettier --write "src/**/*.{js,json}"',
|
|
182
|
-
"check-format": 'prettier --check "src/**/*.{js,json}"',
|
|
183
|
-
prepare: "husky"
|
|
184
|
-
};
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
/**
|
|
188
|
-
* Get JavaScript dependencies (remove TS-specific ones)
|
|
189
|
-
* @param {Object} originalDeps - Original TypeScript dependencies
|
|
190
|
-
* @param {Object} originalDevDeps - Original TypeScript devDependencies
|
|
191
|
-
* @returns {Object} - { dependencies, devDependencies }
|
|
192
|
-
*/
|
|
193
|
-
export function getJavaScriptDependencies(originalDeps, originalDevDeps) {
|
|
194
|
-
// Remove TypeScript-specific packages
|
|
195
|
-
const tsPackages = [
|
|
196
|
-
'typescript',
|
|
197
|
-
'ts-node-dev',
|
|
198
|
-
'tsconfig-paths',
|
|
199
|
-
'@typescript-eslint/eslint-plugin',
|
|
200
|
-
'@typescript-eslint/parser'
|
|
201
|
-
];
|
|
202
|
-
|
|
203
|
-
const typePackages = Object.keys(originalDevDeps).filter(pkg => pkg.startsWith('@types/'));
|
|
204
|
-
|
|
205
|
-
const devDeps = { ...originalDevDeps };
|
|
206
|
-
|
|
207
|
-
// Remove TS packages
|
|
208
|
-
[...tsPackages, ...typePackages].forEach(pkg => {
|
|
209
|
-
delete devDeps[pkg];
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
// Add nodemon for JS development
|
|
213
|
-
devDeps.nodemon = '^3.0.2';
|
|
214
|
-
|
|
215
|
-
return {
|
|
216
|
-
dependencies: { ...originalDeps },
|
|
217
|
-
devDependencies: devDeps
|
|
218
|
-
};
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
/**
|
|
222
|
-
* Get package.json imports field for Node.js native path aliasing
|
|
223
|
-
* This replaces TypeScript's tsconfig paths with Node's native imports
|
|
224
|
-
* @returns {Object} - imports configuration
|
|
225
|
-
*/
|
|
226
|
-
export function getNodeImportsConfig() {
|
|
227
|
-
return {
|
|
228
|
-
"#/*": "./src/*"
|
|
229
|
-
};
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
import fs from 'fs';
|
|
233
|
-
import path from 'path';
|
|
234
|
-
|
|
235
|
-
/**
|
|
236
|
-
* Transform a single TypeScript file to JavaScript
|
|
237
|
-
* @param {string} filePath - Path to .ts file
|
|
238
|
-
*/
|
|
239
|
-
function transformFile(filePath) {
|
|
240
|
-
const content = fs.readFileSync(filePath, 'utf-8');
|
|
241
|
-
const jsContent = stripTypeScript(content);
|
|
242
|
-
|
|
243
|
-
// Write to .js file
|
|
244
|
-
const jsFilePath = filePath.replace(/\.ts$/, '.js');
|
|
245
|
-
fs.writeFileSync(jsFilePath, jsContent);
|
|
246
|
-
|
|
247
|
-
// Remove original .ts file
|
|
248
|
-
fs.unlinkSync(filePath);
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
/**
|
|
252
|
-
* Recursively transform all .ts files in a directory to .js
|
|
253
|
-
* @param {string} dir - Directory path
|
|
254
|
-
*/
|
|
255
|
-
export function transformDirectory(dir) {
|
|
256
|
-
if (!fs.existsSync(dir)) return;
|
|
257
|
-
|
|
258
|
-
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
259
|
-
|
|
260
|
-
for (const entry of entries) {
|
|
261
|
-
const fullPath = path.join(dir, entry.name);
|
|
262
|
-
|
|
263
|
-
if (entry.isDirectory()) {
|
|
264
|
-
// Skip node_modules and other non-source directories
|
|
265
|
-
if (entry.name === 'node_modules' || entry.name === '.git') {
|
|
266
|
-
continue;
|
|
267
|
-
}
|
|
268
|
-
transformDirectory(fullPath);
|
|
269
|
-
} else if (entry.isFile() && entry.name.endsWith('.ts')) {
|
|
270
|
-
transformFile(fullPath);
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
/**
|
|
276
|
-
* Main function to transform a TypeScript project to JavaScript
|
|
277
|
-
* @param {string} targetDir - Root directory of the project
|
|
278
|
-
*/
|
|
279
|
-
export function transformToJavaScript(targetDir) {
|
|
280
|
-
// Transform all .ts files to .js
|
|
281
|
-
const srcDir = path.join(targetDir, 'src');
|
|
282
|
-
if (fs.existsSync(srcDir)) {
|
|
283
|
-
transformDirectory(srcDir);
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
// Update package.json
|
|
287
|
-
const packageJsonPath = path.join(targetDir, 'package.json');
|
|
288
|
-
if (fs.existsSync(packageJsonPath)) {
|
|
289
|
-
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
|
290
|
-
|
|
291
|
-
// Get JavaScript dependencies
|
|
292
|
-
const { dependencies, devDependencies } = getJavaScriptDependencies(
|
|
293
|
-
packageJson.dependencies || {},
|
|
294
|
-
packageJson.devDependencies || {}
|
|
295
|
-
);
|
|
296
|
-
|
|
297
|
-
// Update package.json
|
|
298
|
-
packageJson.dependencies = dependencies;
|
|
299
|
-
packageJson.devDependencies = devDependencies;
|
|
300
|
-
packageJson.scripts = getJavaScriptScripts();
|
|
301
|
-
|
|
302
|
-
// Add Node.js native imports for path aliasing
|
|
303
|
-
packageJson.imports = getNodeImportsConfig();
|
|
304
|
-
|
|
305
|
-
// Ensure type: module is set
|
|
306
|
-
packageJson.type = 'module';
|
|
307
|
-
|
|
308
|
-
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\n');
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
// Remove tsconfig.json if it exists
|
|
312
|
-
const tsconfigPath = path.join(targetDir, 'tsconfig.json');
|
|
313
|
-
if (fs.existsSync(tsconfigPath)) {
|
|
314
|
-
fs.unlinkSync(tsconfigPath);
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
// Update .prettierrc if it exists to use .js instead of .ts
|
|
318
|
-
const prettierrcPath = path.join(targetDir, '.prettierrc');
|
|
319
|
-
if (fs.existsSync(prettierrcPath)) {
|
|
320
|
-
let prettierConfig = fs.readFileSync(prettierrcPath, 'utf-8');
|
|
321
|
-
prettierConfig = prettierConfig.replace(/\.ts/g, '.js');
|
|
322
|
-
fs.writeFileSync(prettierrcPath, prettierConfig);
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
// Update eslint.config.js if it exists
|
|
326
|
-
const eslintConfigPath = path.join(targetDir, 'eslint.config.js');
|
|
327
|
-
if (fs.existsSync(eslintConfigPath)) {
|
|
328
|
-
let eslintConfig = fs.readFileSync(eslintConfigPath, 'utf-8');
|
|
329
|
-
|
|
330
|
-
// Remove TypeScript parser and plugin
|
|
331
|
-
eslintConfig = eslintConfig.replace(/@typescript-eslint\/parser/g, '');
|
|
332
|
-
eslintConfig = eslintConfig.replace(/@typescript-eslint\/eslint-plugin/g, '');
|
|
333
|
-
eslintConfig = eslintConfig.replace(/tseslint\./g, '');
|
|
334
|
-
eslintConfig = eslintConfig.replace(/import tseslint[^\n]+\n/g, '');
|
|
335
|
-
|
|
336
|
-
// Update file patterns
|
|
337
|
-
eslintConfig = eslintConfig.replace(/\*\*\/\*\.ts/g, '**/*.js');
|
|
338
|
-
|
|
339
|
-
fs.writeFileSync(eslintConfigPath, eslintConfig);
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
|
package/template/base/src/app.ts
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
export const gatewayDeps = ["http-proxy-middleware"];
|
|
2
|
-
|
|
3
|
-
export const generateGatewayRoutes = (services) => {
|
|
4
|
-
const routes = services
|
|
5
|
-
.filter(s => s !== "gateway")
|
|
6
|
-
.map((service, index) => {
|
|
7
|
-
const port = 4001 + index; // Gateway is 4000, services start at 4001
|
|
8
|
-
const routePath = service.replace("-service", "");
|
|
9
|
-
|
|
10
|
-
return `
|
|
11
|
-
// Route ${service} to port ${port}
|
|
12
|
-
app.use("/${routePath}", createProxyMiddleware({
|
|
13
|
-
target: "http://localhost:${port}",
|
|
14
|
-
changeOrigin: true,
|
|
15
|
-
pathRewrite: {
|
|
16
|
-
"^/${routePath}": "",
|
|
17
|
-
},
|
|
18
|
-
onError: (err, req, res) => {
|
|
19
|
-
logger.error(\`Proxy error for ${service}:\`, err);
|
|
20
|
-
res.status(503).json({ error: "Service unavailable" });
|
|
21
|
-
},
|
|
22
|
-
}));`;
|
|
23
|
-
})
|
|
24
|
-
.join("\n");
|
|
25
|
-
|
|
26
|
-
return routes;
|
|
27
|
-
};
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|