@magek/core 0.0.6 → 0.0.7

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 (100) 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 +50 -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 +3 -0
  34. package/dist/decorators/index.js +2 -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/role.d.ts +9 -3
  48. package/dist/decorators/role.js +8 -3
  49. package/dist/decorators/scheduled-command.d.ts +4 -1
  50. package/dist/decorators/scheduled-command.js +3 -1
  51. package/dist/decorators/schema-migration.d.ts +11 -27
  52. package/dist/decorators/schema-migration.js +32 -77
  53. package/dist/decorators/sequenced-by.d.ts +7 -25
  54. package/dist/decorators/sequenced-by.js +11 -71
  55. package/dist/event-dispatcher.js +29 -24
  56. package/dist/event-processor.js +106 -103
  57. package/dist/event-stream-consumer.js +25 -20
  58. package/dist/event-stream-producer.js +22 -17
  59. package/dist/events-reader.js +1 -0
  60. package/dist/global-error-dispatcher.js +3 -2
  61. package/dist/graphql-dispatcher.js +161 -156
  62. package/dist/index.js +4 -0
  63. package/dist/instrumentation/decorator/trace.d.ts +11 -3
  64. package/dist/instrumentation/decorator/trace.js +17 -71
  65. package/dist/magek.js +2 -2
  66. package/dist/query-dispatcher.js +2 -0
  67. package/dist/read-model-schema-migrator.js +71 -68
  68. package/dist/read-models-reader.js +178 -180
  69. package/dist/register-handler.js +3 -3
  70. package/dist/scheduled-command-dispatcher.js +48 -42
  71. package/dist/schema-migrator.js +63 -59
  72. package/dist/sensor/health/health-service.js +2 -1
  73. package/dist/services/event-store.js +221 -224
  74. package/dist/services/graphql/graphql-generator.js +11 -8
  75. package/dist/services/graphql/graphql-mutation-generator.js +4 -0
  76. package/dist/services/graphql/graphql-query-generator.js +14 -0
  77. package/dist/services/graphql/graphql-subcriptions-generator.js +7 -0
  78. package/dist/services/graphql/graphql-type-informer.js +4 -3
  79. package/dist/services/graphql/query-generators/graphql-query-by-keys-generator.js +4 -0
  80. package/dist/services/graphql/query-generators/graphql-query-events-generator.js +3 -0
  81. package/dist/services/graphql/query-generators/graphql-query-filters-generator.js +6 -0
  82. package/dist/services/graphql/query-generators/graphql-query-generator.js +4 -0
  83. package/dist/services/graphql/query-generators/graphql-query-listed-generator.js +7 -0
  84. package/dist/services/graphql/query-helpers/graphql-handled-fields-generator.js +5 -2
  85. package/dist/services/graphql/query-helpers/graphql-query-filter-arguments-builder.js +3 -0
  86. package/dist/services/graphql/query-helpers/graphql-query-filter-fields-builder.js +4 -0
  87. package/dist/services/graphql/query-helpers/graphql-query-sort-builder.js +4 -2
  88. package/dist/services/graphql/websocket-protocol/graphql-websocket-protocol.js +5 -3
  89. package/dist/services/pub-sub/read-model-pub-sub.js +1 -0
  90. package/dist/services/raw-events-parser.js +1 -1
  91. package/dist/services/read-model-store.js +16 -17
  92. package/dist/services/token-verifiers/jwks-uri-token-verifier.js +8 -4
  93. package/dist/services/token-verifiers/public-key-token-verifier.js +4 -2
  94. package/dist/services/token-verifiers/role-based-token-verifier.js +2 -1
  95. package/dist/services/token-verifiers/utilities.js +1 -1
  96. package/dist/subscribers-notifier.js +98 -92
  97. package/dist/token-verifier.js +2 -1
  98. package/package.json +4 -4
  99. package/dist/decorators/stage3-utils.d.ts +0 -6
  100. 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}`;
@@ -6,6 +6,7 @@ const global_error_dispatcher_1 = require("../global-error-dispatcher");
6
6
  const read_model_searcher_1 = require("./read-model-searcher");
7
7
  const read_model_schema_migrator_1 = require("../read-model-schema-migrator");
8
8
  class ReadModelStore {
9
+ config;
9
10
  constructor(config) {
10
11
  this.config = config;
11
12
  }
@@ -82,7 +83,7 @@ class ReadModelStore {
82
83
  getUnProjections(entitySnapshotEnvelope) {
83
84
  const unProjections = this.entityUnProjections(entitySnapshotEnvelope);
84
85
  const projections = this.entityProjections(entitySnapshotEnvelope);
85
- if ((projections === null || projections === void 0 ? void 0 : projections.length) > 0) {
86
+ if (projections?.length > 0) {
86
87
  if (!unProjections) {
87
88
  throw new Error(`Missing UnProjections for entity ${entitySnapshotEnvelope.entityTypeName}`);
88
89
  }
@@ -139,46 +140,45 @@ class ReadModelStore {
139
140
  const entitiesJoinKeys = Array.isArray(entityJoinKey) ? entityJoinKey : [entityJoinKey];
140
141
  // 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
142
  for (const readModelId of entitiesJoinKeys) {
142
- const readModel = (currentReadModel === null || currentReadModel === void 0 ? void 0 : currentReadModel.id) === readModelId ? currentReadModel : undefined;
143
+ const readModel = currentReadModel?.id === readModelId ? currentReadModel : undefined;
143
144
  projections.push(this.projectAndStoreReadModelWithRetry(entitySnapshotEnvelope, readModelName, sequenceKey, entityInstance, projectionMetadata, deleteEvent, readModelId, readModel));
144
145
  }
145
146
  }
146
147
  else {
147
148
  // 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));
149
+ projections.push(this.projectAndStoreReadModelWithRetry(entitySnapshotEnvelope, readModelName, sequenceKey, entityInstance, projectionMetadata, deleteEvent, currentReadModel?.id, currentReadModel));
149
150
  }
150
151
  return projections;
151
152
  }
152
153
  async projectAndStoreReadModelWithRetry(entitySnapshotEnvelope, readModelName, sequenceKey, entityInstance, projectionMetadata, deleteEvent, readModelId, currentReadModel) {
153
154
  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}` : '');
155
+ 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
156
  return (0, common_1.retryIfError)((tryNumber) => this.applyProjectionToReadModel(entitySnapshotEnvelope, entityInstance, projectionMetadata, deleteEvent, currentReadModel, entitySnapshotEnvelope, readModelId, sequenceKey, tryNumber), common_1.OptimisticConcurrencyUnexpectedVersionError, logger);
156
157
  }
157
158
  instanceReadModels(readModelName, rawReadModels) {
158
- if (!(rawReadModels === null || rawReadModels === void 0 ? void 0 : rawReadModels.length)) {
159
+ if (!rawReadModels?.length) {
159
160
  return [];
160
161
  }
161
162
  const readModelMetadata = this.config.readModels[readModelName];
162
163
  return rawReadModels.map((rawReadModel) => (0, common_1.createInstance)(readModelMetadata.class, rawReadModel));
163
164
  }
164
165
  async applyProjectionToReadModel(entitySnapshotEnvelope, entity, projectionMetadata, deleteEvent, currentReadModel, lastProjectedEntity, currentReadModelID, sequenceKey, tryNumber) {
165
- var _a, _b, _c, _d, _e, _f;
166
166
  const logger = (0, common_1.getLogger)(this.config, 'ReadModelStore#applyProjectionToReadModel');
167
167
  const readModelName = projectionMetadata.class.name;
168
- const readModelID = currentReadModelID !== null && currentReadModelID !== void 0 ? currentReadModelID : currentReadModel === null || currentReadModel === void 0 ? void 0 : currentReadModel.id;
168
+ const readModelID = currentReadModelID ?? currentReadModel?.id;
169
169
  if (tryNumber && tryNumber > 1) {
170
170
  // 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}` +
171
+ 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
172
  (sequenceKey ? ` and sequence key ${sequenceKey.name} = ${sequenceKey.value}` : ''));
173
173
  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}` +
174
+ logger.debug(`Current read model ${readModelName} with ID ${readModelID} updated with version = ${currentReadModel?.magekMetadata?.version}` +
175
175
  (sequenceKey ? ` and sequence key ${sequenceKey.name} = ${sequenceKey.value}` : ''));
176
176
  }
177
177
  let migratedReadModel;
178
178
  if (currentReadModel) {
179
179
  migratedReadModel = await new read_model_schema_migrator_1.ReadModelSchemaMigrator(this.config).migrate(currentReadModel, readModelName);
180
180
  }
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;
181
+ const currentDatabaseVersion = migratedReadModel?.magekMetadata?.version ?? 0;
182
182
  let newReadModel;
183
183
  const projectionInfo = {
184
184
  reason: deleteEvent ? common_1.ProjectionInfoReason.ENTITY_DELETED : common_1.ProjectionInfoReason.ENTITY_PROJECTED,
@@ -192,31 +192,30 @@ class ReadModelStore {
192
192
  if (error)
193
193
  throw error;
194
194
  }
195
- if (newReadModel === common_1.ReadModelAction.Delete) {
195
+ if (newReadModel === common_1.ProjectionAction.Delete) {
196
196
  logger.debug(`Deleting read model ${readModelName} with ID ${readModelID}:`, migratedReadModel);
197
197
  return this.config.readModelStore.delete(this.config, readModelName, readModelID);
198
198
  }
199
- else if (newReadModel === common_1.ReadModelAction.Nothing) {
199
+ else if (newReadModel === common_1.ProjectionAction.Skip) {
200
200
  logger.debug(`Skipping actions for ${readModelName} with ID ${readModelID}:`, newReadModel);
201
201
  return;
202
202
  }
203
203
  return await this.store(entity, projectionMetadata, readModelID, readModelName, migratedReadModel, newReadModel, currentDatabaseVersion, lastProjectedEntity);
204
204
  }
205
205
  async store(entity, projectionMetadata, readModelID, readModelName, migratedReadModel, newReadModel, expectedCurrentDatabaseVersion, lastProjectedEntity) {
206
- var _a, _b;
207
206
  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);
207
+ const schemaVersion = migratedReadModel?.magekMetadata?.schemaVersion ?? this.config.currentVersionFor(readModelName);
209
208
  // Increment the read model version in 1 before storing
210
209
  const newReadModelVersion = expectedCurrentDatabaseVersion + 1;
211
210
  newReadModel.magekMetadata = {
212
- ...migratedReadModel === null || migratedReadModel === void 0 ? void 0 : migratedReadModel.magekMetadata,
211
+ ...migratedReadModel?.magekMetadata,
213
212
  version: newReadModelVersion,
214
213
  schemaVersion: schemaVersion,
215
214
  lastUpdateAt: new Date().toISOString(),
216
215
  lastProjectionInfo: {
217
216
  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,
217
+ entityName: lastProjectedEntity?.entityTypeName,
218
+ entityUpdatedAt: lastProjectedEntity?.createdAt,
220
219
  projectionMethod: `${projectionMetadata.class.name}.${projectionMetadata.methodName}`,
221
220
  },
222
221
  };
@@ -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
  /**
@@ -7,103 +7,109 @@ const graphql = require("graphql");
7
7
  const graphql_generator_1 = require("./services/graphql/graphql-generator");
8
8
  const read_model_pub_sub_1 = require("./services/pub-sub/read-model-pub-sub");
9
9
  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)));
10
+ let MagekSubscribersNotifier = (() => {
11
+ let _instanceExtraInitializers = [];
12
+ let _dispatch_decorators;
13
+ return class MagekSubscribersNotifier {
14
+ static {
15
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
16
+ _dispatch_decorators = [(0, instrumentation_1.trace)(common_1.TraceActionTypes.DISPATCH_SUBSCRIBER_NOTIFIER)];
17
+ 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);
18
+ if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
25
19
  }
26
- catch (e) {
27
- logger.error(e);
20
+ config = tslib_1.__runInitializers(this, _instanceExtraInitializers);
21
+ graphQLSchema;
22
+ constructor(config) {
23
+ this.config = config;
24
+ this.graphQLSchema = graphql_generator_1.GraphQLGenerator.generateSchema(config);
28
25
  }
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);
26
+ async dispatch(request) {
27
+ const logger = (0, common_1.getLogger)(this.config, 'MagekSubscribersNotifier#dispatch');
28
+ try {
29
+ logger.debug('Received the following event for subscription dispatching: ', request);
30
+ const readModelEnvelopes = await this.config.readModelStore.rawToEnvelopes(this.config, request);
31
+ logger.debug('[SubsciptionDispatcher] The following ReadModels were updated: ', readModelEnvelopes);
32
+ const subscriptions = await this.getSubscriptions(readModelEnvelopes);
33
+ logger.debug('Found the following subscriptions for those read models: ', subscriptions);
34
+ const pubSub = this.getPubSub(readModelEnvelopes);
35
+ await common_1.Promises.allSettledAndFulfilled(subscriptions.map(this.runSubscriptionAndNotify.bind(this, pubSub)));
36
+ }
37
+ catch (e) {
38
+ logger.error(e);
39
+ }
34
40
  }
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);
41
+ getReadModelInstance(envelope) {
42
+ const readModelMetadata = this.config.readModels[envelope.typeName];
43
+ if (!readModelMetadata) {
44
+ throw new Error('Could not get information about read model with name: ' + envelope.typeName);
45
+ }
46
+ const readModelInstance = new readModelMetadata.class();
47
+ Object.assign(readModelInstance, envelope.value);
48
+ return readModelInstance;
71
49
  }
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;
50
+ async getSubscriptions(readModelEnvelopes) {
51
+ const readModelNames = readModelEnvelopes.map((readModelEnvelope) => readModelEnvelope.typeName);
52
+ const readModelUniqueNames = [...new Set(readModelNames)];
53
+ const subscriptionSets = await Promise.all(readModelUniqueNames.map((name) => this.config.sessionStore.fetchSubscriptionsByClassName(this.config, name)));
54
+ return subscriptionSets.flat();
81
55
  }
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));
56
+ getPubSub(readModelEnvelopes) {
57
+ const readModelInstances = readModelEnvelopes.map(this.getReadModelInstance, this);
58
+ return new read_model_pub_sub_1.FilteredReadModelPubSub(readModelInstances);
88
59
  }
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;
60
+ async runSubscriptionAndNotify(pubSub, subscription) {
61
+ const logger = (0, common_1.getLogger)(this.config, 'MagekSubscribersNotifier#runSubscriptionAndNotify');
62
+ const context = {
63
+ connectionID: subscription.connectionID,
64
+ responseHeaders: {},
65
+ requestID: subscription.requestID,
66
+ user: subscription.currentUser,
67
+ operation: subscription.operation,
68
+ pubSub,
69
+ storeSubscriptions: false, // We don't store the subscription again, just get the result now
70
+ };
71
+ const document = this.parseSubscriptionQuery(subscription.operation.query);
72
+ logger.debug('Running subscription with context: ', context);
73
+ const iterator = await graphql.subscribe({
74
+ contextValue: context,
75
+ document: document,
76
+ schema: this.graphQLSchema,
77
+ variableValues: subscription.operation.variables,
78
+ });
79
+ if ('next' in iterator) {
80
+ // It is an AsyncIterator
81
+ return this.processSubscriptionsIterator(iterator, subscription);
82
+ }
83
+ // If "subscribe" returns an ExecutionResult (instead of an async iterator) the subscription failed.
84
+ throw iterator.errors;
95
85
  }
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
- }
86
+ parseSubscriptionQuery(query) {
87
+ const document = graphql.parse(query);
88
+ // We probably don't need to validate this again, as it was validated before storing it. BUT! It's always better to fail early
89
+ const errors = graphql.validate(this.graphQLSchema, document);
90
+ if (errors.length > 0) {
91
+ throw errors;
92
+ }
93
+ return document;
94
+ }
95
+ async processSubscriptionsIterator(iterator, subscription) {
96
+ const notificationPromises = [];
97
+ for await (const result of iterator) {
98
+ notificationPromises.push(this.notifyWithGraphQLResult(subscription, result));
99
+ }
100
+ return Promise.all(notificationPromises);
101
+ }
102
+ async notifyWithGraphQLResult(subscription, result) {
103
+ const logger = (0, common_1.getLogger)(this.config, 'MagekSubscribersNotifier#notifyWithGraphQLResult');
104
+ if (result.errors) {
105
+ throw result.errors;
106
+ }
107
+ const readModel = result.data;
108
+ const message = new common_1.GraphQLData(subscription.operation.id, { data: readModel });
109
+ logger.debug(`Notifying connectionID '${subscription.connectionID}' with the following wrappeed read model: `, readModel);
110
+ await this.config.runtime.messaging.sendMessage(this.config, subscription.connectionID, message);
111
+ logger.debug('Notifications sent');
112
+ }
113
+ };
114
+ })();
103
115
  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) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@magek/core",
3
- "version": "0.0.6",
3
+ "version": "0.0.7",
4
4
  "description": "Library for your Magek apps",
5
5
  "author": "Boosterin Labs SLU",
6
6
  "homepage": "https://magek.ai",
@@ -23,19 +23,19 @@
23
23
  "node": ">=22.0.0 <23.0.0"
24
24
  },
25
25
  "dependencies": {
26
- "@magek/common": "^0.0.6",
26
+ "@magek/common": "^0.0.7",
27
27
  "fp-ts": "2.16.11",
28
28
  "graphql-scalars": "1.25.0",
29
29
  "inflected": "2.1.0",
30
30
  "iterall": "1.3.0",
31
31
  "jsonwebtoken": "9.0.3",
32
- "jwks-rsa": "3.2.1",
32
+ "jwks-rsa": "3.2.2",
33
33
  "tslib": "2.8.1",
34
34
  "validator": "13.15.26",
35
35
  "fast-check": "4.5.3"
36
36
  },
37
37
  "devDependencies": {
38
- "@magek/eslint-config": "^0.0.6",
38
+ "@magek/eslint-config": "^0.0.7",
39
39
  "@types/chai": "5.2.3",
40
40
  "@types/chai-as-promised": "8.0.2",
41
41
  "@types/inflected": "2.1.3",
@@ -1,6 +0,0 @@
1
- /**
2
- * Transfer field metadata from Stage 3 decorator context.metadata to the class constructor.
3
- * This is needed because Symbol.metadata is not available in Node.js, so Stage 3 decorators
4
- * need an explicit step to make field metadata accessible on the class.
5
- */
6
- export declare function transferStage3FieldMetadata(classType: Function, contextMetadata: Record<string | symbol, unknown>): void;