@prostojs/mate 0.3.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -19,27 +19,27 @@ npm install @prostojs/mate
19
19
  After installation, you can start using Mate to define and handle metadata in your TypeScript project. Below is an example that showcases different levels of metadata usage.
20
20
 
21
21
  ```ts
22
- import { TMateParamMeta } from '@prostojs/mate';
23
- import { Mate } from '@prostojs/mate';
22
+ import { TMateParamMeta } from '@prostojs/mate'
23
+ import { Mate } from '@prostojs/mate'
24
24
 
25
25
  // Define your metadata interfaces
26
26
  interface TClassMeta {
27
- name: string;
28
- model: string;
29
- fromParam: string;
30
- manufacturer: string;
31
- data: string[];
32
- inherit?: bolean;
27
+ name: string
28
+ model: string
29
+ fromParam: string
30
+ manufacturer: string
31
+ data: string[]
32
+ inherit?: bolean
33
33
  }
34
34
 
35
35
  interface TPropMeta<TParamMeta> {
36
- description: string;
37
- params: (TMateParamMeta & TParamMeta)[];
36
+ description: string
37
+ params: (TMateParamMeta & TParamMeta)[]
38
38
  inherit?: bolean
39
39
  }
40
40
 
41
41
  interface TParamMeta {
42
- required: boolean;
42
+ required: boolean
43
43
  }
44
44
 
45
45
  const mate = new Mate<TClassMeta, TPropMeta<TParamMeta>>('robot-meta', {
@@ -47,32 +47,32 @@ const mate = new Mate<TClassMeta, TPropMeta<TParamMeta>>('robot-meta', {
47
47
  readType: true,
48
48
  collectPropKeys: true,
49
49
  inherit(classMeta, targetMeta, level, prop) {
50
- return !!targetMeta?.inherit || !!classMeta?.inherit;
50
+ return !!targetMeta?.inherit || !!classMeta?.inherit
51
51
  },
52
- });
52
+ })
53
53
 
54
54
  // Annotate your class
55
- @mate.decorate('name', 'NXT')
56
- @mate.decorate('model', 'EV3')
55
+ @mate.decorate('name', 'NXT')
56
+ @mate.decorate('model', 'EV3')
57
57
  @mate.decorate('manufacturer', 'LEGO')
58
- @mate.decorate('data', 'NXT-0001', true)
58
+ @mate.decorate('data', 'NXT-0001', true)
59
59
  class Robot {
60
60
  @mate.decorate('description', 'Robotic arm for grabbing objects')
61
- arm: string;
61
+ arm: string
62
62
 
63
- @mate.decorate('description', 'Sensors to detect objects')
63
+ @mate.decorate('description', 'Sensors to detect objects')
64
64
  sensors(
65
- @mate.decorateClass('fromParam', 'hoised value')
66
- @mate.decorate('required', true)
67
- input: string
65
+ @mate.decorateClass('fromParam', 'hoised value')
66
+ @mate.decorate('required', true)
67
+ input: string,
68
68
  ): string {
69
- return 'Activated sensors with input: ' + input;
69
+ return 'Activated sensors with input: ' + input
70
70
  }
71
71
  }
72
72
 
73
73
  // Read the metadata
74
- let classMeta = mate.read(Robot);
75
- console.log(classMeta);
74
+ let classMeta = mate.read(Robot)
75
+ console.log(classMeta)
76
76
  // Expected Output:
77
77
  // {
78
78
  // name: 'NXT',
@@ -86,8 +86,8 @@ console.log(classMeta);
86
86
  // }
87
87
 
88
88
  // read the property metadata
89
- let armMeta = mate.read(Robot, 'arm');
90
- console.log(armMeta);
89
+ let armMeta = mate.read(Robot, 'arm')
90
+ console.log(armMeta)
91
91
  // Expected Output:
92
92
  // {
93
93
  // description: 'Robotic arm for grabbing objects',
@@ -97,8 +97,8 @@ console.log(armMeta);
97
97
  // }
98
98
 
99
99
  // read the method metadata
100
- let sensorsMeta = mate.read(Robot, 'sensors');
101
- console.log(sensorsMeta);
100
+ let sensorsMeta = mate.read(Robot, 'sensors')
101
+ console.log(sensorsMeta)
102
102
  // Expected Output:
103
103
  // {
104
104
  // description: 'Sensors to detect objects',
@@ -132,12 +132,14 @@ const mate = new Mate<MyMeta>('my-metadata-key', {
132
132
  if (prop) {
133
133
  // if it is a method metadata
134
134
  // we require a key `inherit` to be true for inheritance
135
- return !!methodMeta?.inherit || !!(classMeta?.inherit && !methodMeta)
135
+ return (
136
+ !!methodMeta?.inherit || !!(classMeta?.inherit && !methodMeta)
137
+ )
136
138
  }
137
139
  // otherwise (in case of class metadata) we require a key `inherit`
138
140
  // to be true for inheritance on class metadata
139
141
  return !!classMeta?.inherit
140
- }
142
+ },
141
143
  })
142
144
  ```
143
145
 
package/dist/index.cjs ADDED
@@ -0,0 +1,204 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ //#region src/utils/helpers.ts
4
+ function getConstructor(instance) {
5
+ return isConstructor(instance) ? instance : instance.constructor ? instance.constructor : Object.getPrototypeOf(instance).constructor;
6
+ }
7
+ function isConstructor(v) {
8
+ return typeof v === "function" && Object.getOwnPropertyDescriptor(v, "prototype") !== void 0 && Object.getOwnPropertyDescriptor(v, "caller") === void 0 && !!v.name;
9
+ }
10
+
11
+ //#endregion
12
+ //#region src/reflect.ts
13
+ let classMetadata = /* @__PURE__ */ new WeakMap();
14
+ let paramMetadata = /* @__PURE__ */ new WeakMap();
15
+ const root = typeof global === "object" ? global : typeof self === "object" ? self : {};
16
+ function getMetaObject(target, prop) {
17
+ const isParam = typeof prop !== "undefined";
18
+ const metadata = isParam ? paramMetadata : classMetadata;
19
+ const targetKey = getConstructor(target);
20
+ let meta = metadata.get(targetKey);
21
+ if (!meta) {
22
+ meta = {};
23
+ metadata.set(targetKey, meta);
24
+ }
25
+ if (isParam) meta = meta[prop] = meta[prop] || {};
26
+ return meta;
27
+ }
28
+ const _reflect = {
29
+ getOwnMetadata(key, target, prop) {
30
+ return getMetaObject(target, prop)[key];
31
+ },
32
+ defineMetadata(key, data, target, prop) {
33
+ const meta = getMetaObject(target, prop);
34
+ meta[key] = data;
35
+ },
36
+ metadata(key, data) {
37
+ return ((target, propKey) => {
38
+ Reflect$1.defineMetadata(key, data, target, propKey);
39
+ });
40
+ },
41
+ _cleanup: (() => {
42
+ classMetadata = /* @__PURE__ */ new WeakMap();
43
+ paramMetadata = /* @__PURE__ */ new WeakMap();
44
+ })
45
+ };
46
+ if (!root.Reflect) root.Reflect = _reflect;
47
+ else {
48
+ const funcs = [
49
+ "getOwnMetadata",
50
+ "defineMetadata",
51
+ "metadata"
52
+ ];
53
+ const target = root.Reflect;
54
+ for (const func of funcs) if (typeof target[func] !== "function") Object.defineProperty(target, func, {
55
+ configurable: true,
56
+ writable: true,
57
+ value: _reflect[func]
58
+ });
59
+ }
60
+ const Reflect$1 = _reflect;
61
+
62
+ //#endregion
63
+ //#region src/mate.ts
64
+ const Reflect = global?.Reflect || self?.Reflect || Reflect$1;
65
+ var Mate = class {
66
+ constructor(workspace, options = {}) {
67
+ this.workspace = workspace;
68
+ this.options = options;
69
+ this.logger = options.logger || console;
70
+ }
71
+ /**
72
+ * Cleanup function to reset metadata
73
+ *
74
+ * It is usefull in dev mode when server restarts
75
+ */
76
+ _cleanup() {
77
+ Reflect._cleanup?.call(Reflect);
78
+ this._readCache = void 0;
79
+ }
80
+ set(args, key, value, isArray) {
81
+ this._readCache = void 0;
82
+ let level = "CLASS";
83
+ const newArgs = args.level === "CLASS" ? { target: getConstructor(args.target) } : args.level === "PROP" ? {
84
+ target: args.target,
85
+ propKey: args.propKey
86
+ } : args;
87
+ let meta = Reflect.getOwnMetadata(this.workspace, newArgs.target, newArgs.propKey) || {};
88
+ if (newArgs.propKey && this.options.readReturnType && !meta.returnType && args.descriptor) meta.returnType = Reflect.getOwnMetadata("design:returntype", newArgs.target, newArgs.propKey);
89
+ if (newArgs.propKey && this.options.readType && !meta.type) meta.type = Reflect.getOwnMetadata("design:type", newArgs.target, newArgs.propKey);
90
+ const { index } = newArgs;
91
+ const cb = typeof key === "function" ? key : void 0;
92
+ let data = meta;
93
+ if (!data.params) {
94
+ const paramTypes = Reflect.getOwnMetadata("design:paramtypes", newArgs.target, newArgs.propKey);
95
+ if (paramTypes) {
96
+ data.params = new Array(paramTypes.length);
97
+ for (let i = 0; i < paramTypes.length; i++) data.params[i] = { type: paramTypes[i] };
98
+ }
99
+ }
100
+ if (typeof index === "number") {
101
+ level = "PARAM";
102
+ data.params = data.params || [];
103
+ data.params[index] = data.params[index] || { type: void 0 };
104
+ if (cb) data.params[index] = cb(data.params[index], level, args.propKey, typeof args.index === "number" ? args.index : void 0);
105
+ else data = data.params[index];
106
+ } else if (!index && !args.descriptor && args.propKey && this.options.collectPropKeys && args.level !== "CLASS") this.set({
107
+ ...args,
108
+ level: "CLASS"
109
+ }, (meta) => {
110
+ if (!meta.properties) meta.properties = [args.propKey];
111
+ else if (!meta.properties.includes(args.propKey)) meta.properties.push(args.propKey);
112
+ return meta;
113
+ });
114
+ level = typeof index === "number" ? "PARAM" : newArgs.propKey && newArgs.descriptor ? "METHOD" : newArgs.propKey ? "PROP" : "CLASS";
115
+ if (typeof key !== "function") if (isArray) {
116
+ const newArray = data[key] || [];
117
+ if (!Array.isArray(newArray))
118
+ /* istanbul ignore next line */
119
+ this.logger.error("Mate.add (isArray=true) called for non-array metadata");
120
+ newArray.unshift(value);
121
+ data[key] = newArray;
122
+ } else data[key] = value;
123
+ else if (cb && typeof index !== "number") meta = cb(data, level, args.propKey, typeof args.index === "number" ? args.index : void 0);
124
+ Reflect.defineMetadata(this.workspace, meta, newArgs.target, newArgs.propKey);
125
+ }
126
+ read(target, propKey) {
127
+ const constructor = isConstructor(target) ? target : getConstructor(target);
128
+ const proto = constructor.prototype;
129
+ const propKeyStr = propKey;
130
+ const ctorCache = this._readCache?.get(constructor);
131
+ if (ctorCache?.has(propKeyStr)) return ctorCache.get(propKeyStr);
132
+ let ownMeta = Reflect.getOwnMetadata(this.workspace, typeof propKey === "string" ? proto : constructor, propKey);
133
+ if (ownMeta && propKey === void 0 && ownMeta.params === void 0) {
134
+ const parent = Object.getPrototypeOf(constructor);
135
+ if (typeof parent === "function" && parent !== fnProto && parent !== constructor) ownMeta.params = this.read(parent)?.params;
136
+ }
137
+ if (this.options.inherit) {
138
+ const inheritFn = typeof this.options.inherit === "function" ? this.options.inherit : void 0;
139
+ let shouldInherit = this.options.inherit;
140
+ if (inheritFn) if (typeof propKey === "string") shouldInherit = inheritFn(Reflect.getOwnMetadata(this.workspace, constructor), ownMeta, "PROP", propKey);
141
+ else shouldInherit = inheritFn(ownMeta, ownMeta, "CLASS");
142
+ if (shouldInherit) {
143
+ const parent = Object.getPrototypeOf(constructor);
144
+ if (typeof parent === "function" && parent !== fnProto && parent !== constructor) {
145
+ const inheritedMeta = this.read(parent, propKey) || {};
146
+ const ownParams = ownMeta?.params;
147
+ ownMeta = {
148
+ ...inheritedMeta,
149
+ ...ownMeta
150
+ };
151
+ if (typeof propKey === "string" && ownParams && inheritedMeta?.params) {
152
+ for (let i = 0; i < ownParams.length; i++) if (typeof inheritedMeta?.params[i] !== "undefined") {
153
+ const ownParam = ownParams[i];
154
+ if (ownMeta.params && inheritFn && inheritFn(ownMeta, ownParam, "PARAM", typeof propKey === "string" ? propKey : void 0)) ownMeta.params[i] = {
155
+ ...inheritedMeta?.params[i],
156
+ ...ownParams[i]
157
+ };
158
+ }
159
+ }
160
+ }
161
+ }
162
+ }
163
+ const cache = this._readCache ??= /* @__PURE__ */ new WeakMap();
164
+ let tc = cache.get(constructor);
165
+ if (!tc) {
166
+ tc = /* @__PURE__ */ new Map();
167
+ cache.set(constructor, tc);
168
+ }
169
+ tc.set(propKeyStr, ownMeta);
170
+ return ownMeta;
171
+ }
172
+ apply(...decorators) {
173
+ return ((target, propKey, descriptor) => {
174
+ for (const d of decorators) d(target, propKey, descriptor);
175
+ });
176
+ }
177
+ decorate(key, value, isArray, level) {
178
+ return ((target, propKey, descriptor) => {
179
+ const args = {
180
+ target,
181
+ propKey,
182
+ descriptor: typeof descriptor === "number" ? void 0 : descriptor,
183
+ index: typeof descriptor === "number" ? descriptor : void 0,
184
+ level
185
+ };
186
+ this.set(args, key, value, isArray);
187
+ });
188
+ }
189
+ decorateConditional(ccb) {
190
+ return ((target, propKey, descriptor) => {
191
+ const d = ccb(typeof descriptor === "number" ? "PARAM" : propKey && descriptor ? "METHOD" : propKey ? "PROP" : "CLASS");
192
+ if (d) d(target, propKey, descriptor);
193
+ });
194
+ }
195
+ decorateClass(key, value, isArray) {
196
+ return this.decorate(key, value, isArray, "CLASS");
197
+ }
198
+ };
199
+ const fnProto = Object.getPrototypeOf(Function);
200
+
201
+ //#endregion
202
+ exports.Mate = Mate;
203
+ exports.getConstructor = getConstructor;
204
+ exports.isConstructor = isConstructor;
@@ -0,0 +1,77 @@
1
+ //#region dts-build/types.d.ts
2
+ type TAny = any;
3
+ type TObject = object;
4
+ type TFunction = Function;
5
+ type TClassConstructor<T = unknown> = new (...args: TAny[]) => T;
6
+ //#endregion
7
+ //#region dts-build/mate.d.ts
8
+ type TLevels = 'CLASS' | 'METHOD' | 'PROP' | 'PARAM';
9
+ interface TMergedDecoratorArgs {
10
+ target: TFunction | TObject;
11
+ propKey?: string;
12
+ descriptor?: TypedPropertyDescriptor<TAny>;
13
+ index?: number;
14
+ level?: TLevels;
15
+ }
16
+ interface TMateParamMeta {
17
+ type?: TFunction;
18
+ }
19
+ interface TMatePropMeta<TParam extends TObject = TEmpty> {
20
+ params?: (TParam & TMateParamMeta)[];
21
+ }
22
+ interface TMateClassMeta<TParam> {
23
+ properties?: string[];
24
+ type?: TFunction;
25
+ returnType?: TFunction;
26
+ params?: (TParam & TMateParamMeta)[];
27
+ }
28
+ type TCommonMate<TParam extends TObject> = TMateClassMeta<TParam> & TMatePropMeta<TParam>;
29
+ type TCommonMateWithParam<TParam extends TObject> = TMateClassMeta<TParam> & TMatePropMeta<TParam> & TParam;
30
+ interface TConsoleBase {
31
+ error: (...args: any) => void;
32
+ }
33
+ interface TMateOptions<TClass extends TObject = TMateClassMeta<TMateParamMeta>, TProp extends {
34
+ params: TMateParamMeta[];
35
+ } = Required<TMatePropMeta<TMateParamMeta>>> {
36
+ logger?: TConsoleBase;
37
+ readReturnType?: boolean;
38
+ readType?: boolean;
39
+ collectPropKeys?: boolean;
40
+ inherit?: boolean | ((classMeta: TClass & TMateClassMeta<TMateParamMeta>, targetMeta: (TMatePropMeta<TProp['params'][0]> & TProp) | (TMateParamMeta & TProp['params'][0]), level: 'CLASS' | 'PROP' | 'PARAM', key?: string) => boolean);
41
+ }
42
+ interface TEmpty {}
43
+ declare class Mate<TClass extends TObject = TMateClassMeta<TMateParamMeta>, TProp extends {
44
+ params: TMateParamMeta[];
45
+ } = Required<TMatePropMeta<TMateParamMeta>>> {
46
+ protected workspace: string;
47
+ protected options: TMateOptions<TClass, TProp>;
48
+ protected logger: TConsoleBase;
49
+ protected _readCache?: WeakMap<object, Map<string | undefined, unknown>>;
50
+ constructor(workspace: string, options?: TMateOptions<TClass, TProp>);
51
+ /**
52
+ * Cleanup function to reset metadata
53
+ *
54
+ * It is usefull in dev mode when server restarts
55
+ */
56
+ _cleanup(): void;
57
+ set<T = TClass & TProp & TCommonMateWithParam<TProp['params'][0]>>(args: TMergedDecoratorArgs, cb: (meta: T, level: TLevels, propKey?: string, index?: number) => T): void;
58
+ set<T = TClass & TProp & TCommonMateWithParam<TProp['params'][0]>, K extends keyof T = keyof T>(args: TMergedDecoratorArgs, key: keyof T, value: T[K]): void;
59
+ set<T = TClass & TProp & TCommonMateWithParam<TProp['params'][0]>, K extends keyof T = keyof T>(args: TMergedDecoratorArgs, key: keyof T, value: T[K], isArray: boolean | undefined): void;
60
+ read<PK>(target: TFunction | TObject, propKey?: PK): PK extends string ? (TClass & TProp & TCommonMate<TProp['params'][0]>) | undefined : TClass | undefined;
61
+ apply(...decorators: (MethodDecorator | ClassDecorator | ParameterDecorator | PropertyDecorator)[]): MethodDecorator & ClassDecorator & ParameterDecorator & PropertyDecorator;
62
+ decorate<T = TClass & TProp & TCommonMateWithParam<TProp['params'][0]>>(cb: (meta: T, level: TLevels, propKey?: string, index?: number) => T): MethodDecorator & ClassDecorator & ParameterDecorator & PropertyDecorator;
63
+ decorate<T = TClass & TProp & TCommonMateWithParam<TProp['params'][0]>, K extends keyof T = keyof T>(key: K, value: T[K]): MethodDecorator & ClassDecorator & ParameterDecorator & PropertyDecorator;
64
+ decorate<T = TClass & TProp & TCommonMateWithParam<TProp['params'][0]>, K extends keyof T = keyof T, TIsArray extends boolean = false>(key: K, value: TIsArray extends true ? ArrayElementType<T[K]> : T[K], isArray: TIsArray): MethodDecorator & ClassDecorator & ParameterDecorator & PropertyDecorator;
65
+ decorate<T = TClass & TProp & TCommonMateWithParam<TProp['params'][0]>, K extends keyof T = keyof T, TIsArray extends boolean = false>(key: K | ((meta: T, level: TLevels, propKey?: string, index?: number) => T), value: TIsArray extends true ? ArrayElementType<T[K]> : T[K], isArray: TIsArray, level: TMergedDecoratorArgs['level']): MethodDecorator & ClassDecorator & ParameterDecorator & PropertyDecorator;
66
+ decorateConditional(ccb: (level: TLevels) => (MethodDecorator & ClassDecorator & ParameterDecorator & PropertyDecorator) | void | undefined): MethodDecorator & ClassDecorator & ParameterDecorator & PropertyDecorator;
67
+ decorateClass<T = TClass>(cb: (meta: T, level: TLevels, propKey?: string, index?: number) => T): MethodDecorator & ClassDecorator & ParameterDecorator & PropertyDecorator;
68
+ decorateClass<T = TClass, K extends keyof T = keyof T, TIsArray extends boolean = false>(key: K, value: TIsArray extends true ? ArrayElementType<T[K]> : T[K]): MethodDecorator & ClassDecorator & ParameterDecorator & PropertyDecorator;
69
+ decorateClass<T = TClass, K extends keyof T = keyof T, TIsArray extends boolean = false>(key: K, value: TIsArray extends true ? ArrayElementType<T[K]> : T[K], isArray: boolean | undefined): MethodDecorator & ClassDecorator & ParameterDecorator & PropertyDecorator;
70
+ }
71
+ type ArrayElementType<T> = T extends (infer E)[] ? E : never;
72
+ //#endregion
73
+ //#region dts-build/utils/helpers.d.ts
74
+ declare function getConstructor<T = TAny>(instance: T): TFunction;
75
+ declare function isConstructor<T = TAny>(v: T): v is T & TClassConstructor;
76
+ //#endregion
77
+ export { Mate, TMateClassMeta, TMateOptions, TMateParamMeta, TMatePropMeta, TMergedDecoratorArgs, getConstructor, isConstructor };
package/dist/index.mjs ADDED
@@ -0,0 +1,200 @@
1
+ //#region src/utils/helpers.ts
2
+ function getConstructor(instance) {
3
+ return isConstructor(instance) ? instance : instance.constructor ? instance.constructor : Object.getPrototypeOf(instance).constructor;
4
+ }
5
+ function isConstructor(v) {
6
+ return typeof v === "function" && Object.getOwnPropertyDescriptor(v, "prototype") !== void 0 && Object.getOwnPropertyDescriptor(v, "caller") === void 0 && !!v.name;
7
+ }
8
+
9
+ //#endregion
10
+ //#region src/reflect.ts
11
+ let classMetadata = /* @__PURE__ */ new WeakMap();
12
+ let paramMetadata = /* @__PURE__ */ new WeakMap();
13
+ const root = typeof global === "object" ? global : typeof self === "object" ? self : {};
14
+ function getMetaObject(target, prop) {
15
+ const isParam = typeof prop !== "undefined";
16
+ const metadata = isParam ? paramMetadata : classMetadata;
17
+ const targetKey = getConstructor(target);
18
+ let meta = metadata.get(targetKey);
19
+ if (!meta) {
20
+ meta = {};
21
+ metadata.set(targetKey, meta);
22
+ }
23
+ if (isParam) meta = meta[prop] = meta[prop] || {};
24
+ return meta;
25
+ }
26
+ const _reflect = {
27
+ getOwnMetadata(key, target, prop) {
28
+ return getMetaObject(target, prop)[key];
29
+ },
30
+ defineMetadata(key, data, target, prop) {
31
+ const meta = getMetaObject(target, prop);
32
+ meta[key] = data;
33
+ },
34
+ metadata(key, data) {
35
+ return ((target, propKey) => {
36
+ Reflect$1.defineMetadata(key, data, target, propKey);
37
+ });
38
+ },
39
+ _cleanup: (() => {
40
+ classMetadata = /* @__PURE__ */ new WeakMap();
41
+ paramMetadata = /* @__PURE__ */ new WeakMap();
42
+ })
43
+ };
44
+ if (!root.Reflect) root.Reflect = _reflect;
45
+ else {
46
+ const funcs = [
47
+ "getOwnMetadata",
48
+ "defineMetadata",
49
+ "metadata"
50
+ ];
51
+ const target = root.Reflect;
52
+ for (const func of funcs) if (typeof target[func] !== "function") Object.defineProperty(target, func, {
53
+ configurable: true,
54
+ writable: true,
55
+ value: _reflect[func]
56
+ });
57
+ }
58
+ const Reflect$1 = _reflect;
59
+
60
+ //#endregion
61
+ //#region src/mate.ts
62
+ const Reflect = global?.Reflect || self?.Reflect || Reflect$1;
63
+ var Mate = class {
64
+ constructor(workspace, options = {}) {
65
+ this.workspace = workspace;
66
+ this.options = options;
67
+ this.logger = options.logger || console;
68
+ }
69
+ /**
70
+ * Cleanup function to reset metadata
71
+ *
72
+ * It is usefull in dev mode when server restarts
73
+ */
74
+ _cleanup() {
75
+ Reflect._cleanup?.call(Reflect);
76
+ this._readCache = void 0;
77
+ }
78
+ set(args, key, value, isArray) {
79
+ this._readCache = void 0;
80
+ let level = "CLASS";
81
+ const newArgs = args.level === "CLASS" ? { target: getConstructor(args.target) } : args.level === "PROP" ? {
82
+ target: args.target,
83
+ propKey: args.propKey
84
+ } : args;
85
+ let meta = Reflect.getOwnMetadata(this.workspace, newArgs.target, newArgs.propKey) || {};
86
+ if (newArgs.propKey && this.options.readReturnType && !meta.returnType && args.descriptor) meta.returnType = Reflect.getOwnMetadata("design:returntype", newArgs.target, newArgs.propKey);
87
+ if (newArgs.propKey && this.options.readType && !meta.type) meta.type = Reflect.getOwnMetadata("design:type", newArgs.target, newArgs.propKey);
88
+ const { index } = newArgs;
89
+ const cb = typeof key === "function" ? key : void 0;
90
+ let data = meta;
91
+ if (!data.params) {
92
+ const paramTypes = Reflect.getOwnMetadata("design:paramtypes", newArgs.target, newArgs.propKey);
93
+ if (paramTypes) {
94
+ data.params = new Array(paramTypes.length);
95
+ for (let i = 0; i < paramTypes.length; i++) data.params[i] = { type: paramTypes[i] };
96
+ }
97
+ }
98
+ if (typeof index === "number") {
99
+ level = "PARAM";
100
+ data.params = data.params || [];
101
+ data.params[index] = data.params[index] || { type: void 0 };
102
+ if (cb) data.params[index] = cb(data.params[index], level, args.propKey, typeof args.index === "number" ? args.index : void 0);
103
+ else data = data.params[index];
104
+ } else if (!index && !args.descriptor && args.propKey && this.options.collectPropKeys && args.level !== "CLASS") this.set({
105
+ ...args,
106
+ level: "CLASS"
107
+ }, (meta) => {
108
+ if (!meta.properties) meta.properties = [args.propKey];
109
+ else if (!meta.properties.includes(args.propKey)) meta.properties.push(args.propKey);
110
+ return meta;
111
+ });
112
+ level = typeof index === "number" ? "PARAM" : newArgs.propKey && newArgs.descriptor ? "METHOD" : newArgs.propKey ? "PROP" : "CLASS";
113
+ if (typeof key !== "function") if (isArray) {
114
+ const newArray = data[key] || [];
115
+ if (!Array.isArray(newArray))
116
+ /* istanbul ignore next line */
117
+ this.logger.error("Mate.add (isArray=true) called for non-array metadata");
118
+ newArray.unshift(value);
119
+ data[key] = newArray;
120
+ } else data[key] = value;
121
+ else if (cb && typeof index !== "number") meta = cb(data, level, args.propKey, typeof args.index === "number" ? args.index : void 0);
122
+ Reflect.defineMetadata(this.workspace, meta, newArgs.target, newArgs.propKey);
123
+ }
124
+ read(target, propKey) {
125
+ const constructor = isConstructor(target) ? target : getConstructor(target);
126
+ const proto = constructor.prototype;
127
+ const propKeyStr = propKey;
128
+ const ctorCache = this._readCache?.get(constructor);
129
+ if (ctorCache?.has(propKeyStr)) return ctorCache.get(propKeyStr);
130
+ let ownMeta = Reflect.getOwnMetadata(this.workspace, typeof propKey === "string" ? proto : constructor, propKey);
131
+ if (ownMeta && propKey === void 0 && ownMeta.params === void 0) {
132
+ const parent = Object.getPrototypeOf(constructor);
133
+ if (typeof parent === "function" && parent !== fnProto && parent !== constructor) ownMeta.params = this.read(parent)?.params;
134
+ }
135
+ if (this.options.inherit) {
136
+ const inheritFn = typeof this.options.inherit === "function" ? this.options.inherit : void 0;
137
+ let shouldInherit = this.options.inherit;
138
+ if (inheritFn) if (typeof propKey === "string") shouldInherit = inheritFn(Reflect.getOwnMetadata(this.workspace, constructor), ownMeta, "PROP", propKey);
139
+ else shouldInherit = inheritFn(ownMeta, ownMeta, "CLASS");
140
+ if (shouldInherit) {
141
+ const parent = Object.getPrototypeOf(constructor);
142
+ if (typeof parent === "function" && parent !== fnProto && parent !== constructor) {
143
+ const inheritedMeta = this.read(parent, propKey) || {};
144
+ const ownParams = ownMeta?.params;
145
+ ownMeta = {
146
+ ...inheritedMeta,
147
+ ...ownMeta
148
+ };
149
+ if (typeof propKey === "string" && ownParams && inheritedMeta?.params) {
150
+ for (let i = 0; i < ownParams.length; i++) if (typeof inheritedMeta?.params[i] !== "undefined") {
151
+ const ownParam = ownParams[i];
152
+ if (ownMeta.params && inheritFn && inheritFn(ownMeta, ownParam, "PARAM", typeof propKey === "string" ? propKey : void 0)) ownMeta.params[i] = {
153
+ ...inheritedMeta?.params[i],
154
+ ...ownParams[i]
155
+ };
156
+ }
157
+ }
158
+ }
159
+ }
160
+ }
161
+ const cache = this._readCache ??= /* @__PURE__ */ new WeakMap();
162
+ let tc = cache.get(constructor);
163
+ if (!tc) {
164
+ tc = /* @__PURE__ */ new Map();
165
+ cache.set(constructor, tc);
166
+ }
167
+ tc.set(propKeyStr, ownMeta);
168
+ return ownMeta;
169
+ }
170
+ apply(...decorators) {
171
+ return ((target, propKey, descriptor) => {
172
+ for (const d of decorators) d(target, propKey, descriptor);
173
+ });
174
+ }
175
+ decorate(key, value, isArray, level) {
176
+ return ((target, propKey, descriptor) => {
177
+ const args = {
178
+ target,
179
+ propKey,
180
+ descriptor: typeof descriptor === "number" ? void 0 : descriptor,
181
+ index: typeof descriptor === "number" ? descriptor : void 0,
182
+ level
183
+ };
184
+ this.set(args, key, value, isArray);
185
+ });
186
+ }
187
+ decorateConditional(ccb) {
188
+ return ((target, propKey, descriptor) => {
189
+ const d = ccb(typeof descriptor === "number" ? "PARAM" : propKey && descriptor ? "METHOD" : propKey ? "PROP" : "CLASS");
190
+ if (d) d(target, propKey, descriptor);
191
+ });
192
+ }
193
+ decorateClass(key, value, isArray) {
194
+ return this.decorate(key, value, isArray, "CLASS");
195
+ }
196
+ };
197
+ const fnProto = Object.getPrototypeOf(Function);
198
+
199
+ //#endregion
200
+ export { Mate, getConstructor, isConstructor };