@open-norantec/herbal 1.0.2-alpha.3 → 1.0.2-alpha.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/abstracts/client.abstract.class.d.ts +13 -0
- package/dist/abstracts/client.abstract.class.js +39 -0
- package/dist/abstracts/index.d.ts +1 -0
- package/dist/abstracts/index.js +1 -0
- package/dist/cli/herbal.js +167 -71
- package/dist/clients/index.d.ts +1 -0
- package/dist/clients/index.js +17 -0
- package/dist/clients/typescript-client.class.d.ts +7 -0
- package/dist/clients/typescript-client.class.js +239 -0
- package/dist/core.d.ts +2 -7
- package/dist/core.js +58 -71
- package/dist/{create.d.ts → create/create-application.d.ts} +8 -8
- package/dist/create/create-application.js +18 -0
- package/dist/create/create-client.d.ts +9 -0
- package/dist/create/create-client.js +17 -0
- package/dist/create/index.d.ts +2 -0
- package/dist/create/index.js +18 -0
- package/dist/decorators/index.d.ts +1 -0
- package/dist/decorators/index.js +1 -0
- package/dist/decorators/no-transaction.decorator.d.ts +5 -0
- package/dist/decorators/no-transaction.decorator.js +16 -0
- package/dist/sequelize-di.js +4 -6
- package/dist/types/request.type.d.ts +3 -2
- package/dist/utilities/controller-util.class.d.ts +43 -2
- package/dist/utilities/controller-util.class.js +260 -82
- package/package.json +9 -12
- package/dist/create.js +0 -154
- package/dist/transformers/reflect-declaration.d.ts +0 -3
- package/dist/transformers/reflect-declaration.js +0 -63
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
import { Constructor } from 'type-fest';
|
|
3
|
+
import { OpenAPIObject } from 'zod-openapi/dist/openapi3-ts/dist/model/openapi31';
|
|
4
|
+
export interface CreateClientOptions {
|
|
5
|
+
Module: Constructor<any>;
|
|
6
|
+
}
|
|
7
|
+
export declare abstract class Client {
|
|
8
|
+
readonly options: CreateClientOptions;
|
|
9
|
+
protected document: OpenAPIObject;
|
|
10
|
+
constructor(options: CreateClientOptions);
|
|
11
|
+
abstract generateClientSourceFile(): Promise<string>;
|
|
12
|
+
createSchema(group?: string): void;
|
|
13
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Client = void 0;
|
|
4
|
+
require("reflect-metadata");
|
|
5
|
+
var nest_util_class_1 = require("../utilities/nest-util.class");
|
|
6
|
+
var string_util_class_1 = require("@open-norantec/utilities/dist/string-util.class");
|
|
7
|
+
var controller_util_class_1 = require("../utilities/controller-util.class");
|
|
8
|
+
var Client = (function () {
|
|
9
|
+
function Client(options) {
|
|
10
|
+
this.options = options;
|
|
11
|
+
this.document = {
|
|
12
|
+
openapi: '3.1.0',
|
|
13
|
+
info: {
|
|
14
|
+
title: 'API Documentation',
|
|
15
|
+
version: '1.0.0',
|
|
16
|
+
},
|
|
17
|
+
paths: {},
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
Client.prototype.createSchema = function (group) {
|
|
21
|
+
var _this = this;
|
|
22
|
+
if (string_util_class_1.StringUtil.isFalsyString(group) && typeof group !== 'undefined')
|
|
23
|
+
return;
|
|
24
|
+
nest_util_class_1.NestUtil.getControllerClasses(this.options.Module).forEach(function (Class) {
|
|
25
|
+
if (string_util_class_1.StringUtil.isFalsyString(Class === null || Class === void 0 ? void 0 : Class.name) || !(0, controller_util_class_1.isHerbalController)(Class))
|
|
26
|
+
return;
|
|
27
|
+
var controllerName = (0, controller_util_class_1.getControllerName)(Class);
|
|
28
|
+
var pool = controller_util_class_1.ControllerUtil.getPool(Class.prototype);
|
|
29
|
+
if (string_util_class_1.StringUtil.isFalsyString(controllerName) || pool === null)
|
|
30
|
+
return;
|
|
31
|
+
Object.entries(pool.getOpenAPIPathsObject(group)).forEach(function (_a) {
|
|
32
|
+
var pathname = _a[0], schemas = _a[1];
|
|
33
|
+
_this.document.paths[["/".concat(controllerName), pathname].join('')] = schemas;
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
return Client;
|
|
38
|
+
}());
|
|
39
|
+
exports.Client = Client;
|
package/dist/abstracts/index.js
CHANGED
|
@@ -15,3 +15,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./auth-adapter.abstract.class"), exports);
|
|
18
|
+
__exportStar(require("./client.abstract.class"), exports);
|
package/dist/cli/herbal.js
CHANGED
|
@@ -1,18 +1,75 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
4
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
5
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
6
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
7
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
8
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
9
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
13
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
14
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
15
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
16
|
+
function step(op) {
|
|
17
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
18
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
19
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
20
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
21
|
+
switch (op[0]) {
|
|
22
|
+
case 0: case 1: t = op; break;
|
|
23
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
24
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
25
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
26
|
+
default:
|
|
27
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
28
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
29
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
30
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
31
|
+
if (t[2]) _.ops.pop();
|
|
32
|
+
_.trys.pop(); continue;
|
|
33
|
+
}
|
|
34
|
+
op = body.call(thisArg, _);
|
|
35
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
36
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
37
|
+
}
|
|
38
|
+
};
|
|
3
39
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
40
|
var commander_1 = require("commander");
|
|
5
41
|
var forge_1 = require("@open-norantec/forge");
|
|
42
|
+
var _ = require("lodash");
|
|
43
|
+
var fs = require("fs-extra");
|
|
44
|
+
var path = require("node:path");
|
|
45
|
+
var requireFromString = require("require-from-string");
|
|
6
46
|
var command = new commander_1.Command('herbal');
|
|
7
|
-
var
|
|
8
|
-
var
|
|
47
|
+
var log = function (level) {
|
|
48
|
+
var _a, _b;
|
|
49
|
+
var messages = [];
|
|
50
|
+
for (var _i = 1; _i < arguments.length; _i++) {
|
|
51
|
+
messages[_i - 1] = arguments[_i];
|
|
52
|
+
}
|
|
53
|
+
console.log("[".concat(new Date().toISOString(), "] -").concat(level, "- ").concat((_b = (_a = messages === null || messages === void 0 ? void 0 : messages.join) === null || _a === void 0 ? void 0 : _a.call(messages, ' ')) !== null && _b !== void 0 ? _b : ''));
|
|
54
|
+
switch (level) {
|
|
55
|
+
case 'error':
|
|
56
|
+
process.exit(1);
|
|
57
|
+
default:
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
var handleGetVirtualEntryFileContent = function (buildEntryFilePath) {
|
|
9
62
|
return [
|
|
10
63
|
"import 'reflect-metadata';",
|
|
11
|
-
"import { ModelUtil, NestFactory } from '@open-norantec/herbal';",
|
|
64
|
+
"import { ModelUtil, NestFactory, isApplication } from '@open-norantec/herbal';",
|
|
12
65
|
"import { LoggerService } from '@open-norantec/herbal/dist/modules/logger/logger.service';",
|
|
13
66
|
"import { Worker, isMainThread, workerData } from 'node:worker_threads';",
|
|
14
|
-
"import ENTRY from '".concat(
|
|
67
|
+
"import ENTRY from '".concat(buildEntryFilePath, "';"),
|
|
15
68
|
'\nasync function bootstrap() {',
|
|
69
|
+
' if (!isApplication(ENTRY)) {',
|
|
70
|
+
' console.log(`The entry file must export an application or a function that returns an application.`);',
|
|
71
|
+
' process.exit(1);',
|
|
72
|
+
' }',
|
|
16
73
|
' const entryOptions = ENTRY?.options;',
|
|
17
74
|
' await entryOptions?.onBeforeBootstrap?.();',
|
|
18
75
|
"\n if (!!workerData?.['__herbal_worker']) {",
|
|
@@ -67,74 +124,113 @@ var getEntryFileContent = function (_a) {
|
|
|
67
124
|
'\nbootstrap();',
|
|
68
125
|
].join('\n');
|
|
69
126
|
};
|
|
70
|
-
var
|
|
71
|
-
var
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
"import * as fs from 'node:fs';",
|
|
76
|
-
"import * as path from 'node:path';",
|
|
77
|
-
'\nasync function bootstrap() {',
|
|
78
|
-
" const outputDirPath = '".concat(outputPath, "';"),
|
|
79
|
-
" const outputFilePath = path.resolve(outputDirPath, '".concat(options.outputName, ".ts');"),
|
|
80
|
-
' await ENTRY?.options?.onBeforeBootstrap?.();',
|
|
81
|
-
' try {',
|
|
82
|
-
' fs.rmSync(outputFilePath, {',
|
|
83
|
-
' recursive: true,',
|
|
84
|
-
' force: true,',
|
|
85
|
-
' });',
|
|
86
|
-
' } catch {}',
|
|
87
|
-
' try {',
|
|
88
|
-
' if (!fs.statSync(path.dirname(outputDirPath)).isDirectory()) {',
|
|
89
|
-
' fs.rmSync(path.dirname(outputDirPath), {',
|
|
90
|
-
' recursive: true,',
|
|
91
|
-
' force: true,',
|
|
92
|
-
' });',
|
|
93
|
-
' }',
|
|
94
|
-
' } catch {}',
|
|
95
|
-
' try {',
|
|
96
|
-
' fs.mkdirSync(outputDirPath, { recursive: true });',
|
|
97
|
-
' } catch {}',
|
|
98
|
-
' fs.writeFileSync(',
|
|
99
|
-
' outputFilePath,',
|
|
100
|
-
' ENTRY?.generateClientSourceFile?.(),',
|
|
101
|
-
' );',
|
|
102
|
-
'}',
|
|
103
|
-
'\nbootstrap();',
|
|
104
|
-
].join('\n');
|
|
105
|
-
};
|
|
106
|
-
var handleLog = function (level, message) {
|
|
107
|
-
console.log("[".concat(new Date().toISOString(), "] [").concat(level, "] ").concat(message));
|
|
108
|
-
switch (level) {
|
|
109
|
-
case 'error':
|
|
110
|
-
process.exit(1);
|
|
111
|
-
default:
|
|
112
|
-
break;
|
|
127
|
+
var handleGetFileContent = function (filePath) {
|
|
128
|
+
var content = _.attempt(function () { return fs.readFileSync(filePath, 'utf-8'); });
|
|
129
|
+
if (content instanceof Error) {
|
|
130
|
+
log('error', "Failed to read file content for ".concat(filePath, ":"), content.message);
|
|
131
|
+
return '';
|
|
113
132
|
}
|
|
133
|
+
return content;
|
|
134
|
+
};
|
|
135
|
+
var handleGetWatcher = function (callback) {
|
|
136
|
+
var watcher = fs.watch(process.cwd(), { recursive: true }, function (eventType, filename) {
|
|
137
|
+
callback(path.resolve(filename));
|
|
138
|
+
});
|
|
139
|
+
return { close: watcher.close.bind(watcher) };
|
|
114
140
|
};
|
|
141
|
+
var createHandleOutputFile = function (disableWriteFile) { return function (filePath, content) {
|
|
142
|
+
if (!disableWriteFile) {
|
|
143
|
+
var dir_1 = path.dirname(filePath);
|
|
144
|
+
if (!fs.existsSync(dir_1) || !fs.statSync(dir_1).isDirectory()) {
|
|
145
|
+
_.attempt(function () { return fs.removeSync(dir_1); });
|
|
146
|
+
_.attempt(function () { return fs.mkdirpSync(dir_1); });
|
|
147
|
+
}
|
|
148
|
+
_.attempt(function () { return fs.writeFileSync(filePath, content, 'utf-8'); });
|
|
149
|
+
log('info', "Generated file: ".concat(filePath));
|
|
150
|
+
}
|
|
151
|
+
}; };
|
|
115
152
|
command
|
|
116
|
-
.addCommand((0, forge_1.
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
153
|
+
.addCommand((0, forge_1.createCommand)('build', {
|
|
154
|
+
hiddenOptions: ['--watch', '--execute-after-build'],
|
|
155
|
+
onLog: log,
|
|
156
|
+
defaultOptions: function (source, output, options) { return ({
|
|
157
|
+
getWatcher: handleGetWatcher,
|
|
158
|
+
getVirtualEntryFileContent: handleGetVirtualEntryFileContent,
|
|
159
|
+
onGetFileContent: handleGetFileContent,
|
|
160
|
+
onOutputFile: createHandleOutputFile(!!(options === null || options === void 0 ? void 0 : options.disableWriteFile)),
|
|
161
|
+
}); },
|
|
162
|
+
}))
|
|
163
|
+
.addCommand((0, forge_1.createCommand)('watch', {
|
|
164
|
+
hiddenOptions: [
|
|
165
|
+
'--watch',
|
|
166
|
+
'--execute-after-build',
|
|
167
|
+
'--obfuscate',
|
|
168
|
+
'--obfuscator-config-file <string>',
|
|
169
|
+
'--disable-write-file',
|
|
170
|
+
],
|
|
171
|
+
onLog: log,
|
|
172
|
+
defaultOptions: function () { return ({
|
|
173
|
+
watch: true,
|
|
174
|
+
executeAfterBuild: true,
|
|
175
|
+
obfuscate: false,
|
|
176
|
+
getWatcher: handleGetWatcher,
|
|
177
|
+
getVirtualEntryFileContent: handleGetVirtualEntryFileContent,
|
|
178
|
+
onGetFileContent: handleGetFileContent,
|
|
179
|
+
onOutputFile: createHandleOutputFile(true),
|
|
180
|
+
}); },
|
|
181
|
+
}))
|
|
182
|
+
.addCommand((0, forge_1.createCommand)('generate-client', function (_a) {
|
|
183
|
+
var addOption = _a.addOption;
|
|
184
|
+
addOption('--group <name>', 'Client group name to generate');
|
|
185
|
+
return {
|
|
186
|
+
onLog: log,
|
|
187
|
+
hiddenOptions: [
|
|
188
|
+
'--watch',
|
|
189
|
+
'--execute-after-build',
|
|
190
|
+
'--obfuscate',
|
|
191
|
+
'--obfuscator-config-file <string>',
|
|
192
|
+
'--disable-write-file',
|
|
193
|
+
],
|
|
194
|
+
defaultOptions: function (source, output, options) { return ({
|
|
195
|
+
watch: false,
|
|
196
|
+
executeAfterBuild: false,
|
|
197
|
+
obfuscate: false,
|
|
198
|
+
getWatcher: handleGetWatcher,
|
|
199
|
+
onGetFileContent: handleGetFileContent,
|
|
200
|
+
onOutputFile: createHandleOutputFile(false),
|
|
201
|
+
getVirtualEntryFileContent: function (buildEntryFilePath) {
|
|
202
|
+
return [
|
|
203
|
+
"const entry = require('".concat(buildEntryFilePath, "')"),
|
|
204
|
+
"const { isClient } = require(\'@open-norantec/herbal\')",
|
|
205
|
+
'module.exports = (context) => {',
|
|
206
|
+
' let client = entry;',
|
|
207
|
+
' if (!isClient(client)) { client = entry?.default; }',
|
|
208
|
+
" if (!isClient(client)) return '';",
|
|
209
|
+
' client.instance.createSchema(context?.group);',
|
|
210
|
+
' return client.instance.generateClientSourceFile();',
|
|
211
|
+
'};',
|
|
212
|
+
].join('\n');
|
|
213
|
+
},
|
|
214
|
+
rewriteOutputFile: function (code) { return __awaiter(void 0, void 0, void 0, function () {
|
|
215
|
+
var generateCodeMethod, error_1;
|
|
216
|
+
return __generator(this, function (_a) {
|
|
217
|
+
switch (_a.label) {
|
|
218
|
+
case 0:
|
|
219
|
+
_a.trys.push([0, 2, , 3]);
|
|
220
|
+
generateCodeMethod = requireFromString(code);
|
|
221
|
+
if (typeof generateCodeMethod !== 'function')
|
|
222
|
+
return [2, ''];
|
|
223
|
+
return [4, Promise.resolve(generateCodeMethod({ group: options === null || options === void 0 ? void 0 : options.group })).then(function (generatedCode) { return generatedCode !== null && generatedCode !== void 0 ? generatedCode : ''; })];
|
|
224
|
+
case 1: return [2, _a.sent()];
|
|
225
|
+
case 2:
|
|
226
|
+
error_1 = _a.sent();
|
|
227
|
+
log('error', "Failed to generate client code:", error_1 instanceof Error ? error_1.message : String(error_1));
|
|
228
|
+
return [2, ''];
|
|
229
|
+
case 3: return [2];
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
}); },
|
|
233
|
+
}); },
|
|
234
|
+
};
|
|
235
|
+
}));
|
|
140
236
|
command.parse(process.argv);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './typescript-client.class';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./typescript-client.class"), exports);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
import { Client, CreateClientOptions } from '../abstracts/client.abstract.class';
|
|
3
|
+
export declare class TypeScriptClient extends Client implements Client {
|
|
4
|
+
constructor(options: CreateClientOptions);
|
|
5
|
+
generateClientSourceFile(): Promise<string>;
|
|
6
|
+
private schemaToTypeScriptLiteral;
|
|
7
|
+
}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __extends = (this && this.__extends) || (function () {
|
|
3
|
+
var extendStatics = function (d, b) {
|
|
4
|
+
extendStatics = Object.setPrototypeOf ||
|
|
5
|
+
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
6
|
+
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
|
7
|
+
return extendStatics(d, b);
|
|
8
|
+
};
|
|
9
|
+
return function (d, b) {
|
|
10
|
+
if (typeof b !== "function" && b !== null)
|
|
11
|
+
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
12
|
+
extendStatics(d, b);
|
|
13
|
+
function __() { this.constructor = d; }
|
|
14
|
+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
15
|
+
};
|
|
16
|
+
})();
|
|
17
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
18
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
19
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
20
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
21
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
22
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
23
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
27
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
28
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
29
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
30
|
+
function step(op) {
|
|
31
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
32
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
33
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
34
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
35
|
+
switch (op[0]) {
|
|
36
|
+
case 0: case 1: t = op; break;
|
|
37
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
38
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
39
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
40
|
+
default:
|
|
41
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
42
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
43
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
44
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
45
|
+
if (t[2]) _.ops.pop();
|
|
46
|
+
_.trys.pop(); continue;
|
|
47
|
+
}
|
|
48
|
+
op = body.call(thisArg, _);
|
|
49
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
50
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
54
|
+
exports.TypeScriptClient = void 0;
|
|
55
|
+
require("reflect-metadata");
|
|
56
|
+
var client_abstract_class_1 = require("../abstracts/client.abstract.class");
|
|
57
|
+
var json_schema_to_typescript_1 = require("json-schema-to-typescript");
|
|
58
|
+
var TypeScriptClient = (function (_super) {
|
|
59
|
+
__extends(TypeScriptClient, _super);
|
|
60
|
+
function TypeScriptClient(options) {
|
|
61
|
+
return _super.call(this, options) || this;
|
|
62
|
+
}
|
|
63
|
+
TypeScriptClient.prototype.generateClientSourceFile = function () {
|
|
64
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
65
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
66
|
+
var options, METHOD_TYPE_MAP_NAME, METHOD_TYPE_MAP_KEYS_NAME, RESPONSE_CALLBACK_DATA_NAME, REQUEST_OPTIONS_NAME, RESULT_TYPE_NAME, REQUEST_METHOD_MAP_NAME, RESPONSE_CACHE_MAP_NAME, REQUEST_BODY_TYPE_ANNOTATION, RESULT_TYPE_ANNOTATION, methodTypeMapCodeLines, _i, _l, _m, pathname, schema, requestSchema, responseSchema, requestTypeLiteral, responseTypeLiteral;
|
|
67
|
+
return __generator(this, function (_o) {
|
|
68
|
+
switch (_o.label) {
|
|
69
|
+
case 0:
|
|
70
|
+
options = this.options;
|
|
71
|
+
if (!(options === null || options === void 0 ? void 0 : options.Module))
|
|
72
|
+
throw new Error("Parameter 'Module' must be specified");
|
|
73
|
+
METHOD_TYPE_MAP_NAME = 'MethodTypeMap';
|
|
74
|
+
METHOD_TYPE_MAP_KEYS_NAME = 'MethodTypeMapKeys';
|
|
75
|
+
RESPONSE_CALLBACK_DATA_NAME = 'ResponseCallbackData';
|
|
76
|
+
REQUEST_OPTIONS_NAME = 'RequestOptions';
|
|
77
|
+
RESULT_TYPE_NAME = 'Result';
|
|
78
|
+
REQUEST_METHOD_MAP_NAME = 'REQUEST_METHOD_MAP';
|
|
79
|
+
RESPONSE_CACHE_MAP_NAME = 'RESPONSE_CACHE_MAP';
|
|
80
|
+
REQUEST_BODY_TYPE_ANNOTATION = "".concat(METHOD_TYPE_MAP_NAME, "[T]['request']");
|
|
81
|
+
RESULT_TYPE_ANNOTATION = "".concat(RESULT_TYPE_NAME, "<").concat(METHOD_TYPE_MAP_NAME, "[T]['response']>");
|
|
82
|
+
methodTypeMapCodeLines = [];
|
|
83
|
+
_i = 0, _l = Object.entries((_a = this.document.paths) !== null && _a !== void 0 ? _a : {});
|
|
84
|
+
_o.label = 1;
|
|
85
|
+
case 1:
|
|
86
|
+
if (!(_i < _l.length)) return [3, 5];
|
|
87
|
+
_m = _l[_i], pathname = _m[0], schema = _m[1];
|
|
88
|
+
requestSchema = (_e = (_d = (_c = (_b = schema === null || schema === void 0 ? void 0 : schema.post) === null || _b === void 0 ? void 0 : _b.requestBody) === null || _c === void 0 ? void 0 : _c.content) === null || _d === void 0 ? void 0 : _d['application/json']) === null || _e === void 0 ? void 0 : _e.schema;
|
|
89
|
+
responseSchema = (_k = (_j = (_h = (_g = (_f = schema === null || schema === void 0 ? void 0 : schema.post) === null || _f === void 0 ? void 0 : _f.responses) === null || _g === void 0 ? void 0 : _g['200']) === null || _h === void 0 ? void 0 : _h.content) === null || _j === void 0 ? void 0 : _j['application/json']) === null || _k === void 0 ? void 0 : _k.schema;
|
|
90
|
+
if (!requestSchema && !responseSchema)
|
|
91
|
+
return [3, 4];
|
|
92
|
+
return [4, this.schemaToTypeScriptLiteral(requestSchema)];
|
|
93
|
+
case 2:
|
|
94
|
+
requestTypeLiteral = _o.sent();
|
|
95
|
+
return [4, this.schemaToTypeScriptLiteral(responseSchema)];
|
|
96
|
+
case 3:
|
|
97
|
+
responseTypeLiteral = _o.sent();
|
|
98
|
+
methodTypeMapCodeLines.push([" '".concat(pathname, "': {"), " request: ".concat(requestTypeLiteral, ";"), " response: ".concat(responseTypeLiteral, ";"), ' };'].join(''));
|
|
99
|
+
_o.label = 4;
|
|
100
|
+
case 4:
|
|
101
|
+
_i++;
|
|
102
|
+
return [3, 1];
|
|
103
|
+
case 5:
|
|
104
|
+
methodTypeMapCodeLines.unshift("export interface ".concat(METHOD_TYPE_MAP_NAME, " {"));
|
|
105
|
+
methodTypeMapCodeLines.push('}');
|
|
106
|
+
return [2, [
|
|
107
|
+
"import * as hash from 'object-hash';",
|
|
108
|
+
"import * as _ from 'lodash';",
|
|
109
|
+
"\n".concat(methodTypeMapCodeLines.join('\n')),
|
|
110
|
+
"\ntype ".concat(METHOD_TYPE_MAP_KEYS_NAME, " = keyof ").concat(METHOD_TYPE_MAP_NAME, ";"),
|
|
111
|
+
"\ntype ".concat(RESPONSE_CALLBACK_DATA_NAME, "<K extends ").concat(METHOD_TYPE_MAP_KEYS_NAME, "> = {"),
|
|
112
|
+
' url: K;',
|
|
113
|
+
" result: ".concat(RESULT_TYPE_NAME, "<").concat(METHOD_TYPE_MAP_NAME, "[K]['response']>;"),
|
|
114
|
+
'};',
|
|
115
|
+
"\nexport interface ".concat(REQUEST_OPTIONS_NAME, " extends RequestInit {"),
|
|
116
|
+
' headers?: Record<string, any>;',
|
|
117
|
+
' ignoreCache?: boolean;',
|
|
118
|
+
' prefix?: string;',
|
|
119
|
+
' timeout?: number;',
|
|
120
|
+
' getAuthorizationCredential?: () => string;',
|
|
121
|
+
" onRequest?: (context: { cached: boolean; id: string; options: Omit<".concat(REQUEST_OPTIONS_NAME, ", 'getAuthorizationCredential' | 'onRequest' | 'onResponse'>; prefix: string | undefined; requestBody: string; url: string; }) => void | Promise<void>;"),
|
|
122
|
+
" onResponse?: <K extends ".concat(METHOD_TYPE_MAP_KEYS_NAME, ">(response: ").concat(RESPONSE_CALLBACK_DATA_NAME, "<K>, id: string) => void | Promise<void>;"),
|
|
123
|
+
'}',
|
|
124
|
+
"\nexport interface ".concat(RESULT_TYPE_NAME, "<T> {"),
|
|
125
|
+
' error: Error | null;',
|
|
126
|
+
" response: T | null;",
|
|
127
|
+
' status: number;',
|
|
128
|
+
' statusText: string;',
|
|
129
|
+
' headers?: Record<string, any>;',
|
|
130
|
+
'}',
|
|
131
|
+
'\nexport class Client {',
|
|
132
|
+
" public constructor(private readonly options: ".concat(REQUEST_OPTIONS_NAME, " = {}) {}"),
|
|
133
|
+
"\n protected readonly ".concat(REQUEST_METHOD_MAP_NAME, " = new Map<keyof ").concat(METHOD_TYPE_MAP_NAME, ", (...params: any[]) => Promise<unknown>>();"),
|
|
134
|
+
"\n protected readonly ".concat(RESPONSE_CACHE_MAP_NAME, " = new Map<string, ").concat(RESULT_TYPE_NAME, "<unknown>>();"),
|
|
135
|
+
"\n public createRequest<T extends keyof ".concat(METHOD_TYPE_MAP_NAME, ">(url: T): (requestBody?: ").concat(REQUEST_BODY_TYPE_ANNOTATION, ", options?: ").concat(REQUEST_OPTIONS_NAME, ") => Promise<").concat(RESULT_TYPE_ANNOTATION, "> {"),
|
|
136
|
+
" if (typeof this.".concat(REQUEST_METHOD_MAP_NAME, ".get(url) !== 'function') {"),
|
|
137
|
+
" this.".concat(REQUEST_METHOD_MAP_NAME, ".set(url, (requestBody?: ").concat(REQUEST_BODY_TYPE_ANNOTATION, ", options?: ").concat(REQUEST_OPTIONS_NAME, ") => this.request.call(this, url, requestBody, options));"),
|
|
138
|
+
' }',
|
|
139
|
+
" return this.".concat(REQUEST_METHOD_MAP_NAME, ".get(url) as (requestBody?: ").concat(REQUEST_BODY_TYPE_ANNOTATION, ", options?: ").concat(REQUEST_OPTIONS_NAME, ") => Promise<").concat(RESULT_TYPE_ANNOTATION, ">;"),
|
|
140
|
+
' }',
|
|
141
|
+
"\n public async request<T extends keyof ".concat(METHOD_TYPE_MAP_NAME, ">(url: T, requestBody?: ").concat(REQUEST_BODY_TYPE_ANNOTATION, ", options?: Omit<").concat(REQUEST_OPTIONS_NAME, ", 'getAuthorizationCredential' | 'onRequest' | 'onResponse'>): Promise<").concat(RESULT_TYPE_ANNOTATION, "> {"),
|
|
142
|
+
' const id = `${Math.random().toString(32).slice(2)}${Date.now().toString(16)}`;',
|
|
143
|
+
' const requestHash = hash(requestBody ?? null);',
|
|
144
|
+
' const requestBodyString = JSON.stringify(requestBody);',
|
|
145
|
+
" const finalOptions = _.merge({}, this?.options, _.omit(options, ['getAuthorizationCredential', 'onRequest', 'onResponse']));",
|
|
146
|
+
" const onRequestOptions = _.omit(finalOptions, ['getAuthorizationCredential', 'onRequest', 'onResponse']);",
|
|
147
|
+
' const { getAuthorizationCredential, onResponse, onRequest, ignoreCache, timeout, prefix, ...requestOptions } = finalOptions;',
|
|
148
|
+
" if (this.".concat(RESPONSE_CACHE_MAP_NAME, ".has(requestHash) && !ignoreCache) {"),
|
|
149
|
+
' onRequest?.({',
|
|
150
|
+
' prefix,',
|
|
151
|
+
' url,',
|
|
152
|
+
' requestBody: requestBodyString,',
|
|
153
|
+
' cached: true,',
|
|
154
|
+
' options: onRequestOptions,',
|
|
155
|
+
' id,',
|
|
156
|
+
' });',
|
|
157
|
+
" return this.".concat(RESPONSE_CACHE_MAP_NAME, ".get(requestHash) as ").concat(RESULT_TYPE_ANNOTATION, ";"),
|
|
158
|
+
' }',
|
|
159
|
+
' onRequest?.({',
|
|
160
|
+
' prefix,',
|
|
161
|
+
' url,',
|
|
162
|
+
' id,',
|
|
163
|
+
' requestBody: requestBodyString,',
|
|
164
|
+
' cached: false,',
|
|
165
|
+
' options: onRequestOptions,',
|
|
166
|
+
' });',
|
|
167
|
+
' const credential = getAuthorizationCredential?.();',
|
|
168
|
+
' const abortController = new AbortController();',
|
|
169
|
+
' if (timeout! > 0) {',
|
|
170
|
+
' setTimeout(() => {',
|
|
171
|
+
' abortController.abort();',
|
|
172
|
+
' }, timeout);',
|
|
173
|
+
' }',
|
|
174
|
+
" const result: ".concat(RESULT_TYPE_ANNOTATION, " = await fetch((prefix ?? '') + url, {"),
|
|
175
|
+
' ...requestOptions,',
|
|
176
|
+
' body: JSON.stringify(requestBody),',
|
|
177
|
+
" method: 'POST',",
|
|
178
|
+
' signal: abortController.signal,',
|
|
179
|
+
' headers: {',
|
|
180
|
+
' ...requestOptions?.headers,',
|
|
181
|
+
" 'Content-Type': 'application/json',",
|
|
182
|
+
" Authorization: (typeof credential === 'string' && credential.length > 0) ? credential : finalOptions?.headers?.Authorization,",
|
|
183
|
+
' },',
|
|
184
|
+
' }).then((response) => {',
|
|
185
|
+
' const status = response?.status;',
|
|
186
|
+
' const statusText = response?.statusText;',
|
|
187
|
+
' const headers = Array.from(response?.headers?.entries?.() ?? []).reduce((result, [key, value]) => {',
|
|
188
|
+
" if (typeof key !== 'string' || key.length === 0) return result;",
|
|
189
|
+
' result[key] = value;',
|
|
190
|
+
' return result;',
|
|
191
|
+
' }, {});',
|
|
192
|
+
' if (!response?.ok) {',
|
|
193
|
+
' return response.text().then((errorText) => ({ error: new Error(errorText), response: null, headers, status, statusText }));',
|
|
194
|
+
' }',
|
|
195
|
+
" return response.json().then((response) => ({ error: null, response, headers, status, statusText } as ".concat(RESULT_TYPE_ANNOTATION, "));"),
|
|
196
|
+
" }).catch((error) => Promise.resolve({ error, response: null, headers: {}, status: 0, statusText: '' }));",
|
|
197
|
+
" onResponse?.({ url, result }, id);",
|
|
198
|
+
" this.".concat(RESPONSE_CACHE_MAP_NAME, ".set(requestHash, result);"),
|
|
199
|
+
' return result;',
|
|
200
|
+
' }',
|
|
201
|
+
'}\n',
|
|
202
|
+
].join('\n')];
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
};
|
|
207
|
+
TypeScriptClient.prototype.schemaToTypeScriptLiteral = function (schema) {
|
|
208
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
209
|
+
var interfaceName;
|
|
210
|
+
return __generator(this, function (_a) {
|
|
211
|
+
switch (_a.label) {
|
|
212
|
+
case 0:
|
|
213
|
+
interfaceName = "Interface".concat(Math.random().toString(36).slice(2));
|
|
214
|
+
return [4, (0, json_schema_to_typescript_1.compile)(schema, interfaceName, {
|
|
215
|
+
format: true,
|
|
216
|
+
bannerComment: '',
|
|
217
|
+
additionalProperties: false,
|
|
218
|
+
unknownAny: false,
|
|
219
|
+
style: {
|
|
220
|
+
singleQuote: true,
|
|
221
|
+
semi: true,
|
|
222
|
+
trailingComma: 'none',
|
|
223
|
+
},
|
|
224
|
+
}).then(function (code) {
|
|
225
|
+
return code
|
|
226
|
+
.trim()
|
|
227
|
+
.split('\n')
|
|
228
|
+
.map(function (line, index) { return "".concat(index === 0 ? '' : ' ').concat(line.trim()); })
|
|
229
|
+
.join('')
|
|
230
|
+
.replace(/^export\s+interface\s+Interface[a-zA-Z0-9-_]+\s+\{/, '{');
|
|
231
|
+
})];
|
|
232
|
+
case 1: return [2, _a.sent()];
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
};
|
|
237
|
+
return TypeScriptClient;
|
|
238
|
+
}(client_abstract_class_1.Client));
|
|
239
|
+
exports.TypeScriptClient = TypeScriptClient;
|
package/dist/core.d.ts
CHANGED
|
@@ -3,16 +3,11 @@ import { HeaderUtil } from '@open-norantec/utilities/dist/header-util.class';
|
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
import { Request } from './types/request.type';
|
|
5
5
|
export * from '@nestjs/core';
|
|
6
|
-
export interface MethodContext<IS extends z.Schema<any>> {
|
|
7
|
-
headers: ReturnType<typeof HeaderUtil.parse>;
|
|
8
|
-
input: z.infer<IS>;
|
|
9
|
-
request: Request;
|
|
10
|
-
}
|
|
11
6
|
export type MethodHandler<IS extends z.Schema<any>, OS extends z.Schema<any>> = (request: Request, input: unknown, headers: ReturnType<typeof HeaderUtil.parse>) => Promise<{
|
|
12
7
|
request: z.infer<IS>;
|
|
13
8
|
response: z.infer<OS>;
|
|
14
9
|
}>;
|
|
15
10
|
export declare class HerbalController {
|
|
16
|
-
|
|
17
|
-
private
|
|
11
|
+
private $handleRequest;
|
|
12
|
+
private $call;
|
|
18
13
|
}
|