vovk 3.0.0-draft.46 → 3.0.0-draft.460

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 (207) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +8 -96
  3. package/bin/index.mjs +8 -0
  4. package/cjs/JSONLinesResponse.d.ts +19 -0
  5. package/cjs/JSONLinesResponse.js +95 -0
  6. package/{VovkApp.d.ts → cjs/VovkApp.d.ts} +14 -8
  7. package/cjs/VovkApp.js +304 -0
  8. package/cjs/client/createRPC.d.ts +5 -0
  9. package/cjs/client/createRPC.js +116 -0
  10. package/cjs/client/defaultHandler.d.ts +6 -0
  11. package/{client → cjs/client}/defaultHandler.js +9 -2
  12. package/cjs/client/defaultStreamHandler.d.ts +9 -0
  13. package/{client → cjs/client}/defaultStreamHandler.js +49 -26
  14. package/cjs/client/fetcher.d.ts +18 -0
  15. package/cjs/client/fetcher.js +97 -0
  16. package/cjs/client/index.d.ts +4 -0
  17. package/cjs/client/index.js +10 -0
  18. package/cjs/client/progressive.d.ts +9 -0
  19. package/cjs/client/progressive.js +54 -0
  20. package/cjs/client/types.d.ts +120 -0
  21. package/{createVovkApp.d.ts → cjs/createVovkApp.d.ts} +19 -16
  22. package/cjs/createVovkApp.js +146 -0
  23. package/cjs/index.d.ts +69 -0
  24. package/cjs/index.js +42 -0
  25. package/cjs/openapi/error.d.ts +2 -0
  26. package/cjs/openapi/error.js +100 -0
  27. package/cjs/openapi/index.d.ts +8 -0
  28. package/cjs/openapi/index.js +21 -0
  29. package/cjs/openapi/openAPIToVovkSchema/applyComponentsSchemas.d.ts +3 -0
  30. package/cjs/openapi/openAPIToVovkSchema/applyComponentsSchemas.js +67 -0
  31. package/cjs/openapi/openAPIToVovkSchema/index.d.ts +4 -0
  32. package/cjs/openapi/openAPIToVovkSchema/index.js +141 -0
  33. package/cjs/openapi/openAPIToVovkSchema/inlineRefs.d.ts +10 -0
  34. package/cjs/openapi/openAPIToVovkSchema/inlineRefs.js +102 -0
  35. package/cjs/openapi/vovkSchemaToOpenAPI.d.ts +8 -0
  36. package/cjs/openapi/vovkSchemaToOpenAPI.js +238 -0
  37. package/cjs/types.d.ts +466 -0
  38. package/{types.js → cjs/types.js} +14 -2
  39. package/cjs/utils/camelCase.d.ts +6 -0
  40. package/cjs/utils/camelCase.js +37 -0
  41. package/cjs/utils/createCodeSamples.d.ts +20 -0
  42. package/cjs/utils/createCodeSamples.js +279 -0
  43. package/cjs/utils/createDecorator.d.ts +6 -0
  44. package/{createDecorator.js → cjs/utils/createDecorator.js} +24 -14
  45. package/cjs/utils/createLLMTools.d.ts +50 -0
  46. package/cjs/utils/createLLMTools.js +168 -0
  47. package/cjs/utils/createStandardValidation.d.ts +82 -0
  48. package/cjs/utils/createStandardValidation.js +34 -0
  49. package/cjs/utils/createValidateOnClient.d.ts +7 -0
  50. package/cjs/utils/createValidateOnClient.js +19 -0
  51. package/cjs/utils/deepExtend.d.ts +54 -0
  52. package/cjs/utils/deepExtend.js +134 -0
  53. package/{utils → cjs/utils}/generateStaticAPI.d.ts +2 -2
  54. package/cjs/utils/generateStaticAPI.js +30 -0
  55. package/cjs/utils/getJSONSchemaExample.d.ts +11 -0
  56. package/cjs/utils/getJSONSchemaExample.js +264 -0
  57. package/cjs/utils/getJSONSchemaSample.d.ts +2 -0
  58. package/cjs/utils/getJSONSchemaSample.js +167 -0
  59. package/cjs/utils/getSampleFromObject.d.ts +9 -0
  60. package/cjs/utils/getSampleFromObject.js +41 -0
  61. package/cjs/utils/getSchema.d.ts +21 -0
  62. package/cjs/utils/getSchema.js +38 -0
  63. package/cjs/utils/multitenant.d.ts +24 -0
  64. package/cjs/utils/multitenant.js +131 -0
  65. package/cjs/utils/parseQuery.d.ts +25 -0
  66. package/cjs/utils/parseQuery.js +156 -0
  67. package/cjs/utils/reqForm.d.ts +2 -0
  68. package/cjs/utils/reqForm.js +33 -0
  69. package/cjs/utils/reqMeta.d.ts +2 -0
  70. package/cjs/utils/reqQuery.d.ts +2 -0
  71. package/cjs/utils/reqQuery.js +10 -0
  72. package/cjs/utils/resolveGeneratorConfigValues.d.ts +18 -0
  73. package/cjs/utils/resolveGeneratorConfigValues.js +82 -0
  74. package/cjs/utils/serializeQuery.d.ts +13 -0
  75. package/cjs/utils/serializeQuery.js +65 -0
  76. package/cjs/utils/setHandlerSchema.d.ts +4 -0
  77. package/cjs/utils/setHandlerSchema.js +15 -0
  78. package/cjs/utils/upperFirst.d.ts +1 -0
  79. package/cjs/utils/upperFirst.js +6 -0
  80. package/cjs/utils/withValidationLibrary.d.ts +77 -0
  81. package/cjs/utils/withValidationLibrary.js +124 -0
  82. package/mjs/HttpException.d.ts +7 -0
  83. package/mjs/HttpException.js +15 -0
  84. package/mjs/JSONLinesResponse.d.ts +19 -0
  85. package/mjs/JSONLinesResponse.js +95 -0
  86. package/mjs/VovkApp.d.ts +34 -0
  87. package/mjs/VovkApp.js +304 -0
  88. package/mjs/client/createRPC.d.ts +5 -0
  89. package/mjs/client/createRPC.js +116 -0
  90. package/mjs/client/defaultHandler.d.ts +6 -0
  91. package/mjs/client/defaultHandler.js +29 -0
  92. package/mjs/client/defaultStreamHandler.d.ts +9 -0
  93. package/mjs/client/defaultStreamHandler.js +105 -0
  94. package/mjs/client/fetcher.d.ts +18 -0
  95. package/mjs/client/fetcher.js +97 -0
  96. package/mjs/client/index.d.ts +4 -0
  97. package/mjs/client/index.js +10 -0
  98. package/mjs/client/progressive.d.ts +9 -0
  99. package/mjs/client/progressive.js +54 -0
  100. package/mjs/client/types.d.ts +120 -0
  101. package/mjs/createVovkApp.d.ts +65 -0
  102. package/mjs/createVovkApp.js +146 -0
  103. package/mjs/index.d.ts +69 -0
  104. package/mjs/index.js +42 -0
  105. package/mjs/openapi/error.d.ts +2 -0
  106. package/mjs/openapi/error.js +100 -0
  107. package/mjs/openapi/index.d.ts +8 -0
  108. package/mjs/openapi/index.js +21 -0
  109. package/mjs/openapi/openAPIToVovkSchema/applyComponentsSchemas.d.ts +3 -0
  110. package/mjs/openapi/openAPIToVovkSchema/applyComponentsSchemas.js +67 -0
  111. package/mjs/openapi/openAPIToVovkSchema/index.d.ts +4 -0
  112. package/mjs/openapi/openAPIToVovkSchema/index.js +141 -0
  113. package/mjs/openapi/openAPIToVovkSchema/inlineRefs.d.ts +10 -0
  114. package/mjs/openapi/openAPIToVovkSchema/inlineRefs.js +102 -0
  115. package/mjs/openapi/vovkSchemaToOpenAPI.d.ts +8 -0
  116. package/mjs/openapi/vovkSchemaToOpenAPI.js +238 -0
  117. package/mjs/types.d.ts +466 -0
  118. package/mjs/types.js +77 -0
  119. package/mjs/utils/camelCase.d.ts +6 -0
  120. package/mjs/utils/camelCase.js +37 -0
  121. package/mjs/utils/createCodeSamples.d.ts +20 -0
  122. package/mjs/utils/createCodeSamples.js +279 -0
  123. package/mjs/utils/createDecorator.d.ts +6 -0
  124. package/mjs/utils/createDecorator.js +48 -0
  125. package/mjs/utils/createLLMTools.d.ts +50 -0
  126. package/mjs/utils/createLLMTools.js +168 -0
  127. package/mjs/utils/createStandardValidation.d.ts +82 -0
  128. package/mjs/utils/createStandardValidation.js +34 -0
  129. package/mjs/utils/createValidateOnClient.d.ts +7 -0
  130. package/mjs/utils/createValidateOnClient.js +19 -0
  131. package/mjs/utils/deepExtend.d.ts +54 -0
  132. package/mjs/utils/deepExtend.js +134 -0
  133. package/mjs/utils/generateStaticAPI.d.ts +4 -0
  134. package/mjs/utils/generateStaticAPI.js +30 -0
  135. package/mjs/utils/getJSONSchemaExample.d.ts +11 -0
  136. package/mjs/utils/getJSONSchemaExample.js +264 -0
  137. package/mjs/utils/getJSONSchemaSample.d.ts +2 -0
  138. package/mjs/utils/getJSONSchemaSample.js +167 -0
  139. package/mjs/utils/getSampleFromObject.d.ts +9 -0
  140. package/mjs/utils/getSampleFromObject.js +41 -0
  141. package/mjs/utils/getSchema.d.ts +21 -0
  142. package/mjs/utils/getSchema.js +38 -0
  143. package/mjs/utils/multitenant.d.ts +24 -0
  144. package/mjs/utils/multitenant.js +131 -0
  145. package/mjs/utils/parseQuery.d.ts +25 -0
  146. package/mjs/utils/parseQuery.js +156 -0
  147. package/mjs/utils/reqForm.d.ts +2 -0
  148. package/mjs/utils/reqForm.js +33 -0
  149. package/mjs/utils/reqMeta.d.ts +2 -0
  150. package/mjs/utils/reqMeta.js +13 -0
  151. package/mjs/utils/reqQuery.d.ts +2 -0
  152. package/mjs/utils/reqQuery.js +10 -0
  153. package/mjs/utils/resolveGeneratorConfigValues.d.ts +18 -0
  154. package/mjs/utils/resolveGeneratorConfigValues.js +82 -0
  155. package/mjs/utils/serializeQuery.d.ts +13 -0
  156. package/mjs/utils/serializeQuery.js +65 -0
  157. package/mjs/utils/setHandlerSchema.d.ts +4 -0
  158. package/mjs/utils/setHandlerSchema.js +15 -0
  159. package/mjs/utils/shim.d.ts +1 -0
  160. package/mjs/utils/shim.js +18 -0
  161. package/mjs/utils/upperFirst.d.ts +1 -0
  162. package/mjs/utils/upperFirst.js +6 -0
  163. package/mjs/utils/withValidationLibrary.d.ts +77 -0
  164. package/mjs/utils/withValidationLibrary.js +124 -0
  165. package/package.json +28 -6
  166. package/.npmignore +0 -2
  167. package/StreamJSONResponse.d.ts +0 -17
  168. package/StreamJSONResponse.js +0 -54
  169. package/VovkApp.js +0 -185
  170. package/client/clientizeController.d.ts +0 -4
  171. package/client/clientizeController.js +0 -93
  172. package/client/defaultFetcher.d.ts +0 -4
  173. package/client/defaultFetcher.js +0 -49
  174. package/client/defaultHandler.d.ts +0 -2
  175. package/client/defaultStreamHandler.d.ts +0 -4
  176. package/client/index.d.ts +0 -4
  177. package/client/index.js +0 -5
  178. package/client/types.d.ts +0 -100
  179. package/createDecorator.d.ts +0 -4
  180. package/createVovkApp.js +0 -118
  181. package/index.d.ts +0 -60
  182. package/index.js +0 -20
  183. package/types.d.ts +0 -157
  184. package/utils/generateStaticAPI.js +0 -18
  185. package/utils/getSchema.d.ts +0 -8
  186. package/utils/getSchema.js +0 -38
  187. package/utils/reqForm.d.ts +0 -3
  188. package/utils/reqForm.js +0 -13
  189. package/utils/reqMeta.d.ts +0 -3
  190. package/utils/reqQuery.d.ts +0 -3
  191. package/utils/reqQuery.js +0 -25
  192. package/utils/setClientValidatorsForHandler.d.ts +0 -5
  193. package/utils/setClientValidatorsForHandler.js +0 -25
  194. package/worker/index.d.ts +0 -3
  195. package/worker/index.js +0 -7
  196. package/worker/promisifyWorker.d.ts +0 -2
  197. package/worker/promisifyWorker.js +0 -141
  198. package/worker/types.d.ts +0 -31
  199. package/worker/worker.d.ts +0 -1
  200. package/worker/worker.js +0 -43
  201. /package/{HttpException.d.ts → cjs/HttpException.d.ts} +0 -0
  202. /package/{HttpException.js → cjs/HttpException.js} +0 -0
  203. /package/{client → cjs/client}/types.js +0 -0
  204. /package/{utils → cjs/utils}/reqMeta.js +0 -0
  205. /package/{utils → cjs/utils}/shim.d.ts +0 -0
  206. /package/{utils → cjs/utils}/shim.js +0 -0
  207. /package/{worker → mjs/client}/types.js +0 -0
@@ -0,0 +1,167 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getJSONSchemaSample = getJSONSchemaSample;
4
+ function getJSONSchemaSample(schema, rootSchema) {
5
+ if (!schema || typeof schema !== 'object')
6
+ return null;
7
+ // Use the input schema as the root if not provided
8
+ rootSchema = rootSchema || schema;
9
+ // If there's an example, use it
10
+ if (schema.example !== undefined) {
11
+ return schema.example;
12
+ }
13
+ // If there are examples, use one of them
14
+ if (schema.examples && schema.examples.length > 0) {
15
+ return schema.examples[0];
16
+ }
17
+ // Handle const if present
18
+ if (schema.const !== undefined) {
19
+ return schema.const;
20
+ }
21
+ // Handle $ref if present
22
+ if (schema.$ref) {
23
+ return handleRef(schema.$ref, rootSchema);
24
+ }
25
+ // Handle enum if present
26
+ if (schema.enum && schema.enum.length > 0) {
27
+ return schema.enum[0];
28
+ }
29
+ // Handle oneOf, anyOf, allOf
30
+ if (schema.oneOf && schema.oneOf.length > 0) {
31
+ return getJSONSchemaSample(schema.oneOf[0], rootSchema);
32
+ }
33
+ if (schema.anyOf && schema.anyOf.length > 0) {
34
+ return getJSONSchemaSample(schema.anyOf[0], rootSchema);
35
+ }
36
+ if (schema.allOf && schema.allOf.length > 0) {
37
+ // Merge all schemas in allOf
38
+ const mergedSchema = schema.allOf.reduce((acc, s) => ({ ...acc, ...s }), {});
39
+ return getJSONSchemaSample(mergedSchema, rootSchema);
40
+ }
41
+ // Handle different types
42
+ if (schema.type) {
43
+ switch (schema.type) {
44
+ case 'string':
45
+ return handleString(schema);
46
+ case 'number':
47
+ case 'integer':
48
+ return handleNumber(schema);
49
+ case 'boolean':
50
+ return handleBoolean();
51
+ case 'object':
52
+ return handleObject(schema, rootSchema);
53
+ case 'array':
54
+ return handleArray(schema, rootSchema);
55
+ case 'null':
56
+ return null;
57
+ default:
58
+ return null;
59
+ }
60
+ }
61
+ // If type is not specified but properties are, treat it as an object
62
+ if (schema.properties) {
63
+ return handleObject(schema, rootSchema);
64
+ }
65
+ // Default fallback
66
+ return null;
67
+ }
68
+ function handleRef(ref, rootSchema) {
69
+ // Parse the reference path
70
+ const path = ref.split('/').slice(1); // Remove the initial '#'
71
+ // Navigate through the schema to find the referenced definition
72
+ let current = rootSchema;
73
+ for (const segment of path) {
74
+ current = current[segment];
75
+ if (current === undefined) {
76
+ return null; // Reference not found
77
+ }
78
+ }
79
+ // Process the referenced schema
80
+ return getJSONSchemaSample(current, rootSchema);
81
+ }
82
+ function handleString(schema) {
83
+ if (schema.format) {
84
+ switch (schema.format) {
85
+ case 'email':
86
+ case 'idn-email':
87
+ return 'user@example.com';
88
+ case 'uri':
89
+ case 'url':
90
+ case 'iri':
91
+ return 'https://example.com';
92
+ case 'date':
93
+ return '2023-01-01';
94
+ case 'date-time':
95
+ return '2023-01-01T00:00:00Z';
96
+ case 'time':
97
+ return '12:00:00Z';
98
+ case 'duration':
99
+ return 'PT1H';
100
+ case 'uuid':
101
+ return '00000000-0000-0000-0000-000000000000';
102
+ case 'regex':
103
+ return '^[a-zA-Z0-9]+$';
104
+ case 'relative-json-pointer':
105
+ return '/some/relative/path';
106
+ case 'color':
107
+ return '#000000';
108
+ case 'hostname':
109
+ return 'example.com';
110
+ case 'zipcode':
111
+ return '12345';
112
+ case 'phone':
113
+ return '+123-456-7890';
114
+ case 'password':
115
+ return '******';
116
+ default:
117
+ return 'string';
118
+ }
119
+ }
120
+ if (schema.pattern) {
121
+ // For simplicity, return a basic string for patterns
122
+ return 'pattern-string';
123
+ }
124
+ return 'string';
125
+ }
126
+ function handleNumber(schema) {
127
+ if (schema.minimum !== undefined && schema.maximum !== undefined) {
128
+ return schema.minimum;
129
+ }
130
+ else if (schema.minimum !== undefined) {
131
+ return schema.minimum;
132
+ }
133
+ else if (schema.maximum !== undefined) {
134
+ return schema.maximum;
135
+ }
136
+ return 0;
137
+ }
138
+ function handleBoolean() {
139
+ return true;
140
+ }
141
+ function handleObject(schema, rootSchema) {
142
+ const result = {};
143
+ if (schema.properties) {
144
+ const required = schema.required || [];
145
+ for (const [key, propSchema] of Object.entries(schema.properties)) {
146
+ // Only include required properties or as a basic example
147
+ if (required.includes(key) || required.length === 0) {
148
+ result[key] = getJSONSchemaSample(propSchema, rootSchema);
149
+ }
150
+ }
151
+ }
152
+ // Handle additionalProperties
153
+ if (schema.additionalProperties && typeof schema.additionalProperties === 'object') {
154
+ result['additionalProp'] = getJSONSchemaSample(schema.additionalProperties, rootSchema);
155
+ }
156
+ return result;
157
+ }
158
+ function handleArray(schema, rootSchema) {
159
+ if (schema.items) {
160
+ const itemSchema = schema.items;
161
+ const minItems = schema.minItems || 1;
162
+ // Create minimum number of items (capped at a reasonable max for examples)
163
+ const numItems = Math.min(minItems, 3);
164
+ return Array.from({ length: numItems }, () => getJSONSchemaSample(itemSchema, rootSchema));
165
+ }
166
+ return [];
167
+ }
@@ -0,0 +1,9 @@
1
+ import { KnownAny } from '../types';
2
+ interface SamplerOptions {
3
+ stripQuotes?: boolean;
4
+ indent?: number;
5
+ nestingIndent?: number;
6
+ quote?: '"' | "'";
7
+ }
8
+ export declare function getSampleFromObject(obj: KnownAny, options?: SamplerOptions): string;
9
+ export {};
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getSampleFromObject = getSampleFromObject;
4
+ function getSampleFromObject(obj, options) {
5
+ const { stripQuotes = false, indent = 0, nestingIndent = 2, quote = '"' } = options || {};
6
+ // Use JSON.stringify with the nesting indent
7
+ let result = JSON.stringify(obj, null, nestingIndent);
8
+ // Replace double quotes with single quotes for string values if requested
9
+ if (quote === "'") {
10
+ // First, escape any existing single quotes in string values
11
+ result = result.replace(/"([^"]*)"/g, (match, content) => {
12
+ // Check if this is a key (followed by colon) or a value
13
+ const matchIndex = result.indexOf(match);
14
+ const afterMatch = result.substring(matchIndex + match.length);
15
+ if (afterMatch.startsWith(':')) {
16
+ // This is a key, keep it for now
17
+ return match;
18
+ }
19
+ // This is a value, replace quotes and escape single quotes
20
+ const escaped = content.replace(/'/g, "\\'");
21
+ return `'${escaped}'`;
22
+ });
23
+ }
24
+ // Strip quotes from keys if requested
25
+ if (stripQuotes) {
26
+ // Remove quotes from keys that are valid JavaScript identifiers
27
+ // Keep quotes for keys with special characters (like 'x-foo', spaces, etc.)
28
+ const keyQuote = quote === "'" ? "'" : '"';
29
+ const pattern = new RegExp(`${keyQuote}([a-zA-Z_$][a-zA-Z0-9_$]*)${keyQuote}:`, 'g');
30
+ result = result.replace(pattern, '$1:');
31
+ }
32
+ // Apply base indentation if specified
33
+ if (indent > 0) {
34
+ const indentStr = ' '.repeat(indent);
35
+ result = result
36
+ .split('\n')
37
+ .map((line, i) => (i === 0 ? line : indentStr + line))
38
+ .join('\n');
39
+ }
40
+ return result;
41
+ }
@@ -0,0 +1,21 @@
1
+ import { type VovkSegmentSchema, type VovkController, type StaticClass } from '../types';
2
+ export declare function getControllerSchema(controller: VovkController, rpcModuleName: string, exposeValidation: boolean): Promise<{
3
+ rpcModuleName: string;
4
+ originalControllerName: string;
5
+ prefix: string;
6
+ handlers: {
7
+ [k: string]: {
8
+ path: string;
9
+ httpMethod: string;
10
+ operationObject?: import("../types").VovkOperationObject;
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
+ forceApiRoot?: string;
21
+ }): Promise<VovkSegmentSchema>;
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getControllerSchema = getControllerSchema;
4
+ exports.default = getSchema;
5
+ const types_1 = require("../types");
6
+ async function getControllerSchema(controller, rpcModuleName, exposeValidation) {
7
+ const handlers = exposeValidation
8
+ ? (controller._handlers ?? {})
9
+ : Object.fromEntries(
10
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
11
+ Object.entries(controller._handlers ?? {}).map(([key, { validation: _v, ...value }]) => [key, value]));
12
+ return {
13
+ rpcModuleName,
14
+ originalControllerName: controller.name,
15
+ prefix: controller._prefix ?? '',
16
+ handlers,
17
+ };
18
+ }
19
+ async function getSchema(options) {
20
+ const exposeValidation = options?.exposeValidation ?? true;
21
+ const emitSchema = options.emitSchema ?? true;
22
+ const schema = {
23
+ $schema: types_1.VovkSchemaIdEnum.SEGMENT,
24
+ emitSchema,
25
+ segmentName: options.segmentName ?? '',
26
+ segmentType: 'segment',
27
+ controllers: {},
28
+ };
29
+ if (options.forceApiRoot) {
30
+ schema.forceApiRoot = options.forceApiRoot;
31
+ }
32
+ if (!emitSchema)
33
+ return schema;
34
+ for (const [rpcModuleName, controller] of Object.entries(options.controllers ?? {})) {
35
+ schema.controllers[rpcModuleName] = await getControllerSchema(controller, rpcModuleName, exposeValidation);
36
+ }
37
+ return schema;
38
+ }
@@ -0,0 +1,24 @@
1
+ type Override = {
2
+ from: string;
3
+ to: string;
4
+ };
5
+ type Config = {
6
+ requestUrl: string;
7
+ requestHost: string;
8
+ targetHost: string;
9
+ overrides: {
10
+ [key: string]: Override[];
11
+ };
12
+ };
13
+ export declare function multitenant(config: Config): {
14
+ action: null;
15
+ destination: null;
16
+ message: string;
17
+ subdomains: null;
18
+ } | {
19
+ action: string;
20
+ destination: string;
21
+ message: string;
22
+ subdomains: Record<string, string> | null;
23
+ };
24
+ export {};
@@ -0,0 +1,131 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.multitenant = multitenant;
4
+ // Get the reserved paths from the overrides configuration
5
+ const getReservedPaths = (overrides) => {
6
+ return Object.keys(overrides).filter((key) => !key.includes('[') && !key.includes(']')); // Filter out dynamic paths
7
+ };
8
+ /**
9
+ * Convert a pattern with [placeholders] to a regex pattern and extract placeholder names
10
+ */
11
+ const patternToRegex = (pattern) => {
12
+ const paramNames = [];
13
+ const regexPattern = pattern
14
+ .replace(/\[([^\]]+)\]/g, (_, name) => {
15
+ paramNames.push(name);
16
+ return '([^.]+)';
17
+ })
18
+ .replace(/\./g, '\\.'); // Escape dots in the pattern
19
+ return {
20
+ regex: new RegExp(`^${regexPattern}$`),
21
+ paramNames,
22
+ };
23
+ };
24
+ function multitenant(config) {
25
+ const { requestUrl, requestHost, targetHost, overrides } = config;
26
+ // Parse the URL
27
+ const urlObj = new URL(requestUrl);
28
+ const pathname = urlObj.pathname.slice(1); // Remove leading slash
29
+ // Skip processing for paths ending with "_schema_"
30
+ if (pathname.endsWith('_schema_')) {
31
+ return {
32
+ action: null,
33
+ destination: null,
34
+ message: 'Schema endpoint, bypassing overrides',
35
+ subdomains: null,
36
+ };
37
+ }
38
+ const pathSegments = pathname.split('/').filter(Boolean);
39
+ // Get reserved paths
40
+ const reservedPaths = getReservedPaths(overrides);
41
+ // Check if any path segment matches a reserved path (e.g., "admin")
42
+ for (let i = 0; i < pathSegments.length; i++) {
43
+ const segment = pathSegments[i];
44
+ if (reservedPaths.includes(segment)) {
45
+ // Create the destination URL with the reserved path as subdomain
46
+ const destinationHost = `${segment}.${targetHost}`;
47
+ // Keep path segments before the reserved path
48
+ const beforeSegments = pathSegments.slice(0, i);
49
+ // Keep path segments after the reserved path
50
+ const afterSegments = pathSegments.slice(i + 1);
51
+ // Construct the new path
52
+ const newPath = [...beforeSegments, ...afterSegments].join('/');
53
+ const destinationUrl = new URL(`${urlObj.protocol}//${destinationHost}`);
54
+ if (newPath) {
55
+ destinationUrl.pathname = `/${newPath}`;
56
+ }
57
+ // Keep any query parameters
58
+ destinationUrl.search = urlObj.search;
59
+ return {
60
+ action: 'redirect',
61
+ destination: destinationUrl.toString(),
62
+ message: `Redirecting to ${segment} subdomain`,
63
+ subdomains: null, // No wildcards used
64
+ };
65
+ }
66
+ }
67
+ // Process based on host and subdomains
68
+ for (const pattern in overrides) {
69
+ const fullPattern = `${pattern}.${targetHost}`;
70
+ const { regex, paramNames } = patternToRegex(fullPattern);
71
+ const match = requestHost.match(regex);
72
+ if (match) {
73
+ const overrideRules = overrides[pattern];
74
+ // Extract parameters from the match
75
+ const params = {};
76
+ if (match.length > 1) {
77
+ for (let i = 0; i < paramNames.length; i++) {
78
+ params[paramNames[i]] = match[i + 1];
79
+ }
80
+ }
81
+ // Find the appropriate rule based on the path
82
+ for (const rule of overrideRules) {
83
+ if (pathname === rule.from || pathname.startsWith(`${rule.from}/`)) {
84
+ // Replace path with the destination
85
+ let destination = pathname.replace(rule.from, rule.to);
86
+ // Replace any dynamic parameters in destination
87
+ if (Object.keys(params).length > 0) {
88
+ Object.entries(params).forEach(([key, value]) => {
89
+ destination = destination.replace(`[${key}]`, value);
90
+ });
91
+ }
92
+ // Only return non-null subdomains if we have wildcard parameters
93
+ const wildcardSubdomains = paramNames.length > 0 ? params : null;
94
+ return {
95
+ action: 'rewrite',
96
+ destination: `${urlObj.protocol}//${urlObj.host}/${destination}${urlObj.search}`,
97
+ message: `Rewriting to ${destination}`,
98
+ subdomains: wildcardSubdomains,
99
+ };
100
+ }
101
+ }
102
+ }
103
+ }
104
+ // Handle cases where a customer subdomain tries to access reserved paths
105
+ if (pathSegments.length > 0 && reservedPaths.includes(pathSegments[0])) {
106
+ const reservedPath = pathSegments[0];
107
+ const restPath = pathSegments.slice(1).join('/');
108
+ // Create the destination URL with the reserved path as subdomain
109
+ const destinationHost = `${reservedPath}.${targetHost}`;
110
+ const destinationUrl = new URL(`${urlObj.protocol}//${destinationHost}`);
111
+ // Only add remaining path segments if they exist
112
+ if (restPath) {
113
+ destinationUrl.pathname = `/${restPath}`;
114
+ }
115
+ // Keep any query parameters
116
+ destinationUrl.search = urlObj.search;
117
+ return {
118
+ action: 'redirect',
119
+ destination: destinationUrl.toString(),
120
+ message: `Redirecting to ${reservedPath} subdomain`,
121
+ subdomains: null, // No wildcards used for reserved paths
122
+ };
123
+ }
124
+ // Default case - pass through
125
+ return {
126
+ action: null,
127
+ destination: null,
128
+ message: 'No action',
129
+ subdomains: null, // No wildcards matched
130
+ };
131
+ }
@@ -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
+ }
@@ -0,0 +1,2 @@
1
+ import type { KnownAny, VovkRequest } from '../types';
2
+ export default function reqForm<T = KnownAny>(req: VovkRequest<KnownAny, KnownAny, KnownAny>): Promise<T>;
@@ -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,2 @@
1
+ import type { KnownAny, VovkRequest } from '../types';
2
+ export default function reqMeta<T = Record<KnownAny, KnownAny>>(req: VovkRequest<KnownAny, KnownAny, KnownAny>, meta?: T | null): T;
@@ -0,0 +1,2 @@
1
+ import type { VovkRequest } from '../types';
2
+ export default function reqQuery<T extends object | undefined>(req: VovkRequest<unknown, T>): T;
@@ -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_1 = __importDefault(require("./parseQuery"));
8
+ function reqQuery(req) {
9
+ return (0, parseQuery_1.default)(req.nextUrl.search);
10
+ }