@magek/core 0.0.6 → 0.0.8

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 (104) hide show
  1. package/dist/authorizer.js +1 -1
  2. package/dist/command-dispatcher.js +47 -41
  3. package/dist/core-concepts/data-migration/entities/data-migration-entity.js +5 -2
  4. package/dist/core-concepts/data-migration/events/data-migration-finished.js +3 -1
  5. package/dist/core-concepts/data-migration/events/data-migration-started.js +3 -1
  6. package/dist/core-concepts/data-migration/events/entity-migrated.js +4 -0
  7. package/dist/core-concepts/touch-entity/events/entity-touched.js +2 -0
  8. package/dist/data-migrations.js +59 -54
  9. package/dist/decorators/command.d.ts +4 -11
  10. package/dist/decorators/command.js +10 -18
  11. package/dist/decorators/data-migration.d.ts +4 -1
  12. package/dist/decorators/data-migration.js +3 -1
  13. package/dist/decorators/decorator-types.d.ts +50 -0
  14. package/dist/decorators/decorator-types.js +11 -0
  15. package/dist/decorators/decorator-utils.d.ts +1 -0
  16. package/dist/decorators/decorator-utils.js +2 -0
  17. package/dist/decorators/entity.d.ts +7 -15
  18. package/dist/decorators/entity.js +27 -37
  19. package/dist/decorators/event-handler.d.ts +11 -1
  20. package/dist/decorators/event-handler.js +13 -1
  21. package/dist/decorators/event.d.ts +4 -1
  22. package/dist/decorators/event.js +3 -2
  23. package/dist/decorators/field-metadata-reader.d.ts +8 -3
  24. package/dist/decorators/field-metadata-reader.js +61 -62
  25. package/dist/decorators/field.d.ts +23 -0
  26. package/dist/decorators/field.js +41 -0
  27. package/dist/decorators/global-error-handler.d.ts +10 -1
  28. package/dist/decorators/global-error-handler.js +9 -1
  29. package/dist/decorators/global-event-handler.d.ts +10 -1
  30. package/dist/decorators/global-event-handler.js +9 -1
  31. package/dist/decorators/health-sensor.d.ts +4 -1
  32. package/dist/decorators/health-sensor.js +3 -2
  33. package/dist/decorators/index.d.ts +4 -0
  34. package/dist/decorators/index.js +3 -0
  35. package/dist/decorators/metadata.d.ts +17 -1
  36. package/dist/decorators/metadata.js +22 -22
  37. package/dist/decorators/non-exposed.d.ts +13 -2
  38. package/dist/decorators/non-exposed.js +22 -20
  39. package/dist/decorators/notification.d.ts +6 -18
  40. package/dist/decorators/notification.js +10 -50
  41. package/dist/decorators/projects.d.ts +5 -18
  42. package/dist/decorators/projects.js +23 -54
  43. package/dist/decorators/query.d.ts +11 -1
  44. package/dist/decorators/query.js +18 -4
  45. package/dist/decorators/read-model.d.ts +13 -27
  46. package/dist/decorators/read-model.js +45 -77
  47. package/dist/decorators/returns.d.ts +37 -0
  48. package/dist/decorators/returns.js +154 -0
  49. package/dist/decorators/role.d.ts +9 -3
  50. package/dist/decorators/role.js +8 -3
  51. package/dist/decorators/scheduled-command.d.ts +4 -1
  52. package/dist/decorators/scheduled-command.js +3 -1
  53. package/dist/decorators/schema-migration.d.ts +11 -27
  54. package/dist/decorators/schema-migration.js +32 -77
  55. package/dist/decorators/sequenced-by.d.ts +7 -25
  56. package/dist/decorators/sequenced-by.js +11 -71
  57. package/dist/event-dispatcher.js +29 -24
  58. package/dist/event-processor.js +107 -103
  59. package/dist/event-stream-consumer.js +25 -20
  60. package/dist/event-stream-producer.js +22 -17
  61. package/dist/events-reader.js +1 -0
  62. package/dist/global-error-dispatcher.js +3 -2
  63. package/dist/graphql-dispatcher.js +161 -156
  64. package/dist/index.js +4 -0
  65. package/dist/instrumentation/decorator/trace.d.ts +11 -3
  66. package/dist/instrumentation/decorator/trace.js +17 -71
  67. package/dist/magek.js +2 -2
  68. package/dist/query-dispatcher.js +2 -0
  69. package/dist/read-model-schema-migrator.js +71 -68
  70. package/dist/read-models-reader.js +178 -180
  71. package/dist/register-handler.js +3 -3
  72. package/dist/scheduled-command-dispatcher.js +48 -42
  73. package/dist/schema-migrator.js +63 -59
  74. package/dist/sensor/health/health-service.js +2 -1
  75. package/dist/services/event-store.js +221 -224
  76. package/dist/services/graphql/graphql-generator.js +11 -8
  77. package/dist/services/graphql/graphql-mutation-generator.js +4 -0
  78. package/dist/services/graphql/graphql-query-generator.js +14 -0
  79. package/dist/services/graphql/graphql-subcriptions-generator.js +7 -0
  80. package/dist/services/graphql/graphql-type-informer.js +4 -3
  81. package/dist/services/graphql/query-generators/graphql-query-by-keys-generator.js +4 -0
  82. package/dist/services/graphql/query-generators/graphql-query-events-generator.js +3 -0
  83. package/dist/services/graphql/query-generators/graphql-query-filters-generator.js +6 -0
  84. package/dist/services/graphql/query-generators/graphql-query-generator.js +4 -0
  85. package/dist/services/graphql/query-generators/graphql-query-listed-generator.js +7 -0
  86. package/dist/services/graphql/query-helpers/graphql-handled-fields-generator.js +5 -2
  87. package/dist/services/graphql/query-helpers/graphql-query-filter-arguments-builder.js +3 -0
  88. package/dist/services/graphql/query-helpers/graphql-query-filter-fields-builder.js +4 -0
  89. package/dist/services/graphql/query-helpers/graphql-query-sort-builder.js +4 -2
  90. package/dist/services/graphql/websocket-protocol/graphql-websocket-protocol.js +5 -3
  91. package/dist/services/pub-sub/read-model-pub-sub.js +1 -0
  92. package/dist/services/raw-events-parser.js +1 -1
  93. package/dist/services/read-model-store.js +20 -20
  94. package/dist/services/token-verifiers/jwks-uri-token-verifier.js +8 -4
  95. package/dist/services/token-verifiers/public-key-token-verifier.js +4 -2
  96. package/dist/services/token-verifiers/role-based-token-verifier.js +2 -1
  97. package/dist/services/token-verifiers/utilities.js +1 -1
  98. package/dist/subscribers-notifier.js +99 -92
  99. package/dist/token-verifier.js +2 -1
  100. package/dist/utils/promises.d.ts +25 -0
  101. package/dist/utils/promises.js +43 -0
  102. package/package.json +4 -4
  103. package/dist/decorators/stage3-utils.d.ts +0 -6
  104. package/dist/decorators/stage3-utils.js +0 -25
@@ -3,6 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.GraphqlQueryByKeysGenerator = void 0;
4
4
  const graphql_1 = require("graphql");
5
5
  class GraphqlQueryByKeysGenerator {
6
+ config;
7
+ readModels;
8
+ typeInformer;
9
+ byIDResolverBuilder;
6
10
  constructor(config, readModels, typeInformer, byIDResolverBuilder) {
7
11
  this.config = config;
8
12
  this.readModels = readModels;
@@ -5,6 +5,9 @@ const graphql_1 = require("graphql");
5
5
  const common_1 = require("../common");
6
6
  const graphql_scalars_1 = require("graphql-scalars");
7
7
  class GraphqlQueryEventsGenerator {
8
+ config;
9
+ byIDResolverBuilder;
10
+ eventsResolver;
8
11
  constructor(config, byIDResolverBuilder, eventsResolver) {
9
12
  this.config = config;
10
13
  this.byIDResolverBuilder = byIDResolverBuilder;
@@ -5,6 +5,12 @@ const graphql_1 = require("graphql");
5
5
  const inflected = require("inflected");
6
6
  const graphql_query_filter_fields_builder_1 = require("../query-helpers/graphql-query-filter-fields-builder");
7
7
  class GraphqlQueryFiltersGenerator {
8
+ readModels;
9
+ typeInformer;
10
+ filterResolverBuilder;
11
+ generatedFiltersByTypeName;
12
+ config;
13
+ graphqlQueryFilterFieldsBuilder;
8
14
  constructor(readModels, typeInformer, filterResolverBuilder, generatedFiltersByTypeName = {}, config) {
9
15
  this.readModels = readModels;
10
16
  this.typeInformer = typeInformer;
@@ -3,6 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.GraphqlQueryGenerator = void 0;
4
4
  const graphql_handled_fields_generator_1 = require("../query-helpers/graphql-handled-fields-generator");
5
5
  class GraphqlQueryGenerator {
6
+ targetTypes;
7
+ typeInformer;
8
+ queryResolveBuilder;
9
+ config;
6
10
  constructor(targetTypes, typeInformer, queryResolveBuilder, config) {
7
11
  this.targetTypes = targetTypes;
8
12
  this.typeInformer = typeInformer;
@@ -7,6 +7,13 @@ const graphql_scalars_1 = require("graphql-scalars");
7
7
  const graphql_query_sort_builder_1 = require("../query-helpers/graphql-query-sort-builder");
8
8
  const graphql_query_filter_arguments_builder_1 = require("../query-helpers/graphql-query-filter-arguments-builder");
9
9
  class GraphqlQueryListedGenerator {
10
+ readModels;
11
+ typeInformer;
12
+ filterResolverBuilder;
13
+ generatedFiltersByTypeName;
14
+ config;
15
+ graphqlQueryFilterArgumentsBuilder;
16
+ graphqlQuerySortBuilder;
10
17
  constructor(readModels, typeInformer, filterResolverBuilder, generatedFiltersByTypeName = {}, config) {
11
18
  this.readModels = readModels;
12
19
  this.typeInformer = typeInformer;
@@ -3,6 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.GraphQLHandledFieldsGenerator = void 0;
4
4
  const graphql_1 = require("graphql");
5
5
  class GraphQLHandledFieldsGenerator {
6
+ targetTypes;
7
+ typeInformer;
8
+ resolver;
9
+ config;
6
10
  constructor(targetTypes, typeInformer, resolver, config) {
7
11
  this.targetTypes = targetTypes;
8
12
  this.typeInformer = typeInformer;
@@ -37,8 +41,7 @@ class GraphQLHandledFieldsGenerator {
37
41
  };
38
42
  }
39
43
  static getHandleMethodMetadata(metadata) {
40
- var _a;
41
- let handleMethodMetadata = (_a = metadata.methods.find((m) => m.name === 'handle')) === null || _a === void 0 ? void 0 : _a.typeInfo;
44
+ let handleMethodMetadata = metadata.methods.find((m) => m.name === 'handle')?.typeInfo;
42
45
  if (handleMethodMetadata && handleMethodMetadata.typeName === 'Promise') {
43
46
  // If async function, return type is wrapped in a Promise
44
47
  handleMethodMetadata = handleMethodMetadata.parameters[0];
@@ -7,6 +7,9 @@ const graphql_scalars_1 = require("graphql-scalars");
7
7
  const common_1 = require("@magek/common");
8
8
  const common_2 = require("../common");
9
9
  class GraphqlQueryFilterArgumentsBuilder {
10
+ typeInformer;
11
+ generatedFiltersByTypeName;
12
+ config;
10
13
  constructor(typeInformer, generatedFiltersByTypeName = {}, config) {
11
14
  this.typeInformer = typeInformer;
12
15
  this.generatedFiltersByTypeName = generatedFiltersByTypeName;
@@ -4,6 +4,10 @@ exports.GraphqlQueryFilterFieldsBuilder = void 0;
4
4
  const graphql_1 = require("graphql");
5
5
  const graphql_query_filter_arguments_builder_1 = require("./graphql-query-filter-arguments-builder");
6
6
  class GraphqlQueryFilterFieldsBuilder {
7
+ typeInformer;
8
+ generatedFiltersByTypeName;
9
+ config;
10
+ graphqlQueryFilterArgumentsBuilder;
7
11
  constructor(typeInformer, generatedFiltersByTypeName = {}, config) {
8
12
  this.typeInformer = typeInformer;
9
13
  this.generatedFiltersByTypeName = generatedFiltersByTypeName;
@@ -5,11 +5,13 @@ const graphql_1 = require("graphql");
5
5
  const metadata_1 = require("../../../decorators/metadata");
6
6
  const common_1 = require("../common");
7
7
  class GraphqlQuerySortBuilder {
8
+ typeInformer;
9
+ config;
10
+ generatedSortByByTypeName = {};
11
+ orderType = (0, common_1.buildGraphqlSimpleEnumFor)('orderProperty', ['ASC', 'DESC']);
8
12
  constructor(typeInformer, config) {
9
13
  this.typeInformer = typeInformer;
10
14
  this.config = config;
11
- this.generatedSortByByTypeName = {};
12
- this.orderType = (0, common_1.buildGraphqlSimpleEnumFor)('orderProperty', ['ASC', 'DESC']);
13
15
  }
14
16
  generateSortArguments(type, excludeProps) {
15
17
  const metadata = (0, metadata_1.getClassMetadata)(type);
@@ -3,6 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.GraphQLWebsocketHandler = void 0;
4
4
  const common_1 = require("@magek/common");
5
5
  class GraphQLWebsocketHandler {
6
+ config;
7
+ callbacks;
8
+ tokenVerifier;
6
9
  constructor(config, callbacks, tokenVerifier) {
7
10
  this.config = config;
8
11
  this.callbacks = callbacks;
@@ -47,10 +50,9 @@ class GraphQLWebsocketHandler {
47
50
  }
48
51
  }
49
52
  async handleInit(connectionID, clientMessage) {
50
- var _a;
51
53
  const logger = (0, common_1.getLogger)(this.config, 'GraphQLWebsocketHandler#handleInit');
52
54
  let userEnvelope;
53
- if ((_a = clientMessage.payload) === null || _a === void 0 ? void 0 : _a.Authorization) {
55
+ if (clientMessage.payload?.Authorization) {
54
56
  userEnvelope = await this.tokenVerifier.verify(clientMessage.payload.Authorization);
55
57
  }
56
58
  const nowEpoch = Math.floor(new Date().getTime() / 1000);
@@ -92,7 +94,7 @@ class GraphQLWebsocketHandler {
92
94
  logger.debug('Found connection data: ', connectionData);
93
95
  return {
94
96
  ...envelope,
95
- currentUser: connectionData === null || connectionData === void 0 ? void 0 : connectionData.user,
97
+ currentUser: connectionData?.user,
96
98
  value: {
97
99
  ...message.payload,
98
100
  id: message.id,
@@ -4,6 +4,7 @@ exports.FilteredReadModelPubSub = void 0;
4
4
  const iterall_1 = require("iterall");
5
5
  const filter_helpers_1 = require("../filter-helpers");
6
6
  class FilteredReadModelPubSub {
7
+ readModels;
7
8
  constructor(readModels) {
8
9
  this.readModels = readModels;
9
10
  }
@@ -32,7 +32,7 @@ function isEventKind(envelope) {
32
32
  return envelope.kind == 'event';
33
33
  }
34
34
  function isNotDeleted(envelope) {
35
- return !(envelope === null || envelope === void 0 ? void 0 : envelope.deletedAt);
35
+ return !envelope?.deletedAt;
36
36
  }
37
37
  function groupByEntity(envelopesPerEntity, envelope) {
38
38
  const entityKey = `${envelope.entityTypeName}-${envelope.entityID}`;
@@ -2,10 +2,12 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ReadModelStore = void 0;
4
4
  const common_1 = require("@magek/common");
5
+ const promises_1 = require("../utils/promises");
5
6
  const global_error_dispatcher_1 = require("../global-error-dispatcher");
6
7
  const read_model_searcher_1 = require("./read-model-searcher");
7
8
  const read_model_schema_migrator_1 = require("../read-model-schema-migrator");
8
9
  class ReadModelStore {
10
+ config;
9
11
  constructor(config) {
10
12
  this.config = config;
11
13
  }
@@ -27,7 +29,7 @@ class ReadModelStore {
27
29
  const sequenceKey = this.sequenceKeyForProjection(entityInstance, projectionMetadata);
28
30
  return this.projectEntity(entityInstance, projectionMetadata, entityMetadata, entitySnapshotEnvelope, readModelName, deleteEvent, sequenceKey);
29
31
  });
30
- await common_1.Promises.allSettledAndFulfilled(projectReadModelPromises);
32
+ await promises_1.Promises.allSettledAndFulfilled(projectReadModelPromises);
31
33
  }
32
34
  /**
33
35
  * Gets the read models for a given entity instance using the projection metadata
@@ -82,7 +84,7 @@ class ReadModelStore {
82
84
  getUnProjections(entitySnapshotEnvelope) {
83
85
  const unProjections = this.entityUnProjections(entitySnapshotEnvelope);
84
86
  const projections = this.entityProjections(entitySnapshotEnvelope);
85
- if ((projections === null || projections === void 0 ? void 0 : projections.length) > 0) {
87
+ if (projections?.length > 0) {
86
88
  if (!unProjections) {
87
89
  throw new Error(`Missing UnProjections for entity ${entitySnapshotEnvelope.entityTypeName}`);
88
90
  }
@@ -122,10 +124,10 @@ class ReadModelStore {
122
124
  const newProjections = await this.projectionsForReadModels(entitySnapshotEnvelope, readModelName, sequenceKey, projectionMetadata, entityInstance, entityMetadata, deleteEvent, currentReadModel);
123
125
  existingReadModelsProjections.push(...newProjections);
124
126
  }
125
- return common_1.Promises.allSettledAndFulfilled(existingReadModelsProjections);
127
+ return promises_1.Promises.allSettledAndFulfilled(existingReadModelsProjections);
126
128
  }
127
129
  const newProjections = await this.projectionsForReadModels(entitySnapshotEnvelope, readModelName, sequenceKey, projectionMetadata, entityInstance, entityMetadata, deleteEvent);
128
- return common_1.Promises.allSettledAndFulfilled(newProjections);
130
+ return promises_1.Promises.allSettledAndFulfilled(newProjections);
129
131
  }
130
132
  async projectionsForReadModels(entitySnapshotEnvelope, readModelName, sequenceKey, projectionMetadata, entityInstance, entityMetadata, deleteEvent, currentReadModel) {
131
133
  const projections = [];
@@ -139,46 +141,45 @@ class ReadModelStore {
139
141
  const entitiesJoinKeys = Array.isArray(entityJoinKey) ? entityJoinKey : [entityJoinKey];
140
142
  // A new Read Model with JoinKey by entity needs to be projected using a JoinKey with an entity query. We don't have a previous read model, but we have the new id from the entity
141
143
  for (const readModelId of entitiesJoinKeys) {
142
- const readModel = (currentReadModel === null || currentReadModel === void 0 ? void 0 : currentReadModel.id) === readModelId ? currentReadModel : undefined;
144
+ const readModel = currentReadModel?.id === readModelId ? currentReadModel : undefined;
143
145
  projections.push(this.projectAndStoreReadModelWithRetry(entitySnapshotEnvelope, readModelName, sequenceKey, entityInstance, projectionMetadata, deleteEvent, readModelId, readModel));
144
146
  }
145
147
  }
146
148
  else {
147
149
  // A new Read Model with JoinKey by ReadModel needs to be projected using a JoinKey with a read model query. We don't have a previous read model nor the new id as we don't have an entity field
148
- projections.push(this.projectAndStoreReadModelWithRetry(entitySnapshotEnvelope, readModelName, sequenceKey, entityInstance, projectionMetadata, deleteEvent, currentReadModel === null || currentReadModel === void 0 ? void 0 : currentReadModel.id, currentReadModel));
150
+ projections.push(this.projectAndStoreReadModelWithRetry(entitySnapshotEnvelope, readModelName, sequenceKey, entityInstance, projectionMetadata, deleteEvent, currentReadModel?.id, currentReadModel));
149
151
  }
150
152
  return projections;
151
153
  }
152
154
  async projectAndStoreReadModelWithRetry(entitySnapshotEnvelope, readModelName, sequenceKey, entityInstance, projectionMetadata, deleteEvent, readModelId, currentReadModel) {
153
155
  const logger = (0, common_1.getLogger)(this.config, 'ReadModelStore#projectAndStoreReadModelWithRetry');
154
- logger.debug('Projecting entity snapshot ', entitySnapshotEnvelope, ` to build new state of read model ${readModelName} with ID ${(currentReadModel === null || currentReadModel === void 0 ? void 0 : currentReadModel.id) || readModelId}`, sequenceKey ? ` sequencing by ${sequenceKey.name} with value ${sequenceKey.value}` : '');
156
+ logger.debug('Projecting entity snapshot ', entitySnapshotEnvelope, ` to build new state of read model ${readModelName} with ID ${currentReadModel?.id || readModelId}`, sequenceKey ? ` sequencing by ${sequenceKey.name} with value ${sequenceKey.value}` : '');
155
157
  return (0, common_1.retryIfError)((tryNumber) => this.applyProjectionToReadModel(entitySnapshotEnvelope, entityInstance, projectionMetadata, deleteEvent, currentReadModel, entitySnapshotEnvelope, readModelId, sequenceKey, tryNumber), common_1.OptimisticConcurrencyUnexpectedVersionError, logger);
156
158
  }
157
159
  instanceReadModels(readModelName, rawReadModels) {
158
- if (!(rawReadModels === null || rawReadModels === void 0 ? void 0 : rawReadModels.length)) {
160
+ if (!rawReadModels?.length) {
159
161
  return [];
160
162
  }
161
163
  const readModelMetadata = this.config.readModels[readModelName];
162
164
  return rawReadModels.map((rawReadModel) => (0, common_1.createInstance)(readModelMetadata.class, rawReadModel));
163
165
  }
164
166
  async applyProjectionToReadModel(entitySnapshotEnvelope, entity, projectionMetadata, deleteEvent, currentReadModel, lastProjectedEntity, currentReadModelID, sequenceKey, tryNumber) {
165
- var _a, _b, _c, _d, _e, _f;
166
167
  const logger = (0, common_1.getLogger)(this.config, 'ReadModelStore#applyProjectionToReadModel');
167
168
  const readModelName = projectionMetadata.class.name;
168
- const readModelID = currentReadModelID !== null && currentReadModelID !== void 0 ? currentReadModelID : currentReadModel === null || currentReadModel === void 0 ? void 0 : currentReadModel.id;
169
+ const readModelID = currentReadModelID ?? currentReadModel?.id;
169
170
  if (tryNumber && tryNumber > 1) {
170
171
  // In case of optimistic concurrency error, we need to fetch the current read model version and retry
171
- logger.debug(`OptimisticConcurrencyUnexpectedVersionError (version=${(_a = currentReadModel === null || currentReadModel === void 0 ? void 0 : currentReadModel.magekMetadata) === null || _a === void 0 ? void 0 : _a.version} and expectedDatabaseVersion=${(_c = (_b = currentReadModel === null || currentReadModel === void 0 ? void 0 : currentReadModel.magekMetadata) === null || _b === void 0 ? void 0 : _b.version) !== null && _c !== void 0 ? _c : 0}). Looking for an updated version of read model ${readModelName} with ID = ${readModelID}` +
172
+ logger.debug(`OptimisticConcurrencyUnexpectedVersionError (version=${currentReadModel?.magekMetadata?.version} and expectedDatabaseVersion=${currentReadModel?.magekMetadata?.version ?? 0}). Looking for an updated version of read model ${readModelName} with ID = ${readModelID}` +
172
173
  (sequenceKey ? ` and sequence key ${sequenceKey.name} = ${sequenceKey.value}` : ''));
173
174
  currentReadModel = await this.fetchReadModel(readModelName, readModelID, sequenceKey);
174
- logger.debug(`Current read model ${readModelName} with ID ${readModelID} updated with version = ${(_d = currentReadModel === null || currentReadModel === void 0 ? void 0 : currentReadModel.magekMetadata) === null || _d === void 0 ? void 0 : _d.version}` +
175
+ logger.debug(`Current read model ${readModelName} with ID ${readModelID} updated with version = ${currentReadModel?.magekMetadata?.version}` +
175
176
  (sequenceKey ? ` and sequence key ${sequenceKey.name} = ${sequenceKey.value}` : ''));
176
177
  }
177
178
  let migratedReadModel;
178
179
  if (currentReadModel) {
179
180
  migratedReadModel = await new read_model_schema_migrator_1.ReadModelSchemaMigrator(this.config).migrate(currentReadModel, readModelName);
180
181
  }
181
- const currentDatabaseVersion = (_f = (_e = migratedReadModel === null || migratedReadModel === void 0 ? void 0 : migratedReadModel.magekMetadata) === null || _e === void 0 ? void 0 : _e.version) !== null && _f !== void 0 ? _f : 0;
182
+ const currentDatabaseVersion = migratedReadModel?.magekMetadata?.version ?? 0;
182
183
  let newReadModel;
183
184
  const projectionInfo = {
184
185
  reason: deleteEvent ? common_1.ProjectionInfoReason.ENTITY_DELETED : common_1.ProjectionInfoReason.ENTITY_PROJECTED,
@@ -192,31 +193,30 @@ class ReadModelStore {
192
193
  if (error)
193
194
  throw error;
194
195
  }
195
- if (newReadModel === common_1.ReadModelAction.Delete) {
196
+ if (newReadModel === common_1.ProjectionAction.Delete) {
196
197
  logger.debug(`Deleting read model ${readModelName} with ID ${readModelID}:`, migratedReadModel);
197
198
  return this.config.readModelStore.delete(this.config, readModelName, readModelID);
198
199
  }
199
- else if (newReadModel === common_1.ReadModelAction.Nothing) {
200
+ else if (newReadModel === common_1.ProjectionAction.Skip) {
200
201
  logger.debug(`Skipping actions for ${readModelName} with ID ${readModelID}:`, newReadModel);
201
202
  return;
202
203
  }
203
204
  return await this.store(entity, projectionMetadata, readModelID, readModelName, migratedReadModel, newReadModel, currentDatabaseVersion, lastProjectedEntity);
204
205
  }
205
206
  async store(entity, projectionMetadata, readModelID, readModelName, migratedReadModel, newReadModel, expectedCurrentDatabaseVersion, lastProjectedEntity) {
206
- var _a, _b;
207
207
  const logger = (0, common_1.getLogger)(this.config, 'ReadModelStore#store');
208
- const schemaVersion = (_b = (_a = migratedReadModel === null || migratedReadModel === void 0 ? void 0 : migratedReadModel.magekMetadata) === null || _a === void 0 ? void 0 : _a.schemaVersion) !== null && _b !== void 0 ? _b : this.config.currentVersionFor(readModelName);
208
+ const schemaVersion = migratedReadModel?.magekMetadata?.schemaVersion ?? this.config.currentVersionFor(readModelName);
209
209
  // Increment the read model version in 1 before storing
210
210
  const newReadModelVersion = expectedCurrentDatabaseVersion + 1;
211
211
  newReadModel.magekMetadata = {
212
- ...migratedReadModel === null || migratedReadModel === void 0 ? void 0 : migratedReadModel.magekMetadata,
212
+ ...migratedReadModel?.magekMetadata,
213
213
  version: newReadModelVersion,
214
214
  schemaVersion: schemaVersion,
215
215
  lastUpdateAt: new Date().toISOString(),
216
216
  lastProjectionInfo: {
217
217
  entityId: entity.id,
218
- entityName: lastProjectedEntity === null || lastProjectedEntity === void 0 ? void 0 : lastProjectedEntity.entityTypeName,
219
- entityUpdatedAt: lastProjectedEntity === null || lastProjectedEntity === void 0 ? void 0 : lastProjectedEntity.createdAt,
218
+ entityName: lastProjectedEntity?.entityTypeName,
219
+ entityUpdatedAt: lastProjectedEntity?.createdAt,
220
220
  projectionMethod: `${projectionMetadata.class.name}.${projectionMetadata.methodName}`,
221
221
  },
222
222
  };
@@ -4,15 +4,19 @@ exports.JwksUriTokenVerifier = void 0;
4
4
  const utilities_1 = require("./utilities");
5
5
  const role_based_token_verifier_1 = require("./role-based-token-verifier");
6
6
  class JwksUriTokenVerifier extends role_based_token_verifier_1.RoleBasedTokenVerifier {
7
+ issuer;
8
+ jwksUri;
9
+ buildClient;
10
+ buildKeyResolver;
11
+ verifyToken;
7
12
  constructor(issuer, jwksUri, rolesClaim, dependencies) {
8
- var _a, _b, _c;
9
13
  super(rolesClaim);
10
14
  this.issuer = issuer;
11
15
  this.jwksUri = jwksUri;
12
- this.buildClient = (_a = dependencies === null || dependencies === void 0 ? void 0 : dependencies.jwksClientFactory) !== null && _a !== void 0 ? _a : utilities_1.getJwksClient;
16
+ this.buildClient = dependencies?.jwksClientFactory ?? utilities_1.getJwksClient;
13
17
  this.buildKeyResolver =
14
- (_b = dependencies === null || dependencies === void 0 ? void 0 : dependencies.keyResolverBuilder) !== null && _b !== void 0 ? _b : ((client) => utilities_1.getKeyWithClient.bind(this, client));
15
- this.verifyToken = (_c = dependencies === null || dependencies === void 0 ? void 0 : dependencies.jwtVerifier) !== null && _c !== void 0 ? _c : utilities_1.verifyJWT;
18
+ dependencies?.keyResolverBuilder ?? ((client) => utilities_1.getKeyWithClient.bind(this, client));
19
+ this.verifyToken = dependencies?.jwtVerifier ?? utilities_1.verifyJWT;
16
20
  }
17
21
  async verify(token) {
18
22
  const client = this.buildClient(this.jwksUri);
@@ -4,12 +4,14 @@ exports.PublicKeyTokenVerifier = void 0;
4
4
  const utilities_1 = require("./utilities");
5
5
  const role_based_token_verifier_1 = require("./role-based-token-verifier");
6
6
  class PublicKeyTokenVerifier extends role_based_token_verifier_1.RoleBasedTokenVerifier {
7
+ issuer;
8
+ publicKeyResolver;
9
+ verifyToken;
7
10
  constructor(issuer, publicKeyResolver, rolesClaim, dependencies) {
8
- var _a;
9
11
  super(rolesClaim);
10
12
  this.issuer = issuer;
11
13
  this.publicKeyResolver = publicKeyResolver;
12
- this.verifyToken = (_a = dependencies === null || dependencies === void 0 ? void 0 : dependencies.jwtVerifier) !== null && _a !== void 0 ? _a : utilities_1.verifyJWT;
14
+ this.verifyToken = dependencies?.jwtVerifier ?? utilities_1.verifyJWT;
13
15
  }
14
16
  async verify(token) {
15
17
  const key = await this.publicKeyResolver;
@@ -15,12 +15,13 @@ function rolesFromTokenRole(rolesClaim) {
15
15
  });
16
16
  }
17
17
  class RoleBasedTokenVerifier {
18
+ rolesClaim;
18
19
  constructor(rolesClaim = exports.DEFAULT_ROLES_CLAIM) {
19
20
  this.rolesClaim = rolesClaim;
20
21
  }
21
22
  toUserEnvelope(decodedToken) {
22
23
  const payload = decodedToken.payload;
23
- const username = (payload === null || payload === void 0 ? void 0 : payload.email) || (payload === null || payload === void 0 ? void 0 : payload.phone_number) || payload.sub;
24
+ const username = payload?.email || payload?.phone_number || payload.sub;
24
25
  const id = payload.sub;
25
26
  const roles = rolesFromTokenRole(payload[this.rolesClaim]);
26
27
  return {
@@ -38,7 +38,7 @@ function getKeyWithClient(client, header, callback) {
38
38
  callback(err);
39
39
  return;
40
40
  }
41
- callback(null, key === null || key === void 0 ? void 0 : key.getPublicKey());
41
+ callback(null, key?.getPublicKey());
42
42
  });
43
43
  }
44
44
  /**
@@ -3,107 +3,114 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MagekSubscribersNotifier = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const common_1 = require("@magek/common");
6
+ const promises_1 = require("./utils/promises");
6
7
  const graphql = require("graphql");
7
8
  const graphql_generator_1 = require("./services/graphql/graphql-generator");
8
9
  const read_model_pub_sub_1 = require("./services/pub-sub/read-model-pub-sub");
9
10
  const instrumentation_1 = require("./instrumentation");
10
- class MagekSubscribersNotifier {
11
- constructor(config) {
12
- this.config = config;
13
- this.graphQLSchema = graphql_generator_1.GraphQLGenerator.generateSchema(config);
14
- }
15
- async dispatch(request) {
16
- const logger = (0, common_1.getLogger)(this.config, 'MagekSubscribersNotifier#dispatch');
17
- try {
18
- logger.debug('Received the following event for subscription dispatching: ', request);
19
- const readModelEnvelopes = await this.config.readModelStore.rawToEnvelopes(this.config, request);
20
- logger.debug('[SubsciptionDispatcher] The following ReadModels were updated: ', readModelEnvelopes);
21
- const subscriptions = await this.getSubscriptions(readModelEnvelopes);
22
- logger.debug('Found the following subscriptions for those read models: ', subscriptions);
23
- const pubSub = this.getPubSub(readModelEnvelopes);
24
- await common_1.Promises.allSettledAndFulfilled(subscriptions.map(this.runSubscriptionAndNotify.bind(this, pubSub)));
11
+ let MagekSubscribersNotifier = (() => {
12
+ let _instanceExtraInitializers = [];
13
+ let _dispatch_decorators;
14
+ return class MagekSubscribersNotifier {
15
+ static {
16
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
17
+ _dispatch_decorators = [(0, instrumentation_1.trace)(common_1.TraceActionTypes.DISPATCH_SUBSCRIBER_NOTIFIER)];
18
+ tslib_1.__esDecorate(this, null, _dispatch_decorators, { kind: "method", name: "dispatch", static: false, private: false, access: { has: obj => "dispatch" in obj, get: obj => obj.dispatch }, metadata: _metadata }, null, _instanceExtraInitializers);
19
+ if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
25
20
  }
26
- catch (e) {
27
- logger.error(e);
21
+ config = tslib_1.__runInitializers(this, _instanceExtraInitializers);
22
+ graphQLSchema;
23
+ constructor(config) {
24
+ this.config = config;
25
+ this.graphQLSchema = graphql_generator_1.GraphQLGenerator.generateSchema(config);
28
26
  }
29
- }
30
- getReadModelInstance(envelope) {
31
- const readModelMetadata = this.config.readModels[envelope.typeName];
32
- if (!readModelMetadata) {
33
- throw new Error('Could not get information about read model with name: ' + envelope.typeName);
27
+ async dispatch(request) {
28
+ const logger = (0, common_1.getLogger)(this.config, 'MagekSubscribersNotifier#dispatch');
29
+ try {
30
+ logger.debug('Received the following event for subscription dispatching: ', request);
31
+ const readModelEnvelopes = await this.config.readModelStore.rawToEnvelopes(this.config, request);
32
+ logger.debug('[SubsciptionDispatcher] The following ReadModels were updated: ', readModelEnvelopes);
33
+ const subscriptions = await this.getSubscriptions(readModelEnvelopes);
34
+ logger.debug('Found the following subscriptions for those read models: ', subscriptions);
35
+ const pubSub = this.getPubSub(readModelEnvelopes);
36
+ await promises_1.Promises.allSettledAndFulfilled(subscriptions.map(this.runSubscriptionAndNotify.bind(this, pubSub)));
37
+ }
38
+ catch (e) {
39
+ logger.error(e);
40
+ }
34
41
  }
35
- const readModelInstance = new readModelMetadata.class();
36
- Object.assign(readModelInstance, envelope.value);
37
- return readModelInstance;
38
- }
39
- async getSubscriptions(readModelEnvelopes) {
40
- const readModelNames = readModelEnvelopes.map((readModelEnvelope) => readModelEnvelope.typeName);
41
- const readModelUniqueNames = [...new Set(readModelNames)];
42
- const subscriptionSets = await Promise.all(readModelUniqueNames.map((name) => this.config.sessionStore.fetchSubscriptionsByClassName(this.config, name)));
43
- return subscriptionSets.flat();
44
- }
45
- getPubSub(readModelEnvelopes) {
46
- const readModelInstances = readModelEnvelopes.map(this.getReadModelInstance, this);
47
- return new read_model_pub_sub_1.FilteredReadModelPubSub(readModelInstances);
48
- }
49
- async runSubscriptionAndNotify(pubSub, subscription) {
50
- const logger = (0, common_1.getLogger)(this.config, 'MagekSubscribersNotifier#runSubscriptionAndNotify');
51
- const context = {
52
- connectionID: subscription.connectionID,
53
- responseHeaders: {},
54
- requestID: subscription.requestID,
55
- user: subscription.currentUser,
56
- operation: subscription.operation,
57
- pubSub,
58
- storeSubscriptions: false, // We don't store the subscription again, just get the result now
59
- };
60
- const document = this.parseSubscriptionQuery(subscription.operation.query);
61
- logger.debug('Running subscription with context: ', context);
62
- const iterator = await graphql.subscribe({
63
- contextValue: context,
64
- document: document,
65
- schema: this.graphQLSchema,
66
- variableValues: subscription.operation.variables,
67
- });
68
- if ('next' in iterator) {
69
- // It is an AsyncIterator
70
- return this.processSubscriptionsIterator(iterator, subscription);
42
+ getReadModelInstance(envelope) {
43
+ const readModelMetadata = this.config.readModels[envelope.typeName];
44
+ if (!readModelMetadata) {
45
+ throw new Error('Could not get information about read model with name: ' + envelope.typeName);
46
+ }
47
+ const readModelInstance = new readModelMetadata.class();
48
+ Object.assign(readModelInstance, envelope.value);
49
+ return readModelInstance;
71
50
  }
72
- // If "subscribe" returns an ExecutionResult (instead of an async iterator) the subscription failed.
73
- throw iterator.errors;
74
- }
75
- parseSubscriptionQuery(query) {
76
- const document = graphql.parse(query);
77
- // We probably don't need to validate this again, as it was validated before storing it. BUT! It's always better to fail early
78
- const errors = graphql.validate(this.graphQLSchema, document);
79
- if (errors.length > 0) {
80
- throw errors;
51
+ async getSubscriptions(readModelEnvelopes) {
52
+ const readModelNames = readModelEnvelopes.map((readModelEnvelope) => readModelEnvelope.typeName);
53
+ const readModelUniqueNames = [...new Set(readModelNames)];
54
+ const subscriptionSets = await Promise.all(readModelUniqueNames.map((name) => this.config.sessionStore.fetchSubscriptionsByClassName(this.config, name)));
55
+ return subscriptionSets.flat();
81
56
  }
82
- return document;
83
- }
84
- async processSubscriptionsIterator(iterator, subscription) {
85
- const notificationPromises = [];
86
- for await (const result of iterator) {
87
- notificationPromises.push(this.notifyWithGraphQLResult(subscription, result));
57
+ getPubSub(readModelEnvelopes) {
58
+ const readModelInstances = readModelEnvelopes.map(this.getReadModelInstance, this);
59
+ return new read_model_pub_sub_1.FilteredReadModelPubSub(readModelInstances);
88
60
  }
89
- return Promise.all(notificationPromises);
90
- }
91
- async notifyWithGraphQLResult(subscription, result) {
92
- const logger = (0, common_1.getLogger)(this.config, 'MagekSubscribersNotifier#notifyWithGraphQLResult');
93
- if (result.errors) {
94
- throw result.errors;
61
+ async runSubscriptionAndNotify(pubSub, subscription) {
62
+ const logger = (0, common_1.getLogger)(this.config, 'MagekSubscribersNotifier#runSubscriptionAndNotify');
63
+ const context = {
64
+ connectionID: subscription.connectionID,
65
+ responseHeaders: {},
66
+ requestID: subscription.requestID,
67
+ user: subscription.currentUser,
68
+ operation: subscription.operation,
69
+ pubSub,
70
+ storeSubscriptions: false, // We don't store the subscription again, just get the result now
71
+ };
72
+ const document = this.parseSubscriptionQuery(subscription.operation.query);
73
+ logger.debug('Running subscription with context: ', context);
74
+ const iterator = await graphql.subscribe({
75
+ contextValue: context,
76
+ document: document,
77
+ schema: this.graphQLSchema,
78
+ variableValues: subscription.operation.variables,
79
+ });
80
+ if ('next' in iterator) {
81
+ // It is an AsyncIterator
82
+ return this.processSubscriptionsIterator(iterator, subscription);
83
+ }
84
+ // If "subscribe" returns an ExecutionResult (instead of an async iterator) the subscription failed.
85
+ throw iterator.errors;
95
86
  }
96
- const readModel = result.data;
97
- const message = new common_1.GraphQLData(subscription.operation.id, { data: readModel });
98
- logger.debug(`Notifying connectionID '${subscription.connectionID}' with the following wrappeed read model: `, readModel);
99
- await this.config.runtime.messaging.sendMessage(this.config, subscription.connectionID, message);
100
- logger.debug('Notifications sent');
101
- }
102
- }
87
+ parseSubscriptionQuery(query) {
88
+ const document = graphql.parse(query);
89
+ // We probably don't need to validate this again, as it was validated before storing it. BUT! It's always better to fail early
90
+ const errors = graphql.validate(this.graphQLSchema, document);
91
+ if (errors.length > 0) {
92
+ throw errors;
93
+ }
94
+ return document;
95
+ }
96
+ async processSubscriptionsIterator(iterator, subscription) {
97
+ const notificationPromises = [];
98
+ for await (const result of iterator) {
99
+ notificationPromises.push(this.notifyWithGraphQLResult(subscription, result));
100
+ }
101
+ return Promise.all(notificationPromises);
102
+ }
103
+ async notifyWithGraphQLResult(subscription, result) {
104
+ const logger = (0, common_1.getLogger)(this.config, 'MagekSubscribersNotifier#notifyWithGraphQLResult');
105
+ if (result.errors) {
106
+ throw result.errors;
107
+ }
108
+ const readModel = result.data;
109
+ const message = new common_1.GraphQLData(subscription.operation.id, { data: readModel });
110
+ logger.debug(`Notifying connectionID '${subscription.connectionID}' with the following wrappeed read model: `, readModel);
111
+ await this.config.runtime.messaging.sendMessage(this.config, subscription.connectionID, message);
112
+ logger.debug('Notifications sent');
113
+ }
114
+ };
115
+ })();
103
116
  exports.MagekSubscribersNotifier = MagekSubscribersNotifier;
104
- tslib_1.__decorate([
105
- (0, instrumentation_1.Trace)(common_1.TraceActionTypes.DISPATCH_SUBSCRIBER_NOTIFIER),
106
- tslib_1.__metadata("design:type", Function),
107
- tslib_1.__metadata("design:paramtypes", [Object]),
108
- tslib_1.__metadata("design:returntype", Promise)
109
- ], MagekSubscribersNotifier.prototype, "dispatch", null);
@@ -4,6 +4,7 @@ exports.MagekTokenVerifier = void 0;
4
4
  const common_1 = require("@magek/common");
5
5
  const jsonwebtoken_1 = require("jsonwebtoken");
6
6
  class MagekTokenVerifier {
7
+ config;
7
8
  constructor(config) {
8
9
  this.config = config;
9
10
  }
@@ -36,7 +37,7 @@ class MagekTokenVerifier {
36
37
  }
37
38
  getErrors(results) {
38
39
  return results
39
- .filter((result) => (result === null || result === void 0 ? void 0 : result.status) && (result === null || result === void 0 ? void 0 : result.status) !== 'fulfilled')
40
+ .filter((result) => result?.status && result?.status !== 'fulfilled')
40
41
  .map((result) => result);
41
42
  }
42
43
  static joinReasons(errors) {