vovk 3.0.0-draft.430 → 3.0.0-draft.431

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,34 +1,13 @@
1
1
  import type { NextRequest } from 'next/server';
2
- import { type KnownAny, type DecoratorOptions, type VovkRequest, type StaticClass } from './types';
2
+ import { type KnownAny, type VovkRequest, type StaticClass } from './types';
3
3
  export declare function createVovkApp(): {
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
- };
4
+ get: any;
5
+ post: any;
6
+ put: any;
7
+ patch: any;
8
+ del: any;
9
+ head: any;
10
+ options: any;
32
11
  prefix: (givenPath?: string) => (givenTarget: KnownAny) => any;
33
12
  initSegment: (options: {
34
13
  segmentName?: string;
@@ -7,13 +7,18 @@ 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
- 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
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, '');
17
22
  const assignSchema = ({ controller, propertyKey, path, options, httpMethod, vovkApp, }) => {
18
23
  if (typeof window !== 'undefined') {
19
24
  throw new Error('HTTP decorators can be used on server-side only. You have probably imported a controller on the client-side.');
@@ -24,41 +29,48 @@ const assignSchema = ({ controller, propertyKey, path, options, httpMethod, vovk
24
29
  decoratorName = 'del';
25
30
  throw new Error(`Decorator must be used on a static class method. Check the controller method named "${propertyKey}" used with @${decoratorName}().`);
26
31
  }
27
- const methods = vovkApp.routes[httpMethod].get(controller) ?? {};
28
- vovkApp.routes[httpMethod].set(controller, methods);
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
29
39
  if (options?.cors) {
30
- const optionsMethods = vovkApp.routes.OPTIONS.get(controller) ?? {};
40
+ const optionsMap = vovkApp.routes.OPTIONS;
41
+ let optionsMethods = optionsMap.get(controller);
42
+ if (!optionsMethods) {
43
+ optionsMap.set(controller, (optionsMethods = Object.create(null)));
44
+ }
31
45
  optionsMethods[path] = (() => { });
32
46
  optionsMethods[path]._options = options;
33
- vovkApp.routes.OPTIONS.set(controller, optionsMethods);
34
47
  }
35
48
  const originalMethod = controller[propertyKey];
49
+ // Direct property assignment without intermediate variables
36
50
  originalMethod._controller = controller;
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
- };
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
+ });
53
67
  methods[path] = originalMethod;
54
68
  methods[path]._options = options;
55
- controller._handlersMetadata = {
56
- ...controller._handlersMetadata,
57
- [propertyKey]: {
58
- ...(controller._handlersMetadata ?? {})[propertyKey],
59
- staticParams: options?.staticParams,
60
- },
61
- };
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
+ }
62
74
  };
63
75
  function createVovkApp() {
64
76
  const vovkApp = new VovkApp_1.VovkApp();
@@ -74,25 +86,40 @@ function createVovkApp() {
74
86
  const auto = (options) => {
75
87
  function decorator(givenTarget, propertyKey) {
76
88
  const controller = givenTarget;
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;
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
+ }
89
117
  assignSchema({ controller, propertyKey, path, options, httpMethod, vovkApp });
90
118
  }
91
119
  return decorator;
92
120
  };
93
- const enhancedDecoratorCreator = decoratorCreator;
94
- enhancedDecoratorCreator.auto = auto;
95
- return enhancedDecoratorCreator;
121
+ decoratorCreator.auto = auto;
122
+ return decoratorCreator;
96
123
  }
97
124
  const prefix = (givenPath = '') => {
98
125
  const path = trimPath(givenPath);
@@ -104,15 +131,23 @@ function createVovkApp() {
104
131
  };
105
132
  const initSegment = (options) => {
106
133
  options.segmentName = trimPath(options.segmentName ?? '');
107
- for (const [rpcModuleName, controller] of Object.entries(options.controllers ?? {})) {
108
- controller._rpcModuleName = rpcModuleName;
109
- controller._onError = options?.onError;
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
+ }
110
141
  }
111
142
  async function GET_DEV(req, data) {
112
143
  const params = await data.params;
113
- if (params[Object.keys(params)[0]]?.[0] === '_schema_') {
114
- const schema = await (0, getSchema_1.default)(options);
115
- return vovkApp.respond(200, { schema });
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
116
151
  }
117
152
  return vovkApp.GET(req, data);
118
153
  }
package/cjs/index.d.ts CHANGED
@@ -14,28 +14,7 @@ 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: {
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: {
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: {
39
18
  segmentName?: string;
40
19
  controllers: Record<string, import("./types").StaticClass>;
41
20
  exposeValidation?: boolean;
@@ -1,34 +1,13 @@
1
1
  import type { NextRequest } from 'next/server';
2
- import { type KnownAny, type DecoratorOptions, type VovkRequest, type StaticClass } from './types';
2
+ import { type KnownAny, type VovkRequest, type StaticClass } from './types';
3
3
  export declare function createVovkApp(): {
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
- };
4
+ get: any;
5
+ post: any;
6
+ put: any;
7
+ patch: any;
8
+ del: any;
9
+ head: any;
10
+ options: any;
32
11
  prefix: (givenPath?: string) => (givenTarget: KnownAny) => any;
33
12
  initSegment: (options: {
34
13
  segmentName?: string;
@@ -7,13 +7,18 @@ 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
- 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
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, '');
17
22
  const assignSchema = ({ controller, propertyKey, path, options, httpMethod, vovkApp, }) => {
18
23
  if (typeof window !== 'undefined') {
19
24
  throw new Error('HTTP decorators can be used on server-side only. You have probably imported a controller on the client-side.');
@@ -24,41 +29,48 @@ const assignSchema = ({ controller, propertyKey, path, options, httpMethod, vovk
24
29
  decoratorName = 'del';
25
30
  throw new Error(`Decorator must be used on a static class method. Check the controller method named "${propertyKey}" used with @${decoratorName}().`);
26
31
  }
27
- const methods = vovkApp.routes[httpMethod].get(controller) ?? {};
28
- vovkApp.routes[httpMethod].set(controller, methods);
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
29
39
  if (options?.cors) {
30
- const optionsMethods = vovkApp.routes.OPTIONS.get(controller) ?? {};
40
+ const optionsMap = vovkApp.routes.OPTIONS;
41
+ let optionsMethods = optionsMap.get(controller);
42
+ if (!optionsMethods) {
43
+ optionsMap.set(controller, (optionsMethods = Object.create(null)));
44
+ }
31
45
  optionsMethods[path] = (() => { });
32
46
  optionsMethods[path]._options = options;
33
- vovkApp.routes.OPTIONS.set(controller, optionsMethods);
34
47
  }
35
48
  const originalMethod = controller[propertyKey];
49
+ // Direct property assignment without intermediate variables
36
50
  originalMethod._controller = controller;
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
- };
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
+ });
53
67
  methods[path] = originalMethod;
54
68
  methods[path]._options = options;
55
- controller._handlersMetadata = {
56
- ...controller._handlersMetadata,
57
- [propertyKey]: {
58
- ...(controller._handlersMetadata ?? {})[propertyKey],
59
- staticParams: options?.staticParams,
60
- },
61
- };
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
+ }
62
74
  };
63
75
  function createVovkApp() {
64
76
  const vovkApp = new VovkApp_1.VovkApp();
@@ -74,25 +86,40 @@ function createVovkApp() {
74
86
  const auto = (options) => {
75
87
  function decorator(givenTarget, propertyKey) {
76
88
  const controller = givenTarget;
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;
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
+ }
89
117
  assignSchema({ controller, propertyKey, path, options, httpMethod, vovkApp });
90
118
  }
91
119
  return decorator;
92
120
  };
93
- const enhancedDecoratorCreator = decoratorCreator;
94
- enhancedDecoratorCreator.auto = auto;
95
- return enhancedDecoratorCreator;
121
+ decoratorCreator.auto = auto;
122
+ return decoratorCreator;
96
123
  }
97
124
  const prefix = (givenPath = '') => {
98
125
  const path = trimPath(givenPath);
@@ -104,15 +131,23 @@ function createVovkApp() {
104
131
  };
105
132
  const initSegment = (options) => {
106
133
  options.segmentName = trimPath(options.segmentName ?? '');
107
- for (const [rpcModuleName, controller] of Object.entries(options.controllers ?? {})) {
108
- controller._rpcModuleName = rpcModuleName;
109
- controller._onError = options?.onError;
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
+ }
110
141
  }
111
142
  async function GET_DEV(req, data) {
112
143
  const params = await data.params;
113
- if (params[Object.keys(params)[0]]?.[0] === '_schema_') {
114
- const schema = await (0, getSchema_1.default)(options);
115
- return vovkApp.respond(200, { schema });
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
116
151
  }
117
152
  return vovkApp.GET(req, data);
118
153
  }
package/mjs/index.d.ts CHANGED
@@ -14,28 +14,7 @@ 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: {
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: {
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: {
39
18
  segmentName?: string;
40
19
  controllers: Record<string, import("./types").StaticClass>;
41
20
  exposeValidation?: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vovk",
3
- "version": "3.0.0-draft.430",
3
+ "version": "3.0.0-draft.431",
4
4
  "main": "./cjs/index.js",
5
5
  "module": "./mjs/index.js",
6
6
  "types": "./mjs/index.d.ts",