@opra/nestjs 0.33.13 → 1.0.0-alpha.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/cjs/augmentation/http-controller.augmentation.js +16 -0
- package/cjs/constants.js +2 -7
- package/cjs/decorators/public.decorator.js +7 -0
- package/cjs/index.js +4 -5
- package/cjs/interfaces/opra-module-options.interface.js +16 -1
- package/cjs/opra-http-core.module.js +60 -0
- package/cjs/opra-http.module.js +24 -0
- package/cjs/opra-nestjs-adapter.js +160 -0
- package/cjs/services/opra-exception-filter.js +14 -13
- package/cjs/services/opra-middleware.js +24 -0
- package/esm/augmentation/http-controller.augmentation.js +16 -0
- package/esm/constants.js +1 -6
- package/esm/decorators/public.decorator.js +3 -0
- package/esm/index.js +4 -5
- package/esm/interfaces/opra-module-options.interface.js +17 -1
- package/esm/opra-http-core.module.js +57 -0
- package/esm/opra-http.module.js +21 -0
- package/esm/opra-nestjs-adapter.js +156 -0
- package/esm/services/opra-exception-filter.js +13 -13
- package/esm/services/opra-middleware.js +21 -0
- package/package.json +16 -13
- package/types/augmentation/http-controller.augmentation.d.ts +0 -0
- package/types/constants.d.ts +1 -6
- package/types/decorators/public.decorator.d.ts +1 -0
- package/types/index.d.ts +4 -5
- package/types/interfaces/opra-module-options.interface.d.ts +0 -25
- package/types/opra-http-core.module.d.ts +10 -0
- package/types/opra-http.module.d.ts +20 -0
- package/types/opra-nestjs-adapter.d.ts +12 -0
- package/types/services/opra-exception-filter.d.ts +6 -2
- package/types/services/opra-middleware.d.ts +5 -0
- package/cjs/augmentation/common-decorator.augmentation.js +0 -40
- package/cjs/decorators/context.decorator.js +0 -10
- package/cjs/enums/handler-paramtype.enum.js +0 -9
- package/cjs/factories/opra-api.factory.js +0 -200
- package/cjs/factories/params.factory.js +0 -23
- package/cjs/opra-core.module.js +0 -140
- package/cjs/opra-module-ref.js +0 -16
- package/cjs/opra.module.js +0 -25
- package/cjs/services/nest-explorer.js +0 -38
- package/cjs/services/opra-api-loader.js +0 -85
- package/cjs/types.js +0 -2
- package/cjs/utils/class.utils.js +0 -25
- package/cjs/utils/function.utils.js +0 -37
- package/cjs/utils/param.utils.js +0 -24
- package/esm/augmentation/common-decorator.augmentation.js +0 -38
- package/esm/decorators/context.decorator.js +0 -7
- package/esm/enums/handler-paramtype.enum.js +0 -6
- package/esm/factories/opra-api.factory.js +0 -197
- package/esm/factories/params.factory.js +0 -19
- package/esm/opra-core.module.js +0 -137
- package/esm/opra-module-ref.js +0 -12
- package/esm/opra.module.js +0 -22
- package/esm/services/nest-explorer.js +0 -34
- package/esm/services/opra-api-loader.js +0 -81
- package/esm/types.js +0 -1
- package/esm/utils/class.utils.js +0 -19
- package/esm/utils/function.utils.js +0 -33
- package/esm/utils/param.utils.js +0 -20
- package/types/augmentation/common-decorator.augmentation.d.ts +0 -1
- package/types/decorators/context.decorator.d.ts +0 -5
- package/types/enums/handler-paramtype.enum.d.ts +0 -5
- package/types/factories/opra-api.factory.d.ts +0 -15
- package/types/factories/params.factory.d.ts +0 -4
- package/types/opra-core.module.d.ts +0 -17
- package/types/opra-module-ref.d.ts +0 -11
- package/types/opra.module.d.ts +0 -6
- package/types/services/nest-explorer.d.ts +0 -8
- package/types/services/opra-api-loader.d.ts +0 -19
- package/types/types.d.ts +0 -2
- package/types/utils/class.utils.d.ts +0 -4
- package/types/utils/function.utils.d.ts +0 -1
- package/types/utils/param.utils.d.ts +0 -8
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { __decorate, __metadata, __param } from "tslib";
|
|
2
|
+
import { Controller, Delete, Get, Head, Next, Options, Patch, Post, Put, Req, Res, Search, UseFilters, } from '@nestjs/common';
|
|
3
|
+
import { ApiDocument, HTTP_CONTROLLER_METADATA, HttpApi, isConstructor, NotFoundError, } from '@opra/common';
|
|
4
|
+
import { HttpAdapter } from '@opra/core';
|
|
5
|
+
import nodePath from 'path';
|
|
6
|
+
import { asMutable } from 'ts-gems';
|
|
7
|
+
import { Public } from './decorators/public.decorator';
|
|
8
|
+
import { OpraExceptionFilter } from './services/opra-exception-filter.js';
|
|
9
|
+
export const kHandler = Symbol.for('kHandler');
|
|
10
|
+
export class OpraNestAdapter extends HttpAdapter {
|
|
11
|
+
constructor(init, options) {
|
|
12
|
+
super((function () {
|
|
13
|
+
const document = new ApiDocument();
|
|
14
|
+
document.api = new HttpApi(document);
|
|
15
|
+
return document;
|
|
16
|
+
})(), options);
|
|
17
|
+
this.nestControllers = [];
|
|
18
|
+
this.options = options;
|
|
19
|
+
let basePath = options?.basePath || '/';
|
|
20
|
+
if (!basePath.startsWith('/'))
|
|
21
|
+
basePath = '/' + basePath;
|
|
22
|
+
this._addRootController(basePath);
|
|
23
|
+
if (init.controllers)
|
|
24
|
+
init.controllers.forEach(c => this._addToNestControllers(c, basePath));
|
|
25
|
+
}
|
|
26
|
+
async close() {
|
|
27
|
+
//
|
|
28
|
+
}
|
|
29
|
+
_addRootController(basePath) {
|
|
30
|
+
const _this = this;
|
|
31
|
+
let RootController = class RootController {
|
|
32
|
+
schema(_req, next) {
|
|
33
|
+
_this[kHandler].sendDocumentSchema(_req.opraContext).catch(next);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
__decorate([
|
|
37
|
+
Get('/\\$schema'),
|
|
38
|
+
__param(0, Req()),
|
|
39
|
+
__param(1, Next()),
|
|
40
|
+
__metadata("design:type", Function),
|
|
41
|
+
__metadata("design:paramtypes", [Object, Function]),
|
|
42
|
+
__metadata("design:returntype", void 0)
|
|
43
|
+
], RootController.prototype, "schema", null);
|
|
44
|
+
RootController = __decorate([
|
|
45
|
+
Controller({
|
|
46
|
+
path: basePath,
|
|
47
|
+
})
|
|
48
|
+
], RootController);
|
|
49
|
+
if (this.options?.schemaRouteIsPublic) {
|
|
50
|
+
Public()(RootController.prototype, 'schema', Object.getOwnPropertyDescriptor(RootController.prototype, 'schema'));
|
|
51
|
+
}
|
|
52
|
+
this.nestControllers.push(RootController);
|
|
53
|
+
}
|
|
54
|
+
_addToNestControllers(sourceClass, currentPath) {
|
|
55
|
+
const metadata = Reflect.getMetadata(HTTP_CONTROLLER_METADATA, sourceClass);
|
|
56
|
+
if (!metadata)
|
|
57
|
+
return;
|
|
58
|
+
const newClass = {
|
|
59
|
+
[sourceClass.name]: class extends sourceClass {
|
|
60
|
+
},
|
|
61
|
+
}[sourceClass.name];
|
|
62
|
+
const newPath = metadata.path ? nodePath.join(currentPath, metadata.path) : currentPath;
|
|
63
|
+
const adapter = this;
|
|
64
|
+
/** Inject exception filter */
|
|
65
|
+
UseFilters(new OpraExceptionFilter(adapter))(newClass);
|
|
66
|
+
Controller()(newClass);
|
|
67
|
+
this.nestControllers.push(newClass);
|
|
68
|
+
if (metadata.operations) {
|
|
69
|
+
for (const [k, v] of Object.entries(metadata.operations)) {
|
|
70
|
+
const operationHandler = sourceClass.prototype[k];
|
|
71
|
+
Object.defineProperty(newClass.prototype, k, {
|
|
72
|
+
writable: true,
|
|
73
|
+
/** NestJS handler method */
|
|
74
|
+
async value(_req) {
|
|
75
|
+
const api = adapter.document.api;
|
|
76
|
+
const controller = api.findController(sourceClass);
|
|
77
|
+
const operation = controller?.operations.get(k);
|
|
78
|
+
const context = asMutable(_req.opraContext);
|
|
79
|
+
if (!(context && operation && typeof operationHandler === 'function')) {
|
|
80
|
+
throw new NotFoundError({
|
|
81
|
+
message: `No endpoint found for [${_req.method}]${_req.baseUrl}`,
|
|
82
|
+
details: {
|
|
83
|
+
path: _req.baseUrl,
|
|
84
|
+
method: _req.method,
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
/** Configure the HttpContext */
|
|
89
|
+
context.adapter = adapter;
|
|
90
|
+
context.document = adapter.document;
|
|
91
|
+
context.operation = operation;
|
|
92
|
+
context.controller = operation.owner;
|
|
93
|
+
context.controllerInstance = this;
|
|
94
|
+
context.operationHandler = operationHandler;
|
|
95
|
+
/** Handle request */
|
|
96
|
+
await adapter[kHandler].handleRequest(context);
|
|
97
|
+
},
|
|
98
|
+
});
|
|
99
|
+
/** Copy metadata keys from source function to new one */
|
|
100
|
+
const metadataKeys = Reflect.getOwnMetadataKeys(operationHandler);
|
|
101
|
+
const newFn = newClass.prototype[k];
|
|
102
|
+
for (const key of metadataKeys) {
|
|
103
|
+
const m = Reflect.getMetadata(key, operationHandler);
|
|
104
|
+
Reflect.defineMetadata(key, m, newFn);
|
|
105
|
+
}
|
|
106
|
+
Req()(newClass.prototype, k, 0);
|
|
107
|
+
Res()(newClass.prototype, k, 1);
|
|
108
|
+
const descriptor = Object.getOwnPropertyDescriptor(newClass.prototype, k);
|
|
109
|
+
const operationPath = newPath + (v.path || '');
|
|
110
|
+
switch (v.method || 'GET') {
|
|
111
|
+
case 'DELETE':
|
|
112
|
+
/** Call @Delete decorator over new property */
|
|
113
|
+
Delete(operationPath)(newClass.prototype, k, descriptor);
|
|
114
|
+
break;
|
|
115
|
+
case 'GET':
|
|
116
|
+
/** Call @Get decorator over new property */
|
|
117
|
+
Get(operationPath)(newClass.prototype, k, descriptor);
|
|
118
|
+
break;
|
|
119
|
+
case 'HEAD':
|
|
120
|
+
/** Call @Head decorator over new property */
|
|
121
|
+
Head(operationPath)(newClass.prototype, k, descriptor);
|
|
122
|
+
break;
|
|
123
|
+
case 'OPTIONS':
|
|
124
|
+
/** Call @Options decorator over new property */
|
|
125
|
+
Options(operationPath)(newClass.prototype, k, descriptor);
|
|
126
|
+
break;
|
|
127
|
+
case 'PATCH':
|
|
128
|
+
/** Call @Patch decorator over new property */
|
|
129
|
+
Patch(operationPath)(newClass.prototype, k, descriptor);
|
|
130
|
+
break;
|
|
131
|
+
case 'POST':
|
|
132
|
+
/** Call @Post decorator over new property */
|
|
133
|
+
Post(operationPath)(newClass.prototype, k, descriptor);
|
|
134
|
+
break;
|
|
135
|
+
case 'PUT':
|
|
136
|
+
/** Call @Put decorator over new property */
|
|
137
|
+
Put(operationPath)(newClass.prototype, k, descriptor);
|
|
138
|
+
break;
|
|
139
|
+
case 'SEARCH':
|
|
140
|
+
/** Call @Search decorator over new property */
|
|
141
|
+
Search(operationPath)(newClass.prototype, k, descriptor);
|
|
142
|
+
break;
|
|
143
|
+
default:
|
|
144
|
+
break;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
if (metadata.controllers) {
|
|
149
|
+
for (const child of metadata.controllers) {
|
|
150
|
+
if (!isConstructor(child))
|
|
151
|
+
throw new TypeError('Controllers should be injectable a class');
|
|
152
|
+
this._addToNestControllers(child, newPath);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
if (exception instanceof OpraException)
|
|
7
|
-
return true;
|
|
8
|
-
throw exception;
|
|
1
|
+
import { HttpOutgoing, wrapException } from '@opra/core';
|
|
2
|
+
export const kHandler = Symbol.for('kHandler');
|
|
3
|
+
export class OpraExceptionFilter {
|
|
4
|
+
constructor(adapter) {
|
|
5
|
+
this.adapter = adapter;
|
|
9
6
|
}
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
7
|
+
catch(exception, host) {
|
|
8
|
+
const ctx = host.switchToHttp();
|
|
9
|
+
const _res = ctx.getResponse();
|
|
10
|
+
const error = wrapException(exception);
|
|
11
|
+
const response = HttpOutgoing.from(_res);
|
|
12
|
+
return this.adapter[kHandler].sendErrorResponse(response, [error]);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { __decorate } from "tslib";
|
|
2
|
+
import { Injectable } from '@nestjs/common';
|
|
3
|
+
import { HttpContext, HttpIncoming, HttpOutgoing } from '@opra/core';
|
|
4
|
+
let OpraMiddleware = class OpraMiddleware {
|
|
5
|
+
use(req, res, next) {
|
|
6
|
+
const request = HttpIncoming.from(req);
|
|
7
|
+
const response = HttpOutgoing.from(res);
|
|
8
|
+
/** Create the HttpContext */
|
|
9
|
+
req.opraContext = new HttpContext({
|
|
10
|
+
adapter: {},
|
|
11
|
+
platform: req.route ? 'express' : 'fastify',
|
|
12
|
+
request,
|
|
13
|
+
response,
|
|
14
|
+
});
|
|
15
|
+
next();
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
OpraMiddleware = __decorate([
|
|
19
|
+
Injectable()
|
|
20
|
+
], OpraMiddleware);
|
|
21
|
+
export { OpraMiddleware };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opra/nestjs",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0-alpha.10",
|
|
4
4
|
"description": "Opra NestJS module",
|
|
5
5
|
"author": "Panates",
|
|
6
6
|
"license": "MIT",
|
|
@@ -17,8 +17,9 @@
|
|
|
17
17
|
"build:esm": "tsc -b tsconfig-build-esm.json",
|
|
18
18
|
"postbuild": "cp README.md package.json ../../LICENSE ../../build/nestjs && cp ../../package.cjs.json ../../build/nestjs/cjs/package.json",
|
|
19
19
|
"lint": "eslint . --max-warnings=0",
|
|
20
|
-
"
|
|
21
|
-
"
|
|
20
|
+
"format": "prettier . --write --log-level=warn",
|
|
21
|
+
"test": "jest --passWithNoTests",
|
|
22
|
+
"cover": "jest --passWithNoTests --collect-coverage",
|
|
22
23
|
"clean": "npm run clean:src && npm run clean:test && npm run clean:dist && npm run clean:cover",
|
|
23
24
|
"clean:src": "ts-cleanup -s src --all",
|
|
24
25
|
"clean:test": "ts-cleanup -s test --all",
|
|
@@ -26,22 +27,24 @@
|
|
|
26
27
|
"clean:cover": "rimraf ../../coverage/client"
|
|
27
28
|
},
|
|
28
29
|
"dependencies": {
|
|
29
|
-
"@opra/common": "^0.
|
|
30
|
-
"@opra/core": "^0.
|
|
31
|
-
"fast-tokenizer": "^1.
|
|
30
|
+
"@opra/common": "^1.0.0-alpha.10",
|
|
31
|
+
"@opra/core": "^1.0.0-alpha.10",
|
|
32
|
+
"fast-tokenizer": "^1.3.0",
|
|
32
33
|
"lodash.head": "^4.0.1",
|
|
33
|
-
"reflect-metadata": "^0.
|
|
34
|
+
"reflect-metadata": "^0.2.2"
|
|
34
35
|
},
|
|
35
36
|
"peerDependencies": {
|
|
36
|
-
"@nestjs/common": "^10.3.
|
|
37
|
-
"@nestjs/core": "^10.3.
|
|
37
|
+
"@nestjs/common": "^10.3.10",
|
|
38
|
+
"@nestjs/core": "^10.3.10"
|
|
38
39
|
},
|
|
39
40
|
"devDependencies": {
|
|
40
|
-
"@nestjs/platform-express": "^10.3.
|
|
41
|
-
"@nestjs/testing": "^10.3.
|
|
41
|
+
"@nestjs/platform-express": "^10.3.10",
|
|
42
|
+
"@nestjs/testing": "^10.3.10",
|
|
42
43
|
"@types/lodash.head": "^4.0.9",
|
|
43
44
|
"filedirname": "^3.4.0",
|
|
44
|
-
"
|
|
45
|
+
"rxjs": "^7.8.1",
|
|
46
|
+
"supertest": "^7.0.0",
|
|
47
|
+
"ts-gems": "^3.4.0"
|
|
45
48
|
},
|
|
46
49
|
"type": "module",
|
|
47
50
|
"module": "./esm/index.js",
|
|
@@ -63,4 +66,4 @@
|
|
|
63
66
|
"opra",
|
|
64
67
|
"nestjs"
|
|
65
68
|
]
|
|
66
|
-
}
|
|
69
|
+
}
|
|
File without changes
|
package/types/constants.d.ts
CHANGED
|
@@ -1,6 +1 @@
|
|
|
1
|
-
export declare const
|
|
2
|
-
export declare const OPRA_MODULE_ID = "opra:module_id";
|
|
3
|
-
export declare const OPRA_INITIALIZER = "opra_initializer";
|
|
4
|
-
export declare const kOptions: unique symbol;
|
|
5
|
-
export declare const kAdapter: unique symbol;
|
|
6
|
-
export declare const PARAM_ARGS_METADATA = "__routeArguments__";
|
|
1
|
+
export declare const IS_PUBLIC_KEY = "isPublic";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const Public: () => import("@nestjs/common").CustomDecorator<string>;
|
package/types/index.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import 'reflect-metadata';
|
|
2
|
-
import './augmentation/common-decorator.augmentation.js';
|
|
3
2
|
import './augmentation/nestjs.augmentation.js';
|
|
4
|
-
export * from './
|
|
5
|
-
export * from './decorators/
|
|
6
|
-
export * from './
|
|
7
|
-
export * from './opra-
|
|
3
|
+
export * from './constants.js';
|
|
4
|
+
export * from './decorators/public.decorator.js';
|
|
5
|
+
export * from './opra-http.module.js';
|
|
6
|
+
export * from './opra-nestjs-adapter.js';
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { ModuleMetadata, Type } from '@nestjs/common';
|
|
2
|
-
import { ApiDocumentFactory } from '@opra/common';
|
|
3
|
-
import { ExpressAdapter, NodeHttpAdapter } from '@opra/core';
|
|
4
|
-
export type OpraModuleOptions = NodeHttpAdapter.Options & {
|
|
5
|
-
id?: any;
|
|
6
|
-
adapterNode?: ExpressAdapter.Options;
|
|
7
|
-
adapterExpress?: ExpressAdapter.Options;
|
|
8
|
-
document?: Partial<ApiDocumentFactory.InitArguments>;
|
|
9
|
-
/**
|
|
10
|
-
* @default true
|
|
11
|
-
*/
|
|
12
|
-
useGlobalPrefix?: boolean;
|
|
13
|
-
};
|
|
14
|
-
type OpraModuleOptionsWithoutId = Omit<OpraModuleOptions, 'id'>;
|
|
15
|
-
export interface OpraModuleOptionsFactory {
|
|
16
|
-
createOptions(): Promise<OpraModuleOptionsWithoutId> | OpraModuleOptionsWithoutId;
|
|
17
|
-
}
|
|
18
|
-
export interface OpraModuleAsyncOptions extends Pick<ModuleMetadata, 'imports' | 'providers'> {
|
|
19
|
-
id?: any;
|
|
20
|
-
useExisting?: Type<OpraModuleOptionsFactory>;
|
|
21
|
-
useClass?: Type<OpraModuleOptionsFactory>;
|
|
22
|
-
useFactory?: (...args: any[]) => Promise<OpraModuleOptionsWithoutId> | OpraModuleOptionsWithoutId;
|
|
23
|
-
inject?: any[];
|
|
24
|
-
}
|
|
25
|
-
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { DynamicModule, MiddlewareConsumer, NestModule, OnModuleDestroy } from '@nestjs/common';
|
|
2
|
+
import type { OpraHttpModule } from './opra-http.module';
|
|
3
|
+
import { OpraNestAdapter } from './opra-nestjs-adapter.js';
|
|
4
|
+
export declare class OpraHttpCoreModule implements OnModuleDestroy, NestModule {
|
|
5
|
+
protected opraAdapter: OpraNestAdapter;
|
|
6
|
+
constructor(opraAdapter: OpraNestAdapter);
|
|
7
|
+
configure(consumer: MiddlewareConsumer): void;
|
|
8
|
+
static forRoot(init: OpraHttpModule.Initiator, options?: OpraHttpModule.Options): DynamicModule;
|
|
9
|
+
onModuleDestroy(): Promise<void>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { DynamicModule } from '@nestjs/common';
|
|
2
|
+
import { ApiDocumentFactory } from '@opra/common';
|
|
3
|
+
export declare namespace OpraHttpModule {
|
|
4
|
+
interface Initiator extends Pick<DynamicModule, 'imports' | 'providers' | 'exports' | 'controllers'>, Pick<ApiDocumentFactory.InitArguments, 'types' | 'references' | 'info'> {
|
|
5
|
+
id?: any;
|
|
6
|
+
name: string;
|
|
7
|
+
}
|
|
8
|
+
interface Options {
|
|
9
|
+
basePath?: string;
|
|
10
|
+
schemaRouteIsPublic?: boolean;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export declare class OpraHttpModule {
|
|
14
|
+
/**
|
|
15
|
+
*
|
|
16
|
+
* @param init
|
|
17
|
+
* @param options
|
|
18
|
+
*/
|
|
19
|
+
static forRoot(init: OpraHttpModule.Initiator, options?: OpraHttpModule.Options): DynamicModule;
|
|
20
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Type } from '@nestjs/common';
|
|
2
|
+
import { HttpAdapter } from '@opra/core';
|
|
3
|
+
import type { OpraHttpModule } from './opra-http.module';
|
|
4
|
+
export declare const kHandler: unique symbol;
|
|
5
|
+
export declare class OpraNestAdapter extends HttpAdapter {
|
|
6
|
+
readonly nestControllers: Type[];
|
|
7
|
+
readonly options?: OpraHttpModule.Options;
|
|
8
|
+
constructor(init: OpraHttpModule.Initiator, options?: OpraHttpModule.Options);
|
|
9
|
+
close(): Promise<void>;
|
|
10
|
+
protected _addRootController(basePath: string): void;
|
|
11
|
+
protected _addToNestControllers(sourceClass: Type, currentPath: string): void;
|
|
12
|
+
}
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import { ExceptionFilter } from '@nestjs/common';
|
|
1
|
+
import { ArgumentsHost, ExceptionFilter } from '@nestjs/common';
|
|
2
|
+
import { OpraNestAdapter } from '../opra-nestjs-adapter.js';
|
|
3
|
+
export declare const kHandler: unique symbol;
|
|
2
4
|
export declare class OpraExceptionFilter implements ExceptionFilter {
|
|
3
|
-
|
|
5
|
+
readonly adapter: OpraNestAdapter;
|
|
6
|
+
constructor(adapter: OpraNestAdapter);
|
|
7
|
+
catch(exception: any, host: ArgumentsHost): Promise<void>;
|
|
4
8
|
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const common_1 = require("@nestjs/common");
|
|
4
|
-
const common_2 = require("@opra/common");
|
|
5
|
-
/*
|
|
6
|
-
Overrides Collection decorator function to call NestJS's Injectable() when Collection decorator called
|
|
7
|
-
*/
|
|
8
|
-
const oldCollectionDecorator = common_2.Collection[common_2.DECORATOR];
|
|
9
|
-
common_2.Collection[common_2.DECORATOR] = function CollectionDecorator(...args) {
|
|
10
|
-
const collectionDecorator = oldCollectionDecorator(...args);
|
|
11
|
-
const injectableDecorator = (0, common_1.Injectable)();
|
|
12
|
-
return (target) => {
|
|
13
|
-
collectionDecorator(target);
|
|
14
|
-
injectableDecorator(target);
|
|
15
|
-
};
|
|
16
|
-
};
|
|
17
|
-
/*
|
|
18
|
-
Overrides Singleton decorator function to call NestJS's Injectable() when Singleton decorator called
|
|
19
|
-
*/
|
|
20
|
-
const oldSingletonDecorator = common_2.Singleton[common_2.DECORATOR];
|
|
21
|
-
common_2.Singleton[common_2.DECORATOR] = function SingletonDecorator(...args) {
|
|
22
|
-
const singletonDecorator = oldSingletonDecorator(...args);
|
|
23
|
-
const injectableDecorator = (0, common_1.Injectable)();
|
|
24
|
-
return (target) => {
|
|
25
|
-
singletonDecorator(target);
|
|
26
|
-
injectableDecorator(target);
|
|
27
|
-
};
|
|
28
|
-
};
|
|
29
|
-
/*
|
|
30
|
-
Overrides Singleton decorator function to call NestJS's Injectable() when Singleton decorator called
|
|
31
|
-
*/
|
|
32
|
-
const oldStorageDecorator = common_2.Storage[common_2.DECORATOR];
|
|
33
|
-
common_2.Storage[common_2.DECORATOR] = function StorageDecorator(...args) {
|
|
34
|
-
const storageDecorator = oldStorageDecorator(...args);
|
|
35
|
-
const injectableDecorator = (0, common_1.Injectable)();
|
|
36
|
-
return (target) => {
|
|
37
|
-
storageDecorator(target);
|
|
38
|
-
injectableDecorator(target);
|
|
39
|
-
};
|
|
40
|
-
};
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
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 `RequestContext`.
|
|
9
|
-
*/
|
|
10
|
-
exports.Context = (0, param_utils_js_1.createOpraParamDecorator)(handler_paramtype_enum_js_1.HandlerParamType.CONTEXT);
|
|
@@ -1,9 +0,0 @@
|
|
|
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["REQUEST"] = 1] = "REQUEST";
|
|
8
|
-
HandlerParamType[HandlerParamType["RESPONSE"] = 2] = "RESPONSE";
|
|
9
|
-
})(HandlerParamType || (exports.HandlerParamType = HandlerParamType = {}));
|
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.OpraApiFactory = void 0;
|
|
4
|
-
const tslib_1 = require("tslib");
|
|
5
|
-
const lodash_head_1 = tslib_1.__importDefault(require("lodash.head"));
|
|
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 common_2 = require("@opra/common");
|
|
13
|
-
const constants_js_1 = require("../constants.js");
|
|
14
|
-
const handler_paramtype_enum_js_1 = require("../enums/handler-paramtype.enum.js");
|
|
15
|
-
const nest_explorer_js_1 = require("../services/nest-explorer.js");
|
|
16
|
-
const function_utils_js_1 = require("../utils/function.utils.js");
|
|
17
|
-
const params_factory_js_1 = require("./params.factory.js");
|
|
18
|
-
const noOpFunction = () => void 0;
|
|
19
|
-
let OpraApiFactory = class OpraApiFactory {
|
|
20
|
-
constructor() {
|
|
21
|
-
this.paramsFactory = new params_factory_js_1.OpraParamsFactory();
|
|
22
|
-
this.injector = new injector_1.Injector();
|
|
23
|
-
}
|
|
24
|
-
async generateService(rootModule, contextType, apiSchema) {
|
|
25
|
-
const info = { ...apiSchema?.info };
|
|
26
|
-
info.title = info.title || 'Untitled service';
|
|
27
|
-
info.version = info.version || '1';
|
|
28
|
-
const root = {
|
|
29
|
-
resources: []
|
|
30
|
-
};
|
|
31
|
-
const apiInit = {
|
|
32
|
-
version: common_2.OpraSchema.SpecVersion,
|
|
33
|
-
...apiSchema,
|
|
34
|
-
info,
|
|
35
|
-
types: apiSchema?.types || [],
|
|
36
|
-
root
|
|
37
|
-
};
|
|
38
|
-
/*
|
|
39
|
-
* Walk through modules and add Resource instances to the api schema
|
|
40
|
-
*/
|
|
41
|
-
this.explorerService.exploreResources(rootModule, (wrapper, modulePath) => {
|
|
42
|
-
const instance = wrapper.instance;
|
|
43
|
-
const ctor = instance.constructor;
|
|
44
|
-
const metadata = Reflect.getMetadata(common_2.RESOURCE_METADATA, ctor);
|
|
45
|
-
let node = root;
|
|
46
|
-
modulePath.forEach(m => {
|
|
47
|
-
const mt = Reflect.getMetadata(common_2.RESOURCE_METADATA, m._metatype);
|
|
48
|
-
if (mt) {
|
|
49
|
-
let n = node.resources.find(x => x.controller === m.instance);
|
|
50
|
-
if (!n) {
|
|
51
|
-
n = {
|
|
52
|
-
...mt,
|
|
53
|
-
kind: 'Container',
|
|
54
|
-
resources: [...(mt.resources || [])],
|
|
55
|
-
controller: m.instance
|
|
56
|
-
};
|
|
57
|
-
node.resources.push(n);
|
|
58
|
-
}
|
|
59
|
-
node = n;
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
// Do not add Modules decorated with @Container
|
|
63
|
-
if (wrapper.metatype !== wrapper.host?.metatype)
|
|
64
|
-
node.resources.push(instance);
|
|
65
|
-
/* Wrap operation and action functions */
|
|
66
|
-
const isRequestScoped = !wrapper.isDependencyTreeStatic();
|
|
67
|
-
const methodNames = [...Object.keys(metadata.operations || []), ...Object.keys(metadata.actions || [])];
|
|
68
|
-
for (const methodName of methodNames) {
|
|
69
|
-
const endpointFunction = instance[methodName];
|
|
70
|
-
const nestHandlerName = methodName + '_nestjs';
|
|
71
|
-
// Skip patch if controller do not have function for endpoint or already patched before
|
|
72
|
-
if (typeof endpointFunction !== 'function')
|
|
73
|
-
continue;
|
|
74
|
-
// NestJs requires calling handler function in different order than Opra.
|
|
75
|
-
// In NestJS, handler functions must be called with these parameters (req, res, next)
|
|
76
|
-
// In Opra, handler functions must be called with these parameters (context)
|
|
77
|
-
// To work handlers properly we create new handlers that will work as a proxy to wrap parameters
|
|
78
|
-
// Opra request (context) -> Nest (req, res, next, context: QueryRequestContext) -> Opra response (context)
|
|
79
|
-
const paramArgsMetadata = Reflect.getMetadata(constants_js_1.PARAM_ARGS_METADATA, instance.constructor, methodName);
|
|
80
|
-
const hasParamsArgs = !!paramArgsMetadata;
|
|
81
|
-
const patchedFn = instance[nestHandlerName] = function (...args) {
|
|
82
|
-
if (hasParamsArgs)
|
|
83
|
-
return endpointFunction.apply(this, args);
|
|
84
|
-
return endpointFunction.call(this, args[3]);
|
|
85
|
-
};
|
|
86
|
-
if (paramArgsMetadata)
|
|
87
|
-
Reflect.defineMetadata(constants_js_1.PARAM_ARGS_METADATA, paramArgsMetadata, instance.constructor, nestHandlerName);
|
|
88
|
-
// Copy all metadata from old Function to new one
|
|
89
|
-
Reflect.getMetadataKeys(endpointFunction).forEach(k => {
|
|
90
|
-
const m = Reflect.getMetadata(k, endpointFunction);
|
|
91
|
-
Reflect.defineMetadata(k, m, patchedFn);
|
|
92
|
-
});
|
|
93
|
-
this._createContextCallback(instance, wrapper, rootModule, methodName, isRequestScoped, contextType);
|
|
94
|
-
}
|
|
95
|
-
});
|
|
96
|
-
// Create api document
|
|
97
|
-
return common_2.ApiDocumentFactory.createDocument(apiInit);
|
|
98
|
-
}
|
|
99
|
-
_createHandler(callback) {
|
|
100
|
-
return function (ctx) {
|
|
101
|
-
switch (ctx.protocol) {
|
|
102
|
-
case 'http':
|
|
103
|
-
const httpContext = ctx.switchToHttp();
|
|
104
|
-
return callback(httpContext.incoming, httpContext.outgoing, noOpFunction, ctx);
|
|
105
|
-
default:
|
|
106
|
-
throw new Error(`"${ctx.protocol}" context type is not implemented yet`);
|
|
107
|
-
}
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
_createContextCallback(instance, wrapper, moduleRef, methodName, isRequestScoped, contextType, options) {
|
|
111
|
-
const paramsFactory = this.paramsFactory;
|
|
112
|
-
const nestHandlerName = methodName + '_nestjs';
|
|
113
|
-
const callback = isRequestScoped
|
|
114
|
-
? async (...args) => {
|
|
115
|
-
const opraContext = paramsFactory.exchangeKeyForValue(handler_paramtype_enum_js_1.HandlerParamType.CONTEXT, undefined, args);
|
|
116
|
-
const contextId = this.getContextId(opraContext);
|
|
117
|
-
this.registerContextProvider(opraContext, contextId);
|
|
118
|
-
const contextInstance = await this.injector.loadPerContext(instance, moduleRef, moduleRef.providers, contextId);
|
|
119
|
-
const contextCallback = this.externalContextCreator.create(contextInstance, contextInstance[methodName], nestHandlerName, constants_js_1.PARAM_ARGS_METADATA, paramsFactory, contextId, wrapper.id, options, opraContext.protocol);
|
|
120
|
-
contextInstance[methodName] = this._createHandler(contextCallback);
|
|
121
|
-
return contextCallback(...args);
|
|
122
|
-
}
|
|
123
|
-
: this.externalContextCreator.create(instance, instance[nestHandlerName], nestHandlerName, constants_js_1.PARAM_ARGS_METADATA, paramsFactory, undefined, undefined, options, contextType);
|
|
124
|
-
instance[methodName] = this._createHandler(callback);
|
|
125
|
-
return callback;
|
|
126
|
-
}
|
|
127
|
-
// noinspection JSMethodCanBeStatic
|
|
128
|
-
getContextId(gqlContext) {
|
|
129
|
-
const numberOfArguments = (0, function_utils_js_1.getNumberOfArguments)(core_1.ContextIdFactory.getByRequest);
|
|
130
|
-
if (numberOfArguments === 2) {
|
|
131
|
-
// @ts-ignore
|
|
132
|
-
const contextId = core_1.ContextIdFactory.getByRequest(gqlContext, ['req']);
|
|
133
|
-
if (!gqlContext[request_constants_1.REQUEST_CONTEXT_ID]) {
|
|
134
|
-
Object.defineProperty(gqlContext, request_constants_1.REQUEST_CONTEXT_ID, {
|
|
135
|
-
value: contextId,
|
|
136
|
-
enumerable: false,
|
|
137
|
-
configurable: false,
|
|
138
|
-
writable: false,
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
return contextId;
|
|
142
|
-
}
|
|
143
|
-
else {
|
|
144
|
-
// TODO remove in the next version (backward-compatibility layer)
|
|
145
|
-
// Left for backward compatibility purposes
|
|
146
|
-
let contextId;
|
|
147
|
-
if (gqlContext && gqlContext[request_constants_1.REQUEST_CONTEXT_ID]) {
|
|
148
|
-
contextId = gqlContext[request_constants_1.REQUEST_CONTEXT_ID];
|
|
149
|
-
}
|
|
150
|
-
else if (gqlContext &&
|
|
151
|
-
gqlContext.req &&
|
|
152
|
-
gqlContext.req[request_constants_1.REQUEST_CONTEXT_ID]) {
|
|
153
|
-
contextId = gqlContext.req[request_constants_1.REQUEST_CONTEXT_ID];
|
|
154
|
-
}
|
|
155
|
-
else {
|
|
156
|
-
contextId = (0, core_1.createContextId)();
|
|
157
|
-
Object.defineProperty(gqlContext, request_constants_1.REQUEST_CONTEXT_ID, {
|
|
158
|
-
value: contextId,
|
|
159
|
-
enumerable: false,
|
|
160
|
-
configurable: false,
|
|
161
|
-
writable: false,
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
return contextId;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
registerContextProvider(request, contextId) {
|
|
168
|
-
const coreModuleArray = [...this.modulesContainer.entries()]
|
|
169
|
-
.filter(
|
|
170
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
171
|
-
([key, { metatype }]) => metatype && metatype.name === internal_core_module_1.InternalCoreModule.name)
|
|
172
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
173
|
-
.map(([key, value]) => value);
|
|
174
|
-
const coreModuleRef = (0, lodash_head_1.default)(coreModuleArray);
|
|
175
|
-
if (!coreModuleRef) {
|
|
176
|
-
return;
|
|
177
|
-
}
|
|
178
|
-
const wrapper = coreModuleRef.getProviderByKey(core_1.REQUEST);
|
|
179
|
-
wrapper.setInstanceByContextId(contextId, {
|
|
180
|
-
instance: request,
|
|
181
|
-
isResolved: true,
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
|
-
};
|
|
185
|
-
exports.OpraApiFactory = OpraApiFactory;
|
|
186
|
-
tslib_1.__decorate([
|
|
187
|
-
(0, common_1.Inject)(),
|
|
188
|
-
tslib_1.__metadata("design:type", core_1.ModulesContainer)
|
|
189
|
-
], OpraApiFactory.prototype, "modulesContainer", void 0);
|
|
190
|
-
tslib_1.__decorate([
|
|
191
|
-
(0, common_1.Inject)(),
|
|
192
|
-
tslib_1.__metadata("design:type", external_context_creator_1.ExternalContextCreator)
|
|
193
|
-
], OpraApiFactory.prototype, "externalContextCreator", void 0);
|
|
194
|
-
tslib_1.__decorate([
|
|
195
|
-
(0, common_1.Inject)(),
|
|
196
|
-
tslib_1.__metadata("design:type", nest_explorer_js_1.NestExplorer)
|
|
197
|
-
], OpraApiFactory.prototype, "explorerService", void 0);
|
|
198
|
-
exports.OpraApiFactory = OpraApiFactory = tslib_1.__decorate([
|
|
199
|
-
(0, common_1.Injectable)()
|
|
200
|
-
], OpraApiFactory);
|