@magek/core 0.0.5 → 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.
- package/dist/authorizer.js +1 -1
- package/dist/command-dispatcher.js +47 -41
- package/dist/core-concepts/data-migration/entities/data-migration-entity.js +5 -2
- package/dist/core-concepts/data-migration/events/data-migration-finished.js +3 -1
- package/dist/core-concepts/data-migration/events/data-migration-started.js +3 -1
- package/dist/core-concepts/data-migration/events/entity-migrated.js +4 -0
- package/dist/core-concepts/touch-entity/events/entity-touched.js +2 -0
- package/dist/data-migrations.js +59 -54
- package/dist/decorators/command.d.ts +4 -11
- package/dist/decorators/command.js +10 -18
- package/dist/decorators/data-migration.d.ts +4 -1
- package/dist/decorators/data-migration.js +3 -1
- package/dist/decorators/decorator-types.d.ts +50 -0
- package/dist/decorators/decorator-types.js +11 -0
- package/dist/decorators/decorator-utils.d.ts +1 -0
- package/dist/decorators/decorator-utils.js +2 -0
- package/dist/decorators/entity.d.ts +7 -15
- package/dist/decorators/entity.js +27 -37
- package/dist/decorators/event-handler.d.ts +11 -1
- package/dist/decorators/event-handler.js +13 -1
- package/dist/decorators/event.d.ts +4 -1
- package/dist/decorators/event.js +3 -2
- package/dist/decorators/field-metadata-reader.d.ts +8 -3
- package/dist/decorators/field-metadata-reader.js +50 -62
- package/dist/decorators/field.d.ts +23 -0
- package/dist/decorators/field.js +41 -0
- package/dist/decorators/global-error-handler.d.ts +10 -1
- package/dist/decorators/global-error-handler.js +9 -1
- package/dist/decorators/global-event-handler.d.ts +10 -1
- package/dist/decorators/global-event-handler.js +9 -1
- package/dist/decorators/health-sensor.d.ts +4 -1
- package/dist/decorators/health-sensor.js +3 -2
- package/dist/decorators/index.d.ts +3 -0
- package/dist/decorators/index.js +2 -0
- package/dist/decorators/metadata.d.ts +17 -1
- package/dist/decorators/metadata.js +22 -22
- package/dist/decorators/non-exposed.d.ts +13 -2
- package/dist/decorators/non-exposed.js +22 -20
- package/dist/decorators/notification.d.ts +6 -18
- package/dist/decorators/notification.js +10 -50
- package/dist/decorators/projects.d.ts +5 -18
- package/dist/decorators/projects.js +23 -54
- package/dist/decorators/query.d.ts +11 -1
- package/dist/decorators/query.js +18 -4
- package/dist/decorators/read-model.d.ts +13 -27
- package/dist/decorators/read-model.js +45 -77
- package/dist/decorators/role.d.ts +9 -3
- package/dist/decorators/role.js +8 -3
- package/dist/decorators/scheduled-command.d.ts +4 -1
- package/dist/decorators/scheduled-command.js +3 -1
- package/dist/decorators/schema-migration.d.ts +11 -27
- package/dist/decorators/schema-migration.js +32 -77
- package/dist/decorators/sequenced-by.d.ts +7 -25
- package/dist/decorators/sequenced-by.js +11 -71
- package/dist/event-dispatcher.js +29 -24
- package/dist/event-processor.js +106 -103
- package/dist/event-stream-consumer.js +25 -20
- package/dist/event-stream-producer.js +22 -17
- package/dist/events-reader.js +1 -0
- package/dist/global-error-dispatcher.js +3 -2
- package/dist/graphql-dispatcher.js +161 -156
- package/dist/index.js +4 -0
- package/dist/instrumentation/decorator/trace.d.ts +11 -3
- package/dist/instrumentation/decorator/trace.js +17 -71
- package/dist/magek.js +2 -2
- package/dist/query-dispatcher.js +2 -0
- package/dist/read-model-schema-migrator.js +71 -68
- package/dist/read-models-reader.js +178 -180
- package/dist/register-handler.js +3 -3
- package/dist/scheduled-command-dispatcher.js +48 -42
- package/dist/schema-migrator.js +63 -59
- package/dist/sensor/health/health-service.js +2 -1
- package/dist/services/event-store.js +221 -224
- package/dist/services/graphql/graphql-generator.js +11 -8
- package/dist/services/graphql/graphql-mutation-generator.js +4 -0
- package/dist/services/graphql/graphql-query-generator.js +14 -0
- package/dist/services/graphql/graphql-subcriptions-generator.js +7 -0
- package/dist/services/graphql/graphql-type-informer.js +4 -3
- package/dist/services/graphql/query-generators/graphql-query-by-keys-generator.js +4 -0
- package/dist/services/graphql/query-generators/graphql-query-events-generator.js +3 -0
- package/dist/services/graphql/query-generators/graphql-query-filters-generator.js +6 -0
- package/dist/services/graphql/query-generators/graphql-query-generator.js +4 -0
- package/dist/services/graphql/query-generators/graphql-query-listed-generator.js +7 -0
- package/dist/services/graphql/query-helpers/graphql-handled-fields-generator.js +5 -2
- package/dist/services/graphql/query-helpers/graphql-query-filter-arguments-builder.js +3 -0
- package/dist/services/graphql/query-helpers/graphql-query-filter-fields-builder.js +4 -0
- package/dist/services/graphql/query-helpers/graphql-query-sort-builder.js +4 -2
- package/dist/services/graphql/websocket-protocol/graphql-websocket-protocol.js +5 -3
- package/dist/services/pub-sub/read-model-pub-sub.js +1 -0
- package/dist/services/raw-events-parser.js +1 -1
- package/dist/services/read-model-store.js +16 -17
- package/dist/services/token-verifiers/jwks-uri-token-verifier.js +8 -4
- package/dist/services/token-verifiers/public-key-token-verifier.js +4 -2
- package/dist/services/token-verifiers/role-based-token-verifier.js +2 -1
- package/dist/services/token-verifiers/utilities.js +1 -1
- package/dist/subscribers-notifier.js +98 -92
- package/dist/token-verifier.js +2 -1
- package/package.json +4 -4
- package/dist/decorators/stage3-utils.d.ts +0 -6
- package/dist/decorators/stage3-utils.js +0 -25
|
@@ -10,251 +10,248 @@ const entity_touched_1 = require("../core-concepts/touch-entity/events/entity-to
|
|
|
10
10
|
const instrumentation_1 = require("../instrumentation");
|
|
11
11
|
const originOfTime = new Date(0).toISOString(); // Unix epoch
|
|
12
12
|
const reducibleEventsTypesNames = [entity_migrated_1.MagekEntityMigrated.name, entity_touched_1.MagekEntityTouched.name];
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
13
|
+
let EventStore = (() => {
|
|
14
|
+
let _instanceExtraInitializers = [];
|
|
15
|
+
let _fetchEntitySnapshot_decorators;
|
|
16
|
+
let _storeDispatchedEvent_decorators;
|
|
17
|
+
let _storeSnapshot_decorators;
|
|
18
|
+
let _loadLatestSnapshot_decorators;
|
|
19
|
+
let _loadEventStreamSince_decorators;
|
|
20
|
+
let _entityReducer_decorators;
|
|
21
|
+
return class EventStore {
|
|
22
|
+
static {
|
|
23
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
24
|
+
_fetchEntitySnapshot_decorators = [(0, instrumentation_1.trace)(common_1.TraceActionTypes.FETCH_ENTITY_SNAPSHOT)];
|
|
25
|
+
_storeDispatchedEvent_decorators = [(0, instrumentation_1.trace)(common_1.TraceActionTypes.CUSTOM)];
|
|
26
|
+
_storeSnapshot_decorators = [(0, instrumentation_1.trace)(common_1.TraceActionTypes.STORE_SNAPSHOT)];
|
|
27
|
+
_loadLatestSnapshot_decorators = [(0, instrumentation_1.trace)(common_1.TraceActionTypes.LOAD_LATEST_SNAPSHOT)];
|
|
28
|
+
_loadEventStreamSince_decorators = [(0, instrumentation_1.trace)(common_1.TraceActionTypes.LOAD_EVENT_STREAM_SINCE)];
|
|
29
|
+
_entityReducer_decorators = [(0, instrumentation_1.trace)(common_1.TraceActionTypes.ENTITY_REDUCER)];
|
|
30
|
+
tslib_1.__esDecorate(this, null, _fetchEntitySnapshot_decorators, { kind: "method", name: "fetchEntitySnapshot", static: false, private: false, access: { has: obj => "fetchEntitySnapshot" in obj, get: obj => obj.fetchEntitySnapshot }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
31
|
+
tslib_1.__esDecorate(this, null, _storeDispatchedEvent_decorators, { kind: "method", name: "storeDispatchedEvent", static: false, private: false, access: { has: obj => "storeDispatchedEvent" in obj, get: obj => obj.storeDispatchedEvent }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
32
|
+
tslib_1.__esDecorate(this, null, _storeSnapshot_decorators, { kind: "method", name: "storeSnapshot", static: false, private: false, access: { has: obj => "storeSnapshot" in obj, get: obj => obj.storeSnapshot }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
33
|
+
tslib_1.__esDecorate(this, null, _loadLatestSnapshot_decorators, { kind: "method", name: "loadLatestSnapshot", static: false, private: false, access: { has: obj => "loadLatestSnapshot" in obj, get: obj => obj.loadLatestSnapshot }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
34
|
+
tslib_1.__esDecorate(this, null, _loadEventStreamSince_decorators, { kind: "method", name: "loadEventStreamSince", static: false, private: false, access: { has: obj => "loadEventStreamSince" in obj, get: obj => obj.loadEventStreamSince }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
35
|
+
tslib_1.__esDecorate(this, null, _entityReducer_decorators, { kind: "method", name: "entityReducer", static: false, private: false, access: { has: obj => "entityReducer" in obj, get: obj => obj.entityReducer }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
36
|
+
if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
34
37
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
38
|
+
config = tslib_1.__runInitializers(this, _instanceExtraInitializers);
|
|
39
|
+
constructor(config) {
|
|
40
|
+
this.config = config;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Will fetch the latest snapshot for an entity by applying a reduction
|
|
44
|
+
* since the time of creation of the last snapshot or from the origin of time
|
|
45
|
+
* if no snapshot is found.
|
|
46
|
+
*
|
|
47
|
+
* Also, in order to make next calls faster, this method caches the newly calculated
|
|
48
|
+
* snapshot storing it at the end of the process.
|
|
49
|
+
*/
|
|
50
|
+
async fetchEntitySnapshot(entityName, entityID) {
|
|
51
|
+
const logger = (0, common_1.getLogger)(this.config, 'EventStore#fetchEntitySnapshot');
|
|
52
|
+
logger.debug(`Fetching snapshot for entity ${entityName} with ID ${entityID}`);
|
|
53
|
+
const latestSnapshotEnvelope = await this.loadLatestSnapshot(entityName, entityID);
|
|
54
|
+
const lastVisitedTime = latestSnapshotEnvelope?.snapshottedEventCreatedAt ?? originOfTime;
|
|
55
|
+
const pendingEvents = await this.loadEventStreamSince(entityName, entityID, lastVisitedTime);
|
|
56
|
+
if (pendingEvents.length <= 0) {
|
|
57
|
+
return latestSnapshotEnvelope;
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
logger.debug(`Looking for the reducer for entity ${entityName} with ID ${entityID}`);
|
|
61
|
+
// In this assignment we discard the `createdAt` field because it's not needed in the reduction process
|
|
62
|
+
let newEntitySnapshot = latestSnapshotEnvelope;
|
|
63
|
+
for (const pendingEvent of pendingEvents) {
|
|
64
|
+
// We double-check that what we are reducing is an event
|
|
65
|
+
if (pendingEvent.kind === 'event') {
|
|
66
|
+
try {
|
|
67
|
+
const reducerResult = await this.entityReducer(pendingEvent, newEntitySnapshot);
|
|
68
|
+
// If reducer returns ReducerAction.Skip, keep the current snapshot unchanged
|
|
69
|
+
if (reducerResult !== common_1.ReducerAction.Skip) {
|
|
70
|
+
newEntitySnapshot = reducerResult;
|
|
71
|
+
}
|
|
52
72
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
73
|
+
catch (e) {
|
|
74
|
+
if (e instanceof common_1.InvalidEventError) {
|
|
75
|
+
const globalErrorDispatcher = new global_error_dispatcher_1.MagekGlobalErrorDispatcher(this.config);
|
|
76
|
+
const error = await globalErrorDispatcher.dispatch(new common_1.EventGlobalError(pendingEvent, e));
|
|
77
|
+
if (error)
|
|
78
|
+
throw error;
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
else if (e instanceof common_1.InvalidReducerError) {
|
|
82
|
+
const globalErrorDispatcher = new global_error_dispatcher_1.MagekGlobalErrorDispatcher(this.config);
|
|
83
|
+
const reducerMetadata = this.config.reducers[pendingEvent.typeName];
|
|
84
|
+
const error = await globalErrorDispatcher.dispatch(new common_1.ReducerGlobalError(pendingEvent, e.eventInstance, e.snapshotInstance, reducerMetadata, e));
|
|
85
|
+
if (error)
|
|
86
|
+
throw error;
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
throw e;
|
|
60
90
|
}
|
|
61
|
-
throw e;
|
|
62
91
|
}
|
|
63
92
|
}
|
|
93
|
+
if (!newEntitySnapshot) {
|
|
94
|
+
logger.debug('No snapshot was found or reduced, returning');
|
|
95
|
+
return newEntitySnapshot;
|
|
96
|
+
}
|
|
97
|
+
if (newEntitySnapshot.entityID !== entityID) {
|
|
98
|
+
logger.debug(`Migrated entity ${entityName} with previous ID ${entityID} to ${newEntitySnapshot?.typeName} with the new ID ${newEntitySnapshot?.entityID}`, newEntitySnapshot);
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
logger.debug(`Reduced new snapshot for entity ${entityName} with ID ${entityID}: `, newEntitySnapshot);
|
|
102
|
+
}
|
|
103
|
+
return await this.storeSnapshot(newEntitySnapshot);
|
|
64
104
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
105
|
+
}
|
|
106
|
+
async storeDispatchedEvent(eventEnvelope) {
|
|
107
|
+
const logger = (0, common_1.getLogger)(this.config, 'EventStore#storeDispatchedEvent');
|
|
108
|
+
try {
|
|
109
|
+
logger.debug('Storing event in the dispatched event store:', eventEnvelope);
|
|
110
|
+
return await this.config.eventStore.storeDispatched(eventEnvelope, this.config);
|
|
71
111
|
}
|
|
72
|
-
|
|
73
|
-
logger.debug(
|
|
112
|
+
catch (e) {
|
|
113
|
+
logger.debug('Could not store dispatched event. Continue its processing.', { error: e, eventEnvelope });
|
|
114
|
+
return true;
|
|
74
115
|
}
|
|
75
|
-
return await this.storeSnapshot(newEntitySnapshot);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
async storeDispatchedEvent(eventEnvelope) {
|
|
79
|
-
const logger = (0, common_1.getLogger)(this.config, 'EventStore#storeDispatchedEvent');
|
|
80
|
-
try {
|
|
81
|
-
logger.debug('Storing event in the dispatched event store:', eventEnvelope);
|
|
82
|
-
return await this.config.eventStore.storeDispatched(eventEnvelope, this.config);
|
|
83
|
-
}
|
|
84
|
-
catch (e) {
|
|
85
|
-
logger.debug('Could not store dispatched event. Continue its processing.', { error: e, eventEnvelope });
|
|
86
|
-
return true;
|
|
87
116
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
117
|
+
async storeSnapshot(snapshot) {
|
|
118
|
+
const logger = (0, common_1.getLogger)(this.config, 'EventStore#storeSnapshot');
|
|
119
|
+
try {
|
|
120
|
+
logger.debug('Storing snapshot in the event store:', snapshot);
|
|
121
|
+
return await this.config.eventStore.storeSnapshot(snapshot, this.config);
|
|
122
|
+
}
|
|
123
|
+
catch (e) {
|
|
124
|
+
logger.error(`The snapshot for entity ${snapshot.typeName} with ID ${snapshot.entityID} couldn't be stored (Tried on ${new Date()})`, snapshot, '\nError:', e);
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
94
127
|
}
|
|
95
|
-
|
|
96
|
-
logger
|
|
97
|
-
|
|
128
|
+
async loadLatestSnapshot(entityName, entityID) {
|
|
129
|
+
const logger = (0, common_1.getLogger)(this.config, 'EventStore#loadLatestSnapshot');
|
|
130
|
+
logger.debug(`Loading latest snapshot for entity ${entityName} and ID ${entityID}`);
|
|
131
|
+
const latestSnapshot = await this.config.eventStore.latestEntitySnapshot(this.config, entityName, entityID);
|
|
132
|
+
if (latestSnapshot) {
|
|
133
|
+
return new schema_migrator_1.SchemaMigrator(this.config).migrate(latestSnapshot);
|
|
134
|
+
}
|
|
135
|
+
return undefined;
|
|
98
136
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
const latestSnapshot = await this.config.eventStore.latestEntitySnapshot(this.config, entityName, entityID);
|
|
104
|
-
if (latestSnapshot) {
|
|
105
|
-
return new schema_migrator_1.SchemaMigrator(this.config).migrate(latestSnapshot);
|
|
137
|
+
async loadEventStreamSince(entityTypeName, entityID, timestamp) {
|
|
138
|
+
const logger = (0, common_1.getLogger)(this.config, 'EventStore#loadEventStreamSince');
|
|
139
|
+
logger.debug(`Loading list of pending events for entity ${entityTypeName} with ID ${entityID} since ${timestamp}`);
|
|
140
|
+
return this.config.eventStore.forEntitySince(this.config, entityTypeName, entityID, timestamp);
|
|
106
141
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
142
|
+
async entityReducer(eventEnvelope, latestSnapshot) {
|
|
143
|
+
const logger = (0, common_1.getLogger)(this.config, 'entityReducer');
|
|
144
|
+
logger.debug('Calling reducer with event: ', eventEnvelope, ' and entity snapshot ', latestSnapshot);
|
|
145
|
+
if (this.shouldReduceMagekSuperKind(eventEnvelope)) {
|
|
146
|
+
return this.reduceSuperKind(eventEnvelope, latestSnapshot);
|
|
147
|
+
}
|
|
148
|
+
const eventMetadata = this.eventMetadataFor(eventEnvelope);
|
|
149
|
+
const migratedEventEnvelope = await new schema_migrator_1.SchemaMigrator(this.config).migrate(eventEnvelope);
|
|
150
|
+
const eventInstance = (0, common_1.createInstance)(eventMetadata.class, migratedEventEnvelope.value);
|
|
151
|
+
const entityMetadata = this.config.entities[migratedEventEnvelope.entityTypeName];
|
|
152
|
+
const reducerMetadata = this.config.reducers[eventEnvelope.typeName];
|
|
153
|
+
const snapshotInstance = latestSnapshot ? (0, common_1.createInstance)(entityMetadata.class, latestSnapshot.value) : null;
|
|
154
|
+
return this.createNewSnapshot(migratedEventEnvelope, eventInstance, snapshotInstance, eventEnvelope, reducerMetadata);
|
|
119
155
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
const entityMetadata = this.config.entities[migratedEventEnvelope.entityTypeName];
|
|
124
|
-
const reducerMetadata = this.config.reducers[eventEnvelope.typeName];
|
|
125
|
-
const snapshotInstance = latestSnapshot ? (0, common_1.createInstance)(entityMetadata.class, latestSnapshot.value) : null;
|
|
126
|
-
return this.createNewSnapshot(migratedEventEnvelope, eventInstance, snapshotInstance, eventEnvelope, reducerMetadata);
|
|
127
|
-
}
|
|
128
|
-
shouldReduceMagekSuperKind(eventEnvelope) {
|
|
129
|
-
const reducible = reducibleEventsTypesNames.includes(eventEnvelope.typeName);
|
|
130
|
-
return eventEnvelope.superKind && eventEnvelope.superKind === common_1.MAGEK_SUPER_KIND && reducible;
|
|
131
|
-
}
|
|
132
|
-
eventMetadataFor(eventEnvelope) {
|
|
133
|
-
const logger = (0, common_1.getLogger)(this.config, 'eventMetadataFor');
|
|
134
|
-
const eventMetadata = this.config.events[eventEnvelope.typeName];
|
|
135
|
-
if (!eventMetadata) {
|
|
136
|
-
logger.error(`No event registered for event ${eventEnvelope.typeName}`);
|
|
137
|
-
throw new common_1.InvalidEventError(`No event registered for event ${eventEnvelope.typeName}`);
|
|
156
|
+
shouldReduceMagekSuperKind(eventEnvelope) {
|
|
157
|
+
const reducible = reducibleEventsTypesNames.includes(eventEnvelope.typeName);
|
|
158
|
+
return eventEnvelope.superKind && eventEnvelope.superKind === common_1.MAGEK_SUPER_KIND && reducible;
|
|
138
159
|
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
kind: 'snapshot',
|
|
148
|
-
superKind: migratedEventEnvelope.superKind,
|
|
149
|
-
requestID: migratedEventEnvelope.requestID,
|
|
150
|
-
entityID: migratedEventEnvelope.entityID,
|
|
151
|
-
entityTypeName: migratedEventEnvelope.entityTypeName,
|
|
152
|
-
typeName: migratedEventEnvelope.entityTypeName,
|
|
153
|
-
value: newEntity,
|
|
154
|
-
snapshottedEventCreatedAt: migratedEventEnvelope.createdAt,
|
|
155
|
-
};
|
|
156
|
-
logger.debug('Reducer result: ', newSnapshot);
|
|
157
|
-
return newSnapshot;
|
|
160
|
+
eventMetadataFor(eventEnvelope) {
|
|
161
|
+
const logger = (0, common_1.getLogger)(this.config, 'eventMetadataFor');
|
|
162
|
+
const eventMetadata = this.config.events[eventEnvelope.typeName];
|
|
163
|
+
if (!eventMetadata) {
|
|
164
|
+
logger.error(`No event registered for event ${eventEnvelope.typeName}`);
|
|
165
|
+
throw new common_1.InvalidEventError(`No event registered for event ${eventEnvelope.typeName}`);
|
|
166
|
+
}
|
|
167
|
+
return eventMetadata;
|
|
158
168
|
}
|
|
159
|
-
|
|
160
|
-
const
|
|
161
|
-
|
|
169
|
+
async createNewSnapshot(migratedEventEnvelope, eventInstance, snapshotInstance, eventEnvelope, reducerMetadata) {
|
|
170
|
+
const logger = (0, common_1.getLogger)(this.config, 'createNewSnapshot');
|
|
171
|
+
try {
|
|
172
|
+
const reducerResult = this.reducerForEvent(migratedEventEnvelope.typeName, eventInstance, snapshotInstance)(eventInstance, snapshotInstance);
|
|
173
|
+
if (reducerResult === common_1.ReducerAction.Skip) {
|
|
174
|
+
logger.debug('Reducer returned ReducerAction.Skip, skipping snapshot creation');
|
|
175
|
+
return common_1.ReducerAction.Skip;
|
|
176
|
+
}
|
|
177
|
+
const newSnapshot = {
|
|
178
|
+
version: this.config.currentVersionFor(eventEnvelope.entityTypeName),
|
|
179
|
+
kind: 'snapshot',
|
|
180
|
+
superKind: migratedEventEnvelope.superKind,
|
|
181
|
+
requestID: migratedEventEnvelope.requestID,
|
|
182
|
+
entityID: migratedEventEnvelope.entityID,
|
|
183
|
+
entityTypeName: migratedEventEnvelope.entityTypeName,
|
|
184
|
+
typeName: migratedEventEnvelope.entityTypeName,
|
|
185
|
+
value: reducerResult,
|
|
186
|
+
snapshottedEventCreatedAt: migratedEventEnvelope.createdAt,
|
|
187
|
+
};
|
|
188
|
+
logger.debug('Reducer result: ', newSnapshot);
|
|
189
|
+
return newSnapshot;
|
|
190
|
+
}
|
|
191
|
+
catch (e) {
|
|
192
|
+
const globalErrorDispatcher = new global_error_dispatcher_1.MagekGlobalErrorDispatcher(this.config);
|
|
193
|
+
throw await globalErrorDispatcher.dispatch(new common_1.ReducerGlobalError(migratedEventEnvelope, eventInstance, snapshotInstance, reducerMetadata, e));
|
|
194
|
+
}
|
|
162
195
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
196
|
+
async reduceSuperKind(eventEnvelope, latestSnapshot) {
|
|
197
|
+
if (eventEnvelope.typeName === entity_touched_1.MagekEntityTouched.name) {
|
|
198
|
+
return this.reduceEntityTouched(eventEnvelope, latestSnapshot);
|
|
199
|
+
}
|
|
200
|
+
if (eventEnvelope.typeName === entity_migrated_1.MagekEntityMigrated.name) {
|
|
201
|
+
return this.reduceEntityMigrated(eventEnvelope);
|
|
202
|
+
}
|
|
203
|
+
throw new common_1.InvalidParameterError(`Unexpected super kind ${eventEnvelope.superKind} to be reduced`);
|
|
167
204
|
}
|
|
168
|
-
|
|
169
|
-
|
|
205
|
+
reduceEntityMigrated(eventEnvelope) {
|
|
206
|
+
const event = eventEnvelope.value;
|
|
207
|
+
return this.toMagekEntitySnapshot(eventEnvelope, event.newEntity, event.newEntityName);
|
|
170
208
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
return;
|
|
209
|
+
reduceEntityTouched(eventEnvelope, latestSnapshot) {
|
|
210
|
+
const logger = (0, common_1.getLogger)(this.config, 'EventStore#reduceEntityTouched');
|
|
211
|
+
logger.debug('Reducing ', eventEnvelope, ' with latestSnapshot');
|
|
212
|
+
if (!latestSnapshot) {
|
|
213
|
+
logger.debug('Latest snapshot not found, returning Skip');
|
|
214
|
+
return common_1.ReducerAction.Skip;
|
|
215
|
+
}
|
|
216
|
+
const event = eventEnvelope.value;
|
|
217
|
+
const entityMetadata = this.config.entities[event.entityName];
|
|
218
|
+
const snapshotInstance = (0, common_1.createInstance)(entityMetadata.class, latestSnapshot.value);
|
|
219
|
+
return this.toMagekEntitySnapshot(eventEnvelope, snapshotInstance, event.entityName);
|
|
183
220
|
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
value: entity,
|
|
200
|
-
snapshottedEventCreatedAt: eventEnvelope.createdAt,
|
|
201
|
-
};
|
|
202
|
-
logger.debug('MagekEntitySnapshot result: ', migratedSnapshot);
|
|
203
|
-
return migratedSnapshot;
|
|
204
|
-
}
|
|
205
|
-
reducerForEvent(eventName, eventInstance, snapshotInstance) {
|
|
206
|
-
const logger = (0, common_1.getLogger)(this.config, 'EventStore#reducerForEvent');
|
|
207
|
-
const reducerMetadata = this.config.reducers[eventName];
|
|
208
|
-
if (!reducerMetadata) {
|
|
209
|
-
throw new common_1.InvalidReducerError(`No reducer registered for event ${eventName}`, eventInstance, snapshotInstance);
|
|
221
|
+
toMagekEntitySnapshot(eventEnvelope, entity, className) {
|
|
222
|
+
const logger = (0, common_1.getLogger)(this.config, 'EventStore#toMagekEntitySnapshot');
|
|
223
|
+
const migratedSnapshot = {
|
|
224
|
+
version: this.config.currentVersionFor(className),
|
|
225
|
+
kind: 'snapshot',
|
|
226
|
+
superKind: eventEnvelope.superKind,
|
|
227
|
+
requestID: eventEnvelope.requestID,
|
|
228
|
+
entityID: entity.id,
|
|
229
|
+
entityTypeName: className,
|
|
230
|
+
typeName: className,
|
|
231
|
+
value: entity,
|
|
232
|
+
snapshottedEventCreatedAt: eventEnvelope.createdAt,
|
|
233
|
+
};
|
|
234
|
+
logger.debug('MagekEntitySnapshot result: ', migratedSnapshot);
|
|
235
|
+
return migratedSnapshot;
|
|
210
236
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
return reducer;
|
|
237
|
+
reducerForEvent(eventName, eventInstance, snapshotInstance) {
|
|
238
|
+
const logger = (0, common_1.getLogger)(this.config, 'EventStore#reducerForEvent');
|
|
239
|
+
const reducerMetadata = this.config.reducers[eventName];
|
|
240
|
+
if (!reducerMetadata) {
|
|
241
|
+
throw new common_1.InvalidReducerError(`No reducer registered for event ${eventName}`, eventInstance, snapshotInstance);
|
|
217
242
|
}
|
|
218
|
-
|
|
219
|
-
|
|
243
|
+
else {
|
|
244
|
+
try {
|
|
245
|
+
const methodName = reducerMetadata.methodName;
|
|
246
|
+
const reducer = reducerMetadata.class[methodName];
|
|
247
|
+
logger.debug(`Found reducer for event ${eventName}: "${reducerMetadata.class.name}.${methodName}"`);
|
|
248
|
+
return reducer;
|
|
249
|
+
}
|
|
250
|
+
catch {
|
|
251
|
+
throw new Error(`Couldn't load the Entity class ${reducerMetadata.class.name}`);
|
|
252
|
+
}
|
|
220
253
|
}
|
|
221
254
|
}
|
|
222
|
-
}
|
|
223
|
-
}
|
|
255
|
+
};
|
|
256
|
+
})();
|
|
224
257
|
exports.EventStore = EventStore;
|
|
225
|
-
tslib_1.__decorate([
|
|
226
|
-
(0, instrumentation_1.Trace)(common_1.TraceActionTypes.FETCH_ENTITY_SNAPSHOT),
|
|
227
|
-
tslib_1.__metadata("design:type", Function),
|
|
228
|
-
tslib_1.__metadata("design:paramtypes", [String, common_1.UUID]),
|
|
229
|
-
tslib_1.__metadata("design:returntype", Promise)
|
|
230
|
-
], EventStore.prototype, "fetchEntitySnapshot", null);
|
|
231
|
-
tslib_1.__decorate([
|
|
232
|
-
(0, instrumentation_1.Trace)(common_1.TraceActionTypes.CUSTOM),
|
|
233
|
-
tslib_1.__metadata("design:type", Function),
|
|
234
|
-
tslib_1.__metadata("design:paramtypes", [Object]),
|
|
235
|
-
tslib_1.__metadata("design:returntype", Promise)
|
|
236
|
-
], EventStore.prototype, "storeDispatchedEvent", null);
|
|
237
|
-
tslib_1.__decorate([
|
|
238
|
-
(0, instrumentation_1.Trace)(common_1.TraceActionTypes.STORE_SNAPSHOT),
|
|
239
|
-
tslib_1.__metadata("design:type", Function),
|
|
240
|
-
tslib_1.__metadata("design:paramtypes", [Object]),
|
|
241
|
-
tslib_1.__metadata("design:returntype", Promise)
|
|
242
|
-
], EventStore.prototype, "storeSnapshot", null);
|
|
243
|
-
tslib_1.__decorate([
|
|
244
|
-
(0, instrumentation_1.Trace)(common_1.TraceActionTypes.LOAD_LATEST_SNAPSHOT),
|
|
245
|
-
tslib_1.__metadata("design:type", Function),
|
|
246
|
-
tslib_1.__metadata("design:paramtypes", [String, common_1.UUID]),
|
|
247
|
-
tslib_1.__metadata("design:returntype", Promise)
|
|
248
|
-
], EventStore.prototype, "loadLatestSnapshot", null);
|
|
249
|
-
tslib_1.__decorate([
|
|
250
|
-
(0, instrumentation_1.Trace)(common_1.TraceActionTypes.LOAD_EVENT_STREAM_SINCE),
|
|
251
|
-
tslib_1.__metadata("design:type", Function),
|
|
252
|
-
tslib_1.__metadata("design:paramtypes", [String, common_1.UUID, String]),
|
|
253
|
-
tslib_1.__metadata("design:returntype", Promise)
|
|
254
|
-
], EventStore.prototype, "loadEventStreamSince", null);
|
|
255
|
-
tslib_1.__decorate([
|
|
256
|
-
(0, instrumentation_1.Trace)(common_1.TraceActionTypes.ENTITY_REDUCER),
|
|
257
|
-
tslib_1.__metadata("design:type", Function),
|
|
258
|
-
tslib_1.__metadata("design:paramtypes", [Object, Object]),
|
|
259
|
-
tslib_1.__metadata("design:returntype", Promise)
|
|
260
|
-
], EventStore.prototype, "entityReducer", null);
|
|
@@ -13,6 +13,11 @@ const graphql_subcriptions_generator_1 = require("./graphql-subcriptions-generat
|
|
|
13
13
|
const graphql_type_informer_1 = require("./graphql-type-informer");
|
|
14
14
|
const query_dispatcher_1 = require("../../query-dispatcher");
|
|
15
15
|
class GraphQLGenerator {
|
|
16
|
+
static commandsDispatcher;
|
|
17
|
+
static queriesDispatcher;
|
|
18
|
+
static readModelsReader;
|
|
19
|
+
static eventsReader;
|
|
20
|
+
static schema;
|
|
16
21
|
static generateSchema(config) {
|
|
17
22
|
const logger = (0, common_1.getLogger)(config, 'GraphQLGenerator#generateSchema');
|
|
18
23
|
if (!this.schema) {
|
|
@@ -40,7 +45,7 @@ class GraphQLGenerator {
|
|
|
40
45
|
let isPaginated = false;
|
|
41
46
|
const fields = this.getFields(info);
|
|
42
47
|
let select = fields.length > 0 ? fields : undefined;
|
|
43
|
-
if (
|
|
48
|
+
if (info?.fieldName === `List${(0, inflected_1.pluralize)(readModelClass.name)}`) {
|
|
44
49
|
isPaginated = true;
|
|
45
50
|
if (select) {
|
|
46
51
|
// In paginated queries, the `items[].` field needs to be removed from the select fields before querying the database
|
|
@@ -72,7 +77,7 @@ class GraphQLGenerator {
|
|
|
72
77
|
const result = await this.commandsDispatcher.dispatchCommand(commandEnvelope, context);
|
|
73
78
|
// It could be that the command didn't return anything
|
|
74
79
|
// so in that case we return `true`, as GraphQL doesn't have a `null` type
|
|
75
|
-
return result
|
|
80
|
+
return result ?? true;
|
|
76
81
|
};
|
|
77
82
|
}
|
|
78
83
|
static queriesResolverBuilder(queryClass) {
|
|
@@ -228,14 +233,13 @@ class GraphQLGenerator {
|
|
|
228
233
|
}
|
|
229
234
|
exports.GraphQLGenerator = GraphQLGenerator;
|
|
230
235
|
function toReadModelRequestEnvelope(readModelClass, args, context, paginatedVersion = false, select) {
|
|
231
|
-
var _a, _b;
|
|
232
236
|
return {
|
|
233
237
|
requestID: context.requestID,
|
|
234
238
|
currentUser: context.user,
|
|
235
239
|
class: readModelClass,
|
|
236
240
|
className: readModelClass.name,
|
|
237
|
-
filters:
|
|
238
|
-
sortBy:
|
|
241
|
+
filters: args.filter ?? {},
|
|
242
|
+
sortBy: args.sortBy ?? {},
|
|
239
243
|
limit: args.limit,
|
|
240
244
|
afterCursor: args.afterCursor,
|
|
241
245
|
paginatedVersion,
|
|
@@ -251,7 +255,6 @@ function toEventSearchRequest(args, context) {
|
|
|
251
255
|
};
|
|
252
256
|
}
|
|
253
257
|
function toEnvelope(typeName, value, context) {
|
|
254
|
-
var _a, _b;
|
|
255
258
|
return {
|
|
256
259
|
requestID: context.requestID,
|
|
257
260
|
currentUser: context.user,
|
|
@@ -260,8 +263,8 @@ function toEnvelope(typeName, value, context) {
|
|
|
260
263
|
version: 1, // TODO: How to pass the version through GraphQL?
|
|
261
264
|
context: {
|
|
262
265
|
request: {
|
|
263
|
-
body:
|
|
264
|
-
headers:
|
|
266
|
+
body: context.context?.request.body,
|
|
267
|
+
headers: context.context?.request.headers,
|
|
265
268
|
},
|
|
266
269
|
rawContext: context,
|
|
267
270
|
},
|
|
@@ -4,6 +4,10 @@ exports.GraphQLMutationGenerator = void 0;
|
|
|
4
4
|
const graphql_1 = require("graphql");
|
|
5
5
|
const graphql_handled_fields_generator_1 = require("./query-helpers/graphql-handled-fields-generator");
|
|
6
6
|
class GraphQLMutationGenerator {
|
|
7
|
+
targetTypes;
|
|
8
|
+
typeInformer;
|
|
9
|
+
mutationResolver;
|
|
10
|
+
config;
|
|
7
11
|
constructor(targetTypes, typeInformer, mutationResolver, config) {
|
|
8
12
|
this.targetTypes = targetTypes;
|
|
9
13
|
this.typeInformer = typeInformer;
|
|
@@ -8,6 +8,20 @@ const graphql_query_filters_generator_1 = require("./query-generators/graphql-qu
|
|
|
8
8
|
const graphql_query_listed_generator_1 = require("./query-generators/graphql-query-listed-generator");
|
|
9
9
|
const graphql_query_generator_1 = require("./query-generators/graphql-query-generator");
|
|
10
10
|
class GraphQLQueryGenerator {
|
|
11
|
+
config;
|
|
12
|
+
readModels;
|
|
13
|
+
targetTypes;
|
|
14
|
+
typeInformer;
|
|
15
|
+
byIDResolverBuilder;
|
|
16
|
+
queryResolverBuilder;
|
|
17
|
+
filterResolverBuilder;
|
|
18
|
+
eventsResolver;
|
|
19
|
+
generatedFiltersByTypeName;
|
|
20
|
+
graphqlQueryByKeysGenerator;
|
|
21
|
+
graphqlQueryGenerator;
|
|
22
|
+
graphqlQueryFiltersGenerator;
|
|
23
|
+
graphqlQueryListedGenerator;
|
|
24
|
+
graphqlQueryEventsGenerator;
|
|
11
25
|
constructor(config, readModels, targetTypes, typeInformer, byIDResolverBuilder, queryResolverBuilder, filterResolverBuilder, eventsResolver, generatedFiltersByTypeName = {}) {
|
|
12
26
|
this.config = config;
|
|
13
27
|
this.readModels = readModels;
|
|
@@ -5,6 +5,13 @@ 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 GraphQLSubscriptionGenerator {
|
|
8
|
+
readModels;
|
|
9
|
+
typeInformer;
|
|
10
|
+
byIDResolverBuilder;
|
|
11
|
+
filterResolverBuilder;
|
|
12
|
+
generatedFiltersByTypeName;
|
|
13
|
+
config;
|
|
14
|
+
graphqlQueryFilterFieldsBuilder;
|
|
8
15
|
constructor(readModels, typeInformer, byIDResolverBuilder, filterResolverBuilder, generatedFiltersByTypeName = {}, config) {
|
|
9
16
|
this.readModels = readModels;
|
|
10
17
|
this.typeInformer = typeInformer;
|
|
@@ -6,9 +6,10 @@ const graphql_1 = require("graphql");
|
|
|
6
6
|
const graphql_scalars_1 = require("graphql-scalars");
|
|
7
7
|
const common_1 = require("./common");
|
|
8
8
|
class GraphQLTypeInformer {
|
|
9
|
+
logger;
|
|
10
|
+
graphQLTypes = {};
|
|
9
11
|
constructor(logger) {
|
|
10
12
|
this.logger = logger;
|
|
11
|
-
this.graphQLTypes = {};
|
|
12
13
|
}
|
|
13
14
|
generateGraphQLTypeForClass(type, excludeProps, inputType = false) {
|
|
14
15
|
this.logger.debug(`Generate GraphQL ${inputType ? 'input' : 'output'} type for class ${type.name}`);
|
|
@@ -123,7 +124,7 @@ class GraphQLTypeInformer {
|
|
|
123
124
|
if (inputType) {
|
|
124
125
|
return new graphql_1.GraphQLInputObjectType({
|
|
125
126
|
name: classMetadata.name + 'Input',
|
|
126
|
-
fields: finalFields
|
|
127
|
+
fields: finalFields?.reduce((obj, prop) => {
|
|
127
128
|
this.logger.debug(`Get or create GraphQL input type for property ${prop.name}`);
|
|
128
129
|
return {
|
|
129
130
|
...obj,
|
|
@@ -147,7 +148,7 @@ class GraphQLTypeInformer {
|
|
|
147
148
|
const finalFields = (0, common_1.nonExcludedFields)(classMetadata.fields, excludeProps);
|
|
148
149
|
return new graphql_1.GraphQLObjectType({
|
|
149
150
|
name: classMetadata.name,
|
|
150
|
-
fields: finalFields
|
|
151
|
+
fields: finalFields?.reduce((obj, prop) => {
|
|
151
152
|
this.logger.debug(`Get or create GraphQL output type for property ${prop.name}`);
|
|
152
153
|
return {
|
|
153
154
|
...obj,
|