@magek/core 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/authorizer.d.ts +7 -0
- package/dist/authorizer.js +35 -0
- package/dist/command-dispatcher.d.ts +8 -0
- package/dist/command-dispatcher.js +55 -0
- package/dist/core-concepts/data-migration/entities/data-migration-entity.d.ts +12 -0
- package/dist/core-concepts/data-migration/entities/data-migration-entity.js +37 -0
- package/dist/core-concepts/data-migration/events/data-migration-finished.d.ts +7 -0
- package/dist/core-concepts/data-migration/events/data-migration-finished.js +13 -0
- package/dist/core-concepts/data-migration/events/data-migration-started.d.ts +7 -0
- package/dist/core-concepts/data-migration/events/data-migration-started.js +13 -0
- package/dist/core-concepts/data-migration/events/entity-migrated.d.ts +9 -0
- package/dist/core-concepts/data-migration/events/entity-migrated.js +15 -0
- package/dist/core-concepts/touch-entity/events/entity-touched.d.ts +7 -0
- package/dist/core-concepts/touch-entity/events/entity-touched.js +13 -0
- package/dist/data-migrations.d.ts +8 -0
- package/dist/data-migrations.js +73 -0
- package/dist/decorators/command.d.ts +19 -0
- package/dist/decorators/command.js +47 -0
- package/dist/decorators/data-migration.d.ts +9 -0
- package/dist/decorators/data-migration.js +25 -0
- package/dist/decorators/entity.d.ts +32 -0
- package/dist/decorators/entity.js +100 -0
- package/dist/decorators/event-handler.d.ts +3 -0
- package/dist/decorators/event-handler.js +18 -0
- package/dist/decorators/event.d.ts +8 -0
- package/dist/decorators/event.js +22 -0
- package/dist/decorators/field-metadata-reader.d.ts +6 -0
- package/dist/decorators/field-metadata-reader.js +221 -0
- package/dist/decorators/global-error-handler.d.ts +2 -0
- package/dist/decorators/global-error-handler.js +15 -0
- package/dist/decorators/global-event-handler.d.ts +3 -0
- package/dist/decorators/global-event-handler.js +9 -0
- package/dist/decorators/health-sensor.d.ts +14 -0
- package/dist/decorators/health-sensor.js +38 -0
- package/dist/decorators/index.d.ts +16 -0
- package/dist/decorators/index.js +19 -0
- package/dist/decorators/metadata.d.ts +13 -0
- package/dist/decorators/metadata.js +55 -0
- package/dist/decorators/non-exposed.d.ts +2 -0
- package/dist/decorators/non-exposed.js +24 -0
- package/dist/decorators/notification.d.ts +35 -0
- package/dist/decorators/notification.js +94 -0
- package/dist/decorators/projects.d.ts +32 -0
- package/dist/decorators/projects.js +87 -0
- package/dist/decorators/query.d.ts +2 -0
- package/dist/decorators/query.js +25 -0
- package/dist/decorators/read-model.d.ts +39 -0
- package/dist/decorators/read-model.js +129 -0
- package/dist/decorators/role.d.ts +6 -0
- package/dist/decorators/role.js +15 -0
- package/dist/decorators/scheduled-command.d.ts +9 -0
- package/dist/decorators/scheduled-command.js +25 -0
- package/dist/decorators/schema-migration.d.ts +36 -0
- package/dist/decorators/schema-migration.js +146 -0
- package/dist/decorators/sequenced-by.d.ts +28 -0
- package/dist/decorators/sequenced-by.js +79 -0
- package/dist/decorators/stage3-utils.d.ts +6 -0
- package/dist/decorators/stage3-utils.js +25 -0
- package/dist/delete-event-dispatcher.d.ts +4 -0
- package/dist/delete-event-dispatcher.js +23 -0
- package/dist/event-dispatcher.d.ts +9 -0
- package/dist/event-dispatcher.js +37 -0
- package/dist/event-processor.d.ts +15 -0
- package/dist/event-processor.js +125 -0
- package/dist/event-search.d.ts +2 -0
- package/dist/event-search.js +26 -0
- package/dist/event-stream-consumer.d.ts +7 -0
- package/dist/event-stream-consumer.js +36 -0
- package/dist/event-stream-producer.d.ts +7 -0
- package/dist/event-stream-producer.js +30 -0
- package/dist/events-reader.d.ts +11 -0
- package/dist/events-reader.js +63 -0
- package/dist/global-error-dispatcher.d.ts +16 -0
- package/dist/global-error-dispatcher.js +109 -0
- package/dist/graphql-dispatcher.d.ts +16 -0
- package/dist/graphql-dispatcher.js +195 -0
- package/dist/importer.d.ts +14 -0
- package/dist/importer.js +49 -0
- package/dist/index.d.ts +60 -0
- package/dist/index.js +100 -0
- package/dist/injectable/index.d.ts +21 -0
- package/dist/injectable/index.js +2 -0
- package/dist/instrumentation/decorator/trace.d.ts +13 -0
- package/dist/instrumentation/decorator/trace.js +116 -0
- package/dist/instrumentation/index.d.ts +2 -0
- package/dist/instrumentation/index.js +5 -0
- package/dist/instrumentation/trace-notifier.d.ts +3 -0
- package/dist/instrumentation/trace-notifier.js +26 -0
- package/dist/magek.d.ts +42 -0
- package/dist/magek.js +158 -0
- package/dist/query-dispatcher.d.ts +8 -0
- package/dist/query-dispatcher.js +47 -0
- package/dist/read-model-schema-migrator.d.ts +14 -0
- package/dist/read-model-schema-migrator.js +80 -0
- package/dist/read-models-reader.d.ts +31 -0
- package/dist/read-models-reader.js +196 -0
- package/dist/register-handler.d.ts +11 -0
- package/dist/register-handler.js +95 -0
- package/dist/rocket-dispatcher.d.ts +6 -0
- package/dist/rocket-dispatcher.js +21 -0
- package/dist/scheduled-command-dispatcher.d.ts +12 -0
- package/dist/scheduled-command-dispatcher.js +54 -0
- package/dist/schema-migrator.d.ts +12 -0
- package/dist/schema-migrator.js +71 -0
- package/dist/sensor/health/health-indicators/database-events-health-indicator.d.ts +5 -0
- package/dist/sensor/health/health-indicators/database-events-health-indicator.js +26 -0
- package/dist/sensor/health/health-indicators/database-health-indicator.d.ts +5 -0
- package/dist/sensor/health/health-indicators/database-health-indicator.js +29 -0
- package/dist/sensor/health/health-indicators/database-read-models-health-indicator.d.ts +5 -0
- package/dist/sensor/health/health-indicators/database-read-models-health-indicator.js +26 -0
- package/dist/sensor/health/health-indicators/default-health-indicators.d.ts +5 -0
- package/dist/sensor/health/health-indicators/default-health-indicators.js +39 -0
- package/dist/sensor/health/health-indicators/function-health-indicator.d.ts +5 -0
- package/dist/sensor/health/health-indicators/function-health-indicator.js +30 -0
- package/dist/sensor/health/health-indicators/health-indicator.d.ts +5 -0
- package/dist/sensor/health/health-indicators/health-indicator.js +30 -0
- package/dist/sensor/health/health-indicators/index.d.ts +3 -0
- package/dist/sensor/health/health-indicators/index.js +6 -0
- package/dist/sensor/health/health-indicators/os-info.d.ts +14 -0
- package/dist/sensor/health/health-indicators/os-info.js +38 -0
- package/dist/sensor/health/health-indicators/rockets-health-indicator.d.ts +5 -0
- package/dist/sensor/health/health-indicators/rockets-health-indicator.js +57 -0
- package/dist/sensor/health/health-indicators/version.d.ts +2 -0
- package/dist/sensor/health/health-indicators/version.js +24 -0
- package/dist/sensor/health/health-service.d.ts +22 -0
- package/dist/sensor/health/health-service.js +117 -0
- package/dist/sensor/health/health-utils.d.ts +7 -0
- package/dist/sensor/health/health-utils.js +53 -0
- package/dist/sensor/health/index.d.ts +3 -0
- package/dist/sensor/health/index.js +6 -0
- package/dist/sensor/index.d.ts +1 -0
- package/dist/sensor/index.js +4 -0
- package/dist/services/event-store.d.ts +27 -0
- package/dist/services/event-store.js +260 -0
- package/dist/services/filter-helpers.d.ts +3 -0
- package/dist/services/filter-helpers.js +19 -0
- package/dist/services/graphql/common.d.ts +26 -0
- package/dist/services/graphql/common.js +53 -0
- package/dist/services/graphql/graphql-generator.d.ts +46 -0
- package/dist/services/graphql/graphql-generator.js +269 -0
- package/dist/services/graphql/graphql-mutation-generator.d.ts +12 -0
- package/dist/services/graphql/graphql-mutation-generator.js +25 -0
- package/dist/services/graphql/graphql-query-generator.d.ts +22 -0
- package/dist/services/graphql/graphql-query-generator.js +39 -0
- package/dist/services/graphql/graphql-subcriptions-generator.d.ts +17 -0
- package/dist/services/graphql/graphql-subcriptions-generator.js +60 -0
- package/dist/services/graphql/graphql-type-informer.d.ts +23 -0
- package/dist/services/graphql/graphql-type-informer.js +160 -0
- package/dist/services/graphql/query-generators/graphql-query-by-keys-generator.d.ts +14 -0
- package/dist/services/graphql/query-generators/graphql-query-by-keys-generator.js +48 -0
- package/dist/services/graphql/query-generators/graphql-query-events-generator.d.ts +11 -0
- package/dist/services/graphql/query-generators/graphql-query-events-generator.js +68 -0
- package/dist/services/graphql/query-generators/graphql-query-filters-generator.d.ts +14 -0
- package/dist/services/graphql/query-generators/graphql-query-filters-generator.js +31 -0
- package/dist/services/graphql/query-generators/graphql-query-generator.d.ts +12 -0
- package/dist/services/graphql/query-generators/graphql-query-generator.js +17 -0
- package/dist/services/graphql/query-generators/graphql-query-listed-generator.d.ts +16 -0
- package/dist/services/graphql/query-generators/graphql-query-listed-generator.js +65 -0
- package/dist/services/graphql/query-helpers/graphql-handled-fields-generator.d.ts +15 -0
- package/dist/services/graphql/query-helpers/graphql-handled-fields-generator.js +65 -0
- package/dist/services/graphql/query-helpers/graphql-query-filter-arguments-builder.d.ts +13 -0
- package/dist/services/graphql/query-helpers/graphql-query-filter-arguments-builder.js +169 -0
- package/dist/services/graphql/query-helpers/graphql-query-filter-fields-builder.d.ts +11 -0
- package/dist/services/graphql/query-helpers/graphql-query-filter-fields-builder.js +28 -0
- package/dist/services/graphql/query-helpers/graphql-query-sort-builder.d.ts +12 -0
- package/dist/services/graphql/query-helpers/graphql-query-sort-builder.js +61 -0
- package/dist/services/graphql/websocket-protocol/graphql-websocket-protocol.d.ts +20 -0
- package/dist/services/graphql/websocket-protocol/graphql-websocket-protocol.js +127 -0
- package/dist/services/pub-sub/noop-read-model-pub-sub.d.ts +5 -0
- package/dist/services/pub-sub/noop-read-model-pub-sub.js +10 -0
- package/dist/services/pub-sub/read-model-pub-sub.d.ts +9 -0
- package/dist/services/pub-sub/read-model-pub-sub.js +112 -0
- package/dist/services/raw-events-parser.d.ts +5 -0
- package/dist/services/raw-events-parser.js +44 -0
- package/dist/services/read-model-searcher.d.ts +2 -0
- package/dist/services/read-model-searcher.js +11 -0
- package/dist/services/read-model-store.d.ts +41 -0
- package/dist/services/read-model-store.js +295 -0
- package/dist/services/token-verifiers/index.d.ts +4 -0
- package/dist/services/token-verifiers/index.js +7 -0
- package/dist/services/token-verifiers/jwks-uri-token-verifier.d.ts +21 -0
- package/dist/services/token-verifiers/jwks-uri-token-verifier.js +23 -0
- package/dist/services/token-verifiers/public-key-token-verifier.d.ts +13 -0
- package/dist/services/token-verifiers/public-key-token-verifier.js +19 -0
- package/dist/services/token-verifiers/role-based-token-verifier.d.ts +8 -0
- package/dist/services/token-verifiers/role-based-token-verifier.js +35 -0
- package/dist/services/token-verifiers/utilities.d.ts +31 -0
- package/dist/services/token-verifiers/utilities.js +70 -0
- package/dist/subscribers-notifier.d.ts +14 -0
- package/dist/subscribers-notifier.js +109 -0
- package/dist/token-verifier.d.ts +11 -0
- package/dist/token-verifier.js +46 -0
- package/dist/touch-entity-handler.d.ts +4 -0
- package/dist/touch-entity-handler.js +16 -0
- package/package.json +71 -0
package/dist/magek.js
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Magek = void 0;
|
|
4
|
+
const common_1 = require("@magek/common");
|
|
5
|
+
const importer_1 = require("./importer");
|
|
6
|
+
const event_store_1 = require("./services/event-store");
|
|
7
|
+
const entity_migrated_1 = require("./core-concepts/data-migration/events/entity-migrated");
|
|
8
|
+
const data_migration_entity_1 = require("./core-concepts/data-migration/entities/data-migration-entity");
|
|
9
|
+
const data_migration_started_1 = require("./core-concepts/data-migration/events/data-migration-started");
|
|
10
|
+
const data_migration_finished_1 = require("./core-concepts/data-migration/events/data-migration-finished");
|
|
11
|
+
const authorizer_1 = require("./authorizer");
|
|
12
|
+
const entity_touched_1 = require("./core-concepts/touch-entity/events/entity-touched");
|
|
13
|
+
const read_model_searcher_1 = require("./services/read-model-searcher");
|
|
14
|
+
const delete_event_dispatcher_1 = require("./delete-event-dispatcher");
|
|
15
|
+
const event_search_1 = require("./event-search");
|
|
16
|
+
const core_1 = require("@oclif/core");
|
|
17
|
+
/**
|
|
18
|
+
* Main class to interact with Magek and configure it.
|
|
19
|
+
* Sensible defaults are used whenever possible:
|
|
20
|
+
* - `appName`: `new-magek-app`
|
|
21
|
+
*
|
|
22
|
+
*/
|
|
23
|
+
class Magek {
|
|
24
|
+
static configureCurrentEnv(configurator) {
|
|
25
|
+
configurator(this.config);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Allows to configure the Magek project.
|
|
29
|
+
*
|
|
30
|
+
* @param environment The name of the environment you want to configure
|
|
31
|
+
* @param configurator A function that receives the configuration object to set the values
|
|
32
|
+
*/
|
|
33
|
+
static configure(environment, configurator) {
|
|
34
|
+
this.configuredEnvironments.add(environment);
|
|
35
|
+
if (this.config.environmentName === environment) {
|
|
36
|
+
configurator(this.config);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Initializes the Magek project
|
|
41
|
+
*/
|
|
42
|
+
static start(codeRootPath) {
|
|
43
|
+
var _a;
|
|
44
|
+
if (!this.config.eventStoreAdapter) {
|
|
45
|
+
throw new Error('No eventStoreAdapter configured. Please add one in MagekConfig.');
|
|
46
|
+
}
|
|
47
|
+
if (!this.config.readModelStoreAdapter) {
|
|
48
|
+
throw new Error('No readModelStoreAdapter configured. Please add one in MagekConfig.');
|
|
49
|
+
}
|
|
50
|
+
if (this.config.enableSubscriptions && !this.config.sessionStoreAdapter) {
|
|
51
|
+
throw new Error('No sessionStoreAdapter configured. Please add one in MagekConfig.');
|
|
52
|
+
}
|
|
53
|
+
const projectRootPath = codeRootPath.replace(new RegExp(this.config.codeRelativePath + '$'), '');
|
|
54
|
+
this.config.userProjectRootPath = projectRootPath;
|
|
55
|
+
importer_1.Importer.importUserProjectFiles(codeRootPath);
|
|
56
|
+
this.configureMagekConcepts();
|
|
57
|
+
this.config.validate();
|
|
58
|
+
const args = process.argv;
|
|
59
|
+
if (((_a = process.env['MAGEK_CLI_HOOK']) === null || _a === void 0 ? void 0 : _a.trim()) !== 'true') {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const injectable = this.config.injectable;
|
|
63
|
+
if (injectable) {
|
|
64
|
+
const { commands } = injectable;
|
|
65
|
+
// Run the injectable CLI commands using oclif
|
|
66
|
+
this.runInjectableCommands(args, commands, projectRootPath).catch((error) => {
|
|
67
|
+
if (error instanceof core_1.Errors.ExitError) {
|
|
68
|
+
process.exit(error.oclif.exit);
|
|
69
|
+
}
|
|
70
|
+
console.error(error);
|
|
71
|
+
process.exit(1);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
static async runInjectableCommands(args, commands, projectRootPath) {
|
|
76
|
+
// Get the subcommand from args (skip node and script path)
|
|
77
|
+
const subcommand = args[2];
|
|
78
|
+
if (!subcommand || !commands[subcommand]) {
|
|
79
|
+
console.log('Available commands:', Object.keys(commands).join(', '));
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
const CommandClass = commands[subcommand];
|
|
83
|
+
// Create a minimal oclif config
|
|
84
|
+
const config = await core_1.Config.load({ root: projectRootPath });
|
|
85
|
+
// Instantiate and run the command
|
|
86
|
+
const instance = new CommandClass(args.slice(3), config);
|
|
87
|
+
await instance.run();
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* This function returns a "Searcher" configured to search instances of the read model class passed as param.
|
|
91
|
+
* For more information, check the Searcher class.
|
|
92
|
+
* @param readModelClass The class of the read model you what to run searches for
|
|
93
|
+
*/
|
|
94
|
+
static readModel(readModelClass) {
|
|
95
|
+
return (0, read_model_searcher_1.readModelSearcher)(this.config, readModelClass);
|
|
96
|
+
}
|
|
97
|
+
static async events(request) {
|
|
98
|
+
return (0, event_search_1.eventSearch)(this.config, request);
|
|
99
|
+
}
|
|
100
|
+
static async entitiesIDs(entityTypeName, limit, afterCursor) {
|
|
101
|
+
return await this.config.eventStore.searchEntitiesIDs(this.config, limit, afterCursor, entityTypeName);
|
|
102
|
+
}
|
|
103
|
+
static async deleteEvent(parameters) {
|
|
104
|
+
return await delete_event_dispatcher_1.MagekDeleteEventDispatcher.deleteEvent(this.config, parameters);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Fetches the last known version of an entity
|
|
108
|
+
* @param entityClass Name of the entity class
|
|
109
|
+
* @param entityID
|
|
110
|
+
*/
|
|
111
|
+
static async entity(entityClass, entityID) {
|
|
112
|
+
const eventStore = new event_store_1.EventStore(this.config);
|
|
113
|
+
const entitySnapshotEnvelope = await eventStore.fetchEntitySnapshot(entityClass.name, entityID);
|
|
114
|
+
return entitySnapshotEnvelope ? (0, common_1.createInstance)(entityClass, entitySnapshotEnvelope.value) : undefined;
|
|
115
|
+
}
|
|
116
|
+
static configureMagekConcepts() {
|
|
117
|
+
this.configureDataMigrations();
|
|
118
|
+
this.configureTouchEntities();
|
|
119
|
+
}
|
|
120
|
+
static configureDataMigrations() {
|
|
121
|
+
this.config.events[entity_migrated_1.MagekEntityMigrated.name] = {
|
|
122
|
+
class: entity_migrated_1.MagekEntityMigrated,
|
|
123
|
+
};
|
|
124
|
+
this.config.events[data_migration_started_1.MagekDataMigrationStarted.name] = {
|
|
125
|
+
class: data_migration_started_1.MagekDataMigrationStarted,
|
|
126
|
+
};
|
|
127
|
+
this.config.reducers[data_migration_started_1.MagekDataMigrationStarted.name] = {
|
|
128
|
+
class: data_migration_entity_1.MagekDataMigrationEntity,
|
|
129
|
+
methodName: 'started',
|
|
130
|
+
};
|
|
131
|
+
this.config.events[data_migration_finished_1.MagekDataMigrationFinished.name] = {
|
|
132
|
+
class: data_migration_finished_1.MagekDataMigrationFinished,
|
|
133
|
+
};
|
|
134
|
+
this.config.reducers[data_migration_finished_1.MagekDataMigrationFinished.name] = {
|
|
135
|
+
class: data_migration_entity_1.MagekDataMigrationEntity,
|
|
136
|
+
methodName: 'finished',
|
|
137
|
+
};
|
|
138
|
+
this.config.entities[data_migration_entity_1.MagekDataMigrationEntity.name] = {
|
|
139
|
+
class: data_migration_entity_1.MagekDataMigrationEntity,
|
|
140
|
+
eventStreamAuthorizer: authorizer_1.MagekAuthorizer.denyAccess,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
static configureTouchEntities() {
|
|
144
|
+
this.config.events[entity_touched_1.MagekEntityTouched.name] = {
|
|
145
|
+
class: entity_touched_1.MagekEntityTouched,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
exports.Magek = Magek;
|
|
150
|
+
Magek.configuredEnvironments = new Set();
|
|
151
|
+
Magek.config = new common_1.MagekConfig(checkAndGetCurrentEnv());
|
|
152
|
+
function checkAndGetCurrentEnv() {
|
|
153
|
+
const env = process.env.MAGEK_ENV;
|
|
154
|
+
if (!env || env.trim().length == 0) {
|
|
155
|
+
throw new Error('Magek environment is missing. You need to provide an environment to configure your Magek project');
|
|
156
|
+
}
|
|
157
|
+
return env;
|
|
158
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { MagekConfig, QueryEnvelope } from '@magek/common';
|
|
2
|
+
import { GraphQLResolverContext } from './services/graphql/common';
|
|
3
|
+
export declare class MagekQueryDispatcher {
|
|
4
|
+
readonly config: MagekConfig;
|
|
5
|
+
private readonly globalErrorDispatcher;
|
|
6
|
+
constructor(config: MagekConfig);
|
|
7
|
+
dispatchQuery(queryEnvelope: QueryEnvelope, context: GraphQLResolverContext): Promise<unknown>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MagekQueryDispatcher = void 0;
|
|
4
|
+
const common_1 = require("@magek/common");
|
|
5
|
+
const global_error_dispatcher_1 = require("./global-error-dispatcher");
|
|
6
|
+
const filter_helpers_1 = require("./services/filter-helpers");
|
|
7
|
+
class MagekQueryDispatcher {
|
|
8
|
+
constructor(config) {
|
|
9
|
+
this.config = config;
|
|
10
|
+
this.globalErrorDispatcher = new global_error_dispatcher_1.MagekGlobalErrorDispatcher(config);
|
|
11
|
+
}
|
|
12
|
+
async dispatchQuery(queryEnvelope, context) {
|
|
13
|
+
const logger = (0, common_1.getLogger)(this.config, 'MagekQueryDispatcher#dispatchQuery');
|
|
14
|
+
logger.debug('Dispatching the following query envelope: ', queryEnvelope);
|
|
15
|
+
if (!queryEnvelope.version) {
|
|
16
|
+
throw new common_1.InvalidParameterError('The required query "version" was not present');
|
|
17
|
+
}
|
|
18
|
+
const queryMetadata = this.config.queryHandlers[queryEnvelope.typeName];
|
|
19
|
+
if (!queryMetadata) {
|
|
20
|
+
throw new common_1.NotFoundError(`Could not find a proper handler for ${queryEnvelope.typeName}`);
|
|
21
|
+
}
|
|
22
|
+
await queryMetadata.authorizer(queryEnvelope.currentUser, queryEnvelope);
|
|
23
|
+
const queryClass = queryMetadata.class;
|
|
24
|
+
logger.debug('Found the following query:', queryClass.name);
|
|
25
|
+
let result;
|
|
26
|
+
try {
|
|
27
|
+
const queryInfo = {
|
|
28
|
+
requestID: queryEnvelope.requestID,
|
|
29
|
+
responseHeaders: context.responseHeaders,
|
|
30
|
+
currentUser: queryEnvelope.currentUser,
|
|
31
|
+
context: queryEnvelope.context,
|
|
32
|
+
};
|
|
33
|
+
const queryInput = await (0, filter_helpers_1.applyBeforeFunctions)(queryEnvelope.value, queryMetadata.before, queryEnvelope.currentUser);
|
|
34
|
+
const queryInstance = (0, common_1.createInstance)(queryClass, queryInput);
|
|
35
|
+
logger.debug('Calling "handle" method on query: ', queryClass);
|
|
36
|
+
result = await queryClass.handle(queryInstance, queryInfo);
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
const e = err;
|
|
40
|
+
const error = await this.globalErrorDispatcher.dispatch(new common_1.QueryHandlerGlobalError(queryEnvelope, e));
|
|
41
|
+
if (error)
|
|
42
|
+
throw error;
|
|
43
|
+
}
|
|
44
|
+
return result;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
exports.MagekQueryDispatcher = MagekQueryDispatcher;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { MagekConfig, ReadModelInterface } from '@magek/common';
|
|
2
|
+
export declare class ReadModelSchemaMigrator {
|
|
3
|
+
private config;
|
|
4
|
+
constructor(config: MagekConfig);
|
|
5
|
+
/**
|
|
6
|
+
* **NOTE:** Read model schema migration is deprecated. Prefer data migration.
|
|
7
|
+
*/
|
|
8
|
+
migrate<TMigratableReadModel extends ReadModelInterface>(readModel: TMigratableReadModel, readModelName: string): Promise<TMigratableReadModel>;
|
|
9
|
+
private checkVersionRange;
|
|
10
|
+
private needsMigration;
|
|
11
|
+
private applyAllMigrations;
|
|
12
|
+
private applyMigration;
|
|
13
|
+
private static readModelSchemaVersion;
|
|
14
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var _a;
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.ReadModelSchemaMigrator = void 0;
|
|
5
|
+
const tslib_1 = require("tslib");
|
|
6
|
+
const common_1 = require("@magek/common");
|
|
7
|
+
const instrumentation_1 = require("./instrumentation");
|
|
8
|
+
class ReadModelSchemaMigrator {
|
|
9
|
+
constructor(config) {
|
|
10
|
+
this.config = config;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* **NOTE:** Read model schema migration is deprecated. Prefer data migration.
|
|
14
|
+
*/
|
|
15
|
+
async migrate(readModel, readModelName) {
|
|
16
|
+
this.checkVersionRange(readModel, readModelName);
|
|
17
|
+
if (this.needsMigration(readModel, readModelName)) {
|
|
18
|
+
return await this.applyAllMigrations(readModel, readModelName);
|
|
19
|
+
}
|
|
20
|
+
return readModel; // The current version is exactly the same as the version of the concept
|
|
21
|
+
}
|
|
22
|
+
checkVersionRange(readModel, readModelName) {
|
|
23
|
+
const readModelVersion = ReadModelSchemaMigrator.readModelSchemaVersion(readModel);
|
|
24
|
+
if (readModelVersion < 1) {
|
|
25
|
+
throw new common_1.InvalidVersionError(`Received an invalid schema version value, ${readModelVersion}, for ${readModelName}. ` +
|
|
26
|
+
'Versions must be greater than 0');
|
|
27
|
+
}
|
|
28
|
+
const currentVersion = this.config.currentVersionFor(readModelName);
|
|
29
|
+
if (currentVersion < readModelVersion) {
|
|
30
|
+
throw new common_1.InvalidVersionError(`Can not migrate schema an unknown version: The current schema version of ${readModelName} is ${currentVersion}, which is ` +
|
|
31
|
+
`lower than the received version ${readModelVersion}`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
needsMigration(readModel, readModelName) {
|
|
35
|
+
const currentVersion = this.config.currentVersionFor(readModelName);
|
|
36
|
+
return currentVersion > ReadModelSchemaMigrator.readModelSchemaVersion(readModel);
|
|
37
|
+
}
|
|
38
|
+
async applyAllMigrations(oldReadModel, readModelName) {
|
|
39
|
+
const logger = (0, common_1.getLogger)(this.config, 'ReadModelSchemaMigrator#applyAllMigrations');
|
|
40
|
+
const oldVersion = ReadModelSchemaMigrator.readModelSchemaVersion(oldReadModel);
|
|
41
|
+
const currentVersion = this.config.currentVersionFor(readModelName);
|
|
42
|
+
logger.info(`Migrating Schema ${readModelName} from version ${oldVersion} to version ${currentVersion}`);
|
|
43
|
+
logger.debug('ReadModel before schema migration:\n', oldReadModel);
|
|
44
|
+
const migrations = this.config.schemaMigrations[readModelName];
|
|
45
|
+
let migratedValue = oldReadModel;
|
|
46
|
+
for (let toVersion = oldVersion + 1; toVersion <= currentVersion; toVersion++) {
|
|
47
|
+
migratedValue = await this.applyMigration(migratedValue, migrations.get(toVersion));
|
|
48
|
+
}
|
|
49
|
+
const newReadModel = Object.assign(migratedValue, {
|
|
50
|
+
magekMetadata: {
|
|
51
|
+
...oldReadModel.magekMetadata,
|
|
52
|
+
schemaVersion: currentVersion,
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
logger.debug('ReadModel after schema migration:\n', newReadModel);
|
|
56
|
+
return newReadModel;
|
|
57
|
+
}
|
|
58
|
+
async applyMigration(oldValue, migration) {
|
|
59
|
+
const logger = (0, common_1.getLogger)(this.config, 'ReadModelSchemaMigrator#applyMigration');
|
|
60
|
+
if (!migration) {
|
|
61
|
+
throw new common_1.InvalidVersionError('Received an undefined schema migration value. Are there "gaps" between the versions of the schema migrations?');
|
|
62
|
+
}
|
|
63
|
+
const oldConcept = Object.assign(new migration.fromSchema(), oldValue);
|
|
64
|
+
const migrationMethod = new migration.migrationClass()[migration.methodName];
|
|
65
|
+
const newConcept = await migrationMethod(oldConcept);
|
|
66
|
+
logger.debug(`Partial schema migration finished. Schema migrated from oldValue=${JSON.stringify(oldConcept)} to newValue=${JSON.stringify(newConcept)}`);
|
|
67
|
+
return newConcept;
|
|
68
|
+
}
|
|
69
|
+
static readModelSchemaVersion(readModel) {
|
|
70
|
+
var _a, _b;
|
|
71
|
+
return (_b = (_a = readModel.magekMetadata) === null || _a === void 0 ? void 0 : _a.schemaVersion) !== null && _b !== void 0 ? _b : 1;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
exports.ReadModelSchemaMigrator = ReadModelSchemaMigrator;
|
|
75
|
+
tslib_1.__decorate([
|
|
76
|
+
(0, instrumentation_1.Trace)(common_1.TraceActionTypes.READ_MODEL_SCHEMA_MIGRATOR_MIGRATE),
|
|
77
|
+
tslib_1.__metadata("design:type", Function),
|
|
78
|
+
tslib_1.__metadata("design:paramtypes", [typeof (_a = typeof TMigratableReadModel !== "undefined" && TMigratableReadModel) === "function" ? _a : Object, String]),
|
|
79
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
80
|
+
], ReadModelSchemaMigrator.prototype, "migrate", null);
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { AnyClass, MagekConfig, FilterFor, GraphQLOperation, ProjectionFor, ReadModelInterface, ReadModelListResult, ReadModelRequestEnvelope, ReadOnlyNonEmptyArray, SequenceKey, SortFor, UUID } from '@magek/common';
|
|
2
|
+
export declare class MagekReadModelsReader {
|
|
3
|
+
readonly config: MagekConfig;
|
|
4
|
+
constructor(config: MagekConfig);
|
|
5
|
+
findById(readModelRequest: ReadModelRequestEnvelope<ReadModelInterface>): Promise<ReadModelInterface | ReadOnlyNonEmptyArray<ReadModelInterface>>;
|
|
6
|
+
search(readModelRequest: ReadModelRequestEnvelope<ReadModelInterface>): Promise<Array<ReadModelInterface> | ReadModelListResult<ReadModelInterface>>;
|
|
7
|
+
readModelSearch<TReadModel extends ReadModelInterface>(readModelClass: AnyClass, filters: FilterFor<unknown>, sort?: SortFor<unknown>, limit?: number, afterCursor?: any, paginatedVersion?: boolean, select?: ProjectionFor<TReadModel>): Promise<Array<TReadModel> | ReadModelListResult<TReadModel>>;
|
|
8
|
+
finderByIdFunction<TReadModel extends ReadModelInterface>(readModelClass: AnyClass, id: UUID, sequenceKey?: SequenceKey): Promise<ReadOnlyNonEmptyArray<TReadModel> | TReadModel>;
|
|
9
|
+
private migrateReadModels;
|
|
10
|
+
private createReadModelInstances;
|
|
11
|
+
/**
|
|
12
|
+
* Creates instances of the read model class with the calculated properties included
|
|
13
|
+
* @param searchResult The search result
|
|
14
|
+
* @param readModelClass The read model class
|
|
15
|
+
* @param propertiesToInclude The properties to include in the response
|
|
16
|
+
* @private
|
|
17
|
+
*/
|
|
18
|
+
private createReadModelInstancesWithCalculatedProperties;
|
|
19
|
+
subscribe(connectionID: string, readModelRequest: ReadModelRequestEnvelope<ReadModelInterface>, operation: GraphQLOperation): Promise<unknown>;
|
|
20
|
+
unsubscribe(connectionID: string, subscriptionID: string): Promise<void>;
|
|
21
|
+
unsubscribeAll(connectionID: string): Promise<void>;
|
|
22
|
+
private validateByIdRequest;
|
|
23
|
+
private validateRequest;
|
|
24
|
+
private processSubscription;
|
|
25
|
+
/**
|
|
26
|
+
* Returns the dependencies of the calculated fields of a read model
|
|
27
|
+
* @param readModelClass The read model class
|
|
28
|
+
* @private
|
|
29
|
+
*/
|
|
30
|
+
private getCalculatedFieldsDependencies;
|
|
31
|
+
}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MagekReadModelsReader = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const common_1 = require("@magek/common");
|
|
6
|
+
const magek_1 = require("./magek");
|
|
7
|
+
const filter_helpers_1 = require("./services/filter-helpers");
|
|
8
|
+
const read_model_schema_migrator_1 = require("./read-model-schema-migrator");
|
|
9
|
+
const instrumentation_1 = require("./instrumentation");
|
|
10
|
+
class MagekReadModelsReader {
|
|
11
|
+
constructor(config) {
|
|
12
|
+
this.config = config;
|
|
13
|
+
}
|
|
14
|
+
async findById(readModelRequest) {
|
|
15
|
+
await this.validateByIdRequest(readModelRequest);
|
|
16
|
+
const readModelMetadata = this.config.readModels[readModelRequest.class.name];
|
|
17
|
+
const readModelTransformedRequest = await (0, filter_helpers_1.applyReadModelRequestBeforeFunctions)(readModelRequest, readModelMetadata.before, readModelRequest.currentUser);
|
|
18
|
+
const key = readModelTransformedRequest.key;
|
|
19
|
+
if (!key) {
|
|
20
|
+
throw 'Tried to run a findById operation without providing a key. An ID is required to perform this operation.';
|
|
21
|
+
}
|
|
22
|
+
const currentReadModel = await magek_1.Magek.readModel(readModelMetadata.class).findById(key.id, key.sequenceKey);
|
|
23
|
+
if (currentReadModel) {
|
|
24
|
+
const readModelInstance = (0, common_1.createInstance)(readModelMetadata.class, currentReadModel);
|
|
25
|
+
const readModelName = readModelMetadata.class.name;
|
|
26
|
+
const readModelSchemaMigrator = new read_model_schema_migrator_1.ReadModelSchemaMigrator(this.config);
|
|
27
|
+
if (Array.isArray(readModelInstance)) {
|
|
28
|
+
return [await readModelSchemaMigrator.migrate(readModelInstance[0], readModelName)];
|
|
29
|
+
}
|
|
30
|
+
return readModelSchemaMigrator.migrate(readModelInstance, readModelName);
|
|
31
|
+
}
|
|
32
|
+
return currentReadModel;
|
|
33
|
+
}
|
|
34
|
+
async search(readModelRequest) {
|
|
35
|
+
await this.validateRequest(readModelRequest);
|
|
36
|
+
const readModelMetadata = this.config.readModels[readModelRequest.class.name];
|
|
37
|
+
const readModelTransformedRequest = await (0, filter_helpers_1.applyReadModelRequestBeforeFunctions)(readModelRequest, readModelMetadata.before, readModelRequest.currentUser);
|
|
38
|
+
return await this.readModelSearch(readModelMetadata.class, readModelTransformedRequest.filters, readModelTransformedRequest.sortBy, readModelTransformedRequest.limit, readModelTransformedRequest.afterCursor, readModelTransformedRequest.paginatedVersion, readModelTransformedRequest.select);
|
|
39
|
+
}
|
|
40
|
+
async readModelSearch(readModelClass, filters, sort, limit, afterCursor, paginatedVersion, select) {
|
|
41
|
+
const readModelName = readModelClass.name;
|
|
42
|
+
let selectWithDependencies = undefined;
|
|
43
|
+
const calculatedFieldsDependencies = this.getCalculatedFieldsDependencies(readModelClass);
|
|
44
|
+
if (select && Object.keys(calculatedFieldsDependencies).length > 0) {
|
|
45
|
+
const extendedSelect = new Set(select);
|
|
46
|
+
select.forEach((field) => {
|
|
47
|
+
const topLevelField = field.split('.')[0].replace('[]', '');
|
|
48
|
+
if (calculatedFieldsDependencies[topLevelField]) {
|
|
49
|
+
calculatedFieldsDependencies[topLevelField].map((dependency) => extendedSelect.add(dependency));
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
selectWithDependencies = Array.from(extendedSelect);
|
|
53
|
+
}
|
|
54
|
+
const searchResult = await this.config.readModelStore.search(this.config, readModelName, filters !== null && filters !== void 0 ? filters : {}, sort !== null && sort !== void 0 ? sort : {}, limit, afterCursor, paginatedVersion !== null && paginatedVersion !== void 0 ? paginatedVersion : false, selectWithDependencies !== null && selectWithDependencies !== void 0 ? selectWithDependencies : select);
|
|
55
|
+
const readModels = this.createReadModelInstances(searchResult, readModelClass);
|
|
56
|
+
if (select) {
|
|
57
|
+
return this.createReadModelInstancesWithCalculatedProperties(searchResult, readModelClass, select !== null && select !== void 0 ? select : []);
|
|
58
|
+
}
|
|
59
|
+
return this.migrateReadModels(readModels, readModelName);
|
|
60
|
+
}
|
|
61
|
+
async finderByIdFunction(readModelClass, id, sequenceKey) {
|
|
62
|
+
const result = await this.config.readModelStore.fetch(this.config, readModelClass.name, id, sequenceKey);
|
|
63
|
+
if (!result) {
|
|
64
|
+
throw new Error(`Read model not found: ${readModelClass.name} with id ${id}`);
|
|
65
|
+
}
|
|
66
|
+
// The adapter returns ReadOnlyNonEmptyArray<TReadModel> | undefined
|
|
67
|
+
// For backward compatibility, we return a single item if sequenceKey is not provided
|
|
68
|
+
return sequenceKey ? result : result[0];
|
|
69
|
+
}
|
|
70
|
+
async migrateReadModels(readModels, readModelName) {
|
|
71
|
+
const readModelSchemaMigrator = new read_model_schema_migrator_1.ReadModelSchemaMigrator(this.config);
|
|
72
|
+
if (Array.isArray(readModels)) {
|
|
73
|
+
return Promise.all(readModels.map((readModel) => readModelSchemaMigrator.migrate(readModel, readModelName)));
|
|
74
|
+
}
|
|
75
|
+
readModels.items = await Promise.all(readModels.items.map((readModel) => readModelSchemaMigrator.migrate(readModel, readModelName)));
|
|
76
|
+
return readModels;
|
|
77
|
+
}
|
|
78
|
+
createReadModelInstances(searchResult, readModelClass) {
|
|
79
|
+
if (Array.isArray(searchResult)) {
|
|
80
|
+
return (0, common_1.createInstances)(readModelClass, searchResult);
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
...searchResult,
|
|
84
|
+
items: (0, common_1.createInstances)(readModelClass, searchResult.items),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Creates instances of the read model class with the calculated properties included
|
|
89
|
+
* @param searchResult The search result
|
|
90
|
+
* @param readModelClass The read model class
|
|
91
|
+
* @param propertiesToInclude The properties to include in the response
|
|
92
|
+
* @private
|
|
93
|
+
*/
|
|
94
|
+
async createReadModelInstancesWithCalculatedProperties(searchResult, readModelClass, propertiesToInclude) {
|
|
95
|
+
const processInstance = async (raw) => {
|
|
96
|
+
const instance = await (0, common_1.createInstanceWithCalculatedProperties)(readModelClass, raw, propertiesToInclude);
|
|
97
|
+
return instance;
|
|
98
|
+
};
|
|
99
|
+
if (Array.isArray(searchResult)) {
|
|
100
|
+
return await Promise.all(searchResult.map(processInstance));
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
const processedItems = await Promise.all(searchResult.items.map(processInstance));
|
|
104
|
+
return {
|
|
105
|
+
...searchResult,
|
|
106
|
+
items: processedItems,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
async subscribe(connectionID, readModelRequest, operation) {
|
|
111
|
+
await this.validateRequest(readModelRequest);
|
|
112
|
+
return this.processSubscription(connectionID, readModelRequest, operation);
|
|
113
|
+
}
|
|
114
|
+
async unsubscribe(connectionID, subscriptionID) {
|
|
115
|
+
return this.config.sessionStore.deleteSubscription(this.config, connectionID, subscriptionID);
|
|
116
|
+
}
|
|
117
|
+
async unsubscribeAll(connectionID) {
|
|
118
|
+
return this.config.sessionStore.deleteSubscriptionsForConnection(this.config, connectionID);
|
|
119
|
+
}
|
|
120
|
+
async validateByIdRequest(readModelByIdRequest) {
|
|
121
|
+
var _a;
|
|
122
|
+
const logger = (0, common_1.getLogger)(this.config, 'MagekReadModelsReader#validateByIdRequest');
|
|
123
|
+
logger.debug('Validating the following read model by id request: ', readModelByIdRequest);
|
|
124
|
+
if (!readModelByIdRequest.version) {
|
|
125
|
+
throw new common_1.InvalidParameterError('The required request "version" was not present');
|
|
126
|
+
}
|
|
127
|
+
const readModelMetadata = this.config.readModels[readModelByIdRequest.class.name];
|
|
128
|
+
if (!readModelMetadata) {
|
|
129
|
+
throw new common_1.NotFoundError(`Could not find read model ${readModelByIdRequest.class.name}`);
|
|
130
|
+
}
|
|
131
|
+
await readModelMetadata.authorizer(readModelByIdRequest.currentUser, readModelByIdRequest);
|
|
132
|
+
if (((_a = readModelByIdRequest === null || readModelByIdRequest === void 0 ? void 0 : readModelByIdRequest.key) === null || _a === void 0 ? void 0 : _a.sequenceKey) &&
|
|
133
|
+
readModelByIdRequest.key.sequenceKey.name !== this.config.readModelSequenceKeys[readModelByIdRequest.class.name]) {
|
|
134
|
+
throw new common_1.InvalidParameterError(`Could not find a sort key defined for ${readModelByIdRequest.class.name} named '${readModelByIdRequest.key.sequenceKey.name}'.`);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
async validateRequest(readModelRequest) {
|
|
138
|
+
const logger = (0, common_1.getLogger)(this.config, 'MagekReadModelsReader#validateRequest');
|
|
139
|
+
logger.debug('Validating the following read model request: ', readModelRequest);
|
|
140
|
+
if (!readModelRequest.version) {
|
|
141
|
+
throw new common_1.InvalidParameterError('The required request "version" was not present');
|
|
142
|
+
}
|
|
143
|
+
const readModelMetadata = this.config.readModels[readModelRequest.class.name];
|
|
144
|
+
if (!readModelMetadata) {
|
|
145
|
+
throw new common_1.NotFoundError(`Could not find read model ${readModelRequest.class.name}`);
|
|
146
|
+
}
|
|
147
|
+
await readModelMetadata.authorizer(readModelRequest.currentUser, readModelRequest);
|
|
148
|
+
}
|
|
149
|
+
async processSubscription(connectionID, readModelRequest, operation) {
|
|
150
|
+
const logger = (0, common_1.getLogger)(this.config, 'MagekReadModelsReader#processSubscription');
|
|
151
|
+
logger.info(`Processing subscription of connection '${connectionID}' to read model '${readModelRequest.class.name}' with the following data: `, readModelRequest);
|
|
152
|
+
const readModelMetadata = this.config.readModels[readModelRequest.class.name];
|
|
153
|
+
const newReadModelRequest = await (0, filter_helpers_1.applyReadModelRequestBeforeFunctions)(readModelRequest, readModelMetadata.before, readModelRequest.currentUser);
|
|
154
|
+
const nowEpoch = Math.floor(new Date().getTime() / 1000);
|
|
155
|
+
const subscription = {
|
|
156
|
+
...newReadModelRequest,
|
|
157
|
+
expirationTime: nowEpoch + this.config.subscriptions.maxDurationInSeconds,
|
|
158
|
+
connectionID,
|
|
159
|
+
operation,
|
|
160
|
+
};
|
|
161
|
+
// Store subscription using session store adapter
|
|
162
|
+
await this.config.sessionStore.storeSubscription(this.config, connectionID, operation.id || subscription.requestID, subscription);
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Returns the dependencies of the calculated fields of a read model
|
|
166
|
+
* @param readModelClass The read model class
|
|
167
|
+
* @private
|
|
168
|
+
*/
|
|
169
|
+
getCalculatedFieldsDependencies(readModelClass) {
|
|
170
|
+
const readModelMetadata = this.config.readModels[readModelClass.name];
|
|
171
|
+
const dependenciesMap = {};
|
|
172
|
+
readModelMetadata === null || readModelMetadata === void 0 ? void 0 : readModelMetadata.properties.map((property) => {
|
|
173
|
+
dependenciesMap[property.name] = property.dependencies;
|
|
174
|
+
});
|
|
175
|
+
return dependenciesMap;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
exports.MagekReadModelsReader = MagekReadModelsReader;
|
|
179
|
+
tslib_1.__decorate([
|
|
180
|
+
(0, instrumentation_1.Trace)(common_1.TraceActionTypes.READ_MODEL_FIND_BY_ID),
|
|
181
|
+
tslib_1.__metadata("design:type", Function),
|
|
182
|
+
tslib_1.__metadata("design:paramtypes", [Object]),
|
|
183
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
184
|
+
], MagekReadModelsReader.prototype, "findById", null);
|
|
185
|
+
tslib_1.__decorate([
|
|
186
|
+
(0, instrumentation_1.Trace)(common_1.TraceActionTypes.GRAPHQL_READ_MODEL_SEARCH),
|
|
187
|
+
tslib_1.__metadata("design:type", Function),
|
|
188
|
+
tslib_1.__metadata("design:paramtypes", [Object]),
|
|
189
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
190
|
+
], MagekReadModelsReader.prototype, "search", null);
|
|
191
|
+
tslib_1.__decorate([
|
|
192
|
+
(0, instrumentation_1.Trace)(common_1.TraceActionTypes.READ_MODEL_SEARCH),
|
|
193
|
+
tslib_1.__metadata("design:type", Function),
|
|
194
|
+
tslib_1.__metadata("design:paramtypes", [Object, Object, Object, Number, Object, Boolean, Array]),
|
|
195
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
196
|
+
], MagekReadModelsReader.prototype, "readModelSearch", null);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { MagekConfig, Register } from '@magek/common';
|
|
2
|
+
export declare class RegisterHandler {
|
|
3
|
+
static handle(config: MagekConfig, register: Register): Promise<void>;
|
|
4
|
+
static flush(record: Register): Promise<void>;
|
|
5
|
+
private static wrapEvent;
|
|
6
|
+
private static getSuperKind;
|
|
7
|
+
private static getTopicName;
|
|
8
|
+
private static getPartitionKey;
|
|
9
|
+
private static getDefaultStateEventEntityId;
|
|
10
|
+
private static getDefaultNotificationPartitionId;
|
|
11
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RegisterHandler = void 0;
|
|
4
|
+
const common_1 = require("@magek/common");
|
|
5
|
+
const entity_migrated_1 = require("./core-concepts/data-migration/events/entity-migrated");
|
|
6
|
+
const data_migration_started_1 = require("./core-concepts/data-migration/events/data-migration-started");
|
|
7
|
+
const data_migration_finished_1 = require("./core-concepts/data-migration/events/data-migration-finished");
|
|
8
|
+
const magek_1 = require("./magek");
|
|
9
|
+
const entity_touched_1 = require("./core-concepts/touch-entity/events/entity-touched");
|
|
10
|
+
const eventsTypesNames = [
|
|
11
|
+
entity_migrated_1.MagekEntityMigrated.name,
|
|
12
|
+
data_migration_started_1.MagekDataMigrationStarted.name,
|
|
13
|
+
data_migration_finished_1.MagekDataMigrationFinished.name,
|
|
14
|
+
entity_touched_1.MagekEntityTouched.name,
|
|
15
|
+
];
|
|
16
|
+
class RegisterHandler {
|
|
17
|
+
static async handle(config, register) {
|
|
18
|
+
if (register.eventList.length == 0) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
await config.eventStore.store(register.eventList.map((event) => RegisterHandler.wrapEvent(config, event, register)), config);
|
|
22
|
+
}
|
|
23
|
+
static async flush(record) {
|
|
24
|
+
return RegisterHandler.handle(magek_1.Magek.config, record);
|
|
25
|
+
}
|
|
26
|
+
static wrapEvent(config, event, register) {
|
|
27
|
+
const eventTypeName = event.constructor.name;
|
|
28
|
+
const entityTypeName = RegisterHandler.getTopicName(eventTypeName, event, config);
|
|
29
|
+
if (!entityTypeName) {
|
|
30
|
+
throw new common_1.NotFoundError(`Couldn't find information about event ${eventTypeName}. Is the event handled by an entity?`);
|
|
31
|
+
}
|
|
32
|
+
const entityID = RegisterHandler.getPartitionKey(event, config);
|
|
33
|
+
if (!entityID) {
|
|
34
|
+
throw new Error(`Event ${eventTypeName} has an empty 'entityID' or the required 'entityID' method was not implemented. Make sure to return a string-compatible value identifying the entity this event belongs to.`);
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
version: config.currentVersionFor(eventTypeName),
|
|
38
|
+
kind: 'event',
|
|
39
|
+
superKind: RegisterHandler.getSuperKind(eventTypeName),
|
|
40
|
+
entityID,
|
|
41
|
+
requestID: register.requestID,
|
|
42
|
+
currentUser: register.currentUser,
|
|
43
|
+
entityTypeName,
|
|
44
|
+
typeName: eventTypeName,
|
|
45
|
+
value: event,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
static getSuperKind(eventTypeName) {
|
|
49
|
+
return eventsTypesNames.includes(eventTypeName) ? common_1.MAGEK_SUPER_KIND : common_1.DOMAIN_SUPER_KIND;
|
|
50
|
+
}
|
|
51
|
+
static getTopicName(eventTypeName, event, config) {
|
|
52
|
+
var _a, _b;
|
|
53
|
+
if (eventTypeName === entity_migrated_1.MagekEntityMigrated.name) {
|
|
54
|
+
return event.oldEntityName;
|
|
55
|
+
}
|
|
56
|
+
if (eventTypeName === entity_touched_1.MagekEntityTouched.name) {
|
|
57
|
+
return event.entityName;
|
|
58
|
+
}
|
|
59
|
+
if (eventTypeName in config.notifications) {
|
|
60
|
+
return (_a = config.eventToTopic[eventTypeName]) !== null && _a !== void 0 ? _a : 'defaultTopic';
|
|
61
|
+
}
|
|
62
|
+
const reducerInfo = config.reducers[eventTypeName];
|
|
63
|
+
return (_b = reducerInfo === null || reducerInfo === void 0 ? void 0 : reducerInfo.class) === null || _b === void 0 ? void 0 : _b.name;
|
|
64
|
+
}
|
|
65
|
+
static getPartitionKey(event, config) {
|
|
66
|
+
const eventName = event.constructor.name;
|
|
67
|
+
const evtObject = event;
|
|
68
|
+
const entityIdField = config.partitionKeys[eventName];
|
|
69
|
+
if (entityIdField && entityIdField in evtObject && typeof evtObject[entityIdField] === 'string') {
|
|
70
|
+
return evtObject[entityIdField];
|
|
71
|
+
}
|
|
72
|
+
if (eventName in config.notifications) {
|
|
73
|
+
return RegisterHandler.getDefaultNotificationPartitionId(event);
|
|
74
|
+
}
|
|
75
|
+
return RegisterHandler.getDefaultStateEventEntityId(event);
|
|
76
|
+
}
|
|
77
|
+
static getDefaultStateEventEntityId(event) {
|
|
78
|
+
const entityID = event.entityID();
|
|
79
|
+
if (entityID) {
|
|
80
|
+
return entityID;
|
|
81
|
+
}
|
|
82
|
+
throw new Error(`Event ${event.constructor.name} has no specification for the entity ID. Make sure to specify a string-compatible value identifying the entity this event belongs to.
|
|
83
|
+
|
|
84
|
+
You can do it by:
|
|
85
|
+
|
|
86
|
+
1. Adding an entityID method to the event`);
|
|
87
|
+
}
|
|
88
|
+
static getDefaultNotificationPartitionId(event) {
|
|
89
|
+
if (event.partitionId && typeof event.partitionId === 'string') {
|
|
90
|
+
return event.partitionId;
|
|
91
|
+
}
|
|
92
|
+
return 'default';
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
exports.RegisterHandler = RegisterHandler;
|