vovk 3.0.0-draft.431 → 3.0.0-draft.433

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.
@@ -1,13 +1,34 @@
1
1
  import type { NextRequest } from 'next/server';
2
- import { type KnownAny, type VovkRequest, type StaticClass } from './types';
2
+ import { type KnownAny, type DecoratorOptions, type VovkRequest, type StaticClass } from './types';
3
3
  export declare function createVovkApp(): {
4
- get: any;
5
- post: any;
6
- put: any;
7
- patch: any;
8
- del: any;
9
- head: any;
10
- options: any;
4
+ get: {
5
+ (givenPath?: string | undefined, options?: DecoratorOptions | undefined): (givenTarget: KnownAny, propertyKey: string) => void;
6
+ auto: (options?: DecoratorOptions) => (givenTarget: KnownAny, propertyKey: string) => void;
7
+ };
8
+ post: {
9
+ (givenPath?: string | undefined, options?: Omit<DecoratorOptions, "staticParams"> | undefined): (givenTarget: KnownAny, propertyKey: string) => void;
10
+ auto: (options?: DecoratorOptions) => (givenTarget: KnownAny, propertyKey: string) => void;
11
+ };
12
+ put: {
13
+ (givenPath?: string | undefined, options?: Omit<DecoratorOptions, "staticParams"> | undefined): (givenTarget: KnownAny, propertyKey: string) => void;
14
+ auto: (options?: DecoratorOptions) => (givenTarget: KnownAny, propertyKey: string) => void;
15
+ };
16
+ patch: {
17
+ (givenPath?: string | undefined, options?: Omit<DecoratorOptions, "staticParams"> | undefined): (givenTarget: KnownAny, propertyKey: string) => void;
18
+ auto: (options?: DecoratorOptions) => (givenTarget: KnownAny, propertyKey: string) => void;
19
+ };
20
+ del: {
21
+ (givenPath?: string | undefined, options?: Omit<DecoratorOptions, "staticParams"> | undefined): (givenTarget: KnownAny, propertyKey: string) => void;
22
+ auto: (options?: DecoratorOptions) => (givenTarget: KnownAny, propertyKey: string) => void;
23
+ };
24
+ head: {
25
+ (givenPath?: string | undefined, options?: Omit<DecoratorOptions, "staticParams"> | undefined): (givenTarget: KnownAny, propertyKey: string) => void;
26
+ auto: (options?: DecoratorOptions) => (givenTarget: KnownAny, propertyKey: string) => void;
27
+ };
28
+ options: {
29
+ (givenPath?: string | undefined, options?: Omit<DecoratorOptions, "staticParams"> | undefined): (givenTarget: KnownAny, propertyKey: string) => void;
30
+ auto: (options?: DecoratorOptions) => (givenTarget: KnownAny, propertyKey: string) => void;
31
+ };
11
32
  prefix: (givenPath?: string) => (givenTarget: KnownAny) => any;
12
33
  initSegment: (options: {
13
34
  segmentName?: string;
@@ -7,18 +7,13 @@ exports.createVovkApp = createVovkApp;
7
7
  const VovkApp_1 = require("./VovkApp");
8
8
  const types_1 = require("./types");
9
9
  const getSchema_1 = __importDefault(require("./utils/getSchema"));
10
- // Pre-compiled regex patterns for better performance
11
- const TRIM_SLASH_REGEX = /^\/|\/$/g;
12
- const trimPath = (path) => path.trim().replace(TRIM_SLASH_REGEX, '');
13
- // Keep original class detection for compatibility with all class types
14
- const isClass = (func) => {
15
- return typeof func === 'function' && /class/.test(func.toString());
16
- };
17
- // Pre-compiled regex for kebab case
18
- const KEBAB_REGEX_1 = /([a-z0-9])([A-Z])/g;
19
- const KEBAB_REGEX_2 = /([A-Z])([A-Z])(?=[a-z])/g;
20
- const LEADING_HYPHEN = /^-/;
21
- const toKebabCase = (str) => str.replace(KEBAB_REGEX_1, '$1-$2').replace(KEBAB_REGEX_2, '$1-$2').toLowerCase().replace(LEADING_HYPHEN, '');
10
+ const trimPath = (path) => path.trim().replace(/^\/|\/$/g, '');
11
+ const isClass = (func) => typeof func === 'function' && /class/.test(func.toString());
12
+ const toKebabCase = (str) => str
13
+ .replace(/([a-z0-9])([A-Z])/g, '$1-$2') // Add hyphen between lowercase/digit and uppercase
14
+ .replace(/([A-Z])([A-Z])(?=[a-z])/g, '$1-$2') // Add hyphen between uppercase letters if the second one is followed by a lowercase
15
+ .toLowerCase()
16
+ .replace(/^-/, ''); // Remove leading hyphen
22
17
  const assignSchema = ({ controller, propertyKey, path, options, httpMethod, vovkApp, }) => {
23
18
  if (typeof window !== 'undefined') {
24
19
  throw new Error('HTTP decorators can be used on server-side only. You have probably imported a controller on the client-side.');
@@ -29,48 +24,41 @@ const assignSchema = ({ controller, propertyKey, path, options, httpMethod, vovk
29
24
  decoratorName = 'del';
30
25
  throw new Error(`Decorator must be used on a static class method. Check the controller method named "${propertyKey}" used with @${decoratorName}().`);
31
26
  }
32
- // Get or create methods object with single Map lookup
33
- const httpMethodMap = vovkApp.routes[httpMethod];
34
- let methods = httpMethodMap.get(controller);
35
- if (!methods) {
36
- httpMethodMap.set(controller, (methods = Object.create(null)));
37
- }
38
- // Handle CORS with minimal overhead
27
+ const methods = vovkApp.routes[httpMethod].get(controller) ?? {};
28
+ vovkApp.routes[httpMethod].set(controller, methods);
39
29
  if (options?.cors) {
40
- const optionsMap = vovkApp.routes.OPTIONS;
41
- let optionsMethods = optionsMap.get(controller);
42
- if (!optionsMethods) {
43
- optionsMap.set(controller, (optionsMethods = Object.create(null)));
44
- }
30
+ const optionsMethods = vovkApp.routes.OPTIONS.get(controller) ?? {};
45
31
  optionsMethods[path] = (() => { });
46
32
  optionsMethods[path]._options = options;
33
+ vovkApp.routes.OPTIONS.set(controller, optionsMethods);
47
34
  }
48
35
  const originalMethod = controller[propertyKey];
49
- // Direct property assignment without intermediate variables
50
36
  originalMethod._controller = controller;
51
- originalMethod._sourceMethod = originalMethod._sourceMethod || originalMethod;
52
- const sourceMethod = originalMethod._sourceMethod;
53
- const schema = sourceMethod._getSchema?.(controller);
54
- // Batch assign properties only if schema exists
55
- if (schema) {
56
- originalMethod.schema = schema;
57
- originalMethod.fn = sourceMethod.fn;
58
- originalMethod.models = sourceMethod.models;
59
- sourceMethod.wrapper = originalMethod;
60
- }
61
- // Use Object.assign for better performance than spread
62
- controller._handlers = controller._handlers || Object.create(null);
63
- controller._handlers[propertyKey] = Object.assign(Object.create(null), schema, controller._handlers[propertyKey], {
64
- path,
65
- httpMethod,
66
- });
37
+ originalMethod._sourceMethod = originalMethod._sourceMethod ?? originalMethod;
38
+ const schema = originalMethod._sourceMethod._getSchema?.(controller);
39
+ // TODO: Some of these assignments probably not needed anymore
40
+ originalMethod.schema = schema;
41
+ originalMethod.fn = originalMethod._sourceMethod?.fn;
42
+ originalMethod.models = originalMethod._sourceMethod?.models;
43
+ originalMethod._sourceMethod.wrapper = originalMethod;
44
+ controller._handlers = {
45
+ ...controller._handlers,
46
+ [propertyKey]: {
47
+ ...schema,
48
+ ...(controller._handlers ?? {})[propertyKey],
49
+ path,
50
+ httpMethod,
51
+ },
52
+ };
67
53
  methods[path] = originalMethod;
68
54
  methods[path]._options = options;
69
- // Only create metadata if needed
70
- if (options?.staticParams) {
71
- controller._handlersMetadata = controller._handlersMetadata || Object.create(null);
72
- controller._handlersMetadata[propertyKey] = Object.assign(Object.create(null), controller._handlersMetadata[propertyKey], { staticParams: options.staticParams });
73
- }
55
+ controller._handlersMetadata = {
56
+ ...controller._handlersMetadata,
57
+ [propertyKey]: {
58
+ ...(controller._handlersMetadata ?? {})[propertyKey],
59
+ staticParams: options?.staticParams,
60
+ },
61
+ };
74
62
  };
75
63
  function createVovkApp() {
76
64
  const vovkApp = new VovkApp_1.VovkApp();
@@ -86,40 +74,25 @@ function createVovkApp() {
86
74
  const auto = (options) => {
87
75
  function decorator(givenTarget, propertyKey) {
88
76
  const controller = givenTarget;
89
- // Single Map lookup
90
- let methods = vovkApp.routes[httpMethod].get(controller);
91
- if (!methods) {
92
- vovkApp.routes[httpMethod].set(controller, (methods = Object.create(null)));
93
- }
94
- controller._handlers = controller._handlers || Object.create(null);
95
- controller._handlers[propertyKey] = Object.assign(Object.create(null), controller._handlers[propertyKey], {
96
- httpMethod,
97
- });
98
- // Build path efficiently
99
- const validation = controller._handlers[propertyKey]?.validation;
100
- const params = validation?.params?.properties;
101
- const kebab = toKebabCase(propertyKey);
102
- let path;
103
- if (params) {
104
- const keys = Object.keys(params);
105
- if (keys.length) {
106
- // Use array join instead of template literals for better performance
107
- const paramPath = keys.map((prop) => `{${prop}}`).join('/');
108
- path = `${kebab}/${paramPath}`;
109
- }
110
- else {
111
- path = kebab;
112
- }
113
- }
114
- else {
115
- path = kebab;
116
- }
77
+ const methods = vovkApp.routes[httpMethod].get(controller) ?? {};
78
+ vovkApp.routes[httpMethod].set(controller, methods);
79
+ controller._handlers = {
80
+ ...controller._handlers,
81
+ [propertyKey]: {
82
+ ...(controller._handlers ?? {})[propertyKey],
83
+ httpMethod,
84
+ },
85
+ };
86
+ const properties = Object.keys(controller._handlers[propertyKey]?.validation?.params?.properties ?? {});
87
+ const kebab = toKebabCase(propertyKey); // 🥙
88
+ const path = properties.length ? `${kebab}/${properties.map((prop) => `{${prop}}`).join('/')}` : kebab;
117
89
  assignSchema({ controller, propertyKey, path, options, httpMethod, vovkApp });
118
90
  }
119
91
  return decorator;
120
92
  };
121
- decoratorCreator.auto = auto;
122
- return decoratorCreator;
93
+ const enhancedDecoratorCreator = decoratorCreator;
94
+ enhancedDecoratorCreator.auto = auto;
95
+ return enhancedDecoratorCreator;
123
96
  }
124
97
  const prefix = (givenPath = '') => {
125
98
  const path = trimPath(givenPath);
@@ -131,23 +104,15 @@ function createVovkApp() {
131
104
  };
132
105
  const initSegment = (options) => {
133
106
  options.segmentName = trimPath(options.segmentName ?? '');
134
- // Use for..of instead of Object.entries for better performance
135
- for (const rpcModuleName in options.controllers) {
136
- if (Object.prototype.hasOwnProperty.call(options.controllers, rpcModuleName)) {
137
- const controller = options.controllers[rpcModuleName];
138
- controller._rpcModuleName = rpcModuleName;
139
- controller._onError = options?.onError;
140
- }
107
+ for (const [rpcModuleName, controller] of Object.entries(options.controllers ?? {})) {
108
+ controller._rpcModuleName = rpcModuleName;
109
+ controller._onError = options?.onError;
141
110
  }
142
111
  async function GET_DEV(req, data) {
143
112
  const params = await data.params;
144
- // Direct access without creating intermediate array
145
- for (const key in params) {
146
- if (params[key]?.[0] === '_schema_') {
147
- const schema = await (0, getSchema_1.default)(options);
148
- return vovkApp.respond(200, { schema });
149
- }
150
- break; // Only check first param
113
+ if (params[Object.keys(params)[0]]?.[0] === '_schema_') {
114
+ const schema = await (0, getSchema_1.default)(options);
115
+ return vovkApp.respond(200, { schema });
151
116
  }
152
117
  return vovkApp.GET(req, data);
153
118
  }
package/cjs/index.d.ts CHANGED
@@ -14,7 +14,28 @@ import { createCodeSamples } from './utils/createCodeSamples';
14
14
  import { createValidateOnClient } from './utils/createValidateOnClient';
15
15
  import { resolveGeneratorConfigValues } from './utils/resolveGeneratorConfigValues';
16
16
  export { type KnownAny, type VovkRPCModule, type VovkFetcher, type VovkFetcherOptions, type VovkStreamAsyncIterable, type VovkValidateOnClient, type VovkSegmentSchema, type VovkErrorResponse, type VovkRequest, type VovkOutput, type VovkIteration, type VovkBody, type VovkQuery, type VovkParams, type VovkYieldType, type VovkReturnType, type VovkMetaSchema, type VovkControllerSchema, type VovkHandlerSchema, type VovkSchema, type VovkConfig, type VovkStrictConfig, type VovkGeneratorConfig, type VovkReadmeConfig, type VovkSamplesConfig, type VovkOpenAPIMixin, type VovkOpenAPIMixinNormalized, type VovkValidationType, type VovkLLMTool, type VovkTypedMethod, type VovkBasicJSONSchema, type VovkOperationObject, VovkSchemaIdEnum, JSONLinesResponse, HttpException, HttpStatus, HttpMethod, createVovkApp, createDecorator, createRPC, fetcher, createFetcher, generateStaticAPI, withValidationLibrary, createStandardValidation, multitenant, createLLMTools, createCodeSamples, createValidateOnClient, progressive, operation, openAPIToVovkSchema, vovkSchemaToOpenAPI, resolveGeneratorConfigValues, };
17
- export declare const get: any, post: any, put: any, patch: any, del: any, head: any, options: any, prefix: (givenPath?: string) => (givenTarget: KnownAny) => any, initSegment: (options: {
17
+ export declare const get: {
18
+ (givenPath?: string | undefined, options?: import("./types").DecoratorOptions | undefined): (givenTarget: KnownAny, propertyKey: string) => void;
19
+ auto: (options?: import("./types").DecoratorOptions) => (givenTarget: KnownAny, propertyKey: string) => void;
20
+ }, post: {
21
+ (givenPath?: string | undefined, options?: Omit<import("./types").DecoratorOptions, "staticParams"> | undefined): (givenTarget: KnownAny, propertyKey: string) => void;
22
+ auto: (options?: import("./types").DecoratorOptions) => (givenTarget: KnownAny, propertyKey: string) => void;
23
+ }, put: {
24
+ (givenPath?: string | undefined, options?: Omit<import("./types").DecoratorOptions, "staticParams"> | undefined): (givenTarget: KnownAny, propertyKey: string) => void;
25
+ auto: (options?: import("./types").DecoratorOptions) => (givenTarget: KnownAny, propertyKey: string) => void;
26
+ }, patch: {
27
+ (givenPath?: string | undefined, options?: Omit<import("./types").DecoratorOptions, "staticParams"> | undefined): (givenTarget: KnownAny, propertyKey: string) => void;
28
+ auto: (options?: import("./types").DecoratorOptions) => (givenTarget: KnownAny, propertyKey: string) => void;
29
+ }, del: {
30
+ (givenPath?: string | undefined, options?: Omit<import("./types").DecoratorOptions, "staticParams"> | undefined): (givenTarget: KnownAny, propertyKey: string) => void;
31
+ auto: (options?: import("./types").DecoratorOptions) => (givenTarget: KnownAny, propertyKey: string) => void;
32
+ }, head: {
33
+ (givenPath?: string | undefined, options?: Omit<import("./types").DecoratorOptions, "staticParams"> | undefined): (givenTarget: KnownAny, propertyKey: string) => void;
34
+ auto: (options?: import("./types").DecoratorOptions) => (givenTarget: KnownAny, propertyKey: string) => void;
35
+ }, options: {
36
+ (givenPath?: string | undefined, options?: Omit<import("./types").DecoratorOptions, "staticParams"> | undefined): (givenTarget: KnownAny, propertyKey: string) => void;
37
+ auto: (options?: import("./types").DecoratorOptions) => (givenTarget: KnownAny, propertyKey: string) => void;
38
+ }, prefix: (givenPath?: string) => (givenTarget: KnownAny) => any, initSegment: (options: {
18
39
  segmentName?: string;
19
40
  controllers: Record<string, import("./types").StaticClass>;
20
41
  exposeValidation?: boolean;
@@ -1,13 +1,34 @@
1
1
  import type { NextRequest } from 'next/server';
2
- import { type KnownAny, type VovkRequest, type StaticClass } from './types';
2
+ import { type KnownAny, type DecoratorOptions, type VovkRequest, type StaticClass } from './types';
3
3
  export declare function createVovkApp(): {
4
- get: any;
5
- post: any;
6
- put: any;
7
- patch: any;
8
- del: any;
9
- head: any;
10
- options: any;
4
+ get: {
5
+ (givenPath?: string | undefined, options?: DecoratorOptions | undefined): (givenTarget: KnownAny, propertyKey: string) => void;
6
+ auto: (options?: DecoratorOptions) => (givenTarget: KnownAny, propertyKey: string) => void;
7
+ };
8
+ post: {
9
+ (givenPath?: string | undefined, options?: Omit<DecoratorOptions, "staticParams"> | undefined): (givenTarget: KnownAny, propertyKey: string) => void;
10
+ auto: (options?: DecoratorOptions) => (givenTarget: KnownAny, propertyKey: string) => void;
11
+ };
12
+ put: {
13
+ (givenPath?: string | undefined, options?: Omit<DecoratorOptions, "staticParams"> | undefined): (givenTarget: KnownAny, propertyKey: string) => void;
14
+ auto: (options?: DecoratorOptions) => (givenTarget: KnownAny, propertyKey: string) => void;
15
+ };
16
+ patch: {
17
+ (givenPath?: string | undefined, options?: Omit<DecoratorOptions, "staticParams"> | undefined): (givenTarget: KnownAny, propertyKey: string) => void;
18
+ auto: (options?: DecoratorOptions) => (givenTarget: KnownAny, propertyKey: string) => void;
19
+ };
20
+ del: {
21
+ (givenPath?: string | undefined, options?: Omit<DecoratorOptions, "staticParams"> | undefined): (givenTarget: KnownAny, propertyKey: string) => void;
22
+ auto: (options?: DecoratorOptions) => (givenTarget: KnownAny, propertyKey: string) => void;
23
+ };
24
+ head: {
25
+ (givenPath?: string | undefined, options?: Omit<DecoratorOptions, "staticParams"> | undefined): (givenTarget: KnownAny, propertyKey: string) => void;
26
+ auto: (options?: DecoratorOptions) => (givenTarget: KnownAny, propertyKey: string) => void;
27
+ };
28
+ options: {
29
+ (givenPath?: string | undefined, options?: Omit<DecoratorOptions, "staticParams"> | undefined): (givenTarget: KnownAny, propertyKey: string) => void;
30
+ auto: (options?: DecoratorOptions) => (givenTarget: KnownAny, propertyKey: string) => void;
31
+ };
11
32
  prefix: (givenPath?: string) => (givenTarget: KnownAny) => any;
12
33
  initSegment: (options: {
13
34
  segmentName?: string;
@@ -7,18 +7,13 @@ exports.createVovkApp = createVovkApp;
7
7
  const VovkApp_1 = require("./VovkApp");
8
8
  const types_1 = require("./types");
9
9
  const getSchema_1 = __importDefault(require("./utils/getSchema"));
10
- // Pre-compiled regex patterns for better performance
11
- const TRIM_SLASH_REGEX = /^\/|\/$/g;
12
- const trimPath = (path) => path.trim().replace(TRIM_SLASH_REGEX, '');
13
- // Keep original class detection for compatibility with all class types
14
- const isClass = (func) => {
15
- return typeof func === 'function' && /class/.test(func.toString());
16
- };
17
- // Pre-compiled regex for kebab case
18
- const KEBAB_REGEX_1 = /([a-z0-9])([A-Z])/g;
19
- const KEBAB_REGEX_2 = /([A-Z])([A-Z])(?=[a-z])/g;
20
- const LEADING_HYPHEN = /^-/;
21
- const toKebabCase = (str) => str.replace(KEBAB_REGEX_1, '$1-$2').replace(KEBAB_REGEX_2, '$1-$2').toLowerCase().replace(LEADING_HYPHEN, '');
10
+ const trimPath = (path) => path.trim().replace(/^\/|\/$/g, '');
11
+ const isClass = (func) => typeof func === 'function' && /class/.test(func.toString());
12
+ const toKebabCase = (str) => str
13
+ .replace(/([a-z0-9])([A-Z])/g, '$1-$2') // Add hyphen between lowercase/digit and uppercase
14
+ .replace(/([A-Z])([A-Z])(?=[a-z])/g, '$1-$2') // Add hyphen between uppercase letters if the second one is followed by a lowercase
15
+ .toLowerCase()
16
+ .replace(/^-/, ''); // Remove leading hyphen
22
17
  const assignSchema = ({ controller, propertyKey, path, options, httpMethod, vovkApp, }) => {
23
18
  if (typeof window !== 'undefined') {
24
19
  throw new Error('HTTP decorators can be used on server-side only. You have probably imported a controller on the client-side.');
@@ -29,48 +24,41 @@ const assignSchema = ({ controller, propertyKey, path, options, httpMethod, vovk
29
24
  decoratorName = 'del';
30
25
  throw new Error(`Decorator must be used on a static class method. Check the controller method named "${propertyKey}" used with @${decoratorName}().`);
31
26
  }
32
- // Get or create methods object with single Map lookup
33
- const httpMethodMap = vovkApp.routes[httpMethod];
34
- let methods = httpMethodMap.get(controller);
35
- if (!methods) {
36
- httpMethodMap.set(controller, (methods = Object.create(null)));
37
- }
38
- // Handle CORS with minimal overhead
27
+ const methods = vovkApp.routes[httpMethod].get(controller) ?? {};
28
+ vovkApp.routes[httpMethod].set(controller, methods);
39
29
  if (options?.cors) {
40
- const optionsMap = vovkApp.routes.OPTIONS;
41
- let optionsMethods = optionsMap.get(controller);
42
- if (!optionsMethods) {
43
- optionsMap.set(controller, (optionsMethods = Object.create(null)));
44
- }
30
+ const optionsMethods = vovkApp.routes.OPTIONS.get(controller) ?? {};
45
31
  optionsMethods[path] = (() => { });
46
32
  optionsMethods[path]._options = options;
33
+ vovkApp.routes.OPTIONS.set(controller, optionsMethods);
47
34
  }
48
35
  const originalMethod = controller[propertyKey];
49
- // Direct property assignment without intermediate variables
50
36
  originalMethod._controller = controller;
51
- originalMethod._sourceMethod = originalMethod._sourceMethod || originalMethod;
52
- const sourceMethod = originalMethod._sourceMethod;
53
- const schema = sourceMethod._getSchema?.(controller);
54
- // Batch assign properties only if schema exists
55
- if (schema) {
56
- originalMethod.schema = schema;
57
- originalMethod.fn = sourceMethod.fn;
58
- originalMethod.models = sourceMethod.models;
59
- sourceMethod.wrapper = originalMethod;
60
- }
61
- // Use Object.assign for better performance than spread
62
- controller._handlers = controller._handlers || Object.create(null);
63
- controller._handlers[propertyKey] = Object.assign(Object.create(null), schema, controller._handlers[propertyKey], {
64
- path,
65
- httpMethod,
66
- });
37
+ originalMethod._sourceMethod = originalMethod._sourceMethod ?? originalMethod;
38
+ const schema = originalMethod._sourceMethod._getSchema?.(controller);
39
+ // TODO: Some of these assignments probably not needed anymore
40
+ originalMethod.schema = schema;
41
+ originalMethod.fn = originalMethod._sourceMethod?.fn;
42
+ originalMethod.models = originalMethod._sourceMethod?.models;
43
+ originalMethod._sourceMethod.wrapper = originalMethod;
44
+ controller._handlers = {
45
+ ...controller._handlers,
46
+ [propertyKey]: {
47
+ ...schema,
48
+ ...(controller._handlers ?? {})[propertyKey],
49
+ path,
50
+ httpMethod,
51
+ },
52
+ };
67
53
  methods[path] = originalMethod;
68
54
  methods[path]._options = options;
69
- // Only create metadata if needed
70
- if (options?.staticParams) {
71
- controller._handlersMetadata = controller._handlersMetadata || Object.create(null);
72
- controller._handlersMetadata[propertyKey] = Object.assign(Object.create(null), controller._handlersMetadata[propertyKey], { staticParams: options.staticParams });
73
- }
55
+ controller._handlersMetadata = {
56
+ ...controller._handlersMetadata,
57
+ [propertyKey]: {
58
+ ...(controller._handlersMetadata ?? {})[propertyKey],
59
+ staticParams: options?.staticParams,
60
+ },
61
+ };
74
62
  };
75
63
  function createVovkApp() {
76
64
  const vovkApp = new VovkApp_1.VovkApp();
@@ -86,40 +74,25 @@ function createVovkApp() {
86
74
  const auto = (options) => {
87
75
  function decorator(givenTarget, propertyKey) {
88
76
  const controller = givenTarget;
89
- // Single Map lookup
90
- let methods = vovkApp.routes[httpMethod].get(controller);
91
- if (!methods) {
92
- vovkApp.routes[httpMethod].set(controller, (methods = Object.create(null)));
93
- }
94
- controller._handlers = controller._handlers || Object.create(null);
95
- controller._handlers[propertyKey] = Object.assign(Object.create(null), controller._handlers[propertyKey], {
96
- httpMethod,
97
- });
98
- // Build path efficiently
99
- const validation = controller._handlers[propertyKey]?.validation;
100
- const params = validation?.params?.properties;
101
- const kebab = toKebabCase(propertyKey);
102
- let path;
103
- if (params) {
104
- const keys = Object.keys(params);
105
- if (keys.length) {
106
- // Use array join instead of template literals for better performance
107
- const paramPath = keys.map((prop) => `{${prop}}`).join('/');
108
- path = `${kebab}/${paramPath}`;
109
- }
110
- else {
111
- path = kebab;
112
- }
113
- }
114
- else {
115
- path = kebab;
116
- }
77
+ const methods = vovkApp.routes[httpMethod].get(controller) ?? {};
78
+ vovkApp.routes[httpMethod].set(controller, methods);
79
+ controller._handlers = {
80
+ ...controller._handlers,
81
+ [propertyKey]: {
82
+ ...(controller._handlers ?? {})[propertyKey],
83
+ httpMethod,
84
+ },
85
+ };
86
+ const properties = Object.keys(controller._handlers[propertyKey]?.validation?.params?.properties ?? {});
87
+ const kebab = toKebabCase(propertyKey); // 🥙
88
+ const path = properties.length ? `${kebab}/${properties.map((prop) => `{${prop}}`).join('/')}` : kebab;
117
89
  assignSchema({ controller, propertyKey, path, options, httpMethod, vovkApp });
118
90
  }
119
91
  return decorator;
120
92
  };
121
- decoratorCreator.auto = auto;
122
- return decoratorCreator;
93
+ const enhancedDecoratorCreator = decoratorCreator;
94
+ enhancedDecoratorCreator.auto = auto;
95
+ return enhancedDecoratorCreator;
123
96
  }
124
97
  const prefix = (givenPath = '') => {
125
98
  const path = trimPath(givenPath);
@@ -131,23 +104,15 @@ function createVovkApp() {
131
104
  };
132
105
  const initSegment = (options) => {
133
106
  options.segmentName = trimPath(options.segmentName ?? '');
134
- // Use for..of instead of Object.entries for better performance
135
- for (const rpcModuleName in options.controllers) {
136
- if (Object.prototype.hasOwnProperty.call(options.controllers, rpcModuleName)) {
137
- const controller = options.controllers[rpcModuleName];
138
- controller._rpcModuleName = rpcModuleName;
139
- controller._onError = options?.onError;
140
- }
107
+ for (const [rpcModuleName, controller] of Object.entries(options.controllers ?? {})) {
108
+ controller._rpcModuleName = rpcModuleName;
109
+ controller._onError = options?.onError;
141
110
  }
142
111
  async function GET_DEV(req, data) {
143
112
  const params = await data.params;
144
- // Direct access without creating intermediate array
145
- for (const key in params) {
146
- if (params[key]?.[0] === '_schema_') {
147
- const schema = await (0, getSchema_1.default)(options);
148
- return vovkApp.respond(200, { schema });
149
- }
150
- break; // Only check first param
113
+ if (params[Object.keys(params)[0]]?.[0] === '_schema_') {
114
+ const schema = await (0, getSchema_1.default)(options);
115
+ return vovkApp.respond(200, { schema });
151
116
  }
152
117
  return vovkApp.GET(req, data);
153
118
  }
package/mjs/index.d.ts CHANGED
@@ -14,7 +14,28 @@ import { createCodeSamples } from './utils/createCodeSamples';
14
14
  import { createValidateOnClient } from './utils/createValidateOnClient';
15
15
  import { resolveGeneratorConfigValues } from './utils/resolveGeneratorConfigValues';
16
16
  export { type KnownAny, type VovkRPCModule, type VovkFetcher, type VovkFetcherOptions, type VovkStreamAsyncIterable, type VovkValidateOnClient, type VovkSegmentSchema, type VovkErrorResponse, type VovkRequest, type VovkOutput, type VovkIteration, type VovkBody, type VovkQuery, type VovkParams, type VovkYieldType, type VovkReturnType, type VovkMetaSchema, type VovkControllerSchema, type VovkHandlerSchema, type VovkSchema, type VovkConfig, type VovkStrictConfig, type VovkGeneratorConfig, type VovkReadmeConfig, type VovkSamplesConfig, type VovkOpenAPIMixin, type VovkOpenAPIMixinNormalized, type VovkValidationType, type VovkLLMTool, type VovkTypedMethod, type VovkBasicJSONSchema, type VovkOperationObject, VovkSchemaIdEnum, JSONLinesResponse, HttpException, HttpStatus, HttpMethod, createVovkApp, createDecorator, createRPC, fetcher, createFetcher, generateStaticAPI, withValidationLibrary, createStandardValidation, multitenant, createLLMTools, createCodeSamples, createValidateOnClient, progressive, operation, openAPIToVovkSchema, vovkSchemaToOpenAPI, resolveGeneratorConfigValues, };
17
- export declare const get: any, post: any, put: any, patch: any, del: any, head: any, options: any, prefix: (givenPath?: string) => (givenTarget: KnownAny) => any, initSegment: (options: {
17
+ export declare const get: {
18
+ (givenPath?: string | undefined, options?: import("./types").DecoratorOptions | undefined): (givenTarget: KnownAny, propertyKey: string) => void;
19
+ auto: (options?: import("./types").DecoratorOptions) => (givenTarget: KnownAny, propertyKey: string) => void;
20
+ }, post: {
21
+ (givenPath?: string | undefined, options?: Omit<import("./types").DecoratorOptions, "staticParams"> | undefined): (givenTarget: KnownAny, propertyKey: string) => void;
22
+ auto: (options?: import("./types").DecoratorOptions) => (givenTarget: KnownAny, propertyKey: string) => void;
23
+ }, put: {
24
+ (givenPath?: string | undefined, options?: Omit<import("./types").DecoratorOptions, "staticParams"> | undefined): (givenTarget: KnownAny, propertyKey: string) => void;
25
+ auto: (options?: import("./types").DecoratorOptions) => (givenTarget: KnownAny, propertyKey: string) => void;
26
+ }, patch: {
27
+ (givenPath?: string | undefined, options?: Omit<import("./types").DecoratorOptions, "staticParams"> | undefined): (givenTarget: KnownAny, propertyKey: string) => void;
28
+ auto: (options?: import("./types").DecoratorOptions) => (givenTarget: KnownAny, propertyKey: string) => void;
29
+ }, del: {
30
+ (givenPath?: string | undefined, options?: Omit<import("./types").DecoratorOptions, "staticParams"> | undefined): (givenTarget: KnownAny, propertyKey: string) => void;
31
+ auto: (options?: import("./types").DecoratorOptions) => (givenTarget: KnownAny, propertyKey: string) => void;
32
+ }, head: {
33
+ (givenPath?: string | undefined, options?: Omit<import("./types").DecoratorOptions, "staticParams"> | undefined): (givenTarget: KnownAny, propertyKey: string) => void;
34
+ auto: (options?: import("./types").DecoratorOptions) => (givenTarget: KnownAny, propertyKey: string) => void;
35
+ }, options: {
36
+ (givenPath?: string | undefined, options?: Omit<import("./types").DecoratorOptions, "staticParams"> | undefined): (givenTarget: KnownAny, propertyKey: string) => void;
37
+ auto: (options?: import("./types").DecoratorOptions) => (givenTarget: KnownAny, propertyKey: string) => void;
38
+ }, prefix: (givenPath?: string) => (givenTarget: KnownAny) => any, initSegment: (options: {
18
39
  segmentName?: string;
19
40
  controllers: Record<string, import("./types").StaticClass>;
20
41
  exposeValidation?: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vovk",
3
- "version": "3.0.0-draft.431",
3
+ "version": "3.0.0-draft.433",
4
4
  "main": "./cjs/index.js",
5
5
  "module": "./mjs/index.js",
6
6
  "types": "./mjs/index.d.ts",