@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
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createOpraParamDecorator = void 0;
|
|
4
|
+
require("reflect-metadata");
|
|
5
|
+
const constants_js_1 = require("../constants.js");
|
|
6
|
+
function assignMetadata(args, paramType, index, data, ...pipes) {
|
|
7
|
+
return {
|
|
8
|
+
...args,
|
|
9
|
+
[`${paramType}:${index}`]: {
|
|
10
|
+
index,
|
|
11
|
+
data,
|
|
12
|
+
pipes,
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function createOpraParamDecorator(paramType) {
|
|
17
|
+
return (target, key, index) => {
|
|
18
|
+
const args = Reflect.getMetadata(constants_js_1.PARAM_ARGS_METADATA, target.constructor, key) || {};
|
|
19
|
+
Reflect.defineMetadata(constants_js_1.PARAM_ARGS_METADATA, assignMetadata(args, paramType, index), target.constructor, key);
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
exports.createOpraParamDecorator = createOpraParamDecorator;
|
package/esm/constants.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Handler method parameter decorator. Populates the decorated
|
|
3
|
+
* parameter with the value of `ExecutionContext`.
|
|
4
|
+
*/
|
|
5
|
+
export declare const Context: ParameterDecorator;
|
|
6
|
+
/**
|
|
7
|
+
* Handler method parameter decorator. Populates the decorated
|
|
8
|
+
* parameter with the value of `ExecutionRequest`.
|
|
9
|
+
*/
|
|
10
|
+
export declare const Request: ParameterDecorator;
|
|
11
|
+
/**
|
|
12
|
+
* Handler method parameter decorator. Populates the decorated
|
|
13
|
+
* parameter with the value of `ExecutionResponse`.
|
|
14
|
+
*/
|
|
15
|
+
export declare const Response: ParameterDecorator;
|
|
16
|
+
/**
|
|
17
|
+
* Handler method parameter decorator. Populates the decorated
|
|
18
|
+
* parameter with the value of `OpraService`.
|
|
19
|
+
*/
|
|
20
|
+
export declare const Service: ParameterDecorator;
|
|
21
|
+
/**
|
|
22
|
+
* Handler method parameter decorator. Populates the decorated
|
|
23
|
+
* parameter with the value of `OpraService`.
|
|
24
|
+
*/
|
|
25
|
+
export declare const Query: ParameterDecorator;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { HandlerParamType } from '../enums/handler-paramtype.enum.js';
|
|
2
|
+
import { createOpraParamDecorator } from '../utils/param.utils.js';
|
|
3
|
+
/**
|
|
4
|
+
* Handler method parameter decorator. Populates the decorated
|
|
5
|
+
* parameter with the value of `ExecutionContext`.
|
|
6
|
+
*/
|
|
7
|
+
export const Context = createOpraParamDecorator(HandlerParamType.CONTEXT);
|
|
8
|
+
/**
|
|
9
|
+
* Handler method parameter decorator. Populates the decorated
|
|
10
|
+
* parameter with the value of `ExecutionRequest`.
|
|
11
|
+
*/
|
|
12
|
+
export const Request = createOpraParamDecorator(HandlerParamType.REQUEST);
|
|
13
|
+
/**
|
|
14
|
+
* Handler method parameter decorator. Populates the decorated
|
|
15
|
+
* parameter with the value of `ExecutionResponse`.
|
|
16
|
+
*/
|
|
17
|
+
export const Response = createOpraParamDecorator(HandlerParamType.RESPONSE);
|
|
18
|
+
/**
|
|
19
|
+
* Handler method parameter decorator. Populates the decorated
|
|
20
|
+
* parameter with the value of `OpraService`.
|
|
21
|
+
*/
|
|
22
|
+
export const Service = createOpraParamDecorator(HandlerParamType.SERVICE);
|
|
23
|
+
/**
|
|
24
|
+
* Handler method parameter decorator. Populates the decorated
|
|
25
|
+
* parameter with the value of `OpraService`.
|
|
26
|
+
*/
|
|
27
|
+
export const Query = createOpraParamDecorator(HandlerParamType.QUERY);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export var HandlerParamType;
|
|
2
|
+
(function (HandlerParamType) {
|
|
3
|
+
HandlerParamType[HandlerParamType["CONTEXT"] = 0] = "CONTEXT";
|
|
4
|
+
HandlerParamType[HandlerParamType["SERVICE"] = 1] = "SERVICE";
|
|
5
|
+
HandlerParamType[HandlerParamType["REQUEST"] = 2] = "REQUEST";
|
|
6
|
+
HandlerParamType[HandlerParamType["QUERY"] = 3] = "QUERY";
|
|
7
|
+
HandlerParamType[HandlerParamType["RESPONSE"] = 4] = "RESPONSE";
|
|
8
|
+
HandlerParamType[HandlerParamType["USER_CONTEXT"] = 5] = "USER_CONTEXT";
|
|
9
|
+
})(HandlerParamType || (HandlerParamType = {}));
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { HandlerParamType } from '../enums/handler-paramtype.enum.js';
|
|
2
|
+
export class OpraParamsFactory {
|
|
3
|
+
exchangeKeyForValue(type, data, args) {
|
|
4
|
+
if (!args) {
|
|
5
|
+
return null;
|
|
6
|
+
}
|
|
7
|
+
args = Array.isArray(args) ? args : [];
|
|
8
|
+
switch (type) {
|
|
9
|
+
case HandlerParamType.CONTEXT:
|
|
10
|
+
return args[3];
|
|
11
|
+
case HandlerParamType.SERVICE:
|
|
12
|
+
return args[3].service;
|
|
13
|
+
case HandlerParamType.REQUEST:
|
|
14
|
+
return args[3].request;
|
|
15
|
+
case HandlerParamType.QUERY:
|
|
16
|
+
return args[3].request.query;
|
|
17
|
+
case HandlerParamType.RESPONSE:
|
|
18
|
+
return args[3].response;
|
|
19
|
+
case HandlerParamType.USER_CONTEXT:
|
|
20
|
+
return args[3].userContext;
|
|
21
|
+
default:
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ContextType } from '@nestjs/common';
|
|
2
|
+
import { Module } from '@nestjs/core/injector/module.js';
|
|
3
|
+
import { OpraService } from '@opra/core';
|
|
4
|
+
import { OpraModuleOptions } from '../interfaces/opra-module-options.interface.js';
|
|
5
|
+
export declare class ServiceFactory {
|
|
6
|
+
private readonly paramsFactory;
|
|
7
|
+
private readonly injector;
|
|
8
|
+
private readonly modulesContainer;
|
|
9
|
+
private readonly externalContextCreator;
|
|
10
|
+
private readonly explorerService;
|
|
11
|
+
generateService(rootModule: Module, moduleOptions: OpraModuleOptions, contextType: ContextType): Promise<OpraService>;
|
|
12
|
+
private _createContextCallback;
|
|
13
|
+
private getContextId;
|
|
14
|
+
private registerContextProvider;
|
|
15
|
+
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { __decorate, __metadata } from "tslib";
|
|
2
|
+
import _ from 'lodash';
|
|
3
|
+
import { Inject, Injectable } from '@nestjs/common';
|
|
4
|
+
import { ContextIdFactory, createContextId, ModulesContainer, REQUEST } from '@nestjs/core';
|
|
5
|
+
import { ExternalContextCreator } from '@nestjs/core/helpers/external-context-creator';
|
|
6
|
+
import { Injector } from '@nestjs/core/injector/injector';
|
|
7
|
+
import { InternalCoreModule } from '@nestjs/core/injector/internal-core-module';
|
|
8
|
+
import { REQUEST_CONTEXT_ID } from '@nestjs/core/router/request/request-constants';
|
|
9
|
+
import { OpraService, RESOURCE_METADATA } from '@opra/core';
|
|
10
|
+
import { OpraSchema } from '@opra/schema';
|
|
11
|
+
import { PARAM_ARGS_METADATA } from '../constants.js';
|
|
12
|
+
import { HandlerParamType } from '../enums/handler-paramtype.enum.js';
|
|
13
|
+
import { NestExplorer } from '../services/nest-explorer.js';
|
|
14
|
+
import { getNumberOfArguments } from '../utils/function.utils.js';
|
|
15
|
+
import { OpraParamsFactory } from './params.factory.js';
|
|
16
|
+
const entityHandlers = ['search', 'create', 'read', 'update', 'updateMany', 'delete', 'deleteMany'];
|
|
17
|
+
const noOpFunction = () => void 0;
|
|
18
|
+
let ServiceFactory = class ServiceFactory {
|
|
19
|
+
paramsFactory = new OpraParamsFactory();
|
|
20
|
+
injector = new Injector();
|
|
21
|
+
modulesContainer;
|
|
22
|
+
externalContextCreator;
|
|
23
|
+
explorerService;
|
|
24
|
+
async generateService(rootModule, moduleOptions, contextType) {
|
|
25
|
+
const info = { title: '', version: '', ...moduleOptions.info };
|
|
26
|
+
info.title = info.title || 'Untitled service';
|
|
27
|
+
info.version = info.version || '1';
|
|
28
|
+
const serviceArgs = {
|
|
29
|
+
info,
|
|
30
|
+
types: [],
|
|
31
|
+
resources: [],
|
|
32
|
+
};
|
|
33
|
+
const wrappers = this.explorerService.exploreResourceWrappers(rootModule);
|
|
34
|
+
for (const wrapper of wrappers) {
|
|
35
|
+
const instance = wrapper.instance;
|
|
36
|
+
const resourceDef = Reflect.getMetadata(RESOURCE_METADATA, instance.constructor);
|
|
37
|
+
/* istanbul ignore next */
|
|
38
|
+
if (!resourceDef)
|
|
39
|
+
continue;
|
|
40
|
+
serviceArgs.resources.push(instance);
|
|
41
|
+
/* Wrap resolver functions */
|
|
42
|
+
const prototype = Object.getPrototypeOf(instance);
|
|
43
|
+
const isRequestScoped = !wrapper.isDependencyTreeStatic();
|
|
44
|
+
if (OpraSchema.isEntityResource(resourceDef)) {
|
|
45
|
+
for (const x of entityHandlers) {
|
|
46
|
+
const fn = instance[x];
|
|
47
|
+
if (typeof fn === 'function') {
|
|
48
|
+
const methodName = fn.name || x;
|
|
49
|
+
const callback = this._createContextCallback(instance, prototype, wrapper, rootModule, methodName, isRequestScoped, undefined, contextType);
|
|
50
|
+
const newFn = instance[x] = (ctx) => {
|
|
51
|
+
switch (ctx.type) {
|
|
52
|
+
case 'http':
|
|
53
|
+
const http = ctx.switchToHttp();
|
|
54
|
+
return callback(http.getRequest().getInstance(), http.getResponse().getInstance(), noOpFunction, ctx);
|
|
55
|
+
default:
|
|
56
|
+
throw new Error(`"${ctx.type}" context type is not implemented yet`);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
if (methodName && newFn.name !== methodName)
|
|
60
|
+
Object.defineProperty(newFn, 'name', {
|
|
61
|
+
configurable: false,
|
|
62
|
+
writable: false,
|
|
63
|
+
enumerable: true,
|
|
64
|
+
value: methodName
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return await OpraService.create(serviceArgs);
|
|
71
|
+
}
|
|
72
|
+
_createContextCallback(instance, prototype, wrapper, moduleRef, methodName, isRequestScoped, transform = _.identity, contextType) {
|
|
73
|
+
const paramsFactory = this.paramsFactory;
|
|
74
|
+
if (isRequestScoped) {
|
|
75
|
+
return async (...args) => {
|
|
76
|
+
const opraContext = paramsFactory.exchangeKeyForValue(HandlerParamType.CONTEXT, undefined, args);
|
|
77
|
+
const contextId = this.getContextId(opraContext);
|
|
78
|
+
this.registerContextProvider(opraContext, contextId);
|
|
79
|
+
const contextInstance = await this.injector.loadPerContext(instance, moduleRef, moduleRef.providers, contextId);
|
|
80
|
+
const callback = this.externalContextCreator.create(contextInstance, transform(contextInstance[methodName]), methodName, PARAM_ARGS_METADATA, paramsFactory, contextId, wrapper.id, undefined, // contextOptions
|
|
81
|
+
opraContext.type);
|
|
82
|
+
return callback(...args);
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
return this.externalContextCreator.create(instance, prototype[methodName], methodName, PARAM_ARGS_METADATA, paramsFactory, undefined, undefined, undefined, // contextOptions
|
|
86
|
+
contextType);
|
|
87
|
+
}
|
|
88
|
+
// noinspection JSMethodCanBeStatic
|
|
89
|
+
getContextId(gqlContext) {
|
|
90
|
+
const numberOfArguments = getNumberOfArguments(ContextIdFactory.getByRequest);
|
|
91
|
+
if (numberOfArguments === 2) {
|
|
92
|
+
// @ts-ignore
|
|
93
|
+
const contextId = ContextIdFactory.getByRequest(gqlContext, ['req']);
|
|
94
|
+
if (!gqlContext[REQUEST_CONTEXT_ID]) {
|
|
95
|
+
Object.defineProperty(gqlContext, REQUEST_CONTEXT_ID, {
|
|
96
|
+
value: contextId,
|
|
97
|
+
enumerable: false,
|
|
98
|
+
configurable: false,
|
|
99
|
+
writable: false,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
return contextId;
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
// TODO remove in the next version (backward-compatibility layer)
|
|
106
|
+
// Left for backward compatibility purposes
|
|
107
|
+
let contextId;
|
|
108
|
+
if (gqlContext && gqlContext[REQUEST_CONTEXT_ID]) {
|
|
109
|
+
contextId = gqlContext[REQUEST_CONTEXT_ID];
|
|
110
|
+
}
|
|
111
|
+
else if (gqlContext &&
|
|
112
|
+
gqlContext.req &&
|
|
113
|
+
gqlContext.req[REQUEST_CONTEXT_ID]) {
|
|
114
|
+
contextId = gqlContext.req[REQUEST_CONTEXT_ID];
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
contextId = createContextId();
|
|
118
|
+
Object.defineProperty(gqlContext, REQUEST_CONTEXT_ID, {
|
|
119
|
+
value: contextId,
|
|
120
|
+
enumerable: false,
|
|
121
|
+
configurable: false,
|
|
122
|
+
writable: false,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
return contextId;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
registerContextProvider(request, contextId) {
|
|
129
|
+
const coreModuleArray = [...this.modulesContainer.entries()]
|
|
130
|
+
.filter(
|
|
131
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
132
|
+
([key, { metatype }]) => metatype && metatype.name === InternalCoreModule.name)
|
|
133
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
134
|
+
.map(([key, value]) => value);
|
|
135
|
+
const coreModuleRef = _.head(coreModuleArray);
|
|
136
|
+
if (!coreModuleRef) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
const wrapper = coreModuleRef.getProviderByKey(REQUEST);
|
|
140
|
+
wrapper.setInstanceByContextId(contextId, {
|
|
141
|
+
instance: request,
|
|
142
|
+
isResolved: true,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
__decorate([
|
|
147
|
+
Inject(),
|
|
148
|
+
__metadata("design:type", ModulesContainer)
|
|
149
|
+
], ServiceFactory.prototype, "modulesContainer", void 0);
|
|
150
|
+
__decorate([
|
|
151
|
+
Inject(),
|
|
152
|
+
__metadata("design:type", ExternalContextCreator)
|
|
153
|
+
], ServiceFactory.prototype, "externalContextCreator", void 0);
|
|
154
|
+
__decorate([
|
|
155
|
+
Inject(),
|
|
156
|
+
__metadata("design:type", NestExplorer)
|
|
157
|
+
], ServiceFactory.prototype, "explorerService", void 0);
|
|
158
|
+
ServiceFactory = __decorate([
|
|
159
|
+
Injectable()
|
|
160
|
+
], ServiceFactory);
|
|
161
|
+
export { ServiceFactory };
|
package/esm/index.d.ts
ADDED
package/esm/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
export * from './opra.module.js';
|
|
3
|
+
export * from './decorators/context.decorator.js';
|
|
4
|
+
export * from './interfaces/opra-execution-context.js';
|
|
5
|
+
export * from './interfaces/opra-module-options.interface.js';
|
|
6
|
+
// export * as Api from './decorators/api.ns.js';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { ExecutionContext } from '@nestjs/common';
|
|
2
|
+
import * as Opra from '@opra/core';
|
|
3
|
+
export declare type OpraExecutionContext = Opra.ExecutionContext;
|
|
4
|
+
export declare namespace OpraExecutionContext {
|
|
5
|
+
function from(source: ExecutionContext): OpraExecutionContext;
|
|
6
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { ModuleMetadata, Type } from '@nestjs/common';
|
|
2
|
+
import { FallbackLng, LanguageResource } from '@opra/i18n';
|
|
3
|
+
import { OpraSchema } from '@opra/schema';
|
|
4
|
+
export declare type OpraModuleOptions = {
|
|
5
|
+
/**
|
|
6
|
+
* @default true
|
|
7
|
+
*/
|
|
8
|
+
useGlobalPrefix?: boolean;
|
|
9
|
+
prefix?: string;
|
|
10
|
+
info?: OpraSchema.DocumentInfo;
|
|
11
|
+
i18n?: I18nInitOptions;
|
|
12
|
+
context?: object | ((request: any, platformName: string) => object | Promise<object>);
|
|
13
|
+
};
|
|
14
|
+
export interface I18nInitOptions {
|
|
15
|
+
/**
|
|
16
|
+
* Language to use
|
|
17
|
+
* @default undefined
|
|
18
|
+
*/
|
|
19
|
+
lng?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Language to use if translations in user language are not available.
|
|
22
|
+
* @default 'dev'
|
|
23
|
+
*/
|
|
24
|
+
fallbackLng?: false | FallbackLng;
|
|
25
|
+
/**
|
|
26
|
+
* Default namespace used if not passed to translation function
|
|
27
|
+
* @default 'translation'
|
|
28
|
+
*/
|
|
29
|
+
defaultNS?: string;
|
|
30
|
+
/**
|
|
31
|
+
* Resources to initialize with
|
|
32
|
+
* @default undefined
|
|
33
|
+
*/
|
|
34
|
+
resources?: LanguageResource;
|
|
35
|
+
/**
|
|
36
|
+
* Resource directories to initialize with (if not using loading or not appending using addResourceBundle)
|
|
37
|
+
* @default undefined
|
|
38
|
+
*/
|
|
39
|
+
resourceDirs?: string[];
|
|
40
|
+
}
|
|
41
|
+
export interface OpraModuleOptionsFactory {
|
|
42
|
+
createOptions(): Promise<OpraModuleOptions> | OpraModuleOptions;
|
|
43
|
+
}
|
|
44
|
+
export interface OpraModuleAsyncOptions extends Pick<ModuleMetadata, 'imports' | 'providers'> {
|
|
45
|
+
useExisting?: Type<OpraModuleOptionsFactory>;
|
|
46
|
+
useClass?: Type<OpraModuleOptionsFactory>;
|
|
47
|
+
useFactory?: (...args: any[]) => Promise<OpraModuleOptions> | OpraModuleOptions;
|
|
48
|
+
inject?: any[];
|
|
49
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { DynamicModule, OnModuleDestroy, OnModuleInit } from '@nestjs/common';
|
|
2
|
+
import { HttpAdapterHost, ModulesContainer } from '@nestjs/core';
|
|
3
|
+
import { OpraModuleAsyncOptions, OpraModuleOptions } from './interfaces/opra-module-options.interface.js';
|
|
4
|
+
import { OpraServiceLoader } from './services/service-loader.js';
|
|
5
|
+
export declare class OpraCoreModule implements OnModuleInit, OnModuleDestroy {
|
|
6
|
+
private readonly httpAdapterHost;
|
|
7
|
+
protected readonly modulesContainer: ModulesContainer;
|
|
8
|
+
private readonly options;
|
|
9
|
+
private readonly opraServiceLoader;
|
|
10
|
+
constructor(httpAdapterHost: HttpAdapterHost, modulesContainer: ModulesContainer, options: OpraModuleOptions, opraServiceLoader: OpraServiceLoader);
|
|
11
|
+
static forRoot(options: OpraModuleOptions & Pick<DynamicModule, 'imports' | 'providers' | 'exports'>): DynamicModule;
|
|
12
|
+
static forRootAsync(asyncOptions: OpraModuleAsyncOptions): DynamicModule;
|
|
13
|
+
private static createI18nProvider;
|
|
14
|
+
private static createAsyncProviders;
|
|
15
|
+
private static createAsyncOptionsProvider;
|
|
16
|
+
onModuleInit(): Promise<void>;
|
|
17
|
+
onModuleDestroy(): Promise<void>;
|
|
18
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
var OpraCoreModule_1;
|
|
2
|
+
import { __decorate, __metadata, __param } from "tslib";
|
|
3
|
+
import * as crypto from 'crypto';
|
|
4
|
+
import { Inject, Module } from '@nestjs/common';
|
|
5
|
+
import { HttpAdapterHost, ModulesContainer } from '@nestjs/core';
|
|
6
|
+
import { MetadataScanner } from '@nestjs/core/metadata-scanner';
|
|
7
|
+
import { I18n } from '@opra/i18n';
|
|
8
|
+
import { OPRA_INITIALIZER, OPRA_MODULE_ID, OPRA_MODULE_OPTIONS } from './constants.js';
|
|
9
|
+
import { ServiceFactory } from './factories/service.factory.js';
|
|
10
|
+
import { NestExplorer } from './services/nest-explorer.js';
|
|
11
|
+
import { OpraServiceLoader } from './services/service-loader.js';
|
|
12
|
+
let OpraCoreModule = OpraCoreModule_1 = class OpraCoreModule {
|
|
13
|
+
httpAdapterHost;
|
|
14
|
+
modulesContainer;
|
|
15
|
+
options;
|
|
16
|
+
opraServiceLoader;
|
|
17
|
+
constructor(httpAdapterHost, modulesContainer, options, opraServiceLoader) {
|
|
18
|
+
this.httpAdapterHost = httpAdapterHost;
|
|
19
|
+
this.modulesContainer = modulesContainer;
|
|
20
|
+
this.options = options;
|
|
21
|
+
this.opraServiceLoader = opraServiceLoader;
|
|
22
|
+
}
|
|
23
|
+
static forRoot(options) {
|
|
24
|
+
return {
|
|
25
|
+
module: OpraCoreModule_1,
|
|
26
|
+
imports: [...(options.imports || [])],
|
|
27
|
+
providers: [
|
|
28
|
+
...(options.providers || []),
|
|
29
|
+
{
|
|
30
|
+
provide: OPRA_MODULE_OPTIONS,
|
|
31
|
+
useValue: options,
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
provide: OPRA_INITIALIZER,
|
|
35
|
+
useClass: OpraServiceLoader
|
|
36
|
+
},
|
|
37
|
+
this.createI18nProvider()
|
|
38
|
+
],
|
|
39
|
+
exports: [...(options.exports || [])]
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
static forRootAsync(asyncOptions) {
|
|
43
|
+
return {
|
|
44
|
+
module: OpraCoreModule_1,
|
|
45
|
+
imports: [...(asyncOptions.imports || [])],
|
|
46
|
+
providers: [
|
|
47
|
+
...(asyncOptions.providers || []),
|
|
48
|
+
{
|
|
49
|
+
provide: OPRA_MODULE_ID,
|
|
50
|
+
useValue: crypto.randomUUID()
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
provide: OPRA_INITIALIZER,
|
|
54
|
+
useClass: OpraServiceLoader
|
|
55
|
+
},
|
|
56
|
+
...this.createAsyncProviders(asyncOptions),
|
|
57
|
+
this.createI18nProvider(),
|
|
58
|
+
]
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
static createI18nProvider() {
|
|
62
|
+
return {
|
|
63
|
+
provide: I18n,
|
|
64
|
+
inject: [OPRA_MODULE_OPTIONS],
|
|
65
|
+
useFactory: async (options) => {
|
|
66
|
+
const opts = options.i18n;
|
|
67
|
+
const initOptions = {
|
|
68
|
+
lng: opts?.lng,
|
|
69
|
+
fallbackLng: opts?.fallbackLng,
|
|
70
|
+
defaultNS: opts?.defaultNS,
|
|
71
|
+
resources: opts?.resources,
|
|
72
|
+
resourceDirs: opts?.resourceDirs
|
|
73
|
+
};
|
|
74
|
+
const instance = I18n.createInstance();
|
|
75
|
+
await instance.init(initOptions);
|
|
76
|
+
return instance;
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
static createAsyncProviders(asyncOptions) {
|
|
81
|
+
if (asyncOptions.useExisting || asyncOptions.useFactory)
|
|
82
|
+
return [this.createAsyncOptionsProvider(asyncOptions)];
|
|
83
|
+
if (asyncOptions.useClass)
|
|
84
|
+
return [
|
|
85
|
+
this.createAsyncOptionsProvider(asyncOptions),
|
|
86
|
+
{
|
|
87
|
+
provide: asyncOptions.useClass,
|
|
88
|
+
useClass: asyncOptions.useClass
|
|
89
|
+
}
|
|
90
|
+
];
|
|
91
|
+
throw new Error('Invalid configuration. Must provide useFactory, useClass or useExisting');
|
|
92
|
+
}
|
|
93
|
+
static createAsyncOptionsProvider(asyncOptions) {
|
|
94
|
+
if (asyncOptions.useFactory) {
|
|
95
|
+
return {
|
|
96
|
+
provide: OPRA_MODULE_OPTIONS,
|
|
97
|
+
useFactory: asyncOptions.useFactory,
|
|
98
|
+
inject: asyncOptions.inject || []
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
const useClass = asyncOptions.useClass || asyncOptions.useExisting;
|
|
102
|
+
if (useClass) {
|
|
103
|
+
return {
|
|
104
|
+
provide: OPRA_MODULE_OPTIONS,
|
|
105
|
+
useFactory: (optionsFactory) => optionsFactory.createOptions(),
|
|
106
|
+
inject: [useClass]
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
throw new Error('Invalid configuration. Must provide useFactory, useClass or useExisting');
|
|
110
|
+
}
|
|
111
|
+
async onModuleInit() {
|
|
112
|
+
const httpAdapter = this.httpAdapterHost?.httpAdapter;
|
|
113
|
+
if (!httpAdapter)
|
|
114
|
+
return;
|
|
115
|
+
const opraModule = (() => {
|
|
116
|
+
for (const m of this.modulesContainer.values()) {
|
|
117
|
+
for (const imp of m.imports.values()) {
|
|
118
|
+
for (const prv of imp.providers.values())
|
|
119
|
+
if (prv.instance === this) {
|
|
120
|
+
return imp;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
})();
|
|
125
|
+
if (opraModule) {
|
|
126
|
+
await this.opraServiceLoader.initialize(opraModule);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
async onModuleDestroy() {
|
|
130
|
+
await this.opraServiceLoader.stop();
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
OpraCoreModule = OpraCoreModule_1 = __decorate([
|
|
134
|
+
Module({
|
|
135
|
+
providers: [
|
|
136
|
+
ServiceFactory,
|
|
137
|
+
MetadataScanner,
|
|
138
|
+
NestExplorer
|
|
139
|
+
]
|
|
140
|
+
}),
|
|
141
|
+
__param(2, Inject(OPRA_MODULE_OPTIONS)),
|
|
142
|
+
__param(3, Inject(OPRA_INITIALIZER)),
|
|
143
|
+
__metadata("design:paramtypes", [HttpAdapterHost,
|
|
144
|
+
ModulesContainer, Object, OpraServiceLoader])
|
|
145
|
+
], OpraCoreModule);
|
|
146
|
+
export { OpraCoreModule };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { DynamicModule } from '@nestjs/common';
|
|
2
|
+
import { OpraModuleAsyncOptions, OpraModuleOptions } from './interfaces/opra-module-options.interface.js';
|
|
3
|
+
export declare class OpraModule {
|
|
4
|
+
static forRoot(options: OpraModuleOptions & Pick<DynamicModule, 'imports' | 'providers' | 'exports'>): DynamicModule;
|
|
5
|
+
static forRootAsync(asyncOptions: OpraModuleAsyncOptions): DynamicModule;
|
|
6
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
var OpraModule_1;
|
|
2
|
+
import { __decorate } from "tslib";
|
|
3
|
+
import { Module } from '@nestjs/common';
|
|
4
|
+
import { OpraCoreModule } from './opra-core.module.js';
|
|
5
|
+
let OpraModule = OpraModule_1 = class OpraModule {
|
|
6
|
+
static forRoot(options) {
|
|
7
|
+
return {
|
|
8
|
+
module: OpraModule_1,
|
|
9
|
+
imports: [OpraCoreModule.forRoot(options)]
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
static forRootAsync(asyncOptions) {
|
|
13
|
+
return {
|
|
14
|
+
module: OpraModule_1,
|
|
15
|
+
imports: [OpraCoreModule.forRootAsync(asyncOptions)]
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
OpraModule = OpraModule_1 = __decorate([
|
|
20
|
+
Module({})
|
|
21
|
+
], OpraModule);
|
|
22
|
+
export { OpraModule };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { InstanceWrapper } from '@nestjs/core/injector/instance-wrapper';
|
|
2
|
+
import { Module } from '@nestjs/core/injector/module';
|
|
3
|
+
export declare class NestExplorer {
|
|
4
|
+
exploreProviders(rootModule: Module, predicate: (wrapper: InstanceWrapper) => boolean): InstanceWrapper<any>[];
|
|
5
|
+
exploreResourceWrappers(rootModule: Module): InstanceWrapper[];
|
|
6
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { RESOURCE_METADATA } from '@opra/core';
|
|
2
|
+
export class NestExplorer {
|
|
3
|
+
exploreProviders(rootModule, predicate) {
|
|
4
|
+
const modules = new Set();
|
|
5
|
+
const wrappers = new Set();
|
|
6
|
+
const scanModules = (m) => {
|
|
7
|
+
if (modules.has(m))
|
|
8
|
+
return;
|
|
9
|
+
modules.add(m);
|
|
10
|
+
for (const mm of m.imports.values()) {
|
|
11
|
+
scanModules(mm);
|
|
12
|
+
}
|
|
13
|
+
for (const wrapper of m.providers.values()) {
|
|
14
|
+
if (!wrappers.has(wrapper) && predicate(wrapper))
|
|
15
|
+
wrappers.add(wrapper);
|
|
16
|
+
if (wrapper.host)
|
|
17
|
+
scanModules(wrapper.host);
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
scanModules(rootModule);
|
|
21
|
+
return Array.from(wrappers.values());
|
|
22
|
+
}
|
|
23
|
+
exploreResourceWrappers(rootModule) {
|
|
24
|
+
return this.exploreProviders(rootModule, (wrapper) => {
|
|
25
|
+
return !!(wrapper.instance
|
|
26
|
+
&& typeof wrapper.instance === 'object'
|
|
27
|
+
&& wrapper.instance.constructor
|
|
28
|
+
&& Reflect.hasMetadata(RESOURCE_METADATA, wrapper.instance.constructor));
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ApplicationConfig, HttpAdapterHost } from '@nestjs/core';
|
|
2
|
+
import { Module } from '@nestjs/core/injector/module.js';
|
|
3
|
+
import { OpraExpressAdapter, OpraService } from '@opra/core';
|
|
4
|
+
import { I18n } from '@opra/i18n';
|
|
5
|
+
import { ServiceFactory } from '../factories/service.factory.js';
|
|
6
|
+
import { OpraModuleOptions } from '../interfaces/opra-module-options.interface.js';
|
|
7
|
+
export declare class OpraServiceLoader {
|
|
8
|
+
private readonly logger;
|
|
9
|
+
private adapter;
|
|
10
|
+
protected readonly httpAdapterHost: HttpAdapterHost;
|
|
11
|
+
protected readonly applicationConfig: ApplicationConfig;
|
|
12
|
+
protected readonly opraFactory: ServiceFactory;
|
|
13
|
+
protected readonly opraModuleOptions: OpraModuleOptions;
|
|
14
|
+
protected readonly i18n: I18n;
|
|
15
|
+
initialize(rootModule: Module): Promise<void>;
|
|
16
|
+
stop(): Promise<void>;
|
|
17
|
+
protected registerExpress(service: OpraService, moduleOptions: OpraModuleOptions): Promise<OpraExpressAdapter | undefined>;
|
|
18
|
+
}
|