@rsdk/metadata 1.0.12 → 2.0.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/dist/index.d.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  import 'reflect-metadata';
2
+ export { RsdkMetadataProvider } from './rsdk-metadata-provider';
2
3
  export { RsdkMetadata, Resource } from './metadata';
package/dist/index.js CHANGED
@@ -1,6 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RsdkMetadata = void 0;
3
+ exports.RsdkMetadata = exports.RsdkMetadataProvider = void 0;
4
4
  require("reflect-metadata");
5
+ var rsdk_metadata_provider_1 = require("./rsdk-metadata-provider");
6
+ Object.defineProperty(exports, "RsdkMetadataProvider", { enumerable: true, get: function () { return rsdk_metadata_provider_1.RsdkMetadataProvider; } });
5
7
  var metadata_1 = require("./metadata");
6
8
  Object.defineProperty(exports, "RsdkMetadata", { enumerable: true, get: function () { return metadata_1.RsdkMetadata; } });
@@ -8,25 +8,42 @@ export type Resource<T> = {
8
8
  * Чтобы получать только значения по-определенному скоупу.
9
9
  * Никаких дополнительных проверок не происходит, используется обычный массив
10
10
  */
11
- scope: string;
11
+ scope?: string;
12
12
  value: T;
13
+ /**
14
+ * Ну, это было неизбежно...
15
+ * В чём собственно дело
16
+ * У нас есть ряд вещей которые необходимо объявить по принципу at-most-once.
17
+ * Но так как они все переиспользуемые они декларируются везде где они нужны.
18
+ * Для того чтобы высекать такие вещи в ряде случаев сделано это поле, работает просто по сравнению `===`
19
+ * Если значение с таким же скоупом уже есть, все последующие будут отброшены
20
+ */
21
+ key?: unknown;
13
22
  };
14
23
  /**
15
24
  * RSDK metadata for object
16
25
  */
17
26
  export declare class RsdkMetadata<T = unknown> {
18
- readonly target: any;
27
+ readonly target: object;
19
28
  readonly scope?: string | undefined;
29
+ private static logger;
20
30
  /**
21
31
  * @param target Target object (could be anything)
22
32
  * @param scope Just tag for organizing metadata into groups
23
33
  */
24
- constructor(target: any, scope?: string | undefined);
34
+ constructor(target: object, scope?: string | undefined);
35
+ static add<T>(target: object, value: T, scope?: string): void;
36
+ static get<T>(target: object, scope?: string): Resource<T>[] | null;
37
+ static set<T>(target: object, key: unknown, value: T, ifNotExist?: boolean): void;
38
+ static isEqual(resource: Resource<any>, definitionResource: Pick<Resource<unknown>, 'scope' | 'key'>): boolean;
39
+ static setWithScope<T>(target: object, scope: string, key: unknown, value: T, ifNotExist?: boolean): void;
25
40
  /**
26
41
  * Sets metadata for object itself
27
42
  * @param value Metadata value (could be anything)
28
43
  */
29
44
  add(value: T): void;
45
+ set(key: unknown, value: T, ifNotExist?: boolean): boolean;
46
+ getResourceByKey(key: any): Resource<T> | null;
30
47
  /**
31
48
  * Sets metadata for property
32
49
  * @param {string|symbol} propKey Property name
@@ -44,4 +61,5 @@ export declare class RsdkMetadata<T = unknown> {
44
61
  * @returns {Resource<T>} Array of resources
45
62
  */
46
63
  getForProperty(propKey: string | symbol): Resource<T>[] | null;
64
+ private getResourceByKeyFromList;
47
65
  }
package/dist/metadata.js CHANGED
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.RsdkMetadata = void 0;
4
+ const logging_1 = require("@rsdk/logging");
4
5
  const constants_1 = require("./constants");
5
6
  /**
6
7
  * RSDK metadata for object
@@ -8,6 +9,7 @@ const constants_1 = require("./constants");
8
9
  class RsdkMetadata {
9
10
  target;
10
11
  scope;
12
+ static logger = logging_1.LoggerFactory.create('RsdkMetadata');
11
13
  /**
12
14
  * @param target Target object (could be anything)
13
15
  * @param scope Just tag for organizing metadata into groups
@@ -15,6 +17,33 @@ class RsdkMetadata {
15
17
  constructor(target, scope) {
16
18
  this.target = target;
17
19
  this.scope = scope;
20
+ if (!['object', 'function'].includes(typeof target)) {
21
+ // TODO InternalException
22
+ throw new Error('target must be object or function, received: ' +
23
+ target +
24
+ 'typeof target - ' +
25
+ typeof target);
26
+ }
27
+ }
28
+ static add(target, value, scope) {
29
+ const metadata = new RsdkMetadata(target, scope);
30
+ metadata.add(value);
31
+ }
32
+ static get(target, scope) {
33
+ const metadata = new RsdkMetadata(target, scope);
34
+ return metadata.get();
35
+ }
36
+ static set(target, key, value, ifNotExist) {
37
+ new RsdkMetadata(target).set(key, value, ifNotExist);
38
+ }
39
+ static isEqual(resource, definitionResource) {
40
+ return (Object.hasOwn(resource, 'key') &&
41
+ Object.hasOwn(definitionResource, 'key') &&
42
+ resource.scope === definitionResource.scope &&
43
+ definitionResource.key === resource.key);
44
+ }
45
+ static setWithScope(target, scope, key, value, ifNotExist) {
46
+ new RsdkMetadata(target, scope).set(key, value, ifNotExist);
18
47
  }
19
48
  /**
20
49
  * Sets metadata for object itself
@@ -22,8 +51,41 @@ class RsdkMetadata {
22
51
  */
23
52
  add(value) {
24
53
  const metadata = Reflect.getMetadata(constants_1.RSDK_METADATA_KEY, this.target) ?? [];
25
- metadata.push({ scope: this.scope, value: value });
54
+ metadata.push({
55
+ ...(this.scope && { scope: this.scope }),
56
+ value: value,
57
+ });
58
+ Reflect.defineMetadata(constants_1.RSDK_METADATA_KEY, metadata, this.target);
59
+ }
60
+ set(key, value, ifNotExist) {
61
+ const metadata = Reflect.getMetadata(constants_1.RSDK_METADATA_KEY, this.target) ?? [];
62
+ const valueWithKey = this.getResourceByKeyFromList(metadata, key);
63
+ if (valueWithKey) {
64
+ if (!ifNotExist) {
65
+ // TODO InternalException
66
+ throw new Error('Value with key ' + key + ' already existed', {
67
+ cause: {
68
+ existed: valueWithKey,
69
+ received: valueWithKey,
70
+ },
71
+ });
72
+ }
73
+ return false;
74
+ }
75
+ metadata.push({
76
+ ...(this.scope && { scope: this.scope }),
77
+ value: value,
78
+ key,
79
+ });
26
80
  Reflect.defineMetadata(constants_1.RSDK_METADATA_KEY, metadata, this.target);
81
+ return true;
82
+ }
83
+ getResourceByKey(key) {
84
+ const metadata = this.get();
85
+ if (!metadata) {
86
+ return null;
87
+ }
88
+ return metadata.find((resource) => resource.key === key) ?? null;
27
89
  }
28
90
  /**
29
91
  * Sets metadata for property
@@ -64,5 +126,11 @@ class RsdkMetadata {
64
126
  }
65
127
  return resources.filter((resource) => resource.scope === this.scope);
66
128
  }
129
+ getResourceByKeyFromList(metadata, key) {
130
+ return (metadata.find((resource) => RsdkMetadata.isEqual(resource, {
131
+ key,
132
+ ...(this.scope && { scope: this.scope }),
133
+ })) ?? null);
134
+ }
67
135
  }
68
136
  exports.RsdkMetadata = RsdkMetadata;
@@ -0,0 +1,26 @@
1
+ import type { ClassProvider, DynamicModule, ExistingProvider, FactoryProvider, InjectionToken, Type, ValueProvider } from '@nestjs/common';
2
+ import type { NestModuleDefinition } from '@rsdk/common';
3
+ import type { Promisable } from 'type-fest';
4
+ import type { Resource } from './metadata';
5
+ /**
6
+ * Провайдер агрегирующий в себе ресурсы из метаданных
7
+ * По задумке должен выступать лишь в роли фасада/агрегатора который знает о структуре ресурсов и её значении
8
+ * Также он знает о том где могут быть записаны rsdk метаданные
9
+ */
10
+ export declare class RsdkMetadataProvider {
11
+ private readonly resources;
12
+ protected constructor(resources: Resource<any>[]);
13
+ static create(...rootModule: Promisable<NestModuleDefinition>[]): Promise<RsdkMetadataProvider>;
14
+ static getMetadataSource(nestDefinition: DynamicModule | Type | ClassProvider | ValueProvider | FactoryProvider | ExistingProvider): IterableIterator<InjectionToken | DynamicModule | Type | ClassProvider | ValueProvider | FactoryProvider | ExistingProvider>;
15
+ private static extractResources;
16
+ /**
17
+ * Есть ли уже этот ресурс в массиве
18
+ * Проверка осуществляется на основе `key` и `scope` у `Resource`
19
+ * @param resources
20
+ * @param definitionResource
21
+ * @private
22
+ */
23
+ private static isDuplicate;
24
+ get<T>(scope?: string): Resource<T>[];
25
+ add(...moduleDef: Promisable<NestModuleDefinition>[]): Promise<void>;
26
+ }
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RsdkMetadataProvider = void 0;
4
+ const nest_tools_1 = require("@rsdk/nest-tools");
5
+ const metadata_1 = require("./metadata");
6
+ /**
7
+ * Провайдер агрегирующий в себе ресурсы из метаданных
8
+ * По задумке должен выступать лишь в роли фасада/агрегатора который знает о структуре ресурсов и её значении
9
+ * Также он знает о том где могут быть записаны rsdk метаданные
10
+ */
11
+ class RsdkMetadataProvider {
12
+ resources;
13
+ constructor(resources) {
14
+ this.resources = resources;
15
+ }
16
+ static async create(...rootModule) {
17
+ const resources = [];
18
+ await this.extractResources(rootModule, resources);
19
+ return new RsdkMetadataProvider(resources);
20
+ }
21
+ static *getMetadataSource(nestDefinition) {
22
+ if ('useClass' in nestDefinition) {
23
+ yield nestDefinition.useClass;
24
+ }
25
+ if ('useValue' in nestDefinition) {
26
+ yield nestDefinition.useValue;
27
+ }
28
+ if ('provide' in nestDefinition) {
29
+ yield nestDefinition.provide;
30
+ }
31
+ yield nestDefinition;
32
+ }
33
+ static async extractResources(rootModule, resources) {
34
+ for await (const rootModuleElement of rootModule) {
35
+ const nestDefinitionIterator = new nest_tools_1.NestDefinitionIterator(rootModuleElement);
36
+ for await (const _nestDefinition of nestDefinitionIterator.iterate()) {
37
+ for (const value of this.getMetadataSource(_nestDefinition)) {
38
+ if (!['object', 'function'].includes(typeof value)) {
39
+ continue;
40
+ }
41
+ const definitionResources = metadata_1.RsdkMetadata.get(value);
42
+ if (!definitionResources) {
43
+ continue;
44
+ }
45
+ for (const definitionResource of definitionResources) {
46
+ const isDuplicate = this.isDuplicate(resources, definitionResource);
47
+ if (isDuplicate) {
48
+ continue;
49
+ }
50
+ resources.push(definitionResource);
51
+ }
52
+ }
53
+ }
54
+ }
55
+ }
56
+ /**
57
+ * Есть ли уже этот ресурс в массиве
58
+ * Проверка осуществляется на основе `key` и `scope` у `Resource`
59
+ * @param resources
60
+ * @param definitionResource
61
+ * @private
62
+ */
63
+ static isDuplicate(resources, definitionResource) {
64
+ return resources.some((resource) => metadata_1.RsdkMetadata.isEqual(resource, definitionResource));
65
+ }
66
+ get(scope) {
67
+ if (scope === undefined) {
68
+ return this.resources;
69
+ }
70
+ return this.resources.filter((resource) => resource.scope === scope);
71
+ }
72
+ async add(...moduleDef) {
73
+ await RsdkMetadataProvider.extractResources(moduleDef, this.resources);
74
+ }
75
+ }
76
+ exports.RsdkMetadataProvider = RsdkMetadataProvider;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rsdk/metadata",
3
- "version": "1.0.12",
3
+ "version": "2.0.0",
4
4
  "license": "Apache License 2.0",
5
5
  "description": "Rsdk stack metadata management",
6
6
  "main": "dist/index.js",
@@ -13,7 +13,10 @@
13
13
  "peerDependencies": {
14
14
  "@nestjs/common": "^9.0.0",
15
15
  "@nestjs/core": "^9.0.0",
16
+ "@rsdk/common": "^2.0.0",
17
+ "@rsdk/logging": "",
18
+ "@rsdk/nest-tools": "^2.0.0",
16
19
  "reflect-metadata": "^0.1.13"
17
20
  },
18
- "gitHead": "e2741fe798655b87946330f8db0705e0f7ba2fb2"
21
+ "gitHead": "9fe1395b8e38e1c7b9578dd5eed12e0c57a9087f"
19
22
  }