vovk 3.2.2 → 3.4.0
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/dist/HttpException.d.ts +7 -0
- package/dist/HttpException.js +15 -0
- package/dist/JSONLinesResponse.d.ts +14 -0
- package/dist/JSONLinesResponse.js +59 -0
- package/dist/VovkApp.d.ts +29 -0
- package/dist/VovkApp.js +189 -0
- package/dist/client/index.d.ts +3 -0
- package/dist/client/index.js +7 -0
- package/dist/client/types.d.ts +102 -0
- package/dist/client/types.js +2 -0
- package/dist/createDecorator.d.ts +6 -0
- package/dist/createDecorator.js +43 -0
- package/dist/createVovkApp.d.ts +62 -0
- package/dist/createVovkApp.js +129 -0
- package/dist/internal.d.ts +1 -1
- package/dist/internal.js +1 -0
- package/dist/tools/createTool.d.ts +32 -32
- package/dist/tools/createToolFactory.d.ts +33 -33
- package/dist/tools/deriveTools.d.ts +5 -5
- package/dist/tools/deriveTools.js +5 -6
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/standard-tool.d.ts +17 -0
- package/dist/types/standard-tool.js +1 -0
- package/dist/types/tools.d.ts +20 -16
- package/dist/types.d.ts +239 -0
- package/dist/types.js +66 -0
- package/dist/utils/generateStaticAPI.d.ts +4 -0
- package/dist/utils/generateStaticAPI.js +30 -0
- package/dist/utils/getSchema.d.ts +20 -0
- package/dist/utils/getSchema.js +33 -0
- package/dist/utils/parseQuery.d.ts +25 -0
- package/dist/utils/parseQuery.js +156 -0
- package/dist/utils/reqForm.d.ts +2 -0
- package/dist/utils/reqForm.js +32 -0
- package/dist/utils/reqMeta.d.ts +2 -0
- package/dist/utils/reqMeta.js +13 -0
- package/dist/utils/reqQuery.d.ts +2 -0
- package/dist/utils/reqQuery.js +10 -0
- package/dist/utils/serializeQuery.d.ts +13 -0
- package/dist/utils/serializeQuery.js +65 -0
- package/dist/utils/setHandlerSchema.d.ts +4 -0
- package/dist/utils/setHandlerSchema.js +15 -0
- package/dist/utils/withValidation.d.ts +21 -0
- package/dist/utils/withValidation.js +88 -0
- package/dist/validation/createStandardValidation.d.ts +32 -32
- package/dist/validation/procedure.d.ts +32 -32
- package/dist/validation/validationSchemasObjectToSingleValidationSchema.d.ts +17 -0
- package/dist/validation/validationSchemasObjectToSingleValidationSchema.js +92 -0
- package/package.json +1 -1
- package/dist/core/compose.d.ts +0 -38
- package/dist/core/compose.js +0 -31
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { CombinedSpec } from './validation.js';
|
|
2
|
+
import type { KnownAny } from './utils.js';
|
|
3
|
+
/**
|
|
4
|
+
* The `standard-tool` convention (https://github.com/finom/standard-tool): a neutral LLM tool shape —
|
|
5
|
+
* `name`, `description`, optional `inputSchema`/`outputSchema`, `execute`. Vendored as a type only
|
|
6
|
+
* (no logic) so `VovkTool` can extend it with zero added dependencies. Kept identical to the
|
|
7
|
+
* `StandardTool` type published by `standard-tool` (`meta` is `KnownAny`, i.e. its `any`).
|
|
8
|
+
*/
|
|
9
|
+
export interface StandardTool<Input = unknown, Output = unknown, FormattedOutput = Output | {
|
|
10
|
+
error: string;
|
|
11
|
+
}> {
|
|
12
|
+
name: string;
|
|
13
|
+
description: string;
|
|
14
|
+
inputSchema?: CombinedSpec<Input>;
|
|
15
|
+
outputSchema?: CombinedSpec<Output>;
|
|
16
|
+
execute(input: Input, meta?: KnownAny): FormattedOutput | Promise<FormattedOutput>;
|
|
17
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/types/tools.d.ts
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import type { VovkJSONSchemaBase } from './json-schema.js';
|
|
2
2
|
import type { VovkRequest } from './request.js';
|
|
3
3
|
import type { CombinedSpec } from './validation.js';
|
|
4
|
+
import type { StandardTool } from './standard-tool.js';
|
|
4
5
|
import type { KnownAny } from './utils.js';
|
|
5
6
|
export type ToModelOutputFn<TInput, TOutput, TFormattedOutput> = (result: TOutput | Error, tool: VovkTool<TInput, TOutput, unknown>, req: Pick<VovkRequest, 'vovk'> | null) => TFormattedOutput | Promise<TFormattedOutput>;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Vovk tool — produced by both `deriveTools` (procedures → tools) and
|
|
9
|
+
* `createTool` (standalone tools); both return the same shape. Extends the
|
|
10
|
+
* {@link StandardTool} convention with Vovk specifics (`title`, `parameters`, `type`).
|
|
11
|
+
* @see https://vovk.dev/tools
|
|
12
|
+
*/
|
|
13
|
+
export interface VovkTool<TInput = KnownAny, TOutput = KnownAny, TFormattedOutput = KnownAny> extends StandardTool<TInput, TOutput, TFormattedOutput> {
|
|
9
14
|
title: string | undefined;
|
|
10
|
-
description: string;
|
|
11
15
|
parameters: {
|
|
12
16
|
type?: 'object';
|
|
13
17
|
properties?: {
|
|
@@ -18,26 +22,26 @@ interface VovkToolCommon<TInput = unknown, TOutput = unknown, TFormattedOutput =
|
|
|
18
22
|
required?: ('body' | 'query' | 'params')[];
|
|
19
23
|
additionalProperties?: false;
|
|
20
24
|
};
|
|
21
|
-
inputSchema:
|
|
22
|
-
outputSchema:
|
|
23
|
-
|
|
25
|
+
inputSchema: TInput extends undefined ? undefined : CombinedSpec<TInput>;
|
|
26
|
+
outputSchema: TOutput extends undefined ? undefined : CombinedSpec<TOutput>;
|
|
27
|
+
/**
|
|
28
|
+
* Per-slot Standard Schemas, populated only when the tool was built via
|
|
29
|
+
* `deriveTools` from a procedure. Always `undefined` for tools built via
|
|
30
|
+
* `createTool`.
|
|
31
|
+
*
|
|
32
|
+
* @deprecated Use {@link VovkTool.inputSchema} (a merged Standard Schema)
|
|
33
|
+
* instead. This field will be removed in the next major version.
|
|
34
|
+
*/
|
|
35
|
+
inputSchemas?: {
|
|
24
36
|
body?: CombinedSpec;
|
|
25
37
|
query?: CombinedSpec;
|
|
26
38
|
params?: CombinedSpec;
|
|
27
|
-
}
|
|
39
|
+
};
|
|
28
40
|
type: 'function';
|
|
29
41
|
}
|
|
30
|
-
export type VovkToolDerived<TInput, TOutput, TFormattedOutput> = VovkToolCommon<TInput, TOutput, TFormattedOutput, true>;
|
|
31
|
-
export type VovkToolNonDerived<TInput, TOutput, TFormattedOutput> = VovkToolCommon<TInput, TOutput, TFormattedOutput, false>;
|
|
32
|
-
/**
|
|
33
|
-
* Vovk tool type, which can be either derived or non-derived.
|
|
34
|
-
* @see https://vovk.dev/tools
|
|
35
|
-
*/
|
|
36
|
-
export type VovkTool<TInput = KnownAny, TOutput = KnownAny, TFormattedOutput = KnownAny> = VovkToolDerived<TInput, TOutput, TFormattedOutput> | VovkToolNonDerived<TInput, TOutput, TFormattedOutput>;
|
|
37
42
|
export type VovkToolOptions = {
|
|
38
43
|
hidden?: boolean;
|
|
39
44
|
name?: string;
|
|
40
45
|
title?: string;
|
|
41
46
|
description?: string;
|
|
42
47
|
};
|
|
43
|
-
export {};
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import type { NextRequest } from 'next/server';
|
|
2
|
+
import type { OperationObject } from 'openapi3-ts/oas31';
|
|
3
|
+
import type { JSONLinesResponse } from './JSONLinesResponse';
|
|
4
|
+
import { VovkStreamAsyncIterable } from './client/types';
|
|
5
|
+
import type { PackageJson } from 'type-fest';
|
|
6
|
+
export type KnownAny = any;
|
|
7
|
+
export type StaticClass = Function;
|
|
8
|
+
export type VovkHandlerSchema = {
|
|
9
|
+
path: string;
|
|
10
|
+
httpMethod: string;
|
|
11
|
+
validation?: {
|
|
12
|
+
query?: KnownAny;
|
|
13
|
+
body?: KnownAny;
|
|
14
|
+
params?: KnownAny;
|
|
15
|
+
output?: KnownAny;
|
|
16
|
+
iteration?: KnownAny;
|
|
17
|
+
};
|
|
18
|
+
openapi?: OperationObject;
|
|
19
|
+
misc?: Record<string, KnownAny>;
|
|
20
|
+
};
|
|
21
|
+
export type VovkControllerSchema = {
|
|
22
|
+
rpcModuleName: string;
|
|
23
|
+
originalControllerName: string;
|
|
24
|
+
prefix?: string;
|
|
25
|
+
handlers: Record<string, VovkHandlerSchema>;
|
|
26
|
+
};
|
|
27
|
+
export type VovkSegmentSchema = {
|
|
28
|
+
emitSchema: boolean;
|
|
29
|
+
segmentName: string;
|
|
30
|
+
controllers: Record<string, VovkControllerSchema>;
|
|
31
|
+
};
|
|
32
|
+
export type VovkErrorResponse = {
|
|
33
|
+
cause?: unknown;
|
|
34
|
+
statusCode: HttpStatus;
|
|
35
|
+
message: string;
|
|
36
|
+
isError: true;
|
|
37
|
+
};
|
|
38
|
+
export type VovkControllerInternal = {
|
|
39
|
+
_rpcModuleName?: VovkControllerSchema['rpcModuleName'];
|
|
40
|
+
_prefix?: VovkControllerSchema['prefix'];
|
|
41
|
+
_handlers: VovkControllerSchema['handlers'];
|
|
42
|
+
_handlersMetadata?: Record<string, {
|
|
43
|
+
staticParams?: Record<string, string>[];
|
|
44
|
+
}>;
|
|
45
|
+
_activated?: true;
|
|
46
|
+
_onError?: (err: Error, req: VovkRequest) => void | Promise<void>;
|
|
47
|
+
};
|
|
48
|
+
export type VovkController = StaticClass & VovkControllerInternal & {
|
|
49
|
+
[key: string]: unknown;
|
|
50
|
+
};
|
|
51
|
+
export type DecoratorOptions = {
|
|
52
|
+
cors?: boolean;
|
|
53
|
+
headers?: Record<string, string>;
|
|
54
|
+
staticParams?: Record<string, string>[];
|
|
55
|
+
before?: (this: VovkController, req: VovkRequest) => unknown;
|
|
56
|
+
};
|
|
57
|
+
export type RouteHandler = ((req: VovkRequest, params: Record<string, string>) => Response | Promise<Response> | Iterable<unknown> | AsyncIterable<unknown>) & {
|
|
58
|
+
_options?: DecoratorOptions;
|
|
59
|
+
};
|
|
60
|
+
export interface VovkRequest<BODY extends KnownAny = null, QUERY extends KnownAny = undefined, PARAMS extends KnownAny = undefined> extends Omit<NextRequest, 'json' | 'nextUrl'> {
|
|
61
|
+
json: () => Promise<BODY>;
|
|
62
|
+
nextUrl: Omit<NextRequest['nextUrl'], 'searchParams'> & {
|
|
63
|
+
searchParams: Omit<NextRequest['nextUrl']['searchParams'], 'get' | 'getAll' | 'entries' | 'forEach' | 'keys' | 'values'> & {
|
|
64
|
+
get: <KEY extends keyof QUERY>(key: KEY) => QUERY[KEY] extends readonly (infer ITEM)[] ? ITEM : QUERY[KEY];
|
|
65
|
+
getAll: <KEY extends keyof QUERY>(key: KEY) => QUERY[KEY] extends KnownAny[] ? QUERY[KEY] : QUERY[KEY][];
|
|
66
|
+
entries: () => IterableIterator<[keyof QUERY, QUERY[keyof QUERY]]>;
|
|
67
|
+
forEach: (callbackfn: (value: QUERY[keyof QUERY], key: keyof QUERY, searchParams: NextRequest['nextUrl']['searchParams']) => void) => void;
|
|
68
|
+
keys: () => IterableIterator<keyof QUERY>;
|
|
69
|
+
values: () => IterableIterator<QUERY[keyof QUERY]>;
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
vovk: {
|
|
73
|
+
body: () => Promise<BODY>;
|
|
74
|
+
query: () => QUERY;
|
|
75
|
+
meta: <T = Record<KnownAny, KnownAny>>(meta?: T | null) => T;
|
|
76
|
+
form: <T = KnownAny>() => Promise<T>;
|
|
77
|
+
params: () => PARAMS;
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
export type ControllerStaticMethod<REQ extends VovkRequest<KnownAny, KnownAny> = VovkRequest<undefined, Record<string, KnownAny>>, PARAMS extends {
|
|
81
|
+
[key: string]: string;
|
|
82
|
+
} = KnownAny> = ((req: REQ, params: PARAMS) => unknown) & {
|
|
83
|
+
_controller?: VovkController;
|
|
84
|
+
};
|
|
85
|
+
export type VovkControllerBody<T extends (...args: KnownAny) => KnownAny> = Awaited<ReturnType<Parameters<T>[0]['vovk']['body']>>;
|
|
86
|
+
export type VovkControllerQuery<T extends (...args: KnownAny) => KnownAny> = ReturnType<Parameters<T>[0]['vovk']['query']>;
|
|
87
|
+
export type VovkControllerParams<T extends (...args: KnownAny) => KnownAny> = Parameters<T>[1] extends object ? Parameters<T>[1] : ReturnType<Parameters<T>[0]['vovk']['params']>;
|
|
88
|
+
export type VovkControllerYieldType<T extends (req: VovkRequest<KnownAny, KnownAny>) => KnownAny> = T extends (...args: KnownAny[]) => AsyncGenerator<infer Y, KnownAny, KnownAny> ? Y : T extends (...args: KnownAny[]) => Generator<infer Y, KnownAny, KnownAny> ? Y : T extends (...args: KnownAny[]) => Promise<JSONLinesResponse<infer Y>> | JSONLinesResponse<infer Y> ? Y : never;
|
|
89
|
+
export type VovkControllerOutput<T extends ((...args: KnownAny) => KnownAny) & {
|
|
90
|
+
__output?: KnownAny;
|
|
91
|
+
}> = T['__output'];
|
|
92
|
+
export type VovkControllerIteration<T extends ((...args: KnownAny) => KnownAny) & {
|
|
93
|
+
__iteration?: KnownAny;
|
|
94
|
+
}> = T['__iteration'];
|
|
95
|
+
export type VovkBody<T extends (...args: KnownAny[]) => unknown> = Parameters<T>[0]['body'];
|
|
96
|
+
export type VovkQuery<T extends (...args: KnownAny[]) => unknown> = Parameters<T>[0]['query'];
|
|
97
|
+
export type VovkParams<T extends (...args: KnownAny[]) => unknown> = Parameters<T>[0]['params'];
|
|
98
|
+
export type VovkYieldType<T extends (...args: KnownAny[]) => unknown> = T extends (...args: KnownAny[]) => Promise<VovkStreamAsyncIterable<infer Y>> ? Y : never;
|
|
99
|
+
export type VovkReturnType<T extends (...args: KnownAny) => unknown> = Awaited<ReturnType<T>>;
|
|
100
|
+
export type StreamAbortMessage = {
|
|
101
|
+
isError: true;
|
|
102
|
+
reason: KnownAny;
|
|
103
|
+
};
|
|
104
|
+
export type VovkValidationType = 'body' | 'query' | 'params' | 'output' | 'iteration';
|
|
105
|
+
export type VovkFullSchema = {
|
|
106
|
+
config: Partial<VovkStrictConfig>;
|
|
107
|
+
segments: Record<string, VovkSegmentSchema>;
|
|
108
|
+
};
|
|
109
|
+
export declare enum HttpMethod {
|
|
110
|
+
GET = "GET",
|
|
111
|
+
POST = "POST",
|
|
112
|
+
PUT = "PUT",
|
|
113
|
+
PATCH = "PATCH",
|
|
114
|
+
DELETE = "DELETE",
|
|
115
|
+
HEAD = "HEAD",
|
|
116
|
+
OPTIONS = "OPTIONS"
|
|
117
|
+
}
|
|
118
|
+
export declare enum HttpStatus {
|
|
119
|
+
NULL = 0,
|
|
120
|
+
CONTINUE = 100,
|
|
121
|
+
SWITCHING_PROTOCOLS = 101,
|
|
122
|
+
PROCESSING = 102,
|
|
123
|
+
EARLYHINTS = 103,
|
|
124
|
+
OK = 200,
|
|
125
|
+
CREATED = 201,
|
|
126
|
+
ACCEPTED = 202,
|
|
127
|
+
NON_AUTHORITATIVE_INFORMATION = 203,
|
|
128
|
+
NO_CONTENT = 204,
|
|
129
|
+
RESET_CONTENT = 205,
|
|
130
|
+
PARTIAL_CONTENT = 206,
|
|
131
|
+
AMBIGUOUS = 300,
|
|
132
|
+
MOVED_PERMANENTLY = 301,
|
|
133
|
+
FOUND = 302,
|
|
134
|
+
SEE_OTHER = 303,
|
|
135
|
+
NOT_MODIFIED = 304,
|
|
136
|
+
TEMPORARY_REDIRECT = 307,
|
|
137
|
+
PERMANENT_REDIRECT = 308,
|
|
138
|
+
BAD_REQUEST = 400,
|
|
139
|
+
UNAUTHORIZED = 401,
|
|
140
|
+
PAYMENT_REQUIRED = 402,
|
|
141
|
+
FORBIDDEN = 403,
|
|
142
|
+
NOT_FOUND = 404,
|
|
143
|
+
METHOD_NOT_ALLOWED = 405,
|
|
144
|
+
NOT_ACCEPTABLE = 406,
|
|
145
|
+
PROXY_AUTHENTICATION_REQUIRED = 407,
|
|
146
|
+
REQUEST_TIMEOUT = 408,
|
|
147
|
+
CONFLICT = 409,
|
|
148
|
+
GONE = 410,
|
|
149
|
+
LENGTH_REQUIRED = 411,
|
|
150
|
+
PRECONDITION_FAILED = 412,
|
|
151
|
+
PAYLOAD_TOO_LARGE = 413,
|
|
152
|
+
URI_TOO_LONG = 414,
|
|
153
|
+
UNSUPPORTED_MEDIA_TYPE = 415,
|
|
154
|
+
REQUESTED_RANGE_NOT_SATISFIABLE = 416,
|
|
155
|
+
EXPECTATION_FAILED = 417,
|
|
156
|
+
I_AM_A_TEAPOT = 418,
|
|
157
|
+
MISDIRECTED = 421,
|
|
158
|
+
UNPROCESSABLE_ENTITY = 422,
|
|
159
|
+
FAILED_DEPENDENCY = 424,
|
|
160
|
+
PRECONDITION_REQUIRED = 428,
|
|
161
|
+
TOO_MANY_REQUESTS = 429,
|
|
162
|
+
INTERNAL_SERVER_ERROR = 500,
|
|
163
|
+
NOT_IMPLEMENTED = 501,
|
|
164
|
+
BAD_GATEWAY = 502,
|
|
165
|
+
SERVICE_UNAVAILABLE = 503,
|
|
166
|
+
GATEWAY_TIMEOUT = 504,
|
|
167
|
+
HTTP_VERSION_NOT_SUPPORTED = 505
|
|
168
|
+
}
|
|
169
|
+
type ClientConfigCommon = {
|
|
170
|
+
enabled?: boolean;
|
|
171
|
+
outDir?: string;
|
|
172
|
+
fromTemplates?: string[];
|
|
173
|
+
} & ({
|
|
174
|
+
excludeSegments?: never;
|
|
175
|
+
includeSegments?: string[];
|
|
176
|
+
} | {
|
|
177
|
+
excludeSegments?: string[];
|
|
178
|
+
includeSegments?: never;
|
|
179
|
+
});
|
|
180
|
+
type ClientConfigFull = ClientConfigCommon & {
|
|
181
|
+
package?: PackageJson;
|
|
182
|
+
};
|
|
183
|
+
type ClientConfigSegmented = ClientConfigCommon & {
|
|
184
|
+
packages?: Record<string, PackageJson>;
|
|
185
|
+
};
|
|
186
|
+
export type ClientTemplateDef = {
|
|
187
|
+
extends?: string;
|
|
188
|
+
templatePath?: string | null;
|
|
189
|
+
origin?: string | null;
|
|
190
|
+
fullClient?: Omit<ClientConfigFull, 'fromTemplates' | 'enabled'>;
|
|
191
|
+
segmentedClient?: Omit<ClientConfigSegmented, 'fromTemplates' | 'enabled'>;
|
|
192
|
+
segmentConfig?: false | Record<string, {
|
|
193
|
+
origin?: string;
|
|
194
|
+
rootEntry?: boolean;
|
|
195
|
+
}>;
|
|
196
|
+
requires?: Record<string, string>;
|
|
197
|
+
};
|
|
198
|
+
export type VovkConfig = {
|
|
199
|
+
emitConfig?: boolean | (keyof VovkStrictConfig)[];
|
|
200
|
+
schemaOutDir?: string;
|
|
201
|
+
fullClient?: ClientConfigFull;
|
|
202
|
+
segmentedClient?: ClientConfigSegmented;
|
|
203
|
+
imports?: {
|
|
204
|
+
fetcher?: string | [string, string] | [string];
|
|
205
|
+
validateOnClient?: string | [string, string] | [string];
|
|
206
|
+
createRPC?: string | [string, string] | [string];
|
|
207
|
+
};
|
|
208
|
+
modulesDir?: string;
|
|
209
|
+
rootEntry?: string;
|
|
210
|
+
origin?: string;
|
|
211
|
+
rootSegmentModulesDirName?: string;
|
|
212
|
+
logLevel?: 'error' | 'trace' | 'debug' | 'info' | 'warn';
|
|
213
|
+
prettifyClient?: boolean;
|
|
214
|
+
devHttps?: boolean;
|
|
215
|
+
clientTemplateDefs?: Record<string, ClientTemplateDef>;
|
|
216
|
+
moduleTemplates?: {
|
|
217
|
+
service?: string;
|
|
218
|
+
controller?: string;
|
|
219
|
+
[key: string]: string | undefined;
|
|
220
|
+
};
|
|
221
|
+
libs?: Record<string, KnownAny>;
|
|
222
|
+
segmentConfig?: false | Record<string, {
|
|
223
|
+
origin?: string;
|
|
224
|
+
rootEntry?: boolean;
|
|
225
|
+
}>;
|
|
226
|
+
};
|
|
227
|
+
export type VovkStrictConfig = Required<Omit<VovkConfig, 'emitConfig' | 'libs' | 'imports' | 'fullClient' | 'segmentedClient'>> & {
|
|
228
|
+
emitConfig: (keyof VovkStrictConfig)[];
|
|
229
|
+
imports: {
|
|
230
|
+
fetcher: [string, string] | [string];
|
|
231
|
+
validateOnClient: [string, string] | [string] | null;
|
|
232
|
+
createRPC: [string, string] | [string];
|
|
233
|
+
};
|
|
234
|
+
libs: Record<string, KnownAny>;
|
|
235
|
+
fullClient: RequireFields<ClientConfigFull, 'enabled' | 'fromTemplates' | 'outDir'>;
|
|
236
|
+
segmentedClient: RequireFields<ClientConfigSegmented, 'enabled' | 'fromTemplates' | 'outDir'>;
|
|
237
|
+
};
|
|
238
|
+
type RequireFields<T, K extends keyof T> = T & Required<Pick<T, K>>;
|
|
239
|
+
export {};
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HttpStatus = exports.HttpMethod = void 0;
|
|
4
|
+
// Enums
|
|
5
|
+
var HttpMethod;
|
|
6
|
+
(function (HttpMethod) {
|
|
7
|
+
HttpMethod["GET"] = "GET";
|
|
8
|
+
HttpMethod["POST"] = "POST";
|
|
9
|
+
HttpMethod["PUT"] = "PUT";
|
|
10
|
+
HttpMethod["PATCH"] = "PATCH";
|
|
11
|
+
HttpMethod["DELETE"] = "DELETE";
|
|
12
|
+
HttpMethod["HEAD"] = "HEAD";
|
|
13
|
+
HttpMethod["OPTIONS"] = "OPTIONS";
|
|
14
|
+
})(HttpMethod || (exports.HttpMethod = HttpMethod = {}));
|
|
15
|
+
var HttpStatus;
|
|
16
|
+
(function (HttpStatus) {
|
|
17
|
+
HttpStatus[HttpStatus["NULL"] = 0] = "NULL";
|
|
18
|
+
HttpStatus[HttpStatus["CONTINUE"] = 100] = "CONTINUE";
|
|
19
|
+
HttpStatus[HttpStatus["SWITCHING_PROTOCOLS"] = 101] = "SWITCHING_PROTOCOLS";
|
|
20
|
+
HttpStatus[HttpStatus["PROCESSING"] = 102] = "PROCESSING";
|
|
21
|
+
HttpStatus[HttpStatus["EARLYHINTS"] = 103] = "EARLYHINTS";
|
|
22
|
+
HttpStatus[HttpStatus["OK"] = 200] = "OK";
|
|
23
|
+
HttpStatus[HttpStatus["CREATED"] = 201] = "CREATED";
|
|
24
|
+
HttpStatus[HttpStatus["ACCEPTED"] = 202] = "ACCEPTED";
|
|
25
|
+
HttpStatus[HttpStatus["NON_AUTHORITATIVE_INFORMATION"] = 203] = "NON_AUTHORITATIVE_INFORMATION";
|
|
26
|
+
HttpStatus[HttpStatus["NO_CONTENT"] = 204] = "NO_CONTENT";
|
|
27
|
+
HttpStatus[HttpStatus["RESET_CONTENT"] = 205] = "RESET_CONTENT";
|
|
28
|
+
HttpStatus[HttpStatus["PARTIAL_CONTENT"] = 206] = "PARTIAL_CONTENT";
|
|
29
|
+
HttpStatus[HttpStatus["AMBIGUOUS"] = 300] = "AMBIGUOUS";
|
|
30
|
+
HttpStatus[HttpStatus["MOVED_PERMANENTLY"] = 301] = "MOVED_PERMANENTLY";
|
|
31
|
+
HttpStatus[HttpStatus["FOUND"] = 302] = "FOUND";
|
|
32
|
+
HttpStatus[HttpStatus["SEE_OTHER"] = 303] = "SEE_OTHER";
|
|
33
|
+
HttpStatus[HttpStatus["NOT_MODIFIED"] = 304] = "NOT_MODIFIED";
|
|
34
|
+
HttpStatus[HttpStatus["TEMPORARY_REDIRECT"] = 307] = "TEMPORARY_REDIRECT";
|
|
35
|
+
HttpStatus[HttpStatus["PERMANENT_REDIRECT"] = 308] = "PERMANENT_REDIRECT";
|
|
36
|
+
HttpStatus[HttpStatus["BAD_REQUEST"] = 400] = "BAD_REQUEST";
|
|
37
|
+
HttpStatus[HttpStatus["UNAUTHORIZED"] = 401] = "UNAUTHORIZED";
|
|
38
|
+
HttpStatus[HttpStatus["PAYMENT_REQUIRED"] = 402] = "PAYMENT_REQUIRED";
|
|
39
|
+
HttpStatus[HttpStatus["FORBIDDEN"] = 403] = "FORBIDDEN";
|
|
40
|
+
HttpStatus[HttpStatus["NOT_FOUND"] = 404] = "NOT_FOUND";
|
|
41
|
+
HttpStatus[HttpStatus["METHOD_NOT_ALLOWED"] = 405] = "METHOD_NOT_ALLOWED";
|
|
42
|
+
HttpStatus[HttpStatus["NOT_ACCEPTABLE"] = 406] = "NOT_ACCEPTABLE";
|
|
43
|
+
HttpStatus[HttpStatus["PROXY_AUTHENTICATION_REQUIRED"] = 407] = "PROXY_AUTHENTICATION_REQUIRED";
|
|
44
|
+
HttpStatus[HttpStatus["REQUEST_TIMEOUT"] = 408] = "REQUEST_TIMEOUT";
|
|
45
|
+
HttpStatus[HttpStatus["CONFLICT"] = 409] = "CONFLICT";
|
|
46
|
+
HttpStatus[HttpStatus["GONE"] = 410] = "GONE";
|
|
47
|
+
HttpStatus[HttpStatus["LENGTH_REQUIRED"] = 411] = "LENGTH_REQUIRED";
|
|
48
|
+
HttpStatus[HttpStatus["PRECONDITION_FAILED"] = 412] = "PRECONDITION_FAILED";
|
|
49
|
+
HttpStatus[HttpStatus["PAYLOAD_TOO_LARGE"] = 413] = "PAYLOAD_TOO_LARGE";
|
|
50
|
+
HttpStatus[HttpStatus["URI_TOO_LONG"] = 414] = "URI_TOO_LONG";
|
|
51
|
+
HttpStatus[HttpStatus["UNSUPPORTED_MEDIA_TYPE"] = 415] = "UNSUPPORTED_MEDIA_TYPE";
|
|
52
|
+
HttpStatus[HttpStatus["REQUESTED_RANGE_NOT_SATISFIABLE"] = 416] = "REQUESTED_RANGE_NOT_SATISFIABLE";
|
|
53
|
+
HttpStatus[HttpStatus["EXPECTATION_FAILED"] = 417] = "EXPECTATION_FAILED";
|
|
54
|
+
HttpStatus[HttpStatus["I_AM_A_TEAPOT"] = 418] = "I_AM_A_TEAPOT";
|
|
55
|
+
HttpStatus[HttpStatus["MISDIRECTED"] = 421] = "MISDIRECTED";
|
|
56
|
+
HttpStatus[HttpStatus["UNPROCESSABLE_ENTITY"] = 422] = "UNPROCESSABLE_ENTITY";
|
|
57
|
+
HttpStatus[HttpStatus["FAILED_DEPENDENCY"] = 424] = "FAILED_DEPENDENCY";
|
|
58
|
+
HttpStatus[HttpStatus["PRECONDITION_REQUIRED"] = 428] = "PRECONDITION_REQUIRED";
|
|
59
|
+
HttpStatus[HttpStatus["TOO_MANY_REQUESTS"] = 429] = "TOO_MANY_REQUESTS";
|
|
60
|
+
HttpStatus[HttpStatus["INTERNAL_SERVER_ERROR"] = 500] = "INTERNAL_SERVER_ERROR";
|
|
61
|
+
HttpStatus[HttpStatus["NOT_IMPLEMENTED"] = 501] = "NOT_IMPLEMENTED";
|
|
62
|
+
HttpStatus[HttpStatus["BAD_GATEWAY"] = 502] = "BAD_GATEWAY";
|
|
63
|
+
HttpStatus[HttpStatus["SERVICE_UNAVAILABLE"] = 503] = "SERVICE_UNAVAILABLE";
|
|
64
|
+
HttpStatus[HttpStatus["GATEWAY_TIMEOUT"] = 504] = "GATEWAY_TIMEOUT";
|
|
65
|
+
HttpStatus[HttpStatus["HTTP_VERSION_NOT_SUPPORTED"] = 505] = "HTTP_VERSION_NOT_SUPPORTED";
|
|
66
|
+
})(HttpStatus || (exports.HttpStatus = HttpStatus = {}));
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateStaticAPI = generateStaticAPI;
|
|
4
|
+
function generateStaticAPI(c, slug = 'vovk') {
|
|
5
|
+
const controllers = c;
|
|
6
|
+
return [
|
|
7
|
+
{ [slug]: ['_schema_'] },
|
|
8
|
+
...Object.values(controllers)
|
|
9
|
+
.map((controller) => {
|
|
10
|
+
const handlers = controller._handlers;
|
|
11
|
+
const splitPrefix = controller._prefix?.split('/') ?? [];
|
|
12
|
+
return Object.entries(handlers)
|
|
13
|
+
.map(([name, handler]) => {
|
|
14
|
+
const staticParams = controller._handlersMetadata?.[name]?.staticParams;
|
|
15
|
+
if (staticParams?.length) {
|
|
16
|
+
return staticParams.map((paramsItem) => {
|
|
17
|
+
let path = handler.path;
|
|
18
|
+
for (const [key, value] of Object.entries(paramsItem)) {
|
|
19
|
+
path = path.replace(`:${key}`, value);
|
|
20
|
+
}
|
|
21
|
+
return { [slug]: [...splitPrefix, ...path.split('/')].filter(Boolean) };
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
return [{ [slug]: [...splitPrefix, ...handler.path.split('/')].filter(Boolean) }];
|
|
25
|
+
})
|
|
26
|
+
.flat();
|
|
27
|
+
})
|
|
28
|
+
.flat(),
|
|
29
|
+
];
|
|
30
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { VovkSegmentSchema, VovkController, StaticClass } from '../types';
|
|
2
|
+
export declare function getControllerSchema(controller: VovkController, rpcModuleName: string, exposeValidation: boolean): {
|
|
3
|
+
rpcModuleName: string;
|
|
4
|
+
originalControllerName: string;
|
|
5
|
+
prefix: string;
|
|
6
|
+
handlers: {
|
|
7
|
+
[k: string]: {
|
|
8
|
+
path: string;
|
|
9
|
+
httpMethod: string;
|
|
10
|
+
openapi?: import("openapi3-ts/oas31").OperationObject;
|
|
11
|
+
misc?: Record<string, import("../types").KnownAny>;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
export default function getSchema(options: {
|
|
16
|
+
emitSchema?: boolean;
|
|
17
|
+
segmentName?: string;
|
|
18
|
+
controllers: Record<string, StaticClass>;
|
|
19
|
+
exposeValidation?: boolean;
|
|
20
|
+
}): VovkSegmentSchema;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getControllerSchema = getControllerSchema;
|
|
4
|
+
exports.default = getSchema;
|
|
5
|
+
function getControllerSchema(controller, rpcModuleName, exposeValidation) {
|
|
6
|
+
return {
|
|
7
|
+
rpcModuleName,
|
|
8
|
+
originalControllerName: controller.name,
|
|
9
|
+
prefix: controller._prefix ?? '',
|
|
10
|
+
handlers: {
|
|
11
|
+
...(exposeValidation
|
|
12
|
+
? controller._handlers
|
|
13
|
+
: Object.fromEntries(
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
15
|
+
Object.entries(controller._handlers ?? {}).map(([key, { validation: _v, ...value }]) => [key, value]))),
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function getSchema(options) {
|
|
20
|
+
const exposeValidation = options?.exposeValidation ?? true;
|
|
21
|
+
const emitSchema = options.emitSchema ?? true;
|
|
22
|
+
const schema = {
|
|
23
|
+
emitSchema,
|
|
24
|
+
segmentName: options.segmentName ?? '',
|
|
25
|
+
controllers: {},
|
|
26
|
+
};
|
|
27
|
+
if (!emitSchema)
|
|
28
|
+
return schema;
|
|
29
|
+
for (const [rpcModuleName, controller] of Object.entries(options.controllers)) {
|
|
30
|
+
schema.controllers[rpcModuleName] = getControllerSchema(controller, rpcModuleName, exposeValidation);
|
|
31
|
+
}
|
|
32
|
+
return schema;
|
|
33
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { KnownAny } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Deserialize a bracket-based query string into an object.
|
|
4
|
+
*
|
|
5
|
+
* Supports:
|
|
6
|
+
* - Key/value pairs with nested brackets (e.g. "a[b][0]=value")
|
|
7
|
+
* - Arrays with empty bracket (e.g. "arr[]=1&arr[]=2")
|
|
8
|
+
* - Mixed arrays of objects, etc.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* parseQuery("x=xx&y[0]=yy&y[1]=uu&z[f]=x&z[u][0]=uu&z[u][1]=xx&z[d][x]=ee")
|
|
12
|
+
* => {
|
|
13
|
+
* x: "xx",
|
|
14
|
+
* y: ["yy", "uu"],
|
|
15
|
+
* z: {
|
|
16
|
+
* f: "x",
|
|
17
|
+
* u: ["uu", "xx"],
|
|
18
|
+
* d: { x: "ee" }
|
|
19
|
+
* }
|
|
20
|
+
* }
|
|
21
|
+
*
|
|
22
|
+
* @param queryString - The raw query string (e.g. location.search.slice(1))
|
|
23
|
+
* @returns - A nested object representing the query params
|
|
24
|
+
*/
|
|
25
|
+
export default function parseQuery(queryString: string): Record<string, KnownAny>;
|
|
@@ -0,0 +1,156 @@
|
|
|
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
|
+
}
|