@opra/nestjs 1.0.0-alpha.2 → 1.0.0-alpha.21

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.
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.IS_PUBLIC_KEY = void 0;
4
+ exports.IS_PUBLIC_KEY = 'isPublic';
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Public = void 0;
4
+ const common_1 = require("@nestjs/common");
5
+ const constants_js_1 = require("../constants.js");
6
+ const Public = () => (0, common_1.SetMetadata)(constants_js_1.IS_PUBLIC_KEY, true);
7
+ exports.Public = Public;
package/cjs/index.js CHANGED
@@ -3,5 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
4
  require("reflect-metadata");
5
5
  require("./augmentation/nestjs.augmentation.js");
6
+ tslib_1.__exportStar(require("./constants.js"), exports);
7
+ tslib_1.__exportStar(require("./decorators/public.decorator.js"), exports);
6
8
  tslib_1.__exportStar(require("./opra-http.module.js"), exports);
7
9
  tslib_1.__exportStar(require("./opra-nestjs-adapter.js"), exports);
@@ -3,40 +3,48 @@ var OpraHttpCoreModule_1;
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.OpraHttpCoreModule = void 0;
5
5
  const tslib_1 = require("tslib");
6
- const ts_gems_1 = require("ts-gems");
7
6
  const common_1 = require("@nestjs/common");
8
7
  const common_2 = require("@opra/common");
8
+ const ts_gems_1 = require("ts-gems");
9
9
  const opra_nestjs_adapter_js_1 = require("./opra-nestjs-adapter.js");
10
+ const opra_middleware_js_1 = require("./services/opra-middleware.js");
10
11
  let OpraHttpCoreModule = OpraHttpCoreModule_1 = class OpraHttpCoreModule {
11
12
  constructor(opraAdapter) {
12
13
  this.opraAdapter = opraAdapter;
13
14
  }
14
- static forRoot(options) {
15
- const opraAdapter = new opra_nestjs_adapter_js_1.OpraNestAdapter(options);
16
- const token = options?.id || opra_nestjs_adapter_js_1.OpraNestAdapter;
15
+ configure(consumer) {
16
+ consumer.apply(opra_middleware_js_1.OpraMiddleware).forRoutes({
17
+ path: '*',
18
+ method: common_1.RequestMethod.ALL,
19
+ });
20
+ }
21
+ static forRoot(init, options) {
22
+ const opraAdapter = new opra_nestjs_adapter_js_1.OpraNestAdapter(init, options);
23
+ const token = init?.id || opra_nestjs_adapter_js_1.OpraNestAdapter;
17
24
  const providers = [
18
- ...(options?.providers || []),
25
+ ...(init?.providers || []),
19
26
  {
20
27
  provide: opra_nestjs_adapter_js_1.OpraNestAdapter,
21
28
  useFactory: async () => {
22
29
  (0, ts_gems_1.asMutable)(opraAdapter).document = await common_2.ApiDocumentFactory.createDocument({
23
- ...options,
24
- api: { protocol: 'http', name: options.name, controllers: opraAdapter.controllers },
30
+ ...init,
31
+ api: { protocol: 'http', name: init.name, controllers: init.controllers },
25
32
  });
26
33
  return opraAdapter;
27
34
  },
28
35
  },
29
36
  ];
30
- if (token !== opra_nestjs_adapter_js_1.OpraNestAdapter)
37
+ if (token !== opra_nestjs_adapter_js_1.OpraNestAdapter) {
31
38
  providers.push({
32
39
  provide: token,
33
40
  useValue: opraAdapter,
34
41
  });
42
+ }
35
43
  return {
36
44
  module: OpraHttpCoreModule_1,
37
- controllers: opraAdapter.controllers,
38
- imports: [...(options?.imports || [])],
39
- exports: [...(options?.exports || []), token],
45
+ controllers: opraAdapter.nestControllers,
46
+ imports: [...(init?.imports || [])],
47
+ exports: [...(init?.exports || []), token],
40
48
  providers,
41
49
  };
42
50
  }
@@ -8,12 +8,13 @@ const opra_http_core_module_js_1 = require("./opra-http-core.module.js");
8
8
  let OpraHttpModule = OpraHttpModule_1 = class OpraHttpModule {
9
9
  /**
10
10
  *
11
+ * @param init
11
12
  * @param options
12
13
  */
13
- static forRoot(options) {
14
+ static forRoot(init, options) {
14
15
  return {
15
16
  module: OpraHttpModule_1,
16
- imports: [opra_http_core_module_js_1.OpraHttpCoreModule.forRoot(options)],
17
+ imports: [opra_http_core_module_js_1.OpraHttpCoreModule.forRoot(init, options)],
17
18
  };
18
19
  }
19
20
  };
@@ -2,92 +2,118 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.OpraNestAdapter = exports.kHandler = void 0;
4
4
  const tslib_1 = require("tslib");
5
- const path_1 = tslib_1.__importDefault(require("path"));
6
5
  const common_1 = require("@nestjs/common");
6
+ const constants_1 = require("@nestjs/common/constants");
7
7
  const common_2 = require("@opra/common");
8
8
  const core_1 = require("@opra/core");
9
+ const path_1 = tslib_1.__importDefault(require("path"));
10
+ const ts_gems_1 = require("ts-gems");
11
+ const public_decorator_js_1 = require("./decorators/public.decorator.js");
9
12
  const opra_exception_filter_js_1 = require("./services/opra-exception-filter.js");
10
13
  exports.kHandler = Symbol.for('kHandler');
11
14
  class OpraNestAdapter extends core_1.HttpAdapter {
12
- constructor(options) {
15
+ constructor(init, options) {
13
16
  super((function () {
14
17
  const document = new common_2.ApiDocument();
15
18
  document.api = new common_2.HttpApi(document);
16
19
  return document;
17
20
  })(), options);
18
- // protected _platform: string = 'express';
19
- this.controllers = [];
20
- let basePath = options.basePath || '/';
21
+ this.nestControllers = [];
22
+ this.options = options;
23
+ let basePath = options?.basePath || '/';
21
24
  if (!basePath.startsWith('/'))
22
25
  basePath = '/' + basePath;
23
- if (options.controllers)
24
- options.controllers.forEach(c => this._createNestControllers(c, basePath));
26
+ this._addRootController(basePath);
27
+ if (init.controllers)
28
+ init.controllers.forEach(c => this._addToNestControllers(c, basePath));
25
29
  }
26
30
  async close() {
27
31
  //
28
32
  }
29
- _createNestControllers(source, currentPath) {
30
- const metadata = Reflect.getMetadata(common_2.HTTP_CONTROLLER_METADATA, source);
33
+ _addRootController(basePath) {
34
+ const _this = this;
35
+ let RootController = class RootController {
36
+ schema(_req, next) {
37
+ _this[exports.kHandler].sendDocumentSchema(_req.opraContext).catch(next);
38
+ }
39
+ };
40
+ tslib_1.__decorate([
41
+ (0, common_1.Get)('/\\$schema'),
42
+ tslib_1.__param(0, (0, common_1.Req)()),
43
+ tslib_1.__param(1, (0, common_1.Next)()),
44
+ tslib_1.__metadata("design:type", Function),
45
+ tslib_1.__metadata("design:paramtypes", [Object, Function]),
46
+ tslib_1.__metadata("design:returntype", void 0)
47
+ ], RootController.prototype, "schema", null);
48
+ RootController = tslib_1.__decorate([
49
+ (0, common_1.Controller)({
50
+ path: basePath,
51
+ })
52
+ ], RootController);
53
+ if (this.options?.schemaRouteIsPublic) {
54
+ (0, public_decorator_js_1.Public)()(RootController.prototype, 'schema', Object.getOwnPropertyDescriptor(RootController.prototype, 'schema'));
55
+ }
56
+ this.nestControllers.push(RootController);
57
+ }
58
+ _addToNestControllers(sourceClass, currentPath, parentClass) {
59
+ const metadata = Reflect.getMetadata(common_2.HTTP_CONTROLLER_METADATA, sourceClass);
31
60
  if (!metadata)
32
61
  return;
33
62
  const newClass = {
34
- [source.name]: class extends source {
63
+ [sourceClass.name]: class extends sourceClass {
35
64
  },
36
- }[source.name];
65
+ }[sourceClass.name];
66
+ /** Copy metadata keys from source class to new one */
67
+ let metadataKeys;
68
+ if (parentClass) {
69
+ OpraNestAdapter.copyDecoratorMetadataToChild(newClass, parentClass);
70
+ }
37
71
  const newPath = metadata.path ? path_1.default.join(currentPath, metadata.path) : currentPath;
38
72
  const adapter = this;
39
73
  /** Inject exception filter */
40
74
  (0, common_1.UseFilters)(new opra_exception_filter_js_1.OpraExceptionFilter(adapter))(newClass);
41
75
  (0, common_1.Controller)()(newClass);
42
- this.controllers.push(newClass);
76
+ this.nestControllers.push(newClass);
43
77
  if (metadata.operations) {
44
78
  for (const [k, v] of Object.entries(metadata.operations)) {
45
- const operationHandler = source.prototype[k];
79
+ const operationHandler = sourceClass.prototype[k];
46
80
  Object.defineProperty(newClass.prototype, k, {
47
81
  writable: true,
48
82
  /** NestJS handler method */
49
- async value(_req, _res) {
50
- const request = core_1.HttpIncoming.from(_req);
51
- const response = core_1.HttpOutgoing.from(_res);
83
+ async value(_req) {
52
84
  const api = adapter.document.api;
53
- const controller = api.findController(newClass);
85
+ const controller = api.findController(sourceClass);
54
86
  const operation = controller?.operations.get(k);
55
- if (!(operation && typeof operationHandler === 'function'))
87
+ const context = (0, ts_gems_1.asMutable)(_req.opraContext);
88
+ if (!(context && operation && typeof operationHandler === 'function')) {
56
89
  throw new common_2.NotFoundError({
57
- message: `No endpoint found for [${request.method}]${request.baseUrl}`,
90
+ message: `No endpoint found for [${_req.method}]${_req.baseUrl}`,
58
91
  details: {
59
- path: request.baseUrl,
60
- method: request.method,
92
+ path: _req.baseUrl,
93
+ method: _req.method,
61
94
  },
62
95
  });
63
- /** Create the HttpContext */
64
- const context = new core_1.HttpContext({
65
- adapter,
66
- platform: _req.route ? 'express' : 'fastify',
67
- platformArgs: {
68
- request,
69
- response,
70
- },
71
- request,
72
- response,
73
- operation,
74
- controller: operation.owner,
75
- controllerInstance: this,
76
- operationHandler,
77
- });
96
+ }
97
+ /** Configure the HttpContext */
98
+ context.adapter = adapter;
99
+ context.document = adapter.document;
100
+ context.operation = operation;
101
+ context.controller = operation.owner;
102
+ context.controllerInstance = this;
103
+ context.operationHandler = operationHandler;
78
104
  /** Handle request */
79
105
  await adapter[exports.kHandler].handleRequest(context);
80
106
  },
81
107
  });
82
- (0, common_1.Req)()(newClass.prototype, k, 0);
83
- (0, common_1.Res)()(newClass.prototype, k, 1);
84
108
  /** Copy metadata keys from source function to new one */
85
- const metadataKeys = Reflect.getOwnMetadataKeys(operationHandler);
109
+ metadataKeys = Reflect.getOwnMetadataKeys(operationHandler);
86
110
  const newFn = newClass.prototype[k];
87
111
  for (const key of metadataKeys) {
88
112
  const m = Reflect.getMetadata(key, operationHandler);
89
113
  Reflect.defineMetadata(key, m, newFn);
90
114
  }
115
+ (0, common_1.Req)()(newClass.prototype, k, 0);
116
+ (0, common_1.Res)()(newClass.prototype, k, 1);
91
117
  const descriptor = Object.getOwnPropertyDescriptor(newClass.prototype, k);
92
118
  const operationPath = newPath + (v.path || '');
93
119
  switch (v.method || 'GET') {
@@ -123,6 +149,8 @@ class OpraNestAdapter extends core_1.HttpAdapter {
123
149
  /** Call @Search decorator over new property */
124
150
  (0, common_1.Search)(operationPath)(newClass.prototype, k, descriptor);
125
151
  break;
152
+ default:
153
+ break;
126
154
  }
127
155
  }
128
156
  }
@@ -130,9 +158,23 @@ class OpraNestAdapter extends core_1.HttpAdapter {
130
158
  for (const child of metadata.controllers) {
131
159
  if (!(0, common_2.isConstructor)(child))
132
160
  throw new TypeError('Controllers should be injectable a class');
133
- this._createNestControllers(child, newPath);
161
+ this._addToNestControllers(child, newPath, sourceClass);
134
162
  }
135
163
  }
136
164
  }
165
+ static copyDecoratorMetadataToChild(target, parent) {
166
+ const metadataKeys = Reflect.getOwnMetadataKeys(parent);
167
+ for (const key of metadataKeys) {
168
+ if (key === constants_1.GUARDS_METADATA || key === constants_1.INTERCEPTORS_METADATA || key === constants_1.EXCEPTION_FILTERS_METADATA) {
169
+ const m1 = Reflect.getMetadata(key, target) || [];
170
+ const m2 = Reflect.getOwnMetadata(key, parent) || [];
171
+ Reflect.defineMetadata(key, [...m1, ...m2], target);
172
+ }
173
+ }
174
+ const subParent = Object.getPrototypeOf(parent.prototype).constructor;
175
+ if (subParent && subParent !== Object) {
176
+ this.copyDecoratorMetadataToChild(target, subParent);
177
+ }
178
+ }
137
179
  }
138
180
  exports.OpraNestAdapter = OpraNestAdapter;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OpraMiddleware = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const common_1 = require("@nestjs/common");
6
+ const core_1 = require("@opra/core");
7
+ let OpraMiddleware = class OpraMiddleware {
8
+ use(req, res, next) {
9
+ const request = core_1.HttpIncoming.from(req);
10
+ const response = core_1.HttpOutgoing.from(res);
11
+ /** Create the HttpContext */
12
+ req.opraContext = new core_1.HttpContext({
13
+ adapter: {},
14
+ platform: req.route ? 'express' : 'fastify',
15
+ request,
16
+ response,
17
+ });
18
+ next();
19
+ }
20
+ };
21
+ exports.OpraMiddleware = OpraMiddleware;
22
+ exports.OpraMiddleware = OpraMiddleware = tslib_1.__decorate([
23
+ (0, common_1.Injectable)()
24
+ ], OpraMiddleware);
@@ -0,0 +1 @@
1
+ export const IS_PUBLIC_KEY = 'isPublic';
@@ -0,0 +1,3 @@
1
+ import { SetMetadata } from '@nestjs/common';
2
+ import { IS_PUBLIC_KEY } from '../constants.js';
3
+ export const Public = () => SetMetadata(IS_PUBLIC_KEY, true);
package/esm/index.js CHANGED
@@ -1,4 +1,6 @@
1
1
  import 'reflect-metadata';
2
2
  import './augmentation/nestjs.augmentation.js';
3
+ export * from './constants.js';
4
+ export * from './decorators/public.decorator.js';
3
5
  export * from './opra-http.module.js';
4
6
  export * from './opra-nestjs-adapter.js';
@@ -1,39 +1,47 @@
1
1
  var OpraHttpCoreModule_1;
2
2
  import { __decorate, __metadata } from "tslib";
3
- import { asMutable } from 'ts-gems';
4
- import { Global, Module } from '@nestjs/common';
3
+ import { Global, Module, RequestMethod, } from '@nestjs/common';
5
4
  import { ApiDocumentFactory } from '@opra/common';
5
+ import { asMutable } from 'ts-gems';
6
6
  import { OpraNestAdapter } from './opra-nestjs-adapter.js';
7
+ import { OpraMiddleware } from './services/opra-middleware.js';
7
8
  let OpraHttpCoreModule = OpraHttpCoreModule_1 = class OpraHttpCoreModule {
8
9
  constructor(opraAdapter) {
9
10
  this.opraAdapter = opraAdapter;
10
11
  }
11
- static forRoot(options) {
12
- const opraAdapter = new OpraNestAdapter(options);
13
- const token = options?.id || OpraNestAdapter;
12
+ configure(consumer) {
13
+ consumer.apply(OpraMiddleware).forRoutes({
14
+ path: '*',
15
+ method: RequestMethod.ALL,
16
+ });
17
+ }
18
+ static forRoot(init, options) {
19
+ const opraAdapter = new OpraNestAdapter(init, options);
20
+ const token = init?.id || OpraNestAdapter;
14
21
  const providers = [
15
- ...(options?.providers || []),
22
+ ...(init?.providers || []),
16
23
  {
17
24
  provide: OpraNestAdapter,
18
25
  useFactory: async () => {
19
26
  asMutable(opraAdapter).document = await ApiDocumentFactory.createDocument({
20
- ...options,
21
- api: { protocol: 'http', name: options.name, controllers: opraAdapter.controllers },
27
+ ...init,
28
+ api: { protocol: 'http', name: init.name, controllers: init.controllers },
22
29
  });
23
30
  return opraAdapter;
24
31
  },
25
32
  },
26
33
  ];
27
- if (token !== OpraNestAdapter)
34
+ if (token !== OpraNestAdapter) {
28
35
  providers.push({
29
36
  provide: token,
30
37
  useValue: opraAdapter,
31
38
  });
39
+ }
32
40
  return {
33
41
  module: OpraHttpCoreModule_1,
34
- controllers: opraAdapter.controllers,
35
- imports: [...(options?.imports || [])],
36
- exports: [...(options?.exports || []), token],
42
+ controllers: opraAdapter.nestControllers,
43
+ imports: [...(init?.imports || [])],
44
+ exports: [...(init?.exports || []), token],
37
45
  providers,
38
46
  };
39
47
  }
@@ -5,12 +5,13 @@ import { OpraHttpCoreModule } from './opra-http-core.module.js';
5
5
  let OpraHttpModule = OpraHttpModule_1 = class OpraHttpModule {
6
6
  /**
7
7
  *
8
+ * @param init
8
9
  * @param options
9
10
  */
10
- static forRoot(options) {
11
+ static forRoot(init, options) {
11
12
  return {
12
13
  module: OpraHttpModule_1,
13
- imports: [OpraHttpCoreModule.forRoot(options)],
14
+ imports: [OpraHttpCoreModule.forRoot(init, options)],
14
15
  };
15
16
  }
16
17
  };
@@ -1,89 +1,116 @@
1
- import nodePath from 'path';
2
- import { Controller, Delete, Get, Head, Options, Patch, Post, Put, Req, Res, Search, UseFilters, } from '@nestjs/common';
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 { EXCEPTION_FILTERS_METADATA, GUARDS_METADATA, INTERCEPTORS_METADATA } from '@nestjs/common/constants';
3
4
  import { ApiDocument, HTTP_CONTROLLER_METADATA, HttpApi, isConstructor, NotFoundError, } from '@opra/common';
4
- import { HttpAdapter, HttpContext, HttpIncoming, HttpOutgoing } from '@opra/core';
5
+ import { HttpAdapter } from '@opra/core';
6
+ import nodePath from 'path';
7
+ import { asMutable } from 'ts-gems';
8
+ import { Public } from './decorators/public.decorator.js';
5
9
  import { OpraExceptionFilter } from './services/opra-exception-filter.js';
6
10
  export const kHandler = Symbol.for('kHandler');
7
11
  export class OpraNestAdapter extends HttpAdapter {
8
- constructor(options) {
12
+ constructor(init, options) {
9
13
  super((function () {
10
14
  const document = new ApiDocument();
11
15
  document.api = new HttpApi(document);
12
16
  return document;
13
17
  })(), options);
14
- // protected _platform: string = 'express';
15
- this.controllers = [];
16
- let basePath = options.basePath || '/';
18
+ this.nestControllers = [];
19
+ this.options = options;
20
+ let basePath = options?.basePath || '/';
17
21
  if (!basePath.startsWith('/'))
18
22
  basePath = '/' + basePath;
19
- if (options.controllers)
20
- options.controllers.forEach(c => this._createNestControllers(c, basePath));
23
+ this._addRootController(basePath);
24
+ if (init.controllers)
25
+ init.controllers.forEach(c => this._addToNestControllers(c, basePath));
21
26
  }
22
27
  async close() {
23
28
  //
24
29
  }
25
- _createNestControllers(source, currentPath) {
26
- const metadata = Reflect.getMetadata(HTTP_CONTROLLER_METADATA, source);
30
+ _addRootController(basePath) {
31
+ const _this = this;
32
+ let RootController = class RootController {
33
+ schema(_req, next) {
34
+ _this[kHandler].sendDocumentSchema(_req.opraContext).catch(next);
35
+ }
36
+ };
37
+ __decorate([
38
+ Get('/\\$schema'),
39
+ __param(0, Req()),
40
+ __param(1, Next()),
41
+ __metadata("design:type", Function),
42
+ __metadata("design:paramtypes", [Object, Function]),
43
+ __metadata("design:returntype", void 0)
44
+ ], RootController.prototype, "schema", null);
45
+ RootController = __decorate([
46
+ Controller({
47
+ path: basePath,
48
+ })
49
+ ], RootController);
50
+ if (this.options?.schemaRouteIsPublic) {
51
+ Public()(RootController.prototype, 'schema', Object.getOwnPropertyDescriptor(RootController.prototype, 'schema'));
52
+ }
53
+ this.nestControllers.push(RootController);
54
+ }
55
+ _addToNestControllers(sourceClass, currentPath, parentClass) {
56
+ const metadata = Reflect.getMetadata(HTTP_CONTROLLER_METADATA, sourceClass);
27
57
  if (!metadata)
28
58
  return;
29
59
  const newClass = {
30
- [source.name]: class extends source {
60
+ [sourceClass.name]: class extends sourceClass {
31
61
  },
32
- }[source.name];
62
+ }[sourceClass.name];
63
+ /** Copy metadata keys from source class to new one */
64
+ let metadataKeys;
65
+ if (parentClass) {
66
+ OpraNestAdapter.copyDecoratorMetadataToChild(newClass, parentClass);
67
+ }
33
68
  const newPath = metadata.path ? nodePath.join(currentPath, metadata.path) : currentPath;
34
69
  const adapter = this;
35
70
  /** Inject exception filter */
36
71
  UseFilters(new OpraExceptionFilter(adapter))(newClass);
37
72
  Controller()(newClass);
38
- this.controllers.push(newClass);
73
+ this.nestControllers.push(newClass);
39
74
  if (metadata.operations) {
40
75
  for (const [k, v] of Object.entries(metadata.operations)) {
41
- const operationHandler = source.prototype[k];
76
+ const operationHandler = sourceClass.prototype[k];
42
77
  Object.defineProperty(newClass.prototype, k, {
43
78
  writable: true,
44
79
  /** NestJS handler method */
45
- async value(_req, _res) {
46
- const request = HttpIncoming.from(_req);
47
- const response = HttpOutgoing.from(_res);
80
+ async value(_req) {
48
81
  const api = adapter.document.api;
49
- const controller = api.findController(newClass);
82
+ const controller = api.findController(sourceClass);
50
83
  const operation = controller?.operations.get(k);
51
- if (!(operation && typeof operationHandler === 'function'))
84
+ const context = asMutable(_req.opraContext);
85
+ if (!(context && operation && typeof operationHandler === 'function')) {
52
86
  throw new NotFoundError({
53
- message: `No endpoint found for [${request.method}]${request.baseUrl}`,
87
+ message: `No endpoint found for [${_req.method}]${_req.baseUrl}`,
54
88
  details: {
55
- path: request.baseUrl,
56
- method: request.method,
89
+ path: _req.baseUrl,
90
+ method: _req.method,
57
91
  },
58
92
  });
59
- /** Create the HttpContext */
60
- const context = new HttpContext({
61
- adapter,
62
- platform: _req.route ? 'express' : 'fastify',
63
- platformArgs: {
64
- request,
65
- response,
66
- },
67
- request,
68
- response,
69
- operation,
70
- controller: operation.owner,
71
- controllerInstance: this,
72
- operationHandler,
73
- });
93
+ }
94
+ /** Configure the HttpContext */
95
+ context.adapter = adapter;
96
+ context.document = adapter.document;
97
+ context.operation = operation;
98
+ context.controller = operation.owner;
99
+ context.controllerInstance = this;
100
+ context.operationHandler = operationHandler;
74
101
  /** Handle request */
75
102
  await adapter[kHandler].handleRequest(context);
76
103
  },
77
104
  });
78
- Req()(newClass.prototype, k, 0);
79
- Res()(newClass.prototype, k, 1);
80
105
  /** Copy metadata keys from source function to new one */
81
- const metadataKeys = Reflect.getOwnMetadataKeys(operationHandler);
106
+ metadataKeys = Reflect.getOwnMetadataKeys(operationHandler);
82
107
  const newFn = newClass.prototype[k];
83
108
  for (const key of metadataKeys) {
84
109
  const m = Reflect.getMetadata(key, operationHandler);
85
110
  Reflect.defineMetadata(key, m, newFn);
86
111
  }
112
+ Req()(newClass.prototype, k, 0);
113
+ Res()(newClass.prototype, k, 1);
87
114
  const descriptor = Object.getOwnPropertyDescriptor(newClass.prototype, k);
88
115
  const operationPath = newPath + (v.path || '');
89
116
  switch (v.method || 'GET') {
@@ -119,6 +146,8 @@ export class OpraNestAdapter extends HttpAdapter {
119
146
  /** Call @Search decorator over new property */
120
147
  Search(operationPath)(newClass.prototype, k, descriptor);
121
148
  break;
149
+ default:
150
+ break;
122
151
  }
123
152
  }
124
153
  }
@@ -126,8 +155,22 @@ export class OpraNestAdapter extends HttpAdapter {
126
155
  for (const child of metadata.controllers) {
127
156
  if (!isConstructor(child))
128
157
  throw new TypeError('Controllers should be injectable a class');
129
- this._createNestControllers(child, newPath);
158
+ this._addToNestControllers(child, newPath, sourceClass);
130
159
  }
131
160
  }
132
161
  }
162
+ static copyDecoratorMetadataToChild(target, parent) {
163
+ const metadataKeys = Reflect.getOwnMetadataKeys(parent);
164
+ for (const key of metadataKeys) {
165
+ if (key === GUARDS_METADATA || key === INTERCEPTORS_METADATA || key === EXCEPTION_FILTERS_METADATA) {
166
+ const m1 = Reflect.getMetadata(key, target) || [];
167
+ const m2 = Reflect.getOwnMetadata(key, parent) || [];
168
+ Reflect.defineMetadata(key, [...m1, ...m2], target);
169
+ }
170
+ }
171
+ const subParent = Object.getPrototypeOf(parent.prototype).constructor;
172
+ if (subParent && subParent !== Object) {
173
+ this.copyDecoratorMetadataToChild(target, subParent);
174
+ }
175
+ }
133
176
  }
@@ -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": "1.0.0-alpha.2",
3
+ "version": "1.0.0-alpha.21",
4
4
  "description": "Opra NestJS module",
5
5
  "author": "Panates",
6
6
  "license": "MIT",
@@ -18,8 +18,8 @@
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
20
  "format": "prettier . --write --log-level=warn",
21
- "test": "jest",
22
- "cover": "jest --collect-coverage",
21
+ "test": "jest --passWithNoTests",
22
+ "cover": "jest --passWithNoTests --collect-coverage",
23
23
  "clean": "npm run clean:src && npm run clean:test && npm run clean:dist && npm run clean:cover",
24
24
  "clean:src": "ts-cleanup -s src --all",
25
25
  "clean:test": "ts-cleanup -s test --all",
@@ -27,21 +27,23 @@
27
27
  "clean:cover": "rimraf ../../coverage/client"
28
28
  },
29
29
  "dependencies": {
30
- "@opra/common": "^1.0.0-alpha.2",
31
- "@opra/core": "^1.0.0-alpha.2",
30
+ "@opra/common": "^1.0.0-alpha.21",
31
+ "@opra/core": "^1.0.0-alpha.21",
32
32
  "fast-tokenizer": "^1.3.0",
33
33
  "lodash.head": "^4.0.1",
34
34
  "reflect-metadata": "^0.2.2"
35
35
  },
36
36
  "peerDependencies": {
37
- "@nestjs/common": "^10.3.9",
38
- "@nestjs/core": "^10.3.9"
37
+ "@nestjs/common": "^10.3.10",
38
+ "@nestjs/core": "^10.3.10"
39
39
  },
40
40
  "devDependencies": {
41
- "@nestjs/platform-express": "^10.3.9",
42
- "@nestjs/testing": "^10.3.9",
41
+ "@nestjs/platform-express": "^10.3.10",
42
+ "@nestjs/testing": "^10.3.10",
43
43
  "@types/lodash.head": "^4.0.9",
44
44
  "filedirname": "^3.4.0",
45
+ "rxjs": "^7.8.1",
46
+ "supertest": "^7.0.0",
45
47
  "ts-gems": "^3.4.0"
46
48
  },
47
49
  "type": "module",
@@ -0,0 +1 @@
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,4 +1,6 @@
1
1
  import 'reflect-metadata';
2
2
  import './augmentation/nestjs.augmentation.js';
3
+ export * from './constants.js';
4
+ export * from './decorators/public.decorator.js';
3
5
  export * from './opra-http.module.js';
4
6
  export * from './opra-nestjs-adapter.js';
@@ -1,9 +1,10 @@
1
- import { DynamicModule, OnModuleDestroy } from '@nestjs/common';
2
- import type { OpraHttpModule } from './opra-http.module';
1
+ import { DynamicModule, MiddlewareConsumer, NestModule, OnModuleDestroy } from '@nestjs/common';
2
+ import type { OpraHttpModule } from './opra-http.module.js';
3
3
  import { OpraNestAdapter } from './opra-nestjs-adapter.js';
4
- export declare class OpraHttpCoreModule implements OnModuleDestroy {
4
+ export declare class OpraHttpCoreModule implements OnModuleDestroy, NestModule {
5
5
  protected opraAdapter: OpraNestAdapter;
6
6
  constructor(opraAdapter: OpraNestAdapter);
7
- static forRoot(options: OpraHttpModule.Options): DynamicModule;
7
+ configure(consumer: MiddlewareConsumer): void;
8
+ static forRoot(init: OpraHttpModule.Initiator, options?: OpraHttpModule.Options): DynamicModule;
8
9
  onModuleDestroy(): Promise<void>;
9
10
  }
@@ -1,16 +1,20 @@
1
1
  import { DynamicModule } from '@nestjs/common';
2
2
  import { ApiDocumentFactory } from '@opra/common';
3
3
  export declare namespace OpraHttpModule {
4
- interface Options extends Pick<DynamicModule, 'imports' | 'providers' | 'exports' | 'controllers'>, Pick<ApiDocumentFactory.InitArguments, 'types' | 'references' | 'info'> {
4
+ interface Initiator extends Pick<DynamicModule, 'imports' | 'providers' | 'exports' | 'controllers'>, Pick<ApiDocumentFactory.InitArguments, 'types' | 'references' | 'info'> {
5
5
  id?: any;
6
6
  name: string;
7
+ }
8
+ interface Options {
7
9
  basePath?: string;
10
+ schemaRouteIsPublic?: boolean;
8
11
  }
9
12
  }
10
13
  export declare class OpraHttpModule {
11
14
  /**
12
15
  *
16
+ * @param init
13
17
  * @param options
14
18
  */
15
- static forRoot(options: OpraHttpModule.Options): DynamicModule;
19
+ static forRoot(init: OpraHttpModule.Initiator, options?: OpraHttpModule.Options): DynamicModule;
16
20
  }
@@ -1,10 +1,13 @@
1
1
  import { Type } from '@nestjs/common';
2
2
  import { HttpAdapter } from '@opra/core';
3
- import type { OpraHttpModule } from './opra-http.module';
3
+ import type { OpraHttpModule } from './opra-http.module.js';
4
4
  export declare const kHandler: unique symbol;
5
5
  export declare class OpraNestAdapter extends HttpAdapter {
6
- readonly controllers: Type[];
7
- constructor(options: OpraHttpModule.Options);
6
+ readonly nestControllers: Type[];
7
+ readonly options?: OpraHttpModule.Options;
8
+ constructor(init: OpraHttpModule.Initiator, options?: OpraHttpModule.Options);
8
9
  close(): Promise<void>;
9
- protected _createNestControllers(source: Type, currentPath: string): void;
10
+ protected _addRootController(basePath: string): void;
11
+ protected _addToNestControllers(sourceClass: Type, currentPath: string, parentClass?: Type): void;
12
+ static copyDecoratorMetadataToChild(target: Type, parent: Type): void;
10
13
  }
@@ -0,0 +1,5 @@
1
+ import { NestMiddleware } from '@nestjs/common';
2
+ import type { NextFunction, Request, Response } from 'express';
3
+ export declare class OpraMiddleware implements NestMiddleware {
4
+ use(req: Request, res: Response, next: NextFunction): void;
5
+ }