@opra/nestjs 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +2 -0
- package/cjs/constants.js +7 -0
- package/cjs/decorators/context.decorator.js +30 -0
- package/cjs/enums/handler-paramtype.enum.js +12 -0
- package/cjs/factories/params.factory.js +29 -0
- package/cjs/factories/service.factory.js +164 -0
- package/cjs/index.js +9 -0
- package/cjs/interfaces/opra-execution-context.js +10 -0
- package/cjs/interfaces/opra-module-options.interface.js +2 -0
- package/cjs/opra-core.module.js +149 -0
- package/cjs/opra.module.js +25 -0
- package/cjs/package.json +3 -0
- package/cjs/services/nest-explorer.js +35 -0
- package/cjs/services/service-loader.js +88 -0
- package/cjs/types.js +2 -0
- package/cjs/utils/class.utils.js +25 -0
- package/cjs/utils/function.utils.js +23 -0
- package/cjs/utils/param.utils.js +22 -0
- package/esm/constants.d.ts +4 -0
- package/esm/constants.js +4 -0
- package/esm/decorators/context.decorator.d.ts +25 -0
- package/esm/decorators/context.decorator.js +27 -0
- package/esm/enums/handler-paramtype.enum.d.ts +8 -0
- package/esm/enums/handler-paramtype.enum.js +9 -0
- package/esm/factories/params.factory.d.ts +4 -0
- package/esm/factories/params.factory.js +25 -0
- package/esm/factories/service.factory.d.ts +15 -0
- package/esm/factories/service.factory.js +161 -0
- package/esm/index.d.ts +5 -0
- package/esm/index.js +6 -0
- package/esm/interfaces/opra-execution-context.d.ts +6 -0
- package/esm/interfaces/opra-execution-context.js +7 -0
- package/esm/interfaces/opra-module-options.interface.d.ts +49 -0
- package/esm/interfaces/opra-module-options.interface.js +1 -0
- package/esm/opra-core.module.d.ts +18 -0
- package/esm/opra-core.module.js +146 -0
- package/esm/opra.module.d.ts +6 -0
- package/esm/opra.module.js +22 -0
- package/esm/services/nest-explorer.d.ts +6 -0
- package/esm/services/nest-explorer.js +31 -0
- package/esm/services/service-loader.d.ts +18 -0
- package/esm/services/service-loader.js +84 -0
- package/esm/types.d.ts +2 -0
- package/esm/types.js +1 -0
- package/esm/utils/class.utils.d.ts +4 -0
- package/esm/utils/class.utils.js +19 -0
- package/esm/utils/function.utils.d.ts +1 -0
- package/esm/utils/function.utils.js +19 -0
- package/esm/utils/param.utils.d.ts +8 -0
- package/esm/utils/param.utils.js +18 -0
- package/package.json +73 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022 Panates
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
package/cjs/constants.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PARAM_ARGS_METADATA = exports.OPRA_INITIALIZER = exports.OPRA_MODULE_ID = exports.OPRA_MODULE_OPTIONS = void 0;
|
|
4
|
+
exports.OPRA_MODULE_OPTIONS = 'opra:module_options';
|
|
5
|
+
exports.OPRA_MODULE_ID = 'opra:module_id';
|
|
6
|
+
exports.OPRA_INITIALIZER = 'opra_initializer';
|
|
7
|
+
exports.PARAM_ARGS_METADATA = '__routeArguments__';
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Query = exports.Service = exports.Response = exports.Request = exports.Context = void 0;
|
|
4
|
+
const handler_paramtype_enum_js_1 = require("../enums/handler-paramtype.enum.js");
|
|
5
|
+
const param_utils_js_1 = require("../utils/param.utils.js");
|
|
6
|
+
/**
|
|
7
|
+
* Handler method parameter decorator. Populates the decorated
|
|
8
|
+
* parameter with the value of `ExecutionContext`.
|
|
9
|
+
*/
|
|
10
|
+
exports.Context = (0, param_utils_js_1.createOpraParamDecorator)(handler_paramtype_enum_js_1.HandlerParamType.CONTEXT);
|
|
11
|
+
/**
|
|
12
|
+
* Handler method parameter decorator. Populates the decorated
|
|
13
|
+
* parameter with the value of `ExecutionRequest`.
|
|
14
|
+
*/
|
|
15
|
+
exports.Request = (0, param_utils_js_1.createOpraParamDecorator)(handler_paramtype_enum_js_1.HandlerParamType.REQUEST);
|
|
16
|
+
/**
|
|
17
|
+
* Handler method parameter decorator. Populates the decorated
|
|
18
|
+
* parameter with the value of `ExecutionResponse`.
|
|
19
|
+
*/
|
|
20
|
+
exports.Response = (0, param_utils_js_1.createOpraParamDecorator)(handler_paramtype_enum_js_1.HandlerParamType.RESPONSE);
|
|
21
|
+
/**
|
|
22
|
+
* Handler method parameter decorator. Populates the decorated
|
|
23
|
+
* parameter with the value of `OpraService`.
|
|
24
|
+
*/
|
|
25
|
+
exports.Service = (0, param_utils_js_1.createOpraParamDecorator)(handler_paramtype_enum_js_1.HandlerParamType.SERVICE);
|
|
26
|
+
/**
|
|
27
|
+
* Handler method parameter decorator. Populates the decorated
|
|
28
|
+
* parameter with the value of `OpraService`.
|
|
29
|
+
*/
|
|
30
|
+
exports.Query = (0, param_utils_js_1.createOpraParamDecorator)(handler_paramtype_enum_js_1.HandlerParamType.QUERY);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HandlerParamType = void 0;
|
|
4
|
+
var HandlerParamType;
|
|
5
|
+
(function (HandlerParamType) {
|
|
6
|
+
HandlerParamType[HandlerParamType["CONTEXT"] = 0] = "CONTEXT";
|
|
7
|
+
HandlerParamType[HandlerParamType["SERVICE"] = 1] = "SERVICE";
|
|
8
|
+
HandlerParamType[HandlerParamType["REQUEST"] = 2] = "REQUEST";
|
|
9
|
+
HandlerParamType[HandlerParamType["QUERY"] = 3] = "QUERY";
|
|
10
|
+
HandlerParamType[HandlerParamType["RESPONSE"] = 4] = "RESPONSE";
|
|
11
|
+
HandlerParamType[HandlerParamType["USER_CONTEXT"] = 5] = "USER_CONTEXT";
|
|
12
|
+
})(HandlerParamType = exports.HandlerParamType || (exports.HandlerParamType = {}));
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OpraParamsFactory = void 0;
|
|
4
|
+
const handler_paramtype_enum_js_1 = require("../enums/handler-paramtype.enum.js");
|
|
5
|
+
class OpraParamsFactory {
|
|
6
|
+
exchangeKeyForValue(type, data, args) {
|
|
7
|
+
if (!args) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
args = Array.isArray(args) ? args : [];
|
|
11
|
+
switch (type) {
|
|
12
|
+
case handler_paramtype_enum_js_1.HandlerParamType.CONTEXT:
|
|
13
|
+
return args[3];
|
|
14
|
+
case handler_paramtype_enum_js_1.HandlerParamType.SERVICE:
|
|
15
|
+
return args[3].service;
|
|
16
|
+
case handler_paramtype_enum_js_1.HandlerParamType.REQUEST:
|
|
17
|
+
return args[3].request;
|
|
18
|
+
case handler_paramtype_enum_js_1.HandlerParamType.QUERY:
|
|
19
|
+
return args[3].request.query;
|
|
20
|
+
case handler_paramtype_enum_js_1.HandlerParamType.RESPONSE:
|
|
21
|
+
return args[3].response;
|
|
22
|
+
case handler_paramtype_enum_js_1.HandlerParamType.USER_CONTEXT:
|
|
23
|
+
return args[3].userContext;
|
|
24
|
+
default:
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
exports.OpraParamsFactory = OpraParamsFactory;
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ServiceFactory = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const lodash_1 = tslib_1.__importDefault(require("lodash"));
|
|
6
|
+
const common_1 = require("@nestjs/common");
|
|
7
|
+
const core_1 = require("@nestjs/core");
|
|
8
|
+
const external_context_creator_1 = require("@nestjs/core/helpers/external-context-creator");
|
|
9
|
+
const injector_1 = require("@nestjs/core/injector/injector");
|
|
10
|
+
const internal_core_module_1 = require("@nestjs/core/injector/internal-core-module");
|
|
11
|
+
const request_constants_1 = require("@nestjs/core/router/request/request-constants");
|
|
12
|
+
const core_2 = require("@opra/core");
|
|
13
|
+
const schema_1 = require("@opra/schema");
|
|
14
|
+
const constants_js_1 = require("../constants.js");
|
|
15
|
+
const handler_paramtype_enum_js_1 = require("../enums/handler-paramtype.enum.js");
|
|
16
|
+
const nest_explorer_js_1 = require("../services/nest-explorer.js");
|
|
17
|
+
const function_utils_js_1 = require("../utils/function.utils.js");
|
|
18
|
+
const params_factory_js_1 = require("./params.factory.js");
|
|
19
|
+
const entityHandlers = ['search', 'create', 'read', 'update', 'updateMany', 'delete', 'deleteMany'];
|
|
20
|
+
const noOpFunction = () => void 0;
|
|
21
|
+
let ServiceFactory = class ServiceFactory {
|
|
22
|
+
paramsFactory = new params_factory_js_1.OpraParamsFactory();
|
|
23
|
+
injector = new injector_1.Injector();
|
|
24
|
+
modulesContainer;
|
|
25
|
+
externalContextCreator;
|
|
26
|
+
explorerService;
|
|
27
|
+
async generateService(rootModule, moduleOptions, contextType) {
|
|
28
|
+
const info = { title: '', version: '', ...moduleOptions.info };
|
|
29
|
+
info.title = info.title || 'Untitled service';
|
|
30
|
+
info.version = info.version || '1';
|
|
31
|
+
const serviceArgs = {
|
|
32
|
+
info,
|
|
33
|
+
types: [],
|
|
34
|
+
resources: [],
|
|
35
|
+
};
|
|
36
|
+
const wrappers = this.explorerService.exploreResourceWrappers(rootModule);
|
|
37
|
+
for (const wrapper of wrappers) {
|
|
38
|
+
const instance = wrapper.instance;
|
|
39
|
+
const resourceDef = Reflect.getMetadata(core_2.RESOURCE_METADATA, instance.constructor);
|
|
40
|
+
/* istanbul ignore next */
|
|
41
|
+
if (!resourceDef)
|
|
42
|
+
continue;
|
|
43
|
+
serviceArgs.resources.push(instance);
|
|
44
|
+
/* Wrap resolver functions */
|
|
45
|
+
const prototype = Object.getPrototypeOf(instance);
|
|
46
|
+
const isRequestScoped = !wrapper.isDependencyTreeStatic();
|
|
47
|
+
if (schema_1.OpraSchema.isEntityResource(resourceDef)) {
|
|
48
|
+
for (const x of entityHandlers) {
|
|
49
|
+
const fn = instance[x];
|
|
50
|
+
if (typeof fn === 'function') {
|
|
51
|
+
const methodName = fn.name || x;
|
|
52
|
+
const callback = this._createContextCallback(instance, prototype, wrapper, rootModule, methodName, isRequestScoped, undefined, contextType);
|
|
53
|
+
const newFn = instance[x] = (ctx) => {
|
|
54
|
+
switch (ctx.type) {
|
|
55
|
+
case 'http':
|
|
56
|
+
const http = ctx.switchToHttp();
|
|
57
|
+
return callback(http.getRequest().getInstance(), http.getResponse().getInstance(), noOpFunction, ctx);
|
|
58
|
+
default:
|
|
59
|
+
throw new Error(`"${ctx.type}" context type is not implemented yet`);
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
if (methodName && newFn.name !== methodName)
|
|
63
|
+
Object.defineProperty(newFn, 'name', {
|
|
64
|
+
configurable: false,
|
|
65
|
+
writable: false,
|
|
66
|
+
enumerable: true,
|
|
67
|
+
value: methodName
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return await core_2.OpraService.create(serviceArgs);
|
|
74
|
+
}
|
|
75
|
+
_createContextCallback(instance, prototype, wrapper, moduleRef, methodName, isRequestScoped, transform = lodash_1.default.identity, contextType) {
|
|
76
|
+
const paramsFactory = this.paramsFactory;
|
|
77
|
+
if (isRequestScoped) {
|
|
78
|
+
return async (...args) => {
|
|
79
|
+
const opraContext = paramsFactory.exchangeKeyForValue(handler_paramtype_enum_js_1.HandlerParamType.CONTEXT, undefined, args);
|
|
80
|
+
const contextId = this.getContextId(opraContext);
|
|
81
|
+
this.registerContextProvider(opraContext, contextId);
|
|
82
|
+
const contextInstance = await this.injector.loadPerContext(instance, moduleRef, moduleRef.providers, contextId);
|
|
83
|
+
const callback = this.externalContextCreator.create(contextInstance, transform(contextInstance[methodName]), methodName, constants_js_1.PARAM_ARGS_METADATA, paramsFactory, contextId, wrapper.id, undefined, // contextOptions
|
|
84
|
+
opraContext.type);
|
|
85
|
+
return callback(...args);
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
return this.externalContextCreator.create(instance, prototype[methodName], methodName, constants_js_1.PARAM_ARGS_METADATA, paramsFactory, undefined, undefined, undefined, // contextOptions
|
|
89
|
+
contextType);
|
|
90
|
+
}
|
|
91
|
+
// noinspection JSMethodCanBeStatic
|
|
92
|
+
getContextId(gqlContext) {
|
|
93
|
+
const numberOfArguments = (0, function_utils_js_1.getNumberOfArguments)(core_1.ContextIdFactory.getByRequest);
|
|
94
|
+
if (numberOfArguments === 2) {
|
|
95
|
+
// @ts-ignore
|
|
96
|
+
const contextId = core_1.ContextIdFactory.getByRequest(gqlContext, ['req']);
|
|
97
|
+
if (!gqlContext[request_constants_1.REQUEST_CONTEXT_ID]) {
|
|
98
|
+
Object.defineProperty(gqlContext, request_constants_1.REQUEST_CONTEXT_ID, {
|
|
99
|
+
value: contextId,
|
|
100
|
+
enumerable: false,
|
|
101
|
+
configurable: false,
|
|
102
|
+
writable: false,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
return contextId;
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
// TODO remove in the next version (backward-compatibility layer)
|
|
109
|
+
// Left for backward compatibility purposes
|
|
110
|
+
let contextId;
|
|
111
|
+
if (gqlContext && gqlContext[request_constants_1.REQUEST_CONTEXT_ID]) {
|
|
112
|
+
contextId = gqlContext[request_constants_1.REQUEST_CONTEXT_ID];
|
|
113
|
+
}
|
|
114
|
+
else if (gqlContext &&
|
|
115
|
+
gqlContext.req &&
|
|
116
|
+
gqlContext.req[request_constants_1.REQUEST_CONTEXT_ID]) {
|
|
117
|
+
contextId = gqlContext.req[request_constants_1.REQUEST_CONTEXT_ID];
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
contextId = (0, core_1.createContextId)();
|
|
121
|
+
Object.defineProperty(gqlContext, request_constants_1.REQUEST_CONTEXT_ID, {
|
|
122
|
+
value: contextId,
|
|
123
|
+
enumerable: false,
|
|
124
|
+
configurable: false,
|
|
125
|
+
writable: false,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
return contextId;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
registerContextProvider(request, contextId) {
|
|
132
|
+
const coreModuleArray = [...this.modulesContainer.entries()]
|
|
133
|
+
.filter(
|
|
134
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
135
|
+
([key, { metatype }]) => metatype && metatype.name === internal_core_module_1.InternalCoreModule.name)
|
|
136
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
137
|
+
.map(([key, value]) => value);
|
|
138
|
+
const coreModuleRef = lodash_1.default.head(coreModuleArray);
|
|
139
|
+
if (!coreModuleRef) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
const wrapper = coreModuleRef.getProviderByKey(core_1.REQUEST);
|
|
143
|
+
wrapper.setInstanceByContextId(contextId, {
|
|
144
|
+
instance: request,
|
|
145
|
+
isResolved: true,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
tslib_1.__decorate([
|
|
150
|
+
(0, common_1.Inject)(),
|
|
151
|
+
tslib_1.__metadata("design:type", core_1.ModulesContainer)
|
|
152
|
+
], ServiceFactory.prototype, "modulesContainer", void 0);
|
|
153
|
+
tslib_1.__decorate([
|
|
154
|
+
(0, common_1.Inject)(),
|
|
155
|
+
tslib_1.__metadata("design:type", external_context_creator_1.ExternalContextCreator)
|
|
156
|
+
], ServiceFactory.prototype, "externalContextCreator", void 0);
|
|
157
|
+
tslib_1.__decorate([
|
|
158
|
+
(0, common_1.Inject)(),
|
|
159
|
+
tslib_1.__metadata("design:type", nest_explorer_js_1.NestExplorer)
|
|
160
|
+
], ServiceFactory.prototype, "explorerService", void 0);
|
|
161
|
+
ServiceFactory = tslib_1.__decorate([
|
|
162
|
+
(0, common_1.Injectable)()
|
|
163
|
+
], ServiceFactory);
|
|
164
|
+
exports.ServiceFactory = ServiceFactory;
|
package/cjs/index.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
require("reflect-metadata");
|
|
5
|
+
tslib_1.__exportStar(require("./opra.module.js"), exports);
|
|
6
|
+
tslib_1.__exportStar(require("./decorators/context.decorator.js"), exports);
|
|
7
|
+
tslib_1.__exportStar(require("./interfaces/opra-execution-context.js"), exports);
|
|
8
|
+
tslib_1.__exportStar(require("./interfaces/opra-module-options.interface.js"), exports);
|
|
9
|
+
// export * as Api from './decorators/api.ns.js';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OpraExecutionContext = void 0;
|
|
4
|
+
var OpraExecutionContext;
|
|
5
|
+
(function (OpraExecutionContext) {
|
|
6
|
+
function from(source) {
|
|
7
|
+
return source.getArgByIndex(4);
|
|
8
|
+
}
|
|
9
|
+
OpraExecutionContext.from = from;
|
|
10
|
+
})(OpraExecutionContext = exports.OpraExecutionContext || (exports.OpraExecutionContext = {}));
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var OpraCoreModule_1;
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.OpraCoreModule = void 0;
|
|
5
|
+
const tslib_1 = require("tslib");
|
|
6
|
+
const crypto = tslib_1.__importStar(require("crypto"));
|
|
7
|
+
const common_1 = require("@nestjs/common");
|
|
8
|
+
const core_1 = require("@nestjs/core");
|
|
9
|
+
const metadata_scanner_1 = require("@nestjs/core/metadata-scanner");
|
|
10
|
+
const i18n_1 = require("@opra/i18n");
|
|
11
|
+
const constants_js_1 = require("./constants.js");
|
|
12
|
+
const service_factory_js_1 = require("./factories/service.factory.js");
|
|
13
|
+
const nest_explorer_js_1 = require("./services/nest-explorer.js");
|
|
14
|
+
const service_loader_js_1 = require("./services/service-loader.js");
|
|
15
|
+
let OpraCoreModule = OpraCoreModule_1 = class OpraCoreModule {
|
|
16
|
+
httpAdapterHost;
|
|
17
|
+
modulesContainer;
|
|
18
|
+
options;
|
|
19
|
+
opraServiceLoader;
|
|
20
|
+
constructor(httpAdapterHost, modulesContainer, options, opraServiceLoader) {
|
|
21
|
+
this.httpAdapterHost = httpAdapterHost;
|
|
22
|
+
this.modulesContainer = modulesContainer;
|
|
23
|
+
this.options = options;
|
|
24
|
+
this.opraServiceLoader = opraServiceLoader;
|
|
25
|
+
}
|
|
26
|
+
static forRoot(options) {
|
|
27
|
+
return {
|
|
28
|
+
module: OpraCoreModule_1,
|
|
29
|
+
imports: [...(options.imports || [])],
|
|
30
|
+
providers: [
|
|
31
|
+
...(options.providers || []),
|
|
32
|
+
{
|
|
33
|
+
provide: constants_js_1.OPRA_MODULE_OPTIONS,
|
|
34
|
+
useValue: options,
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
provide: constants_js_1.OPRA_INITIALIZER,
|
|
38
|
+
useClass: service_loader_js_1.OpraServiceLoader
|
|
39
|
+
},
|
|
40
|
+
this.createI18nProvider()
|
|
41
|
+
],
|
|
42
|
+
exports: [...(options.exports || [])]
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
static forRootAsync(asyncOptions) {
|
|
46
|
+
return {
|
|
47
|
+
module: OpraCoreModule_1,
|
|
48
|
+
imports: [...(asyncOptions.imports || [])],
|
|
49
|
+
providers: [
|
|
50
|
+
...(asyncOptions.providers || []),
|
|
51
|
+
{
|
|
52
|
+
provide: constants_js_1.OPRA_MODULE_ID,
|
|
53
|
+
useValue: crypto.randomUUID()
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
provide: constants_js_1.OPRA_INITIALIZER,
|
|
57
|
+
useClass: service_loader_js_1.OpraServiceLoader
|
|
58
|
+
},
|
|
59
|
+
...this.createAsyncProviders(asyncOptions),
|
|
60
|
+
this.createI18nProvider(),
|
|
61
|
+
]
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
static createI18nProvider() {
|
|
65
|
+
return {
|
|
66
|
+
provide: i18n_1.I18n,
|
|
67
|
+
inject: [constants_js_1.OPRA_MODULE_OPTIONS],
|
|
68
|
+
useFactory: async (options) => {
|
|
69
|
+
const opts = options.i18n;
|
|
70
|
+
const initOptions = {
|
|
71
|
+
lng: opts?.lng,
|
|
72
|
+
fallbackLng: opts?.fallbackLng,
|
|
73
|
+
defaultNS: opts?.defaultNS,
|
|
74
|
+
resources: opts?.resources,
|
|
75
|
+
resourceDirs: opts?.resourceDirs
|
|
76
|
+
};
|
|
77
|
+
const instance = i18n_1.I18n.createInstance();
|
|
78
|
+
await instance.init(initOptions);
|
|
79
|
+
return instance;
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
static createAsyncProviders(asyncOptions) {
|
|
84
|
+
if (asyncOptions.useExisting || asyncOptions.useFactory)
|
|
85
|
+
return [this.createAsyncOptionsProvider(asyncOptions)];
|
|
86
|
+
if (asyncOptions.useClass)
|
|
87
|
+
return [
|
|
88
|
+
this.createAsyncOptionsProvider(asyncOptions),
|
|
89
|
+
{
|
|
90
|
+
provide: asyncOptions.useClass,
|
|
91
|
+
useClass: asyncOptions.useClass
|
|
92
|
+
}
|
|
93
|
+
];
|
|
94
|
+
throw new Error('Invalid configuration. Must provide useFactory, useClass or useExisting');
|
|
95
|
+
}
|
|
96
|
+
static createAsyncOptionsProvider(asyncOptions) {
|
|
97
|
+
if (asyncOptions.useFactory) {
|
|
98
|
+
return {
|
|
99
|
+
provide: constants_js_1.OPRA_MODULE_OPTIONS,
|
|
100
|
+
useFactory: asyncOptions.useFactory,
|
|
101
|
+
inject: asyncOptions.inject || []
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
const useClass = asyncOptions.useClass || asyncOptions.useExisting;
|
|
105
|
+
if (useClass) {
|
|
106
|
+
return {
|
|
107
|
+
provide: constants_js_1.OPRA_MODULE_OPTIONS,
|
|
108
|
+
useFactory: (optionsFactory) => optionsFactory.createOptions(),
|
|
109
|
+
inject: [useClass]
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
throw new Error('Invalid configuration. Must provide useFactory, useClass or useExisting');
|
|
113
|
+
}
|
|
114
|
+
async onModuleInit() {
|
|
115
|
+
const httpAdapter = this.httpAdapterHost?.httpAdapter;
|
|
116
|
+
if (!httpAdapter)
|
|
117
|
+
return;
|
|
118
|
+
const opraModule = (() => {
|
|
119
|
+
for (const m of this.modulesContainer.values()) {
|
|
120
|
+
for (const imp of m.imports.values()) {
|
|
121
|
+
for (const prv of imp.providers.values())
|
|
122
|
+
if (prv.instance === this) {
|
|
123
|
+
return imp;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
})();
|
|
128
|
+
if (opraModule) {
|
|
129
|
+
await this.opraServiceLoader.initialize(opraModule);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
async onModuleDestroy() {
|
|
133
|
+
await this.opraServiceLoader.stop();
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
OpraCoreModule = OpraCoreModule_1 = tslib_1.__decorate([
|
|
137
|
+
(0, common_1.Module)({
|
|
138
|
+
providers: [
|
|
139
|
+
service_factory_js_1.ServiceFactory,
|
|
140
|
+
metadata_scanner_1.MetadataScanner,
|
|
141
|
+
nest_explorer_js_1.NestExplorer
|
|
142
|
+
]
|
|
143
|
+
}),
|
|
144
|
+
tslib_1.__param(2, (0, common_1.Inject)(constants_js_1.OPRA_MODULE_OPTIONS)),
|
|
145
|
+
tslib_1.__param(3, (0, common_1.Inject)(constants_js_1.OPRA_INITIALIZER)),
|
|
146
|
+
tslib_1.__metadata("design:paramtypes", [core_1.HttpAdapterHost,
|
|
147
|
+
core_1.ModulesContainer, Object, service_loader_js_1.OpraServiceLoader])
|
|
148
|
+
], OpraCoreModule);
|
|
149
|
+
exports.OpraCoreModule = OpraCoreModule;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var OpraModule_1;
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.OpraModule = void 0;
|
|
5
|
+
const tslib_1 = require("tslib");
|
|
6
|
+
const common_1 = require("@nestjs/common");
|
|
7
|
+
const opra_core_module_js_1 = require("./opra-core.module.js");
|
|
8
|
+
let OpraModule = OpraModule_1 = class OpraModule {
|
|
9
|
+
static forRoot(options) {
|
|
10
|
+
return {
|
|
11
|
+
module: OpraModule_1,
|
|
12
|
+
imports: [opra_core_module_js_1.OpraCoreModule.forRoot(options)]
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
static forRootAsync(asyncOptions) {
|
|
16
|
+
return {
|
|
17
|
+
module: OpraModule_1,
|
|
18
|
+
imports: [opra_core_module_js_1.OpraCoreModule.forRootAsync(asyncOptions)]
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
OpraModule = OpraModule_1 = tslib_1.__decorate([
|
|
23
|
+
(0, common_1.Module)({})
|
|
24
|
+
], OpraModule);
|
|
25
|
+
exports.OpraModule = OpraModule;
|
package/cjs/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NestExplorer = void 0;
|
|
4
|
+
const core_1 = require("@opra/core");
|
|
5
|
+
class NestExplorer {
|
|
6
|
+
exploreProviders(rootModule, predicate) {
|
|
7
|
+
const modules = new Set();
|
|
8
|
+
const wrappers = new Set();
|
|
9
|
+
const scanModules = (m) => {
|
|
10
|
+
if (modules.has(m))
|
|
11
|
+
return;
|
|
12
|
+
modules.add(m);
|
|
13
|
+
for (const mm of m.imports.values()) {
|
|
14
|
+
scanModules(mm);
|
|
15
|
+
}
|
|
16
|
+
for (const wrapper of m.providers.values()) {
|
|
17
|
+
if (!wrappers.has(wrapper) && predicate(wrapper))
|
|
18
|
+
wrappers.add(wrapper);
|
|
19
|
+
if (wrapper.host)
|
|
20
|
+
scanModules(wrapper.host);
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
scanModules(rootModule);
|
|
24
|
+
return Array.from(wrappers.values());
|
|
25
|
+
}
|
|
26
|
+
exploreResourceWrappers(rootModule) {
|
|
27
|
+
return this.exploreProviders(rootModule, (wrapper) => {
|
|
28
|
+
return !!(wrapper.instance
|
|
29
|
+
&& typeof wrapper.instance === 'object'
|
|
30
|
+
&& wrapper.instance.constructor
|
|
31
|
+
&& Reflect.hasMetadata(core_1.RESOURCE_METADATA, wrapper.instance.constructor));
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
exports.NestExplorer = NestExplorer;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var _a;
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.OpraServiceLoader = void 0;
|
|
5
|
+
const tslib_1 = require("tslib");
|
|
6
|
+
const common_1 = require("@nestjs/common");
|
|
7
|
+
const core_1 = require("@nestjs/core");
|
|
8
|
+
const core_2 = require("@opra/core");
|
|
9
|
+
const i18n_1 = require("@opra/i18n");
|
|
10
|
+
const url_1 = require("@opra/url");
|
|
11
|
+
const constants_js_1 = require("../constants.js");
|
|
12
|
+
const service_factory_js_1 = require("../factories/service.factory.js");
|
|
13
|
+
class OpraServiceLoader {
|
|
14
|
+
logger = new common_1.Logger(OpraServiceLoader.name, { timestamp: true });
|
|
15
|
+
adapter;
|
|
16
|
+
httpAdapterHost;
|
|
17
|
+
applicationConfig;
|
|
18
|
+
opraFactory;
|
|
19
|
+
opraModuleOptions;
|
|
20
|
+
i18n;
|
|
21
|
+
async initialize(rootModule) {
|
|
22
|
+
const httpAdapter = this.httpAdapterHost?.httpAdapter;
|
|
23
|
+
const globalPrefix = this.applicationConfig.getGlobalPrefix();
|
|
24
|
+
const platformName = httpAdapter.getType();
|
|
25
|
+
const moduleOptions = this.opraModuleOptions;
|
|
26
|
+
const prefix = '/' + (0, url_1.normalizePath)((0, url_1.joinPath)((moduleOptions.useGlobalPrefix !== false ? globalPrefix : ''), moduleOptions.prefix || ''), true);
|
|
27
|
+
const name = moduleOptions.info?.title || 'untitled service';
|
|
28
|
+
const options = {
|
|
29
|
+
...moduleOptions,
|
|
30
|
+
prefix
|
|
31
|
+
};
|
|
32
|
+
try {
|
|
33
|
+
const serviceHost = await this.opraFactory.generateService(rootModule, options, 'http');
|
|
34
|
+
if (!Object.keys(serviceHost.resources).length) {
|
|
35
|
+
this.logger.warn(`No resources found (${name})`);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
// serviceConfiguration.i18n = this.i18n;
|
|
39
|
+
if (platformName === 'express') {
|
|
40
|
+
this.adapter = await this.registerExpress(serviceHost, options);
|
|
41
|
+
// else if (platformName === 'fastify')
|
|
42
|
+
// await this.registerFastify();
|
|
43
|
+
}
|
|
44
|
+
else { // noinspection ExceptionCaughtLocallyJS
|
|
45
|
+
throw new Error(`No support for current HttpAdapter: ${platformName}`);
|
|
46
|
+
}
|
|
47
|
+
this.logger.log(`Mapped {${prefix}} to "${name}" service`);
|
|
48
|
+
}
|
|
49
|
+
catch (e) {
|
|
50
|
+
this.logger.error(e);
|
|
51
|
+
throw e;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
async stop() {
|
|
55
|
+
//
|
|
56
|
+
}
|
|
57
|
+
async registerExpress(service, moduleOptions) {
|
|
58
|
+
const httpAdapter = this.httpAdapterHost.httpAdapter;
|
|
59
|
+
if (!httpAdapter)
|
|
60
|
+
return;
|
|
61
|
+
const app = httpAdapter.getInstance();
|
|
62
|
+
return core_2.OpraExpressAdapter.init(app, service, {
|
|
63
|
+
i18n: this.i18n,
|
|
64
|
+
prefix: moduleOptions.prefix
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
tslib_1.__decorate([
|
|
69
|
+
(0, common_1.Inject)(),
|
|
70
|
+
tslib_1.__metadata("design:type", core_1.HttpAdapterHost)
|
|
71
|
+
], OpraServiceLoader.prototype, "httpAdapterHost", void 0);
|
|
72
|
+
tslib_1.__decorate([
|
|
73
|
+
(0, common_1.Inject)(),
|
|
74
|
+
tslib_1.__metadata("design:type", core_1.ApplicationConfig)
|
|
75
|
+
], OpraServiceLoader.prototype, "applicationConfig", void 0);
|
|
76
|
+
tslib_1.__decorate([
|
|
77
|
+
(0, common_1.Inject)(),
|
|
78
|
+
tslib_1.__metadata("design:type", service_factory_js_1.ServiceFactory)
|
|
79
|
+
], OpraServiceLoader.prototype, "opraFactory", void 0);
|
|
80
|
+
tslib_1.__decorate([
|
|
81
|
+
(0, common_1.Inject)(constants_js_1.OPRA_MODULE_OPTIONS),
|
|
82
|
+
tslib_1.__metadata("design:type", Object)
|
|
83
|
+
], OpraServiceLoader.prototype, "opraModuleOptions", void 0);
|
|
84
|
+
tslib_1.__decorate([
|
|
85
|
+
(0, common_1.Inject)(),
|
|
86
|
+
tslib_1.__metadata("design:type", typeof (_a = typeof i18n_1.I18n !== "undefined" && i18n_1.I18n) === "function" ? _a : Object)
|
|
87
|
+
], OpraServiceLoader.prototype, "i18n", void 0);
|
|
88
|
+
exports.OpraServiceLoader = OpraServiceLoader;
|
package/cjs/types.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getClassName = exports.getClassOrUndefined = exports.isConstructor = void 0;
|
|
4
|
+
const shared_utils_1 = require("@nestjs/common/utils/shared.utils");
|
|
5
|
+
function isConstructor(obj) {
|
|
6
|
+
return typeof obj === 'function' &&
|
|
7
|
+
!!(obj.prototype && obj.prototype.constructor);
|
|
8
|
+
}
|
|
9
|
+
exports.isConstructor = isConstructor;
|
|
10
|
+
function getClassOrUndefined(typeOrFunc) {
|
|
11
|
+
return isConstructor(typeOrFunc)
|
|
12
|
+
? typeOrFunc
|
|
13
|
+
: (0, shared_utils_1.isFunction)(typeOrFunc)
|
|
14
|
+
? typeOrFunc()
|
|
15
|
+
: undefined;
|
|
16
|
+
}
|
|
17
|
+
exports.getClassOrUndefined = getClassOrUndefined;
|
|
18
|
+
function getClassName(nameOrType) {
|
|
19
|
+
if ((0, shared_utils_1.isString)(nameOrType)) {
|
|
20
|
+
return nameOrType;
|
|
21
|
+
}
|
|
22
|
+
const classOrUndefined = getClassOrUndefined(nameOrType);
|
|
23
|
+
return classOrUndefined && classOrUndefined.name;
|
|
24
|
+
}
|
|
25
|
+
exports.getClassName = getClassName;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getNumberOfArguments = void 0;
|
|
4
|
+
const fast_tokenizer_1 = require("fast-tokenizer");
|
|
5
|
+
const anythingEnclosedInParenthesesRegex = /\((.+)\)/;
|
|
6
|
+
function getNumberOfArguments(fn) {
|
|
7
|
+
const functionAsString = fn.toString();
|
|
8
|
+
const parametersEnclosedInParentheses = functionAsString.match(anythingEnclosedInParenthesesRegex);
|
|
9
|
+
if (parametersEnclosedInParentheses) {
|
|
10
|
+
const matchString = parametersEnclosedInParentheses[1];
|
|
11
|
+
const argumentsArray = (0, fast_tokenizer_1.splitString)(matchString, {
|
|
12
|
+
brackets: {
|
|
13
|
+
'(': ')',
|
|
14
|
+
'{': '}',
|
|
15
|
+
'[': ']',
|
|
16
|
+
'/*': '*/'
|
|
17
|
+
}, delimiters: ','
|
|
18
|
+
});
|
|
19
|
+
return argumentsArray.length;
|
|
20
|
+
}
|
|
21
|
+
return 0;
|
|
22
|
+
}
|
|
23
|
+
exports.getNumberOfArguments = getNumberOfArguments;
|