@magek/core 0.0.1

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.
Files changed (195) hide show
  1. package/dist/authorizer.d.ts +7 -0
  2. package/dist/authorizer.js +35 -0
  3. package/dist/command-dispatcher.d.ts +8 -0
  4. package/dist/command-dispatcher.js +55 -0
  5. package/dist/core-concepts/data-migration/entities/data-migration-entity.d.ts +12 -0
  6. package/dist/core-concepts/data-migration/entities/data-migration-entity.js +37 -0
  7. package/dist/core-concepts/data-migration/events/data-migration-finished.d.ts +7 -0
  8. package/dist/core-concepts/data-migration/events/data-migration-finished.js +13 -0
  9. package/dist/core-concepts/data-migration/events/data-migration-started.d.ts +7 -0
  10. package/dist/core-concepts/data-migration/events/data-migration-started.js +13 -0
  11. package/dist/core-concepts/data-migration/events/entity-migrated.d.ts +9 -0
  12. package/dist/core-concepts/data-migration/events/entity-migrated.js +15 -0
  13. package/dist/core-concepts/touch-entity/events/entity-touched.d.ts +7 -0
  14. package/dist/core-concepts/touch-entity/events/entity-touched.js +13 -0
  15. package/dist/data-migrations.d.ts +8 -0
  16. package/dist/data-migrations.js +73 -0
  17. package/dist/decorators/command.d.ts +19 -0
  18. package/dist/decorators/command.js +47 -0
  19. package/dist/decorators/data-migration.d.ts +9 -0
  20. package/dist/decorators/data-migration.js +25 -0
  21. package/dist/decorators/entity.d.ts +32 -0
  22. package/dist/decorators/entity.js +100 -0
  23. package/dist/decorators/event-handler.d.ts +3 -0
  24. package/dist/decorators/event-handler.js +18 -0
  25. package/dist/decorators/event.d.ts +8 -0
  26. package/dist/decorators/event.js +22 -0
  27. package/dist/decorators/field-metadata-reader.d.ts +6 -0
  28. package/dist/decorators/field-metadata-reader.js +221 -0
  29. package/dist/decorators/global-error-handler.d.ts +2 -0
  30. package/dist/decorators/global-error-handler.js +15 -0
  31. package/dist/decorators/global-event-handler.d.ts +3 -0
  32. package/dist/decorators/global-event-handler.js +9 -0
  33. package/dist/decorators/health-sensor.d.ts +14 -0
  34. package/dist/decorators/health-sensor.js +38 -0
  35. package/dist/decorators/index.d.ts +16 -0
  36. package/dist/decorators/index.js +19 -0
  37. package/dist/decorators/metadata.d.ts +13 -0
  38. package/dist/decorators/metadata.js +55 -0
  39. package/dist/decorators/non-exposed.d.ts +2 -0
  40. package/dist/decorators/non-exposed.js +24 -0
  41. package/dist/decorators/notification.d.ts +35 -0
  42. package/dist/decorators/notification.js +94 -0
  43. package/dist/decorators/projects.d.ts +32 -0
  44. package/dist/decorators/projects.js +87 -0
  45. package/dist/decorators/query.d.ts +2 -0
  46. package/dist/decorators/query.js +25 -0
  47. package/dist/decorators/read-model.d.ts +39 -0
  48. package/dist/decorators/read-model.js +129 -0
  49. package/dist/decorators/role.d.ts +6 -0
  50. package/dist/decorators/role.js +15 -0
  51. package/dist/decorators/scheduled-command.d.ts +9 -0
  52. package/dist/decorators/scheduled-command.js +25 -0
  53. package/dist/decorators/schema-migration.d.ts +36 -0
  54. package/dist/decorators/schema-migration.js +146 -0
  55. package/dist/decorators/sequenced-by.d.ts +28 -0
  56. package/dist/decorators/sequenced-by.js +79 -0
  57. package/dist/decorators/stage3-utils.d.ts +6 -0
  58. package/dist/decorators/stage3-utils.js +25 -0
  59. package/dist/delete-event-dispatcher.d.ts +4 -0
  60. package/dist/delete-event-dispatcher.js +23 -0
  61. package/dist/event-dispatcher.d.ts +9 -0
  62. package/dist/event-dispatcher.js +37 -0
  63. package/dist/event-processor.d.ts +15 -0
  64. package/dist/event-processor.js +125 -0
  65. package/dist/event-search.d.ts +2 -0
  66. package/dist/event-search.js +26 -0
  67. package/dist/event-stream-consumer.d.ts +7 -0
  68. package/dist/event-stream-consumer.js +36 -0
  69. package/dist/event-stream-producer.d.ts +7 -0
  70. package/dist/event-stream-producer.js +30 -0
  71. package/dist/events-reader.d.ts +11 -0
  72. package/dist/events-reader.js +63 -0
  73. package/dist/global-error-dispatcher.d.ts +16 -0
  74. package/dist/global-error-dispatcher.js +109 -0
  75. package/dist/graphql-dispatcher.d.ts +16 -0
  76. package/dist/graphql-dispatcher.js +195 -0
  77. package/dist/importer.d.ts +14 -0
  78. package/dist/importer.js +49 -0
  79. package/dist/index.d.ts +60 -0
  80. package/dist/index.js +100 -0
  81. package/dist/injectable/index.d.ts +21 -0
  82. package/dist/injectable/index.js +2 -0
  83. package/dist/instrumentation/decorator/trace.d.ts +13 -0
  84. package/dist/instrumentation/decorator/trace.js +116 -0
  85. package/dist/instrumentation/index.d.ts +2 -0
  86. package/dist/instrumentation/index.js +5 -0
  87. package/dist/instrumentation/trace-notifier.d.ts +3 -0
  88. package/dist/instrumentation/trace-notifier.js +26 -0
  89. package/dist/magek.d.ts +42 -0
  90. package/dist/magek.js +158 -0
  91. package/dist/query-dispatcher.d.ts +8 -0
  92. package/dist/query-dispatcher.js +47 -0
  93. package/dist/read-model-schema-migrator.d.ts +14 -0
  94. package/dist/read-model-schema-migrator.js +80 -0
  95. package/dist/read-models-reader.d.ts +31 -0
  96. package/dist/read-models-reader.js +196 -0
  97. package/dist/register-handler.d.ts +11 -0
  98. package/dist/register-handler.js +95 -0
  99. package/dist/rocket-dispatcher.d.ts +6 -0
  100. package/dist/rocket-dispatcher.js +21 -0
  101. package/dist/scheduled-command-dispatcher.d.ts +12 -0
  102. package/dist/scheduled-command-dispatcher.js +54 -0
  103. package/dist/schema-migrator.d.ts +12 -0
  104. package/dist/schema-migrator.js +71 -0
  105. package/dist/sensor/health/health-indicators/database-events-health-indicator.d.ts +5 -0
  106. package/dist/sensor/health/health-indicators/database-events-health-indicator.js +26 -0
  107. package/dist/sensor/health/health-indicators/database-health-indicator.d.ts +5 -0
  108. package/dist/sensor/health/health-indicators/database-health-indicator.js +29 -0
  109. package/dist/sensor/health/health-indicators/database-read-models-health-indicator.d.ts +5 -0
  110. package/dist/sensor/health/health-indicators/database-read-models-health-indicator.js +26 -0
  111. package/dist/sensor/health/health-indicators/default-health-indicators.d.ts +5 -0
  112. package/dist/sensor/health/health-indicators/default-health-indicators.js +39 -0
  113. package/dist/sensor/health/health-indicators/function-health-indicator.d.ts +5 -0
  114. package/dist/sensor/health/health-indicators/function-health-indicator.js +30 -0
  115. package/dist/sensor/health/health-indicators/health-indicator.d.ts +5 -0
  116. package/dist/sensor/health/health-indicators/health-indicator.js +30 -0
  117. package/dist/sensor/health/health-indicators/index.d.ts +3 -0
  118. package/dist/sensor/health/health-indicators/index.js +6 -0
  119. package/dist/sensor/health/health-indicators/os-info.d.ts +14 -0
  120. package/dist/sensor/health/health-indicators/os-info.js +38 -0
  121. package/dist/sensor/health/health-indicators/rockets-health-indicator.d.ts +5 -0
  122. package/dist/sensor/health/health-indicators/rockets-health-indicator.js +57 -0
  123. package/dist/sensor/health/health-indicators/version.d.ts +2 -0
  124. package/dist/sensor/health/health-indicators/version.js +24 -0
  125. package/dist/sensor/health/health-service.d.ts +22 -0
  126. package/dist/sensor/health/health-service.js +117 -0
  127. package/dist/sensor/health/health-utils.d.ts +7 -0
  128. package/dist/sensor/health/health-utils.js +53 -0
  129. package/dist/sensor/health/index.d.ts +3 -0
  130. package/dist/sensor/health/index.js +6 -0
  131. package/dist/sensor/index.d.ts +1 -0
  132. package/dist/sensor/index.js +4 -0
  133. package/dist/services/event-store.d.ts +27 -0
  134. package/dist/services/event-store.js +260 -0
  135. package/dist/services/filter-helpers.d.ts +3 -0
  136. package/dist/services/filter-helpers.js +19 -0
  137. package/dist/services/graphql/common.d.ts +26 -0
  138. package/dist/services/graphql/common.js +53 -0
  139. package/dist/services/graphql/graphql-generator.d.ts +46 -0
  140. package/dist/services/graphql/graphql-generator.js +269 -0
  141. package/dist/services/graphql/graphql-mutation-generator.d.ts +12 -0
  142. package/dist/services/graphql/graphql-mutation-generator.js +25 -0
  143. package/dist/services/graphql/graphql-query-generator.d.ts +22 -0
  144. package/dist/services/graphql/graphql-query-generator.js +39 -0
  145. package/dist/services/graphql/graphql-subcriptions-generator.d.ts +17 -0
  146. package/dist/services/graphql/graphql-subcriptions-generator.js +60 -0
  147. package/dist/services/graphql/graphql-type-informer.d.ts +23 -0
  148. package/dist/services/graphql/graphql-type-informer.js +160 -0
  149. package/dist/services/graphql/query-generators/graphql-query-by-keys-generator.d.ts +14 -0
  150. package/dist/services/graphql/query-generators/graphql-query-by-keys-generator.js +48 -0
  151. package/dist/services/graphql/query-generators/graphql-query-events-generator.d.ts +11 -0
  152. package/dist/services/graphql/query-generators/graphql-query-events-generator.js +68 -0
  153. package/dist/services/graphql/query-generators/graphql-query-filters-generator.d.ts +14 -0
  154. package/dist/services/graphql/query-generators/graphql-query-filters-generator.js +31 -0
  155. package/dist/services/graphql/query-generators/graphql-query-generator.d.ts +12 -0
  156. package/dist/services/graphql/query-generators/graphql-query-generator.js +17 -0
  157. package/dist/services/graphql/query-generators/graphql-query-listed-generator.d.ts +16 -0
  158. package/dist/services/graphql/query-generators/graphql-query-listed-generator.js +65 -0
  159. package/dist/services/graphql/query-helpers/graphql-handled-fields-generator.d.ts +15 -0
  160. package/dist/services/graphql/query-helpers/graphql-handled-fields-generator.js +65 -0
  161. package/dist/services/graphql/query-helpers/graphql-query-filter-arguments-builder.d.ts +13 -0
  162. package/dist/services/graphql/query-helpers/graphql-query-filter-arguments-builder.js +169 -0
  163. package/dist/services/graphql/query-helpers/graphql-query-filter-fields-builder.d.ts +11 -0
  164. package/dist/services/graphql/query-helpers/graphql-query-filter-fields-builder.js +28 -0
  165. package/dist/services/graphql/query-helpers/graphql-query-sort-builder.d.ts +12 -0
  166. package/dist/services/graphql/query-helpers/graphql-query-sort-builder.js +61 -0
  167. package/dist/services/graphql/websocket-protocol/graphql-websocket-protocol.d.ts +20 -0
  168. package/dist/services/graphql/websocket-protocol/graphql-websocket-protocol.js +127 -0
  169. package/dist/services/pub-sub/noop-read-model-pub-sub.d.ts +5 -0
  170. package/dist/services/pub-sub/noop-read-model-pub-sub.js +10 -0
  171. package/dist/services/pub-sub/read-model-pub-sub.d.ts +9 -0
  172. package/dist/services/pub-sub/read-model-pub-sub.js +112 -0
  173. package/dist/services/raw-events-parser.d.ts +5 -0
  174. package/dist/services/raw-events-parser.js +44 -0
  175. package/dist/services/read-model-searcher.d.ts +2 -0
  176. package/dist/services/read-model-searcher.js +11 -0
  177. package/dist/services/read-model-store.d.ts +41 -0
  178. package/dist/services/read-model-store.js +295 -0
  179. package/dist/services/token-verifiers/index.d.ts +4 -0
  180. package/dist/services/token-verifiers/index.js +7 -0
  181. package/dist/services/token-verifiers/jwks-uri-token-verifier.d.ts +21 -0
  182. package/dist/services/token-verifiers/jwks-uri-token-verifier.js +23 -0
  183. package/dist/services/token-verifiers/public-key-token-verifier.d.ts +13 -0
  184. package/dist/services/token-verifiers/public-key-token-verifier.js +19 -0
  185. package/dist/services/token-verifiers/role-based-token-verifier.d.ts +8 -0
  186. package/dist/services/token-verifiers/role-based-token-verifier.js +35 -0
  187. package/dist/services/token-verifiers/utilities.d.ts +31 -0
  188. package/dist/services/token-verifiers/utilities.js +70 -0
  189. package/dist/subscribers-notifier.d.ts +14 -0
  190. package/dist/subscribers-notifier.js +109 -0
  191. package/dist/token-verifier.d.ts +11 -0
  192. package/dist/token-verifier.js +46 -0
  193. package/dist/touch-entity-handler.d.ts +4 -0
  194. package/dist/touch-entity-handler.js +16 -0
  195. package/package.json +71 -0
@@ -0,0 +1,117 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MagekHealthService = void 0;
4
+ const common_1 = require("@magek/common");
5
+ const health_utils_1 = require("./health-utils");
6
+ const health_indicators_1 = require("./health-indicators");
7
+ const token_verifier_1 = require("../../token-verifier");
8
+ const authorizer_1 = require("../../authorizer");
9
+ /**
10
+ * This class is in charge of handling the health check requests
11
+ * and dispatching the health checks to the corresponding health indicators
12
+ */
13
+ class MagekHealthService {
14
+ constructor(config) {
15
+ this.config = config;
16
+ }
17
+ async health(request) {
18
+ try {
19
+ const healthEnvelope = this.config.provider.sensor.rawRequestToHealthEnvelope(request);
20
+ await this.validate(healthEnvelope);
21
+ const healthProviders = this.getHealthProviders();
22
+ const parents = this.parentsHealthProviders(healthEnvelope, healthProviders);
23
+ const healthIndicatorResults = await this.healthProviderResolver(parents, healthProviders);
24
+ // Check if all components are healthy
25
+ const isHealthy = this.isOverallHealthy(healthIndicatorResults);
26
+ // Use the new health specific response handler
27
+ return await this.config.provider.api.healthRequestResult(healthIndicatorResults, isHealthy);
28
+ }
29
+ catch (e) {
30
+ return await this.config.provider.api.requestFailed(e);
31
+ }
32
+ }
33
+ async validate(healthEnvelope) {
34
+ const userEnvelope = await this.verify(healthEnvelope);
35
+ const authorizer = authorizer_1.MagekAuthorizer.build(this.config.sensorConfiguration.health.globalAuthorizer);
36
+ await authorizer(userEnvelope, healthEnvelope);
37
+ }
38
+ async healthProviderResolver(healthIndicatorsMetadata, healthProviders) {
39
+ const result = [];
40
+ for (const current of healthIndicatorsMetadata) {
41
+ const indicatorResult = await this.enabledIndicatorHealth(current, healthProviders);
42
+ if (!indicatorResult) {
43
+ continue;
44
+ }
45
+ const children = (0, health_utils_1.childHealthProviders)(current, healthProviders);
46
+ // Check if the result is already a HealthIndicatorsResult (has name and id)
47
+ const isHealthIndicatorsResult = 'name' in indicatorResult && 'id' in indicatorResult;
48
+ const newResult = {
49
+ ...indicatorResult,
50
+ name: isHealthIndicatorsResult
51
+ ? indicatorResult.name
52
+ : current.healthIndicatorConfiguration.name,
53
+ id: current.healthIndicatorConfiguration.id,
54
+ };
55
+ if (children && (children === null || children === void 0 ? void 0 : children.length) > 0) {
56
+ newResult.components = await this.healthProviderResolver(children, healthProviders);
57
+ }
58
+ result.push(newResult);
59
+ }
60
+ return result;
61
+ }
62
+ async enabledIndicatorHealth(current, healthProviders) {
63
+ if ((0, health_utils_1.isEnabled)(current, healthProviders)) {
64
+ return await this.indicatorHealth(current);
65
+ }
66
+ return;
67
+ }
68
+ async indicatorHealth(metadata) {
69
+ const rootClass = metadata.class;
70
+ const instance = (0, common_1.createInstance)(rootClass, {});
71
+ const healthIndicatorResult = await instance.health(this.config, metadata);
72
+ if (!metadata.healthIndicatorConfiguration.details) {
73
+ healthIndicatorResult.details = undefined;
74
+ }
75
+ return healthIndicatorResult;
76
+ }
77
+ /**
78
+ * If there is not any indicator configured, then we will use only the Magek indicators.
79
+ * @private
80
+ */
81
+ getHealthProviders() {
82
+ return Object.keys(this.config.userHealthIndicators).length !== 0
83
+ ? this.config.userHealthIndicators
84
+ : (0, health_indicators_1.defaultMagekHealthIndicators)(this.config);
85
+ }
86
+ parentsHealthProviders(envelope, healthProviders) {
87
+ const componentPath = envelope.componentPath;
88
+ if (!componentPath || componentPath.length === 0) {
89
+ return (0, health_utils_1.rootHealthProviders)(healthProviders);
90
+ }
91
+ return [(0, health_utils_1.metadataFromId)(healthProviders, componentPath)];
92
+ }
93
+ async verify(envelope) {
94
+ const tokenVerifier = new token_verifier_1.MagekTokenVerifier(this.config);
95
+ const token = envelope.token;
96
+ if (!token) {
97
+ return;
98
+ }
99
+ return await tokenVerifier.verify(token);
100
+ }
101
+ isOverallHealthy(results) {
102
+ for (const result of results) {
103
+ // Check current component's status
104
+ if (result.status !== common_1.HealthStatus.UP) {
105
+ return false;
106
+ }
107
+ // Recursively check child components if they exist
108
+ if (result.components && result.components.length > 0) {
109
+ if (!this.isOverallHealthy(result.components)) {
110
+ return false;
111
+ }
112
+ }
113
+ }
114
+ return true;
115
+ }
116
+ }
117
+ exports.MagekHealthService = MagekHealthService;
@@ -0,0 +1,7 @@
1
+ import { HealthIndicatorMetadata } from '@magek/common';
2
+ export declare function metadataFromId(healthProviders: Record<string, HealthIndicatorMetadata>, id: string): HealthIndicatorMetadata;
3
+ export declare function parentId(healthProvider: HealthIndicatorMetadata): string;
4
+ export declare function rootHealthProviders(healthProviders: Record<string, HealthIndicatorMetadata>): Array<HealthIndicatorMetadata>;
5
+ export declare function childHealthProviders(healthIndicatorMetadata: HealthIndicatorMetadata, healthProviders: Record<string, HealthIndicatorMetadata>): Array<HealthIndicatorMetadata>;
6
+ export declare function isEnabled(mainIndicatorMetadata: HealthIndicatorMetadata, healthProviders: Record<string, HealthIndicatorMetadata>): boolean;
7
+ export declare function showChildren(mainIndicatorMetadata: HealthIndicatorMetadata, healthProviders: Record<string, HealthIndicatorMetadata>): boolean;
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.metadataFromId = metadataFromId;
4
+ exports.parentId = parentId;
5
+ exports.rootHealthProviders = rootHealthProviders;
6
+ exports.childHealthProviders = childHealthProviders;
7
+ exports.isEnabled = isEnabled;
8
+ exports.showChildren = showChildren;
9
+ const PATH_SEPARATOR = '/';
10
+ function metadataFromId(healthProviders, id) {
11
+ const healthProvider = healthProviders[id];
12
+ if (!healthProvider) {
13
+ throw new Error(`Unexpected HealthProvider id ${id}`);
14
+ }
15
+ return healthProvider;
16
+ }
17
+ function parentId(healthProvider) {
18
+ const childId = healthProvider.healthIndicatorConfiguration.id;
19
+ const childPath = childId.split(PATH_SEPARATOR);
20
+ return childPath.slice(0, -1).join(PATH_SEPARATOR);
21
+ }
22
+ function rootHealthProviders(healthProviders) {
23
+ return Object.values(healthProviders).filter((healthProvider) => healthProvider.healthIndicatorConfiguration.id.split(PATH_SEPARATOR).length === 1);
24
+ }
25
+ function childHealthProviders(healthIndicatorMetadata, healthProviders) {
26
+ if (!showChildren(healthIndicatorMetadata, healthProviders)) {
27
+ return [];
28
+ }
29
+ const currentParentId = healthIndicatorMetadata.healthIndicatorConfiguration.id;
30
+ return Object.values(healthProviders).filter((healthProvider) => {
31
+ return parentId(healthProvider) === currentParentId;
32
+ });
33
+ }
34
+ function isEnabled(mainIndicatorMetadata, healthProviders) {
35
+ if (!mainIndicatorMetadata.healthIndicatorConfiguration.enabled) {
36
+ return false;
37
+ }
38
+ const parent = healthProviders[parentId(mainIndicatorMetadata)];
39
+ if (!parent) {
40
+ return true;
41
+ }
42
+ return isEnabled(parent, healthProviders);
43
+ }
44
+ function showChildren(mainIndicatorMetadata, healthProviders) {
45
+ if (!mainIndicatorMetadata.healthIndicatorConfiguration.showChildren) {
46
+ return false;
47
+ }
48
+ const parent = healthProviders[parentId(mainIndicatorMetadata)];
49
+ if (!parent) {
50
+ return true;
51
+ }
52
+ return showChildren(parent, healthProviders);
53
+ }
@@ -0,0 +1,3 @@
1
+ export * from '../../decorators/health-sensor';
2
+ export * from './health-indicators/index';
3
+ export * from './health-service';
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ tslib_1.__exportStar(require("../../decorators/health-sensor"), exports);
5
+ tslib_1.__exportStar(require("./health-indicators/index"), exports);
6
+ tslib_1.__exportStar(require("./health-service"), exports);
@@ -0,0 +1 @@
1
+ export * from './health/index';
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ tslib_1.__exportStar(require("./health/index"), exports);
@@ -0,0 +1,27 @@
1
+ import { MagekConfig, EntitySnapshotEnvelope, EventEnvelope, UUID } from '@magek/common';
2
+ export declare class EventStore {
3
+ readonly config: MagekConfig;
4
+ constructor(config: MagekConfig);
5
+ /**
6
+ * Will fetch the latest snapshot for an entity by applying a reduction
7
+ * since the time of creation of the last snapshot or from the origin of time
8
+ * if no snapshot is found.
9
+ *
10
+ * Also, in order to make next calls faster, this method caches the newly calculated
11
+ * snapshot storing it at the end of the process.
12
+ */
13
+ fetchEntitySnapshot(entityName: string, entityID: UUID): Promise<EntitySnapshotEnvelope | undefined>;
14
+ storeDispatchedEvent(eventEnvelope: EventEnvelope): Promise<boolean | undefined>;
15
+ private storeSnapshot;
16
+ private loadLatestSnapshot;
17
+ private loadEventStreamSince;
18
+ private entityReducer;
19
+ private shouldReduceMagekSuperKind;
20
+ private eventMetadataFor;
21
+ private createNewSnapshot;
22
+ private reduceSuperKind;
23
+ private reduceEntityMigrated;
24
+ private reduceEntityTouched;
25
+ private toMagekEntitySnapshot;
26
+ private reducerForEvent;
27
+ }
@@ -0,0 +1,260 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EventStore = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const common_1 = require("@magek/common");
6
+ const global_error_dispatcher_1 = require("../global-error-dispatcher");
7
+ const schema_migrator_1 = require("../schema-migrator");
8
+ const entity_migrated_1 = require("../core-concepts/data-migration/events/entity-migrated");
9
+ const entity_touched_1 = require("../core-concepts/touch-entity/events/entity-touched");
10
+ const instrumentation_1 = require("../instrumentation");
11
+ const originOfTime = new Date(0).toISOString(); // Unix epoch
12
+ const reducibleEventsTypesNames = [entity_migrated_1.MagekEntityMigrated.name, entity_touched_1.MagekEntityTouched.name];
13
+ class EventStore {
14
+ constructor(config) {
15
+ this.config = config;
16
+ }
17
+ /**
18
+ * Will fetch the latest snapshot for an entity by applying a reduction
19
+ * since the time of creation of the last snapshot or from the origin of time
20
+ * if no snapshot is found.
21
+ *
22
+ * Also, in order to make next calls faster, this method caches the newly calculated
23
+ * snapshot storing it at the end of the process.
24
+ */
25
+ async fetchEntitySnapshot(entityName, entityID) {
26
+ var _a;
27
+ const logger = (0, common_1.getLogger)(this.config, 'EventStore#fetchEntitySnapshot');
28
+ logger.debug(`Fetching snapshot for entity ${entityName} with ID ${entityID}`);
29
+ const latestSnapshotEnvelope = await this.loadLatestSnapshot(entityName, entityID);
30
+ const lastVisitedTime = (_a = latestSnapshotEnvelope === null || latestSnapshotEnvelope === void 0 ? void 0 : latestSnapshotEnvelope.snapshottedEventCreatedAt) !== null && _a !== void 0 ? _a : originOfTime;
31
+ const pendingEvents = await this.loadEventStreamSince(entityName, entityID, lastVisitedTime);
32
+ if (pendingEvents.length <= 0) {
33
+ return latestSnapshotEnvelope;
34
+ }
35
+ else {
36
+ logger.debug(`Looking for the reducer for entity ${entityName} with ID ${entityID}`);
37
+ // In this assignment we discard the `createdAt` field because it's not needed in the reduction process
38
+ let newEntitySnapshot = latestSnapshotEnvelope;
39
+ for (const pendingEvent of pendingEvents) {
40
+ // We double-check that what we are reducing is an event
41
+ if (pendingEvent.kind === 'event') {
42
+ try {
43
+ newEntitySnapshot = await this.entityReducer(pendingEvent, newEntitySnapshot);
44
+ }
45
+ catch (e) {
46
+ if (e instanceof common_1.InvalidEventError) {
47
+ const globalErrorDispatcher = new global_error_dispatcher_1.MagekGlobalErrorDispatcher(this.config);
48
+ const error = await globalErrorDispatcher.dispatch(new common_1.EventGlobalError(pendingEvent, e));
49
+ if (error)
50
+ throw error;
51
+ continue;
52
+ }
53
+ else if (e instanceof common_1.InvalidReducerError) {
54
+ const globalErrorDispatcher = new global_error_dispatcher_1.MagekGlobalErrorDispatcher(this.config);
55
+ const reducerMetadata = this.config.reducers[pendingEvent.typeName];
56
+ const error = await globalErrorDispatcher.dispatch(new common_1.ReducerGlobalError(pendingEvent, e.eventInstance, e.snapshotInstance, reducerMetadata, e));
57
+ if (error)
58
+ throw error;
59
+ continue;
60
+ }
61
+ throw e;
62
+ }
63
+ }
64
+ }
65
+ if (!newEntitySnapshot) {
66
+ logger.debug('No snapshot was found or reduced, returning');
67
+ return newEntitySnapshot;
68
+ }
69
+ if (newEntitySnapshot.entityID !== entityID) {
70
+ logger.debug(`Migrated entity ${entityName} with previous ID ${entityID} to ${newEntitySnapshot === null || newEntitySnapshot === void 0 ? void 0 : newEntitySnapshot.typeName} with the new ID ${newEntitySnapshot === null || newEntitySnapshot === void 0 ? void 0 : newEntitySnapshot.entityID}`, newEntitySnapshot);
71
+ }
72
+ else {
73
+ logger.debug(`Reduced new snapshot for entity ${entityName} with ID ${entityID}: `, newEntitySnapshot);
74
+ }
75
+ return await this.storeSnapshot(newEntitySnapshot);
76
+ }
77
+ }
78
+ async storeDispatchedEvent(eventEnvelope) {
79
+ const logger = (0, common_1.getLogger)(this.config, 'EventStore#storeDispatchedEvent');
80
+ try {
81
+ logger.debug('Storing event in the dispatched event store:', eventEnvelope);
82
+ return await this.config.eventStore.storeDispatched(eventEnvelope, this.config);
83
+ }
84
+ catch (e) {
85
+ logger.debug('Could not store dispatched event. Continue its processing.', { error: e, eventEnvelope });
86
+ return true;
87
+ }
88
+ }
89
+ async storeSnapshot(snapshot) {
90
+ const logger = (0, common_1.getLogger)(this.config, 'EventStore#storeSnapshot');
91
+ try {
92
+ logger.debug('Storing snapshot in the event store:', snapshot);
93
+ return await this.config.eventStore.storeSnapshot(snapshot, this.config);
94
+ }
95
+ catch (e) {
96
+ logger.error(`The snapshot for entity ${snapshot.typeName} with ID ${snapshot.entityID} couldn't be stored (Tried on ${new Date()})`, snapshot, '\nError:', e);
97
+ return;
98
+ }
99
+ }
100
+ async loadLatestSnapshot(entityName, entityID) {
101
+ const logger = (0, common_1.getLogger)(this.config, 'EventStore#loadLatestSnapshot');
102
+ logger.debug(`Loading latest snapshot for entity ${entityName} and ID ${entityID}`);
103
+ const latestSnapshot = await this.config.eventStore.latestEntitySnapshot(this.config, entityName, entityID);
104
+ if (latestSnapshot) {
105
+ return new schema_migrator_1.SchemaMigrator(this.config).migrate(latestSnapshot);
106
+ }
107
+ return undefined;
108
+ }
109
+ async loadEventStreamSince(entityTypeName, entityID, timestamp) {
110
+ const logger = (0, common_1.getLogger)(this.config, 'EventStore#loadEventStreamSince');
111
+ logger.debug(`Loading list of pending events for entity ${entityTypeName} with ID ${entityID} since ${timestamp}`);
112
+ return this.config.eventStore.forEntitySince(this.config, entityTypeName, entityID, timestamp);
113
+ }
114
+ async entityReducer(eventEnvelope, latestSnapshot) {
115
+ const logger = (0, common_1.getLogger)(this.config, 'entityReducer');
116
+ logger.debug('Calling reducer with event: ', eventEnvelope, ' and entity snapshot ', latestSnapshot);
117
+ if (this.shouldReduceMagekSuperKind(eventEnvelope)) {
118
+ return this.reduceSuperKind(eventEnvelope, latestSnapshot);
119
+ }
120
+ const eventMetadata = this.eventMetadataFor(eventEnvelope);
121
+ const migratedEventEnvelope = await new schema_migrator_1.SchemaMigrator(this.config).migrate(eventEnvelope);
122
+ const eventInstance = (0, common_1.createInstance)(eventMetadata.class, migratedEventEnvelope.value);
123
+ const entityMetadata = this.config.entities[migratedEventEnvelope.entityTypeName];
124
+ const reducerMetadata = this.config.reducers[eventEnvelope.typeName];
125
+ const snapshotInstance = latestSnapshot ? (0, common_1.createInstance)(entityMetadata.class, latestSnapshot.value) : null;
126
+ return this.createNewSnapshot(migratedEventEnvelope, eventInstance, snapshotInstance, eventEnvelope, reducerMetadata);
127
+ }
128
+ shouldReduceMagekSuperKind(eventEnvelope) {
129
+ const reducible = reducibleEventsTypesNames.includes(eventEnvelope.typeName);
130
+ return eventEnvelope.superKind && eventEnvelope.superKind === common_1.MAGEK_SUPER_KIND && reducible;
131
+ }
132
+ eventMetadataFor(eventEnvelope) {
133
+ const logger = (0, common_1.getLogger)(this.config, 'eventMetadataFor');
134
+ const eventMetadata = this.config.events[eventEnvelope.typeName];
135
+ if (!eventMetadata) {
136
+ logger.error(`No event registered for event ${eventEnvelope.typeName}`);
137
+ throw new common_1.InvalidEventError(`No event registered for event ${eventEnvelope.typeName}`);
138
+ }
139
+ return eventMetadata;
140
+ }
141
+ async createNewSnapshot(migratedEventEnvelope, eventInstance, snapshotInstance, eventEnvelope, reducerMetadata) {
142
+ const logger = (0, common_1.getLogger)(this.config, 'createNewSnapshot');
143
+ try {
144
+ const newEntity = this.reducerForEvent(migratedEventEnvelope.typeName, eventInstance, snapshotInstance)(eventInstance, snapshotInstance);
145
+ const newSnapshot = {
146
+ version: this.config.currentVersionFor(eventEnvelope.entityTypeName),
147
+ kind: 'snapshot',
148
+ superKind: migratedEventEnvelope.superKind,
149
+ requestID: migratedEventEnvelope.requestID,
150
+ entityID: migratedEventEnvelope.entityID,
151
+ entityTypeName: migratedEventEnvelope.entityTypeName,
152
+ typeName: migratedEventEnvelope.entityTypeName,
153
+ value: newEntity,
154
+ snapshottedEventCreatedAt: migratedEventEnvelope.createdAt,
155
+ };
156
+ logger.debug('Reducer result: ', newSnapshot);
157
+ return newSnapshot;
158
+ }
159
+ catch (e) {
160
+ const globalErrorDispatcher = new global_error_dispatcher_1.MagekGlobalErrorDispatcher(this.config);
161
+ throw await globalErrorDispatcher.dispatch(new common_1.ReducerGlobalError(migratedEventEnvelope, eventInstance, snapshotInstance, reducerMetadata, e));
162
+ }
163
+ }
164
+ async reduceSuperKind(eventEnvelope, latestSnapshot) {
165
+ if (eventEnvelope.typeName === entity_touched_1.MagekEntityTouched.name) {
166
+ return this.reduceEntityTouched(eventEnvelope, latestSnapshot);
167
+ }
168
+ if (eventEnvelope.typeName === entity_migrated_1.MagekEntityMigrated.name) {
169
+ return this.reduceEntityMigrated(eventEnvelope);
170
+ }
171
+ throw new common_1.InvalidParameterError(`Unexpected super kind ${eventEnvelope.superKind} to be reduced`);
172
+ }
173
+ reduceEntityMigrated(eventEnvelope) {
174
+ const event = eventEnvelope.value;
175
+ return this.toMagekEntitySnapshot(eventEnvelope, event.newEntity, event.newEntityName);
176
+ }
177
+ reduceEntityTouched(eventEnvelope, latestSnapshot) {
178
+ const logger = (0, common_1.getLogger)(this.config, 'EventStore#reduceEntityTouched');
179
+ logger.debug('Reducing ', eventEnvelope, ' with latestSnapshot');
180
+ if (!latestSnapshot) {
181
+ logger.debug('Latest snapshot not found, returning');
182
+ return;
183
+ }
184
+ const event = eventEnvelope.value;
185
+ const entityMetadata = this.config.entities[event.entityName];
186
+ const snapshotInstance = (0, common_1.createInstance)(entityMetadata.class, latestSnapshot.value);
187
+ return this.toMagekEntitySnapshot(eventEnvelope, snapshotInstance, event.entityName);
188
+ }
189
+ toMagekEntitySnapshot(eventEnvelope, entity, className) {
190
+ const logger = (0, common_1.getLogger)(this.config, 'EventStore#toMagekEntitySnapshot');
191
+ const migratedSnapshot = {
192
+ version: this.config.currentVersionFor(className),
193
+ kind: 'snapshot',
194
+ superKind: eventEnvelope.superKind,
195
+ requestID: eventEnvelope.requestID,
196
+ entityID: entity.id,
197
+ entityTypeName: className,
198
+ typeName: className,
199
+ value: entity,
200
+ snapshottedEventCreatedAt: eventEnvelope.createdAt,
201
+ };
202
+ logger.debug('MagekEntitySnapshot result: ', migratedSnapshot);
203
+ return migratedSnapshot;
204
+ }
205
+ reducerForEvent(eventName, eventInstance, snapshotInstance) {
206
+ const logger = (0, common_1.getLogger)(this.config, 'EventStore#reducerForEvent');
207
+ const reducerMetadata = this.config.reducers[eventName];
208
+ if (!reducerMetadata) {
209
+ throw new common_1.InvalidReducerError(`No reducer registered for event ${eventName}`, eventInstance, snapshotInstance);
210
+ }
211
+ else {
212
+ try {
213
+ const methodName = reducerMetadata.methodName;
214
+ const reducer = reducerMetadata.class[methodName];
215
+ logger.debug(`Found reducer for event ${eventName}: "${reducerMetadata.class.name}.${methodName}"`);
216
+ return reducer;
217
+ }
218
+ catch {
219
+ throw new Error(`Couldn't load the Entity class ${reducerMetadata.class.name}`);
220
+ }
221
+ }
222
+ }
223
+ }
224
+ exports.EventStore = EventStore;
225
+ tslib_1.__decorate([
226
+ (0, instrumentation_1.Trace)(common_1.TraceActionTypes.FETCH_ENTITY_SNAPSHOT),
227
+ tslib_1.__metadata("design:type", Function),
228
+ tslib_1.__metadata("design:paramtypes", [String, common_1.UUID]),
229
+ tslib_1.__metadata("design:returntype", Promise)
230
+ ], EventStore.prototype, "fetchEntitySnapshot", null);
231
+ tslib_1.__decorate([
232
+ (0, instrumentation_1.Trace)(common_1.TraceActionTypes.CUSTOM),
233
+ tslib_1.__metadata("design:type", Function),
234
+ tslib_1.__metadata("design:paramtypes", [Object]),
235
+ tslib_1.__metadata("design:returntype", Promise)
236
+ ], EventStore.prototype, "storeDispatchedEvent", null);
237
+ tslib_1.__decorate([
238
+ (0, instrumentation_1.Trace)(common_1.TraceActionTypes.STORE_SNAPSHOT),
239
+ tslib_1.__metadata("design:type", Function),
240
+ tslib_1.__metadata("design:paramtypes", [Object]),
241
+ tslib_1.__metadata("design:returntype", Promise)
242
+ ], EventStore.prototype, "storeSnapshot", null);
243
+ tslib_1.__decorate([
244
+ (0, instrumentation_1.Trace)(common_1.TraceActionTypes.LOAD_LATEST_SNAPSHOT),
245
+ tslib_1.__metadata("design:type", Function),
246
+ tslib_1.__metadata("design:paramtypes", [String, common_1.UUID]),
247
+ tslib_1.__metadata("design:returntype", Promise)
248
+ ], EventStore.prototype, "loadLatestSnapshot", null);
249
+ tslib_1.__decorate([
250
+ (0, instrumentation_1.Trace)(common_1.TraceActionTypes.LOAD_EVENT_STREAM_SINCE),
251
+ tslib_1.__metadata("design:type", Function),
252
+ tslib_1.__metadata("design:paramtypes", [String, common_1.UUID, String]),
253
+ tslib_1.__metadata("design:returntype", Promise)
254
+ ], EventStore.prototype, "loadEventStreamSince", null);
255
+ tslib_1.__decorate([
256
+ (0, instrumentation_1.Trace)(common_1.TraceActionTypes.ENTITY_REDUCER),
257
+ tslib_1.__metadata("design:type", Function),
258
+ tslib_1.__metadata("design:paramtypes", [Object, Object]),
259
+ tslib_1.__metadata("design:returntype", Promise)
260
+ ], EventStore.prototype, "entityReducer", null);
@@ -0,0 +1,3 @@
1
+ import { ReadModelBeforeFunction, CommandBeforeFunction, CommandInput, UserEnvelope, ReadModelRequestEnvelope, ReadModelInterface, QueryInput, QueryBeforeFunction } from '@magek/common';
2
+ export declare const applyReadModelRequestBeforeFunctions: (readModelRequestEnvelope: ReadModelRequestEnvelope<ReadModelInterface>, beforeHooks: Array<ReadModelBeforeFunction>, currentUser?: UserEnvelope) => Promise<ReadModelRequestEnvelope<ReadModelInterface>>;
3
+ export declare const applyBeforeFunctions: (commandInput: CommandInput | QueryInput, beforeHooks: Array<CommandBeforeFunction | QueryBeforeFunction>, currentUser?: UserEnvelope) => Promise<CommandInput | QueryInput>;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.applyBeforeFunctions = exports.applyReadModelRequestBeforeFunctions = void 0;
4
+ const applyReadModelRequestBeforeFunctions = async (readModelRequestEnvelope, beforeHooks, currentUser) => {
5
+ let result = readModelRequestEnvelope;
6
+ for (const beforeHook of beforeHooks) {
7
+ result = await beforeHook(result, currentUser);
8
+ }
9
+ return result;
10
+ };
11
+ exports.applyReadModelRequestBeforeFunctions = applyReadModelRequestBeforeFunctions;
12
+ const applyBeforeFunctions = async (commandInput, beforeHooks, currentUser) => {
13
+ let result = commandInput;
14
+ for (const beforeHook of beforeHooks) {
15
+ result = await beforeHook(result, currentUser);
16
+ }
17
+ return result;
18
+ };
19
+ exports.applyBeforeFunctions = applyBeforeFunctions;
@@ -0,0 +1,26 @@
1
+ import { GraphQLScalarType } from 'graphql/type/definition';
2
+ import { AnyClass, UserEnvelope, UUID, GraphQLOperation, ReadModelInterface, ContextEnvelope, PropertyMetadata, TypeMetadata } from '@magek/common';
3
+ import { GraphQLEnumType, GraphQLFieldResolver, GraphQLList, GraphQLObjectType, GraphQLType } from 'graphql';
4
+ import { ReadModelPubSub } from '../pub-sub/read-model-pub-sub';
5
+ export type TargetTypesMap = Record<string, TargetTypeMetadata>;
6
+ export interface TargetTypeMetadata {
7
+ class: AnyClass;
8
+ properties: Array<PropertyMetadata>;
9
+ methods: Array<PropertyMetadata>;
10
+ }
11
+ export type GraphQLNonInputType = GraphQLObjectType | GraphQLScalarType | GraphQLList<GraphQLType>;
12
+ export type ResolverBuilder = (objectClass: AnyClass) => GraphQLFieldResolver<unknown, GraphQLResolverContext, any>;
13
+ export interface GraphQLResolverContext {
14
+ connectionID?: string;
15
+ responseHeaders: Record<string, string>;
16
+ operation: GraphQLOperation;
17
+ requestID: UUID;
18
+ user?: UserEnvelope;
19
+ storeSubscriptions: boolean;
20
+ pubSub: ReadModelPubSub<ReadModelInterface>;
21
+ context?: ContextEnvelope;
22
+ }
23
+ export declare const DateScalar: GraphQLScalarType<Date, string>;
24
+ export declare function isExternalType(typeMetadata: Pick<TypeMetadata, 'importPath'>): boolean;
25
+ export declare const buildGraphqlSimpleEnumFor: (enumName: string, values: Array<string>) => GraphQLEnumType;
26
+ export declare function nonExcludedFields(fields: Array<PropertyMetadata>, excludeProps?: Array<string>): Array<PropertyMetadata>;
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildGraphqlSimpleEnumFor = exports.DateScalar = void 0;
4
+ exports.isExternalType = isExternalType;
5
+ exports.nonExcludedFields = nonExcludedFields;
6
+ const definition_1 = require("graphql/type/definition");
7
+ const graphql_1 = require("graphql");
8
+ function parseDate(inputValue) {
9
+ const result = safeParse();
10
+ switch (result.type) {
11
+ case 'success':
12
+ return result.date;
13
+ case 'error':
14
+ throw new Error(result.message);
15
+ }
16
+ function safeParse() {
17
+ if (typeof inputValue !== 'string')
18
+ return { type: 'error', message: `Invalid date, not a string: ${inputValue}` };
19
+ const date = new Date(inputValue); // Verified that it's a string, so it's safe to cast.
20
+ return isNaN(date.getTime()) ? { type: 'error', message: `Invalid date: ${inputValue}` } : { type: 'success', date };
21
+ }
22
+ }
23
+ exports.DateScalar = new definition_1.GraphQLScalarType({
24
+ name: 'Date',
25
+ description: 'Date custom scalar type',
26
+ serialize(value) {
27
+ return value.toJSON();
28
+ },
29
+ parseValue: parseDate,
30
+ parseLiteral(ast) {
31
+ if (ast.kind === graphql_1.Kind.STRING) {
32
+ return parseDate(ast.value);
33
+ }
34
+ // This should never happen, it's not safe, but the safeguards at the edges should guarantee this.
35
+ return null;
36
+ },
37
+ });
38
+ function isExternalType(typeMetadata) {
39
+ return !!typeMetadata.importPath && !typeMetadata.importPath.startsWith('.');
40
+ }
41
+ const buildGraphqlSimpleEnumFor = (enumName, values) => {
42
+ return new graphql_1.GraphQLEnumType({
43
+ name: enumName,
44
+ values: values.reduce((valuesRecord, value) => {
45
+ valuesRecord[value] = { value };
46
+ return valuesRecord;
47
+ }, {}),
48
+ });
49
+ };
50
+ exports.buildGraphqlSimpleEnumFor = buildGraphqlSimpleEnumFor;
51
+ function nonExcludedFields(fields, excludeProps) {
52
+ return excludeProps ? fields.filter((field) => !excludeProps.includes(field.name)) : fields;
53
+ }
@@ -0,0 +1,46 @@
1
+ import { AnyClass, MagekConfig, EventSearchParameters, EventSearchResponse, ReadModelByIdRequestArgs, ReadModelInterface, ReadModelRequestArgs, ReadModelRequestProperties } from '@magek/common';
2
+ import { GraphQLFieldResolver, GraphQLSchema } from 'graphql';
3
+ import { GraphQLResolverContext } from './common';
4
+ export declare class GraphQLGenerator {
5
+ private static commandsDispatcher;
6
+ private static queriesDispatcher;
7
+ private static readModelsReader;
8
+ private static eventsReader;
9
+ private static schema;
10
+ static generateSchema(config: MagekConfig): GraphQLSchema;
11
+ static readModelResolverBuilder(readModelClass: AnyClass): GraphQLFieldResolver<unknown, GraphQLResolverContext, ReadModelRequestArgs<ReadModelInterface>>;
12
+ static readModelByIDResolverBuilder(config: MagekConfig, readModelClass: AnyClass): GraphQLFieldResolver<unknown, GraphQLResolverContext, ReadModelByIdRequestArgs>;
13
+ static eventResolver(parent: unknown, args: EventSearchParameters, context: GraphQLResolverContext): Promise<Array<EventSearchResponse>>;
14
+ static commandResolverBuilder(commandClass: AnyClass): GraphQLFieldResolver<unknown, GraphQLResolverContext, {
15
+ input: unknown;
16
+ }>;
17
+ static queriesResolverBuilder(queryClass: AnyClass): GraphQLFieldResolver<unknown, GraphQLResolverContext, {
18
+ input: unknown;
19
+ }>;
20
+ static subscriptionByIDResolverBuilder(config: MagekConfig, readModelClass: AnyClass): GraphQLFieldResolver<unknown, GraphQLResolverContext, ReadModelRequestProperties<ReadModelInterface>>;
21
+ static subscriptionResolverBuilder(config: MagekConfig, readModelClass: AnyClass): GraphQLFieldResolver<unknown, GraphQLResolverContext, ReadModelRequestArgs<ReadModelInterface>>;
22
+ private static toReadModelByIdRequestEnvelope;
23
+ /**
24
+ * Extracts the fields from a GraphQLResolveInfo object. This object is part of a GraphQL request and the goal is to
25
+ * identify the fields in the request. For example, for the following GraphQL query request:
26
+ *
27
+ * ```graphql
28
+ * query {
29
+ * CartReadModel {
30
+ * id
31
+ * cartItems {
32
+ * id
33
+ * quantity
34
+ * }
35
+ * }
36
+ * }
37
+ * ```
38
+ *
39
+ * it will return the following list of fields: `['id', 'cartItems[].id', 'cartItems[].quantity']`
40
+ *
41
+ * @param {GraphQLResolveInfo} info - The GraphQLResolveInfo object.
42
+ * @returns {string[]} - The extracted fields.
43
+ * @private
44
+ */
45
+ private static getFields;
46
+ }