vovk 3.0.0-draft.65 → 3.0.0-draft.69

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.
@@ -17,7 +17,12 @@ const defaultFetcher = async ({ httpMethod, getEndpoint, validate, defaultHandle
17
17
  if (e instanceof HttpException_1.HttpException)
18
18
  throw e;
19
19
  // otherwise, throw HttpException with status 0
20
- throw new HttpException_1.HttpException(types_1.HttpStatus.NULL, e.message ?? exports.DEFAULT_ERROR_MESSAGE, { body, query, params, endpoint });
20
+ throw new HttpException_1.HttpException(types_1.HttpStatus.NULL, e.message ?? exports.DEFAULT_ERROR_MESSAGE, {
21
+ body,
22
+ query,
23
+ params,
24
+ endpoint,
25
+ });
21
26
  }
22
27
  }
23
28
  const init = {
@@ -36,7 +41,12 @@ const defaultFetcher = async ({ httpMethod, getEndpoint, validate, defaultHandle
36
41
  }
37
42
  catch (e) {
38
43
  // handle network errors
39
- throw new HttpException_1.HttpException(types_1.HttpStatus.NULL, e?.message ?? exports.DEFAULT_ERROR_MESSAGE, { body, query, params, endpoint });
44
+ throw new HttpException_1.HttpException(types_1.HttpStatus.NULL, e?.message ?? exports.DEFAULT_ERROR_MESSAGE, {
45
+ body,
46
+ query,
47
+ params,
48
+ endpoint,
49
+ });
40
50
  }
41
51
  const contentType = response.headers.get('content-type');
42
52
  if (contentType?.startsWith('application/json')) {
@@ -51,7 +51,7 @@ export type VovkClient<T, OPTS extends {
51
51
  }> = OmitNever<VovkClientWithNever<T, OPTS>>;
52
52
  export type VovkClientFetcher<OPTS extends Record<string, KnownAny> = Record<string, never>, T = KnownAny> = (options: {
53
53
  name: keyof T;
54
- httpMethod: HttpMethod;
54
+ httpMethod: `${HttpMethod}`;
55
55
  getEndpoint: (data: {
56
56
  apiRoot: string;
57
57
  params: {
@@ -19,6 +19,7 @@ function createDecorator(handler, initHandler) {
19
19
  ...handlerSchema,
20
20
  // avoid override of path and httpMethod
21
21
  ...(initResult?.validation ? { validation: initResult.validation } : {}),
22
+ ...(initResult?.openapi ? { openapi: initResult.openapi } : {}),
22
23
  ...(initResult?.custom ? { custom: initResult.custom } : {}),
23
24
  },
24
25
  };
package/dist/index.d.ts CHANGED
@@ -1,12 +1,13 @@
1
1
  import { createVovkApp } from './createVovkApp';
2
2
  import { HttpStatus as HttpStatus, HttpMethod as HttpMethod, type KnownAny, type VovkErrorResponse, type VovkRequest, type VovkBody, type VovkQuery, type VovkParams, type VovkReturnType, type VovkYieldType, type VovkControllerBody, type VovkControllerQuery, type VovkControllerParams, type VovkControllerYieldType, type VovkSchema, type VovkControllerSchema, type VovkHandlerSchema } from './types';
3
3
  import { type VovkClient, type VovkClientOptions, type VovkClientFetcher, type VovkDefaultFetcherOptions, type VovkValidateOnClient, type VovkStreamAsyncIterable, createRPC } from './client';
4
+ import { openapi } from './openapi';
4
5
  import { HttpException } from './HttpException';
5
6
  import { createDecorator } from './createDecorator';
6
7
  import { StreamJSONResponse } from './StreamJSONResponse';
7
8
  import { generateStaticAPI } from './utils/generateStaticAPI';
8
9
  import { setClientValidatorsForHandler } from './utils/setClientValidatorsForHandler';
9
- 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, 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, };
10
11
  export declare const get: {
11
12
  (givenPath?: string | undefined, options?: import("./types").DecoratorOptions | undefined): ReturnType<(givenPath?: string, options?: import("./types").DecoratorOptions) => (givenTarget: KnownAny, propertyKey: string) => void>;
12
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.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.setClientValidatorsForHandler = 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");
@@ -9,6 +9,8 @@ Object.defineProperty(exports, "HttpStatus", { enumerable: true, get: function (
9
9
  Object.defineProperty(exports, "HttpMethod", { enumerable: true, get: function () { return types_1.HttpMethod; } });
10
10
  const client_1 = require("./client");
11
11
  Object.defineProperty(exports, "createRPC", { enumerable: true, get: function () { return client_1.createRPC; } });
12
+ const openapi_1 = require("./openapi");
13
+ Object.defineProperty(exports, "openapi", { enumerable: true, get: function () { return openapi_1.openapi; } });
12
14
  const HttpException_1 = require("./HttpException");
13
15
  Object.defineProperty(exports, "HttpException", { enumerable: true, get: function () { return HttpException_1.HttpException; } });
14
16
  const createDecorator_1 = require("./createDecorator");
@@ -0,0 +1,3 @@
1
+ import type { OpenAPIObject } from 'openapi3-ts/oas31';
2
+ import type { VovkSchema } from '../types';
3
+ export declare function fromSchema(apiRoot: string, vovkSchema: Record<string, VovkSchema>, extendWith?: Partial<OpenAPIObject>): OpenAPIObject;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fromSchema = fromSchema;
4
+ function fromSchema(apiRoot, vovkSchema, extendWith) {
5
+ const paths = {};
6
+ for (const [segmentName, schema] of Object.entries(vovkSchema)) {
7
+ for (const c of Object.values(schema.controllers)) {
8
+ for (const h of Object.values(c.handlers)) {
9
+ if (h.openapi) {
10
+ const path = '/' + [apiRoot.replace(/^\/+|\/+$/g, ''), segmentName, c.prefix, h.path].filter(Boolean).join('/');
11
+ paths[path] = paths[path] ?? {};
12
+ paths[path][h.httpMethod.toLowerCase()] = { ...h.openapi };
13
+ }
14
+ }
15
+ }
16
+ }
17
+ return {
18
+ openapi: '3.1.0',
19
+ paths,
20
+ info: extendWith?.info ?? {
21
+ title: 'API',
22
+ version: '1.0.0',
23
+ },
24
+ ...extendWith,
25
+ };
26
+ }
@@ -0,0 +1 @@
1
+ export { openapi } from './openapi';
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.openapi = void 0;
4
+ var openapi_1 = require("./openapi");
5
+ Object.defineProperty(exports, "openapi", { enumerable: true, get: function () { return openapi_1.openapi; } });
@@ -0,0 +1,10 @@
1
+ import type { OperationObject } from 'openapi3-ts/oas31';
2
+ import { fromSchema } from './fromSchema';
3
+ type OperationObjectWithCustomProperties = OperationObject & {
4
+ [key in `${'x' | 'X'}-${string}`]: any;
5
+ };
6
+ declare const openapiDecorator: (openAPIOperationObject?: OperationObjectWithCustomProperties | undefined) => (target: import("..").KnownAny, propertyKey: string) => void;
7
+ export declare const openapi: typeof openapiDecorator & {
8
+ fromSchema: typeof fromSchema;
9
+ };
10
+ export {};
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.openapi = void 0;
4
+ const createDecorator_1 = require("../createDecorator");
5
+ const fromSchema_1 = require("./fromSchema");
6
+ const openapiDecorator = (0, createDecorator_1.createDecorator)(null, (openAPIOperationObject = {}) => {
7
+ return (handlerSchema) => ({
8
+ ...handlerSchema,
9
+ openapi: {
10
+ ...handlerSchema?.openapi,
11
+ ...openAPIOperationObject,
12
+ },
13
+ });
14
+ });
15
+ exports.openapi = openapiDecorator;
16
+ exports.openapi.fromSchema = fromSchema_1.fromSchema;
package/dist/types.d.ts CHANGED
@@ -1,15 +1,17 @@
1
1
  import type { NextRequest } from 'next/server';
2
+ import type { OperationObject } from 'openapi3-ts/oas31';
2
3
  import type { StreamJSONResponse } from './StreamJSONResponse';
3
4
  import { VovkStreamAsyncIterable } from './client/types';
4
5
  export type KnownAny = any;
5
6
  export type StaticClass = Function;
6
7
  export type VovkHandlerSchema = {
7
8
  path: string;
8
- httpMethod: HttpMethod;
9
+ httpMethod: `${HttpMethod}`;
9
10
  validation?: {
10
11
  query?: KnownAny;
11
12
  body?: KnownAny;
12
13
  };
14
+ openapi?: OperationObject;
13
15
  custom?: Record<string, KnownAny>;
14
16
  };
15
17
  export type VovkControllerSchema = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vovk",
3
- "version": "3.0.0-draft.65",
3
+ "version": "3.0.0-draft.69",
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": {
@@ -27,5 +27,8 @@
27
27
  "homepage": "https://vovk.dev",
28
28
  "peerDependencies": {
29
29
  "next": "*"
30
+ },
31
+ "optionalDependencies": {
32
+ "openapi3-ts": "^4.4.0"
30
33
  }
31
34
  }
package/src/VovkApp.ts CHANGED
@@ -87,11 +87,7 @@ export class VovkApp {
87
87
  );
88
88
  };
89
89
 
90
- #callMethod = async (
91
- httpMethod: HttpMethod,
92
- nextReq: NextRequest,
93
- params: Record<string, string[]>
94
- ) => {
90
+ #callMethod = async (httpMethod: HttpMethod, nextReq: NextRequest, params: Record<string, string[]>) => {
95
91
  const req = nextReq as unknown as VovkRequest;
96
92
  const controllers = this.routes[httpMethod];
97
93
  const methodParams: Record<string, string> = {};
@@ -19,7 +19,12 @@ const defaultFetcher: VovkClientFetcher<VovkDefaultFetcherOptions> = async (
19
19
  // if HttpException is thrown, rethrow it
20
20
  if (e instanceof HttpException) throw e;
21
21
  // otherwise, throw HttpException with status 0
22
- throw new HttpException(HttpStatus.NULL, (e as Error).message ?? DEFAULT_ERROR_MESSAGE, { body, query, params, endpoint });
22
+ throw new HttpException(HttpStatus.NULL, (e as Error).message ?? DEFAULT_ERROR_MESSAGE, {
23
+ body,
24
+ query,
25
+ params,
26
+ endpoint,
27
+ });
23
28
  }
24
29
  }
25
30
 
@@ -40,7 +45,12 @@ const defaultFetcher: VovkClientFetcher<VovkDefaultFetcherOptions> = async (
40
45
  response = await fetch(endpoint, init);
41
46
  } catch (e) {
42
47
  // handle network errors
43
- throw new HttpException(HttpStatus.NULL, (e as Error)?.message ?? DEFAULT_ERROR_MESSAGE, { body, query, params, endpoint });
48
+ throw new HttpException(HttpStatus.NULL, (e as Error)?.message ?? DEFAULT_ERROR_MESSAGE, {
49
+ body,
50
+ query,
51
+ params,
52
+ endpoint,
53
+ });
44
54
  }
45
55
 
46
56
  const contentType = response.headers.get('content-type');
@@ -81,7 +81,7 @@ export type VovkClient<T, OPTS extends { [key: string]: KnownAny }> = OmitNever<
81
81
  export type VovkClientFetcher<OPTS extends Record<string, KnownAny> = Record<string, never>, T = KnownAny> = (
82
82
  options: {
83
83
  name: keyof T;
84
- httpMethod: HttpMethod;
84
+ httpMethod: `${HttpMethod}`;
85
85
  getEndpoint: (data: {
86
86
  apiRoot: string;
87
87
  params: { [key: string]: string };
@@ -35,6 +35,7 @@ export function createDecorator<ARGS extends unknown[], REQUEST = VovkRequest>(
35
35
  ...handlerSchema,
36
36
  // avoid override of path and httpMethod
37
37
  ...(initResult?.validation ? { validation: initResult.validation } : {}),
38
+ ...(initResult?.openapi ? { openapi: initResult.openapi } : {}),
38
39
  ...(initResult?.custom ? { custom: initResult.custom } : {}),
39
40
  },
40
41
  };
package/src/index.ts CHANGED
@@ -27,6 +27,7 @@ import {
27
27
  type VovkStreamAsyncIterable,
28
28
  createRPC,
29
29
  } from './client';
30
+ import { openapi } from './openapi';
30
31
  import { HttpException } from './HttpException';
31
32
  import { createDecorator } from './createDecorator';
32
33
  import { StreamJSONResponse } from './StreamJSONResponse';
@@ -63,6 +64,7 @@ export {
63
64
  createDecorator,
64
65
  createRPC,
65
66
  generateStaticAPI,
67
+ openapi,
66
68
  setClientValidatorsForHandler,
67
69
  };
68
70
 
@@ -0,0 +1,33 @@
1
+ import type { OpenAPIObject, PathsObject } from 'openapi3-ts/oas31';
2
+ import type { HttpMethod, VovkSchema } from '../types';
3
+
4
+ export function fromSchema(
5
+ apiRoot: string,
6
+ vovkSchema: Record<string, VovkSchema>,
7
+ extendWith?: Partial<OpenAPIObject>
8
+ ): OpenAPIObject {
9
+ const paths: PathsObject = {};
10
+
11
+ for (const [segmentName, schema] of Object.entries(vovkSchema)) {
12
+ for (const c of Object.values(schema.controllers)) {
13
+ for (const h of Object.values(c.handlers)) {
14
+ if (h.openapi) {
15
+ const path =
16
+ '/' + [apiRoot.replace(/^\/+|\/+$/g, ''), segmentName, c.prefix, h.path].filter(Boolean).join('/');
17
+ paths[path] = paths[path] ?? {};
18
+ paths[path][h.httpMethod.toLowerCase() as Lowercase<HttpMethod>] = { ...h.openapi };
19
+ }
20
+ }
21
+ }
22
+ }
23
+
24
+ return {
25
+ openapi: '3.1.0',
26
+ paths,
27
+ info: extendWith?.info ?? {
28
+ title: 'API',
29
+ version: '1.0.0',
30
+ },
31
+ ...extendWith,
32
+ };
33
+ }
@@ -0,0 +1 @@
1
+ export { openapi } from './openapi';
@@ -0,0 +1,23 @@
1
+ import type { OperationObject } from 'openapi3-ts/oas31';
2
+ import { createDecorator } from '../createDecorator';
3
+ import { fromSchema } from './fromSchema';
4
+
5
+ type OperationObjectWithCustomProperties = OperationObject & {
6
+ [key in `${'x' | 'X'}-${string}`]: any;
7
+ }
8
+
9
+ const openapiDecorator = createDecorator(null, (openAPIOperationObject: OperationObjectWithCustomProperties = {}) => {
10
+ return (handlerSchema) => ({
11
+ ...handlerSchema,
12
+ openapi: {
13
+ ...handlerSchema?.openapi,
14
+ ...openAPIOperationObject,
15
+ },
16
+ });
17
+ });
18
+
19
+ export const openapi = openapiDecorator as typeof openapiDecorator & {
20
+ fromSchema: typeof fromSchema;
21
+ };
22
+
23
+ openapi.fromSchema = fromSchema;
package/src/types.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { NextRequest } from 'next/server';
2
+ import type { OperationObject } from 'openapi3-ts/oas31';
2
3
  import type { StreamJSONResponse } from './StreamJSONResponse';
3
4
  import { VovkStreamAsyncIterable } from './client/types';
4
5
 
@@ -8,8 +9,9 @@ export type StaticClass = Function; // eslint-disable-line @typescript-eslint/no
8
9
 
9
10
  export type VovkHandlerSchema = {
10
11
  path: string;
11
- httpMethod: HttpMethod;
12
+ httpMethod: `${HttpMethod}`;
12
13
  validation?: { query?: KnownAny; body?: KnownAny };
14
+ openapi?: OperationObject;
13
15
  custom?: Record<string, KnownAny>;
14
16
  };
15
17