@magek/core 0.0.6 → 0.0.8
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 +61 -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 +4 -0
- package/dist/decorators/index.js +3 -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/returns.d.ts +37 -0
- package/dist/decorators/returns.js +154 -0
- 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 +107 -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 +20 -20
- 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 +99 -92
- package/dist/token-verifier.js +2 -1
- package/dist/utils/promises.d.ts +25 -0
- package/dist/utils/promises.js +43 -0
- package/package.json +4 -4
- package/dist/decorators/stage3-utils.d.ts +0 -6
- package/dist/decorators/stage3-utils.js +0 -25
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RETURNS_METADATA_KEY = void 0;
|
|
4
|
+
exports.getReturnTypeMetadata = getReturnTypeMetadata;
|
|
5
|
+
exports.returns = returns;
|
|
6
|
+
/** Symbol used to store return type metadata in decorator context.metadata */
|
|
7
|
+
exports.RETURNS_METADATA_KEY = Symbol.for('magek:returns');
|
|
8
|
+
/**
|
|
9
|
+
* Analyze a type and convert it to TypeMetadata for return types.
|
|
10
|
+
* This returns the GraphQL-compatible type directly (not wrapped in Promise).
|
|
11
|
+
*/
|
|
12
|
+
function analyzeReturnType(targetType) {
|
|
13
|
+
// Handle primitives
|
|
14
|
+
if (targetType === String) {
|
|
15
|
+
return {
|
|
16
|
+
name: 'string',
|
|
17
|
+
typeGroup: 'String',
|
|
18
|
+
typeName: 'String',
|
|
19
|
+
parameters: [],
|
|
20
|
+
isNullable: false,
|
|
21
|
+
isGetAccessor: false,
|
|
22
|
+
type: String,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
if (targetType === Number) {
|
|
26
|
+
return {
|
|
27
|
+
name: 'number',
|
|
28
|
+
typeGroup: 'Number',
|
|
29
|
+
typeName: 'Number',
|
|
30
|
+
parameters: [],
|
|
31
|
+
isNullable: false,
|
|
32
|
+
isGetAccessor: false,
|
|
33
|
+
type: Number,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
if (targetType === Boolean) {
|
|
37
|
+
return {
|
|
38
|
+
name: 'boolean',
|
|
39
|
+
typeGroup: 'Boolean',
|
|
40
|
+
typeName: 'Boolean',
|
|
41
|
+
parameters: [],
|
|
42
|
+
isNullable: false,
|
|
43
|
+
isGetAccessor: false,
|
|
44
|
+
type: Boolean,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
// Handle void - return never to signal void return
|
|
48
|
+
if (targetType === undefined || targetType === null) {
|
|
49
|
+
return {
|
|
50
|
+
name: 'never',
|
|
51
|
+
typeGroup: 'Other',
|
|
52
|
+
typeName: 'never',
|
|
53
|
+
parameters: [],
|
|
54
|
+
isNullable: false,
|
|
55
|
+
isGetAccessor: false,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
// Handle Array
|
|
59
|
+
if (Array.isArray(targetType)) {
|
|
60
|
+
if (targetType.length === 0) {
|
|
61
|
+
throw new Error('@returns decorator array type must specify an element type, e.g., @returns(type => [String])');
|
|
62
|
+
}
|
|
63
|
+
const elementType = targetType[0];
|
|
64
|
+
const elementMetadata = analyzeReturnType(elementType);
|
|
65
|
+
return {
|
|
66
|
+
name: `${elementMetadata.name}[]`,
|
|
67
|
+
typeGroup: 'Array',
|
|
68
|
+
typeName: 'Array',
|
|
69
|
+
parameters: [elementMetadata],
|
|
70
|
+
isNullable: false,
|
|
71
|
+
isGetAccessor: false,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
// Handle Class types (e.g., UUID, custom types)
|
|
75
|
+
if (typeof targetType === 'function') {
|
|
76
|
+
return {
|
|
77
|
+
name: targetType.name || 'Unknown',
|
|
78
|
+
typeGroup: 'Class',
|
|
79
|
+
typeName: targetType.name,
|
|
80
|
+
parameters: [],
|
|
81
|
+
isNullable: false,
|
|
82
|
+
isGetAccessor: false,
|
|
83
|
+
type: targetType,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
// Default fallback
|
|
87
|
+
return {
|
|
88
|
+
name: 'unknown',
|
|
89
|
+
typeGroup: 'Other',
|
|
90
|
+
typeName: 'unknown',
|
|
91
|
+
parameters: [],
|
|
92
|
+
isNullable: false,
|
|
93
|
+
isGetAccessor: false,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Get the return type metadata for a method from decorator metadata.
|
|
98
|
+
*
|
|
99
|
+
* @param contextMetadata - The context.metadata from a class decorator
|
|
100
|
+
* @param methodName - The name of the method to get return type for
|
|
101
|
+
*/
|
|
102
|
+
function getReturnTypeMetadata(contextMetadata, methodName) {
|
|
103
|
+
if (!contextMetadata) {
|
|
104
|
+
return undefined;
|
|
105
|
+
}
|
|
106
|
+
const returnsMetadataList = contextMetadata[exports.RETURNS_METADATA_KEY];
|
|
107
|
+
if (!returnsMetadataList) {
|
|
108
|
+
return undefined;
|
|
109
|
+
}
|
|
110
|
+
const metadata = returnsMetadataList.find((m) => m.methodName === methodName);
|
|
111
|
+
if (!metadata) {
|
|
112
|
+
return undefined;
|
|
113
|
+
}
|
|
114
|
+
// Evaluate the type function and analyze the result
|
|
115
|
+
const typeResult = metadata.typeFunction();
|
|
116
|
+
// Return the actual type (not wrapped in Promise) - this is the GraphQL return type
|
|
117
|
+
return analyzeReturnType(typeResult);
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* @returns() decorator for explicit return type declaration on methods.
|
|
121
|
+
*
|
|
122
|
+
* Uses TC39 Stage 3 decorators to capture return type metadata that is used
|
|
123
|
+
* for GraphQL schema generation. The type specified should be the GraphQL
|
|
124
|
+
* return type (not wrapped in Promise).
|
|
125
|
+
*
|
|
126
|
+
* Usage:
|
|
127
|
+
* @returns(type => UUID)
|
|
128
|
+
* public static async handle(...): Promise<UUID> { ... }
|
|
129
|
+
*
|
|
130
|
+
* @returns(type => String)
|
|
131
|
+
* public static async handle(...): Promise<string> { ... }
|
|
132
|
+
*
|
|
133
|
+
* @returns(type => [CartItem])
|
|
134
|
+
* public static async handle(...): Promise<CartItem[]> { ... }
|
|
135
|
+
*/
|
|
136
|
+
function returns(typeFunction) {
|
|
137
|
+
return function returnsDecorator(_target, context) {
|
|
138
|
+
const methodName = context.name.toString();
|
|
139
|
+
// Store in context.metadata for later retrieval by class decorators
|
|
140
|
+
if (context.metadata) {
|
|
141
|
+
if (!context.metadata[exports.RETURNS_METADATA_KEY]) {
|
|
142
|
+
context.metadata[exports.RETURNS_METADATA_KEY] = [];
|
|
143
|
+
}
|
|
144
|
+
const returnsList = context.metadata[exports.RETURNS_METADATA_KEY];
|
|
145
|
+
// Remove any existing entry for this method (in case of decorator re-application)
|
|
146
|
+
const filteredList = returnsList.filter((m) => m.methodName !== methodName);
|
|
147
|
+
filteredList.push({
|
|
148
|
+
methodName,
|
|
149
|
+
typeFunction,
|
|
150
|
+
});
|
|
151
|
+
context.metadata[exports.RETURNS_METADATA_KEY] = filteredList;
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
}
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { Class, RoleMetadata, RoleInterface } from '@magek/common';
|
|
2
|
+
import { ClassDecoratorContext } from './decorator-types';
|
|
2
3
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
4
|
+
* Decorator to mark a class as a Magek Role.
|
|
5
|
+
* Roles define authorization and authentication configurations.
|
|
6
|
+
*
|
|
7
|
+
* Uses TC39 Stage 3 decorators.
|
|
8
|
+
*
|
|
9
|
+
* @param roleMetadata - Role configuration including auth settings
|
|
10
|
+
* @returns A class decorator function
|
|
5
11
|
*/
|
|
6
|
-
export declare function Role(roleMetadata?: RoleMetadata): (role: Class<RoleInterface
|
|
12
|
+
export declare function Role(roleMetadata?: RoleMetadata): (role: Class<RoleInterface>, context: ClassDecoratorContext) => void;
|
package/dist/decorators/role.js
CHANGED
|
@@ -3,11 +3,16 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.Role = Role;
|
|
4
4
|
const magek_1 = require("../magek");
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* Decorator to mark a class as a Magek Role.
|
|
7
|
+
* Roles define authorization and authentication configurations.
|
|
8
|
+
*
|
|
9
|
+
* Uses TC39 Stage 3 decorators.
|
|
10
|
+
*
|
|
11
|
+
* @param roleMetadata - Role configuration including auth settings
|
|
12
|
+
* @returns A class decorator function
|
|
8
13
|
*/
|
|
9
14
|
function Role(roleMetadata = { auth: {} }) {
|
|
10
|
-
return (role) => {
|
|
15
|
+
return (role, _context) => {
|
|
11
16
|
magek_1.Magek.configureCurrentEnv((config) => {
|
|
12
17
|
config.roles[role.name] = roleMetadata;
|
|
13
18
|
});
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { ScheduledCommandInterface, ScheduleInterface } from '@magek/common';
|
|
2
|
+
import { ClassDecoratorContext } from './decorator-types';
|
|
2
3
|
/**
|
|
3
4
|
* Decorator to mark a class as a Magek Scheduled Command.
|
|
4
5
|
* Scheduled commands are executed automatically based on a schedule.
|
|
5
6
|
*
|
|
7
|
+
* Uses TC39 Stage 3 decorators.
|
|
8
|
+
*
|
|
6
9
|
* @param attributes - Schedule configuration (e.g., cron expression)
|
|
7
10
|
* @returns A class decorator function
|
|
8
11
|
*/
|
|
9
|
-
export declare function ScheduledCommand(attributes: ScheduleInterface): (scheduledCommandClass: ScheduledCommandInterface) => void;
|
|
12
|
+
export declare function ScheduledCommand(attributes: ScheduleInterface): (scheduledCommandClass: ScheduledCommandInterface, context: ClassDecoratorContext) => void;
|
|
@@ -6,11 +6,13 @@ const magek_1 = require("../magek");
|
|
|
6
6
|
* Decorator to mark a class as a Magek Scheduled Command.
|
|
7
7
|
* Scheduled commands are executed automatically based on a schedule.
|
|
8
8
|
*
|
|
9
|
+
* Uses TC39 Stage 3 decorators.
|
|
10
|
+
*
|
|
9
11
|
* @param attributes - Schedule configuration (e.g., cron expression)
|
|
10
12
|
* @returns A class decorator function
|
|
11
13
|
*/
|
|
12
14
|
function ScheduledCommand(attributes) {
|
|
13
|
-
return (commandClass) => {
|
|
15
|
+
return (commandClass, _context) => {
|
|
14
16
|
magek_1.Magek.configureCurrentEnv((config) => {
|
|
15
17
|
if (config.scheduledCommandHandlers[commandClass.name]) {
|
|
16
18
|
throw new Error(`A command called ${commandClass.name} is already registered.
|
|
@@ -1,36 +1,20 @@
|
|
|
1
|
-
import { Class, AnyClass
|
|
2
|
-
|
|
3
|
-
* Stage 3 method decorator context
|
|
4
|
-
*/
|
|
5
|
-
interface Stage3MethodContext {
|
|
6
|
-
kind: 'method';
|
|
7
|
-
name: string | symbol;
|
|
8
|
-
static: boolean;
|
|
9
|
-
private: boolean;
|
|
10
|
-
metadata: Record<string | symbol, unknown>;
|
|
11
|
-
addInitializer?: (initializer: () => void) => void;
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* Stage 3 class decorator context
|
|
15
|
-
*/
|
|
16
|
-
interface Stage3ClassContext {
|
|
17
|
-
kind: 'class';
|
|
18
|
-
name: string | undefined;
|
|
19
|
-
metadata: Record<string | symbol, unknown>;
|
|
20
|
-
addInitializer?: (initializer: () => void) => void;
|
|
21
|
-
}
|
|
1
|
+
import { Class, AnyClass } from '@magek/common';
|
|
2
|
+
import { MethodDecoratorContext, ClassDecoratorContext } from './decorator-types';
|
|
22
3
|
/**
|
|
23
4
|
* **NOTE:** Using this decorator for read model migrations is deprecated. Prefer using `@DataMigration` instead.
|
|
5
|
+
*
|
|
6
|
+
* Uses TC39 Stage 3 decorators.
|
|
24
7
|
*/
|
|
25
|
-
export declare function SchemaMigration(conceptClass: AnyClass): (schemaMigrationClass: AnyClass, context
|
|
8
|
+
export declare function SchemaMigration(conceptClass: AnyClass): (schemaMigrationClass: AnyClass, context: ClassDecoratorContext) => void;
|
|
26
9
|
/**
|
|
27
|
-
* Decorator to tell Magek the version you are migrating to
|
|
10
|
+
* Decorator to tell Magek the version you are migrating to.
|
|
11
|
+
*
|
|
12
|
+
* Uses TC39 Stage 3 decorators.
|
|
13
|
+
*
|
|
28
14
|
* @param toVersion
|
|
29
15
|
* @param props
|
|
30
16
|
*/
|
|
31
|
-
export declare function
|
|
17
|
+
export declare function toVersion<TOldSchema, TNewSchema>(toVersion: number, props: {
|
|
32
18
|
fromSchema: Class<TOldSchema>;
|
|
33
19
|
toSchema: Class<TNewSchema>;
|
|
34
|
-
}): (
|
|
35
|
-
type MigrationMethod<TOldSchema, TNewSchema> = TypedPropertyDescriptor<(old: TOldSchema) => Promise<TNewSchema>>;
|
|
36
|
-
export {};
|
|
20
|
+
}): (method: Function, context: MethodDecoratorContext) => void;
|
|
@@ -1,43 +1,24 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.SchemaMigration = SchemaMigration;
|
|
4
|
-
exports.
|
|
4
|
+
exports.toVersion = toVersion;
|
|
5
5
|
const magek_1 = require("../magek");
|
|
6
6
|
const common_1 = require("@magek/common");
|
|
7
7
|
const migrationMethodsMetadataKey = 'magek:migrationsMethods';
|
|
8
|
-
|
|
9
|
-
* Type guard to detect Stage 3 method decorator context
|
|
10
|
-
*/
|
|
11
|
-
function isStage3MethodContext(arg) {
|
|
12
|
-
return (arg !== null &&
|
|
13
|
-
typeof arg === 'object' &&
|
|
14
|
-
'kind' in arg &&
|
|
15
|
-
arg.kind === 'method' &&
|
|
16
|
-
'name' in arg);
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Type guard to detect Stage 3 class decorator context
|
|
20
|
-
*/
|
|
21
|
-
function isStage3ClassContext(arg) {
|
|
22
|
-
return (arg !== null &&
|
|
23
|
-
typeof arg === 'object' &&
|
|
24
|
-
'kind' in arg &&
|
|
25
|
-
arg.kind === 'class' &&
|
|
26
|
-
'metadata' in arg);
|
|
27
|
-
}
|
|
28
|
-
// Symbol for storing migration metadata in Stage 3 decorator context.metadata
|
|
8
|
+
// Symbol for storing migration metadata in decorator context.metadata
|
|
29
9
|
const MIGRATIONS_METADATA_KEY = Symbol.for('magek:migrationsMethods');
|
|
30
10
|
/**
|
|
31
11
|
* **NOTE:** Using this decorator for read model migrations is deprecated. Prefer using `@DataMigration` instead.
|
|
12
|
+
*
|
|
13
|
+
* Uses TC39 Stage 3 decorators.
|
|
32
14
|
*/
|
|
33
15
|
function SchemaMigration(conceptClass) {
|
|
34
16
|
return (schemaMigrationClass, context) => {
|
|
35
17
|
magek_1.Magek.configureCurrentEnv((config) => {
|
|
36
18
|
const conceptMigrations = getConceptMigrations(config, conceptClass);
|
|
37
|
-
// Get migration methods
|
|
19
|
+
// Get migration methods from context.metadata
|
|
38
20
|
let migrationMethodsMetadata;
|
|
39
|
-
if (
|
|
40
|
-
// Stage 3: read from context.metadata
|
|
21
|
+
if (context.metadata) {
|
|
41
22
|
migrationMethodsMetadata =
|
|
42
23
|
context.metadata[MIGRATIONS_METADATA_KEY] || [];
|
|
43
24
|
// Update each metadata entry with the actual class reference
|
|
@@ -47,11 +28,10 @@ function SchemaMigration(conceptClass) {
|
|
|
47
28
|
}));
|
|
48
29
|
}
|
|
49
30
|
else {
|
|
50
|
-
|
|
51
|
-
migrationMethodsMetadata = getMigrationMethods(schemaMigrationClass);
|
|
31
|
+
migrationMethodsMetadata = [];
|
|
52
32
|
}
|
|
53
33
|
if (!migrationMethodsMetadata || migrationMethodsMetadata.length === 0) {
|
|
54
|
-
throw new Error('No migration methods found in this class. Define at least one migration and annotate it with @
|
|
34
|
+
throw new Error('No migration methods found in this class. Define at least one migration and annotate it with @toVersion()');
|
|
55
35
|
}
|
|
56
36
|
for (const schemaMigrationMetadata of migrationMethodsMetadata) {
|
|
57
37
|
if (conceptMigrations.has(schemaMigrationMetadata.toVersion)) {
|
|
@@ -69,27 +49,21 @@ function getConceptMigrations(config, conceptClass) {
|
|
|
69
49
|
}
|
|
70
50
|
return config.schemaMigrations[conceptClass.name];
|
|
71
51
|
}
|
|
72
|
-
function getMigrationMethods(migrationClass) {
|
|
73
|
-
const migrationMethods = (0, common_1.getMetadata)(migrationMethodsMetadataKey, migrationClass);
|
|
74
|
-
if (!migrationMethods || migrationMethods.length == 0) {
|
|
75
|
-
throw new Error('No migration methods found in this class. Define at least one migration and annotate it with @ToVersion()');
|
|
76
|
-
}
|
|
77
|
-
return migrationMethods;
|
|
78
|
-
}
|
|
79
52
|
/**
|
|
80
|
-
* Decorator to tell Magek the version you are migrating to
|
|
53
|
+
* Decorator to tell Magek the version you are migrating to.
|
|
54
|
+
*
|
|
55
|
+
* Uses TC39 Stage 3 decorators.
|
|
56
|
+
*
|
|
81
57
|
* @param toVersion
|
|
82
58
|
* @param props
|
|
83
59
|
*/
|
|
84
|
-
function
|
|
60
|
+
function toVersion(toVersion, props) {
|
|
85
61
|
if (toVersion <= 1) {
|
|
86
62
|
throw new Error('Migration versions must always be greater than 1');
|
|
87
63
|
}
|
|
88
|
-
return (
|
|
89
|
-
//
|
|
90
|
-
if (
|
|
91
|
-
// Stage 3 decorator - store in context.metadata so @SchemaMigration can read it
|
|
92
|
-
const context = propertyNameOrContext;
|
|
64
|
+
return (_method, context) => {
|
|
65
|
+
// Stage 3 decorator - store in context.metadata so @SchemaMigration can read it
|
|
66
|
+
if (context.metadata) {
|
|
93
67
|
// Get or initialize the migrations array in context.metadata
|
|
94
68
|
let migrationMethods = context.metadata[MIGRATIONS_METADATA_KEY];
|
|
95
69
|
if (!migrationMethods) {
|
|
@@ -104,43 +78,24 @@ function ToVersion(toVersion, props) {
|
|
|
104
78
|
fromSchema: props.fromSchema,
|
|
105
79
|
toSchema: props.toSchema,
|
|
106
80
|
});
|
|
107
|
-
// Also store in Reflect metadata for the standalone test case
|
|
108
|
-
if (context.addInitializer) {
|
|
109
|
-
context.addInitializer(function () {
|
|
110
|
-
const migrationClass = context.static ? this : this.constructor;
|
|
111
|
-
let reflectMethods = (0, common_1.getMetadata)(migrationMethodsMetadataKey, migrationClass);
|
|
112
|
-
if (!reflectMethods) {
|
|
113
|
-
reflectMethods = [];
|
|
114
|
-
}
|
|
115
|
-
reflectMethods.push({
|
|
116
|
-
migrationClass,
|
|
117
|
-
methodName: context.name.toString(),
|
|
118
|
-
toVersion,
|
|
119
|
-
fromSchema: props.fromSchema,
|
|
120
|
-
toSchema: props.toSchema,
|
|
121
|
-
});
|
|
122
|
-
(0, common_1.defineMetadata)(migrationMethodsMetadataKey, reflectMethods, migrationClass);
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
81
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
82
|
+
// Also store in Reflect metadata for standalone usage
|
|
83
|
+
if (context.addInitializer) {
|
|
84
|
+
context.addInitializer(function () {
|
|
85
|
+
const migrationClass = context.static ? this : this.constructor;
|
|
86
|
+
let reflectMethods = (0, common_1.getMetadata)(migrationMethodsMetadataKey, migrationClass);
|
|
87
|
+
if (!reflectMethods) {
|
|
88
|
+
reflectMethods = [];
|
|
89
|
+
}
|
|
90
|
+
reflectMethods.push({
|
|
91
|
+
migrationClass,
|
|
92
|
+
methodName: context.name.toString(),
|
|
93
|
+
toVersion,
|
|
94
|
+
fromSchema: props.fromSchema,
|
|
95
|
+
toSchema: props.toSchema,
|
|
96
|
+
});
|
|
97
|
+
(0, common_1.defineMetadata)(migrationMethodsMetadataKey, reflectMethods, migrationClass);
|
|
141
98
|
});
|
|
142
|
-
// Here we just store the information (version and method). All the checks will be done in the @Migrates decorator
|
|
143
|
-
(0, common_1.defineMetadata)(migrationMethodsMetadataKey, migrationMethods, migrationClass);
|
|
144
99
|
}
|
|
145
100
|
};
|
|
146
101
|
}
|
|
@@ -1,28 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
/**
|
|
3
|
-
|
|
4
|
-
*/
|
|
5
|
-
interface Stage3FieldContext {
|
|
6
|
-
kind: 'field';
|
|
7
|
-
name: string | symbol;
|
|
8
|
-
static: boolean;
|
|
9
|
-
private: boolean;
|
|
10
|
-
metadata: Record<string | symbol, unknown>;
|
|
11
|
-
access?: {
|
|
12
|
-
get: () => unknown;
|
|
13
|
-
set: (value: unknown) => void;
|
|
14
|
-
};
|
|
15
|
-
addInitializer?: (initializer: () => void) => void;
|
|
16
|
-
}
|
|
1
|
+
import { FieldDecoratorContext } from './decorator-types';
|
|
2
|
+
/** Symbol for storing sequence key in decorator context.metadata */
|
|
3
|
+
export declare const SEQUENCE_KEY_SYMBOL: unique symbol;
|
|
17
4
|
/**
|
|
18
5
|
* Decorator to specify the sequencing key for a ReadModel.
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
|
|
22
|
-
export declare function sequencedBy(target: Class<ReadModelInterface> | Object | undefined, propertyKeyOrContext?: string | symbol | Stage3FieldContext, parameterIndex?: number): void;
|
|
23
|
-
/**
|
|
24
|
-
* Transfer sequence key metadata from Stage 3 context to class.
|
|
25
|
-
* Called by the ReadModel class decorator.
|
|
6
|
+
*
|
|
7
|
+
* Uses TC39 Stage 3 decorators.
|
|
8
|
+
* The sequence key is stored in context.metadata and read by @ReadModel.
|
|
26
9
|
*/
|
|
27
|
-
export declare function
|
|
28
|
-
export {};
|
|
10
|
+
export declare function sequencedBy(_value: undefined, context: FieldDecoratorContext): void;
|
|
@@ -1,79 +1,19 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SEQUENCE_KEY_SYMBOL = void 0;
|
|
3
4
|
exports.sequencedBy = sequencedBy;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const metadata_1 = require("./metadata");
|
|
7
|
-
// Symbol for storing sequence key in Stage 3 decorator context.metadata
|
|
8
|
-
const SEQUENCE_KEY_SYMBOL = Symbol.for('magek:sequenceKey');
|
|
9
|
-
/**
|
|
10
|
-
* Type guard to detect Stage 3 field context
|
|
11
|
-
*/
|
|
12
|
-
function isStage3FieldContext(arg) {
|
|
13
|
-
return (arg !== null &&
|
|
14
|
-
typeof arg === 'object' &&
|
|
15
|
-
'kind' in arg &&
|
|
16
|
-
arg.kind === 'field' &&
|
|
17
|
-
'name' in arg &&
|
|
18
|
-
'metadata' in arg);
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Register sequence key for a class
|
|
22
|
-
*/
|
|
23
|
-
function registerSequenceKey(klass, propertyName) {
|
|
24
|
-
magek_1.Magek.configureCurrentEnv((config) => {
|
|
25
|
-
if (config.readModelSequenceKeys[klass.name] && config.readModelSequenceKeys[klass.name] !== propertyName) {
|
|
26
|
-
throw new Error(`Error trying to register a sort key named \`${propertyName}\` for class \`${klass.name}\`. It already had the sort key \`${config.readModelSequenceKeys[klass.name]}\` defined and only one sort key is allowed for each read model.`);
|
|
27
|
-
}
|
|
28
|
-
else {
|
|
29
|
-
config.readModelSequenceKeys[klass.name] = propertyName;
|
|
30
|
-
}
|
|
31
|
-
});
|
|
32
|
-
}
|
|
5
|
+
/** Symbol for storing sequence key in decorator context.metadata */
|
|
6
|
+
exports.SEQUENCE_KEY_SYMBOL = Symbol.for('magek:sequenceKey');
|
|
33
7
|
/**
|
|
34
8
|
* Decorator to specify the sequencing key for a ReadModel.
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
|
|
38
|
-
function sequencedBy(target, propertyKeyOrContext, parameterIndex) {
|
|
39
|
-
// Detect Stage 3 field decorator
|
|
40
|
-
if (isStage3FieldContext(propertyKeyOrContext)) {
|
|
41
|
-
const context = propertyKeyOrContext;
|
|
42
|
-
const propertyName = String(context.name);
|
|
43
|
-
// Store the sequence key in context.metadata for ReadModel decorator to pick up
|
|
44
|
-
context.metadata[SEQUENCE_KEY_SYMBOL] = propertyName;
|
|
45
|
-
// Also use addInitializer to register immediately when class is defined
|
|
46
|
-
if (context.addInitializer) {
|
|
47
|
-
context.addInitializer(function () {
|
|
48
|
-
const klass = this.constructor;
|
|
49
|
-
registerSequenceKey(klass, propertyName);
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
// Legacy decorator handling
|
|
55
|
-
const propertyKey = propertyKeyOrContext;
|
|
56
|
-
// Property decorator usage: @sequencedBy on a class property
|
|
57
|
-
if (propertyKey !== undefined && parameterIndex === undefined) {
|
|
58
|
-
const klass = target.constructor;
|
|
59
|
-
const propertyName = String(propertyKey);
|
|
60
|
-
registerSequenceKey(klass, propertyName);
|
|
61
|
-
}
|
|
62
|
-
// Parameter decorator usage: @sequencedBy on constructor parameter
|
|
63
|
-
else if (parameterIndex !== undefined) {
|
|
64
|
-
const klass = target;
|
|
65
|
-
const args = (0, metadata_1.getFunctionArguments)(klass);
|
|
66
|
-
const propertyName = args[parameterIndex];
|
|
67
|
-
registerSequenceKey(klass, propertyName);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Transfer sequence key metadata from Stage 3 context to class.
|
|
72
|
-
* Called by the ReadModel class decorator.
|
|
9
|
+
*
|
|
10
|
+
* Uses TC39 Stage 3 decorators.
|
|
11
|
+
* The sequence key is stored in context.metadata and read by @ReadModel.
|
|
73
12
|
*/
|
|
74
|
-
function
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
13
|
+
function sequencedBy(_value, context) {
|
|
14
|
+
const propertyName = String(context.name);
|
|
15
|
+
// Store the sequence key in context.metadata for ReadModel decorator to pick up
|
|
16
|
+
if (context.metadata) {
|
|
17
|
+
context.metadata[exports.SEQUENCE_KEY_SYMBOL] = propertyName;
|
|
78
18
|
}
|
|
79
19
|
}
|
package/dist/event-dispatcher.js
CHANGED
|
@@ -8,30 +8,35 @@ const raw_events_parser_1 = require("./services/raw-events-parser");
|
|
|
8
8
|
const read_model_store_1 = require("./services/read-model-store");
|
|
9
9
|
const instrumentation_1 = require("./instrumentation");
|
|
10
10
|
const event_processor_1 = require("./event-processor");
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
logger.debug('Event workflow started for raw events:', require('util').inspect(rawEvents, false, null, false));
|
|
22
|
-
try {
|
|
23
|
-
const eventEnvelopes = config.eventStore.rawToEnvelopes(rawEvents);
|
|
24
|
-
await raw_events_parser_1.RawEventsParser.streamPerEntityEvents(config, eventEnvelopes, event_processor_1.MagekEventProcessor.eventProcessor(eventStore, readModelStore));
|
|
11
|
+
let MagekEventDispatcher = (() => {
|
|
12
|
+
let _staticExtraInitializers = [];
|
|
13
|
+
let _static_dispatch_decorators;
|
|
14
|
+
return class MagekEventDispatcher {
|
|
15
|
+
static {
|
|
16
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
17
|
+
_static_dispatch_decorators = [(0, instrumentation_1.trace)(common_1.TraceActionTypes.DISPATCH_EVENTS)];
|
|
18
|
+
tslib_1.__esDecorate(this, null, _static_dispatch_decorators, { kind: "method", name: "dispatch", static: true, private: false, access: { has: obj => "dispatch" in obj, get: obj => obj.dispatch }, metadata: _metadata }, null, _staticExtraInitializers);
|
|
19
|
+
if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
20
|
+
tslib_1.__runInitializers(this, _staticExtraInitializers);
|
|
25
21
|
}
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Entry point to dispatch events.
|
|
24
|
+
* @param rawEvents List of raw events
|
|
25
|
+
* @param config
|
|
26
|
+
*/
|
|
27
|
+
static async dispatch(rawEvents, config) {
|
|
28
|
+
const logger = (0, common_1.getLogger)(config, 'MagekEventDispatcher#dispatch');
|
|
29
|
+
const eventStore = new event_store_1.EventStore(config);
|
|
30
|
+
const readModelStore = new read_model_store_1.ReadModelStore(config);
|
|
31
|
+
logger.debug('Event workflow started for raw events:', require('util').inspect(rawEvents, false, null, false));
|
|
32
|
+
try {
|
|
33
|
+
const eventEnvelopes = config.eventStore.rawToEnvelopes(rawEvents);
|
|
34
|
+
await raw_events_parser_1.RawEventsParser.streamPerEntityEvents(config, eventEnvelopes, event_processor_1.MagekEventProcessor.eventProcessor(eventStore, readModelStore));
|
|
35
|
+
}
|
|
36
|
+
catch (e) {
|
|
37
|
+
logger.error('Unhandled error while dispatching event: ', e);
|
|
38
|
+
}
|
|
28
39
|
}
|
|
29
|
-
}
|
|
30
|
-
}
|
|
40
|
+
};
|
|
41
|
+
})();
|
|
31
42
|
exports.MagekEventDispatcher = MagekEventDispatcher;
|
|
32
|
-
tslib_1.__decorate([
|
|
33
|
-
(0, instrumentation_1.Trace)(common_1.TraceActionTypes.DISPATCH_EVENTS),
|
|
34
|
-
tslib_1.__metadata("design:type", Function),
|
|
35
|
-
tslib_1.__metadata("design:paramtypes", [Object, common_1.MagekConfig]),
|
|
36
|
-
tslib_1.__metadata("design:returntype", Promise)
|
|
37
|
-
], MagekEventDispatcher, "dispatch", null);
|