vovk 3.0.3 → 3.0.4

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.
@@ -0,0 +1,7 @@
1
+ import type { VovkController } from '../types/core.js';
2
+ import type { KnownAny } from '../types/utils.js';
3
+ /**
4
+ * Adapts a decorator callback to work with experimental, 2018-09, and TC39 Stage 3 decorator formats.
5
+ * The callback receives (controller, propertyKey) when the class and field/method value are available.
6
+ */
7
+ export declare function applyDecoratorAdapter(arg1: unknown, arg2: unknown, callback: (controller: VovkController, propertyKey: string) => void): KnownAny;
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Adapts a decorator callback to work with experimental, 2018-09, and TC39 Stage 3 decorator formats.
3
+ * The callback receives (controller, propertyKey) when the class and field/method value are available.
4
+ */
5
+ export function applyDecoratorAdapter(arg1, arg2, callback) {
6
+ // Experimental decorators: (target, propertyKey: string)
7
+ if (typeof arg2 === 'string') {
8
+ callback(arg1, arg2);
9
+ return;
10
+ }
11
+ // TC39 Stage 3: (value, context: { kind, name, addInitializer })
12
+ if (typeof arg2 === 'object' && arg2 !== null && 'name' in arg2) {
13
+ const ctx = arg2;
14
+ const propertyKey = String(ctx.name);
15
+ if (ctx.kind === 'field') {
16
+ return function (initialValue) {
17
+ this[propertyKey] = initialValue;
18
+ callback(this, propertyKey);
19
+ return this[propertyKey];
20
+ };
21
+ }
22
+ ctx.addInitializer(function () {
23
+ callback(this, propertyKey);
24
+ });
25
+ return;
26
+ }
27
+ // 2018-09 proposal: (descriptor: { kind, key, placement, initializer? })
28
+ if (typeof arg1 === 'object' && arg1 !== null && 'kind' in arg1 && 'key' in arg1) {
29
+ const desc = arg1;
30
+ const propertyKey = String(desc.key);
31
+ if (desc.kind === 'field') {
32
+ const origInit = desc.initializer;
33
+ return {
34
+ ...desc,
35
+ initializer() {
36
+ const value = origInit?.call(this);
37
+ this[propertyKey] = value;
38
+ callback(this, propertyKey);
39
+ return this[propertyKey];
40
+ },
41
+ };
42
+ }
43
+ return {
44
+ ...desc,
45
+ finisher(klass) {
46
+ callback(klass, propertyKey);
47
+ },
48
+ };
49
+ }
50
+ }
@@ -2,17 +2,11 @@ import type { VovkHandlerSchema, VovkController } from '../types/core.js';
2
2
  import type { VovkRequest } from '../types/request.js';
3
3
  import type { KnownAny } from '../types/utils.js';
4
4
  type Next = () => Promise<unknown>;
5
- /** Minimal shape shared by all TC39 Stage 3 decorator context objects. */
6
- type _Stage3Context = {
7
- kind: string;
8
- name: string | symbol;
9
- addInitializer: (fn: () => void) => void;
10
- };
11
5
  /**
12
6
  * Creates a custom decorator for Vovk controllers.
13
7
  * @see https://vovk.dev/decorator
14
8
  */
15
9
  export declare function createDecorator<TArgs extends unknown[], TRequest = VovkRequest>(handler: null | ((this: VovkController, req: TRequest, next: Next, ...args: TArgs) => unknown), initHandler?: (this: VovkController, ...args: TArgs) => Omit<VovkHandlerSchema, 'path' | 'httpMethod'> | ((handlerSchema: VovkHandlerSchema | null, options: {
16
10
  handlerName: string;
17
- }) => Omit<Partial<VovkHandlerSchema>, 'path' | 'httpMethod'>) | null | undefined): (...args: TArgs) => (target: KnownAny, propertyKeyOrContext: string | _Stage3Context) => void;
11
+ }) => Omit<Partial<VovkHandlerSchema>, 'path' | 'httpMethod'>) | null | undefined): (...args: TArgs) => (target: KnownAny, propertyKeyOrContext?: unknown) => KnownAny;
18
12
  export {};
@@ -1,3 +1,4 @@
1
+ import { applyDecoratorAdapter } from './applyDecoratorAdapter.js';
1
2
  /**
2
3
  * Creates a custom decorator for Vovk controllers.
3
4
  * @see https://vovk.dev/decorator
@@ -5,16 +6,7 @@
5
6
  export function createDecorator(handler, initHandler) {
6
7
  return function decoratorCreator(...args) {
7
8
  return function decorator(target, propertyKeyOrContext) {
8
- if (typeof propertyKeyOrContext === 'object' && propertyKeyOrContext !== null && 'kind' in propertyKeyOrContext) {
9
- // TC39 Stage 3 decorator — defer to addInitializer where `this` is the class
10
- const propertyKey = String(propertyKeyOrContext.name);
11
- propertyKeyOrContext.addInitializer(function () {
12
- applyDecorator(this, propertyKey);
13
- });
14
- return;
15
- }
16
- // Experimental decorator — target is the class for static members
17
- applyDecorator(target, propertyKeyOrContext);
9
+ return applyDecoratorAdapter(target, propertyKeyOrContext, applyDecorator);
18
10
  function applyDecorator(controller, propertyKey) {
19
11
  const originalMethod = controller[propertyKey];
20
12
  if (typeof originalMethod !== 'function') {
@@ -1,11 +1,5 @@
1
1
  import type { DecoratorOptions } from '../types/core.js';
2
2
  import type { KnownAny } from '../types/utils.js';
3
- /** Minimal shape shared by all TC39 Stage 3 decorator context objects. */
4
- type _Stage3Context = {
5
- kind: string;
6
- name: string | symbol;
7
- addInitializer: (fn: () => void) => void;
8
- };
9
3
  /**
10
4
  * Prefix for all routes in the controller.
11
5
  */
@@ -18,49 +12,48 @@ export declare function cloneControllerMetadata(): <T extends new (...args: Know
18
12
  * GET HTTP method decorator.
19
13
  */
20
14
  export declare const get: {
21
- (givenPath?: string | undefined, options?: DecoratorOptions | undefined): (givenTarget: unknown, propertyKeyOrContext: string | _Stage3Context) => void;
22
- auto: (options?: DecoratorOptions) => (givenTarget: unknown, propertyKeyOrContext: string | _Stage3Context) => void;
15
+ (givenPath?: string | undefined, options?: DecoratorOptions | undefined): (givenTarget: unknown, propertyKeyOrContext?: unknown) => KnownAny;
16
+ auto: (options?: DecoratorOptions) => (givenTarget: unknown, propertyKeyOrContext?: unknown) => KnownAny;
23
17
  };
24
18
  /**
25
19
  * POST HTTP method decorator.
26
20
  */
27
21
  export declare const post: {
28
- (givenPath?: string | undefined, options?: Omit<DecoratorOptions, "staticParams"> | undefined): (givenTarget: unknown, propertyKeyOrContext: string | _Stage3Context) => void;
29
- auto: (options?: DecoratorOptions) => (givenTarget: unknown, propertyKeyOrContext: string | _Stage3Context) => void;
22
+ (givenPath?: string | undefined, options?: Omit<DecoratorOptions, "staticParams"> | undefined): (givenTarget: unknown, propertyKeyOrContext?: unknown) => KnownAny;
23
+ auto: (options?: DecoratorOptions) => (givenTarget: unknown, propertyKeyOrContext?: unknown) => KnownAny;
30
24
  };
31
25
  /**
32
26
  * PUT HTTP method decorator.
33
27
  */
34
28
  export declare const put: {
35
- (givenPath?: string | undefined, options?: Omit<DecoratorOptions, "staticParams"> | undefined): (givenTarget: unknown, propertyKeyOrContext: string | _Stage3Context) => void;
36
- auto: (options?: DecoratorOptions) => (givenTarget: unknown, propertyKeyOrContext: string | _Stage3Context) => void;
29
+ (givenPath?: string | undefined, options?: Omit<DecoratorOptions, "staticParams"> | undefined): (givenTarget: unknown, propertyKeyOrContext?: unknown) => KnownAny;
30
+ auto: (options?: DecoratorOptions) => (givenTarget: unknown, propertyKeyOrContext?: unknown) => KnownAny;
37
31
  };
38
32
  /**
39
33
  * PATCH HTTP method decorator.
40
34
  */
41
35
  export declare const patch: {
42
- (givenPath?: string | undefined, options?: Omit<DecoratorOptions, "staticParams"> | undefined): (givenTarget: unknown, propertyKeyOrContext: string | _Stage3Context) => void;
43
- auto: (options?: DecoratorOptions) => (givenTarget: unknown, propertyKeyOrContext: string | _Stage3Context) => void;
36
+ (givenPath?: string | undefined, options?: Omit<DecoratorOptions, "staticParams"> | undefined): (givenTarget: unknown, propertyKeyOrContext?: unknown) => KnownAny;
37
+ auto: (options?: DecoratorOptions) => (givenTarget: unknown, propertyKeyOrContext?: unknown) => KnownAny;
44
38
  };
45
39
  /**
46
40
  * DELETE HTTP method decorator.
47
41
  */
48
42
  export declare const del: {
49
- (givenPath?: string | undefined, options?: Omit<DecoratorOptions, "staticParams"> | undefined): (givenTarget: unknown, propertyKeyOrContext: string | _Stage3Context) => void;
50
- auto: (options?: DecoratorOptions) => (givenTarget: unknown, propertyKeyOrContext: string | _Stage3Context) => void;
43
+ (givenPath?: string | undefined, options?: Omit<DecoratorOptions, "staticParams"> | undefined): (givenTarget: unknown, propertyKeyOrContext?: unknown) => KnownAny;
44
+ auto: (options?: DecoratorOptions) => (givenTarget: unknown, propertyKeyOrContext?: unknown) => KnownAny;
51
45
  };
52
46
  /**
53
47
  * HEAD HTTP method decorator.
54
48
  */
55
49
  export declare const head: {
56
- (givenPath?: string | undefined, options?: Omit<DecoratorOptions, "staticParams"> | undefined): (givenTarget: unknown, propertyKeyOrContext: string | _Stage3Context) => void;
57
- auto: (options?: DecoratorOptions) => (givenTarget: unknown, propertyKeyOrContext: string | _Stage3Context) => void;
50
+ (givenPath?: string | undefined, options?: Omit<DecoratorOptions, "staticParams"> | undefined): (givenTarget: unknown, propertyKeyOrContext?: unknown) => KnownAny;
51
+ auto: (options?: DecoratorOptions) => (givenTarget: unknown, propertyKeyOrContext?: unknown) => KnownAny;
58
52
  };
59
53
  /**
60
54
  * OPTIONS HTTP method decorator.
61
55
  */
62
56
  export declare const options: {
63
- (givenPath?: string | undefined, options?: Omit<DecoratorOptions, "staticParams"> | undefined): (givenTarget: unknown, propertyKeyOrContext: string | _Stage3Context) => void;
64
- auto: (options?: DecoratorOptions) => (givenTarget: unknown, propertyKeyOrContext: string | _Stage3Context) => void;
57
+ (givenPath?: string | undefined, options?: Omit<DecoratorOptions, "staticParams"> | undefined): (givenTarget: unknown, propertyKeyOrContext?: unknown) => KnownAny;
58
+ auto: (options?: DecoratorOptions) => (givenTarget: unknown, propertyKeyOrContext?: unknown) => KnownAny;
65
59
  };
66
- export {};
@@ -1,10 +1,9 @@
1
1
  import { vovkApp } from './vovkApp.js';
2
2
  import { trimPath } from '../utils/trimPath.js';
3
3
  import { toKebabCase } from '../utils/toKebabCase.js';
4
+ import { applyDecoratorAdapter } from './applyDecoratorAdapter.js';
4
5
  import { HttpMethod } from '../types/enums.js';
5
6
  const isClass = (func) => typeof func === 'function' && /class/.test(func.toString());
6
- /** Detects whether the second decorator argument is a TC39 Stage 3 context object. */
7
- const _isStage3 = (arg) => typeof arg === 'object' && arg !== null && 'kind' in arg;
8
7
  const assignSchema = ({ controller, propertyKey, path, options, httpMethod, }) => {
9
8
  if (typeof window !== 'undefined') {
10
9
  throw new Error('HTTP decorators can be used on server-side only. You have probably imported a controller on the client-side.');
@@ -55,42 +54,22 @@ function createHTTPDecorator(httpMethod) {
55
54
  function decoratorFactory(givenPath = '', options) {
56
55
  const path = trimPath(givenPath);
57
56
  function decorator(givenTarget, propertyKeyOrContext) {
58
- if (_isStage3(propertyKeyOrContext)) {
59
- const propertyKey = String(propertyKeyOrContext.name);
60
- propertyKeyOrContext.addInitializer(function () {
61
- assignSchema({ controller: this, propertyKey, path, options, httpMethod });
62
- });
63
- return;
64
- }
65
- const controller = givenTarget;
66
- assignSchema({ controller, propertyKey: propertyKeyOrContext, path, options, httpMethod });
57
+ return applyDecoratorAdapter(givenTarget, propertyKeyOrContext, (controller, propertyKey) => {
58
+ assignSchema({ controller, propertyKey, path, options, httpMethod });
59
+ });
67
60
  }
68
61
  return decorator;
69
62
  }
70
63
  const auto = (options) => {
71
64
  function decorator(givenTarget, propertyKeyOrContext) {
72
- if (_isStage3(propertyKeyOrContext)) {
73
- const propertyKey = String(propertyKeyOrContext.name);
74
- propertyKeyOrContext.addInitializer(function () {
75
- const controller = this;
76
- // validation is already assigned at procedure function
77
- const properties = Object.keys(controller._handlers?.[propertyKey]?.validation?.params?.properties ?? {});
78
- const kebabCasePath = toKebabCase(propertyKey);
79
- const path = properties.length
80
- ? `${kebabCasePath}/${properties.map((prop) => `{${prop}}`).join('/')}`
81
- : kebabCasePath;
82
- assignSchema({ controller, propertyKey, path, options, httpMethod });
83
- });
84
- return;
85
- }
86
- const controller = givenTarget;
87
- // validation is already assigned at procedure function
88
- const properties = Object.keys(controller._handlers?.[propertyKeyOrContext]?.validation?.params?.properties ?? {});
89
- const kebabCasePath = toKebabCase(propertyKeyOrContext);
90
- const path = properties.length
91
- ? `${kebabCasePath}/${properties.map((prop) => `{${prop}}`).join('/')}`
92
- : kebabCasePath;
93
- assignSchema({ controller, propertyKey: propertyKeyOrContext, path, options, httpMethod });
65
+ return applyDecoratorAdapter(givenTarget, propertyKeyOrContext, (controller, propertyKey) => {
66
+ const properties = Object.keys(controller._handlers?.[propertyKey]?.validation?.params?.properties ?? {});
67
+ const kebabCasePath = toKebabCase(propertyKey);
68
+ const path = properties.length
69
+ ? `${kebabCasePath}/${properties.map((prop) => `{${prop}}`).join('/')}`
70
+ : kebabCasePath;
71
+ assignSchema({ controller, propertyKey, path, options, httpMethod });
72
+ });
94
73
  }
95
74
  return decorator;
96
75
  };
@@ -1,6 +1,2 @@
1
1
  import { HttpStatus } from '../types/enums.js';
2
- export declare const error: (status: HttpStatus, message: string) => (target: import("../types/utils.js").KnownAny, propertyKeyOrContext: string | {
3
- kind: string;
4
- name: string | symbol;
5
- addInitializer: (fn: () => void) => void;
6
- }) => void;
2
+ export declare const error: (status: HttpStatus, message: string) => (target: import("../types/utils.js").KnownAny, propertyKeyOrContext?: unknown) => import("../types/utils.js").KnownAny;
@@ -1,26 +1,10 @@
1
1
  import type { VovkOperationObject } from '../types/operation.js';
2
- export declare const operationDecorator: (openAPIOperationObject?: VovkOperationObject | undefined) => (target: import("../types/utils.js").KnownAny, propertyKeyOrContext: string | {
3
- kind: string;
4
- name: string | symbol;
5
- addInitializer: (fn: () => void) => void;
6
- }) => void;
2
+ export declare const operationDecorator: (openAPIOperationObject?: VovkOperationObject | undefined) => (target: import("../types/utils.js").KnownAny, propertyKeyOrContext?: unknown) => import("../types/utils.js").KnownAny;
7
3
  /**
8
4
  * OpenAPI operation decorator to add metadata to API operations. Also includes `error` and `tool` utilities.
9
5
  * @see https://vovk.dev/openapi
10
6
  */
11
- export declare const operation: ((openAPIOperationObject?: VovkOperationObject | undefined) => (target: import("../types/utils.js").KnownAny, propertyKeyOrContext: string | {
12
- kind: string;
13
- name: string | symbol;
14
- addInitializer: (fn: () => void) => void;
15
- }) => void) & {
16
- error: (status: import("../index.js").HttpStatus, message: string) => (target: import("../types/utils.js").KnownAny, propertyKeyOrContext: string | {
17
- kind: string;
18
- name: string | symbol;
19
- addInitializer: (fn: () => void) => void;
20
- }) => void;
21
- tool: (toolOptions: import("../types/tools.js").VovkToolOptions) => (target: import("../types/utils.js").KnownAny, propertyKeyOrContext: string | {
22
- kind: string;
23
- name: string | symbol;
24
- addInitializer: (fn: () => void) => void;
25
- }) => void;
7
+ export declare const operation: ((openAPIOperationObject?: VovkOperationObject | undefined) => (target: import("../types/utils.js").KnownAny, propertyKeyOrContext?: unknown) => import("../types/utils.js").KnownAny) & {
8
+ error: (status: import("../index.js").HttpStatus, message: string) => (target: import("../types/utils.js").KnownAny, propertyKeyOrContext?: unknown) => import("../types/utils.js").KnownAny;
9
+ tool: (toolOptions: import("../types/tools.js").VovkToolOptions) => (target: import("../types/utils.js").KnownAny, propertyKeyOrContext?: unknown) => import("../types/utils.js").KnownAny;
26
10
  };
@@ -1,6 +1,2 @@
1
1
  import type { VovkToolOptions } from '../types/tools.js';
2
- export declare const tool: (toolOptions: VovkToolOptions) => (target: import("../types/utils.js").KnownAny, propertyKeyOrContext: string | {
3
- kind: string;
4
- name: string | symbol;
5
- addInitializer: (fn: () => void) => void;
6
- }) => void;
2
+ export declare const tool: (toolOptions: VovkToolOptions) => (target: import("../types/utils.js").KnownAny, propertyKeyOrContext?: unknown) => import("../types/utils.js").KnownAny;
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  ],
8
8
  "main": "./dist/index.js",
9
9
  "types": "./dist/index.d.ts",
10
- "version": "3.0.3",
10
+ "version": "3.0.4",
11
11
  "bin": {
12
12
  "vovk-cli-npx": "./bin/index.mjs"
13
13
  },