vovk 3.0.0-draft.3 → 3.0.0-draft.31

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 CHANGED
@@ -28,7 +28,6 @@
28
28
  <a href="https://github.com/finom/vovk/actions/workflows/main.yml"><img src="https://github.com/finom/vovk/actions/workflows/main.yml/badge.svg" alt="Build status" /></a>
29
29
  </p>
30
30
 
31
-
32
31
  <br />
33
32
 
34
33
  Example back-end Controller Class:
@@ -37,7 +36,7 @@ Example back-end Controller Class:
37
36
  // /src/modules/post/PostController.ts
38
37
  import { get, prefix, type VovkRequest } from 'vovk';
39
38
  import PostService from './PostService';
40
-
39
+
41
40
  @prefix('posts')
42
41
  export default class PostController {
43
42
  /**
@@ -47,19 +46,19 @@ export default class PostController {
47
46
  @post(':postId/comments')
48
47
  static async createComment(
49
48
  // decorate NextRequest type with body and query types
50
- req: VovkRequest<
51
- { content: string; userId: string },
52
- { notificationType: 'push' | 'email' }
53
- >,
49
+ req: VovkRequest<{ content: string; userId: string }, { notificationType: 'push' | 'email' }>,
54
50
  { postId }: { postId: string } // params
55
51
  ) {
56
52
  // use standard Next.js API to get body and query
57
53
  const { content, userId } = await req.json();
58
54
  const notificationType = req.nextUrl.searchParams.get('notificationType');
59
-
55
+
60
56
  // perform the request to the database in a custom service
61
- return PostService.createComment({
62
- postId, content, userId, notificationType,
57
+ return PostService.createComment({
58
+ postId,
59
+ content,
60
+ userId,
61
+ notificationType,
63
62
  });
64
63
  }
65
64
  }
@@ -72,23 +71,25 @@ Example component that uses the auto-generated client library:
72
71
  import { useState } from 'react';
73
72
  import { PostController } from 'vovk-client';
74
73
  import type { VovkReturnType } from 'vovk';
75
-
74
+
76
75
  export default function Example() {
77
76
  const [response, setResponse] = useState<VovkReturnType<typeof PostController.createComment>>();
78
-
77
+
79
78
  return (
80
79
  <>
81
80
  <button
82
- onClick={async () => setResponse(
83
- await PostController.createComment({
84
- body: {
85
- content: 'Hello, World!',
86
- userId: '1',
87
- },
88
- params: { postId: '69' },
89
- query: { notificationType: 'push' }
90
- })
91
- )}
81
+ onClick={async () =>
82
+ setResponse(
83
+ await PostController.createComment({
84
+ body: {
85
+ content: 'Hello, World!',
86
+ userId: '1',
87
+ },
88
+ params: { postId: '69' },
89
+ query: { notificationType: 'push' },
90
+ })
91
+ )
92
+ }
92
93
  >
93
94
  Post a comment
94
95
  </button>
@@ -103,9 +104,9 @@ Alternatively, the resource can be fetched wit the regular `fetch` function:
103
104
  ```ts
104
105
  fetch('/api/posts/69?notificationType=push', {
105
106
  method: 'POST',
106
- body: JSON.stringify({
107
- content: 'Hello, World!',
108
- userId: '1',
107
+ body: JSON.stringify({
108
+ content: 'Hello, World!',
109
+ userId: '1',
109
110
  }),
110
- })
111
+ });
111
112
  ```
@@ -1,8 +1,9 @@
1
1
  import { _KnownAny as KnownAny, _StreamAbortMessage as StreamAbortMessage } from './types';
2
2
  import './utils/shim';
3
- export declare class _StreamResponse<T> extends Response {
3
+ export declare class _StreamJSONResponse<T> extends Response {
4
4
  static defaultHeaders: {
5
- 'Content-Type': string;
5
+ 'content-type': string;
6
+ 'x-vovk-stream': string;
6
7
  };
7
8
  isClosed: boolean;
8
9
  controller?: ReadableStreamDefaultController;
@@ -1,10 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports._StreamResponse = void 0;
3
+ exports._StreamJSONResponse = void 0;
4
4
  require("./utils/shim");
5
- class _StreamResponse extends Response {
5
+ class _StreamJSONResponse extends Response {
6
6
  static defaultHeaders = {
7
- 'Content-Type': 'text/plain; charset=utf-8',
7
+ 'content-type': 'text/plain; charset=utf-8',
8
+ 'x-vovk-stream': 'true',
8
9
  };
9
10
  isClosed = false;
10
11
  controller;
@@ -23,7 +24,7 @@ class _StreamResponse extends Response {
23
24
  });
24
25
  super(readableStream, {
25
26
  ...init,
26
- headers: init?.headers ?? _StreamResponse.defaultHeaders,
27
+ headers: init?.headers ?? _StreamJSONResponse.defaultHeaders,
27
28
  });
28
29
  this.readableStream = readableStream;
29
30
  this.encoder = encoder;
@@ -50,4 +51,4 @@ class _StreamResponse extends Response {
50
51
  this.close();
51
52
  }
52
53
  }
53
- exports._StreamResponse = _StreamResponse;
54
+ exports._StreamJSONResponse = _StreamJSONResponse;
@@ -1,8 +1,8 @@
1
1
  import { _HttpMethod as HttpMethod, _HttpStatus as HttpStatus, type _RouteHandler as RouteHandler, type _VovkController as VovkController, type _DecoratorOptions as DecoratorOptions, type _VovkRequest as VovkRequest } from './types';
2
- export declare class _Segment {
2
+ export declare class _VovkApp {
3
3
  #private;
4
4
  private static getHeadersFromOptions;
5
- _routes: Record<HttpMethod, Map<VovkController, Record<string, RouteHandler>>>;
5
+ routes: Record<HttpMethod, Map<VovkController, Record<string, RouteHandler>>>;
6
6
  GET: (req: VovkRequest, data: {
7
7
  params: Promise<Record<string, string[]>>;
8
8
  }) => Promise<Response>;
@@ -4,13 +4,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  var _a;
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports._Segment = void 0;
7
+ exports._VovkApp = void 0;
8
8
  const types_1 = require("./types");
9
9
  const HttpException_1 = require("./HttpException");
10
- const StreamResponse_1 = require("./StreamResponse");
10
+ const StreamJSONResponse_1 = require("./StreamJSONResponse");
11
11
  const reqQuery_1 = __importDefault(require("./utils/reqQuery"));
12
12
  const reqMeta_1 = __importDefault(require("./utils/reqMeta"));
13
- class _Segment {
13
+ const reqForm_1 = __importDefault(require("./utils/reqForm"));
14
+ class _VovkApp {
14
15
  static getHeadersFromOptions(options) {
15
16
  if (!options)
16
17
  return {};
@@ -25,7 +26,7 @@ class _Segment {
25
26
  };
26
27
  return headers;
27
28
  }
28
- _routes = {
29
+ routes = {
29
30
  GET: new Map(),
30
31
  POST: new Map(),
31
32
  PUT: new Map(),
@@ -50,15 +51,16 @@ class _Segment {
50
51
  },
51
52
  });
52
53
  };
53
- #respondWithError = (statusCode, message, options) => {
54
+ #respondWithError = (statusCode, message, options, cause) => {
54
55
  return this.respond(statusCode, {
56
+ cause,
55
57
  statusCode,
56
58
  message,
57
59
  isError: true,
58
60
  }, options);
59
61
  };
60
62
  #callMethod = async (httpMethod, req, params) => {
61
- const controllers = this._routes[httpMethod];
63
+ const controllers = this.routes[httpMethod];
62
64
  const methodParams = {};
63
65
  const path = params[Object.keys(params)[0]];
64
66
  const handlers = {};
@@ -127,6 +129,7 @@ class _Segment {
127
129
  body: () => req.json(),
128
130
  query: () => (0, reqQuery_1.default)(req),
129
131
  meta: (meta) => (0, reqMeta_1.default)(req, meta),
132
+ form: () => (0, reqForm_1.default)(req),
130
133
  };
131
134
  try {
132
135
  const result = await staticMethod.call(controller, req, methodParams);
@@ -137,9 +140,9 @@ class _Segment {
137
140
  (Reflect.has(result, Symbol.asyncIterator) &&
138
141
  typeof result[Symbol.asyncIterator] === 'function'));
139
142
  if (isIterator && !(result instanceof Array)) {
140
- const streamResponse = new StreamResponse_1._StreamResponse({
143
+ const streamResponse = new StreamJSONResponse_1._StreamJSONResponse({
141
144
  headers: {
142
- ...StreamResponse_1._StreamResponse.defaultHeaders,
145
+ ...StreamJSONResponse_1._StreamJSONResponse.defaultHeaders,
143
146
  ..._a.getHeadersFromOptions(staticMethod._options),
144
147
  },
145
148
  });
@@ -172,11 +175,11 @@ class _Segment {
172
175
  }
173
176
  if (err.message !== 'NEXT_REDIRECT' && err.message !== 'NEXT_NOT_FOUND') {
174
177
  const statusCode = err.statusCode ?? types_1._HttpStatus.INTERNAL_SERVER_ERROR;
175
- return this.#respondWithError(statusCode, err.message, staticMethod._options);
178
+ return this.#respondWithError(statusCode, err.message, staticMethod._options, err.cause);
176
179
  }
177
180
  throw e; // if NEXT_REDIRECT or NEXT_NOT_FOUND, rethrow it
178
181
  }
179
182
  };
180
183
  }
181
- exports._Segment = _Segment;
182
- _a = _Segment;
184
+ exports._VovkApp = _VovkApp;
185
+ _a = _VovkApp;
@@ -1,4 +1,4 @@
1
1
  import { type _VovkControllerSchema as VovkControllerSchema, type _KnownAny as KnownAny } from '../types';
2
2
  import { type _VovkClientOptions as VovkClientOptions, type _VovkClient as VovkClient, type _VovkDefaultFetcherOptions as VovkDefaultFetcherOptions } from './types';
3
3
  export declare const ARRAY_QUERY_KEY = "_vovkarr";
4
- export declare const _clientizeController: <T, OPTS extends Record<string, KnownAny> = VovkDefaultFetcherOptions>(givenController: VovkControllerSchema, segmentName?: string, options?: VovkClientOptions<OPTS>) => VovkClient<T, OPTS>;
4
+ export declare const _clientizeController: <T, OPTS extends Record<string, KnownAny> = VovkDefaultFetcherOptions>(controllerSchema: VovkControllerSchema, segmentName?: string, options?: VovkClientOptions<OPTS>) => VovkClient<T, OPTS>;
@@ -36,27 +36,26 @@ const getHandlerPath = (endpoint, params, query) => {
36
36
  }
37
37
  return `${result}${hasQuery ? '?' : ''}${searchParams.toString()}`;
38
38
  };
39
- const _clientizeController = (givenController, segmentName, options) => {
40
- const controller = givenController;
39
+ const _clientizeController = (controllerSchema, segmentName, options) => {
40
+ const schema = controllerSchema;
41
41
  const client = {};
42
- if (!controller)
43
- throw new Error(`Unable to clientize. Controller schema is not provided`);
44
- const schema = controller._handlers;
45
42
  if (!schema)
46
- throw new Error(`Unable to clientize. No schema for controller ${String(controller?._controllerName)}`);
47
- const controllerPrefix = trimPath(controller._prefix ?? '');
43
+ throw new Error(`Unable to clientize. Controller schema is not provided`);
44
+ if (!schema.handlers)
45
+ throw new Error(`Unable to clientize. No schema for controller ${String(schema?.controllerName)}`);
46
+ const controllerPrefix = trimPath(schema.prefix ?? '');
48
47
  const { fetcher: settingsFetcher = defaultFetcher_1.default } = options ?? {};
49
- for (const [staticMethodName, { path, httpMethod, clientValidators }] of Object.entries(schema)) {
50
- const getEndpoint = ({ prefix, params, query, }) => {
51
- const mainPrefix = (prefix.startsWith('http://') || prefix.startsWith('https://') || prefix.startsWith('/') ? '' : '/') +
52
- (prefix.endsWith('/') ? prefix : `${prefix}/`) +
48
+ for (const [staticMethodName, { path, httpMethod, validation }] of Object.entries(schema.handlers)) {
49
+ const getEndpoint = ({ apiRoot, params, query, }) => {
50
+ const mainPrefix = (apiRoot.startsWith('http://') || apiRoot.startsWith('https://') || apiRoot.startsWith('/') ? '' : '/') +
51
+ (apiRoot.endsWith('/') ? apiRoot : `${apiRoot}/`) +
53
52
  (segmentName ? `${segmentName}/` : '');
54
53
  return mainPrefix + getHandlerPath([controllerPrefix, path].filter(Boolean).join('/'), params, query);
55
54
  };
56
55
  const handler = (input = {}) => {
57
56
  const fetcher = input.fetcher ?? settingsFetcher;
58
57
  const validate = async ({ body, query, endpoint }) => {
59
- await (input.validateOnClient ?? options?.validateOnClient)?.({ body, query, endpoint }, clientValidators ?? {});
58
+ await (input.validateOnClient ?? options?.validateOnClient)?.({ body, query, endpoint }, validation ?? {});
60
59
  };
61
60
  const internalOptions = {
62
61
  name: staticMethodName,
@@ -85,7 +84,7 @@ const _clientizeController = (givenController, segmentName, options) => {
85
84
  return Promise.resolve(fetcherPromise);
86
85
  return input.transform ? fetcherPromise.then(input.transform) : fetcherPromise;
87
86
  };
88
- // @ts-expect-error TODO: Fix this
87
+ // @ts-expect-error TODO
89
88
  client[staticMethodName] = handler;
90
89
  }
91
90
  return client;
@@ -6,8 +6,8 @@ const HttpException_1 = require("../HttpException");
6
6
  exports.DEFAULT_ERROR_MESSAGE = 'Unknown error at defaultFetcher';
7
7
  // defaultFetcher uses HttpException class to throw errors of fake HTTP status 0 if client-side error occurs
8
8
  // For normal HTTP errors, it uses message and status code from the response of VovkErrorResponse type
9
- const defaultFetcher = async ({ httpMethod, getEndpoint, validate, defaultHandler, defaultStreamHandler }, { params, query, body, prefix = '/api', ...options }) => {
10
- const endpoint = getEndpoint({ prefix, params, query });
9
+ const defaultFetcher = async ({ httpMethod, getEndpoint, validate, defaultHandler, defaultStreamHandler }, { params, query, body, apiRoot = '/api', ...options }) => {
10
+ const endpoint = getEndpoint({ apiRoot, params, query });
11
11
  if (!options.disableClientValidation) {
12
12
  try {
13
13
  await validate({ body, query, endpoint });
@@ -41,7 +41,7 @@ const defaultFetcher = async ({ httpMethod, getEndpoint, validate, defaultHandle
41
41
  if (response.headers.get('content-type')?.includes('application/json')) {
42
42
  return defaultHandler(response);
43
43
  }
44
- if (response.headers.get('content-type')?.includes('text/plain; charset=utf-8')) {
44
+ if (response.headers.get('x-vovk-stream') === 'true') {
45
45
  return defaultStreamHandler(response);
46
46
  }
47
47
  return response;
@@ -14,7 +14,8 @@ const _defaultHandler = async (response) => {
14
14
  }
15
15
  if (!response.ok) {
16
16
  // handle server errors
17
- throw new HttpException_1._HttpException(response.status, result?.message ?? exports.DEFAULT_ERROR_MESSAGE);
17
+ const errorResponse = result;
18
+ throw new HttpException_1._HttpException(response.status, errorResponse?.message ?? exports.DEFAULT_ERROR_MESSAGE, errorResponse?.cause);
18
19
  }
19
20
  return result;
20
21
  };
package/client/types.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { _KnownAny as KnownAny, _HttpMethod as HttpMethod, _ControllerStaticMethod, _VovkControllerBody, _VovkControllerQuery, _VovkControllerParams } from '../types';
2
- import { _StreamResponse as StreamResponse } from '../StreamResponse';
2
+ import { _StreamJSONResponse as StreamJSONResponse } from '../StreamJSONResponse';
3
3
  import type { NextResponse } from 'next/server';
4
4
  export type _StaticMethodInput<T extends _ControllerStaticMethod> = (_VovkControllerBody<T> extends undefined | void ? {
5
5
  body?: undefined;
@@ -24,9 +24,9 @@ export type _StreamAsyncIterator<T> = {
24
24
  [Symbol.asyncIterator](): AsyncIterator<T>;
25
25
  cancel: () => Promise<void> | void;
26
26
  };
27
- type StaticMethodReturn<T extends _ControllerStaticMethod> = ReturnType<T> extends NextResponse<infer U> | Promise<NextResponse<infer U>> ? U : ReturnType<T> extends Response | Promise<Response> ? unknown : ReturnType<T>;
27
+ type StaticMethodReturn<T extends _ControllerStaticMethod> = ReturnType<T> extends NextResponse<infer U> | Promise<NextResponse<infer U>> ? U : ReturnType<T> extends Response | Promise<Response> ? Awaited<ReturnType<T>> : ReturnType<T>;
28
28
  type StaticMethodReturnPromise<T extends _ControllerStaticMethod> = ToPromise<StaticMethodReturn<T>>;
29
- type ClientMethod<T extends (...args: KnownAny[]) => void | object | StreamResponse<STREAM> | Promise<StreamResponse<STREAM>>, OPTS extends Record<string, KnownAny>, STREAM extends KnownAny = unknown> = <R>(options: (_StaticMethodInput<T> extends {
29
+ type ClientMethod<T extends (...args: KnownAny[]) => void | object | StreamJSONResponse<STREAM> | Promise<StreamJSONResponse<STREAM>>, OPTS extends Record<string, KnownAny>, STREAM extends KnownAny = unknown> = <R>(options: (_StaticMethodInput<T> extends {
30
30
  body?: undefined | null;
31
31
  query?: undefined;
32
32
  params?: undefined;
@@ -34,7 +34,7 @@ type ClientMethod<T extends (...args: KnownAny[]) => void | object | StreamRespo
34
34
  params: _StaticMethodInput<T>['params'];
35
35
  } : unknown : _StaticMethodInput<T>) & (Partial<OPTS & {
36
36
  transform: (staticMethodReturn: Awaited<StaticMethodReturn<T>>) => R;
37
- }> | void)) => ReturnType<T> extends Promise<StreamResponse<infer U>> | StreamResponse<infer U> | Iterator<infer U> | AsyncIterator<infer U> ? Promise<_StreamAsyncIterator<U>> : R extends object ? Promise<R> : StaticMethodReturnPromise<T>;
37
+ }> | void)) => ReturnType<T> extends Promise<StreamJSONResponse<infer U>> | StreamJSONResponse<infer U> | Iterator<infer U> | AsyncIterator<infer U> ? Promise<_StreamAsyncIterator<U>> : R extends object ? Promise<R> : StaticMethodReturnPromise<T>;
38
38
  type OmitNever<T> = {
39
39
  [K in keyof T as T[K] extends never ? never : K]: T[K];
40
40
  };
@@ -50,7 +50,7 @@ export type _VovkClientFetcher<OPTS extends Record<string, KnownAny> = Record<st
50
50
  name: keyof T;
51
51
  httpMethod: HttpMethod;
52
52
  getEndpoint: (data: {
53
- prefix: string;
53
+ apiRoot: string;
54
54
  params: {
55
55
  [key: string]: string;
56
56
  };
@@ -78,7 +78,7 @@ export interface _VovkDefaultFetcherOptions extends Omit<RequestInit, 'body' | '
78
78
  reactNative?: {
79
79
  textStreaming: boolean;
80
80
  };
81
- prefix?: string;
81
+ apiRoot?: string;
82
82
  segmentName?: string;
83
83
  disableClientValidation?: boolean;
84
84
  validateOnClient?: _VovkValidateOnClient;
@@ -18,8 +18,8 @@ function _createDecorator(handler, initHandler) {
18
18
  [propertyKey]: {
19
19
  ...handlerSchema,
20
20
  // avoid override of path and httpMethod
21
- ...(initResult?.clientValidators ? { clientValidators: initResult.clientValidators } : {}),
22
- ...(initResult?.customSchema ? { customSchema: initResult.customSchema } : {}),
21
+ ...(initResult?.validation ? { validation: initResult.validation } : {}),
22
+ ...(initResult?.custom ? { custom: initResult.custom } : {}),
23
23
  },
24
24
  };
25
25
  const method = function method(req, params) {
@@ -1,5 +1,5 @@
1
- import { type _KnownAny as KnownAny, type _DecoratorOptions as DecoratorOptions, type _VovkRequest as VovkRequest } from './types';
2
- export declare function _createSegment(): {
1
+ import { type _KnownAny as KnownAny, type _DecoratorOptions as DecoratorOptions, type _VovkRequest as VovkRequest, type _StaticClass as StaticClass } from './types';
2
+ export declare function _createVovkApp(): {
3
3
  get: {
4
4
  (givenPath?: string | undefined, options?: DecoratorOptions | undefined): ReturnType<(givenPath?: string, options?: DecoratorOptions) => (givenTarget: KnownAny, propertyKey: string) => void>;
5
5
  auto: (options?: DecoratorOptions) => (givenTarget: KnownAny, propertyKey: string) => void;
@@ -31,8 +31,8 @@ export declare function _createSegment(): {
31
31
  prefix: (givenPath?: string) => (givenTarget: KnownAny) => any;
32
32
  initVovk: (options: {
33
33
  segmentName?: string;
34
- controllers: Record<string, Function>;
35
- workers?: Record<string, Function>;
34
+ controllers: Record<string, StaticClass>;
35
+ workers?: Record<string, StaticClass>;
36
36
  exposeValidation?: boolean;
37
37
  emitSchema?: boolean;
38
38
  onError?: (err: Error, req: VovkRequest) => void | Promise<void>;
@@ -3,9 +3,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports._createSegment = _createSegment;
7
- /* eslint-disable no-console */
8
- const Segment_1 = require("./Segment");
6
+ exports._createVovkApp = _createVovkApp;
7
+ const VovkApp_1 = require("./VovkApp");
9
8
  const types_1 = require("./types");
10
9
  const getSchema_1 = __importDefault(require("./utils/getSchema"));
11
10
  const trimPath = (path) => path.trim().replace(/^\/|\/$/g, '');
@@ -14,9 +13,9 @@ const toKebabCase = (str) => str
14
13
  .replace(/([A-Z])/g, '-$1')
15
14
  .toLowerCase()
16
15
  .replace(/^-/, '');
17
- function _createSegment() {
18
- const segment = new Segment_1._Segment();
19
- const getDecoratorCreator = (httpMethod) => {
16
+ function _createVovkApp() {
17
+ const vovkApp = new VovkApp_1._VovkApp();
18
+ const createHTTPDecorator = (httpMethod) => {
20
19
  const assignSchema = (controller, propertyKey, path, options) => {
21
20
  if (typeof window !== 'undefined') {
22
21
  throw new Error('Decorators are intended for server-side use only. You have probably imported a controller on the client-side.');
@@ -27,8 +26,8 @@ function _createSegment() {
27
26
  decoratorName = 'del';
28
27
  throw new Error(`Decorator must be used on a static class method. Check the controller method named "${propertyKey}" used with @${decoratorName}.`);
29
28
  }
30
- const methods = segment._routes[httpMethod].get(controller) ?? {};
31
- segment._routes[httpMethod].set(controller, methods);
29
+ const methods = vovkApp.routes[httpMethod].get(controller) ?? {};
30
+ vovkApp.routes[httpMethod].set(controller, methods);
32
31
  controller._handlers = {
33
32
  ...controller._handlers,
34
33
  [propertyKey]: {
@@ -54,8 +53,8 @@ function _createSegment() {
54
53
  const auto = (options) => {
55
54
  function decorator(givenTarget, propertyKey) {
56
55
  const controller = givenTarget;
57
- const methods = segment._routes[httpMethod].get(controller) ?? {};
58
- segment._routes[httpMethod].set(controller, methods);
56
+ const methods = vovkApp.routes[httpMethod].get(controller) ?? {};
57
+ vovkApp.routes[httpMethod].set(controller, methods);
59
58
  controller._handlers = {
60
59
  ...controller._handlers,
61
60
  [propertyKey]: {
@@ -76,7 +75,6 @@ function _createSegment() {
76
75
  return (givenTarget) => {
77
76
  const controller = givenTarget;
78
77
  controller._prefix = path;
79
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
80
78
  return givenTarget;
81
79
  };
82
80
  };
@@ -92,28 +90,28 @@ function _createSegment() {
92
90
  // Wait for schema to be set (it can be set after decorators are called with another setTimeout)
93
91
  await new Promise((resolve) => setTimeout(resolve, 10));
94
92
  const schema = (0, getSchema_1.default)(options);
95
- return segment.respond(200, { schema });
93
+ return vovkApp.respond(200, { schema });
96
94
  }
97
- return segment.GET(req, data);
95
+ return vovkApp.GET(req, data);
98
96
  }
99
97
  return {
100
- GET: process.env.NODE_ENV === 'development' ? GET_DEV : segment.GET,
101
- POST: segment.POST,
102
- PUT: segment.PUT,
103
- PATCH: segment.PATCH,
104
- DELETE: segment.DELETE,
105
- HEAD: segment.HEAD,
106
- OPTIONS: segment.OPTIONS,
98
+ GET: process.env.NODE_ENV === 'development' ? GET_DEV : vovkApp.GET,
99
+ POST: vovkApp.POST,
100
+ PUT: vovkApp.PUT,
101
+ PATCH: vovkApp.PATCH,
102
+ DELETE: vovkApp.DELETE,
103
+ HEAD: vovkApp.HEAD,
104
+ OPTIONS: vovkApp.OPTIONS,
107
105
  };
108
106
  };
109
107
  return {
110
- get: getDecoratorCreator(types_1._HttpMethod.GET),
111
- post: getDecoratorCreator(types_1._HttpMethod.POST),
112
- put: getDecoratorCreator(types_1._HttpMethod.PUT),
113
- patch: getDecoratorCreator(types_1._HttpMethod.PATCH),
114
- del: getDecoratorCreator(types_1._HttpMethod.DELETE),
115
- head: getDecoratorCreator(types_1._HttpMethod.HEAD),
116
- options: getDecoratorCreator(types_1._HttpMethod.OPTIONS),
108
+ get: createHTTPDecorator(types_1._HttpMethod.GET),
109
+ post: createHTTPDecorator(types_1._HttpMethod.POST),
110
+ put: createHTTPDecorator(types_1._HttpMethod.PUT),
111
+ patch: createHTTPDecorator(types_1._HttpMethod.PATCH),
112
+ del: createHTTPDecorator(types_1._HttpMethod.DELETE),
113
+ head: createHTTPDecorator(types_1._HttpMethod.HEAD),
114
+ options: createHTTPDecorator(types_1._HttpMethod.OPTIONS),
117
115
  prefix,
118
116
  initVovk,
119
117
  };
package/index.d.ts CHANGED
@@ -1,12 +1,12 @@
1
- import { _createSegment as createSegment } from './createSegment';
2
- import { type _VovkErrorResponse as VovkErrorResponse, type _VovkRequest as VovkRequest, type _VovkControllerBody as VovkControllerBody, type _VovkControllerQuery as VovkControllerQuery, type _VovkControllerParams as VovkControllerParams, type _VovkControllerReturnType as VovkControllerReturnType, type _VovkControlerYieldType as VovkControlerYieldType, type _VovkBody as VovkBody, type _VovkQuery as VovkQuery, type _VovkParams as VovkParams, type _VovkReturnType as VovkReturnType, type _VovkYieldType as VovkYieldType, type _VovkSchema as VovkSchema, _HttpStatus as HttpStatus, _HttpMethod as HttpMethod } from './types';
1
+ import { _createVovkApp as createVovkApp } from './createVovkApp';
2
+ import { type _VovkErrorResponse as VovkErrorResponse, type _VovkRequest as VovkRequest, type _VovkBody as VovkBody, type _VovkQuery as VovkQuery, type _VovkParams as VovkParams, type _VovkReturnType as VovkReturnType, type _VovkYieldType as VovkYieldType, type _VovkControllerBody as VovkControllerBody, type _VovkControllerQuery as VovkControllerQuery, type _VovkControllerParams as VovkControllerParams, type _VovkControllerYieldType as VovkControllerYieldType, type _VovkSchema as VovkSchema, _HttpStatus as HttpStatus, _HttpMethod as HttpMethod } from './types';
3
3
  import type { _VovkClientOptions as VovkClientOptions, _VovkClientFetcher as VovkClientFetcher, _VovkDefaultFetcherOptions as VovkDefaultFetcherOptions, _VovkValidateOnClient as VovkValidateOnClient } from './client/types';
4
4
  import { _HttpException as HttpException } from './HttpException';
5
5
  import { _createDecorator as createDecorator } from './createDecorator';
6
- import { _StreamResponse as StreamResponse } from './StreamResponse';
6
+ import { _StreamJSONResponse as StreamJSONResponse } from './StreamJSONResponse';
7
7
  import { worker } from './worker';
8
- import { _generateStaticAPI as generateStaticAPI } from './generateStaticAPI';
9
- export { type VovkClientFetcher, type VovkDefaultFetcherOptions, type VovkValidateOnClient, type VovkSchema, type VovkErrorResponse, type VovkRequest, type VovkControllerBody, type VovkControllerQuery, type VovkControllerParams, type VovkControllerReturnType, type VovkControlerYieldType, type VovkBody, type VovkQuery, type VovkParams, type VovkReturnType, type VovkYieldType, type VovkClientOptions, StreamResponse, HttpException, HttpStatus, HttpMethod, createSegment, createDecorator, worker, generateStaticAPI, };
8
+ import { _generateStaticAPI as generateStaticAPI } from './utils/generateStaticAPI';
9
+ export { type VovkClientFetcher, type VovkDefaultFetcherOptions, 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, StreamJSONResponse, HttpException, HttpStatus, HttpMethod, createVovkApp, createDecorator, worker, generateStaticAPI, };
10
10
  export declare const get: {
11
11
  (givenPath?: string | undefined, options?: import("./types")._DecoratorOptions | undefined): ReturnType<(givenPath?: string, options?: import("./types")._DecoratorOptions) => (givenTarget: import("./types")._KnownAny, propertyKey: string) => void>;
12
12
  auto: (options?: import("./types")._DecoratorOptions) => (givenTarget: import("./types")._KnownAny, propertyKey: string) => void;
@@ -30,8 +30,8 @@ export declare const get: {
30
30
  auto: (options?: import("./types")._DecoratorOptions) => (givenTarget: import("./types")._KnownAny, propertyKey: string) => void;
31
31
  }, prefix: (givenPath?: string) => (givenTarget: import("./types")._KnownAny) => any, initVovk: (options: {
32
32
  segmentName?: string;
33
- controllers: Record<string, Function>;
34
- workers?: Record<string, Function>;
33
+ controllers: Record<string, import("./types")._StaticClass>;
34
+ workers?: Record<string, import("./types")._StaticClass>;
35
35
  exposeValidation?: boolean;
36
36
  emitSchema?: boolean;
37
37
  onError?: (err: Error, req: VovkRequest) => void | Promise<void>;
package/index.js CHANGED
@@ -1,9 +1,9 @@
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.generateStaticAPI = exports.worker = exports.createDecorator = exports.createSegment = exports.HttpMethod = exports.HttpStatus = exports.HttpException = exports.StreamResponse = void 0;
5
- const createSegment_1 = require("./createSegment");
6
- Object.defineProperty(exports, "createSegment", { enumerable: true, get: function () { return createSegment_1._createSegment; } });
4
+ exports.initVovk = exports.prefix = exports.options = exports.head = exports.del = exports.patch = exports.put = exports.post = exports.get = exports.generateStaticAPI = exports.worker = exports.createDecorator = exports.createVovkApp = exports.HttpMethod = exports.HttpStatus = exports.HttpException = exports.StreamJSONResponse = void 0;
5
+ const createVovkApp_1 = require("./createVovkApp");
6
+ Object.defineProperty(exports, "createVovkApp", { enumerable: true, get: function () { return createVovkApp_1._createVovkApp; } });
7
7
  const types_1 = require("./types");
8
8
  Object.defineProperty(exports, "HttpStatus", { enumerable: true, get: function () { return types_1._HttpStatus; } });
9
9
  Object.defineProperty(exports, "HttpMethod", { enumerable: true, get: function () { return types_1._HttpMethod; } });
@@ -11,10 +11,10 @@ const HttpException_1 = require("./HttpException");
11
11
  Object.defineProperty(exports, "HttpException", { enumerable: true, get: function () { return HttpException_1._HttpException; } });
12
12
  const createDecorator_1 = require("./createDecorator");
13
13
  Object.defineProperty(exports, "createDecorator", { enumerable: true, get: function () { return createDecorator_1._createDecorator; } });
14
- const StreamResponse_1 = require("./StreamResponse");
15
- Object.defineProperty(exports, "StreamResponse", { enumerable: true, get: function () { return StreamResponse_1._StreamResponse; } });
14
+ const StreamJSONResponse_1 = require("./StreamJSONResponse");
15
+ Object.defineProperty(exports, "StreamJSONResponse", { enumerable: true, get: function () { return StreamJSONResponse_1._StreamJSONResponse; } });
16
16
  const worker_1 = require("./worker");
17
17
  Object.defineProperty(exports, "worker", { enumerable: true, get: function () { return worker_1.worker; } });
18
- const generateStaticAPI_1 = require("./generateStaticAPI");
18
+ const generateStaticAPI_1 = require("./utils/generateStaticAPI");
19
19
  Object.defineProperty(exports, "generateStaticAPI", { enumerable: true, get: function () { return generateStaticAPI_1._generateStaticAPI; } });
20
- _a = (0, createSegment_1._createSegment)(), 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;
20
+ _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;
package/package.json CHANGED
@@ -1,14 +1,15 @@
1
1
  {
2
2
  "name": "vovk",
3
- "version": "3.0.0-draft.3",
3
+ "version": "3.0.0-draft.31",
4
4
  "description": "RESTful RPC for Next.js - Transforms Next.js into a powerful REST API platform with RPC capabilities.",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/finom/vovk.git"
8
8
  },
9
9
  "scripts": {
10
- "build": "rm -rf dist && tsc && cp {package.json,LICENSE,.npmignore} dist && cp ../../README.md dist",
10
+ "build": "shx rm -rf dist && tsc && shx cp package.json LICENSE .npmignore dist && shx cp ../../README.md dist",
11
11
  "lint": "eslint . --fix",
12
+ "tsc": "tsc --noEmit",
12
13
  "npm-publish": "if [ -z \"$NPM_TAG\" ]; then echo 'Error: NPM_TAG is not set'; exit 1; fi; cd ./dist && npm publish --tag=$NPM_TAG && cd ..",
13
14
  "ncu": "npm-check-updates -u"
14
15
  },
package/types.d.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  import type { NextRequest } from 'next/server';
2
- import type { _StreamResponse as StreamResponse } from './StreamResponse';
2
+ import type { _StreamJSONResponse as StreamJSONResponse } from './StreamJSONResponse';
3
3
  import { _StreamAsyncIterator as StreamAsyncIterator } from './client/types';
4
4
  export type _KnownAny = any;
5
+ export type _StaticClass = Function;
5
6
  export type _VovkSchema = {
6
7
  emitSchema: boolean;
7
8
  segmentName: string;
@@ -9,6 +10,7 @@ export type _VovkSchema = {
9
10
  controllers: Record<string, _VovkControllerSchema>;
10
11
  };
11
12
  export type _VovkErrorResponse = {
13
+ cause?: unknown;
12
14
  statusCode: _HttpStatus;
13
15
  message: string;
14
16
  isError: true;
@@ -16,33 +18,37 @@ export type _VovkErrorResponse = {
16
18
  export type _HandlerSchema = {
17
19
  path: string;
18
20
  httpMethod: _HttpMethod;
19
- clientValidators?: {
21
+ validation?: {
20
22
  query?: _KnownAny;
21
23
  body?: _KnownAny;
22
24
  };
23
- customSchema?: Record<string, _KnownAny>;
25
+ custom?: Record<string, _KnownAny>;
24
26
  };
25
27
  export type _VovkControllerSchema = {
26
- _controllerName: string;
27
- _originalControllerName: string;
28
- _prefix?: string;
29
- _handlers: Record<string, _HandlerSchema>;
28
+ controllerName: string;
29
+ originalControllerName: string;
30
+ prefix?: string;
31
+ handlers: Record<string, _HandlerSchema>;
30
32
  };
31
33
  export type _VovkWorkerSchema = {
32
- _workerName: string;
33
- _originalWorkerName: string;
34
- _handlers: Record<string, {
34
+ workerName: string;
35
+ originalWorkerName: string;
36
+ handlers: Record<string, {
35
37
  isGenerator?: true;
36
38
  }>;
37
39
  };
38
- export type _VovkControllerInternal = _VovkControllerSchema & {
40
+ export type _VovkControllerInternal = {
41
+ _controllerName?: _VovkControllerSchema['controllerName'];
42
+ _prefix?: _VovkControllerSchema['prefix'];
43
+ _handlers: _VovkControllerSchema['handlers'];
39
44
  _activated?: true;
40
45
  _onError?: (err: Error, req: _VovkRequest) => void | Promise<void>;
41
46
  };
42
- export type _VovkController = Function & _VovkControllerInternal & {
47
+ export type _VovkController = _StaticClass & _VovkControllerInternal & {
43
48
  [key: string]: unknown;
44
49
  };
45
- export type _VovkWorker = Function & _VovkWorkerSchema & {
50
+ export type _VovkWorker = _StaticClass & {
51
+ _handlers: _VovkWorkerSchema['handlers'];
46
52
  [key: string]: unknown;
47
53
  };
48
54
  export type _DecoratorOptions = {
@@ -62,49 +68,29 @@ export interface _VovkRequest<BODY = undefined, QUERY extends object | undefined
62
68
  forEach: (callbackfn: (value: QUERY[keyof QUERY], key: keyof QUERY, searchParams: NextRequest['nextUrl']['searchParams']) => void) => void;
63
69
  keys: () => IterableIterator<keyof QUERY>;
64
70
  values: () => IterableIterator<QUERY[keyof QUERY]>;
65
- readonly __queryType: QUERY;
66
71
  };
67
72
  };
68
73
  vovk: {
69
74
  body: () => Promise<BODY>;
70
75
  query: () => QUERY;
71
76
  meta: <T = Record<_KnownAny, _KnownAny>>(meta?: T | null) => T;
77
+ form: <T = _KnownAny>() => Promise<T>;
72
78
  };
73
79
  }
74
- export type _ControllerStaticMethod<REQ extends _VovkRequest<undefined, _KnownAny> = _VovkRequest<undefined, Record<string, string | string[]>>, PARAMS extends {
80
+ export type _ControllerStaticMethod<REQ extends _VovkRequest<_KnownAny, _KnownAny> = _VovkRequest<undefined, Record<string, string | string[]>>, PARAMS extends {
75
81
  [key: string]: string;
76
82
  } = _KnownAny> = ((req: REQ, params: PARAMS) => unknown) & {
77
83
  _controller?: _VovkController;
78
84
  };
79
- export type _VovkControllerBody<T extends _ControllerStaticMethod<REQ, PARAMS>, REQ extends _VovkRequest<undefined, _KnownAny> = Parameters<T>[0], PARAMS extends {
80
- [key: string]: string;
81
- } = _KnownAny> = Awaited<ReturnType<Parameters<T>[0]['json']>>;
82
- export type _VovkControllerQuery<T extends _ControllerStaticMethod<REQ, PARAMS>, REQ extends _VovkRequest<undefined, _KnownAny> = Parameters<T>[0], PARAMS extends {
83
- [key: string]: string;
84
- } = _KnownAny> = Parameters<T>[0]['nextUrl']['searchParams']['__queryType'];
85
- export type _VovkControllerParams<T extends _ControllerStaticMethod<REQ, PARAMS>, REQ extends _VovkRequest<undefined, _KnownAny> = Parameters<T>[0], PARAMS extends {
86
- [key: string]: string;
87
- } = _KnownAny> = Parameters<T>[1];
88
- export type _VovkBody<T extends (options: OPTIONS) => _KnownAny, OPTIONS extends {
89
- body: B;
90
- [key: string]: _KnownAny;
91
- } = Parameters<T>[0], B = _KnownAny> = Parameters<T>[0]['body'];
92
- export type _VovkQuery<T extends (options: OPTIONS) => _KnownAny, OPTIONS extends {
93
- query: Q;
94
- [key: string]: _KnownAny;
95
- } = Parameters<T>[0], Q = _KnownAny> = Parameters<T>[0]['query'];
96
- export type _VovkParams<T extends (options: OPTIONS) => _KnownAny, OPTIONS extends {
97
- params: P;
98
- [key: string]: _KnownAny;
99
- } = Parameters<T>[0], P = _KnownAny> = Parameters<T>[0]['params'];
100
- export type _VovkControllerReturnType<T extends _ControllerStaticMethod<REQ, PARAMS>, REQ extends _VovkRequest<undefined, _KnownAny> = Parameters<T>[0], PARAMS extends {
101
- [key: string]: string;
102
- } = _KnownAny> = Awaited<ReturnType<T>>;
103
- export type _VovkControlerYieldType<T extends _ControllerStaticMethod<REQ, PARAMS>, REQ extends _VovkRequest<undefined, _KnownAny> = Parameters<T>[0], PARAMS extends {
104
- [key: string]: string;
105
- } = _KnownAny> = T extends (...args: _KnownAny[]) => AsyncGenerator<infer Y, _KnownAny, _KnownAny> ? Y : T extends (...args: _KnownAny[]) => Generator<infer Y, _KnownAny, _KnownAny> ? Y : T extends (...args: _KnownAny[]) => Promise<StreamResponse<infer Y>> | StreamResponse<infer Y> ? Y : never;
106
- export type _VovkReturnType<T extends (...args: _KnownAny) => unknown> = Awaited<ReturnType<T>>;
85
+ export type _VovkControllerBody<T extends (...args: _KnownAny) => _KnownAny> = Awaited<ReturnType<Parameters<T>[0]['vovk']['body']>>;
86
+ export type _VovkControllerQuery<T extends (...args: _KnownAny) => _KnownAny> = ReturnType<Parameters<T>[0]['vovk']['query']>;
87
+ export type _VovkControllerParams<T extends (...args: _KnownAny) => _KnownAny> = Parameters<T>[1];
88
+ export type _VovkControllerYieldType<T extends (req: _VovkRequest<_KnownAny, _KnownAny>) => _KnownAny> = T extends (...args: _KnownAny[]) => AsyncGenerator<infer Y, _KnownAny, _KnownAny> ? Y : T extends (...args: _KnownAny[]) => Generator<infer Y, _KnownAny, _KnownAny> ? Y : T extends (...args: _KnownAny[]) => Promise<StreamJSONResponse<infer Y>> | StreamJSONResponse<infer Y> ? Y : never;
89
+ export type _VovkBody<T extends (...args: _KnownAny[]) => unknown> = Parameters<T>[0]['body'];
90
+ export type _VovkQuery<T extends (...args: _KnownAny[]) => unknown> = Parameters<T>[0]['query'];
91
+ export type _VovkParams<T extends (...args: _KnownAny[]) => unknown> = Parameters<T>[0]['params'];
107
92
  export type _VovkYieldType<T extends (...args: _KnownAny[]) => unknown> = T extends (...args: _KnownAny[]) => Promise<StreamAsyncIterator<infer Y>> ? Y : never;
93
+ export type _VovkReturnType<T extends (...args: _KnownAny) => unknown> = Awaited<ReturnType<T>>;
108
94
  export type _StreamAbortMessage = {
109
95
  isError: true;
110
96
  reason: _KnownAny;
@@ -0,0 +1,4 @@
1
+ import { _StaticClass as StaticClass } from '../types';
2
+ export declare function _generateStaticAPI(c: Record<string, StaticClass>, slug?: string): {
3
+ [x: string]: string[];
4
+ }[];
@@ -1,11 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports._generateStaticAPI = _generateStaticAPI;
4
- // eslint-disable-next-line @typescript-eslint/ban-types
5
4
  function _generateStaticAPI(c, slug = 'vovk') {
6
5
  const controllers = c;
7
6
  return [
8
- { [slug]: ['_vovk-ping_'] },
7
+ { [slug]: ['_schema_'] },
9
8
  ...Object.values(controllers)
10
9
  .map((controller) => {
11
10
  const handlers = controller._handlers;
@@ -1,8 +1,8 @@
1
- import { _VovkSchema as VovkSchema } from '../types';
2
- export default function (options: {
1
+ import { _VovkSchema as VovkSchema, _StaticClass as StaticClass } from '../types';
2
+ export default function getSchema(options: {
3
3
  emitSchema?: boolean;
4
4
  segmentName?: string;
5
- controllers: Record<string, Function>;
6
- workers?: Record<string, Function>;
5
+ controllers: Record<string, StaticClass>;
6
+ workers?: Record<string, StaticClass>;
7
7
  exposeValidation?: boolean;
8
8
  }): VovkSchema;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.default = default_1;
4
- function default_1(options) {
3
+ exports.default = getSchema;
4
+ function getSchema(options) {
5
5
  const exposeValidation = options?.exposeValidation ?? true;
6
6
  const emitSchema = options.emitSchema ?? true;
7
7
  const schema = {
@@ -14,24 +14,24 @@ function default_1(options) {
14
14
  return schema;
15
15
  for (const [controllerName, controller] of Object.entries(options.controllers)) {
16
16
  schema.controllers[controllerName] = {
17
- _controllerName: controllerName,
18
- _originalControllerName: controller.name,
19
- _prefix: controller._prefix ?? '',
20
- _handlers: {
17
+ controllerName: controllerName,
18
+ originalControllerName: controller.name,
19
+ prefix: controller._prefix ?? '',
20
+ handlers: {
21
21
  ...(exposeValidation
22
22
  ? controller._handlers
23
- : Object.fromEntries(Object.entries(controller._handlers).map(([key, value]) => [
23
+ : Object.fromEntries(Object.entries(controller._handlers ?? {}).map(([key, value]) => [
24
24
  key,
25
- { ...value, clientValidators: undefined },
25
+ { ...value, validation: undefined },
26
26
  ]))),
27
27
  },
28
28
  };
29
29
  }
30
30
  for (const [workerName, worker] of Object.entries(options.workers ?? {})) {
31
31
  schema.workers[workerName] = {
32
- _workerName: workerName,
33
- _originalWorkerName: worker.name,
34
- _handlers: { ...worker._handlers },
32
+ workerName,
33
+ originalWorkerName: worker.name,
34
+ handlers: { ...worker._handlers },
35
35
  };
36
36
  }
37
37
  return schema;
@@ -0,0 +1,3 @@
1
+ import { VovkRequest } from 'vovk';
2
+ import { _KnownAny as KnownAny } from '../types';
3
+ export default function reqForm<T = KnownAny>(req: VovkRequest<KnownAny, KnownAny>): Promise<T>;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = reqForm;
4
+ const formMap = new WeakMap();
5
+ async function reqForm(req) {
6
+ if (formMap.has(req)) {
7
+ return formMap.get(req);
8
+ }
9
+ const body = await req.formData();
10
+ const formData = Object.fromEntries(body.entries());
11
+ formMap.set(req, formData);
12
+ return formData;
13
+ }
@@ -1,5 +1,5 @@
1
1
  import { _KnownAny as KnownAny } from '../types';
2
- export default function setClientValidatorsForHandler(h: (...args: KnownAny[]) => KnownAny, validators: {
2
+ export default function setClientValidatorsForHandler(h: (...args: KnownAny[]) => KnownAny, validation: {
3
3
  body: unknown;
4
4
  query: unknown;
5
5
  }): Promise<void>;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.default = setClientValidatorsForHandler;
4
- function setClientValidatorsForHandler(h, validators) {
4
+ function setClientValidatorsForHandler(h, validation) {
5
5
  return new Promise((resolve) => {
6
6
  setTimeout(() => {
7
7
  const controller = h._controller;
@@ -16,10 +16,7 @@ function setClientValidatorsForHandler(h, validators) {
16
16
  ...controller._handlers,
17
17
  [handlerName]: {
18
18
  ...controller._handlers[handlerName],
19
- clientValidators: {
20
- body: validators.body,
21
- query: validators.query,
22
- },
19
+ validation,
23
20
  },
24
21
  };
25
22
  resolve();
@@ -1,2 +1,2 @@
1
1
  import type { _WorkerPromiseInstance as WorkerPromiseInstance } from './types';
2
- export declare function _promisifyWorker<T extends object>(currentWorker: Worker | null, givenWorkerService: object): WorkerPromiseInstance<T>;
2
+ export declare function _promisifyWorker<T extends object>(currentWorker: Worker | null, workerSchema: object): WorkerPromiseInstance<T>;
@@ -1,10 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports._promisifyWorker = _promisifyWorker;
4
- function _promisifyWorker(currentWorker, givenWorkerService) {
5
- if (!givenWorkerService)
4
+ function _promisifyWorker(currentWorker, workerSchema) {
5
+ if (!workerSchema)
6
6
  throw new Error('Worker schema is not provided');
7
- const workerService = givenWorkerService;
7
+ const schema = workerSchema;
8
8
  const instance = {
9
9
  worker: currentWorker,
10
10
  };
@@ -23,15 +23,11 @@ function _promisifyWorker(currentWorker, givenWorkerService) {
23
23
  instance.worker = worker;
24
24
  return instance;
25
25
  };
26
- instance.fork = (worker) => {
27
- return _promisifyWorker(worker, givenWorkerService);
28
- };
29
- for (const method of Object.keys(workerService._handlers)) {
30
- const { isGenerator } = workerService._handlers[method];
31
- const value = workerService[method];
26
+ instance.fork = (worker) => _promisifyWorker(worker, schema);
27
+ for (const methodName of Object.keys(schema.handlers)) {
28
+ const { isGenerator } = schema.handlers[methodName];
32
29
  if (isGenerator) {
33
- // @ts-expect-error TODO Fix this
34
- instance[method] = (...args) => {
30
+ const method = (...args) => {
35
31
  const key = callsKey;
36
32
  callsKey += 1;
37
33
  return {
@@ -43,8 +39,8 @@ function _promisifyWorker(currentWorker, givenWorkerService) {
43
39
  const messageQueue = [];
44
40
  let messageResolver = null;
45
41
  const onMessage = (e) => {
46
- const { method: m, key: k } = e.data;
47
- if (k !== key || m !== method) {
42
+ const { methodName: m, key: k } = e.data;
43
+ if (k !== key || m !== methodName) {
48
44
  return;
49
45
  }
50
46
  if (messageResolver) {
@@ -69,7 +65,7 @@ function _promisifyWorker(currentWorker, givenWorkerService) {
69
65
  };
70
66
  w.addEventListener('message', onMessage);
71
67
  w.addEventListener('error', onError);
72
- w.postMessage({ key, args, method });
68
+ w.postMessage({ key, args, methodName });
73
69
  try {
74
70
  while (true) {
75
71
  let message = null;
@@ -101,10 +97,11 @@ function _promisifyWorker(currentWorker, givenWorkerService) {
101
97
  },
102
98
  };
103
99
  };
100
+ // @ts-expect-error TODO
101
+ instance[methodName] = method;
104
102
  }
105
103
  else {
106
- // @ts-expect-error TODO Fix this
107
- instance[method] = (...args) => {
104
+ const method = (...args) => {
108
105
  if (!instance.worker) {
109
106
  throw new Error('Worker is not provided or terminated');
110
107
  }
@@ -118,8 +115,8 @@ function _promisifyWorker(currentWorker, givenWorkerService) {
118
115
  reject(e);
119
116
  };
120
117
  const onMessage = (e) => {
121
- const { result, error, key: k, method: m } = e.data;
122
- if (k !== key || m !== method) {
118
+ const { result, error, key: k, methodName: m } = e.data;
119
+ if (k !== key || m !== methodName) {
123
120
  return;
124
121
  }
125
122
  w.removeEventListener('message', onMessage);
@@ -133,9 +130,11 @@ function _promisifyWorker(currentWorker, givenWorkerService) {
133
130
  };
134
131
  w.addEventListener('message', onMessage);
135
132
  w.addEventListener('error', onError);
136
- w.postMessage({ key, args, method });
133
+ w.postMessage({ key, args, methodName });
137
134
  });
138
135
  };
136
+ // @ts-expect-error TODO
137
+ instance[methodName] = method;
139
138
  }
140
139
  }
141
140
  return instance;
package/worker/types.d.ts CHANGED
@@ -17,15 +17,15 @@ export type _WorkerPromiseInstance<T> = OmitNever<_WorkerPromiseInstanceWithNeve
17
17
  [Symbol.dispose]: () => void;
18
18
  };
19
19
  export interface _WorkerInput {
20
- method: string;
20
+ methodName: string;
21
21
  args: unknown[];
22
22
  key: number;
23
23
  }
24
24
  export interface _WorkerOutput {
25
+ methodName: string;
25
26
  result?: unknown;
26
27
  error?: unknown;
27
28
  done?: true;
28
29
  key: number;
29
- method: string;
30
30
  }
31
31
  export {};
package/worker/worker.js CHANGED
@@ -5,7 +5,6 @@ function _worker() {
5
5
  return (t) => {
6
6
  const target = t;
7
7
  target._handlers = {};
8
- // TODO: Experimental: You can pass Worker Service instead of schema to prommisify worker
9
8
  for (const key of Object.getOwnPropertyNames(target)) {
10
9
  const member = target[key];
11
10
  if (typeof member === 'function') {
@@ -20,25 +19,24 @@ function _worker() {
20
19
  }
21
20
  if (typeof self === 'undefined')
22
21
  return; // no-op in non-worker environment
23
- // eslint-disable-next-line no-undef
24
22
  const w = self;
25
23
  w.onmessage = async (evt) => {
26
- const { method, args, key } = evt.data;
24
+ const { methodName, args, key } = evt.data;
27
25
  try {
28
- const result = await target[method](...args);
26
+ const result = await target[methodName](...args);
29
27
  if (result && typeof result === 'object' && 'next' in result && typeof result.next === 'function') {
30
28
  const iterable = result;
31
29
  for await (const result of iterable) {
32
- w.postMessage({ result, key, method });
30
+ w.postMessage({ result, key, methodName });
33
31
  }
34
- w.postMessage({ done: true, key, method });
32
+ w.postMessage({ done: true, key, methodName });
35
33
  }
36
34
  else {
37
- w.postMessage({ result, key, method });
35
+ w.postMessage({ result, key, methodName });
38
36
  }
39
37
  }
40
38
  catch (e) {
41
- w.postMessage({ error: e, key, method });
39
+ w.postMessage({ error: e, key, methodName });
42
40
  }
43
41
  };
44
42
  };
@@ -1,3 +0,0 @@
1
- export declare function _generateStaticAPI(c: Record<string, Function>, slug?: string): {
2
- [x: string]: string[];
3
- }[];