vovk 3.4.0 → 3.4.1

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 (43) hide show
  1. package/dist/core/compose.d.ts +38 -0
  2. package/dist/core/compose.js +31 -0
  3. package/dist/internal.d.ts +1 -0
  4. package/dist/internal.js +1 -0
  5. package/dist/openapi/openAPIToVovkSchema/applyComponentsSchemas.d.ts +21 -1
  6. package/dist/openapi/openAPIToVovkSchema/applyComponentsSchemas.js +37 -12
  7. package/dist/openapi/openAPIToVovkSchema/index.js +3 -2
  8. package/dist/tsconfig.tsbuildinfo +1 -1
  9. package/package.json +1 -1
  10. package/dist/HttpException.d.ts +0 -7
  11. package/dist/HttpException.js +0 -15
  12. package/dist/JSONLinesResponse.d.ts +0 -14
  13. package/dist/JSONLinesResponse.js +0 -59
  14. package/dist/VovkApp.d.ts +0 -29
  15. package/dist/VovkApp.js +0 -189
  16. package/dist/client/index.d.ts +0 -3
  17. package/dist/client/index.js +0 -7
  18. package/dist/client/types.d.ts +0 -102
  19. package/dist/client/types.js +0 -2
  20. package/dist/createDecorator.d.ts +0 -6
  21. package/dist/createDecorator.js +0 -43
  22. package/dist/createVovkApp.d.ts +0 -62
  23. package/dist/createVovkApp.js +0 -129
  24. package/dist/types.d.ts +0 -239
  25. package/dist/types.js +0 -66
  26. package/dist/utils/generateStaticAPI.d.ts +0 -4
  27. package/dist/utils/generateStaticAPI.js +0 -30
  28. package/dist/utils/getSchema.d.ts +0 -20
  29. package/dist/utils/getSchema.js +0 -33
  30. package/dist/utils/parseQuery.d.ts +0 -25
  31. package/dist/utils/parseQuery.js +0 -156
  32. package/dist/utils/reqForm.d.ts +0 -2
  33. package/dist/utils/reqForm.js +0 -32
  34. package/dist/utils/reqMeta.d.ts +0 -2
  35. package/dist/utils/reqMeta.js +0 -13
  36. package/dist/utils/reqQuery.d.ts +0 -2
  37. package/dist/utils/reqQuery.js +0 -10
  38. package/dist/utils/serializeQuery.d.ts +0 -13
  39. package/dist/utils/serializeQuery.js +0 -65
  40. package/dist/utils/setHandlerSchema.d.ts +0 -4
  41. package/dist/utils/setHandlerSchema.js +0 -15
  42. package/dist/utils/withValidation.d.ts +0 -21
  43. package/dist/utils/withValidation.js +0 -88
@@ -1,156 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.default = parseQuery;
4
- /**
5
- * Parse a bracket-based key (e.g. "z[d][0][x]" or "arr[]")
6
- * into an array of path segments (strings or special push-markers).
7
- *
8
- * Example: "z[d][0][x]" => ["z", "d", "0", "x"]
9
- * Example: "arr[]" => ["arr", "" ] // "" indicates "push" onto array
10
- */
11
- function parseKey(key) {
12
- // The first segment is everything up to the first '[' (or the entire key if no '[')
13
- const segments = [];
14
- const topKeyMatch = key.match(/^([^[\]]+)/);
15
- if (topKeyMatch) {
16
- segments.push(topKeyMatch[1]);
17
- }
18
- else {
19
- // If it starts with brackets, treat it as empty? (edge case)
20
- segments.push('');
21
- }
22
- // Now capture all bracket parts: [something], [0], []
23
- const bracketRegex = /\[([^[\]]*)\]/g;
24
- let match;
25
- while ((match = bracketRegex.exec(key)) !== null) {
26
- // match[1] is the content inside the brackets
27
- segments.push(match[1]);
28
- }
29
- return segments;
30
- }
31
- /**
32
- * Recursively set a value in a nested object/array, given a path of segments.
33
- * - If segment is numeric => treat as array index
34
- * - If segment is empty "" => push to array
35
- * - Else => object property
36
- */
37
- function setValue(obj, path, value) {
38
- let current = obj;
39
- for (let i = 0; i < path.length; i++) {
40
- const segment = path[i];
41
- // If we're at the last segment, set the value
42
- if (i === path.length - 1) {
43
- if (segment === '') {
44
- // Empty bracket => push
45
- if (!Array.isArray(current)) {
46
- current = [];
47
- }
48
- current.push(value);
49
- }
50
- else if (!isNaN(Number(segment))) {
51
- // Numeric segment => array index
52
- const idx = Number(segment);
53
- if (!Array.isArray(current)) {
54
- current = [];
55
- }
56
- current[idx] = value;
57
- }
58
- else {
59
- // Object property
60
- current[segment] = value;
61
- }
62
- }
63
- else {
64
- // Not the last segment: descend into existing structure or create it
65
- const nextSegment = path[i + 1];
66
- if (segment === '') {
67
- // Empty bracket => push
68
- if (!Array.isArray(current)) {
69
- // Convert the current node into an array, if not one
70
- current = [];
71
- }
72
- // If we are not at the last path, we need a placeholder object or array
73
- // for the next segment. We'll push something and move current to that.
74
- if (current.length === 0) {
75
- // nothing in array yet
76
- current.push(typeof nextSegment === 'string' && !isNaN(Number(nextSegment)) ? [] : {});
77
- }
78
- else if (typeof nextSegment === 'string' && !isNaN(Number(nextSegment))) {
79
- // next is numeric => we want an array
80
- if (!Array.isArray(current[current.length - 1])) {
81
- current[current.length - 1] = [];
82
- }
83
- }
84
- else {
85
- // next is not numeric => we want an object
86
- if (typeof current[current.length - 1] !== 'object') {
87
- current[current.length - 1] = {};
88
- }
89
- }
90
- current = current[current.length - 1];
91
- }
92
- else if (!isNaN(Number(segment))) {
93
- // segment is numeric => array index
94
- const idx = Number(segment);
95
- if (!Array.isArray(current)) {
96
- current = [];
97
- }
98
- if (current[idx] === undefined) {
99
- // Create placeholder for next segment
100
- current[idx] = typeof nextSegment === 'string' && !isNaN(Number(nextSegment)) ? [] : {};
101
- }
102
- current = current[idx];
103
- }
104
- else {
105
- // segment is an object key
106
- if (current[segment] === undefined) {
107
- // Create placeholder
108
- current[segment] = typeof nextSegment === 'string' && !isNaN(Number(nextSegment)) ? [] : {};
109
- }
110
- current = current[segment];
111
- }
112
- }
113
- }
114
- }
115
- /**
116
- * Deserialize a bracket-based query string into an object.
117
- *
118
- * Supports:
119
- * - Key/value pairs with nested brackets (e.g. "a[b][0]=value")
120
- * - Arrays with empty bracket (e.g. "arr[]=1&arr[]=2")
121
- * - Mixed arrays of objects, etc.
122
- *
123
- * @example
124
- * parseQuery("x=xx&y[0]=yy&y[1]=uu&z[f]=x&z[u][0]=uu&z[u][1]=xx&z[d][x]=ee")
125
- * => {
126
- * x: "xx",
127
- * y: ["yy", "uu"],
128
- * z: {
129
- * f: "x",
130
- * u: ["uu", "xx"],
131
- * d: { x: "ee" }
132
- * }
133
- * }
134
- *
135
- * @param queryString - The raw query string (e.g. location.search.slice(1))
136
- * @returns - A nested object representing the query params
137
- */
138
- function parseQuery(queryString) {
139
- const result = {};
140
- if (!queryString)
141
- return result;
142
- // Split into key=value pairs
143
- const pairs = queryString
144
- .replace(/^\?/, '') // Remove leading "?" if present
145
- .split('&');
146
- for (const pair of pairs) {
147
- const [rawKey, rawVal = ''] = pair.split('=');
148
- const decodedKey = decodeURIComponent(rawKey || '');
149
- const decodedVal = decodeURIComponent(rawVal);
150
- // Parse bracket notation
151
- const pathSegments = parseKey(decodedKey);
152
- // Insert into the result object
153
- setValue(result, pathSegments, decodedVal);
154
- }
155
- return result;
156
- }
@@ -1,2 +0,0 @@
1
- import type { KnownAny, VovkRequest } from '../types';
2
- export default function reqForm<T = KnownAny>(req: VovkRequest<KnownAny, KnownAny>): Promise<T>;
@@ -1,32 +0,0 @@
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 = {};
11
- for (const [key, value] of body.entries()) {
12
- if (value instanceof File) {
13
- // If this key already exists, convert to array or append to existing array
14
- if (formData[key]) {
15
- if (Array.isArray(formData[key])) {
16
- formData[key].push(value);
17
- }
18
- else {
19
- formData[key] = [formData[key], value];
20
- }
21
- }
22
- else {
23
- formData[key] = value;
24
- }
25
- }
26
- else {
27
- formData[key] = value.toString();
28
- }
29
- }
30
- formMap.set(req, formData);
31
- return formData;
32
- }
@@ -1,2 +0,0 @@
1
- import type { KnownAny, VovkRequest } from '../types';
2
- export default function reqMeta<T = Record<KnownAny, KnownAny>>(req: VovkRequest<KnownAny, KnownAny>, meta?: T | null): T;
@@ -1,13 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.default = reqMeta;
4
- const metaMap = new WeakMap();
5
- function reqMeta(req, meta) {
6
- if (meta) {
7
- metaMap.set(req, { ...metaMap.get(req), ...meta });
8
- }
9
- else if (meta === null) {
10
- metaMap.delete(req);
11
- }
12
- return (metaMap.get(req) ?? {});
13
- }
@@ -1,2 +0,0 @@
1
- import type { KnownAny, VovkRequest } from '../types';
2
- export default function reqQuery<T extends object | undefined>(req: VovkRequest<KnownAny, T>): T;
@@ -1,10 +0,0 @@
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.default = reqQuery;
7
- const parseQuery_1 = __importDefault(require("./parseQuery"));
8
- function reqQuery(req) {
9
- return (0, parseQuery_1.default)(req.nextUrl.search);
10
- }
@@ -1,13 +0,0 @@
1
- import type { KnownAny } from '../types';
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;
@@ -1,65 +0,0 @@
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
- }
@@ -1,4 +0,0 @@
1
- import type { KnownAny, VovkController, VovkHandlerSchema } from '../types';
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>;
@@ -1,15 +0,0 @@
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
- }
@@ -1,21 +0,0 @@
1
- import { VovkValidationType, type KnownAny, type VovkRequest } from '../types';
2
- export declare function withValidation<T extends (req: KnownAny, params: KnownAny) => KnownAny, BODY_MODEL, QUERY_MODEL, PARAMS_MODEL, OUTPUT_MODEL, ITERATION_MODEL>({ disableServerSideValidation, skipSchemaEmission, validateEachIteration, body, query, params, output, iteration, handle, getJSONSchemaFromModel, validate, }: {
3
- disableServerSideValidation?: boolean | VovkValidationType[];
4
- skipSchemaEmission?: boolean | VovkValidationType[];
5
- validateEachIteration?: boolean;
6
- body?: BODY_MODEL;
7
- query?: QUERY_MODEL;
8
- params?: PARAMS_MODEL;
9
- output?: OUTPUT_MODEL;
10
- iteration?: ITERATION_MODEL;
11
- handle: T;
12
- getJSONSchemaFromModel?: (model: NonNullable<BODY_MODEL | QUERY_MODEL | PARAMS_MODEL | OUTPUT_MODEL | ITERATION_MODEL>, meta: {
13
- type: VovkValidationType;
14
- }) => KnownAny;
15
- validate: (data: KnownAny, model: NonNullable<BODY_MODEL | QUERY_MODEL | PARAMS_MODEL | OUTPUT_MODEL | ITERATION_MODEL>, meta: {
16
- type: VovkValidationType;
17
- req: VovkRequest<KnownAny, KnownAny>;
18
- status?: number;
19
- i?: number;
20
- }) => KnownAny;
21
- }): T;
@@ -1,88 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.withValidation = withValidation;
4
- const HttpException_1 = require("../HttpException");
5
- const types_1 = require("../types");
6
- const setHandlerSchema_1 = require("./setHandlerSchema");
7
- const validationTypes = ['body', 'query', 'params', 'output', 'iteration'];
8
- function withValidation({ disableServerSideValidation, skipSchemaEmission, validateEachIteration, body, query, params, output, iteration, handle, getJSONSchemaFromModel, validate, }) {
9
- const disableServerSideValidationKeys = disableServerSideValidation === false
10
- ? []
11
- : disableServerSideValidation === true
12
- ? validationTypes
13
- : (disableServerSideValidation ?? []);
14
- const skipSchemaEmissionKeys = skipSchemaEmission === false ? [] : skipSchemaEmission === true ? validationTypes : (skipSchemaEmission ?? []);
15
- const outputHandler = async (req, handlerParams) => {
16
- const data = await handle(req, handlerParams);
17
- if (output && iteration) {
18
- throw new HttpException_1.HttpException(types_1.HttpStatus.INTERNAL_SERVER_ERROR, "Output and iteration are mutually exclusive. You can't use them together.");
19
- }
20
- if (output && !disableServerSideValidationKeys.includes('output')) {
21
- if (!data) {
22
- throw new HttpException_1.HttpException(types_1.HttpStatus.INTERNAL_SERVER_ERROR, 'Output is required. You probably forgot to return something from your handler.');
23
- }
24
- await validate(data, output, { type: 'output', req });
25
- }
26
- if (iteration && !disableServerSideValidationKeys.includes('iteration')) {
27
- // We assume `data` is an async iterable here; you might want to check that:
28
- if (!data || typeof data[Symbol.asyncIterator] !== 'function') {
29
- throw new HttpException_1.HttpException(types_1.HttpStatus.INTERNAL_SERVER_ERROR, 'Data is not an async iterable but iteration validation is defined.');
30
- }
31
- // Return a brand-new async generator that yields validated items
32
- return (async function* () {
33
- let i = 0;
34
- for await (const item of data) {
35
- if (validateEachIteration || i === 0) {
36
- await validate(item, iteration, { type: 'iteration', req, status: 200, i });
37
- }
38
- i++;
39
- yield item;
40
- }
41
- })();
42
- }
43
- else if (validateEachIteration) {
44
- throw new HttpException_1.HttpException(types_1.HttpStatus.INTERNAL_SERVER_ERROR, 'validateEachIteration is set but iteration is not defined.');
45
- }
46
- return data;
47
- };
48
- const resultHandler = async (req, handlerParams) => {
49
- if (body && !disableServerSideValidationKeys.includes('body')) {
50
- const data = await req.json();
51
- const instance = (await validate(data, body, { type: 'body', req })) ?? data;
52
- // redeclare to add ability to call req.json() again
53
- req.json = () => Promise.resolve(data);
54
- req.vovk.body = () => Promise.resolve(instance);
55
- }
56
- if (query && !disableServerSideValidationKeys.includes('query')) {
57
- const data = req.vovk.query();
58
- const instance = (await validate(data, query, { type: 'query', req })) ?? data;
59
- req.vovk.query = () => instance;
60
- }
61
- if (params && !disableServerSideValidationKeys.includes('params')) {
62
- const data = req.vovk.params();
63
- const instance = (await validate(data, params, { type: 'params', req })) ?? data;
64
- req.vovk.params = () => instance;
65
- }
66
- return outputHandler(req, handlerParams);
67
- };
68
- if (getJSONSchemaFromModel) {
69
- const validation = {};
70
- if (body && !skipSchemaEmissionKeys.includes('body')) {
71
- validation.body = getJSONSchemaFromModel(body, { type: 'body' });
72
- }
73
- if (query && !skipSchemaEmissionKeys.includes('query')) {
74
- validation.query = getJSONSchemaFromModel(query, { type: 'query' });
75
- }
76
- if (params && !skipSchemaEmissionKeys.includes('params')) {
77
- validation.params = getJSONSchemaFromModel(params, { type: 'params' });
78
- }
79
- if (output && !skipSchemaEmissionKeys.includes('output')) {
80
- validation.output = getJSONSchemaFromModel(output, { type: 'output' });
81
- }
82
- if (iteration && !skipSchemaEmissionKeys.includes('iteration')) {
83
- validation.iteration = getJSONSchemaFromModel(iteration, { type: 'iteration' });
84
- }
85
- (0, setHandlerSchema_1.setHandlerSchema)(resultHandler, { validation });
86
- }
87
- return resultHandler;
88
- }