vovk 3.0.0-draft.70 → 3.0.0-draft.71

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.
@@ -10,6 +10,18 @@ function createDecorator(handler, initHandler) {
10
10
  throw new Error(`Unable to decorate: ${propertyKey} is not a function`);
11
11
  }
12
12
  const sourceMethod = originalMethod._sourceMethod ?? originalMethod;
13
+ const method = function method(req, params) {
14
+ const next = async () => {
15
+ return (await originalMethod.call(controller, req, params));
16
+ };
17
+ return handler ? handler.call(controller, req, next, ...args) : next();
18
+ };
19
+ controller[propertyKey] = method;
20
+ method._controller = controller;
21
+ method._sourceMethod = sourceMethod;
22
+ // TODO define internal method type
23
+ originalMethod._controller = controller;
24
+ originalMethod?._onSettled?.(controller);
13
25
  const handlerSchema = controller._handlers?.[propertyKey] ?? null;
14
26
  const initResultReturn = initHandler?.call(controller, ...args);
15
27
  const initResult = typeof initResultReturn === 'function' ? initResultReturn(handlerSchema) : initResultReturn;
@@ -23,17 +35,6 @@ function createDecorator(handler, initHandler) {
23
35
  ...(initResult?.custom ? { custom: initResult.custom } : {}),
24
36
  },
25
37
  };
26
- const method = function method(req, params) {
27
- const next = async () => {
28
- return (await originalMethod.call(controller, req, params));
29
- };
30
- return handler ? handler.call(controller, req, next, ...args) : next();
31
- };
32
- method._controller = controller;
33
- // TODO define internal method type
34
- originalMethod._controller = controller;
35
- controller[propertyKey] = method;
36
- method._sourceMethod = sourceMethod;
37
38
  };
38
39
  };
39
40
  }
package/dist/index.d.ts CHANGED
@@ -6,8 +6,8 @@ import { HttpException } from './HttpException';
6
6
  import { createDecorator } from './createDecorator';
7
7
  import { StreamJSONResponse } from './StreamJSONResponse';
8
8
  import { generateStaticAPI } from './utils/generateStaticAPI';
9
- import { setClientValidatorsForHandler } from './utils/setClientValidatorsForHandler';
10
- export { type KnownAny, type VovkClient, type VovkClientFetcher, type VovkDefaultFetcherOptions, type VovkStreamAsyncIterable, type VovkValidateOnClient, type VovkSchema, type VovkErrorResponse, type VovkRequest, type VovkControllerBody, type VovkControllerQuery, type VovkControllerParams, type VovkControllerYieldType, type VovkBody, type VovkQuery, type VovkParams, type VovkYieldType, type VovkReturnType, type VovkClientOptions, type VovkControllerSchema, type VovkHandlerSchema, StreamJSONResponse, HttpException, HttpStatus, HttpMethod, createVovkApp, createDecorator, createRPC, generateStaticAPI, openapi, setClientValidatorsForHandler, };
9
+ import { setHandlerValidation } from './utils/setHandlerValidation';
10
+ export { type KnownAny, type VovkClient, type VovkClientFetcher, type VovkDefaultFetcherOptions, type VovkStreamAsyncIterable, type VovkValidateOnClient, type VovkSchema, type VovkErrorResponse, type VovkRequest, type VovkControllerBody, type VovkControllerQuery, type VovkControllerParams, type VovkControllerYieldType, type VovkBody, type VovkQuery, type VovkParams, type VovkYieldType, type VovkReturnType, type VovkClientOptions, type VovkControllerSchema, type VovkHandlerSchema, StreamJSONResponse, HttpException, HttpStatus, HttpMethod, createVovkApp, createDecorator, createRPC, generateStaticAPI, openapi, setHandlerValidation, };
11
11
  export declare const get: {
12
12
  (givenPath?: string | undefined, options?: import("./types").DecoratorOptions | undefined): ReturnType<(givenPath?: string, options?: import("./types").DecoratorOptions) => (givenTarget: KnownAny, propertyKey: string) => void>;
13
13
  auto: (options?: import("./types").DecoratorOptions) => (givenTarget: KnownAny, propertyKey: string) => void;
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  var _a;
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.initVovk = exports.prefix = exports.options = exports.head = exports.del = exports.patch = exports.put = exports.post = exports.get = exports.setClientValidatorsForHandler = exports.openapi = exports.generateStaticAPI = exports.createRPC = exports.createDecorator = exports.createVovkApp = exports.HttpMethod = exports.HttpStatus = exports.HttpException = exports.StreamJSONResponse = void 0;
4
+ exports.initVovk = exports.prefix = exports.options = exports.head = exports.del = exports.patch = exports.put = exports.post = exports.get = exports.setHandlerValidation = exports.openapi = exports.generateStaticAPI = exports.createRPC = exports.createDecorator = exports.createVovkApp = exports.HttpMethod = exports.HttpStatus = exports.HttpException = exports.StreamJSONResponse = void 0;
5
5
  const createVovkApp_1 = require("./createVovkApp");
6
6
  Object.defineProperty(exports, "createVovkApp", { enumerable: true, get: function () { return createVovkApp_1.createVovkApp; } });
7
7
  const types_1 = require("./types");
@@ -19,6 +19,6 @@ const StreamJSONResponse_1 = require("./StreamJSONResponse");
19
19
  Object.defineProperty(exports, "StreamJSONResponse", { enumerable: true, get: function () { return StreamJSONResponse_1.StreamJSONResponse; } });
20
20
  const generateStaticAPI_1 = require("./utils/generateStaticAPI");
21
21
  Object.defineProperty(exports, "generateStaticAPI", { enumerable: true, get: function () { return generateStaticAPI_1.generateStaticAPI; } });
22
- const setClientValidatorsForHandler_1 = require("./utils/setClientValidatorsForHandler");
23
- Object.defineProperty(exports, "setClientValidatorsForHandler", { enumerable: true, get: function () { return setClientValidatorsForHandler_1.setClientValidatorsForHandler; } });
22
+ const setHandlerValidation_1 = require("./utils/setHandlerValidation");
23
+ Object.defineProperty(exports, "setHandlerValidation", { enumerable: true, get: function () { return setHandlerValidation_1.setHandlerValidation; } });
24
24
  _a = (0, createVovkApp_1.createVovkApp)(), exports.get = _a.get, exports.post = _a.post, exports.put = _a.put, exports.patch = _a.patch, exports.del = _a.del, exports.head = _a.head, exports.options = _a.options, exports.prefix = _a.prefix, exports.initVovk = _a.initVovk;
@@ -8,6 +8,60 @@ const openapiDecorator = (0, createDecorator_1.createDecorator)(null, (openAPIOp
8
8
  ...handlerSchema,
9
9
  openapi: {
10
10
  ...handlerSchema?.openapi,
11
+ ...(handlerSchema?.validation?.output &&
12
+ 'type' in handlerSchema.validation.output &&
13
+ 'properties' in handlerSchema.validation.output
14
+ ? {
15
+ responses: {
16
+ 200: {
17
+ description: 'description' in handlerSchema.validation.output
18
+ ? handlerSchema.validation.output.description
19
+ : 'Success',
20
+ content: {
21
+ 'application/json': {
22
+ schema: handlerSchema.validation.output,
23
+ },
24
+ },
25
+ },
26
+ },
27
+ }
28
+ : {}),
29
+ ...(handlerSchema?.validation?.body &&
30
+ 'type' in handlerSchema.validation.body &&
31
+ 'properties' in handlerSchema.validation.body
32
+ ? {
33
+ requestBody: {
34
+ description: 'description' in handlerSchema.validation.body
35
+ ? handlerSchema.validation.body.description
36
+ : 'Request body',
37
+ required: true,
38
+ content: {
39
+ 'application/json': {
40
+ schema: handlerSchema.validation.body,
41
+ },
42
+ },
43
+ },
44
+ }
45
+ : {}),
46
+ ...(handlerSchema?.validation?.query &&
47
+ 'type' in handlerSchema.validation.query &&
48
+ 'properties' in handlerSchema.validation.query
49
+ ? {
50
+ parameters: Object.entries(handlerSchema.validation.query.properties)
51
+ .filter(([, propSchema]) => propSchema.type === 'string')
52
+ .map(([propName, propSchema]) => ({
53
+ name: propName,
54
+ in: 'query',
55
+ description: propSchema.description || '',
56
+ required: handlerSchema.validation?.query.required
57
+ ? handlerSchema.validation.query.required.includes(propName)
58
+ : false,
59
+ schema: {
60
+ type: 'string',
61
+ },
62
+ })),
63
+ }
64
+ : {}),
11
65
  ...openAPIOperationObject,
12
66
  },
13
67
  });
package/dist/types.d.ts CHANGED
@@ -10,6 +10,7 @@ export type VovkHandlerSchema = {
10
10
  validation?: {
11
11
  query?: KnownAny;
12
12
  body?: KnownAny;
13
+ output?: KnownAny;
13
14
  };
14
15
  openapi?: OperationObject;
15
16
  custom?: Record<string, KnownAny>;
@@ -0,0 +1,4 @@
1
+ import type { KnownAny, VovkController, VovkHandlerSchema } from '../types';
2
+ export declare function setHandlerValidation(h: ((...args: KnownAny[]) => KnownAny) & {
3
+ _onSettled?: (controller: VovkController) => void;
4
+ }, validation: Pick<Exclude<VovkHandlerSchema['validation'], undefined>, 'body' | 'query' | 'output'>): Promise<void>;
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.setHandlerValidation = setHandlerValidation;
4
+ async function setHandlerValidation(h, validation) {
5
+ h._onSettled = (controller) => {
6
+ if (!controller) {
7
+ throw new Error('Error setting client validators. Controller not found. Did you forget to use an HTTP decorator?');
8
+ }
9
+ const handlerName = Object.getOwnPropertyNames(controller).find((key) => controller[key]._sourceMethod === h);
10
+ if (!handlerName) {
11
+ throw new Error('Error setting client validators. Handler not found.');
12
+ }
13
+ controller._handlers = {
14
+ ...controller._handlers,
15
+ [handlerName]: {
16
+ ...controller._handlers[handlerName],
17
+ validation,
18
+ },
19
+ };
20
+ };
21
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vovk",
3
- "version": "3.0.0-draft.70",
3
+ "version": "3.0.0-draft.71",
4
4
  "main": "dist/index.js",
5
5
  "description": "RESTful RPC for Next.js - Transforms Next.js into a powerful REST API platform with RPC capabilities.",
6
6
  "repository": {
@@ -18,13 +18,30 @@ export function createDecorator<ARGS extends unknown[], REQUEST = VovkRequest>(
18
18
  const controller = target as VovkController;
19
19
 
20
20
  const originalMethod = controller[propertyKey] as ((...args: KnownAny) => KnownAny) & {
21
- _sourceMethod?: (...args: KnownAny) => KnownAny;
21
+ _sourceMethod?: ((...args: KnownAny) => KnownAny);
22
+ _onSettled?: (controller: VovkController) => void;
22
23
  };
23
24
  if (typeof originalMethod !== 'function') {
24
25
  throw new Error(`Unable to decorate: ${propertyKey} is not a function`);
25
26
  }
26
27
  const sourceMethod = originalMethod._sourceMethod ?? originalMethod;
27
28
 
29
+ const method = function method(req: REQUEST, params?: unknown) {
30
+ const next: Next = async () => {
31
+ return (await originalMethod.call(controller, req, params)) as unknown;
32
+ };
33
+
34
+ return handler ? handler.call(controller, req, next, ...args) : next();
35
+ };
36
+
37
+ controller[propertyKey] = method;
38
+
39
+ method._controller = controller;
40
+ method._sourceMethod = sourceMethod;
41
+ // TODO define internal method type
42
+ (originalMethod as unknown as { _controller: VovkController })._controller = controller;
43
+ originalMethod?._onSettled?.(controller);
44
+
28
45
  const handlerSchema: VovkHandlerSchema | null = controller._handlers?.[propertyKey] ?? null;
29
46
  const initResultReturn = initHandler?.call(controller, ...args);
30
47
  const initResult = typeof initResultReturn === 'function' ? initResultReturn(handlerSchema) : initResultReturn;
@@ -39,23 +56,6 @@ export function createDecorator<ARGS extends unknown[], REQUEST = VovkRequest>(
39
56
  ...(initResult?.custom ? { custom: initResult.custom } : {}),
40
57
  },
41
58
  };
42
-
43
- const method = function method(req: REQUEST, params?: unknown) {
44
- const next: Next = async () => {
45
- return (await originalMethod.call(controller, req, params)) as unknown;
46
- };
47
-
48
- return handler ? handler.call(controller, req, next, ...args) : next();
49
- };
50
-
51
- method._controller = controller;
52
-
53
- // TODO define internal method type
54
- (originalMethod as unknown as { _controller: VovkController })._controller = controller;
55
-
56
- controller[propertyKey] = method;
57
-
58
- method._sourceMethod = sourceMethod;
59
59
  };
60
60
  };
61
61
  }
package/src/index.ts CHANGED
@@ -32,7 +32,7 @@ import { HttpException } from './HttpException';
32
32
  import { createDecorator } from './createDecorator';
33
33
  import { StreamJSONResponse } from './StreamJSONResponse';
34
34
  import { generateStaticAPI } from './utils/generateStaticAPI';
35
- import { setClientValidatorsForHandler } from './utils/setClientValidatorsForHandler';
35
+ import { setHandlerValidation } from './utils/setHandlerValidation';
36
36
 
37
37
  export {
38
38
  type KnownAny,
@@ -65,7 +65,7 @@ export {
65
65
  createRPC,
66
66
  generateStaticAPI,
67
67
  openapi,
68
- setClientValidatorsForHandler,
68
+ setHandlerValidation,
69
69
  };
70
70
 
71
71
  export const { get, post, put, patch, del, head, options, prefix, initVovk } = createVovkApp();
@@ -4,13 +4,75 @@ import { fromSchema } from './fromSchema';
4
4
 
5
5
  type OperationObjectWithCustomProperties = OperationObject & {
6
6
  [key in `${'x' | 'X'}-${string}`]: any;
7
- }
7
+ };
8
+
9
+ type SimpleJsonSchema = {
10
+ type: 'object';
11
+ properties: Record<string, any>;
12
+ required?: string[];
13
+ };
8
14
 
9
15
  const openapiDecorator = createDecorator(null, (openAPIOperationObject: OperationObjectWithCustomProperties = {}) => {
10
16
  return (handlerSchema) => ({
11
17
  ...handlerSchema,
12
18
  openapi: {
13
19
  ...handlerSchema?.openapi,
20
+ ...(handlerSchema?.validation?.output &&
21
+ 'type' in handlerSchema.validation.output &&
22
+ 'properties' in handlerSchema.validation.output
23
+ ? {
24
+ responses: {
25
+ 200: {
26
+ description:
27
+ 'description' in handlerSchema.validation.output
28
+ ? handlerSchema.validation.output.description
29
+ : 'Success',
30
+ content: {
31
+ 'application/json': {
32
+ schema: handlerSchema.validation.output,
33
+ },
34
+ },
35
+ },
36
+ },
37
+ }
38
+ : {}),
39
+ ...(handlerSchema?.validation?.body &&
40
+ 'type' in handlerSchema.validation.body &&
41
+ 'properties' in handlerSchema.validation.body
42
+ ? {
43
+ requestBody: {
44
+ description:
45
+ 'description' in handlerSchema.validation.body
46
+ ? handlerSchema.validation.body.description
47
+ : 'Request body',
48
+ required: true,
49
+ content: {
50
+ 'application/json': {
51
+ schema: handlerSchema.validation.body,
52
+ },
53
+ },
54
+ },
55
+ }
56
+ : {}),
57
+ ...(handlerSchema?.validation?.query &&
58
+ 'type' in handlerSchema.validation.query &&
59
+ 'properties' in handlerSchema.validation.query
60
+ ? {
61
+ parameters: Object.entries((handlerSchema.validation.query as SimpleJsonSchema).properties)
62
+ .filter(([, propSchema]) => propSchema.type === 'string')
63
+ .map(([propName, propSchema]) => ({
64
+ name: propName,
65
+ in: 'query',
66
+ description: propSchema.description || '',
67
+ required: handlerSchema.validation?.query.required
68
+ ? handlerSchema.validation.query.required.includes(propName)
69
+ : false,
70
+ schema: {
71
+ type: 'string',
72
+ },
73
+ })),
74
+ }
75
+ : {}),
14
76
  ...openAPIOperationObject,
15
77
  },
16
78
  });
package/src/types.ts CHANGED
@@ -10,7 +10,7 @@ export type StaticClass = Function; // eslint-disable-line @typescript-eslint/no
10
10
  export type VovkHandlerSchema = {
11
11
  path: string;
12
12
  httpMethod: string; // HttpMethod type makes JSON incompatible with VovkHandlerSchema type
13
- validation?: { query?: KnownAny; body?: KnownAny };
13
+ validation?: { query?: KnownAny; body?: KnownAny; output?: KnownAny };
14
14
  openapi?: OperationObject;
15
15
  custom?: Record<string, KnownAny>;
16
16
  };
@@ -0,0 +1,35 @@
1
+ import type { KnownAny, VovkController, VovkHandlerSchema } from '../types';
2
+
3
+ export async function setHandlerValidation(
4
+ h: ((...args: KnownAny[]) => KnownAny) & { _onSettled?: (controller: VovkController) => void },
5
+ validation: Pick<Exclude<VovkHandlerSchema['validation'], undefined>, 'body' | 'query' | 'output'>
6
+ ) {
7
+ h._onSettled = (controller) => {
8
+ if (!controller) {
9
+ throw new Error(
10
+ 'Error setting client validators. Controller not found. Did you forget to use an HTTP decorator?'
11
+ );
12
+ }
13
+
14
+ const handlerName = Object.getOwnPropertyNames(controller).find(
15
+ (key) =>
16
+ (
17
+ controller[key] as {
18
+ _sourceMethod?: unknown;
19
+ }
20
+ )._sourceMethod === h
21
+ );
22
+
23
+ if (!handlerName) {
24
+ throw new Error('Error setting client validators. Handler not found.');
25
+ }
26
+
27
+ controller._handlers = {
28
+ ...controller._handlers,
29
+ [handlerName]: {
30
+ ...controller._handlers[handlerName],
31
+ validation,
32
+ },
33
+ };
34
+ };
35
+ }
@@ -1,5 +0,0 @@
1
- import type { KnownAny } from '../types';
2
- export declare function setClientValidatorsForHandler(h: (...args: KnownAny[]) => KnownAny, validation: {
3
- body: unknown;
4
- query: unknown;
5
- }): Promise<void>;
@@ -1,26 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.setClientValidatorsForHandler = setClientValidatorsForHandler;
4
- function setClientValidatorsForHandler(h, validation) {
5
- return new Promise((resolve) => {
6
- // the setTimeout is necessary to ensure that the _controller is already defined
7
- setTimeout(() => {
8
- const controller = h._controller;
9
- if (!controller) {
10
- throw new Error('Error setting client validators. Controller not found. Did you forget to use an HTTP decorator?');
11
- }
12
- const handlerName = Object.getOwnPropertyNames(controller).find((key) => controller[key]._sourceMethod === h);
13
- if (!handlerName) {
14
- throw new Error('Error setting client validators. Handler not found.');
15
- }
16
- controller._handlers = {
17
- ...controller._handlers,
18
- [handlerName]: {
19
- ...controller._handlers[handlerName],
20
- validation,
21
- },
22
- };
23
- resolve();
24
- }, 0);
25
- });
26
- }
@@ -1,45 +0,0 @@
1
- import type { KnownAny, VovkController } from '../types';
2
-
3
- export function setClientValidatorsForHandler(
4
- h: (...args: KnownAny[]) => KnownAny,
5
- validation: {
6
- body: unknown;
7
- query: unknown;
8
- }
9
- ) {
10
- return new Promise<void>((resolve) => {
11
- // the setTimeout is necessary to ensure that the _controller is already defined
12
- setTimeout(() => {
13
- const controller = (h as unknown as { _controller: VovkController })._controller;
14
-
15
- if (!controller) {
16
- throw new Error(
17
- 'Error setting client validators. Controller not found. Did you forget to use an HTTP decorator?'
18
- );
19
- }
20
-
21
- const handlerName = Object.getOwnPropertyNames(controller).find(
22
- (key) =>
23
- (
24
- controller[key] as {
25
- _sourceMethod?: unknown;
26
- }
27
- )._sourceMethod === h
28
- );
29
-
30
- if (!handlerName) {
31
- throw new Error('Error setting client validators. Handler not found.');
32
- }
33
-
34
- controller._handlers = {
35
- ...controller._handlers,
36
- [handlerName]: {
37
- ...controller._handlers[handlerName],
38
- validation,
39
- },
40
- };
41
-
42
- resolve();
43
- }, 0);
44
- });
45
- }