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.
- package/LICENSE +1 -1
- package/README.md +8 -96
- package/bin/index.mjs +8 -0
- package/{HttpException.d.ts → cjs/HttpException.d.ts} +2 -2
- package/{HttpException.js → cjs/HttpException.js} +3 -3
- package/cjs/JSONLinesResponse.d.ts +14 -0
- package/{StreamJSONResponse.js → cjs/JSONLinesResponse.js} +15 -10
- package/{Segment.d.ts → cjs/VovkApp.d.ts} +11 -10
- package/cjs/VovkApp.js +189 -0
- package/cjs/client/createRPC.d.ts +3 -0
- package/cjs/client/createRPC.js +87 -0
- package/{client → cjs/client}/defaultHandler.d.ts +1 -1
- package/cjs/client/defaultHandler.js +22 -0
- package/cjs/client/defaultStreamHandler.d.ts +4 -0
- package/{client → cjs/client}/defaultStreamHandler.js +11 -12
- package/cjs/client/fetcher.d.ts +13 -0
- package/cjs/client/fetcher.js +90 -0
- package/cjs/client/index.d.ts +3 -0
- package/cjs/client/index.js +8 -0
- package/cjs/client/types.d.ts +111 -0
- package/{createSegment.d.ts → cjs/createVovkApp.d.ts} +11 -10
- package/cjs/createVovkApp.js +132 -0
- package/cjs/index.d.ts +65 -0
- package/cjs/index.js +37 -0
- package/cjs/openapi/error.d.ts +2 -0
- package/cjs/openapi/error.js +100 -0
- package/cjs/openapi/generateFnName.d.ts +23 -0
- package/cjs/openapi/generateFnName.js +81 -0
- package/cjs/openapi/index.d.ts +12 -0
- package/cjs/openapi/index.js +21 -0
- package/cjs/openapi/openAPIToVovkSchema.d.ts +2 -0
- package/cjs/openapi/openAPIToVovkSchema.js +197 -0
- package/cjs/openapi/vovkSchemaToOpenAPI.d.ts +9 -0
- package/cjs/openapi/vovkSchemaToOpenAPI.js +237 -0
- package/cjs/types.d.ts +364 -0
- package/cjs/types.js +74 -0
- package/cjs/utils/camelCase.d.ts +6 -0
- package/cjs/utils/camelCase.js +37 -0
- package/cjs/utils/createCodeExamples.d.ts +19 -0
- package/cjs/utils/createCodeExamples.js +114 -0
- package/cjs/utils/createDecorator.d.ts +6 -0
- package/{createDecorator.js → cjs/utils/createDecorator.js} +24 -16
- package/cjs/utils/createLLMFunctions.d.ts +20 -0
- package/cjs/utils/createLLMFunctions.js +100 -0
- package/cjs/utils/generateStaticAPI.d.ts +4 -0
- package/cjs/utils/generateStaticAPI.js +30 -0
- package/cjs/utils/getSchema.d.ts +21 -0
- package/cjs/utils/getSchema.js +43 -0
- package/cjs/utils/multitenant.d.ts +24 -0
- package/cjs/utils/multitenant.js +170 -0
- package/cjs/utils/parseQuery.d.ts +25 -0
- package/cjs/utils/parseQuery.js +156 -0
- package/cjs/utils/reqForm.d.ts +2 -0
- package/cjs/utils/reqForm.js +33 -0
- package/{utils → cjs/utils}/reqMeta.d.ts +1 -2
- package/cjs/utils/reqQuery.d.ts +2 -0
- package/cjs/utils/reqQuery.js +10 -0
- package/cjs/utils/serializeQuery.d.ts +13 -0
- package/cjs/utils/serializeQuery.js +65 -0
- package/cjs/utils/setHandlerSchema.d.ts +4 -0
- package/cjs/utils/setHandlerSchema.js +15 -0
- package/cjs/utils/withStandard.d.ts +51 -0
- package/cjs/utils/withStandard.js +30 -0
- package/cjs/utils/withValidationLibrary.d.ts +49 -0
- package/cjs/utils/withValidationLibrary.js +123 -0
- package/mjs/HttpException.d.ts +7 -0
- package/mjs/HttpException.js +15 -0
- package/mjs/JSONLinesResponse.d.ts +14 -0
- package/mjs/JSONLinesResponse.js +59 -0
- package/mjs/VovkApp.d.ts +29 -0
- package/mjs/VovkApp.js +189 -0
- package/mjs/client/createRPC.d.ts +3 -0
- package/mjs/client/createRPC.js +87 -0
- package/mjs/client/defaultHandler.d.ts +2 -0
- package/mjs/client/defaultHandler.js +22 -0
- package/mjs/client/defaultStreamHandler.d.ts +4 -0
- package/mjs/client/defaultStreamHandler.js +81 -0
- package/mjs/client/fetcher.d.ts +13 -0
- package/mjs/client/fetcher.js +90 -0
- package/mjs/client/index.d.ts +3 -0
- package/mjs/client/index.js +8 -0
- package/mjs/client/types.d.ts +111 -0
- package/mjs/createVovkApp.d.ts +63 -0
- package/mjs/createVovkApp.js +132 -0
- package/mjs/index.d.ts +65 -0
- package/mjs/index.js +37 -0
- package/mjs/openapi/error.d.ts +2 -0
- package/mjs/openapi/error.js +100 -0
- package/mjs/openapi/generateFnName.d.ts +23 -0
- package/mjs/openapi/generateFnName.js +81 -0
- package/mjs/openapi/index.d.ts +12 -0
- package/mjs/openapi/index.js +21 -0
- package/mjs/openapi/openAPIToVovkSchema.d.ts +2 -0
- package/mjs/openapi/openAPIToVovkSchema.js +197 -0
- package/mjs/openapi/vovkSchemaToOpenAPI.d.ts +9 -0
- package/mjs/openapi/vovkSchemaToOpenAPI.js +237 -0
- package/mjs/types.d.ts +364 -0
- package/mjs/types.js +74 -0
- package/mjs/utils/camelCase.d.ts +6 -0
- package/mjs/utils/camelCase.js +37 -0
- package/mjs/utils/createCodeExamples.d.ts +19 -0
- package/mjs/utils/createCodeExamples.js +114 -0
- package/mjs/utils/createDecorator.d.ts +6 -0
- package/mjs/utils/createDecorator.js +46 -0
- package/mjs/utils/createLLMFunctions.d.ts +20 -0
- package/mjs/utils/createLLMFunctions.js +100 -0
- package/mjs/utils/generateStaticAPI.d.ts +4 -0
- package/mjs/utils/generateStaticAPI.js +30 -0
- package/mjs/utils/getSchema.d.ts +21 -0
- package/mjs/utils/getSchema.js +43 -0
- package/mjs/utils/multitenant.d.ts +24 -0
- package/mjs/utils/multitenant.js +170 -0
- package/mjs/utils/parseQuery.d.ts +25 -0
- package/mjs/utils/parseQuery.js +156 -0
- package/mjs/utils/reqForm.d.ts +2 -0
- package/mjs/utils/reqForm.js +33 -0
- package/mjs/utils/reqMeta.d.ts +2 -0
- package/mjs/utils/reqMeta.js +13 -0
- package/mjs/utils/reqQuery.d.ts +2 -0
- package/mjs/utils/reqQuery.js +10 -0
- package/mjs/utils/serializeQuery.d.ts +13 -0
- package/mjs/utils/serializeQuery.js +65 -0
- package/mjs/utils/setHandlerSchema.d.ts +4 -0
- package/mjs/utils/setHandlerSchema.js +15 -0
- package/mjs/utils/shim.d.ts +1 -0
- package/mjs/utils/shim.js +18 -0
- package/mjs/utils/withStandard.d.ts +51 -0
- package/mjs/utils/withStandard.js +30 -0
- package/mjs/utils/withValidationLibrary.d.ts +49 -0
- package/mjs/utils/withValidationLibrary.js +123 -0
- package/package.json +30 -5
- package/.npmignore +0 -2
- package/Segment.js +0 -182
- package/StreamJSONResponse.d.ts +0 -17
- package/client/clientizeController.d.ts +0 -4
- package/client/clientizeController.js +0 -92
- package/client/defaultFetcher.d.ts +0 -4
- package/client/defaultFetcher.js +0 -49
- package/client/defaultHandler.js +0 -21
- package/client/defaultStreamHandler.d.ts +0 -4
- package/client/index.d.ts +0 -4
- package/client/index.js +0 -5
- package/client/types.d.ts +0 -100
- package/createDecorator.d.ts +0 -4
- package/createSegment.js +0 -118
- package/generateStaticAPI.d.ts +0 -4
- package/generateStaticAPI.js +0 -18
- package/index.d.ts +0 -60
- package/index.js +0 -20
- package/types.d.ts +0 -155
- package/types.js +0 -65
- package/utils/getSchema.d.ts +0 -8
- package/utils/getSchema.js +0 -38
- package/utils/reqQuery.d.ts +0 -3
- package/utils/reqQuery.js +0 -25
- package/utils/setClientValidatorsForHandler.d.ts +0 -5
- package/utils/setClientValidatorsForHandler.js +0 -28
- package/worker/index.d.ts +0 -3
- package/worker/index.js +0 -7
- package/worker/promisifyWorker.d.ts +0 -2
- package/worker/promisifyWorker.js +0 -141
- package/worker/types.d.ts +0 -31
- package/worker/worker.d.ts +0 -1
- package/worker/worker.js +0 -43
- /package/{client → cjs/client}/types.js +0 -0
- /package/{utils → cjs/utils}/reqMeta.js +0 -0
- /package/{utils → cjs/utils}/shim.d.ts +0 -0
- /package/{utils → cjs/utils}/shim.js +0 -0
- /package/{worker → mjs/client}/types.js +0 -0
|
@@ -0,0 +1,33 @@
|
|
|
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
|
+
req.formData = () => Promise.resolve(body);
|
|
11
|
+
const formData = {};
|
|
12
|
+
for (const [key, value] of body.entries()) {
|
|
13
|
+
if (value instanceof File) {
|
|
14
|
+
// If this key already exists, convert to array or append to existing array
|
|
15
|
+
if (formData[key]) {
|
|
16
|
+
if (Array.isArray(formData[key])) {
|
|
17
|
+
formData[key].push(value);
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
formData[key] = [formData[key], value];
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
formData[key] = value;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
formData[key] = value.toString();
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
formMap.set(req, formData);
|
|
32
|
+
return formData;
|
|
33
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
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_js_1 = __importDefault(require("./parseQuery.js"));
|
|
8
|
+
function reqQuery(req) {
|
|
9
|
+
return (0, parseQuery_js_1.default)(req.nextUrl.search);
|
|
10
|
+
}
|
|
@@ -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,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
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HttpException = void 0;
|
|
4
|
+
class HttpException extends Error {
|
|
5
|
+
statusCode;
|
|
6
|
+
message;
|
|
7
|
+
cause;
|
|
8
|
+
constructor(statusCode, message, cause) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.statusCode = statusCode;
|
|
11
|
+
this.message = message;
|
|
12
|
+
this.cause = cause;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
exports.HttpException = HttpException;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { headers } from 'next/headers';
|
|
2
|
+
import type { KnownAny, StreamAbortMessage } from './types.js';
|
|
3
|
+
import './utils/shim.js';
|
|
4
|
+
export declare class JSONLinesResponse<T> extends Response {
|
|
5
|
+
isClosed: boolean;
|
|
6
|
+
controller?: ReadableStreamDefaultController;
|
|
7
|
+
readonly encoder: TextEncoder;
|
|
8
|
+
readonly readableStream: ReadableStream;
|
|
9
|
+
constructor(requestHeaders: Awaited<ReturnType<typeof headers>>, init?: ResponseInit);
|
|
10
|
+
send(data: T | StreamAbortMessage): void;
|
|
11
|
+
close(): void;
|
|
12
|
+
throw(e: KnownAny): void;
|
|
13
|
+
[Symbol.dispose](): void;
|
|
14
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.JSONLinesResponse = void 0;
|
|
4
|
+
require("./utils/shim.js");
|
|
5
|
+
class JSONLinesResponse extends Response {
|
|
6
|
+
isClosed = false;
|
|
7
|
+
controller;
|
|
8
|
+
encoder;
|
|
9
|
+
readableStream;
|
|
10
|
+
constructor(requestHeaders, init) {
|
|
11
|
+
const encoder = new TextEncoder();
|
|
12
|
+
let readableController;
|
|
13
|
+
const readableStream = new ReadableStream({
|
|
14
|
+
cancel: () => {
|
|
15
|
+
this.isClosed = true;
|
|
16
|
+
},
|
|
17
|
+
start: (controller) => {
|
|
18
|
+
readableController = controller;
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
if (!requestHeaders) {
|
|
22
|
+
throw new Error('Request headers are required');
|
|
23
|
+
}
|
|
24
|
+
const accept = requestHeaders.get('accept');
|
|
25
|
+
super(readableStream, {
|
|
26
|
+
...init,
|
|
27
|
+
headers: {
|
|
28
|
+
...init?.headers,
|
|
29
|
+
'Content-Type': accept?.includes('application/jsonl')
|
|
30
|
+
? 'application/jsonl; charset=utf-8'
|
|
31
|
+
: 'text/plain; charset=utf-8',
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
this.readableStream = readableStream;
|
|
35
|
+
this.encoder = encoder;
|
|
36
|
+
this.controller = readableController;
|
|
37
|
+
}
|
|
38
|
+
send(data) {
|
|
39
|
+
const { controller, encoder } = this;
|
|
40
|
+
if (this.isClosed)
|
|
41
|
+
return;
|
|
42
|
+
return controller?.enqueue(encoder.encode(JSON.stringify(data) + '\n'));
|
|
43
|
+
}
|
|
44
|
+
close() {
|
|
45
|
+
const { controller } = this;
|
|
46
|
+
if (this.isClosed)
|
|
47
|
+
return;
|
|
48
|
+
this.isClosed = true;
|
|
49
|
+
controller?.close();
|
|
50
|
+
}
|
|
51
|
+
throw(e) {
|
|
52
|
+
this.send({ isError: true, reason: e instanceof Error ? e.message : e });
|
|
53
|
+
return this.close();
|
|
54
|
+
}
|
|
55
|
+
[Symbol.dispose]() {
|
|
56
|
+
this.close();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
exports.JSONLinesResponse = JSONLinesResponse;
|
package/mjs/VovkApp.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { NextRequest } from 'next/server';
|
|
2
|
+
import { HttpMethod, HttpStatus, type RouteHandler, type VovkController, type DecoratorOptions } from './types.js';
|
|
3
|
+
export declare class VovkApp {
|
|
4
|
+
#private;
|
|
5
|
+
private static getHeadersFromOptions;
|
|
6
|
+
routes: Record<HttpMethod, Map<VovkController, Record<string, RouteHandler>>>;
|
|
7
|
+
GET: (req: NextRequest, data: {
|
|
8
|
+
params: Promise<Record<string, string[]>>;
|
|
9
|
+
}) => Promise<Response>;
|
|
10
|
+
POST: (req: NextRequest, data: {
|
|
11
|
+
params: Promise<Record<string, string[]>>;
|
|
12
|
+
}) => Promise<Response>;
|
|
13
|
+
PUT: (req: NextRequest, data: {
|
|
14
|
+
params: Promise<Record<string, string[]>>;
|
|
15
|
+
}) => Promise<Response>;
|
|
16
|
+
PATCH: (req: NextRequest, data: {
|
|
17
|
+
params: Promise<Record<string, string[]>>;
|
|
18
|
+
}) => Promise<Response>;
|
|
19
|
+
DELETE: (req: NextRequest, data: {
|
|
20
|
+
params: Promise<Record<string, string[]>>;
|
|
21
|
+
}) => Promise<Response>;
|
|
22
|
+
HEAD: (req: NextRequest, data: {
|
|
23
|
+
params: Promise<Record<string, string[]>>;
|
|
24
|
+
}) => Promise<Response>;
|
|
25
|
+
OPTIONS: (req: NextRequest, data: {
|
|
26
|
+
params: Promise<Record<string, string[]>>;
|
|
27
|
+
}) => Promise<Response>;
|
|
28
|
+
respond: (status: HttpStatus, body: unknown, options?: DecoratorOptions) => Response;
|
|
29
|
+
}
|