@open-norantec/herbal 1.0.2-alpha.0 → 1.0.2-alpha.10

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.
@@ -1,18 +1,63 @@
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 utilities_1 = require("../utilities");
43
+ var _ = require("lodash");
44
+ var fs = require("fs-extra");
45
+ var path = require("node:path");
46
+ var attempt_util_class_1 = require("@open-norantec/utilities/dist/attempt-util.class");
6
47
  var command = new commander_1.Command('herbal');
7
48
  var getEntryFileContent = function (_a) {
8
49
  var entryFilePath = _a.entryFilePath;
9
50
  return [
10
51
  "import 'reflect-metadata';",
11
- "import { ModelUtil, NestFactory } from '@open-norantec/herbal';",
52
+ "import { ModelUtil, NestFactory, isApplication } from '@open-norantec/herbal';",
12
53
  "import { LoggerService } from '@open-norantec/herbal/dist/modules/logger/logger.service';",
13
54
  "import { Worker, isMainThread, workerData } from 'node:worker_threads';",
14
55
  "import ENTRY from '".concat(entryFilePath, "';"),
15
56
  '\nasync function bootstrap() {',
57
+ ' if (!isApplication(ENTRY)) {',
58
+ ' console.log(`The entry file must export an application or a function that returns an application.`);',
59
+ ' process.exit(1);',
60
+ ' }',
16
61
  ' const entryOptions = ENTRY?.options;',
17
62
  ' await entryOptions?.onBeforeBootstrap?.();',
18
63
  "\n if (!!workerData?.['__herbal_worker']) {",
@@ -67,42 +112,6 @@ var getEntryFileContent = function (_a) {
67
112
  '\nbootstrap();',
68
113
  ].join('\n');
69
114
  };
70
- var getGenerateClientEntryFileContent = function (_a) {
71
- var entryFilePath = _a.entryFilePath, outputPath = _a.outputPath, options = _a.options;
72
- return [
73
- "import 'reflect-metadata';",
74
- "import ENTRY from '".concat(entryFilePath, "';"),
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
115
  var handleLog = function (level, message) {
107
116
  console.log("[".concat(new Date().toISOString(), "] [").concat(level, "] ").concat(message));
108
117
  switch (level) {
@@ -127,14 +136,45 @@ command
127
136
  mode: 'development',
128
137
  afterEmitAction: 'watch',
129
138
  }).name('watch'))
130
- .addCommand((0, forge_1.createForgeCommand)({
131
- onLog: handleLog,
132
- getEntryFileContent: getGenerateClientEntryFileContent,
133
- hideOptions: ['--after-emit-action', '--ts-compiler', '--mode'],
134
- mode: 'production',
135
- afterEmitAction: 'run-once',
136
- tsCompiler: require.resolve('ts-patch/compiler', {
137
- paths: [__dirname, process.cwd()],
138
- }),
139
- }).name('generate-client'));
139
+ .addCommand((function () {
140
+ var subCommand = new commander_1.Command('generate-client');
141
+ subCommand
142
+ .requiredOption('--entry <entry>', 'The entry file path of the application. It must export an instance generated with `createClient` to default.')
143
+ .requiredOption('--output-file <path>', 'The output file path of the generated client source file.')
144
+ .option('--group <group>', 'The group name of the generated client. It is used to distinguish different clients when there are multiple clients in the same application.')
145
+ .action(function (options) { return __awaiter(void 0, void 0, void 0, function () {
146
+ var clientUtil;
147
+ return __generator(this, function (_a) {
148
+ switch (_a.label) {
149
+ case 0:
150
+ clientUtil = _.attempt(function () {
151
+ return new utilities_1.ClientUtil(options, function (absoluteOutputFile, content) {
152
+ var absoluteOutputDir = path.dirname(absoluteOutputFile);
153
+ if (!fs.existsSync(absoluteOutputDir) || !fs.statSync(absoluteOutputDir).isDirectory()) {
154
+ _.attempt(function () { return fs.removeSync(absoluteOutputDir); });
155
+ _.attempt(function () { return fs.mkdirpSync(absoluteOutputDir); });
156
+ }
157
+ var writeResult = attempt_util_class_1.AttemptUtil.exec(function () {
158
+ return fs.writeFileSync(absoluteOutputFile, content, { encoding: 'utf-8' });
159
+ });
160
+ if (writeResult instanceof Error) {
161
+ handleLog === null || handleLog === void 0 ? void 0 : handleLog('error', "Failed to write client code: ".concat(writeResult.message));
162
+ return;
163
+ }
164
+ handleLog === null || handleLog === void 0 ? void 0 : handleLog('info', "Client code generated successfully at ".concat(absoluteOutputFile));
165
+ }, handleLog);
166
+ });
167
+ if (clientUtil instanceof Error) {
168
+ handleLog('error', "Failed to initialize the client utility: ".concat(clientUtil.message));
169
+ return [2];
170
+ }
171
+ return [4, clientUtil.generateClientCode()];
172
+ case 1:
173
+ _a.sent();
174
+ return [2];
175
+ }
176
+ });
177
+ }); });
178
+ return subCommand;
179
+ })());
140
180
  command.parse(process.argv);
package/dist/create.d.ts CHANGED
@@ -1,11 +1,10 @@
1
1
  import 'reflect-metadata';
2
2
  import { CorsOptions, CorsOptionsDelegate } from '@nestjs/common/interfaces/external/cors-options.interface';
3
3
  import { Constructor } from 'type-fest';
4
- import { GroupsFactory } from './decorators/client-groups.decorator';
5
4
  import { CanActivate, ExceptionFilter, INestApplication, NestApplicationOptions, NestInterceptor, PipeTransform, WebSocketAdapter } from '@nestjs/common';
6
5
  export type Resolver = <T>(Class: Constructor<T>) => Promise<T>;
7
6
  export type TypeCustomizerFn = (dataTypeMapName: string, name: string, genericName: string) => string[];
8
- export interface CreateOptions {
7
+ export interface CreateApplicationOptions {
9
8
  Module: Constructor<any>;
10
9
  cors?: CorsOptions | CorsOptionsDelegate<any> | false;
11
10
  factoryOptions?: NestApplicationOptions;
@@ -16,12 +15,30 @@ export interface CreateOptions {
16
15
  uses?: any[];
17
16
  websocketAdapter?: WebSocketAdapter;
18
17
  getListenPort: (resolver: Resolver) => number | Promise<number>;
19
- allowedClientGroupsFactory?: GroupsFactory;
20
18
  callback?: (listenPort: number, app: INestApplication<any>) => void | Promise<void>;
21
19
  onBeforeBootstrap?: () => void | Promise<void>;
22
20
  worker?: (resolver: Resolver, listenPort: number) => any;
23
21
  }
24
- export declare function create(options: CreateOptions): {
25
- options: CreateOptions;
26
- generateClientSourceFile: () => string;
27
- };
22
+ export interface CreateClientOptions {
23
+ Module: Constructor<any>;
24
+ allowedClientGroupsFactory?: (currentGroup: string | undefined, defaultGroupName: string) => string[] | null | undefined;
25
+ }
26
+ declare class Application {
27
+ readonly options: CreateApplicationOptions;
28
+ constructor(options: CreateApplicationOptions);
29
+ }
30
+ export declare function isApplication(input: any): boolean;
31
+ export declare function createApplication(options: CreateApplicationOptions): Application;
32
+ export declare abstract class Client {
33
+ readonly options: CreateClientOptions;
34
+ constructor(options: CreateClientOptions);
35
+ abstract generateClientSourceFile(currentGroup?: string): string;
36
+ }
37
+ declare class TypeScriptClient extends Client implements Client {
38
+ readonly options: CreateClientOptions;
39
+ constructor(options: CreateClientOptions);
40
+ generateClientSourceFile(currentGroup?: string): string;
41
+ }
42
+ export declare function isClient(input: any): boolean;
43
+ export declare function createTypeScriptClient(options: CreateClientOptions): TypeScriptClient;
44
+ export {};
package/dist/create.js CHANGED
@@ -1,6 +1,21 @@
1
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
+ })();
2
17
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.create = void 0;
18
+ exports.createTypeScriptClient = exports.isClient = exports.Client = exports.createApplication = exports.isApplication = void 0;
4
19
  require("reflect-metadata");
5
20
  var _ = require("lodash");
6
21
  var nest_util_class_1 = require("./utilities/nest-util.class");
@@ -8,147 +23,183 @@ var string_util_class_1 = require("@open-norantec/utilities/dist/string-util.cla
8
23
  var reflect_declaration_1 = require("./transformers/reflect-declaration");
9
24
  var client_groups_decorator_1 = require("./decorators/client-groups.decorator");
10
25
  var controller_util_class_1 = require("./utilities/controller-util.class");
11
- function create(options) {
12
- return {
13
- options: options,
14
- generateClientSourceFile: function () {
15
- if (!(options === null || options === void 0 ? void 0 : options.Module))
16
- throw new Error("Parameter 'Module' must be specified");
17
- var METHOD_TYPE_MAP_NAME = 'MethodTypeMap';
18
- var METHOD_TYPE_MAP_KEYS_NAME = 'MethodTypeMapKeys';
19
- var RESPONSE_CALLBACK_DATA_NAME = 'ResponseCallbackData';
20
- var REQUEST_OPTIONS_NAME = 'RequestOptions';
21
- var RESULT_TYPE_NAME = 'Result';
22
- var HTTP_RESPONSE_BODY_TYPE_NAME = 'HttpResponseBody';
23
- var REQUEST_METHOD_MAP_NAME = 'REQUEST_METHOD_MAP';
24
- var RESPONSE_CACHE_MAP_NAME = 'RESPONSE_CACHE_MAP';
25
- var REQUEST_BODY_TYPE_ANNOTATION = "".concat(METHOD_TYPE_MAP_NAME, "[T]['request']");
26
- var RESULT_TYPE_ANNOTATION = "".concat(RESULT_TYPE_NAME, "<").concat(HTTP_RESPONSE_BODY_TYPE_NAME, "<").concat(METHOD_TYPE_MAP_NAME, "[T]['response']>>");
27
- var methodTypeMapCodeLines = nest_util_class_1.NestUtil.getControllerClasses(options.Module)
28
- .reduce(function (result, Class) {
29
- if (string_util_class_1.StringUtil.isFalsyString(Class === null || Class === void 0 ? void 0 : Class.name))
30
- return result;
31
- var controllerName = _.camelCase(Class.name.replace(/Controller$/g, ''));
32
- if (string_util_class_1.StringUtil.isFalsyString(controllerName) || !(0, controller_util_class_1.isHerbalController)(Class)) {
26
+ var Application = (function () {
27
+ function Application(options) {
28
+ this.options = options;
29
+ }
30
+ return Application;
31
+ }());
32
+ function isApplication(input) {
33
+ return input instanceof Application;
34
+ }
35
+ exports.isApplication = isApplication;
36
+ function createApplication(options) {
37
+ return new Application(options);
38
+ }
39
+ exports.createApplication = createApplication;
40
+ var Client = (function () {
41
+ function Client(options) {
42
+ this.options = options;
43
+ }
44
+ return Client;
45
+ }());
46
+ exports.Client = Client;
47
+ var TypeScriptClient = (function (_super) {
48
+ __extends(TypeScriptClient, _super);
49
+ function TypeScriptClient(options) {
50
+ var _this = _super.call(this, options) || this;
51
+ _this.options = options;
52
+ return _this;
53
+ }
54
+ TypeScriptClient.prototype.generateClientSourceFile = function (currentGroup) {
55
+ var options = this.options;
56
+ if (!(options === null || options === void 0 ? void 0 : options.Module))
57
+ throw new Error("Parameter 'Module' must be specified");
58
+ var METHOD_TYPE_MAP_NAME = 'MethodTypeMap';
59
+ var METHOD_TYPE_MAP_KEYS_NAME = 'MethodTypeMapKeys';
60
+ var RESPONSE_CALLBACK_DATA_NAME = 'ResponseCallbackData';
61
+ var REQUEST_OPTIONS_NAME = 'RequestOptions';
62
+ var RESULT_TYPE_NAME = 'Result';
63
+ var HTTP_RESPONSE_BODY_TYPE_NAME = 'HttpResponseBody';
64
+ var REQUEST_METHOD_MAP_NAME = 'REQUEST_METHOD_MAP';
65
+ var RESPONSE_CACHE_MAP_NAME = 'RESPONSE_CACHE_MAP';
66
+ var REQUEST_BODY_TYPE_ANNOTATION = "".concat(METHOD_TYPE_MAP_NAME, "[T]['request']");
67
+ var RESULT_TYPE_ANNOTATION = "".concat(RESULT_TYPE_NAME, "<").concat(HTTP_RESPONSE_BODY_TYPE_NAME, "<").concat(METHOD_TYPE_MAP_NAME, "[T]['response']>>");
68
+ var methodTypeMapCodeLines = nest_util_class_1.NestUtil.getControllerClasses(options.Module)
69
+ .reduce(function (result, Class) {
70
+ if (string_util_class_1.StringUtil.isFalsyString(Class === null || Class === void 0 ? void 0 : Class.name))
71
+ return result;
72
+ var controllerName = _.camelCase(Class.name.replace(/Controller$/g, ''));
73
+ if (string_util_class_1.StringUtil.isFalsyString(controllerName) || !(0, controller_util_class_1.isHerbalController)(Class)) {
74
+ return result;
75
+ }
76
+ var metadataNames = Reflect.getMetadataKeys(Class.prototype).filter(function (metadataName) { return !string_util_class_1.StringUtil.isFalsyString(metadataName); });
77
+ return result.concat(metadataNames.reduce(function (result, metadataName) {
78
+ var methodName = metadataName.slice(reflect_declaration_1.DECORATOR_NAME_PREFIX.length);
79
+ if (string_util_class_1.StringUtil.isFalsyString(metadataName) ||
80
+ !metadataName.startsWith(reflect_declaration_1.DECORATOR_NAME_PREFIX) ||
81
+ !client_groups_decorator_1.ClientGroups.shouldShowInClient(Class, methodName, function (defaultGroupName) {
82
+ var _a;
83
+ return (_a = options.allowedClientGroupsFactory) === null || _a === void 0 ? void 0 : _a.call(options, currentGroup, defaultGroupName);
84
+ })) {
33
85
  return result;
34
86
  }
35
- var metadataNames = Reflect.getMetadataKeys(Class.prototype).filter(function (metadataName) { return !string_util_class_1.StringUtil.isFalsyString(metadataName); });
36
- return result.concat(metadataNames.reduce(function (result, metadataName) {
37
- var methodName = metadataName.slice(reflect_declaration_1.DECORATOR_NAME_PREFIX.length);
38
- if (string_util_class_1.StringUtil.isFalsyString(metadataName) ||
39
- !metadataName.startsWith(reflect_declaration_1.DECORATOR_NAME_PREFIX) ||
40
- !client_groups_decorator_1.ClientGroups.shouldShowInClient(Class, methodName, options === null || options === void 0 ? void 0 : options.allowedClientGroupsFactory)) {
41
- return result;
42
- }
43
- var scopeIdentifier = "/".concat(controllerName, "/").concat(methodName);
44
- return result.concat(["'".concat(scopeIdentifier, "'"), "".concat(Reflect.getMetadata(metadataName, Class.prototype), ";")].join(': '));
45
- }, []));
46
- }, [])
47
- .map(function (line) { return " ".concat(line); });
48
- methodTypeMapCodeLines.unshift("export interface ".concat(METHOD_TYPE_MAP_NAME, " {"));
49
- methodTypeMapCodeLines.push('}');
50
- return [
51
- "import * as hash from 'object-hash';",
52
- "import * as _ from 'lodash';",
53
- "\n".concat(methodTypeMapCodeLines.join('\n')),
54
- "\ntype ".concat(METHOD_TYPE_MAP_KEYS_NAME, " = keyof ").concat(METHOD_TYPE_MAP_NAME, ";"),
55
- "\ntype ".concat(RESPONSE_CALLBACK_DATA_NAME, "<K extends ").concat(METHOD_TYPE_MAP_KEYS_NAME, "> = {"),
56
- ' url: K;',
57
- " result: ".concat(RESULT_TYPE_NAME, "<").concat(HTTP_RESPONSE_BODY_TYPE_NAME, "<").concat(METHOD_TYPE_MAP_NAME, "[K]['response']>>;"),
58
- '};',
59
- "\nexport type ".concat(HTTP_RESPONSE_BODY_TYPE_NAME, "<T> = {"),
60
- ' data: T;',
61
- ' token: string | null;',
62
- '};',
63
- "\nexport interface ".concat(REQUEST_OPTIONS_NAME, " extends RequestInit {"),
64
- ' headers?: Record<string, any>;',
65
- ' ignoreCache?: boolean;',
66
- ' prefix?: string;',
67
- ' timeout?: number;',
68
- ' getAuthorizationCredential?: () => string;',
69
- " 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>;"),
70
- " onResponse?: <K extends ".concat(METHOD_TYPE_MAP_KEYS_NAME, ">(response: ").concat(RESPONSE_CALLBACK_DATA_NAME, "<K>, id: string) => void | Promise<void>;"),
71
- '}',
72
- "\nexport interface ".concat(RESULT_TYPE_NAME, "<T> {"),
73
- ' error: Error | null;',
74
- " response: T | null;",
75
- ' status: number;',
76
- ' statusText: string;',
77
- ' headers?: Record<string, any>;',
78
- '}',
79
- '\nexport class Client {',
80
- " public constructor(private readonly options: ".concat(REQUEST_OPTIONS_NAME, " = {}) {}"),
81
- "\n protected readonly ".concat(REQUEST_METHOD_MAP_NAME, " = new Map<keyof ").concat(METHOD_TYPE_MAP_NAME, ", (...params: any[]) => Promise<unknown>>();"),
82
- "\n protected readonly ".concat(RESPONSE_CACHE_MAP_NAME, " = new Map<string, ").concat(RESULT_TYPE_NAME, "<unknown>>();"),
83
- "\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, "> {"),
84
- " if (typeof this.".concat(REQUEST_METHOD_MAP_NAME, ".get(url) !== 'function') {"),
85
- " 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));"),
86
- ' }',
87
- " 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, ">;"),
88
- ' }',
89
- "\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, "> {"),
90
- ' const id = `${Math.random().toString(32).slice(2)}${Date.now().toString(16)}`;',
91
- ' const requestHash = hash(requestBody ?? null);',
92
- ' const requestBodyString = JSON.stringify(requestBody);',
93
- " const finalOptions = _.merge({}, this?.options, _.omit(options, ['getAuthorizationCredential', 'onRequest', 'onResponse']));",
94
- " const onRequestOptions = _.omit(finalOptions, ['getAuthorizationCredential', 'onRequest', 'onResponse']);",
95
- ' const { getAuthorizationCredential, onResponse, onRequest, ignoreCache, timeout, prefix, ...requestOptions } = finalOptions;',
96
- " if (this.".concat(RESPONSE_CACHE_MAP_NAME, ".has(requestHash) && !ignoreCache) {"),
97
- ' onRequest?.({',
98
- ' prefix,',
99
- ' url,',
100
- ' requestBody: requestBodyString,',
101
- ' cached: true,',
102
- ' options: onRequestOptions,',
103
- ' id,',
104
- ' });',
105
- " return this.".concat(RESPONSE_CACHE_MAP_NAME, ".get(requestHash) as ").concat(RESULT_TYPE_ANNOTATION, ";"),
106
- ' }',
107
- ' onRequest?.({',
108
- ' prefix,',
109
- ' url,',
110
- ' id,',
111
- ' requestBody: requestBodyString,',
112
- ' cached: false,',
113
- ' options: onRequestOptions,',
114
- ' });',
115
- ' const credential = getAuthorizationCredential?.();',
116
- ' const abortController = new AbortController();',
117
- ' if (timeout! > 0) {',
118
- ' setTimeout(() => {',
119
- ' abortController.abort();',
120
- ' }, timeout);',
121
- ' }',
122
- " const result: ".concat(RESULT_TYPE_ANNOTATION, " = await fetch((prefix ?? '') + url, {"),
123
- ' ...requestOptions,',
124
- ' body: JSON.stringify(requestBody),',
125
- " method: 'POST',",
126
- ' signal: abortController.signal,',
127
- ' headers: {',
128
- ' ...requestOptions?.headers,',
129
- " 'Content-Type': 'application/json',",
130
- " Authorization: (typeof credential === 'string' && credential.length > 0) ? credential : finalOptions?.headers?.Authorization,",
131
- ' },',
132
- ' }).then((response) => {',
133
- ' const status = response?.status;',
134
- ' const statusText = response?.statusText;',
135
- ' const headers = Array.from(response?.headers?.entries?.() ?? []).reduce((result, [key, value]) => {',
136
- " if (typeof key !== 'string' || key.length === 0) return result;",
137
- ' result[key] = value;',
138
- ' return result;',
139
- ' }, {});',
140
- ' if (!response?.ok) {',
141
- ' return response.text().then((errorText) => ({ error: new Error(errorText), response: null, headers, status, statusText }));',
142
- ' }',
143
- " return response.json().then((response) => ({ error: null, response, headers, status, statusText } as ".concat(RESULT_TYPE_ANNOTATION, "));"),
144
- " }).catch((error) => Promise.resolve({ error, response: null, headers: {}, status: 0, statusText: '' }));",
145
- " onResponse?.({ url, result }, id);",
146
- " this.".concat(RESPONSE_CACHE_MAP_NAME, ".set(requestHash, result);"),
147
- ' return result;',
148
- ' }',
149
- '}\n',
150
- ].join('\n');
151
- },
87
+ var scopeIdentifier = "/".concat(controllerName, "/").concat(methodName);
88
+ return result.concat(["'".concat(scopeIdentifier, "'"), "".concat(Reflect.getMetadata(metadataName, Class.prototype), ";")].join(': '));
89
+ }, []));
90
+ }, [])
91
+ .map(function (line) { return " ".concat(line); });
92
+ methodTypeMapCodeLines.unshift("export interface ".concat(METHOD_TYPE_MAP_NAME, " {"));
93
+ methodTypeMapCodeLines.push('}');
94
+ return [
95
+ "import * as hash from 'object-hash';",
96
+ "import * as _ from 'lodash';",
97
+ "\n".concat(methodTypeMapCodeLines.join('\n')),
98
+ "\ntype ".concat(METHOD_TYPE_MAP_KEYS_NAME, " = keyof ").concat(METHOD_TYPE_MAP_NAME, ";"),
99
+ "\ntype ".concat(RESPONSE_CALLBACK_DATA_NAME, "<K extends ").concat(METHOD_TYPE_MAP_KEYS_NAME, "> = {"),
100
+ ' url: K;',
101
+ " result: ".concat(RESULT_TYPE_NAME, "<").concat(HTTP_RESPONSE_BODY_TYPE_NAME, "<").concat(METHOD_TYPE_MAP_NAME, "[K]['response']>>;"),
102
+ '};',
103
+ "\nexport type ".concat(HTTP_RESPONSE_BODY_TYPE_NAME, "<T> = {"),
104
+ ' data: T;',
105
+ ' token: string | null;',
106
+ '};',
107
+ "\nexport interface ".concat(REQUEST_OPTIONS_NAME, " extends RequestInit {"),
108
+ ' headers?: Record<string, any>;',
109
+ ' ignoreCache?: boolean;',
110
+ ' prefix?: string;',
111
+ ' timeout?: number;',
112
+ ' getAuthorizationCredential?: () => string;',
113
+ " 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>;"),
114
+ " onResponse?: <K extends ".concat(METHOD_TYPE_MAP_KEYS_NAME, ">(response: ").concat(RESPONSE_CALLBACK_DATA_NAME, "<K>, id: string) => void | Promise<void>;"),
115
+ '}',
116
+ "\nexport interface ".concat(RESULT_TYPE_NAME, "<T> {"),
117
+ ' error: Error | null;',
118
+ " response: T | null;",
119
+ ' status: number;',
120
+ ' statusText: string;',
121
+ ' headers?: Record<string, any>;',
122
+ '}',
123
+ '\nexport class Client {',
124
+ " public constructor(private readonly options: ".concat(REQUEST_OPTIONS_NAME, " = {}) {}"),
125
+ "\n protected readonly ".concat(REQUEST_METHOD_MAP_NAME, " = new Map<keyof ").concat(METHOD_TYPE_MAP_NAME, ", (...params: any[]) => Promise<unknown>>();"),
126
+ "\n protected readonly ".concat(RESPONSE_CACHE_MAP_NAME, " = new Map<string, ").concat(RESULT_TYPE_NAME, "<unknown>>();"),
127
+ "\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, "> {"),
128
+ " if (typeof this.".concat(REQUEST_METHOD_MAP_NAME, ".get(url) !== 'function') {"),
129
+ " 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));"),
130
+ ' }',
131
+ " 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, ">;"),
132
+ ' }',
133
+ "\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, "> {"),
134
+ ' const id = `${Math.random().toString(32).slice(2)}${Date.now().toString(16)}`;',
135
+ ' const requestHash = hash(requestBody ?? null);',
136
+ ' const requestBodyString = JSON.stringify(requestBody);',
137
+ " const finalOptions = _.merge({}, this?.options, _.omit(options, ['getAuthorizationCredential', 'onRequest', 'onResponse']));",
138
+ " const onRequestOptions = _.omit(finalOptions, ['getAuthorizationCredential', 'onRequest', 'onResponse']);",
139
+ ' const { getAuthorizationCredential, onResponse, onRequest, ignoreCache, timeout, prefix, ...requestOptions } = finalOptions;',
140
+ " if (this.".concat(RESPONSE_CACHE_MAP_NAME, ".has(requestHash) && !ignoreCache) {"),
141
+ ' onRequest?.({',
142
+ ' prefix,',
143
+ ' url,',
144
+ ' requestBody: requestBodyString,',
145
+ ' cached: true,',
146
+ ' options: onRequestOptions,',
147
+ ' id,',
148
+ ' });',
149
+ " return this.".concat(RESPONSE_CACHE_MAP_NAME, ".get(requestHash) as ").concat(RESULT_TYPE_ANNOTATION, ";"),
150
+ ' }',
151
+ ' onRequest?.({',
152
+ ' prefix,',
153
+ ' url,',
154
+ ' id,',
155
+ ' requestBody: requestBodyString,',
156
+ ' cached: false,',
157
+ ' options: onRequestOptions,',
158
+ ' });',
159
+ ' const credential = getAuthorizationCredential?.();',
160
+ ' const abortController = new AbortController();',
161
+ ' if (timeout! > 0) {',
162
+ ' setTimeout(() => {',
163
+ ' abortController.abort();',
164
+ ' }, timeout);',
165
+ ' }',
166
+ " const result: ".concat(RESULT_TYPE_ANNOTATION, " = await fetch((prefix ?? '') + url, {"),
167
+ ' ...requestOptions,',
168
+ ' body: JSON.stringify(requestBody),',
169
+ " method: 'POST',",
170
+ ' signal: abortController.signal,',
171
+ ' headers: {',
172
+ ' ...requestOptions?.headers,',
173
+ " 'Content-Type': 'application/json',",
174
+ " Authorization: (typeof credential === 'string' && credential.length > 0) ? credential : finalOptions?.headers?.Authorization,",
175
+ ' },',
176
+ ' }).then((response) => {',
177
+ ' const status = response?.status;',
178
+ ' const statusText = response?.statusText;',
179
+ ' const headers = Array.from(response?.headers?.entries?.() ?? []).reduce((result, [key, value]) => {',
180
+ " if (typeof key !== 'string' || key.length === 0) return result;",
181
+ ' result[key] = value;',
182
+ ' return result;',
183
+ ' }, {});',
184
+ ' if (!response?.ok) {',
185
+ ' return response.text().then((errorText) => ({ error: new Error(errorText), response: null, headers, status, statusText }));',
186
+ ' }',
187
+ " return response.json().then((response) => ({ error: null, response, headers, status, statusText } as ".concat(RESULT_TYPE_ANNOTATION, "));"),
188
+ " }).catch((error) => Promise.resolve({ error, response: null, headers: {}, status: 0, statusText: '' }));",
189
+ " onResponse?.({ url, result }, id);",
190
+ " this.".concat(RESPONSE_CACHE_MAP_NAME, ".set(requestHash, result);"),
191
+ ' return result;',
192
+ ' }',
193
+ '}\n',
194
+ ].join('\n');
152
195
  };
196
+ return TypeScriptClient;
197
+ }(Client));
198
+ function isClient(input) {
199
+ return input instanceof Client;
200
+ }
201
+ exports.isClient = isClient;
202
+ function createTypeScriptClient(options) {
203
+ return new TypeScriptClient(options);
153
204
  }
154
- exports.create = create;
205
+ exports.createTypeScriptClient = createTypeScriptClient;
@@ -1,2 +1,3 @@
1
1
  export * from './auth-adapter.decorator';
2
2
  export * from './client-groups.decorator';
3
+ export * from './no-transaction.decorator';
@@ -16,3 +16,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./auth-adapter.decorator"), exports);
18
18
  __exportStar(require("./client-groups.decorator"), exports);
19
+ __exportStar(require("./no-transaction.decorator"), exports);
@@ -0,0 +1,5 @@
1
+ import 'reflect-metadata';
2
+ export declare function NoTransaction(): PropertyDecorator;
3
+ export declare namespace NoTransaction {
4
+ var isDisabled: (target: object, propertyKey: string) => boolean;
5
+ }
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NoTransaction = void 0;
4
+ require("reflect-metadata");
5
+ var _ = require("lodash");
6
+ var TRANSACTION_DISABLED = Symbol();
7
+ function NoTransaction() {
8
+ return function (target, propertyKey) {
9
+ Reflect.defineMetadata(TRANSACTION_DISABLED, true, target, propertyKey);
10
+ };
11
+ }
12
+ exports.NoTransaction = NoTransaction;
13
+ NoTransaction.isDisabled = function (target, propertyKey) {
14
+ var result = _.attempt(function () { return Reflect.getMetadata(TRANSACTION_DISABLED, target, propertyKey); });
15
+ return result === true;
16
+ };