vovk 3.0.0-draft.21 → 3.0.0-draft.211

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.
Files changed (169) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +8 -96
  3. package/bin/index.mjs +8 -0
  4. package/{HttpException.d.ts → cjs/HttpException.d.ts} +2 -2
  5. package/{HttpException.js → cjs/HttpException.js} +3 -3
  6. package/cjs/JSONLinesResponse.d.ts +14 -0
  7. package/{StreamJSONResponse.js → cjs/JSONLinesResponse.js} +15 -10
  8. package/{Segment.d.ts → cjs/VovkApp.d.ts} +11 -10
  9. package/cjs/VovkApp.js +189 -0
  10. package/cjs/client/createRPC.d.ts +3 -0
  11. package/cjs/client/createRPC.js +87 -0
  12. package/{client → cjs/client}/defaultHandler.d.ts +1 -1
  13. package/cjs/client/defaultHandler.js +22 -0
  14. package/cjs/client/defaultStreamHandler.d.ts +4 -0
  15. package/{client → cjs/client}/defaultStreamHandler.js +11 -12
  16. package/cjs/client/fetcher.d.ts +13 -0
  17. package/cjs/client/fetcher.js +90 -0
  18. package/cjs/client/index.d.ts +3 -0
  19. package/cjs/client/index.js +8 -0
  20. package/cjs/client/types.d.ts +111 -0
  21. package/{createSegment.d.ts → cjs/createVovkApp.d.ts} +11 -10
  22. package/cjs/createVovkApp.js +132 -0
  23. package/cjs/index.d.ts +65 -0
  24. package/cjs/index.js +37 -0
  25. package/cjs/openapi/error.d.ts +2 -0
  26. package/cjs/openapi/error.js +100 -0
  27. package/cjs/openapi/generateFnName.d.ts +23 -0
  28. package/cjs/openapi/generateFnName.js +81 -0
  29. package/cjs/openapi/index.d.ts +12 -0
  30. package/cjs/openapi/index.js +21 -0
  31. package/cjs/openapi/openAPIToVovkSchema.d.ts +2 -0
  32. package/cjs/openapi/openAPIToVovkSchema.js +197 -0
  33. package/cjs/openapi/vovkSchemaToOpenAPI.d.ts +9 -0
  34. package/cjs/openapi/vovkSchemaToOpenAPI.js +237 -0
  35. package/cjs/types.d.ts +364 -0
  36. package/cjs/types.js +74 -0
  37. package/cjs/utils/camelCase.d.ts +6 -0
  38. package/cjs/utils/camelCase.js +37 -0
  39. package/cjs/utils/createCodeExamples.d.ts +19 -0
  40. package/cjs/utils/createCodeExamples.js +114 -0
  41. package/cjs/utils/createDecorator.d.ts +6 -0
  42. package/{createDecorator.js → cjs/utils/createDecorator.js} +24 -16
  43. package/cjs/utils/createLLMFunctions.d.ts +20 -0
  44. package/cjs/utils/createLLMFunctions.js +100 -0
  45. package/cjs/utils/generateStaticAPI.d.ts +4 -0
  46. package/cjs/utils/generateStaticAPI.js +30 -0
  47. package/cjs/utils/getSchema.d.ts +21 -0
  48. package/cjs/utils/getSchema.js +43 -0
  49. package/cjs/utils/multitenant.d.ts +24 -0
  50. package/cjs/utils/multitenant.js +170 -0
  51. package/cjs/utils/parseQuery.d.ts +25 -0
  52. package/cjs/utils/parseQuery.js +156 -0
  53. package/cjs/utils/reqForm.d.ts +2 -0
  54. package/cjs/utils/reqForm.js +33 -0
  55. package/{utils → cjs/utils}/reqMeta.d.ts +1 -2
  56. package/cjs/utils/reqQuery.d.ts +2 -0
  57. package/cjs/utils/reqQuery.js +10 -0
  58. package/cjs/utils/serializeQuery.d.ts +13 -0
  59. package/cjs/utils/serializeQuery.js +65 -0
  60. package/cjs/utils/setHandlerSchema.d.ts +4 -0
  61. package/cjs/utils/setHandlerSchema.js +15 -0
  62. package/cjs/utils/withStandard.d.ts +51 -0
  63. package/cjs/utils/withStandard.js +30 -0
  64. package/cjs/utils/withValidationLibrary.d.ts +49 -0
  65. package/cjs/utils/withValidationLibrary.js +123 -0
  66. package/mjs/HttpException.d.ts +7 -0
  67. package/mjs/HttpException.js +15 -0
  68. package/mjs/JSONLinesResponse.d.ts +14 -0
  69. package/mjs/JSONLinesResponse.js +59 -0
  70. package/mjs/VovkApp.d.ts +29 -0
  71. package/mjs/VovkApp.js +189 -0
  72. package/mjs/client/createRPC.d.ts +3 -0
  73. package/mjs/client/createRPC.js +87 -0
  74. package/mjs/client/defaultHandler.d.ts +2 -0
  75. package/mjs/client/defaultHandler.js +22 -0
  76. package/mjs/client/defaultStreamHandler.d.ts +4 -0
  77. package/mjs/client/defaultStreamHandler.js +81 -0
  78. package/mjs/client/fetcher.d.ts +13 -0
  79. package/mjs/client/fetcher.js +90 -0
  80. package/mjs/client/index.d.ts +3 -0
  81. package/mjs/client/index.js +8 -0
  82. package/mjs/client/types.d.ts +111 -0
  83. package/mjs/createVovkApp.d.ts +63 -0
  84. package/mjs/createVovkApp.js +132 -0
  85. package/mjs/index.d.ts +65 -0
  86. package/mjs/index.js +37 -0
  87. package/mjs/openapi/error.d.ts +2 -0
  88. package/mjs/openapi/error.js +100 -0
  89. package/mjs/openapi/generateFnName.d.ts +23 -0
  90. package/mjs/openapi/generateFnName.js +81 -0
  91. package/mjs/openapi/index.d.ts +12 -0
  92. package/mjs/openapi/index.js +21 -0
  93. package/mjs/openapi/openAPIToVovkSchema.d.ts +2 -0
  94. package/mjs/openapi/openAPIToVovkSchema.js +197 -0
  95. package/mjs/openapi/vovkSchemaToOpenAPI.d.ts +9 -0
  96. package/mjs/openapi/vovkSchemaToOpenAPI.js +237 -0
  97. package/mjs/types.d.ts +364 -0
  98. package/mjs/types.js +74 -0
  99. package/mjs/utils/camelCase.d.ts +6 -0
  100. package/mjs/utils/camelCase.js +37 -0
  101. package/mjs/utils/createCodeExamples.d.ts +19 -0
  102. package/mjs/utils/createCodeExamples.js +114 -0
  103. package/mjs/utils/createDecorator.d.ts +6 -0
  104. package/mjs/utils/createDecorator.js +46 -0
  105. package/mjs/utils/createLLMFunctions.d.ts +20 -0
  106. package/mjs/utils/createLLMFunctions.js +100 -0
  107. package/mjs/utils/generateStaticAPI.d.ts +4 -0
  108. package/mjs/utils/generateStaticAPI.js +30 -0
  109. package/mjs/utils/getSchema.d.ts +21 -0
  110. package/mjs/utils/getSchema.js +43 -0
  111. package/mjs/utils/multitenant.d.ts +24 -0
  112. package/mjs/utils/multitenant.js +170 -0
  113. package/mjs/utils/parseQuery.d.ts +25 -0
  114. package/mjs/utils/parseQuery.js +156 -0
  115. package/mjs/utils/reqForm.d.ts +2 -0
  116. package/mjs/utils/reqForm.js +33 -0
  117. package/mjs/utils/reqMeta.d.ts +2 -0
  118. package/mjs/utils/reqMeta.js +13 -0
  119. package/mjs/utils/reqQuery.d.ts +2 -0
  120. package/mjs/utils/reqQuery.js +10 -0
  121. package/mjs/utils/serializeQuery.d.ts +13 -0
  122. package/mjs/utils/serializeQuery.js +65 -0
  123. package/mjs/utils/setHandlerSchema.d.ts +4 -0
  124. package/mjs/utils/setHandlerSchema.js +15 -0
  125. package/mjs/utils/shim.d.ts +1 -0
  126. package/mjs/utils/shim.js +18 -0
  127. package/mjs/utils/withStandard.d.ts +51 -0
  128. package/mjs/utils/withStandard.js +30 -0
  129. package/mjs/utils/withValidationLibrary.d.ts +49 -0
  130. package/mjs/utils/withValidationLibrary.js +123 -0
  131. package/package.json +30 -5
  132. package/.npmignore +0 -2
  133. package/Segment.js +0 -182
  134. package/StreamJSONResponse.d.ts +0 -17
  135. package/client/clientizeController.d.ts +0 -4
  136. package/client/clientizeController.js +0 -92
  137. package/client/defaultFetcher.d.ts +0 -4
  138. package/client/defaultFetcher.js +0 -49
  139. package/client/defaultHandler.js +0 -21
  140. package/client/defaultStreamHandler.d.ts +0 -4
  141. package/client/index.d.ts +0 -4
  142. package/client/index.js +0 -5
  143. package/client/types.d.ts +0 -100
  144. package/createDecorator.d.ts +0 -4
  145. package/createSegment.js +0 -118
  146. package/generateStaticAPI.d.ts +0 -4
  147. package/generateStaticAPI.js +0 -18
  148. package/index.d.ts +0 -60
  149. package/index.js +0 -20
  150. package/types.d.ts +0 -155
  151. package/types.js +0 -65
  152. package/utils/getSchema.d.ts +0 -8
  153. package/utils/getSchema.js +0 -38
  154. package/utils/reqQuery.d.ts +0 -3
  155. package/utils/reqQuery.js +0 -25
  156. package/utils/setClientValidatorsForHandler.d.ts +0 -5
  157. package/utils/setClientValidatorsForHandler.js +0 -28
  158. package/worker/index.d.ts +0 -3
  159. package/worker/index.js +0 -7
  160. package/worker/promisifyWorker.d.ts +0 -2
  161. package/worker/promisifyWorker.js +0 -141
  162. package/worker/types.d.ts +0 -31
  163. package/worker/worker.d.ts +0 -1
  164. package/worker/worker.js +0 -43
  165. /package/{client → cjs/client}/types.js +0 -0
  166. /package/{utils → cjs/utils}/reqMeta.js +0 -0
  167. /package/{utils → cjs/utils}/shim.d.ts +0 -0
  168. /package/{utils → cjs/utils}/shim.js +0 -0
  169. /package/{worker → mjs/client}/types.js +0 -0
@@ -0,0 +1,13 @@
1
+ import type { KnownAny } from '../types.js';
2
+ /**
3
+ * Serialize a nested object (including arrays, arrays of objects, etc.)
4
+ * into a bracket-based query string.
5
+ *
6
+ * @example
7
+ * serializeQuery({ x: 'xx', y: [1, 2], z: { f: 'x' } })
8
+ * => "x=xx&y[0]=1&y[1]=2&z[f]=x"
9
+ *
10
+ * @param obj - The input object to be serialized
11
+ * @returns - A bracket-based query string (without leading "?")
12
+ */
13
+ export default function serializeQuery(obj: Record<string, KnownAny>): string;
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = serializeQuery;
4
+ /**
5
+ * Recursively build query parameters from an object.
6
+ *
7
+ * @param key - The query key so far (e.g. 'user', 'user[0]', 'user[0][name]')
8
+ * @param value - The current value to serialize
9
+ * @returns - An array of `key=value` strings
10
+ */
11
+ function buildParams(key, value) {
12
+ if (value === null || value === undefined) {
13
+ return []; // skip null/undefined values entirely
14
+ }
15
+ // If value is an object or array, we need to recurse
16
+ if (typeof value === 'object') {
17
+ // Array case
18
+ if (Array.isArray(value)) {
19
+ /**
20
+ * We use index-based bracket notation here:
21
+ * e.g. for value = ['aa', 'bb'] and key = 'foo'
22
+ * => "foo[0]=aa&foo[1]=bb"
23
+ *
24
+ * If you prefer "foo[]=aa&foo[]=bb" style, replace:
25
+ * `${key}[${i}]`
26
+ * with:
27
+ * `${key}[]`
28
+ */
29
+ return value.flatMap((v, i) => {
30
+ const newKey = `${key}[${i}]`;
31
+ return buildParams(newKey, v);
32
+ });
33
+ }
34
+ // Plain object case
35
+ return Object.keys(value).flatMap((k) => {
36
+ const newKey = `${key}[${k}]`;
37
+ return buildParams(newKey, value[k]);
38
+ });
39
+ }
40
+ return [`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`];
41
+ }
42
+ /**
43
+ * Serialize a nested object (including arrays, arrays of objects, etc.)
44
+ * into a bracket-based query string.
45
+ *
46
+ * @example
47
+ * serializeQuery({ x: 'xx', y: [1, 2], z: { f: 'x' } })
48
+ * => "x=xx&y[0]=1&y[1]=2&z[f]=x"
49
+ *
50
+ * @param obj - The input object to be serialized
51
+ * @returns - A bracket-based query string (without leading "?")
52
+ */
53
+ function serializeQuery(obj) {
54
+ if (!obj || typeof obj !== 'object')
55
+ return '';
56
+ // Collect query segments
57
+ const segments = [];
58
+ for (const key in obj) {
59
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
60
+ const value = obj[key];
61
+ segments.push(...buildParams(key, value));
62
+ }
63
+ }
64
+ return segments.join('&');
65
+ }
@@ -0,0 +1,4 @@
1
+ import type { KnownAny, VovkController, VovkHandlerSchema } from '../types.js';
2
+ export declare function setHandlerSchema(h: ((...args: KnownAny[]) => KnownAny) & {
3
+ _getSchema?: (controller: VovkController) => Omit<VovkHandlerSchema, 'httpMethod' | 'path'>;
4
+ }, schema: Omit<VovkHandlerSchema, 'httpMethod' | 'path'>): Promise<void>;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.setHandlerSchema = setHandlerSchema;
4
+ async function setHandlerSchema(h, schema) {
5
+ h._getSchema = (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
+ return schema;
14
+ };
15
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ if (typeof Symbol.dispose !== 'symbol') {
4
+ Object.defineProperty(Symbol, 'dispose', {
5
+ configurable: false,
6
+ enumerable: false,
7
+ writable: false,
8
+ value: Symbol.for('dispose'),
9
+ });
10
+ }
11
+ if (typeof Symbol.asyncDispose !== 'symbol') {
12
+ Object.defineProperty(Symbol, 'asyncDispose', {
13
+ configurable: false,
14
+ enumerable: false,
15
+ writable: false,
16
+ value: Symbol.for('asyncDispose'),
17
+ });
18
+ }
@@ -0,0 +1,51 @@
1
+ import type { StandardSchemaV1 } from '@standard-schema/spec';
2
+ import { KnownAny, VovkRequest, VovkTypedMethod, VovkValidationType } from '../types';
3
+ import { withValidationLibrary } from './withValidationLibrary';
4
+ export declare function withStandard<T extends (req: REQ, params: PARAMS extends StandardSchemaV1 ? StandardSchemaV1.InferInput<PARAMS> : Record<string, string>) => KnownAny, BODY extends StandardSchemaV1, QUERY extends StandardSchemaV1, PARAMS extends StandardSchemaV1, OUTPUT extends StandardSchemaV1, ITERATION extends StandardSchemaV1, REQ extends VovkRequest<KnownAny, KnownAny, KnownAny> = VovkRequest<BODY extends StandardSchemaV1 ? StandardSchemaV1.InferInput<BODY> : undefined, QUERY extends StandardSchemaV1 ? StandardSchemaV1.InferInput<QUERY> : undefined, PARAMS extends StandardSchemaV1 ? StandardSchemaV1.InferInput<PARAMS> : undefined>, IS_FORM extends boolean = false>({ isForm, body, query, params, output, iteration, handle, toJSONSchema, disableServerSideValidation, skipSchemaEmission, validateEachIteration, }: {
5
+ isForm?: IS_FORM;
6
+ body?: BODY;
7
+ query?: QUERY;
8
+ params?: PARAMS;
9
+ output?: OUTPUT;
10
+ iteration?: ITERATION;
11
+ handle: T;
12
+ disableServerSideValidation?: boolean | VovkValidationType[];
13
+ skipSchemaEmission?: boolean | VovkValidationType[];
14
+ validateEachIteration?: boolean;
15
+ toJSONSchema: Parameters<typeof withValidationLibrary>[0]['toJSONSchema'];
16
+ }): T & {
17
+ __types: {
18
+ body: BODY extends StandardSchemaV1<unknown, unknown> ? StandardSchemaV1.InferOutput<BODY> : any;
19
+ query: QUERY extends StandardSchemaV1<unknown, unknown> ? StandardSchemaV1.InferOutput<QUERY> : any;
20
+ params: PARAMS extends StandardSchemaV1<unknown, unknown> ? StandardSchemaV1.InferOutput<PARAMS> : any;
21
+ output: OUTPUT extends StandardSchemaV1<unknown, unknown> ? StandardSchemaV1.InferOutput<OUTPUT> : any;
22
+ iteration: ITERATION extends StandardSchemaV1<unknown, unknown> ? StandardSchemaV1.InferOutput<ITERATION> : any;
23
+ isForm: IS_FORM extends true ? true : any;
24
+ };
25
+ isRPC?: boolean;
26
+ } & {
27
+ schema: import("../types").VovkHandlerSchema;
28
+ } & {
29
+ func: (input: {
30
+ disableValidation?: boolean;
31
+ } & (undefined extends BODY | undefined ? {
32
+ body?: VovkTypedMethod<T, BODY extends StandardSchemaV1<unknown, unknown> ? StandardSchemaV1.InferOutput<BODY> : any, QUERY extends StandardSchemaV1<unknown, unknown> ? StandardSchemaV1.InferOutput<QUERY> : any, PARAMS extends StandardSchemaV1<unknown, unknown> ? StandardSchemaV1.InferOutput<PARAMS> : any, OUTPUT extends StandardSchemaV1<unknown, unknown> ? StandardSchemaV1.InferOutput<OUTPUT> : any, ITERATION extends StandardSchemaV1<unknown, unknown> ? StandardSchemaV1.InferOutput<ITERATION> : any, IS_FORM extends true ? true : any>["__types"]["body"] | undefined;
33
+ } : {
34
+ body: VovkTypedMethod<T, BODY extends StandardSchemaV1<unknown, unknown> ? StandardSchemaV1.InferOutput<BODY> : any, QUERY extends StandardSchemaV1<unknown, unknown> ? StandardSchemaV1.InferOutput<QUERY> : any, PARAMS extends StandardSchemaV1<unknown, unknown> ? StandardSchemaV1.InferOutput<PARAMS> : any, OUTPUT extends StandardSchemaV1<unknown, unknown> ? StandardSchemaV1.InferOutput<OUTPUT> : any, ITERATION extends StandardSchemaV1<unknown, unknown> ? StandardSchemaV1.InferOutput<ITERATION> : any, IS_FORM extends true ? true : any>["__types"]["body"];
35
+ }) & (undefined extends QUERY | undefined ? {
36
+ query?: VovkTypedMethod<T, BODY extends StandardSchemaV1<unknown, unknown> ? StandardSchemaV1.InferOutput<BODY> : any, QUERY extends StandardSchemaV1<unknown, unknown> ? StandardSchemaV1.InferOutput<QUERY> : any, PARAMS extends StandardSchemaV1<unknown, unknown> ? StandardSchemaV1.InferOutput<PARAMS> : any, OUTPUT extends StandardSchemaV1<unknown, unknown> ? StandardSchemaV1.InferOutput<OUTPUT> : any, ITERATION extends StandardSchemaV1<unknown, unknown> ? StandardSchemaV1.InferOutput<ITERATION> : any, IS_FORM extends true ? true : any>["__types"]["query"] | undefined;
37
+ } : {
38
+ query: VovkTypedMethod<T, BODY extends StandardSchemaV1<unknown, unknown> ? StandardSchemaV1.InferOutput<BODY> : any, QUERY extends StandardSchemaV1<unknown, unknown> ? StandardSchemaV1.InferOutput<QUERY> : any, PARAMS extends StandardSchemaV1<unknown, unknown> ? StandardSchemaV1.InferOutput<PARAMS> : any, OUTPUT extends StandardSchemaV1<unknown, unknown> ? StandardSchemaV1.InferOutput<OUTPUT> : any, ITERATION extends StandardSchemaV1<unknown, unknown> ? StandardSchemaV1.InferOutput<ITERATION> : any, IS_FORM extends true ? true : any>["__types"]["query"];
39
+ }) & (undefined extends PARAMS | undefined ? {
40
+ params?: VovkTypedMethod<T, BODY extends StandardSchemaV1<unknown, unknown> ? StandardSchemaV1.InferOutput<BODY> : any, QUERY extends StandardSchemaV1<unknown, unknown> ? StandardSchemaV1.InferOutput<QUERY> : any, PARAMS extends StandardSchemaV1<unknown, unknown> ? StandardSchemaV1.InferOutput<PARAMS> : any, OUTPUT extends StandardSchemaV1<unknown, unknown> ? StandardSchemaV1.InferOutput<OUTPUT> : any, ITERATION extends StandardSchemaV1<unknown, unknown> ? StandardSchemaV1.InferOutput<ITERATION> : any, IS_FORM extends true ? true : any>["__types"]["params"] | undefined;
41
+ } : {
42
+ params: VovkTypedMethod<T, BODY extends StandardSchemaV1<unknown, unknown> ? StandardSchemaV1.InferOutput<BODY> : any, QUERY extends StandardSchemaV1<unknown, unknown> ? StandardSchemaV1.InferOutput<QUERY> : any, PARAMS extends StandardSchemaV1<unknown, unknown> ? StandardSchemaV1.InferOutput<PARAMS> : any, OUTPUT extends StandardSchemaV1<unknown, unknown> ? StandardSchemaV1.InferOutput<OUTPUT> : any, ITERATION extends StandardSchemaV1<unknown, unknown> ? StandardSchemaV1.InferOutput<ITERATION> : any, IS_FORM extends true ? true : any>["__types"]["params"];
43
+ })) => ReturnType<VovkTypedMethod<T, BODY extends StandardSchemaV1<unknown, unknown> ? StandardSchemaV1.InferOutput<BODY> : any, QUERY extends StandardSchemaV1<unknown, unknown> ? StandardSchemaV1.InferOutput<QUERY> : any, PARAMS extends StandardSchemaV1<unknown, unknown> ? StandardSchemaV1.InferOutput<PARAMS> : any, OUTPUT extends StandardSchemaV1<unknown, unknown> ? StandardSchemaV1.InferOutput<OUTPUT> : any, ITERATION extends StandardSchemaV1<unknown, unknown> ? StandardSchemaV1.InferOutput<ITERATION> : any, IS_FORM extends true ? true : any>>;
44
+ models: {
45
+ body: BODY | undefined;
46
+ query: QUERY | undefined;
47
+ params: PARAMS | undefined;
48
+ output: OUTPUT | undefined;
49
+ iteration: ITERATION | undefined;
50
+ };
51
+ };
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.withStandard = withStandard;
4
+ const types_1 = require("../types");
5
+ const withValidationLibrary_1 = require("./withValidationLibrary");
6
+ const HttpException_1 = require("../HttpException");
7
+ function withStandard({ isForm, body, query, params, output, iteration, handle, toJSONSchema, disableServerSideValidation, skipSchemaEmission, validateEachIteration, }) {
8
+ return (0, withValidationLibrary_1.withValidationLibrary)({
9
+ isForm,
10
+ body,
11
+ query,
12
+ params,
13
+ output,
14
+ iteration,
15
+ disableServerSideValidation,
16
+ skipSchemaEmission,
17
+ validateEachIteration,
18
+ handle: handle,
19
+ toJSONSchema,
20
+ validate: async (data, model, { type, i }) => {
21
+ const result = await model['~standard'].validate(data);
22
+ if (result.issues?.length) {
23
+ throw new HttpException_1.HttpException(types_1.HttpStatus.BAD_REQUEST, `Validation failed. Invalid ${type === 'iteration' ? `${type} #${i}` : type} on server: ${result.issues
24
+ .map(({ message, path }) => `${message}${path ? ` at ${path.join('.')}` : ''}`)
25
+ .join(', ')}`, { [type]: data, result });
26
+ }
27
+ return result.value;
28
+ },
29
+ });
30
+ }
@@ -0,0 +1,49 @@
1
+ import { VovkHandlerSchema, VovkTypedMethod, VovkValidationType, type KnownAny, type VovkRequest } from '../types.js';
2
+ type VovkRequestAny = VovkRequest<KnownAny, KnownAny, KnownAny>;
3
+ export declare function withValidationLibrary<T extends VovkTypedMethod<(req: KnownAny, params: KnownAny) => KnownAny>, BODY_MODEL, QUERY_MODEL, PARAMS_MODEL, OUTPUT_MODEL, ITERATION_MODEL, IS_FORM extends boolean = false>({ isForm, disableServerSideValidation, skipSchemaEmission, validateEachIteration, body, query, params, output, iteration, handle, toJSONSchema, validate, }: {
4
+ isForm?: IS_FORM;
5
+ disableServerSideValidation?: boolean | VovkValidationType[];
6
+ skipSchemaEmission?: boolean | VovkValidationType[];
7
+ validateEachIteration?: boolean;
8
+ body?: BODY_MODEL;
9
+ query?: QUERY_MODEL;
10
+ params?: PARAMS_MODEL;
11
+ output?: OUTPUT_MODEL;
12
+ iteration?: ITERATION_MODEL;
13
+ handle: T;
14
+ toJSONSchema?: (model: NonNullable<BODY_MODEL | QUERY_MODEL | PARAMS_MODEL | OUTPUT_MODEL | ITERATION_MODEL>, meta: {
15
+ type: VovkValidationType;
16
+ }) => KnownAny;
17
+ validate: (data: KnownAny, model: NonNullable<BODY_MODEL | QUERY_MODEL | PARAMS_MODEL | OUTPUT_MODEL | ITERATION_MODEL>, meta: {
18
+ type: VovkValidationType | 'form';
19
+ req: VovkRequestAny;
20
+ status?: number;
21
+ i?: number;
22
+ }) => KnownAny;
23
+ }): T & {
24
+ schema: VovkHandlerSchema;
25
+ } & {
26
+ func: (input: {
27
+ disableValidation?: boolean;
28
+ } & (undefined extends typeof body ? {
29
+ body?: T["__types"]["body"];
30
+ } : {
31
+ body: T["__types"]["body"];
32
+ }) & (undefined extends typeof query ? {
33
+ query?: T["__types"]["query"];
34
+ } : {
35
+ query: T["__types"]["query"];
36
+ }) & (undefined extends typeof params ? {
37
+ params?: T["__types"]["params"];
38
+ } : {
39
+ params: T["__types"]["params"];
40
+ })) => ReturnType<T>;
41
+ models: {
42
+ body: BODY_MODEL | undefined;
43
+ query: QUERY_MODEL | undefined;
44
+ params: PARAMS_MODEL | undefined;
45
+ output: OUTPUT_MODEL | undefined;
46
+ iteration: ITERATION_MODEL | undefined;
47
+ };
48
+ };
49
+ export {};
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.withValidationLibrary = withValidationLibrary;
7
+ const HttpException_js_1 = require("../HttpException.js");
8
+ const types_js_1 = require("../types.js");
9
+ const reqMeta_js_1 = __importDefault(require("./reqMeta.js"));
10
+ const setHandlerSchema_js_1 = require("./setHandlerSchema.js");
11
+ const validationTypes = ['body', 'query', 'params', 'output', 'iteration'];
12
+ function withValidationLibrary({ isForm, disableServerSideValidation, skipSchemaEmission, validateEachIteration, body, query, params, output, iteration, handle, toJSONSchema, validate, }) {
13
+ const disableServerSideValidationKeys = disableServerSideValidation === false
14
+ ? []
15
+ : disableServerSideValidation === true
16
+ ? validationTypes
17
+ : (disableServerSideValidation ?? []);
18
+ const skipSchemaEmissionKeys = skipSchemaEmission === false ? [] : skipSchemaEmission === true ? validationTypes : (skipSchemaEmission ?? []);
19
+ const outputHandler = async (req, handlerParams) => {
20
+ const { __disableValidation } = req.vovk.meta();
21
+ const data = await handle(req, handlerParams);
22
+ if (__disableValidation) {
23
+ return data;
24
+ }
25
+ if (output && iteration) {
26
+ throw new HttpException_js_1.HttpException(types_js_1.HttpStatus.INTERNAL_SERVER_ERROR, "Output and iteration are mutually exclusive. You can't use them together.");
27
+ }
28
+ if (output && !disableServerSideValidationKeys.includes('output')) {
29
+ if (!data) {
30
+ throw new HttpException_js_1.HttpException(types_js_1.HttpStatus.INTERNAL_SERVER_ERROR, 'Output is required. You probably forgot to return something from your handler.');
31
+ }
32
+ await validate(data, output, { type: 'output', req });
33
+ }
34
+ if (iteration && !disableServerSideValidationKeys.includes('iteration')) {
35
+ // We assume `data` is an async iterable here; you might want to check that:
36
+ if (!data || typeof data[Symbol.asyncIterator] !== 'function') {
37
+ throw new HttpException_js_1.HttpException(types_js_1.HttpStatus.INTERNAL_SERVER_ERROR, 'Data is not an async iterable but iteration validation is defined.');
38
+ }
39
+ // Return a brand-new async generator that yields validated items
40
+ return (async function* () {
41
+ let i = 0;
42
+ for await (const item of data) {
43
+ if (validateEachIteration || i === 0) {
44
+ await validate(item, iteration, { type: 'iteration', req, status: 200, i });
45
+ }
46
+ i++;
47
+ yield item;
48
+ }
49
+ })();
50
+ }
51
+ else if (validateEachIteration) {
52
+ throw new HttpException_js_1.HttpException(types_js_1.HttpStatus.INTERNAL_SERVER_ERROR, 'validateEachIteration is set but iteration is not defined.');
53
+ }
54
+ return data;
55
+ };
56
+ const resultHandler = (async (req, handlerParams) => {
57
+ const { __disableValidation } = req.vovk.meta();
58
+ if (!__disableValidation) {
59
+ if (body && !disableServerSideValidationKeys.includes('body')) {
60
+ const data = await req.vovk[isForm ? 'form' : 'body']();
61
+ const instance = (await validate(data, body, { type: isForm ? 'form' : 'body', req })) ?? data;
62
+ // redeclare to add ability to call req.json() and req.vovk.body() again
63
+ req.json = () => Promise.resolve(data);
64
+ req.vovk[isForm ? 'form' : 'body'] = () => Promise.resolve(instance);
65
+ }
66
+ if (query && !disableServerSideValidationKeys.includes('query')) {
67
+ const data = req.vovk.query();
68
+ const instance = (await validate(data, query, { type: 'query', req })) ?? data;
69
+ req.vovk.query = () => instance;
70
+ }
71
+ if (params && !disableServerSideValidationKeys.includes('params')) {
72
+ const data = req.vovk.params();
73
+ const instance = (await validate(data, params, { type: 'params', req })) ?? data;
74
+ req.vovk.params = () => instance;
75
+ }
76
+ }
77
+ return outputHandler(req, handlerParams);
78
+ });
79
+ function func(input) {
80
+ const fakeReq = {
81
+ vovk: {
82
+ body: () => Promise.resolve(input.body),
83
+ query: () => input.query,
84
+ params: () => input.params,
85
+ meta: (meta) => (0, reqMeta_js_1.default)(fakeReq, meta),
86
+ form: () => {
87
+ throw new Error('Form data is not supported in this context.');
88
+ },
89
+ },
90
+ };
91
+ fakeReq.vovk.meta({ __disableValidation: input.disableValidation });
92
+ return resultHandler(fakeReq, input.params ?? {});
93
+ }
94
+ const models = {
95
+ body,
96
+ query,
97
+ params,
98
+ output,
99
+ iteration,
100
+ };
101
+ const resultHandlerEnhanced = Object.assign(resultHandler, { func, models });
102
+ if (toJSONSchema) {
103
+ const getJsonSchema = (model, type) => Object.assign(toJSONSchema(model, { type }), type === 'body' && isForm ? { 'x-formData': isForm } : {});
104
+ const validation = {};
105
+ if (body && !skipSchemaEmissionKeys.includes('body')) {
106
+ validation.body = getJsonSchema(body, 'body');
107
+ }
108
+ if (query && !skipSchemaEmissionKeys.includes('query')) {
109
+ validation.query = getJsonSchema(query, 'query');
110
+ }
111
+ if (params && !skipSchemaEmissionKeys.includes('params')) {
112
+ validation.params = getJsonSchema(params, 'params');
113
+ }
114
+ if (output && !skipSchemaEmissionKeys.includes('output')) {
115
+ validation.output = getJsonSchema(output, 'output');
116
+ }
117
+ if (iteration && !skipSchemaEmissionKeys.includes('iteration')) {
118
+ validation.iteration = getJsonSchema(iteration, 'iteration');
119
+ }
120
+ (0, setHandlerSchema_js_1.setHandlerSchema)(resultHandlerEnhanced, { validation });
121
+ }
122
+ return resultHandlerEnhanced;
123
+ }
package/package.json CHANGED
@@ -1,23 +1,40 @@
1
1
  {
2
2
  "name": "vovk",
3
- "version": "3.0.0-draft.21",
4
- "description": "RESTful RPC for Next.js - Transforms Next.js into a powerful REST API platform with RPC capabilities.",
3
+ "version": "3.0.0-draft.211",
4
+ "main": "./cjs/index.js",
5
+ "module": "./mjs/index.js",
6
+ "types": "./mjs/index.d.ts",
7
+ "bin": {
8
+ "vovk-cli-npx": "./bin/index.mjs"
9
+ },
10
+ "exports": {
11
+ ".": {
12
+ "import": "./mjs/index.js",
13
+ "require": "./cjs/index.js",
14
+ "types": "./mjs/index.d.ts"
15
+ }
16
+ },
17
+ "description": "RESTful RPC for Next.js",
5
18
  "repository": {
6
19
  "type": "git",
7
20
  "url": "git+https://github.com/finom/vovk.git"
8
21
  },
9
22
  "scripts": {
10
- "build": "rm -rf dist && tsc && cp {package.json,LICENSE,.npmignore} dist && cp ../../README.md dist",
23
+ "postbuild": "shx chmod +x ./bin/index.mjs",
24
+ "build": "shx rm -f *.tsbuildinfo && npm run build:cjs && npm run build:esm",
25
+ "build:esm": "tsc --module NodeNext --outDir mjs --moduleResolution nodenext",
26
+ "build:cjs": "tsc --module commonjs --outDir cjs",
27
+ "rm-dist": "shx rm -rf mjs cjs",
11
28
  "lint": "eslint . --fix",
12
29
  "tsc": "tsc --noEmit",
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 ..",
30
+ "npm-publish": "if [ -z \"$NPM_TAG\" ]; then echo 'Error: NPM_TAG is not set'; exit 1; fi; npm publish --tag=$NPM_TAG",
14
31
  "ncu": "npm-check-updates -u"
15
32
  },
16
33
  "keywords": [
17
34
  "nextjs",
18
35
  "router"
19
36
  ],
20
- "author": "Andrii Gubanov",
37
+ "author": "Andrey Gubanov",
21
38
  "license": "MIT",
22
39
  "bugs": {
23
40
  "url": "https://github.com/finom/vovk/issues"
@@ -25,5 +42,13 @@
25
42
  "homepage": "https://vovk.dev",
26
43
  "peerDependencies": {
27
44
  "next": "*"
45
+ },
46
+ "devDependencies": {
47
+ "type-fest": "*"
48
+ },
49
+ "dependencies": {
50
+ "@standard-schema/spec": "^1.0.0",
51
+ "@stoplight/json-schema-sampler": "^0.3.0",
52
+ "openapi3-ts": "^4.4.0"
28
53
  }
29
54
  }
package/.npmignore DELETED
@@ -1,2 +0,0 @@
1
- !*
2
- tsconfig.*
package/Segment.js DELETED
@@ -1,182 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- var _a;
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- exports._Segment = void 0;
8
- const types_1 = require("./types");
9
- const HttpException_1 = require("./HttpException");
10
- const StreamJSONResponse_1 = require("./StreamJSONResponse");
11
- const reqQuery_1 = __importDefault(require("./utils/reqQuery"));
12
- const reqMeta_1 = __importDefault(require("./utils/reqMeta"));
13
- class _Segment {
14
- static getHeadersFromOptions(options) {
15
- if (!options)
16
- return {};
17
- const corsHeaders = {
18
- 'Access-Control-Allow-Origin': '*',
19
- 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS, HEAD',
20
- 'Access-Control-Allow-Headers': 'Content-Type, Authorization',
21
- };
22
- const headers = {
23
- ...(options.cors ? corsHeaders : {}),
24
- ...(options.headers ?? {}),
25
- };
26
- return headers;
27
- }
28
- _routes = {
29
- GET: new Map(),
30
- POST: new Map(),
31
- PUT: new Map(),
32
- PATCH: new Map(),
33
- DELETE: new Map(),
34
- HEAD: new Map(),
35
- OPTIONS: new Map(),
36
- };
37
- GET = async (req, data) => this.#callMethod(types_1._HttpMethod.GET, req, await data.params);
38
- POST = async (req, data) => this.#callMethod(types_1._HttpMethod.POST, req, await data.params);
39
- PUT = async (req, data) => this.#callMethod(types_1._HttpMethod.PUT, req, await data.params);
40
- PATCH = async (req, data) => this.#callMethod(types_1._HttpMethod.PATCH, req, await data.params);
41
- DELETE = async (req, data) => this.#callMethod(types_1._HttpMethod.DELETE, req, await data.params);
42
- HEAD = async (req, data) => this.#callMethod(types_1._HttpMethod.HEAD, req, await data.params);
43
- OPTIONS = async (req, data) => this.#callMethod(types_1._HttpMethod.OPTIONS, req, await data.params);
44
- respond = (status, body, options) => {
45
- return new Response(JSON.stringify(body), {
46
- status,
47
- headers: {
48
- 'Content-Type': 'application/json',
49
- ..._a.getHeadersFromOptions(options),
50
- },
51
- });
52
- };
53
- #respondWithError = (statusCode, message, options) => {
54
- return this.respond(statusCode, {
55
- statusCode,
56
- message,
57
- isError: true,
58
- }, options);
59
- };
60
- #callMethod = async (httpMethod, req, params) => {
61
- const controllers = this._routes[httpMethod];
62
- const methodParams = {};
63
- const path = params[Object.keys(params)[0]];
64
- const handlers = {};
65
- controllers.forEach((staticMethods, controller) => {
66
- const prefix = controller._prefix ?? '';
67
- if (!controller._activated) {
68
- throw new HttpException_1._HttpException(types_1._HttpStatus.INTERNAL_SERVER_ERROR, `Controller "${controller.name}" found but not activated`);
69
- }
70
- Object.entries(staticMethods).forEach(([path, staticMethod]) => {
71
- const fullPath = [prefix, path].filter(Boolean).join('/');
72
- handlers[fullPath] = { staticMethod, controller };
73
- });
74
- });
75
- const getHandler = () => {
76
- if (Object.keys(params).length === 0) {
77
- return handlers[''];
78
- }
79
- const allMethodKeys = Object.keys(handlers);
80
- let methodKeys = [];
81
- methodKeys = allMethodKeys
82
- // First, try to match literal routes exactly.
83
- .filter((p) => {
84
- if (p.includes(':'))
85
- return false; // Skip parameterized paths
86
- return p === path.join('/');
87
- });
88
- if (!methodKeys.length) {
89
- methodKeys = allMethodKeys.filter((p) => {
90
- const routeSegments = p.split('/');
91
- if (routeSegments.length !== path.length)
92
- return false;
93
- for (let i = 0; i < routeSegments.length; i++) {
94
- const routeSegment = routeSegments[i];
95
- const pathSegment = path[i];
96
- if (routeSegment.startsWith(':')) {
97
- const parameter = routeSegment.slice(1);
98
- if (parameter in methodParams) {
99
- throw new HttpException_1._HttpException(types_1._HttpStatus.INTERNAL_SERVER_ERROR, `Duplicate parameter "${parameter}"`);
100
- }
101
- // If it's a parameterized segment, capture the parameter value.
102
- methodParams[parameter] = pathSegment;
103
- }
104
- else if (routeSegment !== pathSegment) {
105
- // If it's a literal segment and it does not match the corresponding path segment, return false.
106
- return false;
107
- }
108
- }
109
- return true;
110
- });
111
- }
112
- if (methodKeys.length > 1) {
113
- throw new HttpException_1._HttpException(types_1._HttpStatus.INTERNAL_SERVER_ERROR, `Conflicting routes found: ${methodKeys.join(', ')}`);
114
- }
115
- const [methodKey] = methodKeys;
116
- if (methodKey) {
117
- return handlers[methodKey];
118
- }
119
- return null;
120
- };
121
- const handler = getHandler();
122
- if (!handler) {
123
- return this.#respondWithError(types_1._HttpStatus.NOT_FOUND, `Route ${path.join('/')} is not found`);
124
- }
125
- const { staticMethod, controller } = handler;
126
- req.vovk = {
127
- body: () => req.json(),
128
- query: () => (0, reqQuery_1.default)(req),
129
- meta: (meta) => (0, reqMeta_1.default)(req, meta),
130
- };
131
- try {
132
- const result = await staticMethod.call(controller, req, methodParams);
133
- const isIterator = typeof result === 'object' &&
134
- !!result &&
135
- ((Reflect.has(result, Symbol.iterator) &&
136
- typeof result[Symbol.iterator] === 'function') ||
137
- (Reflect.has(result, Symbol.asyncIterator) &&
138
- typeof result[Symbol.asyncIterator] === 'function'));
139
- if (isIterator && !(result instanceof Array)) {
140
- const streamResponse = new StreamJSONResponse_1._StreamJSONResponse({
141
- headers: {
142
- ...StreamJSONResponse_1._StreamJSONResponse.defaultHeaders,
143
- ..._a.getHeadersFromOptions(staticMethod._options),
144
- },
145
- });
146
- void (async () => {
147
- try {
148
- for await (const chunk of result) {
149
- streamResponse.send(chunk);
150
- }
151
- }
152
- catch (e) {
153
- return streamResponse.throw(e);
154
- }
155
- return streamResponse.close();
156
- })();
157
- return streamResponse;
158
- }
159
- if (result instanceof Response) {
160
- return result;
161
- }
162
- return this.respond(200, result ?? null, staticMethod._options);
163
- }
164
- catch (e) {
165
- const err = e;
166
- try {
167
- await controller._onError?.(err, req);
168
- }
169
- catch (onErrorError) {
170
- // eslint-disable-next-line no-console
171
- console.error(onErrorError);
172
- }
173
- if (err.message !== 'NEXT_REDIRECT' && err.message !== 'NEXT_NOT_FOUND') {
174
- const statusCode = err.statusCode ?? types_1._HttpStatus.INTERNAL_SERVER_ERROR;
175
- return this.#respondWithError(statusCode, err.message, staticMethod._options);
176
- }
177
- throw e; // if NEXT_REDIRECT or NEXT_NOT_FOUND, rethrow it
178
- }
179
- };
180
- }
181
- exports._Segment = _Segment;
182
- _a = _Segment;
@@ -1,17 +0,0 @@
1
- import { _KnownAny as KnownAny, _StreamAbortMessage as StreamAbortMessage } from './types';
2
- import './utils/shim';
3
- export declare class _StreamJSONResponse<T> extends Response {
4
- static defaultHeaders: {
5
- 'content-type': string;
6
- 'x-vovk-stream': string;
7
- };
8
- isClosed: boolean;
9
- controller?: ReadableStreamDefaultController;
10
- readonly encoder: TextEncoder;
11
- readonly readableStream: ReadableStream;
12
- constructor(init?: ResponseInit);
13
- send(data: T | StreamAbortMessage): void;
14
- close(): void;
15
- throw(e: KnownAny): void;
16
- [Symbol.dispose](): void;
17
- }
@@ -1,4 +0,0 @@
1
- import { type _VovkControllerSchema as VovkControllerSchema, type _KnownAny as KnownAny } from '../types';
2
- import { type _VovkClientOptions as VovkClientOptions, type _VovkClient as VovkClient, type _VovkDefaultFetcherOptions as VovkDefaultFetcherOptions } from './types';
3
- export declare const ARRAY_QUERY_KEY = "_vovkarr";
4
- export declare const _clientizeController: <T, OPTS extends Record<string, KnownAny> = VovkDefaultFetcherOptions>(controllerSchema: VovkControllerSchema, segmentName?: string, options?: VovkClientOptions<OPTS>) => VovkClient<T, OPTS>;