@opra/common 1.0.0-beta.2 → 1.0.0-beta.4
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/browser/index.cjs +5 -5
- package/browser/index.mjs +5 -5
- package/cjs/document/api-document.js +14 -0
- package/cjs/document/common/api-base.js +5 -3
- package/cjs/document/common/document-node.js +6 -2
- package/cjs/document/constants.js +2 -1
- package/cjs/document/decorators/http-controller.decorator.js +1 -1
- package/cjs/document/decorators/http-operation-entity.decorator.js +1 -1
- package/cjs/document/decorators/http-operation.decorator.js +5 -5
- package/cjs/document/decorators/rpc-controller.decorator.js +69 -0
- package/cjs/document/decorators/rpc-operation.decorator.js +80 -0
- package/cjs/document/factory/api-document.factory.js +9 -3
- package/cjs/document/factory/data-type.factory.js +20 -0
- package/cjs/document/factory/http-api.factory.js +50 -77
- package/cjs/document/factory/rpc-api.factory.js +202 -0
- package/cjs/document/http/http-api.js +5 -4
- package/cjs/document/http/http-controller.js +16 -0
- package/cjs/document/http/http-operation.js +6 -0
- package/cjs/document/index.js +8 -0
- package/cjs/document/rpc/rpc-api.js +54 -0
- package/cjs/document/rpc/rpc-controller.js +116 -0
- package/cjs/document/rpc/rpc-header.js +40 -0
- package/cjs/document/rpc/rpc-operation-response.js +58 -0
- package/cjs/document/rpc/rpc-operation.js +80 -0
- package/cjs/enums/index.js +7 -0
- package/cjs/exception/http-errors/forbidden.error.js +1 -1
- package/cjs/exception/http-errors/resource-not.available.error.js +1 -1
- package/cjs/index.js +1 -1
- package/cjs/schema/opra-schema.js +3 -0
- package/cjs/schema/rpc/rpc-controller.interface.js +11 -0
- package/cjs/schema/rpc/rpc-header.interface.js +2 -0
- package/cjs/schema/rpc/rpc-operation.interface.js +7 -0
- package/esm/document/api-document.js +14 -0
- package/esm/document/common/api-base.js +5 -3
- package/esm/document/common/document-node.js +6 -2
- package/esm/document/constants.js +1 -0
- package/esm/document/decorators/http-controller.decorator.js +1 -1
- package/esm/document/decorators/http-operation-entity.decorator.js +1 -1
- package/esm/document/decorators/http-operation.decorator.js +5 -5
- package/esm/document/decorators/rpc-controller.decorator.js +65 -0
- package/esm/document/decorators/rpc-operation.decorator.js +76 -0
- package/esm/document/factory/api-document.factory.js +9 -3
- package/esm/document/factory/data-type.factory.js +20 -0
- package/esm/document/factory/http-api.factory.js +50 -77
- package/esm/document/factory/rpc-api.factory.js +198 -0
- package/esm/document/http/http-api.js +5 -4
- package/esm/document/http/http-controller.js +17 -1
- package/esm/document/http/http-operation.js +6 -0
- package/esm/document/index.js +8 -0
- package/esm/document/rpc/rpc-api.js +50 -0
- package/esm/document/rpc/rpc-controller.js +113 -0
- package/esm/document/rpc/rpc-header.js +37 -0
- package/esm/document/rpc/rpc-operation-response.js +54 -0
- package/esm/document/rpc/rpc-operation.js +77 -0
- package/esm/enums/index.js +4 -0
- package/esm/exception/http-errors/forbidden.error.js +1 -1
- package/esm/exception/http-errors/resource-not.available.error.js +1 -1
- package/esm/index.js +1 -1
- package/esm/schema/opra-schema.js +3 -0
- package/esm/schema/rpc/rpc-controller.interface.js +8 -0
- package/esm/schema/rpc/rpc-header.interface.js +1 -0
- package/esm/schema/rpc/rpc-operation.interface.js +4 -0
- package/package.json +2 -2
- package/types/document/api-document.d.ts +5 -2
- package/types/document/common/api-base.d.ts +3 -2
- package/types/document/constants.d.ts +1 -0
- package/types/document/decorators/http-operation.decorator.d.ts +3 -3
- package/types/document/decorators/rpc-controller.decorator.d.ts +20 -0
- package/types/document/decorators/rpc-operation.decorator.d.ts +32 -0
- package/types/document/factory/api-document.factory.d.ts +2 -1
- package/types/document/factory/data-type.factory.d.ts +1 -0
- package/types/document/factory/http-api.factory.d.ts +10 -6
- package/types/document/factory/rpc-api.factory.d.ts +40 -0
- package/types/document/http/http-api.d.ts +8 -3
- package/types/document/http/http-controller.d.ts +8 -2
- package/types/document/index.d.ts +11 -0
- package/types/document/rpc/rpc-api.d.ts +27 -0
- package/types/document/rpc/rpc-controller.d.ts +89 -0
- package/types/document/rpc/rpc-header.d.ts +47 -0
- package/types/document/rpc/rpc-operation-response.d.ts +41 -0
- package/types/document/rpc/rpc-operation.d.ts +77 -0
- package/types/enums/index.d.ts +4 -0
- package/types/exception/http-errors/forbidden.error.d.ts +1 -1
- package/types/index.d.cts +1 -1
- package/types/index.d.ts +1 -1
- package/types/schema/api-document.interface.d.ts +25 -4
- package/types/schema/opra-schema.d.ts +3 -0
- package/types/schema/rpc/rpc-controller.interface.d.ts +22 -0
- package/types/schema/rpc/rpc-header.interface.d.ts +19 -0
- package/types/schema/rpc/rpc-operation.interface.d.ts +26 -0
- package/cjs/http/index.js +0 -7
- package/esm/http/index.js +0 -4
- package/types/http/index.d.ts +0 -4
- /package/cjs/{http/enums → enums}/http-headers-codes.enum.js +0 -0
- /package/cjs/{http/enums → enums}/http-status-codes.enum.js +0 -0
- /package/cjs/{http/enums → enums}/http-status-messages.js +0 -0
- /package/cjs/{http/enums → enums}/mime-types.enum.js +0 -0
- /package/esm/{http/enums → enums}/http-headers-codes.enum.js +0 -0
- /package/esm/{http/enums → enums}/http-status-codes.enum.js +0 -0
- /package/esm/{http/enums → enums}/http-status-messages.js +0 -0
- /package/esm/{http/enums → enums}/mime-types.enum.js +0 -0
- /package/types/{http/enums → enums}/http-headers-codes.enum.d.ts +0 -0
- /package/types/{http/enums → enums}/http-status-codes.enum.d.ts +0 -0
- /package/types/{http/enums → enums}/http-status-messages.d.ts +0 -0
- /package/types/{http/enums → enums}/mime-types.enum.d.ts +0 -0
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { isConstructor, resolveThunk } from '../../helpers/index.js';
|
|
2
|
+
import { RPC_CONTROLLER_METADATA } from '../constants.js';
|
|
3
|
+
import { RpcApi } from '../rpc/rpc-api.js';
|
|
4
|
+
import { RpcController } from '../rpc/rpc-controller.js';
|
|
5
|
+
import { RpcHeader } from '../rpc/rpc-header.js';
|
|
6
|
+
import { RpcOperation } from '../rpc/rpc-operation.js';
|
|
7
|
+
import { RpcOperationResponse } from '../rpc/rpc-operation-response.js';
|
|
8
|
+
import { DataTypeFactory } from './data-type.factory.js';
|
|
9
|
+
/**
|
|
10
|
+
* @class RpcApiFactory
|
|
11
|
+
*/
|
|
12
|
+
export class RpcApiFactory {
|
|
13
|
+
/**
|
|
14
|
+
* Generates RpcApi
|
|
15
|
+
* @param context
|
|
16
|
+
* @param init
|
|
17
|
+
*/
|
|
18
|
+
static async createApi(context, init) {
|
|
19
|
+
const api = new RpcApi(init);
|
|
20
|
+
if (init.controllers) {
|
|
21
|
+
await context.enterAsync('.controllers', async () => {
|
|
22
|
+
if (Array.isArray(init.controllers)) {
|
|
23
|
+
for (const c of init.controllers) {
|
|
24
|
+
const controller = await this._createController(context, api, c);
|
|
25
|
+
if (controller)
|
|
26
|
+
api.controllers.set(controller.name, controller);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
for (const [k, v] of Object.entries(init.controllers)) {
|
|
31
|
+
const controller = await this._createController(context, api, v, k);
|
|
32
|
+
if (controller)
|
|
33
|
+
api.controllers.set(controller.name, controller);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
return api;
|
|
39
|
+
}
|
|
40
|
+
static async _createController(context, parent, thunk, name) {
|
|
41
|
+
if (typeof thunk === 'function' && !isConstructor(thunk)) {
|
|
42
|
+
thunk = thunk();
|
|
43
|
+
}
|
|
44
|
+
thunk = await resolveThunk(thunk);
|
|
45
|
+
let ctor;
|
|
46
|
+
let metadata;
|
|
47
|
+
let instance;
|
|
48
|
+
// If thunk is a class
|
|
49
|
+
if (typeof thunk === 'function') {
|
|
50
|
+
metadata = Reflect.getMetadata(RPC_CONTROLLER_METADATA, thunk);
|
|
51
|
+
if (!metadata)
|
|
52
|
+
return context.addError(`Class "${thunk.name}" doesn't have a valid RpcController metadata`);
|
|
53
|
+
ctor = thunk;
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
// If thunk is an instance of a class decorated with RpcController()
|
|
57
|
+
ctor = Object.getPrototypeOf(thunk).constructor;
|
|
58
|
+
metadata = Reflect.getMetadata(RPC_CONTROLLER_METADATA, ctor);
|
|
59
|
+
if (metadata)
|
|
60
|
+
instance = thunk;
|
|
61
|
+
else {
|
|
62
|
+
// If thunk is a DecoratorMetadata or InitArguments
|
|
63
|
+
metadata = thunk;
|
|
64
|
+
if (thunk.instance === 'object') {
|
|
65
|
+
instance = thunk.instance;
|
|
66
|
+
ctor = Object.getPrototypeOf(instance).constructor;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (!metadata)
|
|
71
|
+
return context.addError(`Class "${ctor.name}" is not decorated with RpcController()`);
|
|
72
|
+
name = name || metadata.name;
|
|
73
|
+
if (!name)
|
|
74
|
+
throw new TypeError(`Controller name required`);
|
|
75
|
+
const controller = new RpcController(parent, {
|
|
76
|
+
...metadata,
|
|
77
|
+
name,
|
|
78
|
+
instance,
|
|
79
|
+
ctor,
|
|
80
|
+
});
|
|
81
|
+
if (metadata.types) {
|
|
82
|
+
await context.enterAsync('.types', async () => {
|
|
83
|
+
await DataTypeFactory.addDataTypes(context, controller, metadata.types);
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
if (metadata.headers) {
|
|
87
|
+
await context.enterAsync('.headers', async () => {
|
|
88
|
+
let i = 0;
|
|
89
|
+
for (const v of metadata.headers) {
|
|
90
|
+
await context.enterAsync(`[${i++}]`, async () => {
|
|
91
|
+
const prmArgs = { ...v };
|
|
92
|
+
await context.enterAsync('.type', async () => {
|
|
93
|
+
if (v.type)
|
|
94
|
+
prmArgs.type = controller.node.findDataType(v.type);
|
|
95
|
+
if (!prmArgs.type && typeof v.type === 'object') {
|
|
96
|
+
prmArgs.type = await DataTypeFactory.createDataType(context, controller, v.type);
|
|
97
|
+
}
|
|
98
|
+
if (!prmArgs.type)
|
|
99
|
+
prmArgs.type = controller.node.getDataType('any');
|
|
100
|
+
});
|
|
101
|
+
const prm = new RpcHeader(controller, prmArgs);
|
|
102
|
+
controller.headers.push(prm);
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
if (metadata.operations) {
|
|
108
|
+
await context.enterAsync('.operations', async () => {
|
|
109
|
+
for (const [operationName, operationMeta] of Object.entries(metadata.operations)) {
|
|
110
|
+
await context.enterAsync(`[${operationName}]`, async () => {
|
|
111
|
+
const operation = new RpcOperation(controller, {
|
|
112
|
+
...operationMeta,
|
|
113
|
+
name: operationName,
|
|
114
|
+
types: undefined,
|
|
115
|
+
payloadType: undefined,
|
|
116
|
+
keyType: undefined,
|
|
117
|
+
});
|
|
118
|
+
await this._initRpcOperation(context, operation, operationMeta);
|
|
119
|
+
controller.operations.set(operation.name, operation);
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
return controller;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Initializes RpcOperation
|
|
128
|
+
* @param context
|
|
129
|
+
* @param operation
|
|
130
|
+
* @param metadata
|
|
131
|
+
* @protected
|
|
132
|
+
*/
|
|
133
|
+
static async _initRpcOperation(context, operation, metadata) {
|
|
134
|
+
if (metadata.types) {
|
|
135
|
+
await context.enterAsync('.types', async () => {
|
|
136
|
+
await DataTypeFactory.addDataTypes(context, operation, metadata.types);
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
operation.payloadType = await DataTypeFactory.resolveDataType(context, operation, metadata.payloadType);
|
|
140
|
+
if (metadata.keyType) {
|
|
141
|
+
operation.keyType = await DataTypeFactory.resolveDataType(context, operation, metadata.keyType);
|
|
142
|
+
}
|
|
143
|
+
if (metadata.headers) {
|
|
144
|
+
await context.enterAsync('.headers', async () => {
|
|
145
|
+
let i = 0;
|
|
146
|
+
for (const v of metadata.headers) {
|
|
147
|
+
await context.enterAsync(`[${i++}]`, async () => {
|
|
148
|
+
const prmArgs = { ...v };
|
|
149
|
+
await context.enterAsync('.type', async () => {
|
|
150
|
+
prmArgs.type = await DataTypeFactory.resolveDataType(context, operation, v.type);
|
|
151
|
+
});
|
|
152
|
+
const prm = new RpcHeader(operation, prmArgs);
|
|
153
|
+
operation.headers.push(prm);
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
if (metadata.response) {
|
|
159
|
+
await context.enterAsync('.response', async () => {
|
|
160
|
+
const response = new RpcOperationResponse(operation, {
|
|
161
|
+
...metadata.response,
|
|
162
|
+
payloadType: undefined,
|
|
163
|
+
keyType: undefined,
|
|
164
|
+
});
|
|
165
|
+
await this._initRpcOperationResponse(context, response, metadata.response);
|
|
166
|
+
operation.response = response;
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Initializes RpcOperationResponse
|
|
172
|
+
* @param context
|
|
173
|
+
* @param response
|
|
174
|
+
* @param metadata
|
|
175
|
+
* @protected
|
|
176
|
+
*/
|
|
177
|
+
static async _initRpcOperationResponse(context, response, metadata) {
|
|
178
|
+
response.payloadType = await DataTypeFactory.resolveDataType(context, response, metadata.payloadType);
|
|
179
|
+
if (metadata.keyType) {
|
|
180
|
+
response.keyType = await DataTypeFactory.resolveDataType(context, response, metadata.keyType);
|
|
181
|
+
}
|
|
182
|
+
if (metadata.headers) {
|
|
183
|
+
await context.enterAsync('.headers', async () => {
|
|
184
|
+
let i = 0;
|
|
185
|
+
for (const v of metadata.headers) {
|
|
186
|
+
await context.enterAsync(`[${i++}]`, async () => {
|
|
187
|
+
const prmArgs = { ...v };
|
|
188
|
+
await context.enterAsync('.type', async () => {
|
|
189
|
+
prmArgs.type = await DataTypeFactory.resolveDataType(context, response, v.type);
|
|
190
|
+
});
|
|
191
|
+
const prm = new RpcHeader(response, prmArgs);
|
|
192
|
+
response.headers.push(prm);
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
@@ -5,12 +5,13 @@ import { HttpController } from './http-controller.js';
|
|
|
5
5
|
* @class HttpApi
|
|
6
6
|
*/
|
|
7
7
|
export class HttpApi extends ApiBase {
|
|
8
|
-
constructor(
|
|
9
|
-
super(
|
|
8
|
+
constructor(init) {
|
|
9
|
+
super(init);
|
|
10
10
|
// noinspection JSUnusedGlobalSymbols
|
|
11
11
|
this._controllerReverseMap = new WeakMap();
|
|
12
|
-
this.
|
|
12
|
+
this.transport = 'http';
|
|
13
13
|
this.controllers = new ResponsiveMap();
|
|
14
|
+
this.url = init.url;
|
|
14
15
|
}
|
|
15
16
|
findController(arg0) {
|
|
16
17
|
return HttpController.prototype.findController.call(this, arg0);
|
|
@@ -23,7 +24,7 @@ export class HttpApi extends ApiBase {
|
|
|
23
24
|
const schema = super.toJSON();
|
|
24
25
|
const out = {
|
|
25
26
|
...schema,
|
|
26
|
-
|
|
27
|
+
transport: this.transport,
|
|
27
28
|
url: this.url,
|
|
28
29
|
controllers: {},
|
|
29
30
|
};
|
|
@@ -4,7 +4,7 @@ import { omitUndefined, ResponsiveMap } from '../../helpers/index.js';
|
|
|
4
4
|
import { OpraSchema } from '../../schema/index.js';
|
|
5
5
|
import { DataTypeMap } from '../common/data-type-map.js';
|
|
6
6
|
import { DocumentElement } from '../common/document-element.js';
|
|
7
|
-
import { CLASS_NAME_PATTERN, DECORATOR, kDataTypeMap } from '../constants.js';
|
|
7
|
+
import { CLASS_NAME_PATTERN, DECORATOR, HTTP_CONTROLLER_METADATA, kDataTypeMap } from '../constants.js';
|
|
8
8
|
import { HttpControllerDecoratorFactory } from '../decorators/http-controller.decorator.js';
|
|
9
9
|
import { colorFgMagenta, colorFgYellow, colorReset, nodeInspectCustom } from '../utils/inspect.util.js';
|
|
10
10
|
/**
|
|
@@ -32,6 +32,8 @@ export const HttpController = function (...args) {
|
|
|
32
32
|
_this.ctor = initArgs.ctor;
|
|
33
33
|
_this._controllerReverseMap = new WeakMap();
|
|
34
34
|
_this._initialize?.(initArgs);
|
|
35
|
+
_this.onInit = initArgs.onInit;
|
|
36
|
+
_this.onShutdown = initArgs.onShutdown;
|
|
35
37
|
};
|
|
36
38
|
/**
|
|
37
39
|
*
|
|
@@ -151,3 +153,17 @@ class HttpControllerClass extends DocumentElement {
|
|
|
151
153
|
HttpController.prototype = HttpControllerClass.prototype;
|
|
152
154
|
Object.assign(HttpController, HttpControllerDecoratorFactory);
|
|
153
155
|
HttpController[DECORATOR] = HttpControllerDecoratorFactory;
|
|
156
|
+
HttpController.OnInit = function () {
|
|
157
|
+
return (target, propertyKey) => {
|
|
158
|
+
const sourceMetadata = (Reflect.getOwnMetadata(HTTP_CONTROLLER_METADATA, target.constructor) || {});
|
|
159
|
+
sourceMetadata.onInit = target[propertyKey];
|
|
160
|
+
Reflect.defineMetadata(HTTP_CONTROLLER_METADATA, target.constructor, sourceMetadata);
|
|
161
|
+
};
|
|
162
|
+
};
|
|
163
|
+
HttpController.OnShutdown = function () {
|
|
164
|
+
return (target, propertyKey) => {
|
|
165
|
+
const sourceMetadata = (Reflect.getOwnMetadata(HTTP_CONTROLLER_METADATA, target.constructor) || {});
|
|
166
|
+
sourceMetadata.onShutdown = target[propertyKey];
|
|
167
|
+
Reflect.defineMetadata(HTTP_CONTROLLER_METADATA, target.constructor, sourceMetadata);
|
|
168
|
+
};
|
|
169
|
+
};
|
|
@@ -74,6 +74,12 @@ class HttpOperationClass extends DocumentElement {
|
|
|
74
74
|
composition: this.composition,
|
|
75
75
|
requestBody: this.requestBody?.toJSON(),
|
|
76
76
|
});
|
|
77
|
+
if (this.types.size) {
|
|
78
|
+
out.types = {};
|
|
79
|
+
for (const v of this.types.values()) {
|
|
80
|
+
out.types[v.name] = v.toJSON();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
77
83
|
if (this.parameters.length) {
|
|
78
84
|
out.parameters = [];
|
|
79
85
|
for (const prm of this.parameters) {
|
package/esm/document/index.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import 'reflect-metadata';
|
|
2
|
+
import * as RpcControllerDecorator_ from './decorators/rpc-controller.decorator.js';
|
|
3
|
+
import * as RpcOperationDecorator_ from './decorators/rpc-operation.decorator.js';
|
|
2
4
|
import * as DataTypeFactory_ from './factory/data-type.factory.js';
|
|
3
5
|
import * as HttpApiFactory_ from './factory/http-api.factory.js';
|
|
4
6
|
export * from './api-document.js';
|
|
@@ -33,8 +35,14 @@ export * from './http/http-operation-response.js';
|
|
|
33
35
|
export * from './http/http-parameter.js';
|
|
34
36
|
export * from './http/http-request-body.js';
|
|
35
37
|
export * from './http/http-status-range.js';
|
|
38
|
+
export * from './rpc/rpc-api.js';
|
|
39
|
+
export * from './rpc/rpc-controller.js';
|
|
40
|
+
export * from './rpc/rpc-header.js';
|
|
41
|
+
export * from './rpc/rpc-operation.js';
|
|
36
42
|
export var classes;
|
|
37
43
|
(function (classes) {
|
|
38
44
|
classes.HttpApiFactory = HttpApiFactory_.HttpApiFactory;
|
|
39
45
|
classes.DataTypeFactory = DataTypeFactory_.DataTypeFactory;
|
|
46
|
+
classes.RpcOperationDecoratorFactory = RpcOperationDecorator_.RpcOperationDecoratorFactory;
|
|
47
|
+
classes.RpcControllerDecoratorFactory = RpcControllerDecorator_.RpcControllerDecoratorFactory;
|
|
40
48
|
})(classes || (classes = {}));
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { ResponsiveMap } from '../../helpers/index.js';
|
|
2
|
+
import { ApiBase } from '../common/api-base.js';
|
|
3
|
+
/**
|
|
4
|
+
* @class RpcApi
|
|
5
|
+
*/
|
|
6
|
+
export class RpcApi extends ApiBase {
|
|
7
|
+
constructor(init) {
|
|
8
|
+
super(init);
|
|
9
|
+
// noinspection JSUnusedGlobalSymbols
|
|
10
|
+
this._controllerReverseMap = new WeakMap();
|
|
11
|
+
this.transport = 'rpc';
|
|
12
|
+
this.controllers = new ResponsiveMap();
|
|
13
|
+
this.platform = init.platform;
|
|
14
|
+
}
|
|
15
|
+
findController(arg0) {
|
|
16
|
+
if (typeof arg0 === 'function') {
|
|
17
|
+
/** Check for cached mapping */
|
|
18
|
+
const controller = this._controllerReverseMap.get(arg0);
|
|
19
|
+
if (controller != null)
|
|
20
|
+
return controller;
|
|
21
|
+
/** Lookup for ctor in all controllers */
|
|
22
|
+
for (const c of this.controllers.values()) {
|
|
23
|
+
if (c.ctor === arg0) {
|
|
24
|
+
this._controllerReverseMap.set(arg0, c);
|
|
25
|
+
return c;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
this._controllerReverseMap.set(arg0, null);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
return this.controllers.get(arg0);
|
|
32
|
+
}
|
|
33
|
+
findOperation(arg0, operationName) {
|
|
34
|
+
const controller = this.findController(arg0);
|
|
35
|
+
return controller?.operations.get(operationName);
|
|
36
|
+
}
|
|
37
|
+
toJSON() {
|
|
38
|
+
const schema = super.toJSON();
|
|
39
|
+
const out = {
|
|
40
|
+
...schema,
|
|
41
|
+
transport: this.transport,
|
|
42
|
+
platform: this.platform,
|
|
43
|
+
controllers: {},
|
|
44
|
+
};
|
|
45
|
+
for (const v of this.controllers.values()) {
|
|
46
|
+
out.controllers[v.name] = v.toJSON();
|
|
47
|
+
}
|
|
48
|
+
return out;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { asMutable } from 'ts-gems';
|
|
2
|
+
import { omitUndefined, ResponsiveMap } from '../../helpers/index.js';
|
|
3
|
+
import { OpraSchema } from '../../schema/index.js';
|
|
4
|
+
import { DataTypeMap } from '../common/data-type-map.js';
|
|
5
|
+
import { DocumentElement } from '../common/document-element.js';
|
|
6
|
+
import { CLASS_NAME_PATTERN, DECORATOR, kDataTypeMap, RPC_CONTROLLER_METADATA } from '../constants.js';
|
|
7
|
+
import { RpcControllerDecoratorFactory } from '../decorators/rpc-controller.decorator.js';
|
|
8
|
+
import { colorFgMagenta, colorFgYellow, colorReset, nodeInspectCustom } from '../utils/inspect.util.js';
|
|
9
|
+
/**
|
|
10
|
+
* RpcController
|
|
11
|
+
*/
|
|
12
|
+
export const RpcController = function (...args) {
|
|
13
|
+
// ClassDecorator
|
|
14
|
+
if (!this)
|
|
15
|
+
return RpcController[DECORATOR].apply(undefined, args);
|
|
16
|
+
// Constructor
|
|
17
|
+
const [owner, initArgs] = args;
|
|
18
|
+
DocumentElement.call(this, owner);
|
|
19
|
+
if (!CLASS_NAME_PATTERN.test(initArgs.name))
|
|
20
|
+
throw new TypeError(`Invalid resource name (${initArgs.name})`);
|
|
21
|
+
const _this = asMutable(this);
|
|
22
|
+
_this.kind = OpraSchema.RpcController.Kind;
|
|
23
|
+
_this.types = _this.node[kDataTypeMap] = new DataTypeMap();
|
|
24
|
+
_this.operations = new ResponsiveMap();
|
|
25
|
+
_this.headers = [];
|
|
26
|
+
_this.name = initArgs.name;
|
|
27
|
+
_this.description = initArgs.description;
|
|
28
|
+
_this.instance = initArgs.instance;
|
|
29
|
+
_this.ctor = initArgs.ctor;
|
|
30
|
+
_this._controllerReverseMap = new WeakMap();
|
|
31
|
+
_this._initialize?.(initArgs);
|
|
32
|
+
_this.onInit = initArgs.onInit;
|
|
33
|
+
_this.onShutdown = initArgs.onShutdown;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
*
|
|
37
|
+
* @class RpcController
|
|
38
|
+
*/
|
|
39
|
+
class RpcControllerClass extends DocumentElement {
|
|
40
|
+
findHeader(paramName, location) {
|
|
41
|
+
const paramNameLower = paramName.toLowerCase();
|
|
42
|
+
let prm;
|
|
43
|
+
for (prm of this.headers) {
|
|
44
|
+
if (typeof prm.name === 'string') {
|
|
45
|
+
prm._nameLower = prm._nameLower || prm.name.toLowerCase();
|
|
46
|
+
if (prm._nameLower === paramNameLower)
|
|
47
|
+
return prm;
|
|
48
|
+
}
|
|
49
|
+
if (prm.name instanceof RegExp && prm.name.test(paramName))
|
|
50
|
+
return prm;
|
|
51
|
+
}
|
|
52
|
+
if (this.node.parent && this.node.parent.element instanceof RpcController) {
|
|
53
|
+
return this.node.parent.element.findHeader(paramName, location);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
*
|
|
58
|
+
*/
|
|
59
|
+
toString() {
|
|
60
|
+
return `[RpcController ${this.name}]`;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
*
|
|
64
|
+
*/
|
|
65
|
+
toJSON() {
|
|
66
|
+
const out = omitUndefined({
|
|
67
|
+
kind: this.kind,
|
|
68
|
+
description: this.description,
|
|
69
|
+
});
|
|
70
|
+
if (this.operations.size) {
|
|
71
|
+
out.operations = {};
|
|
72
|
+
for (const v of this.operations.values()) {
|
|
73
|
+
out.operations[v.name] = v.toJSON();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (this.types.size) {
|
|
77
|
+
out.types = {};
|
|
78
|
+
for (const v of this.types.values()) {
|
|
79
|
+
out.types[v.name] = v.toJSON();
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if (this.headers.length) {
|
|
83
|
+
out.headers = [];
|
|
84
|
+
for (const prm of this.headers) {
|
|
85
|
+
out.headers.push(prm.toJSON());
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return out;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
*
|
|
92
|
+
*/
|
|
93
|
+
[nodeInspectCustom]() {
|
|
94
|
+
return `[${colorFgYellow}RpcController${colorFgMagenta + this.name + colorReset}]`;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
RpcController.prototype = RpcControllerClass.prototype;
|
|
98
|
+
Object.assign(RpcController, RpcControllerDecoratorFactory);
|
|
99
|
+
RpcController[DECORATOR] = RpcControllerDecoratorFactory;
|
|
100
|
+
RpcController.OnInit = function () {
|
|
101
|
+
return (target, propertyKey) => {
|
|
102
|
+
const sourceMetadata = (Reflect.getOwnMetadata(RPC_CONTROLLER_METADATA, target.constructor) || {});
|
|
103
|
+
sourceMetadata.onInit = target[propertyKey];
|
|
104
|
+
Reflect.defineMetadata(RPC_CONTROLLER_METADATA, target.constructor, sourceMetadata);
|
|
105
|
+
};
|
|
106
|
+
};
|
|
107
|
+
RpcController.OnShutdown = function () {
|
|
108
|
+
return (target, propertyKey) => {
|
|
109
|
+
const sourceMetadata = (Reflect.getOwnMetadata(RPC_CONTROLLER_METADATA, target.constructor) || {});
|
|
110
|
+
sourceMetadata.onShutdown = target[propertyKey];
|
|
111
|
+
Reflect.defineMetadata(RPC_CONTROLLER_METADATA, target.constructor, sourceMetadata);
|
|
112
|
+
};
|
|
113
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { asMutable } from 'ts-gems';
|
|
2
|
+
import { omitUndefined } from '../../helpers/index.js';
|
|
3
|
+
import { Value } from '../common/value.js';
|
|
4
|
+
import { parseRegExp } from '../utils/parse-regexp.util.js';
|
|
5
|
+
export const RpcHeader = function (owner, initArgs) {
|
|
6
|
+
if (!this)
|
|
7
|
+
throw new TypeError('"this" should be passed to call class constructor');
|
|
8
|
+
Value.call(this, owner, initArgs);
|
|
9
|
+
const _this = asMutable(this);
|
|
10
|
+
if (initArgs.name) {
|
|
11
|
+
_this.name =
|
|
12
|
+
initArgs.name instanceof RegExp
|
|
13
|
+
? initArgs.name
|
|
14
|
+
: initArgs.name.startsWith('/')
|
|
15
|
+
? parseRegExp(initArgs.name, {
|
|
16
|
+
includeFlags: 'i',
|
|
17
|
+
excludeFlags: 'm',
|
|
18
|
+
})
|
|
19
|
+
: initArgs.name;
|
|
20
|
+
}
|
|
21
|
+
_this.deprecated = initArgs.deprecated;
|
|
22
|
+
_this.required = initArgs.required;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* @class RpcHeader
|
|
26
|
+
*/
|
|
27
|
+
class RpcHeaderClass extends Value {
|
|
28
|
+
toJSON() {
|
|
29
|
+
return omitUndefined({
|
|
30
|
+
...super.toJSON(),
|
|
31
|
+
name: this.name,
|
|
32
|
+
required: this.required,
|
|
33
|
+
deprecated: this.deprecated,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
RpcHeader.prototype = RpcHeaderClass.prototype;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { omitUndefined } from '../../helpers/index.js';
|
|
2
|
+
import { DocumentElement } from '../common/document-element.js';
|
|
3
|
+
import { DataType } from '../data-type/data-type.js';
|
|
4
|
+
/**
|
|
5
|
+
* @class RpcOperationResponse
|
|
6
|
+
*/
|
|
7
|
+
export class RpcOperationResponse extends DocumentElement {
|
|
8
|
+
constructor(owner, initArgs) {
|
|
9
|
+
super(owner);
|
|
10
|
+
this.headers = [];
|
|
11
|
+
this.channel = initArgs?.channel;
|
|
12
|
+
this.description = initArgs?.description;
|
|
13
|
+
if (initArgs?.payloadType) {
|
|
14
|
+
this.payloadType =
|
|
15
|
+
initArgs?.payloadType instanceof DataType
|
|
16
|
+
? initArgs.payloadType
|
|
17
|
+
: this.owner.node.getDataType(initArgs.payloadType);
|
|
18
|
+
}
|
|
19
|
+
else
|
|
20
|
+
this.payloadType = this.owner.node.getDataType('any');
|
|
21
|
+
if (initArgs?.keyType) {
|
|
22
|
+
this.keyType =
|
|
23
|
+
initArgs?.keyType instanceof DataType ? initArgs.keyType : this.owner.node.getDataType(initArgs.keyType);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
findHeader(paramName) {
|
|
27
|
+
const paramNameLower = paramName.toLowerCase();
|
|
28
|
+
let prm;
|
|
29
|
+
for (prm of this.headers) {
|
|
30
|
+
if (typeof prm.name === 'string') {
|
|
31
|
+
prm._nameLower = prm._nameLower || prm.name.toLowerCase();
|
|
32
|
+
if (prm._nameLower === paramNameLower)
|
|
33
|
+
return prm;
|
|
34
|
+
}
|
|
35
|
+
if (prm.name instanceof RegExp && prm.name.test(paramName))
|
|
36
|
+
return prm;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
toJSON() {
|
|
40
|
+
const out = omitUndefined({
|
|
41
|
+
description: this.description,
|
|
42
|
+
channel: this.channel,
|
|
43
|
+
payloadType: this.payloadType.name ? this.payloadType.name : this.payloadType.toJSON(),
|
|
44
|
+
keyType: this.keyType ? (this.keyType.name ? this.keyType.name : this.keyType.toJSON()) : undefined,
|
|
45
|
+
});
|
|
46
|
+
if (this.headers.length) {
|
|
47
|
+
out.headers = [];
|
|
48
|
+
for (const prm of this.headers) {
|
|
49
|
+
out.headers.push(prm.toJSON());
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return out;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { asMutable } from 'ts-gems';
|
|
2
|
+
import { omitUndefined } from '../../helpers/index.js';
|
|
3
|
+
import { OpraSchema } from '../../schema/index.js';
|
|
4
|
+
import { DataTypeMap } from '../common/data-type-map.js';
|
|
5
|
+
import { DocumentElement } from '../common/document-element.js';
|
|
6
|
+
import { CLASS_NAME_PATTERN, DECORATOR, kDataTypeMap } from '../constants.js';
|
|
7
|
+
import { DataType } from '../data-type/data-type.js';
|
|
8
|
+
import { RpcOperationDecoratorFactory } from '../decorators/rpc-operation.decorator.js';
|
|
9
|
+
/**
|
|
10
|
+
* RpcOperation
|
|
11
|
+
*/
|
|
12
|
+
export const RpcOperation = function (...args) {
|
|
13
|
+
// Decorator
|
|
14
|
+
if (!this) {
|
|
15
|
+
const [payloadType, options] = args;
|
|
16
|
+
const decoratorChain = [];
|
|
17
|
+
return RpcOperation[DECORATOR].call(undefined, decoratorChain, payloadType, options);
|
|
18
|
+
}
|
|
19
|
+
// Constructor
|
|
20
|
+
const [resource, initArgs] = args;
|
|
21
|
+
DocumentElement.call(this, resource);
|
|
22
|
+
if (!CLASS_NAME_PATTERN.test(initArgs.name))
|
|
23
|
+
throw new TypeError(`Invalid operation name (${initArgs.name})`);
|
|
24
|
+
const _this = asMutable(this);
|
|
25
|
+
_this.headers = [];
|
|
26
|
+
_this.types = _this.node[kDataTypeMap] = new DataTypeMap();
|
|
27
|
+
_this.name = initArgs.name;
|
|
28
|
+
_this.description = initArgs.description;
|
|
29
|
+
_this.channel = initArgs.channel;
|
|
30
|
+
if (initArgs?.payloadType) {
|
|
31
|
+
_this.payloadType =
|
|
32
|
+
initArgs?.payloadType instanceof DataType
|
|
33
|
+
? initArgs.payloadType
|
|
34
|
+
: _this.owner.node.getDataType(initArgs.payloadType);
|
|
35
|
+
}
|
|
36
|
+
if (initArgs?.keyType) {
|
|
37
|
+
_this.keyType =
|
|
38
|
+
initArgs?.keyType instanceof DataType ? initArgs.keyType : _this.owner.node.getDataType(initArgs.keyType);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* @class RpcOperation
|
|
43
|
+
*/
|
|
44
|
+
class RpcOperationClass extends DocumentElement {
|
|
45
|
+
findHeader(paramName) {
|
|
46
|
+
const paramNameLower = paramName.toLowerCase();
|
|
47
|
+
let prm;
|
|
48
|
+
for (prm of this.headers) {
|
|
49
|
+
if (typeof prm.name === 'string') {
|
|
50
|
+
prm._nameLower = prm._nameLower || prm.name.toLowerCase();
|
|
51
|
+
if (prm._nameLower === paramNameLower)
|
|
52
|
+
return prm;
|
|
53
|
+
}
|
|
54
|
+
if (prm.name instanceof RegExp && prm.name.test(paramName))
|
|
55
|
+
return prm;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
toJSON() {
|
|
59
|
+
const out = omitUndefined({
|
|
60
|
+
kind: OpraSchema.RpcOperation.Kind,
|
|
61
|
+
description: this.description,
|
|
62
|
+
channel: this.channel,
|
|
63
|
+
payloadType: this.payloadType.name ? this.payloadType.name : this.payloadType.toJSON(),
|
|
64
|
+
keyType: this.keyType ? (this.keyType.name ? this.keyType.name : this.keyType.toJSON()) : undefined,
|
|
65
|
+
response: this.response?.toJSON(),
|
|
66
|
+
});
|
|
67
|
+
if (this.headers.length) {
|
|
68
|
+
out.headers = [];
|
|
69
|
+
for (const prm of this.headers) {
|
|
70
|
+
out.headers.push(prm.toJSON());
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return out;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
RpcOperation.prototype = RpcOperationClass.prototype;
|
|
77
|
+
RpcOperation[DECORATOR] = RpcOperationDecoratorFactory;
|
package/esm/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export * from './document/index.js';
|
|
2
|
+
export * from './enums/index.js';
|
|
2
3
|
export * from './exception/index.js';
|
|
3
4
|
export * from './filter/index.js';
|
|
4
5
|
export * from './helpers/index.js';
|
|
5
|
-
export * from './http/index.js';
|
|
6
6
|
export * from './i18n/index.js';
|
|
7
7
|
export * from './schema/index.js';
|
|
8
8
|
export * from './types.js';
|
|
@@ -16,6 +16,9 @@ export * from './http/http-operation-response.interface.js';
|
|
|
16
16
|
export * from './http/http-parameter.interface.js';
|
|
17
17
|
export * from './http/http-request-body.interface.js';
|
|
18
18
|
export * from './http/http-status-range.interface.js';
|
|
19
|
+
export * from './rpc/rpc-controller.interface.js';
|
|
20
|
+
export * from './rpc/rpc-header.interface.js';
|
|
21
|
+
export * from './rpc/rpc-operation.interface.js';
|
|
19
22
|
export * from './type-guards.js';
|
|
20
23
|
export * from './types.js';
|
|
21
24
|
export * from './value.interface.js';
|