@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.
Files changed (104) hide show
  1. package/dist/authorizer.js +1 -1
  2. package/dist/command-dispatcher.js +47 -41
  3. package/dist/core-concepts/data-migration/entities/data-migration-entity.js +5 -2
  4. package/dist/core-concepts/data-migration/events/data-migration-finished.js +3 -1
  5. package/dist/core-concepts/data-migration/events/data-migration-started.js +3 -1
  6. package/dist/core-concepts/data-migration/events/entity-migrated.js +4 -0
  7. package/dist/core-concepts/touch-entity/events/entity-touched.js +2 -0
  8. package/dist/data-migrations.js +59 -54
  9. package/dist/decorators/command.d.ts +4 -11
  10. package/dist/decorators/command.js +10 -18
  11. package/dist/decorators/data-migration.d.ts +4 -1
  12. package/dist/decorators/data-migration.js +3 -1
  13. package/dist/decorators/decorator-types.d.ts +50 -0
  14. package/dist/decorators/decorator-types.js +11 -0
  15. package/dist/decorators/decorator-utils.d.ts +1 -0
  16. package/dist/decorators/decorator-utils.js +2 -0
  17. package/dist/decorators/entity.d.ts +7 -15
  18. package/dist/decorators/entity.js +27 -37
  19. package/dist/decorators/event-handler.d.ts +11 -1
  20. package/dist/decorators/event-handler.js +13 -1
  21. package/dist/decorators/event.d.ts +4 -1
  22. package/dist/decorators/event.js +3 -2
  23. package/dist/decorators/field-metadata-reader.d.ts +8 -3
  24. package/dist/decorators/field-metadata-reader.js +61 -62
  25. package/dist/decorators/field.d.ts +23 -0
  26. package/dist/decorators/field.js +41 -0
  27. package/dist/decorators/global-error-handler.d.ts +10 -1
  28. package/dist/decorators/global-error-handler.js +9 -1
  29. package/dist/decorators/global-event-handler.d.ts +10 -1
  30. package/dist/decorators/global-event-handler.js +9 -1
  31. package/dist/decorators/health-sensor.d.ts +4 -1
  32. package/dist/decorators/health-sensor.js +3 -2
  33. package/dist/decorators/index.d.ts +4 -0
  34. package/dist/decorators/index.js +3 -0
  35. package/dist/decorators/metadata.d.ts +17 -1
  36. package/dist/decorators/metadata.js +22 -22
  37. package/dist/decorators/non-exposed.d.ts +13 -2
  38. package/dist/decorators/non-exposed.js +22 -20
  39. package/dist/decorators/notification.d.ts +6 -18
  40. package/dist/decorators/notification.js +10 -50
  41. package/dist/decorators/projects.d.ts +5 -18
  42. package/dist/decorators/projects.js +23 -54
  43. package/dist/decorators/query.d.ts +11 -1
  44. package/dist/decorators/query.js +18 -4
  45. package/dist/decorators/read-model.d.ts +13 -27
  46. package/dist/decorators/read-model.js +45 -77
  47. package/dist/decorators/returns.d.ts +37 -0
  48. package/dist/decorators/returns.js +154 -0
  49. package/dist/decorators/role.d.ts +9 -3
  50. package/dist/decorators/role.js +8 -3
  51. package/dist/decorators/scheduled-command.d.ts +4 -1
  52. package/dist/decorators/scheduled-command.js +3 -1
  53. package/dist/decorators/schema-migration.d.ts +11 -27
  54. package/dist/decorators/schema-migration.js +32 -77
  55. package/dist/decorators/sequenced-by.d.ts +7 -25
  56. package/dist/decorators/sequenced-by.js +11 -71
  57. package/dist/event-dispatcher.js +29 -24
  58. package/dist/event-processor.js +107 -103
  59. package/dist/event-stream-consumer.js +25 -20
  60. package/dist/event-stream-producer.js +22 -17
  61. package/dist/events-reader.js +1 -0
  62. package/dist/global-error-dispatcher.js +3 -2
  63. package/dist/graphql-dispatcher.js +161 -156
  64. package/dist/index.js +4 -0
  65. package/dist/instrumentation/decorator/trace.d.ts +11 -3
  66. package/dist/instrumentation/decorator/trace.js +17 -71
  67. package/dist/magek.js +2 -2
  68. package/dist/query-dispatcher.js +2 -0
  69. package/dist/read-model-schema-migrator.js +71 -68
  70. package/dist/read-models-reader.js +178 -180
  71. package/dist/register-handler.js +3 -3
  72. package/dist/scheduled-command-dispatcher.js +48 -42
  73. package/dist/schema-migrator.js +63 -59
  74. package/dist/sensor/health/health-service.js +2 -1
  75. package/dist/services/event-store.js +221 -224
  76. package/dist/services/graphql/graphql-generator.js +11 -8
  77. package/dist/services/graphql/graphql-mutation-generator.js +4 -0
  78. package/dist/services/graphql/graphql-query-generator.js +14 -0
  79. package/dist/services/graphql/graphql-subcriptions-generator.js +7 -0
  80. package/dist/services/graphql/graphql-type-informer.js +4 -3
  81. package/dist/services/graphql/query-generators/graphql-query-by-keys-generator.js +4 -0
  82. package/dist/services/graphql/query-generators/graphql-query-events-generator.js +3 -0
  83. package/dist/services/graphql/query-generators/graphql-query-filters-generator.js +6 -0
  84. package/dist/services/graphql/query-generators/graphql-query-generator.js +4 -0
  85. package/dist/services/graphql/query-generators/graphql-query-listed-generator.js +7 -0
  86. package/dist/services/graphql/query-helpers/graphql-handled-fields-generator.js +5 -2
  87. package/dist/services/graphql/query-helpers/graphql-query-filter-arguments-builder.js +3 -0
  88. package/dist/services/graphql/query-helpers/graphql-query-filter-fields-builder.js +4 -0
  89. package/dist/services/graphql/query-helpers/graphql-query-sort-builder.js +4 -2
  90. package/dist/services/graphql/websocket-protocol/graphql-websocket-protocol.js +5 -3
  91. package/dist/services/pub-sub/read-model-pub-sub.js +1 -0
  92. package/dist/services/raw-events-parser.js +1 -1
  93. package/dist/services/read-model-store.js +20 -20
  94. package/dist/services/token-verifiers/jwks-uri-token-verifier.js +8 -4
  95. package/dist/services/token-verifiers/public-key-token-verifier.js +4 -2
  96. package/dist/services/token-verifiers/role-based-token-verifier.js +2 -1
  97. package/dist/services/token-verifiers/utilities.js +1 -1
  98. package/dist/subscribers-notifier.js +99 -92
  99. package/dist/token-verifier.js +2 -1
  100. package/dist/utils/promises.d.ts +25 -0
  101. package/dist/utils/promises.js +43 -0
  102. package/package.json +4 -4
  103. package/dist/decorators/stage3-utils.d.ts +0 -6
  104. 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
- * Annotation to tell Magek which classes represent your roles
4
- * @param roleMetadata
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>) => void;
12
+ export declare function Role(roleMetadata?: RoleMetadata): (role: Class<RoleInterface>, context: ClassDecoratorContext) => void;
@@ -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
- * Annotation to tell Magek which classes represent your roles
7
- * @param roleMetadata
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, Instance } from '@magek/common';
2
- /**
3
- * Stage 3 method decorator context
4
- */
5
- interface Stage3MethodContext {
6
- kind: 'method';
7
- name: string | symbol;
8
- static: boolean;
9
- private: boolean;
10
- metadata: Record<string | symbol, unknown>;
11
- addInitializer?: (initializer: () => void) => void;
12
- }
13
- /**
14
- * Stage 3 class decorator context
15
- */
16
- interface Stage3ClassContext {
17
- kind: 'class';
18
- name: string | undefined;
19
- metadata: Record<string | symbol, unknown>;
20
- addInitializer?: (initializer: () => void) => void;
21
- }
1
+ import { Class, AnyClass } from '@magek/common';
2
+ import { MethodDecoratorContext, ClassDecoratorContext } from './decorator-types';
22
3
  /**
23
4
  * **NOTE:** Using this decorator for read model migrations is deprecated. Prefer using `@DataMigration` instead.
5
+ *
6
+ * Uses TC39 Stage 3 decorators.
24
7
  */
25
- export declare function SchemaMigration(conceptClass: AnyClass): (schemaMigrationClass: AnyClass, context?: Stage3ClassContext) => void;
8
+ export declare function SchemaMigration(conceptClass: AnyClass): (schemaMigrationClass: AnyClass, context: ClassDecoratorContext) => void;
26
9
  /**
27
- * Decorator to tell Magek the version you are migrating to
10
+ * Decorator to tell Magek the version you are migrating to.
11
+ *
12
+ * Uses TC39 Stage 3 decorators.
13
+ *
28
14
  * @param toVersion
29
15
  * @param props
30
16
  */
31
- export declare function ToVersion<TOldSchema, TNewSchema>(toVersion: number, props: {
17
+ export declare function toVersion<TOldSchema, TNewSchema>(toVersion: number, props: {
32
18
  fromSchema: Class<TOldSchema>;
33
19
  toSchema: Class<TNewSchema>;
34
- }): (migrationInstanceOrMethod: Instance | Function, propertyNameOrContext: string | Stage3MethodContext, propertyDescriptor?: MigrationMethod<TOldSchema, TNewSchema>) => void;
35
- type MigrationMethod<TOldSchema, TNewSchema> = TypedPropertyDescriptor<(old: TOldSchema) => Promise<TNewSchema>>;
36
- export {};
20
+ }): (method: Function, context: MethodDecoratorContext) => void;
@@ -1,43 +1,24 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SchemaMigration = SchemaMigration;
4
- exports.ToVersion = ToVersion;
4
+ exports.toVersion = toVersion;
5
5
  const magek_1 = require("../magek");
6
6
  const common_1 = require("@magek/common");
7
7
  const migrationMethodsMetadataKey = 'magek:migrationsMethods';
8
- /**
9
- * Type guard to detect Stage 3 method decorator context
10
- */
11
- function isStage3MethodContext(arg) {
12
- return (arg !== null &&
13
- typeof arg === 'object' &&
14
- 'kind' in arg &&
15
- arg.kind === 'method' &&
16
- 'name' in arg);
17
- }
18
- /**
19
- * Type guard to detect Stage 3 class decorator context
20
- */
21
- function isStage3ClassContext(arg) {
22
- return (arg !== null &&
23
- typeof arg === 'object' &&
24
- 'kind' in arg &&
25
- arg.kind === 'class' &&
26
- 'metadata' in arg);
27
- }
28
- // Symbol for storing migration metadata in Stage 3 decorator context.metadata
8
+ // Symbol for storing migration metadata in decorator context.metadata
29
9
  const MIGRATIONS_METADATA_KEY = Symbol.for('magek:migrationsMethods');
30
10
  /**
31
11
  * **NOTE:** Using this decorator for read model migrations is deprecated. Prefer using `@DataMigration` instead.
12
+ *
13
+ * Uses TC39 Stage 3 decorators.
32
14
  */
33
15
  function SchemaMigration(conceptClass) {
34
16
  return (schemaMigrationClass, context) => {
35
17
  magek_1.Magek.configureCurrentEnv((config) => {
36
18
  const conceptMigrations = getConceptMigrations(config, conceptClass);
37
- // Get migration methods - for Stage 3, read from context.metadata first
19
+ // Get migration methods from context.metadata
38
20
  let migrationMethodsMetadata;
39
- if (isStage3ClassContext(context)) {
40
- // Stage 3: read from context.metadata
21
+ if (context.metadata) {
41
22
  migrationMethodsMetadata =
42
23
  context.metadata[MIGRATIONS_METADATA_KEY] || [];
43
24
  // Update each metadata entry with the actual class reference
@@ -47,11 +28,10 @@ function SchemaMigration(conceptClass) {
47
28
  }));
48
29
  }
49
30
  else {
50
- // Legacy: read from Reflect.getMetadata
51
- migrationMethodsMetadata = getMigrationMethods(schemaMigrationClass);
31
+ migrationMethodsMetadata = [];
52
32
  }
53
33
  if (!migrationMethodsMetadata || migrationMethodsMetadata.length === 0) {
54
- throw new Error('No migration methods found in this class. Define at least one migration and annotate it with @ToVersion()');
34
+ throw new Error('No migration methods found in this class. Define at least one migration and annotate it with @toVersion()');
55
35
  }
56
36
  for (const schemaMigrationMetadata of migrationMethodsMetadata) {
57
37
  if (conceptMigrations.has(schemaMigrationMetadata.toVersion)) {
@@ -69,27 +49,21 @@ function getConceptMigrations(config, conceptClass) {
69
49
  }
70
50
  return config.schemaMigrations[conceptClass.name];
71
51
  }
72
- function getMigrationMethods(migrationClass) {
73
- const migrationMethods = (0, common_1.getMetadata)(migrationMethodsMetadataKey, migrationClass);
74
- if (!migrationMethods || migrationMethods.length == 0) {
75
- throw new Error('No migration methods found in this class. Define at least one migration and annotate it with @ToVersion()');
76
- }
77
- return migrationMethods;
78
- }
79
52
  /**
80
- * Decorator to tell Magek the version you are migrating to
53
+ * Decorator to tell Magek the version you are migrating to.
54
+ *
55
+ * Uses TC39 Stage 3 decorators.
56
+ *
81
57
  * @param toVersion
82
58
  * @param props
83
59
  */
84
- function ToVersion(toVersion, props) {
60
+ function toVersion(toVersion, props) {
85
61
  if (toVersion <= 1) {
86
62
  throw new Error('Migration versions must always be greater than 1');
87
63
  }
88
- return (migrationInstanceOrMethod, propertyNameOrContext) => {
89
- // Detect Stage 3 vs Legacy decorator
90
- if (isStage3MethodContext(propertyNameOrContext)) {
91
- // Stage 3 decorator - store in context.metadata so @SchemaMigration can read it
92
- const context = propertyNameOrContext;
64
+ return (_method, context) => {
65
+ // Stage 3 decorator - store in context.metadata so @SchemaMigration can read it
66
+ if (context.metadata) {
93
67
  // Get or initialize the migrations array in context.metadata
94
68
  let migrationMethods = context.metadata[MIGRATIONS_METADATA_KEY];
95
69
  if (!migrationMethods) {
@@ -104,43 +78,24 @@ function ToVersion(toVersion, props) {
104
78
  fromSchema: props.fromSchema,
105
79
  toSchema: props.toSchema,
106
80
  });
107
- // Also store in Reflect metadata for the standalone test case
108
- if (context.addInitializer) {
109
- context.addInitializer(function () {
110
- const migrationClass = context.static ? this : this.constructor;
111
- let reflectMethods = (0, common_1.getMetadata)(migrationMethodsMetadataKey, migrationClass);
112
- if (!reflectMethods) {
113
- reflectMethods = [];
114
- }
115
- reflectMethods.push({
116
- migrationClass,
117
- methodName: context.name.toString(),
118
- toVersion,
119
- fromSchema: props.fromSchema,
120
- toSchema: props.toSchema,
121
- });
122
- (0, common_1.defineMetadata)(migrationMethodsMetadataKey, reflectMethods, migrationClass);
123
- });
124
- }
125
81
  }
126
- else {
127
- // Legacy decorator
128
- const migrationInstance = migrationInstanceOrMethod;
129
- const propertyName = propertyNameOrContext;
130
- const migrationClass = migrationInstance.constructor;
131
- let migrationMethods = (0, common_1.getMetadata)(migrationMethodsMetadataKey, migrationClass);
132
- if (!migrationMethods) {
133
- migrationMethods = [];
134
- }
135
- migrationMethods.push({
136
- migrationClass,
137
- methodName: propertyName,
138
- toVersion,
139
- fromSchema: props.fromSchema,
140
- toSchema: props.toSchema,
82
+ // Also store in Reflect metadata for standalone usage
83
+ if (context.addInitializer) {
84
+ context.addInitializer(function () {
85
+ const migrationClass = context.static ? this : this.constructor;
86
+ let reflectMethods = (0, common_1.getMetadata)(migrationMethodsMetadataKey, migrationClass);
87
+ if (!reflectMethods) {
88
+ reflectMethods = [];
89
+ }
90
+ reflectMethods.push({
91
+ migrationClass,
92
+ methodName: context.name.toString(),
93
+ toVersion,
94
+ fromSchema: props.fromSchema,
95
+ toSchema: props.toSchema,
96
+ });
97
+ (0, common_1.defineMetadata)(migrationMethodsMetadataKey, reflectMethods, migrationClass);
141
98
  });
142
- // Here we just store the information (version and method). All the checks will be done in the @Migrates decorator
143
- (0, common_1.defineMetadata)(migrationMethodsMetadataKey, migrationMethods, migrationClass);
144
99
  }
145
100
  };
146
101
  }
@@ -1,28 +1,10 @@
1
- import { Class, ReadModelInterface, AnyClass } from '@magek/common';
2
- /**
3
- * Stage 3 field decorator context
4
- */
5
- interface Stage3FieldContext {
6
- kind: 'field';
7
- name: string | symbol;
8
- static: boolean;
9
- private: boolean;
10
- metadata: Record<string | symbol, unknown>;
11
- access?: {
12
- get: () => unknown;
13
- set: (value: unknown) => void;
14
- };
15
- addInitializer?: (initializer: () => void) => void;
16
- }
1
+ import { FieldDecoratorContext } from './decorator-types';
2
+ /** Symbol for storing sequence key in decorator context.metadata */
3
+ export declare const SEQUENCE_KEY_SYMBOL: unique symbol;
17
4
  /**
18
5
  * Decorator to specify the sequencing key for a ReadModel.
19
- * Can be used as both a parameter decorator and property decorator.
20
- * Supports both legacy (experimentalDecorators) and Stage 3 decorators.
21
- */
22
- export declare function sequencedBy(target: Class<ReadModelInterface> | Object | undefined, propertyKeyOrContext?: string | symbol | Stage3FieldContext, parameterIndex?: number): void;
23
- /**
24
- * Transfer sequence key metadata from Stage 3 context to class.
25
- * Called by the ReadModel class decorator.
6
+ *
7
+ * Uses TC39 Stage 3 decorators.
8
+ * The sequence key is stored in context.metadata and read by @ReadModel.
26
9
  */
27
- export declare function transferSequenceKeyMetadata(classType: AnyClass, contextMetadata: Record<string | symbol, unknown>): void;
28
- export {};
10
+ export declare function sequencedBy(_value: undefined, context: FieldDecoratorContext): void;
@@ -1,79 +1,19 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SEQUENCE_KEY_SYMBOL = void 0;
3
4
  exports.sequencedBy = sequencedBy;
4
- exports.transferSequenceKeyMetadata = transferSequenceKeyMetadata;
5
- const magek_1 = require("../magek");
6
- const metadata_1 = require("./metadata");
7
- // Symbol for storing sequence key in Stage 3 decorator context.metadata
8
- const SEQUENCE_KEY_SYMBOL = Symbol.for('magek:sequenceKey');
9
- /**
10
- * Type guard to detect Stage 3 field context
11
- */
12
- function isStage3FieldContext(arg) {
13
- return (arg !== null &&
14
- typeof arg === 'object' &&
15
- 'kind' in arg &&
16
- arg.kind === 'field' &&
17
- 'name' in arg &&
18
- 'metadata' in arg);
19
- }
20
- /**
21
- * Register sequence key for a class
22
- */
23
- function registerSequenceKey(klass, propertyName) {
24
- magek_1.Magek.configureCurrentEnv((config) => {
25
- if (config.readModelSequenceKeys[klass.name] && config.readModelSequenceKeys[klass.name] !== propertyName) {
26
- throw new Error(`Error trying to register a sort key named \`${propertyName}\` for class \`${klass.name}\`. It already had the sort key \`${config.readModelSequenceKeys[klass.name]}\` defined and only one sort key is allowed for each read model.`);
27
- }
28
- else {
29
- config.readModelSequenceKeys[klass.name] = propertyName;
30
- }
31
- });
32
- }
5
+ /** Symbol for storing sequence key in decorator context.metadata */
6
+ exports.SEQUENCE_KEY_SYMBOL = Symbol.for('magek:sequenceKey');
33
7
  /**
34
8
  * Decorator to specify the sequencing key for a ReadModel.
35
- * Can be used as both a parameter decorator and property decorator.
36
- * Supports both legacy (experimentalDecorators) and Stage 3 decorators.
37
- */
38
- function sequencedBy(target, propertyKeyOrContext, parameterIndex) {
39
- // Detect Stage 3 field decorator
40
- if (isStage3FieldContext(propertyKeyOrContext)) {
41
- const context = propertyKeyOrContext;
42
- const propertyName = String(context.name);
43
- // Store the sequence key in context.metadata for ReadModel decorator to pick up
44
- context.metadata[SEQUENCE_KEY_SYMBOL] = propertyName;
45
- // Also use addInitializer to register immediately when class is defined
46
- if (context.addInitializer) {
47
- context.addInitializer(function () {
48
- const klass = this.constructor;
49
- registerSequenceKey(klass, propertyName);
50
- });
51
- }
52
- return;
53
- }
54
- // Legacy decorator handling
55
- const propertyKey = propertyKeyOrContext;
56
- // Property decorator usage: @sequencedBy on a class property
57
- if (propertyKey !== undefined && parameterIndex === undefined) {
58
- const klass = target.constructor;
59
- const propertyName = String(propertyKey);
60
- registerSequenceKey(klass, propertyName);
61
- }
62
- // Parameter decorator usage: @sequencedBy on constructor parameter
63
- else if (parameterIndex !== undefined) {
64
- const klass = target;
65
- const args = (0, metadata_1.getFunctionArguments)(klass);
66
- const propertyName = args[parameterIndex];
67
- registerSequenceKey(klass, propertyName);
68
- }
69
- }
70
- /**
71
- * Transfer sequence key metadata from Stage 3 context to class.
72
- * Called by the ReadModel class decorator.
9
+ *
10
+ * Uses TC39 Stage 3 decorators.
11
+ * The sequence key is stored in context.metadata and read by @ReadModel.
73
12
  */
74
- function transferSequenceKeyMetadata(classType, contextMetadata) {
75
- const sequenceKey = contextMetadata[SEQUENCE_KEY_SYMBOL];
76
- if (sequenceKey) {
77
- registerSequenceKey(classType, sequenceKey);
13
+ function sequencedBy(_value, context) {
14
+ const propertyName = String(context.name);
15
+ // Store the sequence key in context.metadata for ReadModel decorator to pick up
16
+ if (context.metadata) {
17
+ context.metadata[exports.SEQUENCE_KEY_SYMBOL] = propertyName;
78
18
  }
79
19
  }
@@ -8,30 +8,35 @@ const raw_events_parser_1 = require("./services/raw-events-parser");
8
8
  const read_model_store_1 = require("./services/read-model-store");
9
9
  const instrumentation_1 = require("./instrumentation");
10
10
  const event_processor_1 = require("./event-processor");
11
- class MagekEventDispatcher {
12
- /**
13
- * Entry point to dispatch events.
14
- * @param rawEvents List of raw events
15
- * @param config
16
- */
17
- static async dispatch(rawEvents, config) {
18
- const logger = (0, common_1.getLogger)(config, 'MagekEventDispatcher#dispatch');
19
- const eventStore = new event_store_1.EventStore(config);
20
- const readModelStore = new read_model_store_1.ReadModelStore(config);
21
- logger.debug('Event workflow started for raw events:', require('util').inspect(rawEvents, false, null, false));
22
- try {
23
- const eventEnvelopes = config.eventStore.rawToEnvelopes(rawEvents);
24
- await raw_events_parser_1.RawEventsParser.streamPerEntityEvents(config, eventEnvelopes, event_processor_1.MagekEventProcessor.eventProcessor(eventStore, readModelStore));
11
+ let MagekEventDispatcher = (() => {
12
+ let _staticExtraInitializers = [];
13
+ let _static_dispatch_decorators;
14
+ return class MagekEventDispatcher {
15
+ static {
16
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
17
+ _static_dispatch_decorators = [(0, instrumentation_1.trace)(common_1.TraceActionTypes.DISPATCH_EVENTS)];
18
+ tslib_1.__esDecorate(this, null, _static_dispatch_decorators, { kind: "method", name: "dispatch", static: true, private: false, access: { has: obj => "dispatch" in obj, get: obj => obj.dispatch }, metadata: _metadata }, null, _staticExtraInitializers);
19
+ if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
20
+ tslib_1.__runInitializers(this, _staticExtraInitializers);
25
21
  }
26
- catch (e) {
27
- logger.error('Unhandled error while dispatching event: ', e);
22
+ /**
23
+ * Entry point to dispatch events.
24
+ * @param rawEvents List of raw events
25
+ * @param config
26
+ */
27
+ static async dispatch(rawEvents, config) {
28
+ const logger = (0, common_1.getLogger)(config, 'MagekEventDispatcher#dispatch');
29
+ const eventStore = new event_store_1.EventStore(config);
30
+ const readModelStore = new read_model_store_1.ReadModelStore(config);
31
+ logger.debug('Event workflow started for raw events:', require('util').inspect(rawEvents, false, null, false));
32
+ try {
33
+ const eventEnvelopes = config.eventStore.rawToEnvelopes(rawEvents);
34
+ await raw_events_parser_1.RawEventsParser.streamPerEntityEvents(config, eventEnvelopes, event_processor_1.MagekEventProcessor.eventProcessor(eventStore, readModelStore));
35
+ }
36
+ catch (e) {
37
+ logger.error('Unhandled error while dispatching event: ', e);
38
+ }
28
39
  }
29
- }
30
- }
40
+ };
41
+ })();
31
42
  exports.MagekEventDispatcher = MagekEventDispatcher;
32
- tslib_1.__decorate([
33
- (0, instrumentation_1.Trace)(common_1.TraceActionTypes.DISPATCH_EVENTS),
34
- tslib_1.__metadata("design:type", Function),
35
- tslib_1.__metadata("design:paramtypes", [Object, common_1.MagekConfig]),
36
- tslib_1.__metadata("design:returntype", Promise)
37
- ], MagekEventDispatcher, "dispatch", null);