@edifice.io/edifice-nestjs-core 1.0.0 → 1.0.3-develop.20260513125613
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 +43 -2
- package/dist/appregistry/appregistry.service.js +2 -2
- package/dist/appregistry/appregistry.service.js.map +1 -1
- package/dist/bin/generate-rest-clients.d.ts +2 -0
- package/dist/bin/generate-rest-clients.js +581 -0
- package/dist/bin/generate-rest-clients.js.map +1 -0
- package/dist/bin/generate-swagger-pdf.d.ts +1 -0
- package/dist/bin/generate-swagger-pdf.js +172 -0
- package/dist/bin/generate-swagger-pdf.js.map +1 -0
- package/dist/config/configuration.d.ts +23 -0
- package/dist/config/configuration.js +39 -0
- package/dist/config/configuration.js.map +1 -1
- package/dist/config/postgres.config.js +2 -0
- package/dist/config/postgres.config.js.map +1 -1
- package/dist/core.module.js +22 -9
- package/dist/core.module.js.map +1 -1
- package/dist/database/migration.service.js +3 -3
- package/dist/database/migration.service.js.map +1 -1
- package/dist/frontend.controller.js +6 -6
- package/dist/frontend.controller.js.map +1 -1
- package/dist/health/health.controller.js +2 -2
- package/dist/health/health.controller.js.map +1 -1
- package/dist/i18n/i18n-bootstrap.service.d.ts +13 -0
- package/dist/i18n/i18n-bootstrap.service.js +54 -0
- package/dist/i18n/i18n-bootstrap.service.js.map +1 -0
- package/dist/i18n/i18n-lifecycle.controller.d.ts +17 -0
- package/dist/i18n/i18n-lifecycle.controller.js +55 -0
- package/dist/i18n/i18n-lifecycle.controller.js.map +1 -0
- package/dist/i18n/i18n.module.js +4 -1
- package/dist/i18n/i18n.module.js.map +1 -1
- package/dist/i18n/i18n.service.d.ts +1 -0
- package/dist/i18n/i18n.service.js +8 -0
- package/dist/i18n/i18n.service.js.map +1 -1
- package/dist/i18n/index.d.ts +2 -3
- package/dist/i18n/index.js +2 -2
- package/dist/i18n/index.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/logger/request-logger.service.js +3 -2
- package/dist/logger/request-logger.service.js.map +1 -1
- package/dist/performance/copy-metadata.utils.d.ts +1 -0
- package/dist/performance/copy-metadata.utils.js +9 -0
- package/dist/performance/copy-metadata.utils.js.map +1 -0
- package/dist/performance/correlation.interceptor.d.ts +5 -0
- package/dist/performance/correlation.interceptor.js +28 -0
- package/dist/performance/correlation.interceptor.js.map +1 -0
- package/dist/performance/index.d.ts +4 -0
- package/dist/performance/index.js +16 -0
- package/dist/performance/index.js.map +1 -0
- package/dist/performance/performance-stats.d.ts +26 -0
- package/dist/performance/performance-stats.js +57 -0
- package/dist/performance/performance-stats.js.map +1 -0
- package/dist/performance/performance.decorator.d.ts +11 -0
- package/dist/performance/performance.decorator.js +56 -0
- package/dist/performance/performance.decorator.js.map +1 -0
- package/dist/performance/performance.module.d.ts +5 -0
- package/dist/performance/performance.module.js +38 -0
- package/dist/performance/performance.module.js.map +1 -0
- package/dist/permission/admc.guard.d.ts +0 -3
- package/dist/permission/admc.guard.js +1 -18
- package/dist/permission/admc.guard.js.map +1 -1
- package/dist/permission/basicauth.guard.d.ts +12 -0
- package/dist/permission/basicauth.guard.js +54 -0
- package/dist/permission/basicauth.guard.js.map +1 -0
- package/dist/permission/decorators.d.ts +10 -0
- package/dist/permission/decorators.js +20 -0
- package/dist/permission/decorators.js.map +1 -0
- package/dist/permission/global.guard.d.ts +16 -0
- package/dist/permission/global.guard.js +68 -0
- package/dist/permission/global.guard.js.map +1 -0
- package/dist/permission/index.d.ts +4 -3
- package/dist/permission/index.js +4 -3
- package/dist/permission/index.js.map +1 -1
- package/dist/permission/permission.guard.d.ts +1 -1
- package/dist/permission/permission.guard.js +2 -18
- package/dist/permission/permission.guard.js.map +1 -1
- package/dist/permission/require-login.guard.d.ts +8 -0
- package/dist/permission/require-login.guard.js +49 -0
- package/dist/permission/require-login.guard.js.map +1 -0
- package/dist/redirect/redirect-lifecycle.controller.d.ts +15 -0
- package/dist/redirect/redirect-lifecycle.controller.js +48 -0
- package/dist/redirect/redirect-lifecycle.controller.js.map +1 -0
- package/dist/redirect/redirect.module.d.ts +2 -0
- package/dist/redirect/redirect.module.js +25 -0
- package/dist/redirect/redirect.module.js.map +1 -0
- package/dist/redirect/redirect.service.d.ts +28 -0
- package/dist/redirect/redirect.service.js +154 -0
- package/dist/redirect/redirect.service.js.map +1 -0
- package/dist/session/frontend-session.middleware.d.ts +10 -0
- package/dist/session/frontend-session.middleware.js +40 -0
- package/dist/session/frontend-session.middleware.js.map +1 -0
- package/dist/session/query-param-token.middleware.d.ts +11 -0
- package/dist/session/query-param-token.middleware.js +68 -0
- package/dist/session/query-param-token.middleware.js.map +1 -0
- package/dist/session/session-middleware.utils.d.ts +17 -0
- package/dist/session/session-middleware.utils.js +82 -0
- package/dist/session/session-middleware.utils.js.map +1 -0
- package/dist/session/session.middleware.d.ts +8 -8
- package/dist/session/session.middleware.js +29 -47
- package/dist/session/session.middleware.js.map +1 -1
- package/dist/session/session.module.js +14 -2
- package/dist/session/session.module.js.map +1 -1
- package/dist/timeline/index.d.ts +2 -3
- package/dist/timeline/index.js +2 -2
- package/dist/timeline/index.js.map +1 -1
- package/dist/timeline/timeline-i18n-bootstrap.service.d.ts +13 -0
- package/dist/timeline/timeline-i18n-bootstrap.service.js +54 -0
- package/dist/timeline/timeline-i18n-bootstrap.service.js.map +1 -0
- package/dist/timeline/timeline-lifecycle.controller.d.ts +17 -0
- package/dist/timeline/timeline-lifecycle.controller.js +55 -0
- package/dist/timeline/timeline-lifecycle.controller.js.map +1 -0
- package/dist/timeline/timeline.module.js +4 -1
- package/dist/timeline/timeline.module.js.map +1 -1
- package/dist/timeline/timeline.service.d.ts +11 -0
- package/dist/timeline/timeline.service.js +98 -13
- package/dist/timeline/timeline.service.js.map +1 -1
- package/dist/timeline/timeline.types.d.ts +8 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utils/static-assets.utils.js +1 -1
- package/dist/utils/static-assets.utils.js.map +1 -1
- package/package.json +19 -12
- package/dist/permission/admc.decorator.d.ts +0 -2
- package/dist/permission/admc.decorator.js +0 -11
- package/dist/permission/admc.decorator.js.map +0 -1
- package/dist/permission/permission.decorator.d.ts +0 -2
- package/dist/permission/permission.decorator.js +0 -8
- package/dist/permission/permission.decorator.js.map +0 -1
- package/dist/permission/public.decorator.d.ts +0 -2
- package/dist/permission/public.decorator.js +0 -8
- package/dist/permission/public.decorator.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
# About edifice-nestjs-core
|
|
2
|
+
|
|
3
|
+
- Licence : Copyright Edifice
|
|
4
|
+
- Funder(s) : Edifice
|
|
5
|
+
- Developer(s) : Edifice
|
|
6
|
+
|
|
1
7
|
# @edifice.io/edifice-nestjs-core
|
|
2
8
|
|
|
3
9
|
Core NestJS modules and utilities for Edifice applications.
|
|
@@ -661,10 +667,10 @@ It provides decorators and guards for workflow-based and admin authorization, en
|
|
|
661
667
|
|
|
662
668
|
**Features:**
|
|
663
669
|
|
|
664
|
-
- `@RequirePermission('PERMISSION_NAME')`: Restricts access to endpoints based on user workflow rights.
|
|
670
|
+
- `@RequirePermission('PERMISSION_NAME')`: Restricts access to endpoints based on user workflow rights. Mandatory decorator.
|
|
665
671
|
- `@RequireAdmc()`: Restricts access to endpoints for super administrators (ADMC).
|
|
666
672
|
- `@Public()`: Marks endpoints as public (no authentication required).
|
|
667
|
-
-
|
|
673
|
+
- `@BasicAuth()`: Adds Basic authorization method for an endpoint. The authorized user and password are set in configuration.
|
|
668
674
|
|
|
669
675
|
**How it works:**
|
|
670
676
|
|
|
@@ -988,6 +994,7 @@ Each tool is available as a binary when you install `@edifice.io/edifice-nestjs-
|
|
|
988
994
|
- **edifice-generate-entities**: Generate MikroORM entities from database schema
|
|
989
995
|
- **edifice-generate-metadata**: Generate application metadata file
|
|
990
996
|
- **edifice-k6-sync-dto**: Synchronize DTOs for K6 Testing
|
|
997
|
+
- **generate-swagger-pdf**: Generate a PDF from your NestJS API Swagger documentation
|
|
991
998
|
|
|
992
999
|
---
|
|
993
1000
|
|
|
@@ -1073,6 +1080,40 @@ pnpm edifice-k6-sync-dto
|
|
|
1073
1080
|
|
|
1074
1081
|
---
|
|
1075
1082
|
|
|
1083
|
+
#### generate-swagger-pdf
|
|
1084
|
+
|
|
1085
|
+
**Purpose:**
|
|
1086
|
+
Generate a PDF from the Swagger (OpenAPI) documentation exposed by your NestJS server.
|
|
1087
|
+
|
|
1088
|
+
**Usage:**
|
|
1089
|
+
|
|
1090
|
+
```bash
|
|
1091
|
+
npx generate-swagger-pdf --host <host> --port <port>
|
|
1092
|
+
```
|
|
1093
|
+
|
|
1094
|
+
**Options:**
|
|
1095
|
+
|
|
1096
|
+
- `--host`, `-h`: Swagger server host (default: `127.0.0.1`)
|
|
1097
|
+
- `--port`, `-p`: Swagger server port (default: `3002`)
|
|
1098
|
+
|
|
1099
|
+
The PDF will be generated in the `documentation/api-docs.pdf` folder of your project.
|
|
1100
|
+
|
|
1101
|
+
**Example:**
|
|
1102
|
+
|
|
1103
|
+
```bash
|
|
1104
|
+
npx generate-swagger-pdf --host 127.0.0.1 --port 4000
|
|
1105
|
+
```
|
|
1106
|
+
|
|
1107
|
+
This package provides several CLI tools to help you automate common backend tasks.
|
|
1108
|
+
Each tool is available as a binary when you install `@edifice.io/edifice-nestjs-core`.
|
|
1109
|
+
|
|
1110
|
+
- **edifice-generate-entities**: Generate MikroORM entities from database schema
|
|
1111
|
+
- **edifice-generate-metadata**: Generate application metadata file
|
|
1112
|
+
- **edifice-k6-sync-dto**: Synchronize DTOs for K6 Testing
|
|
1113
|
+
- **generate-swagger-pdf**: Generate a PDF from your NestJS API Swagger documentation
|
|
1114
|
+
|
|
1115
|
+
---
|
|
1116
|
+
|
|
1076
1117
|
**Note:**
|
|
1077
1118
|
All CLI tools are available after installing the package.
|
|
1078
1119
|
You can run them with `pnpm` or `npx` from your project root.
|
|
@@ -15,7 +15,7 @@ const edifice_ent_client_1 = require("@edifice.io/edifice-ent-client");
|
|
|
15
15
|
const common_1 = require("@nestjs/common");
|
|
16
16
|
const config_1 = require("@nestjs/config");
|
|
17
17
|
const core_1 = require("@nestjs/core");
|
|
18
|
-
const
|
|
18
|
+
const decorators_1 = require("../permission/decorators");
|
|
19
19
|
let AppRegistryService = AppRegistryService_1 = class AppRegistryService {
|
|
20
20
|
configService;
|
|
21
21
|
entClient;
|
|
@@ -42,7 +42,7 @@ let AppRegistryService = AppRegistryService_1 = class AppRegistryService {
|
|
|
42
42
|
const controllerName = instance.constructor.name;
|
|
43
43
|
this.metadataScanner.scanFromPrototype(instance, prototype, (methodName) => {
|
|
44
44
|
const methodRef = prototype[methodName];
|
|
45
|
-
const permission = Reflect.getMetadata(
|
|
45
|
+
const permission = Reflect.getMetadata(decorators_1.PERMISSION_KEY, methodRef);
|
|
46
46
|
if (permission) {
|
|
47
47
|
if (Array.isArray(permission)) {
|
|
48
48
|
permission.forEach((p) => permissionsSet.add(p));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"appregistry.service.js","sourceRoot":"","sources":["../../src/appregistry/appregistry.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,uEAGwC;AAExC,2CAAoD;AACpD,2CAA+C;AAC/C,uCAAiE;AAEjE,
|
|
1
|
+
{"version":3,"file":"appregistry.service.js","sourceRoot":"","sources":["../../src/appregistry/appregistry.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,581 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
const ts = __importStar(require("typescript"));
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
const PRIMITIVE_TYPES = new Set([
|
|
41
|
+
'string',
|
|
42
|
+
'number',
|
|
43
|
+
'boolean',
|
|
44
|
+
'Date',
|
|
45
|
+
'any',
|
|
46
|
+
'void',
|
|
47
|
+
'object',
|
|
48
|
+
'never',
|
|
49
|
+
'unknown',
|
|
50
|
+
'null',
|
|
51
|
+
'undefined',
|
|
52
|
+
]);
|
|
53
|
+
function parseControllers(filePath) {
|
|
54
|
+
const program = ts.createProgram([filePath], {
|
|
55
|
+
target: ts.ScriptTarget.ES2020,
|
|
56
|
+
module: ts.ModuleKind.CommonJS,
|
|
57
|
+
});
|
|
58
|
+
const sourceFile = program.getSourceFile(filePath);
|
|
59
|
+
if (!sourceFile) {
|
|
60
|
+
throw new Error(`Could not load source file: ${filePath}`);
|
|
61
|
+
}
|
|
62
|
+
const controllers = [];
|
|
63
|
+
ts.forEachChild(sourceFile, (node) => {
|
|
64
|
+
if (ts.isClassDeclaration(node) && node.name) {
|
|
65
|
+
const controllerDecorator = getDecorator(node, 'Controller');
|
|
66
|
+
if (!controllerDecorator)
|
|
67
|
+
return;
|
|
68
|
+
const basePath = getDecoratorArgument(controllerDecorator) || '';
|
|
69
|
+
const apiTagDecorator = getDecorator(node, 'ApiTags');
|
|
70
|
+
const tag = apiTagDecorator
|
|
71
|
+
? getDecoratorArgument(apiTagDecorator)
|
|
72
|
+
: undefined;
|
|
73
|
+
const controller = {
|
|
74
|
+
name: node.name.text,
|
|
75
|
+
basePath,
|
|
76
|
+
methods: [],
|
|
77
|
+
jsdoc: getJsDoc(node),
|
|
78
|
+
tag,
|
|
79
|
+
};
|
|
80
|
+
node.members.forEach((member) => {
|
|
81
|
+
if (ts.isMethodDeclaration(member) && member.name) {
|
|
82
|
+
const methodMetadata = parseMethod(member);
|
|
83
|
+
if (methodMetadata) {
|
|
84
|
+
controller.methods.push(methodMetadata);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
controllers.push(controller);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
return controllers;
|
|
92
|
+
}
|
|
93
|
+
function parseMethod(method) {
|
|
94
|
+
const httpMethods = ['Get', 'Post', 'Put', 'Patch', 'Delete'];
|
|
95
|
+
let httpMethod = null;
|
|
96
|
+
let routePath = '';
|
|
97
|
+
for (const httpMethodName of httpMethods) {
|
|
98
|
+
const decorator = getDecorator(method, httpMethodName);
|
|
99
|
+
if (decorator) {
|
|
100
|
+
httpMethod = httpMethodName.toUpperCase();
|
|
101
|
+
routePath = getDecoratorArgument(decorator) || '';
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (!httpMethod)
|
|
106
|
+
return null;
|
|
107
|
+
const methodName = method.name.text;
|
|
108
|
+
const params = [];
|
|
109
|
+
const reservedNames = new Set(['options', 'queryParams']);
|
|
110
|
+
method.parameters.forEach((param) => {
|
|
111
|
+
let paramName = param.name.text;
|
|
112
|
+
if (getDecorator(param, 'Req'))
|
|
113
|
+
return;
|
|
114
|
+
const paramDecorator = getDecorator(param, 'Param');
|
|
115
|
+
const queryDecorator = getDecorator(param, 'Query');
|
|
116
|
+
const bodyDecorator = getDecorator(param, 'Body');
|
|
117
|
+
let paramType = getTypeName(param.type);
|
|
118
|
+
if (paramDecorator) {
|
|
119
|
+
const expression = paramDecorator.expression;
|
|
120
|
+
if (ts.isCallExpression(expression) && expression.arguments.length > 1) {
|
|
121
|
+
const pipeArg = expression.arguments[1];
|
|
122
|
+
let pipeName = '';
|
|
123
|
+
if (ts.isIdentifier(pipeArg)) {
|
|
124
|
+
pipeName = pipeArg.text;
|
|
125
|
+
}
|
|
126
|
+
else if (ts.isNewExpression(pipeArg) &&
|
|
127
|
+
ts.isIdentifier(pipeArg.expression)) {
|
|
128
|
+
pipeName = pipeArg.expression.text;
|
|
129
|
+
}
|
|
130
|
+
const pipeTypeMap = {
|
|
131
|
+
ParseIntPipe: 'number',
|
|
132
|
+
ParseBoolPipe: 'boolean',
|
|
133
|
+
ParseFloatPipe: 'number',
|
|
134
|
+
ParseUUIDPipe: 'string',
|
|
135
|
+
ParseEnumPipe: 'string',
|
|
136
|
+
};
|
|
137
|
+
for (const [pipe, type] of Object.entries(pipeTypeMap)) {
|
|
138
|
+
if (pipeName.includes(pipe)) {
|
|
139
|
+
paramType = type;
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
if (bodyDecorator) {
|
|
146
|
+
const bodyFieldArg = getDecoratorArgument(bodyDecorator);
|
|
147
|
+
if (bodyFieldArg) {
|
|
148
|
+
paramName = bodyFieldArg;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
if (queryDecorator) {
|
|
152
|
+
const queryFieldArg = getDecoratorArgument(queryDecorator);
|
|
153
|
+
if (queryFieldArg) {
|
|
154
|
+
paramName = queryFieldArg;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
if (reservedNames.has(paramName)) {
|
|
158
|
+
paramName = `_${paramName}`;
|
|
159
|
+
}
|
|
160
|
+
if (paramDecorator) {
|
|
161
|
+
params.push({
|
|
162
|
+
name: paramName,
|
|
163
|
+
type: paramType,
|
|
164
|
+
decorator: 'Param',
|
|
165
|
+
isOptional: !!param.questionToken,
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
else if (queryDecorator) {
|
|
169
|
+
params.push({
|
|
170
|
+
name: paramName,
|
|
171
|
+
type: paramType,
|
|
172
|
+
decorator: 'Query',
|
|
173
|
+
isOptional: !!param.questionToken,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
else if (bodyDecorator) {
|
|
177
|
+
params.push({
|
|
178
|
+
name: paramName,
|
|
179
|
+
type: paramType,
|
|
180
|
+
decorator: 'Body',
|
|
181
|
+
isOptional: !!param.questionToken,
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
const returnType = getReturnType(method);
|
|
186
|
+
const apiOperationDecorator = getDecorator(method, 'ApiOperation');
|
|
187
|
+
const operationSummary = apiOperationDecorator
|
|
188
|
+
? getDecoratorObjectProperty(apiOperationDecorator, 'summary')
|
|
189
|
+
: undefined;
|
|
190
|
+
return {
|
|
191
|
+
name: methodName,
|
|
192
|
+
httpMethod,
|
|
193
|
+
path: routePath,
|
|
194
|
+
params,
|
|
195
|
+
returnType,
|
|
196
|
+
jsdoc: getJsDoc(method),
|
|
197
|
+
operationSummary,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
function getDecorator(node, decoratorName) {
|
|
201
|
+
const decorators = ts.getDecorators(node);
|
|
202
|
+
if (!decorators)
|
|
203
|
+
return undefined;
|
|
204
|
+
return decorators.find((decorator) => {
|
|
205
|
+
try {
|
|
206
|
+
const expression = decorator.expression;
|
|
207
|
+
if (ts.isCallExpression(expression)) {
|
|
208
|
+
const callExpression = expression.expression;
|
|
209
|
+
if (ts.isIdentifier(callExpression)) {
|
|
210
|
+
return callExpression.text === decoratorName;
|
|
211
|
+
}
|
|
212
|
+
if (ts.isPropertyAccessExpression(callExpression)) {
|
|
213
|
+
const name = callExpression.name;
|
|
214
|
+
if (ts.isIdentifier(name)) {
|
|
215
|
+
return name.text === decoratorName;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return false;
|
|
219
|
+
}
|
|
220
|
+
if (ts.isIdentifier(expression)) {
|
|
221
|
+
return expression.text === decoratorName;
|
|
222
|
+
}
|
|
223
|
+
if (ts.isPropertyAccessExpression(expression)) {
|
|
224
|
+
const name = expression.name;
|
|
225
|
+
if (ts.isIdentifier(name)) {
|
|
226
|
+
return name.text === decoratorName;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
231
|
+
catch (_) {
|
|
232
|
+
return false;
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
function getDecoratorArgument(decorator) {
|
|
237
|
+
const expression = decorator.expression;
|
|
238
|
+
if (ts.isCallExpression(expression) && expression.arguments.length > 0) {
|
|
239
|
+
const arg = expression.arguments[0];
|
|
240
|
+
if (ts.isStringLiteral(arg)) {
|
|
241
|
+
return arg.text;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
return undefined;
|
|
245
|
+
}
|
|
246
|
+
function getDecoratorObjectProperty(decorator, propertyName) {
|
|
247
|
+
const expression = decorator.expression;
|
|
248
|
+
if (ts.isCallExpression(expression) && expression.arguments.length > 0) {
|
|
249
|
+
const arg = expression.arguments[0];
|
|
250
|
+
if (ts.isObjectLiteralExpression(arg)) {
|
|
251
|
+
const property = arg.properties.find((prop) => {
|
|
252
|
+
if (!ts.isPropertyAssignment(prop))
|
|
253
|
+
return false;
|
|
254
|
+
let propName;
|
|
255
|
+
if (ts.isIdentifier(prop.name)) {
|
|
256
|
+
propName = prop.name.text;
|
|
257
|
+
}
|
|
258
|
+
else if (ts.isStringLiteral(prop.name)) {
|
|
259
|
+
propName = prop.name.text;
|
|
260
|
+
}
|
|
261
|
+
return propName === propertyName;
|
|
262
|
+
});
|
|
263
|
+
if (property && ts.isPropertyAssignment(property)) {
|
|
264
|
+
if (ts.isStringLiteral(property.initializer)) {
|
|
265
|
+
return property.initializer.text;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
return undefined;
|
|
271
|
+
}
|
|
272
|
+
function getReturnType(method) {
|
|
273
|
+
if (!method.type)
|
|
274
|
+
return 'void';
|
|
275
|
+
try {
|
|
276
|
+
const typeNode = method.type;
|
|
277
|
+
if (ts.isTypeReferenceNode(typeNode)) {
|
|
278
|
+
const typeName = ts.isIdentifier(typeNode.typeName)
|
|
279
|
+
? typeNode.typeName.text
|
|
280
|
+
: 'any';
|
|
281
|
+
if (typeName === 'Promise' &&
|
|
282
|
+
typeNode.typeArguments &&
|
|
283
|
+
typeNode.typeArguments.length > 0) {
|
|
284
|
+
const innerType = getTypeName(typeNode.typeArguments[0]);
|
|
285
|
+
return innerType === 'void' ? 'void' : innerType;
|
|
286
|
+
}
|
|
287
|
+
return typeName;
|
|
288
|
+
}
|
|
289
|
+
if (ts.isIdentifier(typeNode)) {
|
|
290
|
+
return typeNode.text;
|
|
291
|
+
}
|
|
292
|
+
if (typeNode.kind === ts.SyntaxKind.VoidKeyword) {
|
|
293
|
+
return 'void';
|
|
294
|
+
}
|
|
295
|
+
return 'void';
|
|
296
|
+
}
|
|
297
|
+
catch (_) {
|
|
298
|
+
return 'void';
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
function getTypeName(typeNode) {
|
|
302
|
+
if (!typeNode)
|
|
303
|
+
return 'any';
|
|
304
|
+
try {
|
|
305
|
+
if (typeNode.kind === ts.SyntaxKind.VoidKeyword) {
|
|
306
|
+
return 'void';
|
|
307
|
+
}
|
|
308
|
+
if (typeNode.kind === ts.SyntaxKind.StringKeyword) {
|
|
309
|
+
return 'string';
|
|
310
|
+
}
|
|
311
|
+
if (typeNode.kind === ts.SyntaxKind.NumberKeyword) {
|
|
312
|
+
return 'number';
|
|
313
|
+
}
|
|
314
|
+
if (typeNode.kind === ts.SyntaxKind.BooleanKeyword) {
|
|
315
|
+
return 'boolean';
|
|
316
|
+
}
|
|
317
|
+
if (ts.isIdentifier(typeNode)) {
|
|
318
|
+
return typeNode.text;
|
|
319
|
+
}
|
|
320
|
+
if (ts.isArrayTypeNode(typeNode)) {
|
|
321
|
+
const elementType = getTypeName(typeNode.elementType);
|
|
322
|
+
return `${elementType}[]`;
|
|
323
|
+
}
|
|
324
|
+
if (ts.isTypeReferenceNode(typeNode)) {
|
|
325
|
+
const typeName = ts.isIdentifier(typeNode.typeName)
|
|
326
|
+
? typeNode.typeName.text
|
|
327
|
+
: typeNode.typeName.getText?.();
|
|
328
|
+
if (typeNode.typeArguments && typeNode.typeArguments.length > 0) {
|
|
329
|
+
const args = typeNode.typeArguments
|
|
330
|
+
.map((arg) => getTypeName(arg))
|
|
331
|
+
.join(', ');
|
|
332
|
+
return `${typeName}<${args}>`;
|
|
333
|
+
}
|
|
334
|
+
return typeName || 'any';
|
|
335
|
+
}
|
|
336
|
+
if (ts.isUnionTypeNode(typeNode)) {
|
|
337
|
+
return typeNode.types.map((t) => getTypeName(t)).join(' | ');
|
|
338
|
+
}
|
|
339
|
+
if (ts.isTypeLiteralNode(typeNode)) {
|
|
340
|
+
const members = typeNode.members
|
|
341
|
+
.map((member) => {
|
|
342
|
+
if (ts.isPropertySignature(member) && member.name && member.type) {
|
|
343
|
+
const propName = ts.isIdentifier(member.name)
|
|
344
|
+
? member.name.text
|
|
345
|
+
: member.name.getText?.() || 'unknown';
|
|
346
|
+
const propType = getTypeName(member.type);
|
|
347
|
+
const optional = member.questionToken ? '?' : '';
|
|
348
|
+
return `${propName}${optional}: ${propType}`;
|
|
349
|
+
}
|
|
350
|
+
return null;
|
|
351
|
+
})
|
|
352
|
+
.filter(Boolean)
|
|
353
|
+
.join('; ');
|
|
354
|
+
return `{ ${members} }`;
|
|
355
|
+
}
|
|
356
|
+
if (typeNode.getText && typeNode.getSourceFile?.()) {
|
|
357
|
+
return typeNode.getText();
|
|
358
|
+
}
|
|
359
|
+
return 'any';
|
|
360
|
+
}
|
|
361
|
+
catch (_) {
|
|
362
|
+
return 'any';
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
function getJsDoc(node) {
|
|
366
|
+
const jsDocTags = ts.getJSDocTags(node);
|
|
367
|
+
if (jsDocTags.length > 0) {
|
|
368
|
+
return jsDocTags.map((tag) => tag.comment).join('\n');
|
|
369
|
+
}
|
|
370
|
+
return undefined;
|
|
371
|
+
}
|
|
372
|
+
function generateClientClass(controller) {
|
|
373
|
+
const clientName = controller.name.replace('Controller', 'Client');
|
|
374
|
+
const methods = controller.methods.map((method) => generateClientMethod(controller.basePath, method));
|
|
375
|
+
const dtoImports = new Set();
|
|
376
|
+
const shouldImportType = (type) => {
|
|
377
|
+
if (PRIMITIVE_TYPES.has(type))
|
|
378
|
+
return false;
|
|
379
|
+
if (type.startsWith('{'))
|
|
380
|
+
return false;
|
|
381
|
+
if (type.includes('{') && type.includes('}'))
|
|
382
|
+
return false;
|
|
383
|
+
return true;
|
|
384
|
+
};
|
|
385
|
+
controller.methods.forEach((method) => {
|
|
386
|
+
method.params.forEach((param) => {
|
|
387
|
+
const baseType = param.type.replace('[]', '');
|
|
388
|
+
if (shouldImportType(baseType)) {
|
|
389
|
+
dtoImports.add(baseType);
|
|
390
|
+
}
|
|
391
|
+
});
|
|
392
|
+
const baseReturnType = method.returnType.replace('[]', '');
|
|
393
|
+
if (shouldImportType(baseReturnType)) {
|
|
394
|
+
dtoImports.add(baseReturnType);
|
|
395
|
+
}
|
|
396
|
+
});
|
|
397
|
+
const imports = Array.from(dtoImports).join(', ');
|
|
398
|
+
const importsSection = imports
|
|
399
|
+
? `import {
|
|
400
|
+
${imports}
|
|
401
|
+
} from "../../../dtos";
|
|
402
|
+
`
|
|
403
|
+
: '';
|
|
404
|
+
return `import {
|
|
405
|
+
BaseApiClient,
|
|
406
|
+
ApiClientOptions,
|
|
407
|
+
RequestOptions,
|
|
408
|
+
} from "@edifice.io/rest-client-base";
|
|
409
|
+
${importsSection}
|
|
410
|
+
/**
|
|
411
|
+
* Client for interacting with the ${controller.tag || controller.name} API
|
|
412
|
+
* ${controller.jsdoc || ''}
|
|
413
|
+
*
|
|
414
|
+
* @example
|
|
415
|
+
* // Basic usage with fetch (default)
|
|
416
|
+
* const client = new ${clientName}();
|
|
417
|
+
*
|
|
418
|
+
* @example
|
|
419
|
+
* // With Edifice HttpService
|
|
420
|
+
* import { odeServices } from '@edifice.io/client';
|
|
421
|
+
*
|
|
422
|
+
* const httpService = odeServices.http();
|
|
423
|
+
* const client = new ${clientName}({
|
|
424
|
+
* httpService: httpService
|
|
425
|
+
* });
|
|
426
|
+
*/
|
|
427
|
+
export class ${clientName} extends BaseApiClient {
|
|
428
|
+
/**
|
|
429
|
+
* Creates a new ${clientName}
|
|
430
|
+
* @param options Client configuration options
|
|
431
|
+
*/
|
|
432
|
+
constructor(options: ApiClientOptions = {}) {
|
|
433
|
+
super(options);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
${methods.join('\n\n')}
|
|
437
|
+
}
|
|
438
|
+
`;
|
|
439
|
+
}
|
|
440
|
+
function generateClientMethod(basePath, method) {
|
|
441
|
+
const methodName = toCamelCase(method.name);
|
|
442
|
+
const params = [];
|
|
443
|
+
const queryParams = [];
|
|
444
|
+
const pathParams = new Map();
|
|
445
|
+
let bodyParam = null;
|
|
446
|
+
method.params.forEach((param) => {
|
|
447
|
+
const paramDeclaration = `${param.name}${param.isOptional ? '?' : ''}: ${param.type}`;
|
|
448
|
+
if (param.decorator === 'Param') {
|
|
449
|
+
params.push(paramDeclaration);
|
|
450
|
+
pathParams.set(param.name, param.type);
|
|
451
|
+
}
|
|
452
|
+
else if (param.decorator === 'Query') {
|
|
453
|
+
params.push(paramDeclaration);
|
|
454
|
+
queryParams.push(param.name);
|
|
455
|
+
}
|
|
456
|
+
else if (param.decorator === 'Body') {
|
|
457
|
+
params.push(paramDeclaration);
|
|
458
|
+
bodyParam = param.name;
|
|
459
|
+
}
|
|
460
|
+
});
|
|
461
|
+
params.push('options?: RequestOptions');
|
|
462
|
+
let url = basePath;
|
|
463
|
+
if (method.path) {
|
|
464
|
+
if (!basePath.endsWith('/') && !method.path.startsWith('/')) {
|
|
465
|
+
url += '/';
|
|
466
|
+
}
|
|
467
|
+
url += method.path;
|
|
468
|
+
}
|
|
469
|
+
pathParams.forEach((_, paramName) => {
|
|
470
|
+
url = url.replace(`:${paramName}`, `\${${paramName}}`);
|
|
471
|
+
});
|
|
472
|
+
const queryParamsCode = queryParams.length > 0
|
|
473
|
+
? `
|
|
474
|
+
const queryParams = new URLSearchParams();
|
|
475
|
+
${queryParams
|
|
476
|
+
.map((param) => {
|
|
477
|
+
const paramMeta = method.params.find((p) => p.name === param);
|
|
478
|
+
if (paramMeta?.isOptional) {
|
|
479
|
+
return ` if (${param}) queryParams.append("${param}", String(${param}));`;
|
|
480
|
+
}
|
|
481
|
+
return ` queryParams.append("${param}", String(${param}));`;
|
|
482
|
+
})
|
|
483
|
+
.join('\n')}
|
|
484
|
+
`
|
|
485
|
+
: '';
|
|
486
|
+
const queryArg = queryParams.length > 0 ? 'queryParams' : 'undefined';
|
|
487
|
+
const httpMethodLower = method.httpMethod.toLowerCase();
|
|
488
|
+
const returnType = method.returnType === 'void'
|
|
489
|
+
? 'Promise<void>'
|
|
490
|
+
: `Promise<${method.returnType}>`;
|
|
491
|
+
const jsdoc = method.operationSummary || method.jsdoc || '';
|
|
492
|
+
let methodCall;
|
|
493
|
+
if (httpMethodLower === 'get' || httpMethodLower === 'delete') {
|
|
494
|
+
const genericType = method.returnType === 'void' ? '' : `<${method.returnType}>`;
|
|
495
|
+
methodCall = `this.${httpMethodLower}${genericType}(
|
|
496
|
+
\`${url}\`,
|
|
497
|
+
${queryArg},
|
|
498
|
+
options
|
|
499
|
+
)`;
|
|
500
|
+
}
|
|
501
|
+
else {
|
|
502
|
+
const bodyArg = bodyParam || 'undefined';
|
|
503
|
+
const genericType = method.returnType === 'void' ? '' : `<${method.returnType}>`;
|
|
504
|
+
methodCall = `this.${httpMethodLower}${genericType}(
|
|
505
|
+
\`${url}\`,
|
|
506
|
+
${bodyArg},
|
|
507
|
+
${queryArg},
|
|
508
|
+
options
|
|
509
|
+
)`;
|
|
510
|
+
}
|
|
511
|
+
return ` /**
|
|
512
|
+
* ${jsdoc}
|
|
513
|
+
${method.params.map((p) => ` * @param ${p.name} ${p.type}`).join('\n')}
|
|
514
|
+
* @param options Additional request options
|
|
515
|
+
* @returns ${method.returnType === 'void' ? 'void' : method.returnType}
|
|
516
|
+
*/
|
|
517
|
+
async ${methodName}(
|
|
518
|
+
${params.join(',\n ')}
|
|
519
|
+
): ${returnType} {${queryParamsCode}
|
|
520
|
+
return ${methodCall};
|
|
521
|
+
}`;
|
|
522
|
+
}
|
|
523
|
+
function toCamelCase(str) {
|
|
524
|
+
return str.charAt(0).toLowerCase() + str.slice(1);
|
|
525
|
+
}
|
|
526
|
+
function generateIndexFile(clientOutputDir, controllers) {
|
|
527
|
+
const clientNames = controllers.map((controller) => controller.name.replace('Controller', 'Client'));
|
|
528
|
+
const imports = clientNames
|
|
529
|
+
.map((name) => {
|
|
530
|
+
const fileName = toCamelCase(name.replace('Client', ''));
|
|
531
|
+
return `export { ${name} } from "./${fileName}.client";`;
|
|
532
|
+
})
|
|
533
|
+
.join('\n');
|
|
534
|
+
const indexFilePath = path.join(clientOutputDir, 'clients', 'index.ts');
|
|
535
|
+
const indexContent = `// This file is auto-generated by generate-rest-clients.ts
|
|
536
|
+
// Do not edit manually
|
|
537
|
+
|
|
538
|
+
${imports}
|
|
539
|
+
`;
|
|
540
|
+
fs.writeFileSync(indexFilePath, indexContent, 'utf-8');
|
|
541
|
+
console.log(`✅ Generated ${indexFilePath}`);
|
|
542
|
+
}
|
|
543
|
+
const args = process.argv.slice(2);
|
|
544
|
+
if (args.length < 2) {
|
|
545
|
+
console.warn('Usage: generate-rest-clients <backend-src-dir> <client-output-dir>');
|
|
546
|
+
}
|
|
547
|
+
const backendSrcDir = path.resolve(args[0] || './backend/src');
|
|
548
|
+
const clientOutputDir = path.resolve(args[1] || './client/rest/src/clients/generated');
|
|
549
|
+
const controllerFiles = [];
|
|
550
|
+
function findControllerFiles(dir) {
|
|
551
|
+
const files = fs.readdirSync(dir);
|
|
552
|
+
files.forEach((file) => {
|
|
553
|
+
const fullPath = path.join(dir, file);
|
|
554
|
+
if (fs.statSync(fullPath).isDirectory()) {
|
|
555
|
+
findControllerFiles(fullPath);
|
|
556
|
+
}
|
|
557
|
+
else if (file.endsWith('.controller.ts')) {
|
|
558
|
+
controllerFiles.push(fullPath);
|
|
559
|
+
}
|
|
560
|
+
});
|
|
561
|
+
}
|
|
562
|
+
findControllerFiles(backendSrcDir);
|
|
563
|
+
console.log(`Found ${controllerFiles.length} controller files`);
|
|
564
|
+
const allControllers = [];
|
|
565
|
+
controllerFiles.forEach((controllerFile) => {
|
|
566
|
+
console.log(`Processing ${controllerFile}...`);
|
|
567
|
+
const controllers = parseControllers(controllerFile);
|
|
568
|
+
allControllers.push(...controllers);
|
|
569
|
+
controllers.forEach((controller) => {
|
|
570
|
+
const clientName = controller.name.replace('Controller', 'Client');
|
|
571
|
+
const clientFileName = `${toCamelCase(clientName.replace('Client', ''))}.client.ts`;
|
|
572
|
+
const clientFilePath = path.join(clientOutputDir, 'clients', clientFileName);
|
|
573
|
+
const clientCode = generateClientClass(controller);
|
|
574
|
+
fs.mkdirSync(path.dirname(clientFilePath), { recursive: true });
|
|
575
|
+
fs.writeFileSync(clientFilePath, clientCode, 'utf-8');
|
|
576
|
+
console.log(`✅ Generated ${clientFilePath}`);
|
|
577
|
+
});
|
|
578
|
+
});
|
|
579
|
+
generateIndexFile(clientOutputDir, allControllers);
|
|
580
|
+
console.log('✅ Client generation complete!');
|
|
581
|
+
//# sourceMappingURL=generate-rest-clients.js.map
|