@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.
- 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
package/dist/magek.js
CHANGED
|
@@ -20,6 +20,8 @@ const event_search_1 = require("./event-search");
|
|
|
20
20
|
*
|
|
21
21
|
*/
|
|
22
22
|
class Magek {
|
|
23
|
+
static configuredEnvironments = new Set();
|
|
24
|
+
static config = new common_1.MagekConfig(checkAndGetCurrentEnv());
|
|
23
25
|
static configureCurrentEnv(configurator) {
|
|
24
26
|
configurator(this.config);
|
|
25
27
|
}
|
|
@@ -115,8 +117,6 @@ class Magek {
|
|
|
115
117
|
}
|
|
116
118
|
}
|
|
117
119
|
exports.Magek = Magek;
|
|
118
|
-
Magek.configuredEnvironments = new Set();
|
|
119
|
-
Magek.config = new common_1.MagekConfig(checkAndGetCurrentEnv());
|
|
120
120
|
function checkAndGetCurrentEnv() {
|
|
121
121
|
const env = process.env.MAGEK_ENV;
|
|
122
122
|
if (!env || env.trim().length == 0) {
|
package/dist/query-dispatcher.js
CHANGED
|
@@ -5,6 +5,8 @@ const common_1 = require("@magek/common");
|
|
|
5
5
|
const global_error_dispatcher_1 = require("./global-error-dispatcher");
|
|
6
6
|
const filter_helpers_1 = require("./services/filter-helpers");
|
|
7
7
|
class MagekQueryDispatcher {
|
|
8
|
+
config;
|
|
9
|
+
globalErrorDispatcher;
|
|
8
10
|
constructor(config) {
|
|
9
11
|
this.config = config;
|
|
10
12
|
this.globalErrorDispatcher = new global_error_dispatcher_1.MagekGlobalErrorDispatcher(config);
|
|
@@ -1,80 +1,83 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var _a;
|
|
3
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
3
|
exports.ReadModelSchemaMigrator = void 0;
|
|
5
4
|
const tslib_1 = require("tslib");
|
|
6
5
|
const common_1 = require("@magek/common");
|
|
7
6
|
const instrumentation_1 = require("./instrumentation");
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
if (this.needsMigration(readModel, readModelName)) {
|
|
18
|
-
return await this.applyAllMigrations(readModel, readModelName);
|
|
7
|
+
let ReadModelSchemaMigrator = (() => {
|
|
8
|
+
let _instanceExtraInitializers = [];
|
|
9
|
+
let _migrate_decorators;
|
|
10
|
+
return class ReadModelSchemaMigrator {
|
|
11
|
+
static {
|
|
12
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
13
|
+
_migrate_decorators = [(0, instrumentation_1.trace)(common_1.TraceActionTypes.READ_MODEL_SCHEMA_MIGRATOR_MIGRATE)];
|
|
14
|
+
tslib_1.__esDecorate(this, null, _migrate_decorators, { kind: "method", name: "migrate", static: false, private: false, access: { has: obj => "migrate" in obj, get: obj => obj.migrate }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
15
|
+
if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
19
16
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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');
|
|
17
|
+
config = tslib_1.__runInitializers(this, _instanceExtraInitializers);
|
|
18
|
+
constructor(config) {
|
|
19
|
+
this.config = config;
|
|
27
20
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
21
|
+
/**
|
|
22
|
+
* **NOTE:** Read model schema migration is deprecated. Prefer data migration.
|
|
23
|
+
*/
|
|
24
|
+
async migrate(readModel, readModelName) {
|
|
25
|
+
this.checkVersionRange(readModel, readModelName);
|
|
26
|
+
if (this.needsMigration(readModel, readModelName)) {
|
|
27
|
+
return await this.applyAllMigrations(readModel, readModelName);
|
|
28
|
+
}
|
|
29
|
+
return readModel; // The current version is exactly the same as the version of the concept
|
|
32
30
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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));
|
|
31
|
+
checkVersionRange(readModel, readModelName) {
|
|
32
|
+
const readModelVersion = ReadModelSchemaMigrator.readModelSchemaVersion(readModel);
|
|
33
|
+
if (readModelVersion < 1) {
|
|
34
|
+
throw new common_1.InvalidVersionError(`Received an invalid schema version value, ${readModelVersion}, for ${readModelName}. ` +
|
|
35
|
+
'Versions must be greater than 0');
|
|
36
|
+
}
|
|
37
|
+
const currentVersion = this.config.currentVersionFor(readModelName);
|
|
38
|
+
if (currentVersion < readModelVersion) {
|
|
39
|
+
throw new common_1.InvalidVersionError(`Can not migrate schema an unknown version: The current schema version of ${readModelName} is ${currentVersion}, which is ` +
|
|
40
|
+
`lower than the received version ${readModelVersion}`);
|
|
41
|
+
}
|
|
48
42
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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?');
|
|
43
|
+
needsMigration(readModel, readModelName) {
|
|
44
|
+
const currentVersion = this.config.currentVersionFor(readModelName);
|
|
45
|
+
return currentVersion > ReadModelSchemaMigrator.readModelSchemaVersion(readModel);
|
|
62
46
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
47
|
+
async applyAllMigrations(oldReadModel, readModelName) {
|
|
48
|
+
const logger = (0, common_1.getLogger)(this.config, 'ReadModelSchemaMigrator#applyAllMigrations');
|
|
49
|
+
const oldVersion = ReadModelSchemaMigrator.readModelSchemaVersion(oldReadModel);
|
|
50
|
+
const currentVersion = this.config.currentVersionFor(readModelName);
|
|
51
|
+
logger.info(`Migrating Schema ${readModelName} from version ${oldVersion} to version ${currentVersion}`);
|
|
52
|
+
logger.debug('ReadModel before schema migration:\n', oldReadModel);
|
|
53
|
+
const migrations = this.config.schemaMigrations[readModelName];
|
|
54
|
+
let migratedValue = oldReadModel;
|
|
55
|
+
for (let toVersion = oldVersion + 1; toVersion <= currentVersion; toVersion++) {
|
|
56
|
+
migratedValue = await this.applyMigration(migratedValue, migrations.get(toVersion));
|
|
57
|
+
}
|
|
58
|
+
const newReadModel = Object.assign(migratedValue, {
|
|
59
|
+
magekMetadata: {
|
|
60
|
+
...oldReadModel.magekMetadata,
|
|
61
|
+
schemaVersion: currentVersion,
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
logger.debug('ReadModel after schema migration:\n', newReadModel);
|
|
65
|
+
return newReadModel;
|
|
66
|
+
}
|
|
67
|
+
async applyMigration(oldValue, migration) {
|
|
68
|
+
const logger = (0, common_1.getLogger)(this.config, 'ReadModelSchemaMigrator#applyMigration');
|
|
69
|
+
if (!migration) {
|
|
70
|
+
throw new common_1.InvalidVersionError('Received an undefined schema migration value. Are there "gaps" between the versions of the schema migrations?');
|
|
71
|
+
}
|
|
72
|
+
const oldConcept = Object.assign(new migration.fromSchema(), oldValue);
|
|
73
|
+
const migrationMethod = new migration.migrationClass()[migration.methodName];
|
|
74
|
+
const newConcept = await migrationMethod(oldConcept);
|
|
75
|
+
logger.debug(`Partial schema migration finished. Schema migrated from oldValue=${JSON.stringify(oldConcept)} to newValue=${JSON.stringify(newConcept)}`);
|
|
76
|
+
return newConcept;
|
|
77
|
+
}
|
|
78
|
+
static readModelSchemaVersion(readModel) {
|
|
79
|
+
return readModel.magekMetadata?.schemaVersion ?? 1;
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
})();
|
|
74
83
|
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);
|
|
@@ -7,190 +7,188 @@ const magek_1 = require("./magek");
|
|
|
7
7
|
const filter_helpers_1 = require("./services/filter-helpers");
|
|
8
8
|
const read_model_schema_migrator_1 = require("./read-model-schema-migrator");
|
|
9
9
|
const instrumentation_1 = require("./instrumentation");
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
10
|
+
let MagekReadModelsReader = (() => {
|
|
11
|
+
let _instanceExtraInitializers = [];
|
|
12
|
+
let _findById_decorators;
|
|
13
|
+
let _search_decorators;
|
|
14
|
+
let _readModelSearch_decorators;
|
|
15
|
+
return class MagekReadModelsReader {
|
|
16
|
+
static {
|
|
17
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
18
|
+
_findById_decorators = [(0, instrumentation_1.trace)(common_1.TraceActionTypes.READ_MODEL_FIND_BY_ID)];
|
|
19
|
+
_search_decorators = [(0, instrumentation_1.trace)(common_1.TraceActionTypes.GRAPHQL_READ_MODEL_SEARCH)];
|
|
20
|
+
_readModelSearch_decorators = [(0, instrumentation_1.trace)(common_1.TraceActionTypes.READ_MODEL_SEARCH)];
|
|
21
|
+
tslib_1.__esDecorate(this, null, _findById_decorators, { kind: "method", name: "findById", static: false, private: false, access: { has: obj => "findById" in obj, get: obj => obj.findById }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
22
|
+
tslib_1.__esDecorate(this, null, _search_decorators, { kind: "method", name: "search", static: false, private: false, access: { has: obj => "search" in obj, get: obj => obj.search }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
23
|
+
tslib_1.__esDecorate(this, null, _readModelSearch_decorators, { kind: "method", name: "readModelSearch", static: false, private: false, access: { has: obj => "readModelSearch" in obj, get: obj => obj.readModelSearch }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
24
|
+
if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
25
|
+
}
|
|
26
|
+
config = tslib_1.__runInitializers(this, _instanceExtraInitializers);
|
|
27
|
+
constructor(config) {
|
|
28
|
+
this.config = config;
|
|
29
|
+
}
|
|
30
|
+
async findById(readModelRequest) {
|
|
31
|
+
await this.validateByIdRequest(readModelRequest);
|
|
32
|
+
const readModelMetadata = this.config.readModels[readModelRequest.class.name];
|
|
33
|
+
const readModelTransformedRequest = await (0, filter_helpers_1.applyReadModelRequestBeforeFunctions)(readModelRequest, readModelMetadata.before, readModelRequest.currentUser);
|
|
34
|
+
const key = readModelTransformedRequest.key;
|
|
35
|
+
if (!key) {
|
|
36
|
+
throw 'Tried to run a findById operation without providing a key. An ID is required to perform this operation.';
|
|
29
37
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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));
|
|
38
|
+
const currentReadModel = await magek_1.Magek.readModel(readModelMetadata.class).findById(key.id, key.sequenceKey);
|
|
39
|
+
if (currentReadModel) {
|
|
40
|
+
const readModelInstance = (0, common_1.createInstance)(readModelMetadata.class, currentReadModel);
|
|
41
|
+
const readModelName = readModelMetadata.class.name;
|
|
42
|
+
const readModelSchemaMigrator = new read_model_schema_migrator_1.ReadModelSchemaMigrator(this.config);
|
|
43
|
+
if (Array.isArray(readModelInstance)) {
|
|
44
|
+
return [await readModelSchemaMigrator.migrate(readModelInstance[0], readModelName)];
|
|
50
45
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
return
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
return
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
const processedItems = await Promise.all(searchResult.items.map(processInstance));
|
|
46
|
+
return readModelSchemaMigrator.migrate(readModelInstance, readModelName);
|
|
47
|
+
}
|
|
48
|
+
return currentReadModel;
|
|
49
|
+
}
|
|
50
|
+
async search(readModelRequest) {
|
|
51
|
+
await this.validateRequest(readModelRequest);
|
|
52
|
+
const readModelMetadata = this.config.readModels[readModelRequest.class.name];
|
|
53
|
+
const readModelTransformedRequest = await (0, filter_helpers_1.applyReadModelRequestBeforeFunctions)(readModelRequest, readModelMetadata.before, readModelRequest.currentUser);
|
|
54
|
+
return await this.readModelSearch(readModelMetadata.class, readModelTransformedRequest.filters, readModelTransformedRequest.sortBy, readModelTransformedRequest.limit, readModelTransformedRequest.afterCursor, readModelTransformedRequest.paginatedVersion, readModelTransformedRequest.select);
|
|
55
|
+
}
|
|
56
|
+
async readModelSearch(readModelClass, filters, sort, limit, afterCursor, paginatedVersion, select) {
|
|
57
|
+
const readModelName = readModelClass.name;
|
|
58
|
+
let selectWithDependencies = undefined;
|
|
59
|
+
const calculatedFieldsDependencies = this.getCalculatedFieldsDependencies(readModelClass);
|
|
60
|
+
if (select && Object.keys(calculatedFieldsDependencies).length > 0) {
|
|
61
|
+
const extendedSelect = new Set(select);
|
|
62
|
+
select.forEach((field) => {
|
|
63
|
+
const topLevelField = field.split('.')[0].replace('[]', '');
|
|
64
|
+
if (calculatedFieldsDependencies[topLevelField]) {
|
|
65
|
+
calculatedFieldsDependencies[topLevelField].map((dependency) => extendedSelect.add(dependency));
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
selectWithDependencies = Array.from(extendedSelect);
|
|
69
|
+
}
|
|
70
|
+
const searchResult = await this.config.readModelStore.search(this.config, readModelName, filters ?? {}, sort ?? {}, limit, afterCursor, paginatedVersion ?? false, selectWithDependencies ?? select);
|
|
71
|
+
const readModels = this.createReadModelInstances(searchResult, readModelClass);
|
|
72
|
+
if (select) {
|
|
73
|
+
return this.createReadModelInstancesWithCalculatedProperties(searchResult, readModelClass, select ?? []);
|
|
74
|
+
}
|
|
75
|
+
return this.migrateReadModels(readModels, readModelName);
|
|
76
|
+
}
|
|
77
|
+
async finderByIdFunction(readModelClass, id, sequenceKey) {
|
|
78
|
+
const result = await this.config.readModelStore.fetch(this.config, readModelClass.name, id, sequenceKey);
|
|
79
|
+
if (!result) {
|
|
80
|
+
throw new Error(`Read model not found: ${readModelClass.name} with id ${id}`);
|
|
81
|
+
}
|
|
82
|
+
// The adapter returns ReadOnlyNonEmptyArray<TReadModel> | undefined
|
|
83
|
+
// For backward compatibility, we return a single item if sequenceKey is not provided
|
|
84
|
+
return sequenceKey ? result : result[0];
|
|
85
|
+
}
|
|
86
|
+
async migrateReadModels(readModels, readModelName) {
|
|
87
|
+
const readModelSchemaMigrator = new read_model_schema_migrator_1.ReadModelSchemaMigrator(this.config);
|
|
88
|
+
if (Array.isArray(readModels)) {
|
|
89
|
+
return Promise.all(readModels.map((readModel) => readModelSchemaMigrator.migrate(readModel, readModelName)));
|
|
90
|
+
}
|
|
91
|
+
readModels.items = await Promise.all(readModels.items.map((readModel) => readModelSchemaMigrator.migrate(readModel, readModelName)));
|
|
92
|
+
return readModels;
|
|
93
|
+
}
|
|
94
|
+
createReadModelInstances(searchResult, readModelClass) {
|
|
95
|
+
if (Array.isArray(searchResult)) {
|
|
96
|
+
return (0, common_1.createInstances)(readModelClass, searchResult);
|
|
97
|
+
}
|
|
104
98
|
return {
|
|
105
99
|
...searchResult,
|
|
106
|
-
items:
|
|
100
|
+
items: (0, common_1.createInstances)(readModelClass, searchResult.items),
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Creates instances of the read model class with the calculated properties included
|
|
105
|
+
* @param searchResult The search result
|
|
106
|
+
* @param readModelClass The read model class
|
|
107
|
+
* @param propertiesToInclude The properties to include in the response
|
|
108
|
+
* @private
|
|
109
|
+
*/
|
|
110
|
+
async createReadModelInstancesWithCalculatedProperties(searchResult, readModelClass, propertiesToInclude) {
|
|
111
|
+
const processInstance = async (raw) => {
|
|
112
|
+
const instance = await (0, common_1.createInstanceWithCalculatedProperties)(readModelClass, raw, propertiesToInclude);
|
|
113
|
+
return instance;
|
|
107
114
|
};
|
|
115
|
+
if (Array.isArray(searchResult)) {
|
|
116
|
+
return await Promise.all(searchResult.map(processInstance));
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
const processedItems = await Promise.all(searchResult.items.map(processInstance));
|
|
120
|
+
return {
|
|
121
|
+
...searchResult,
|
|
122
|
+
items: processedItems,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
async subscribe(connectionID, readModelRequest, operation) {
|
|
127
|
+
await this.validateRequest(readModelRequest);
|
|
128
|
+
return this.processSubscription(connectionID, readModelRequest, operation);
|
|
129
|
+
}
|
|
130
|
+
async unsubscribe(connectionID, subscriptionID) {
|
|
131
|
+
return this.config.sessionStore.deleteSubscription(this.config, connectionID, subscriptionID);
|
|
132
|
+
}
|
|
133
|
+
async unsubscribeAll(connectionID) {
|
|
134
|
+
return this.config.sessionStore.deleteSubscriptionsForConnection(this.config, connectionID);
|
|
135
|
+
}
|
|
136
|
+
async validateByIdRequest(readModelByIdRequest) {
|
|
137
|
+
const logger = (0, common_1.getLogger)(this.config, 'MagekReadModelsReader#validateByIdRequest');
|
|
138
|
+
logger.debug('Validating the following read model by id request: ', readModelByIdRequest);
|
|
139
|
+
if (!readModelByIdRequest.version) {
|
|
140
|
+
throw new common_1.InvalidParameterError('The required request "version" was not present');
|
|
141
|
+
}
|
|
142
|
+
const readModelMetadata = this.config.readModels[readModelByIdRequest.class.name];
|
|
143
|
+
if (!readModelMetadata) {
|
|
144
|
+
throw new common_1.NotFoundError(`Could not find read model ${readModelByIdRequest.class.name}`);
|
|
145
|
+
}
|
|
146
|
+
await readModelMetadata.authorizer(readModelByIdRequest.currentUser, readModelByIdRequest);
|
|
147
|
+
if (readModelByIdRequest?.key?.sequenceKey &&
|
|
148
|
+
readModelByIdRequest.key.sequenceKey.name !== this.config.readModelSequenceKeys[readModelByIdRequest.class.name]) {
|
|
149
|
+
throw new common_1.InvalidParameterError(`Could not find a sort key defined for ${readModelByIdRequest.class.name} named '${readModelByIdRequest.key.sequenceKey.name}'.`);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
async validateRequest(readModelRequest) {
|
|
153
|
+
const logger = (0, common_1.getLogger)(this.config, 'MagekReadModelsReader#validateRequest');
|
|
154
|
+
logger.debug('Validating the following read model request: ', readModelRequest);
|
|
155
|
+
if (!readModelRequest.version) {
|
|
156
|
+
throw new common_1.InvalidParameterError('The required request "version" was not present');
|
|
157
|
+
}
|
|
158
|
+
const readModelMetadata = this.config.readModels[readModelRequest.class.name];
|
|
159
|
+
if (!readModelMetadata) {
|
|
160
|
+
throw new common_1.NotFoundError(`Could not find read model ${readModelRequest.class.name}`);
|
|
161
|
+
}
|
|
162
|
+
await readModelMetadata.authorizer(readModelRequest.currentUser, readModelRequest);
|
|
163
|
+
}
|
|
164
|
+
async processSubscription(connectionID, readModelRequest, operation) {
|
|
165
|
+
const logger = (0, common_1.getLogger)(this.config, 'MagekReadModelsReader#processSubscription');
|
|
166
|
+
logger.info(`Processing subscription of connection '${connectionID}' to read model '${readModelRequest.class.name}' with the following data: `, readModelRequest);
|
|
167
|
+
const readModelMetadata = this.config.readModels[readModelRequest.class.name];
|
|
168
|
+
const newReadModelRequest = await (0, filter_helpers_1.applyReadModelRequestBeforeFunctions)(readModelRequest, readModelMetadata.before, readModelRequest.currentUser);
|
|
169
|
+
const nowEpoch = Math.floor(new Date().getTime() / 1000);
|
|
170
|
+
const subscription = {
|
|
171
|
+
...newReadModelRequest,
|
|
172
|
+
expirationTime: nowEpoch + this.config.subscriptions.maxDurationInSeconds,
|
|
173
|
+
connectionID,
|
|
174
|
+
operation,
|
|
175
|
+
};
|
|
176
|
+
// Store subscription using session store adapter
|
|
177
|
+
await this.config.sessionStore.storeSubscription(this.config, connectionID, operation.id || subscription.requestID, subscription);
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Returns the dependencies of the calculated fields of a read model
|
|
181
|
+
* @param readModelClass The read model class
|
|
182
|
+
* @private
|
|
183
|
+
*/
|
|
184
|
+
getCalculatedFieldsDependencies(readModelClass) {
|
|
185
|
+
const readModelMetadata = this.config.readModels[readModelClass.name];
|
|
186
|
+
const dependenciesMap = {};
|
|
187
|
+
readModelMetadata?.properties.map((property) => {
|
|
188
|
+
dependenciesMap[property.name] = property.dependencies;
|
|
189
|
+
});
|
|
190
|
+
return dependenciesMap;
|
|
108
191
|
}
|
|
109
|
-
}
|
|
110
|
-
|
|
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
|
-
}
|
|
192
|
+
};
|
|
193
|
+
})();
|
|
178
194
|
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);
|
package/dist/register-handler.js
CHANGED
|
@@ -43,13 +43,13 @@ class RegisterHandler {
|
|
|
43
43
|
entityTypeName,
|
|
44
44
|
typeName: eventTypeName,
|
|
45
45
|
value: event,
|
|
46
|
+
createdAt: (0, common_1.getTimestampGenerator)().next(),
|
|
46
47
|
};
|
|
47
48
|
}
|
|
48
49
|
static getSuperKind(eventTypeName) {
|
|
49
50
|
return eventsTypesNames.includes(eventTypeName) ? common_1.MAGEK_SUPER_KIND : common_1.DOMAIN_SUPER_KIND;
|
|
50
51
|
}
|
|
51
52
|
static getTopicName(eventTypeName, event, config) {
|
|
52
|
-
var _a, _b;
|
|
53
53
|
if (eventTypeName === entity_migrated_1.MagekEntityMigrated.name) {
|
|
54
54
|
return event.oldEntityName;
|
|
55
55
|
}
|
|
@@ -57,10 +57,10 @@ class RegisterHandler {
|
|
|
57
57
|
return event.entityName;
|
|
58
58
|
}
|
|
59
59
|
if (eventTypeName in config.notifications) {
|
|
60
|
-
return
|
|
60
|
+
return config.eventToTopic[eventTypeName] ?? 'defaultTopic';
|
|
61
61
|
}
|
|
62
62
|
const reducerInfo = config.reducers[eventTypeName];
|
|
63
|
-
return
|
|
63
|
+
return reducerInfo?.class?.name;
|
|
64
64
|
}
|
|
65
65
|
static getPartitionKey(event, config) {
|
|
66
66
|
const eventName = event.constructor.name;
|