@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
@@ -1,36 +1,20 @@
1
- import { Class, AnyClass, Instance } from '@magek/common';
2
- /**
3
- * Stage 3 method decorator context
4
- */
5
- interface Stage3MethodContext {
6
- kind: 'method';
7
- name: string | symbol;
8
- static: boolean;
9
- private: boolean;
10
- metadata: Record<string | symbol, unknown>;
11
- addInitializer?: (initializer: () => void) => void;
12
- }
13
- /**
14
- * Stage 3 class decorator context
15
- */
16
- interface Stage3ClassContext {
17
- kind: 'class';
18
- name: string | undefined;
19
- metadata: Record<string | symbol, unknown>;
20
- addInitializer?: (initializer: () => void) => void;
21
- }
1
+ import { Class, AnyClass } from '@magek/common';
2
+ import { MethodDecoratorContext, ClassDecoratorContext } from './decorator-types';
22
3
  /**
23
4
  * **NOTE:** Using this decorator for read model migrations is deprecated. Prefer using `@DataMigration` instead.
5
+ *
6
+ * Uses TC39 Stage 3 decorators.
24
7
  */
25
- export declare function SchemaMigration(conceptClass: AnyClass): (schemaMigrationClass: AnyClass, context?: Stage3ClassContext) => void;
8
+ export declare function SchemaMigration(conceptClass: AnyClass): (schemaMigrationClass: AnyClass, context: ClassDecoratorContext) => void;
26
9
  /**
27
- * Decorator to tell Magek the version you are migrating to
10
+ * Decorator to tell Magek the version you are migrating to.
11
+ *
12
+ * Uses TC39 Stage 3 decorators.
13
+ *
28
14
  * @param toVersion
29
15
  * @param props
30
16
  */
31
- export declare function ToVersion<TOldSchema, TNewSchema>(toVersion: number, props: {
17
+ export declare function toVersion<TOldSchema, TNewSchema>(toVersion: number, props: {
32
18
  fromSchema: Class<TOldSchema>;
33
19
  toSchema: Class<TNewSchema>;
34
- }): (migrationInstanceOrMethod: Instance | Function, propertyNameOrContext: string | Stage3MethodContext, propertyDescriptor?: MigrationMethod<TOldSchema, TNewSchema>) => void;
35
- type MigrationMethod<TOldSchema, TNewSchema> = TypedPropertyDescriptor<(old: TOldSchema) => Promise<TNewSchema>>;
36
- export {};
20
+ }): (method: Function, context: MethodDecoratorContext) => void;
@@ -1,43 +1,24 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SchemaMigration = SchemaMigration;
4
- exports.ToVersion = ToVersion;
4
+ exports.toVersion = toVersion;
5
5
  const magek_1 = require("../magek");
6
6
  const common_1 = require("@magek/common");
7
7
  const migrationMethodsMetadataKey = 'magek:migrationsMethods';
8
- /**
9
- * Type guard to detect Stage 3 method decorator context
10
- */
11
- function isStage3MethodContext(arg) {
12
- return (arg !== null &&
13
- typeof arg === 'object' &&
14
- 'kind' in arg &&
15
- arg.kind === 'method' &&
16
- 'name' in arg);
17
- }
18
- /**
19
- * Type guard to detect Stage 3 class decorator context
20
- */
21
- function isStage3ClassContext(arg) {
22
- return (arg !== null &&
23
- typeof arg === 'object' &&
24
- 'kind' in arg &&
25
- arg.kind === 'class' &&
26
- 'metadata' in arg);
27
- }
28
- // Symbol for storing migration metadata in Stage 3 decorator context.metadata
8
+ // Symbol for storing migration metadata in decorator context.metadata
29
9
  const MIGRATIONS_METADATA_KEY = Symbol.for('magek:migrationsMethods');
30
10
  /**
31
11
  * **NOTE:** Using this decorator for read model migrations is deprecated. Prefer using `@DataMigration` instead.
12
+ *
13
+ * Uses TC39 Stage 3 decorators.
32
14
  */
33
15
  function SchemaMigration(conceptClass) {
34
16
  return (schemaMigrationClass, context) => {
35
17
  magek_1.Magek.configureCurrentEnv((config) => {
36
18
  const conceptMigrations = getConceptMigrations(config, conceptClass);
37
- // Get migration methods - for Stage 3, read from context.metadata first
19
+ // Get migration methods from context.metadata
38
20
  let migrationMethodsMetadata;
39
- if (isStage3ClassContext(context)) {
40
- // Stage 3: read from context.metadata
21
+ if (context.metadata) {
41
22
  migrationMethodsMetadata =
42
23
  context.metadata[MIGRATIONS_METADATA_KEY] || [];
43
24
  // Update each metadata entry with the actual class reference
@@ -47,11 +28,10 @@ function SchemaMigration(conceptClass) {
47
28
  }));
48
29
  }
49
30
  else {
50
- // Legacy: read from Reflect.getMetadata
51
- migrationMethodsMetadata = getMigrationMethods(schemaMigrationClass);
31
+ migrationMethodsMetadata = [];
52
32
  }
53
33
  if (!migrationMethodsMetadata || migrationMethodsMetadata.length === 0) {
54
- throw new Error('No migration methods found in this class. Define at least one migration and annotate it with @ToVersion()');
34
+ throw new Error('No migration methods found in this class. Define at least one migration and annotate it with @toVersion()');
55
35
  }
56
36
  for (const schemaMigrationMetadata of migrationMethodsMetadata) {
57
37
  if (conceptMigrations.has(schemaMigrationMetadata.toVersion)) {
@@ -69,27 +49,21 @@ function getConceptMigrations(config, conceptClass) {
69
49
  }
70
50
  return config.schemaMigrations[conceptClass.name];
71
51
  }
72
- function getMigrationMethods(migrationClass) {
73
- const migrationMethods = (0, common_1.getMetadata)(migrationMethodsMetadataKey, migrationClass);
74
- if (!migrationMethods || migrationMethods.length == 0) {
75
- throw new Error('No migration methods found in this class. Define at least one migration and annotate it with @ToVersion()');
76
- }
77
- return migrationMethods;
78
- }
79
52
  /**
80
- * Decorator to tell Magek the version you are migrating to
53
+ * Decorator to tell Magek the version you are migrating to.
54
+ *
55
+ * Uses TC39 Stage 3 decorators.
56
+ *
81
57
  * @param toVersion
82
58
  * @param props
83
59
  */
84
- function ToVersion(toVersion, props) {
60
+ function toVersion(toVersion, props) {
85
61
  if (toVersion <= 1) {
86
62
  throw new Error('Migration versions must always be greater than 1');
87
63
  }
88
- return (migrationInstanceOrMethod, propertyNameOrContext) => {
89
- // Detect Stage 3 vs Legacy decorator
90
- if (isStage3MethodContext(propertyNameOrContext)) {
91
- // Stage 3 decorator - store in context.metadata so @SchemaMigration can read it
92
- const context = propertyNameOrContext;
64
+ return (_method, context) => {
65
+ // Stage 3 decorator - store in context.metadata so @SchemaMigration can read it
66
+ if (context.metadata) {
93
67
  // Get or initialize the migrations array in context.metadata
94
68
  let migrationMethods = context.metadata[MIGRATIONS_METADATA_KEY];
95
69
  if (!migrationMethods) {
@@ -104,43 +78,24 @@ function ToVersion(toVersion, props) {
104
78
  fromSchema: props.fromSchema,
105
79
  toSchema: props.toSchema,
106
80
  });
107
- // Also store in Reflect metadata for the standalone test case
108
- if (context.addInitializer) {
109
- context.addInitializer(function () {
110
- const migrationClass = context.static ? this : this.constructor;
111
- let reflectMethods = (0, common_1.getMetadata)(migrationMethodsMetadataKey, migrationClass);
112
- if (!reflectMethods) {
113
- reflectMethods = [];
114
- }
115
- reflectMethods.push({
116
- migrationClass,
117
- methodName: context.name.toString(),
118
- toVersion,
119
- fromSchema: props.fromSchema,
120
- toSchema: props.toSchema,
121
- });
122
- (0, common_1.defineMetadata)(migrationMethodsMetadataKey, reflectMethods, migrationClass);
123
- });
124
- }
125
81
  }
126
- else {
127
- // Legacy decorator
128
- const migrationInstance = migrationInstanceOrMethod;
129
- const propertyName = propertyNameOrContext;
130
- const migrationClass = migrationInstance.constructor;
131
- let migrationMethods = (0, common_1.getMetadata)(migrationMethodsMetadataKey, migrationClass);
132
- if (!migrationMethods) {
133
- migrationMethods = [];
134
- }
135
- migrationMethods.push({
136
- migrationClass,
137
- methodName: propertyName,
138
- toVersion,
139
- fromSchema: props.fromSchema,
140
- toSchema: props.toSchema,
82
+ // Also store in Reflect metadata for standalone usage
83
+ if (context.addInitializer) {
84
+ context.addInitializer(function () {
85
+ const migrationClass = context.static ? this : this.constructor;
86
+ let reflectMethods = (0, common_1.getMetadata)(migrationMethodsMetadataKey, migrationClass);
87
+ if (!reflectMethods) {
88
+ reflectMethods = [];
89
+ }
90
+ reflectMethods.push({
91
+ migrationClass,
92
+ methodName: context.name.toString(),
93
+ toVersion,
94
+ fromSchema: props.fromSchema,
95
+ toSchema: props.toSchema,
96
+ });
97
+ (0, common_1.defineMetadata)(migrationMethodsMetadataKey, reflectMethods, migrationClass);
141
98
  });
142
- // Here we just store the information (version and method). All the checks will be done in the @Migrates decorator
143
- (0, common_1.defineMetadata)(migrationMethodsMetadataKey, migrationMethods, migrationClass);
144
99
  }
145
100
  };
146
101
  }
@@ -1,28 +1,10 @@
1
- import { Class, ReadModelInterface, AnyClass } from '@magek/common';
2
- /**
3
- * Stage 3 field decorator context
4
- */
5
- interface Stage3FieldContext {
6
- kind: 'field';
7
- name: string | symbol;
8
- static: boolean;
9
- private: boolean;
10
- metadata: Record<string | symbol, unknown>;
11
- access?: {
12
- get: () => unknown;
13
- set: (value: unknown) => void;
14
- };
15
- addInitializer?: (initializer: () => void) => void;
16
- }
1
+ import { FieldDecoratorContext } from './decorator-types';
2
+ /** Symbol for storing sequence key in decorator context.metadata */
3
+ export declare const SEQUENCE_KEY_SYMBOL: unique symbol;
17
4
  /**
18
5
  * Decorator to specify the sequencing key for a ReadModel.
19
- * Can be used as both a parameter decorator and property decorator.
20
- * Supports both legacy (experimentalDecorators) and Stage 3 decorators.
21
- */
22
- export declare function sequencedBy(target: Class<ReadModelInterface> | Object | undefined, propertyKeyOrContext?: string | symbol | Stage3FieldContext, parameterIndex?: number): void;
23
- /**
24
- * Transfer sequence key metadata from Stage 3 context to class.
25
- * Called by the ReadModel class decorator.
6
+ *
7
+ * Uses TC39 Stage 3 decorators.
8
+ * The sequence key is stored in context.metadata and read by @ReadModel.
26
9
  */
27
- export declare function transferSequenceKeyMetadata(classType: AnyClass, contextMetadata: Record<string | symbol, unknown>): void;
28
- export {};
10
+ export declare function sequencedBy(_value: undefined, context: FieldDecoratorContext): void;
@@ -1,79 +1,19 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SEQUENCE_KEY_SYMBOL = void 0;
3
4
  exports.sequencedBy = sequencedBy;
4
- exports.transferSequenceKeyMetadata = transferSequenceKeyMetadata;
5
- const magek_1 = require("../magek");
6
- const metadata_1 = require("./metadata");
7
- // Symbol for storing sequence key in Stage 3 decorator context.metadata
8
- const SEQUENCE_KEY_SYMBOL = Symbol.for('magek:sequenceKey');
9
- /**
10
- * Type guard to detect Stage 3 field context
11
- */
12
- function isStage3FieldContext(arg) {
13
- return (arg !== null &&
14
- typeof arg === 'object' &&
15
- 'kind' in arg &&
16
- arg.kind === 'field' &&
17
- 'name' in arg &&
18
- 'metadata' in arg);
19
- }
20
- /**
21
- * Register sequence key for a class
22
- */
23
- function registerSequenceKey(klass, propertyName) {
24
- magek_1.Magek.configureCurrentEnv((config) => {
25
- if (config.readModelSequenceKeys[klass.name] && config.readModelSequenceKeys[klass.name] !== propertyName) {
26
- throw new Error(`Error trying to register a sort key named \`${propertyName}\` for class \`${klass.name}\`. It already had the sort key \`${config.readModelSequenceKeys[klass.name]}\` defined and only one sort key is allowed for each read model.`);
27
- }
28
- else {
29
- config.readModelSequenceKeys[klass.name] = propertyName;
30
- }
31
- });
32
- }
5
+ /** Symbol for storing sequence key in decorator context.metadata */
6
+ exports.SEQUENCE_KEY_SYMBOL = Symbol.for('magek:sequenceKey');
33
7
  /**
34
8
  * Decorator to specify the sequencing key for a ReadModel.
35
- * Can be used as both a parameter decorator and property decorator.
36
- * Supports both legacy (experimentalDecorators) and Stage 3 decorators.
37
- */
38
- function sequencedBy(target, propertyKeyOrContext, parameterIndex) {
39
- // Detect Stage 3 field decorator
40
- if (isStage3FieldContext(propertyKeyOrContext)) {
41
- const context = propertyKeyOrContext;
42
- const propertyName = String(context.name);
43
- // Store the sequence key in context.metadata for ReadModel decorator to pick up
44
- context.metadata[SEQUENCE_KEY_SYMBOL] = propertyName;
45
- // Also use addInitializer to register immediately when class is defined
46
- if (context.addInitializer) {
47
- context.addInitializer(function () {
48
- const klass = this.constructor;
49
- registerSequenceKey(klass, propertyName);
50
- });
51
- }
52
- return;
53
- }
54
- // Legacy decorator handling
55
- const propertyKey = propertyKeyOrContext;
56
- // Property decorator usage: @sequencedBy on a class property
57
- if (propertyKey !== undefined && parameterIndex === undefined) {
58
- const klass = target.constructor;
59
- const propertyName = String(propertyKey);
60
- registerSequenceKey(klass, propertyName);
61
- }
62
- // Parameter decorator usage: @sequencedBy on constructor parameter
63
- else if (parameterIndex !== undefined) {
64
- const klass = target;
65
- const args = (0, metadata_1.getFunctionArguments)(klass);
66
- const propertyName = args[parameterIndex];
67
- registerSequenceKey(klass, propertyName);
68
- }
69
- }
70
- /**
71
- * Transfer sequence key metadata from Stage 3 context to class.
72
- * Called by the ReadModel class decorator.
9
+ *
10
+ * Uses TC39 Stage 3 decorators.
11
+ * The sequence key is stored in context.metadata and read by @ReadModel.
73
12
  */
74
- function transferSequenceKeyMetadata(classType, contextMetadata) {
75
- const sequenceKey = contextMetadata[SEQUENCE_KEY_SYMBOL];
76
- if (sequenceKey) {
77
- registerSequenceKey(classType, sequenceKey);
13
+ function sequencedBy(_value, context) {
14
+ const propertyName = String(context.name);
15
+ // Store the sequence key in context.metadata for ReadModel decorator to pick up
16
+ if (context.metadata) {
17
+ context.metadata[exports.SEQUENCE_KEY_SYMBOL] = propertyName;
78
18
  }
79
19
  }
@@ -8,30 +8,35 @@ const raw_events_parser_1 = require("./services/raw-events-parser");
8
8
  const read_model_store_1 = require("./services/read-model-store");
9
9
  const instrumentation_1 = require("./instrumentation");
10
10
  const event_processor_1 = require("./event-processor");
11
- class MagekEventDispatcher {
12
- /**
13
- * Entry point to dispatch events.
14
- * @param rawEvents List of raw events
15
- * @param config
16
- */
17
- static async dispatch(rawEvents, config) {
18
- const logger = (0, common_1.getLogger)(config, 'MagekEventDispatcher#dispatch');
19
- const eventStore = new event_store_1.EventStore(config);
20
- const readModelStore = new read_model_store_1.ReadModelStore(config);
21
- logger.debug('Event workflow started for raw events:', require('util').inspect(rawEvents, false, null, false));
22
- try {
23
- const eventEnvelopes = config.eventStore.rawToEnvelopes(rawEvents);
24
- await raw_events_parser_1.RawEventsParser.streamPerEntityEvents(config, eventEnvelopes, event_processor_1.MagekEventProcessor.eventProcessor(eventStore, readModelStore));
11
+ let MagekEventDispatcher = (() => {
12
+ let _staticExtraInitializers = [];
13
+ let _static_dispatch_decorators;
14
+ return class MagekEventDispatcher {
15
+ static {
16
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
17
+ _static_dispatch_decorators = [(0, instrumentation_1.trace)(common_1.TraceActionTypes.DISPATCH_EVENTS)];
18
+ tslib_1.__esDecorate(this, null, _static_dispatch_decorators, { kind: "method", name: "dispatch", static: true, private: false, access: { has: obj => "dispatch" in obj, get: obj => obj.dispatch }, metadata: _metadata }, null, _staticExtraInitializers);
19
+ if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
20
+ tslib_1.__runInitializers(this, _staticExtraInitializers);
25
21
  }
26
- catch (e) {
27
- logger.error('Unhandled error while dispatching event: ', e);
22
+ /**
23
+ * Entry point to dispatch events.
24
+ * @param rawEvents List of raw events
25
+ * @param config
26
+ */
27
+ static async dispatch(rawEvents, config) {
28
+ const logger = (0, common_1.getLogger)(config, 'MagekEventDispatcher#dispatch');
29
+ const eventStore = new event_store_1.EventStore(config);
30
+ const readModelStore = new read_model_store_1.ReadModelStore(config);
31
+ logger.debug('Event workflow started for raw events:', require('util').inspect(rawEvents, false, null, false));
32
+ try {
33
+ const eventEnvelopes = config.eventStore.rawToEnvelopes(rawEvents);
34
+ await raw_events_parser_1.RawEventsParser.streamPerEntityEvents(config, eventEnvelopes, event_processor_1.MagekEventProcessor.eventProcessor(eventStore, readModelStore));
35
+ }
36
+ catch (e) {
37
+ logger.error('Unhandled error while dispatching event: ', e);
38
+ }
28
39
  }
29
- }
30
- }
40
+ };
41
+ })();
31
42
  exports.MagekEventDispatcher = MagekEventDispatcher;
32
- tslib_1.__decorate([
33
- (0, instrumentation_1.Trace)(common_1.TraceActionTypes.DISPATCH_EVENTS),
34
- tslib_1.__metadata("design:type", Function),
35
- tslib_1.__metadata("design:paramtypes", [Object, common_1.MagekConfig]),
36
- tslib_1.__metadata("design:returntype", Promise)
37
- ], MagekEventDispatcher, "dispatch", null);
@@ -7,119 +7,122 @@ const register_handler_1 = require("./register-handler");
7
7
  const global_error_dispatcher_1 = require("./global-error-dispatcher");
8
8
  const instrumentation_1 = require("./instrumentation");
9
9
  const decorators_1 = require("./decorators");
10
- class MagekEventProcessor {
11
- /**
12
- * Function that will be called once for each entity from the `RawEventsParser.streamPerEntityEvents` method
13
- * after the page of events is grouped by entity.
14
- */
15
- static eventProcessor(eventStore, readModelStore) {
16
- return async (entityName, entityID, eventEnvelopes, config) => {
17
- // Filter events that have already been dispatched
18
- const eventsNotDispatched = await MagekEventProcessor.filterDispatched(config, eventEnvelopes, eventStore);
19
- const eventEnvelopesProcessors = [
20
- MagekEventProcessor.dispatchEntityEventsToEventHandlers(eventsNotDispatched, config),
21
- ];
22
- // Read models are not updated for notification events (events that are not related to an entity but a topic)
23
- if (!(entityName in config.topicToEvent)) {
24
- eventEnvelopesProcessors.push(MagekEventProcessor.snapshotAndUpdateReadModels(config, entityName, entityID, eventStore, readModelStore));
25
- }
26
- await common_1.Promises.allSettledAndFulfilled(eventEnvelopesProcessors);
27
- };
28
- }
29
- static async filterDispatched(config, eventEnvelopes, eventStore) {
30
- const logger = (0, common_1.getLogger)(config, 'MagekEventDispatcher#filterDispatched');
31
- const filteredResults = await Promise.all(eventEnvelopes.map(async (eventEnvelope) => {
32
- const result = await eventStore.storeDispatchedEvent(eventEnvelope);
33
- if (!result) {
34
- logger.warn('Event has already been dispatched. Skipping.', eventEnvelope);
35
- }
36
- return result;
37
- }));
38
- return eventEnvelopes.filter((_, index) => filteredResults[index]);
39
- }
40
- static async snapshotAndUpdateReadModels(config, entityName, entityID, eventStore, readModelStore) {
41
- const logger = (0, common_1.getLogger)(config, 'MagekEventDispatcher#snapshotAndUpdateReadModels');
42
- let entitySnapshot = undefined;
43
- try {
44
- entitySnapshot = await eventStore.fetchEntitySnapshot(entityName, entityID);
45
- }
46
- catch (e) {
47
- logger.error('Error while fetching or reducing entity snapshot:', e);
10
+ let MagekEventProcessor = (() => {
11
+ let _staticExtraInitializers = [];
12
+ let _static_dispatchEntityEventsToEventHandlers_decorators;
13
+ return class MagekEventProcessor {
14
+ static {
15
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
16
+ _static_dispatchEntityEventsToEventHandlers_decorators = [(0, instrumentation_1.trace)(common_1.TraceActionTypes.EVENT_HANDLERS_PROCESS)];
17
+ tslib_1.__esDecorate(this, null, _static_dispatchEntityEventsToEventHandlers_decorators, { kind: "method", name: "dispatchEntityEventsToEventHandlers", static: true, private: false, access: { has: obj => "dispatchEntityEventsToEventHandlers" in obj, get: obj => obj.dispatchEntityEventsToEventHandlers }, metadata: _metadata }, null, _staticExtraInitializers);
18
+ if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
19
+ tslib_1.__runInitializers(this, _staticExtraInitializers);
48
20
  }
49
- if (!entitySnapshot) {
50
- logger.debug('No new snapshot generated, skipping read models projection');
51
- return;
52
- }
53
- logger.debug('Snapshot loaded and started read models projection:', entitySnapshot);
54
- await readModelStore.project(entitySnapshot);
55
- }
56
- static async dispatchEntityEventsToEventHandlers(entityEventEnvelopes, config) {
57
- const logger = (0, common_1.getLogger)(config, 'MagekEventDispatcher.dispatchEntityEventsToEventHandlers');
58
- try {
59
- await common_1.Promises.allSettledAndFulfilled(entityEventEnvelopes.map(async (eventEnvelope) => {
60
- let eventHandlers = config.eventHandlers[eventEnvelope.typeName] || [];
61
- const globalEventHandler = config.eventHandlers[decorators_1.GLOBAL_EVENT_HANDLERS];
62
- if (globalEventHandler && globalEventHandler.length > 0) {
63
- eventHandlers = eventHandlers.concat(globalEventHandler);
21
+ /**
22
+ * Function that will be called once for each entity from the `RawEventsParser.streamPerEntityEvents` method
23
+ * after the page of events is grouped by entity.
24
+ */
25
+ static eventProcessor(eventStore, readModelStore) {
26
+ return async (entityName, entityID, eventEnvelopes, config) => {
27
+ // Filter events that have already been dispatched
28
+ const eventsNotDispatched = await MagekEventProcessor.filterDispatched(config, eventEnvelopes, eventStore);
29
+ const eventEnvelopesProcessors = [
30
+ MagekEventProcessor.dispatchEntityEventsToEventHandlers(eventsNotDispatched, config),
31
+ ];
32
+ // Read models are not updated for notification events (events that are not related to an entity but a topic)
33
+ if (!(entityName in config.topicToEvent)) {
34
+ eventEnvelopesProcessors.push(MagekEventProcessor.snapshotAndUpdateReadModels(config, entityName, entityID, eventStore, readModelStore));
64
35
  }
65
- if (!eventHandlers || eventHandlers.length == 0) {
66
- logger.debug(`No event-handlers found for event ${eventEnvelope.typeName}. Skipping...`);
67
- return;
36
+ await common_1.Promises.allSettledAndFulfilled(eventEnvelopesProcessors);
37
+ };
38
+ }
39
+ static async filterDispatched(config, eventEnvelopes, eventStore) {
40
+ const logger = (0, common_1.getLogger)(config, 'MagekEventDispatcher#filterDispatched');
41
+ const filteredResults = await Promise.all(eventEnvelopes.map(async (eventEnvelope) => {
42
+ const result = await eventStore.storeDispatchedEvent(eventEnvelope);
43
+ if (!result) {
44
+ logger.warn('Event has already been dispatched. Skipping.', eventEnvelope);
68
45
  }
69
- const eventInstance = this.getEventInstance(config, eventEnvelope);
70
- if (eventHandlers && eventHandlers.length > 0) {
71
- try {
72
- await common_1.Promises.allSettledAndFulfilled(eventHandlers.map(async (eventHandler) => {
73
- logger.debug('Calling "handle" method on event handler: ', eventHandler);
74
- await this.callEventHandler(eventHandler, eventInstance, eventEnvelope, config);
75
- }));
46
+ return result;
47
+ }));
48
+ return eventEnvelopes.filter((_, index) => filteredResults[index]);
49
+ }
50
+ static async snapshotAndUpdateReadModels(config, entityName, entityID, eventStore, readModelStore) {
51
+ const logger = (0, common_1.getLogger)(config, 'MagekEventDispatcher#snapshotAndUpdateReadModels');
52
+ let entitySnapshot = undefined;
53
+ try {
54
+ entitySnapshot = await eventStore.fetchEntitySnapshot(entityName, entityID);
55
+ }
56
+ catch (e) {
57
+ logger.error('Error while fetching or reducing entity snapshot:', e);
58
+ }
59
+ if (!entitySnapshot) {
60
+ logger.debug('No new snapshot generated, skipping read models projection');
61
+ return;
62
+ }
63
+ logger.debug('Snapshot loaded and started read models projection:', entitySnapshot);
64
+ await readModelStore.project(entitySnapshot);
65
+ }
66
+ static async dispatchEntityEventsToEventHandlers(entityEventEnvelopes, config) {
67
+ const logger = (0, common_1.getLogger)(config, 'MagekEventDispatcher.dispatchEntityEventsToEventHandlers');
68
+ try {
69
+ await common_1.Promises.allSettledAndFulfilled(entityEventEnvelopes.map(async (eventEnvelope) => {
70
+ let eventHandlers = config.eventHandlers[eventEnvelope.typeName] || [];
71
+ const globalEventHandler = config.eventHandlers[decorators_1.GLOBAL_EVENT_HANDLERS];
72
+ if (globalEventHandler && globalEventHandler.length > 0) {
73
+ eventHandlers = eventHandlers.concat(globalEventHandler);
74
+ }
75
+ if (!eventHandlers || eventHandlers.length == 0) {
76
+ logger.debug(`No event-handlers found for event ${eventEnvelope.typeName}. Skipping...`);
77
+ return;
76
78
  }
77
- catch (error) {
78
- if (error instanceof common_1.PromisesError) {
79
- logger.error(`Failed to process handlers for event ${eventEnvelope.typeName}:`, error.failedReasons);
79
+ const eventInstance = this.getEventInstance(config, eventEnvelope);
80
+ if (eventHandlers && eventHandlers.length > 0) {
81
+ try {
82
+ await common_1.Promises.allSettledAndFulfilled(eventHandlers.map(async (eventHandler) => {
83
+ logger.debug('Calling "handle" method on event handler: ', eventHandler);
84
+ await this.callEventHandler(eventHandler, eventInstance, eventEnvelope, config);
85
+ }));
80
86
  }
81
- else {
82
- logger.error(`Unexpected error processing handlers for event ${eventEnvelope.typeName}:`, error);
87
+ catch (error) {
88
+ if (error instanceof common_1.PromisesError) {
89
+ logger.error(`Failed to process handlers for event ${eventEnvelope.typeName}:`, error.failedReasons);
90
+ }
91
+ else {
92
+ logger.error(`Unexpected error processing handlers for event ${eventEnvelope.typeName}:`, error);
93
+ }
83
94
  }
84
95
  }
85
- }
86
- }));
87
- }
88
- catch (error) {
89
- if (error instanceof common_1.PromisesError) {
90
- logger.error('Failed to process events:', error.failedReasons);
96
+ }));
91
97
  }
92
- else {
93
- logger.error('Unexpected error processing events:', error);
98
+ catch (error) {
99
+ if (error instanceof common_1.PromisesError) {
100
+ logger.error('Failed to process events:', error.failedReasons);
101
+ }
102
+ else {
103
+ logger.error('Unexpected error processing events:', error);
104
+ }
94
105
  }
95
106
  }
96
- }
97
- static getEventInstance(config, eventEnvelope) {
98
- var _a;
99
- const eventClass = (_a = config.events[eventEnvelope.typeName]) !== null && _a !== void 0 ? _a : config.notifications[eventEnvelope.typeName];
100
- return (0, common_1.createInstance)(eventClass.class, eventEnvelope.value);
101
- }
102
- static async callEventHandler(eventHandler, eventInstance, eventEnvelope, config) {
103
- const register = new common_1.Register(eventEnvelope.requestID, {}, register_handler_1.RegisterHandler.flush, eventEnvelope.currentUser);
104
- try {
105
- const logger = (0, common_1.getLogger)(config, 'MagekEventProcessor#handleEvent');
106
- logger.debug('Calling "handle" method on event handler: ', eventHandler);
107
- await eventHandler.handle(eventInstance, register);
107
+ static getEventInstance(config, eventEnvelope) {
108
+ const eventClass = config.events[eventEnvelope.typeName] ?? config.notifications[eventEnvelope.typeName];
109
+ return (0, common_1.createInstance)(eventClass.class, eventEnvelope.value);
108
110
  }
109
- catch (e) {
110
- const globalErrorDispatcher = new global_error_dispatcher_1.MagekGlobalErrorDispatcher(config);
111
- const error = await globalErrorDispatcher.dispatch(new common_1.EventHandlerGlobalError(eventEnvelope, eventInstance, e.eventHandlerMetadata, e));
112
- if (error)
113
- throw error;
111
+ static async callEventHandler(eventHandler, eventInstance, eventEnvelope, config) {
112
+ const register = new common_1.Register(eventEnvelope.requestID, {}, register_handler_1.RegisterHandler.flush, eventEnvelope.currentUser);
113
+ try {
114
+ const logger = (0, common_1.getLogger)(config, 'MagekEventProcessor#handleEvent');
115
+ logger.debug('Calling "handle" method on event handler: ', eventHandler);
116
+ await eventHandler.handle(eventInstance, register);
117
+ }
118
+ catch (e) {
119
+ const globalErrorDispatcher = new global_error_dispatcher_1.MagekGlobalErrorDispatcher(config);
120
+ const error = await globalErrorDispatcher.dispatch(new common_1.EventHandlerGlobalError(eventEnvelope, eventInstance, e.eventHandlerMetadata, e));
121
+ if (error)
122
+ throw error;
123
+ }
124
+ await register_handler_1.RegisterHandler.handle(config, register);
114
125
  }
115
- await register_handler_1.RegisterHandler.handle(config, register);
116
- }
117
- }
126
+ };
127
+ })();
118
128
  exports.MagekEventProcessor = MagekEventProcessor;
119
- tslib_1.__decorate([
120
- (0, instrumentation_1.Trace)(common_1.TraceActionTypes.EVENT_HANDLERS_PROCESS),
121
- tslib_1.__metadata("design:type", Function),
122
- tslib_1.__metadata("design:paramtypes", [Array,
123
- common_1.MagekConfig]),
124
- tslib_1.__metadata("design:returntype", Promise)
125
- ], MagekEventProcessor, "dispatchEntityEventsToEventHandlers", null);