@magek/core 0.0.5 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) 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 +50 -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 +3 -0
  34. package/dist/decorators/index.js +2 -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/role.d.ts +9 -3
  48. package/dist/decorators/role.js +8 -3
  49. package/dist/decorators/scheduled-command.d.ts +4 -1
  50. package/dist/decorators/scheduled-command.js +3 -1
  51. package/dist/decorators/schema-migration.d.ts +11 -27
  52. package/dist/decorators/schema-migration.js +32 -77
  53. package/dist/decorators/sequenced-by.d.ts +7 -25
  54. package/dist/decorators/sequenced-by.js +11 -71
  55. package/dist/event-dispatcher.js +29 -24
  56. package/dist/event-processor.js +106 -103
  57. package/dist/event-stream-consumer.js +25 -20
  58. package/dist/event-stream-producer.js +22 -17
  59. package/dist/events-reader.js +1 -0
  60. package/dist/global-error-dispatcher.js +3 -2
  61. package/dist/graphql-dispatcher.js +161 -156
  62. package/dist/index.js +4 -0
  63. package/dist/instrumentation/decorator/trace.d.ts +11 -3
  64. package/dist/instrumentation/decorator/trace.js +17 -71
  65. package/dist/magek.js +2 -2
  66. package/dist/query-dispatcher.js +2 -0
  67. package/dist/read-model-schema-migrator.js +71 -68
  68. package/dist/read-models-reader.js +178 -180
  69. package/dist/register-handler.js +3 -3
  70. package/dist/scheduled-command-dispatcher.js +48 -42
  71. package/dist/schema-migrator.js +63 -59
  72. package/dist/sensor/health/health-service.js +2 -1
  73. package/dist/services/event-store.js +221 -224
  74. package/dist/services/graphql/graphql-generator.js +11 -8
  75. package/dist/services/graphql/graphql-mutation-generator.js +4 -0
  76. package/dist/services/graphql/graphql-query-generator.js +14 -0
  77. package/dist/services/graphql/graphql-subcriptions-generator.js +7 -0
  78. package/dist/services/graphql/graphql-type-informer.js +4 -3
  79. package/dist/services/graphql/query-generators/graphql-query-by-keys-generator.js +4 -0
  80. package/dist/services/graphql/query-generators/graphql-query-events-generator.js +3 -0
  81. package/dist/services/graphql/query-generators/graphql-query-filters-generator.js +6 -0
  82. package/dist/services/graphql/query-generators/graphql-query-generator.js +4 -0
  83. package/dist/services/graphql/query-generators/graphql-query-listed-generator.js +7 -0
  84. package/dist/services/graphql/query-helpers/graphql-handled-fields-generator.js +5 -2
  85. package/dist/services/graphql/query-helpers/graphql-query-filter-arguments-builder.js +3 -0
  86. package/dist/services/graphql/query-helpers/graphql-query-filter-fields-builder.js +4 -0
  87. package/dist/services/graphql/query-helpers/graphql-query-sort-builder.js +4 -2
  88. package/dist/services/graphql/websocket-protocol/graphql-websocket-protocol.js +5 -3
  89. package/dist/services/pub-sub/read-model-pub-sub.js +1 -0
  90. package/dist/services/raw-events-parser.js +1 -1
  91. package/dist/services/read-model-store.js +16 -17
  92. package/dist/services/token-verifiers/jwks-uri-token-verifier.js +8 -4
  93. package/dist/services/token-verifiers/public-key-token-verifier.js +4 -2
  94. package/dist/services/token-verifiers/role-based-token-verifier.js +2 -1
  95. package/dist/services/token-verifiers/utilities.js +1 -1
  96. package/dist/subscribers-notifier.js +98 -92
  97. package/dist/token-verifier.js +2 -1
  98. package/package.json +4 -4
  99. package/dist/decorators/stage3-utils.d.ts +0 -6
  100. package/dist/decorators/stage3-utils.js +0 -25
@@ -11,26 +11,31 @@ const event_processor_1 = require("./event-processor");
11
11
  /**
12
12
  * This class consumes events from the event stream and dispatches them to the event handlers
13
13
  */
14
- class MagekEventStreamConsumer {
15
- static async consume(rawEvents, config) {
16
- const logger = (0, common_1.getLogger)(config, 'MagekEventDispatcher#dispatch');
17
- const eventStore = new event_store_1.EventStore(config);
18
- const readModelStore = new read_model_store_1.ReadModelStore(config);
19
- logger.debug('Stream event workflow started for raw events:', require('util').inspect(rawEvents, false, null, false));
20
- try {
21
- const dedupEvents = await config.eventStore.dedupEventStream(config, rawEvents);
22
- const eventEnvelopes = config.eventStore.rawStreamToEnvelopes(config, rawEvents, dedupEvents);
23
- await raw_events_parser_1.RawEventsParser.streamPerEntityEvents(config, eventEnvelopes, event_processor_1.MagekEventProcessor.eventProcessor(eventStore, readModelStore));
14
+ let MagekEventStreamConsumer = (() => {
15
+ let _staticExtraInitializers = [];
16
+ let _static_consume_decorators;
17
+ return class MagekEventStreamConsumer {
18
+ static {
19
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
20
+ _static_consume_decorators = [(0, instrumentation_1.trace)(common_1.TraceActionTypes.CONSUME_STREAM_EVENTS)];
21
+ tslib_1.__esDecorate(this, null, _static_consume_decorators, { kind: "method", name: "consume", static: true, private: false, access: { has: obj => "consume" in obj, get: obj => obj.consume }, metadata: _metadata }, null, _staticExtraInitializers);
22
+ if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
23
+ tslib_1.__runInitializers(this, _staticExtraInitializers);
24
24
  }
25
- catch (e) {
26
- logger.error('Unhandled error while consuming event: ', e);
25
+ static async consume(rawEvents, config) {
26
+ const logger = (0, common_1.getLogger)(config, 'MagekEventDispatcher#dispatch');
27
+ const eventStore = new event_store_1.EventStore(config);
28
+ const readModelStore = new read_model_store_1.ReadModelStore(config);
29
+ logger.debug('Stream event workflow started for raw events:', require('util').inspect(rawEvents, false, null, false));
30
+ try {
31
+ const dedupEvents = await config.eventStore.dedupEventStream(config, rawEvents);
32
+ const eventEnvelopes = config.eventStore.rawStreamToEnvelopes(config, rawEvents, dedupEvents);
33
+ await raw_events_parser_1.RawEventsParser.streamPerEntityEvents(config, eventEnvelopes, event_processor_1.MagekEventProcessor.eventProcessor(eventStore, readModelStore));
34
+ }
35
+ catch (e) {
36
+ logger.error('Unhandled error while consuming event: ', e);
37
+ }
27
38
  }
28
- }
29
- }
39
+ };
40
+ })();
30
41
  exports.MagekEventStreamConsumer = MagekEventStreamConsumer;
31
- tslib_1.__decorate([
32
- (0, instrumentation_1.Trace)(common_1.TraceActionTypes.CONSUME_STREAM_EVENTS),
33
- tslib_1.__metadata("design:type", Function),
34
- tslib_1.__metadata("design:paramtypes", [Object, common_1.MagekConfig]),
35
- tslib_1.__metadata("design:returntype", Promise)
36
- ], MagekEventStreamConsumer, "consume", null);
@@ -8,23 +8,28 @@ const raw_events_parser_1 = require("./services/raw-events-parser");
8
8
  /**
9
9
  * Produces events to the event stream
10
10
  */
11
- class MagekEventStreamProducer {
12
- static async produce(request, config) {
13
- const logger = (0, common_1.getLogger)(config, 'MagekEventStreamProducer#produce');
14
- logger.debug('Produce event workflow started for request:', require('util').inspect(request, false, null, false));
15
- try {
16
- const eventEnvelopes = config.eventStore.rawToEnvelopes(request);
17
- await raw_events_parser_1.RawEventsParser.streamPerEntityEvents(config, eventEnvelopes, config.eventStore.produce);
11
+ let MagekEventStreamProducer = (() => {
12
+ let _staticExtraInitializers = [];
13
+ let _static_produce_decorators;
14
+ return class MagekEventStreamProducer {
15
+ static {
16
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
17
+ _static_produce_decorators = [(0, instrumentation_1.trace)(common_1.TraceActionTypes.PRODUCE_STREAM_EVENTS)];
18
+ tslib_1.__esDecorate(this, null, _static_produce_decorators, { kind: "method", name: "produce", static: true, private: false, access: { has: obj => "produce" in obj, get: obj => obj.produce }, 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);
18
21
  }
19
- catch (e) {
20
- logger.error('Unhandled error while producing events: ', e);
22
+ static async produce(request, config) {
23
+ const logger = (0, common_1.getLogger)(config, 'MagekEventStreamProducer#produce');
24
+ logger.debug('Produce event workflow started for request:', require('util').inspect(request, false, null, false));
25
+ try {
26
+ const eventEnvelopes = config.eventStore.rawToEnvelopes(request);
27
+ await raw_events_parser_1.RawEventsParser.streamPerEntityEvents(config, eventEnvelopes, config.eventStore.produce);
28
+ }
29
+ catch (e) {
30
+ logger.error('Unhandled error while producing events: ', e);
31
+ }
21
32
  }
22
- }
23
- }
33
+ };
34
+ })();
24
35
  exports.MagekEventStreamProducer = MagekEventStreamProducer;
25
- tslib_1.__decorate([
26
- (0, instrumentation_1.Trace)(common_1.TraceActionTypes.PRODUCE_STREAM_EVENTS),
27
- tslib_1.__metadata("design:type", Function),
28
- tslib_1.__metadata("design:paramtypes", [Object, common_1.MagekConfig]),
29
- tslib_1.__metadata("design:returntype", Promise)
30
- ], MagekEventStreamProducer, "produce", null);
@@ -4,6 +4,7 @@ exports.MagekEventsReader = void 0;
4
4
  const common_1 = require("@magek/common");
5
5
  const magek_1 = require("./magek");
6
6
  class MagekEventsReader {
7
+ config;
7
8
  constructor(config) {
8
9
  this.config = config;
9
10
  }
@@ -3,10 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MagekGlobalErrorDispatcher = void 0;
4
4
  const common_1 = require("@magek/common");
5
5
  class MagekGlobalErrorDispatcher {
6
+ config;
7
+ errorHandler;
6
8
  constructor(config) {
7
- var _a;
8
9
  this.config = config;
9
- this.errorHandler = (_a = this.config.globalErrorsHandler) === null || _a === void 0 ? void 0 : _a.class;
10
+ this.errorHandler = this.config.globalErrorsHandler?.class;
10
11
  }
11
12
  async dispatch(error) {
12
13
  const logger = (0, common_1.getLogger)(this.config, 'MagekGlobalErrorDispatcher#dispatch');
@@ -11,172 +11,177 @@ const noop_read_model_pub_sub_1 = require("./services/pub-sub/noop-read-model-pu
11
11
  const graphql_websocket_protocol_1 = require("./services/graphql/websocket-protocol/graphql-websocket-protocol");
12
12
  const token_verifier_1 = require("./token-verifier");
13
13
  const instrumentation_1 = require("./instrumentation");
14
- class MagekGraphQLDispatcher {
15
- constructor(config) {
16
- this.config = config;
17
- this.readModelDispatcher = new read_models_reader_1.MagekReadModelsReader(config);
18
- this.graphQLSchema = graphql_generator_1.GraphQLGenerator.generateSchema(config);
19
- this.tokenVerifier = new token_verifier_1.MagekTokenVerifier(config);
20
- this.websocketHandler = new graphql_websocket_protocol_1.GraphQLWebsocketHandler(config, {
21
- onStartOperation: this.runGraphQLOperation.bind(this),
22
- onStopOperation: this.readModelDispatcher.unsubscribe.bind(this.readModelDispatcher),
23
- onTerminate: this.handleDisconnect.bind(this),
24
- }, this.tokenVerifier);
25
- }
26
- async dispatch(request) {
27
- const logger = (0, common_1.getLogger)(this.config, 'MagekGraphQLDispatcher#dispatch');
28
- const envelopeOrError = await this.config.runtime.graphQL.rawToEnvelope(this.config, request);
29
- logger.debug('Received the following GraphQL envelope: ', envelopeOrError);
30
- switch (envelopeOrError.eventType) {
31
- case 'CONNECT':
32
- return this.config.runtime.graphQL.handleResult(null, common_1.graphQLWebsocketSubprotocolHeaders);
33
- case 'MESSAGE':
34
- const responseHeaders = { ...this.config.defaultResponseHeaders };
35
- const result = await this.handleMessage(envelopeOrError, responseHeaders);
36
- return this.config.runtime.graphQL.handleResult(result, responseHeaders);
37
- case 'DISCONNECT':
38
- return this.config.runtime.graphQL.handleResult(await this.handleDisconnect(envelopeOrError.connectionID));
39
- default:
40
- return this.config.runtime.graphQL.handleResult({
41
- errors: [new Error(`Unknown message type ${envelopeOrError.eventType}`)],
42
- });
43
- }
44
- }
45
- async verifyTokenFromEnvelope(envelope) {
46
- const logger = (0, common_1.getLogger)(this.config, 'MagekGraphQLDispatcher#verifyTokenFromEnvelop');
47
- if (envelope.token) {
48
- try {
49
- logger.debug(`Decoding current user from auth token: ${envelope.token}`);
50
- envelope.currentUser = await this.tokenVerifier.verify(envelope.token);
51
- }
52
- catch (e) {
53
- envelope = {
54
- ...envelope,
55
- error: e,
56
- };
57
- logger.debug('Unable to decode auth token');
58
- }
14
+ let MagekGraphQLDispatcher = (() => {
15
+ let _instanceExtraInitializers = [];
16
+ let _dispatch_decorators;
17
+ let _runGraphQLOperation_decorators;
18
+ return class MagekGraphQLDispatcher {
19
+ static {
20
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
21
+ _dispatch_decorators = [(0, instrumentation_1.trace)(common_1.TraceActionTypes.GRAPHQL_DISPATCH)];
22
+ _runGraphQLOperation_decorators = [(0, instrumentation_1.trace)(common_1.TraceActionTypes.GRAPHQL_RUN_OPERATION)];
23
+ tslib_1.__esDecorate(this, null, _dispatch_decorators, { kind: "method", name: "dispatch", static: false, private: false, access: { has: obj => "dispatch" in obj, get: obj => obj.dispatch }, metadata: _metadata }, null, _instanceExtraInitializers);
24
+ tslib_1.__esDecorate(this, null, _runGraphQLOperation_decorators, { kind: "method", name: "runGraphQLOperation", static: false, private: false, access: { has: obj => "runGraphQLOperation" in obj, get: obj => obj.runGraphQLOperation }, metadata: _metadata }, null, _instanceExtraInitializers);
25
+ if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
59
26
  }
60
- return envelope;
61
- }
62
- async handleMessage(envelope, responseHeaders) {
63
- const logger = (0, common_1.getLogger)(this.config, 'MagekGraphQLDispatcher#handleMessage');
64
- logger.debug('Starting GraphQL operation:', envelope);
65
- const envelopeOrError = await this.verifyTokenFromEnvelope(envelope);
66
- if (cameThroughSocket(envelopeOrError)) {
67
- return this.websocketHandler.handle(envelopeOrError);
27
+ config = tslib_1.__runInitializers(this, _instanceExtraInitializers);
28
+ graphQLSchema;
29
+ websocketHandler;
30
+ readModelDispatcher;
31
+ tokenVerifier;
32
+ constructor(config) {
33
+ this.config = config;
34
+ this.readModelDispatcher = new read_models_reader_1.MagekReadModelsReader(config);
35
+ this.graphQLSchema = graphql_generator_1.GraphQLGenerator.generateSchema(config);
36
+ this.tokenVerifier = new token_verifier_1.MagekTokenVerifier(config);
37
+ this.websocketHandler = new graphql_websocket_protocol_1.GraphQLWebsocketHandler(config, {
38
+ onStartOperation: this.runGraphQLOperation.bind(this),
39
+ onStopOperation: this.readModelDispatcher.unsubscribe.bind(this.readModelDispatcher),
40
+ onTerminate: this.handleDisconnect.bind(this),
41
+ }, this.tokenVerifier);
68
42
  }
69
- return this.runGraphQLOperation(envelopeOrError, responseHeaders);
70
- }
71
- async runGraphQLOperation(envelope, responseHeaders = {}) {
72
- const logger = (0, common_1.getLogger)(this.config, 'MagekGraphQLDispatcher#runGraphQLOperation');
73
- try {
74
- if ('error' in envelope) {
75
- throw envelope.error;
76
- }
77
- if (!envelope.value) {
78
- throw new common_1.InvalidParameterError('Received an empty GraphQL body');
43
+ async dispatch(request) {
44
+ const logger = (0, common_1.getLogger)(this.config, 'MagekGraphQLDispatcher#dispatch');
45
+ const envelopeOrError = await this.config.runtime.graphQL.rawToEnvelope(this.config, request);
46
+ logger.debug('Received the following GraphQL envelope: ', envelopeOrError);
47
+ switch (envelopeOrError.eventType) {
48
+ case 'CONNECT':
49
+ return this.config.runtime.graphQL.handleResult(null, common_1.graphQLWebsocketSubprotocolHeaders);
50
+ case 'MESSAGE':
51
+ const responseHeaders = { ...this.config.defaultResponseHeaders };
52
+ const result = await this.handleMessage(envelopeOrError, responseHeaders);
53
+ return this.config.runtime.graphQL.handleResult(result, responseHeaders);
54
+ case 'DISCONNECT':
55
+ return this.config.runtime.graphQL.handleResult(await this.handleDisconnect(envelopeOrError.connectionID));
56
+ default:
57
+ return this.config.runtime.graphQL.handleResult({
58
+ errors: [new Error(`Unknown message type ${envelopeOrError.eventType}`)],
59
+ });
79
60
  }
80
- const operation = envelope.value;
81
- if (!operation.query) {
82
- throw new common_1.InvalidParameterError('Received an empty GraphQL query');
83
- }
84
- const queryDocument = graphql.parse(operation.query);
85
- const errors = graphql.validate(this.graphQLSchema, queryDocument);
86
- if (errors.length > 0) {
87
- throw errors;
61
+ }
62
+ async verifyTokenFromEnvelope(envelope) {
63
+ const logger = (0, common_1.getLogger)(this.config, 'MagekGraphQLDispatcher#verifyTokenFromEnvelop');
64
+ if (envelope.token) {
65
+ try {
66
+ logger.debug(`Decoding current user from auth token: ${envelope.token}`);
67
+ envelope.currentUser = await this.tokenVerifier.verify(envelope.token);
68
+ }
69
+ catch (e) {
70
+ envelope = {
71
+ ...envelope,
72
+ error: e,
73
+ };
74
+ logger.debug('Unable to decode auth token');
75
+ }
88
76
  }
89
- const operationData = graphql.getOperationAST(queryDocument, operation.operationName);
90
- const isIntrospectionQuery = operation.operationName === 'IntrospectionQuery' || operation.query.includes('__schema');
91
- if (isIntrospectionQuery && !this.config.enableGraphQLIntrospection) {
92
- throw new common_1.InvalidProtocolError('Instrospection queries are disabled. Check the configuration if you want to enable them.');
77
+ return envelope;
78
+ }
79
+ async handleMessage(envelope, responseHeaders) {
80
+ const logger = (0, common_1.getLogger)(this.config, 'MagekGraphQLDispatcher#handleMessage');
81
+ logger.debug('Starting GraphQL operation:', envelope);
82
+ const envelopeOrError = await this.verifyTokenFromEnvelope(envelope);
83
+ if (cameThroughSocket(envelopeOrError)) {
84
+ return this.websocketHandler.handle(envelopeOrError);
93
85
  }
94
- if (!operationData) {
95
- throw new common_1.InvalidParameterError('Could not extract GraphQL operation. ' +
96
- 'Be sure to either send only one query, mutation, or subscription, or, in case you send several operations, ' +
97
- 'include the "operationName" field');
86
+ return this.runGraphQLOperation(envelopeOrError, responseHeaders);
87
+ }
88
+ async runGraphQLOperation(envelope, responseHeaders = {}) {
89
+ const logger = (0, common_1.getLogger)(this.config, 'MagekGraphQLDispatcher#runGraphQLOperation');
90
+ try {
91
+ if ('error' in envelope) {
92
+ throw envelope.error;
93
+ }
94
+ if (!envelope.value) {
95
+ throw new common_1.InvalidParameterError('Received an empty GraphQL body');
96
+ }
97
+ const operation = envelope.value;
98
+ if (!operation.query) {
99
+ throw new common_1.InvalidParameterError('Received an empty GraphQL query');
100
+ }
101
+ const queryDocument = graphql.parse(operation.query);
102
+ const errors = graphql.validate(this.graphQLSchema, queryDocument);
103
+ if (errors.length > 0) {
104
+ throw errors;
105
+ }
106
+ const operationData = graphql.getOperationAST(queryDocument, operation.operationName);
107
+ const isIntrospectionQuery = operation.operationName === 'IntrospectionQuery' || operation.query.includes('__schema');
108
+ if (isIntrospectionQuery && !this.config.enableGraphQLIntrospection) {
109
+ throw new common_1.InvalidProtocolError('Instrospection queries are disabled. Check the configuration if you want to enable them.');
110
+ }
111
+ if (!operationData) {
112
+ throw new common_1.InvalidParameterError('Could not extract GraphQL operation. ' +
113
+ 'Be sure to either send only one query, mutation, or subscription, or, in case you send several operations, ' +
114
+ 'include the "operationName" field');
115
+ }
116
+ const resolverContext = {
117
+ connectionID: envelope.connectionID,
118
+ responseHeaders: responseHeaders,
119
+ requestID: envelope.requestID,
120
+ user: envelope.currentUser,
121
+ operation: {
122
+ ...operation,
123
+ },
124
+ pubSub: new noop_read_model_pub_sub_1.NoopReadModelPubSub(),
125
+ storeSubscriptions: true,
126
+ context: envelope.context,
127
+ };
128
+ switch (operationData.operation) {
129
+ case graphql_1.OperationTypeNode.QUERY:
130
+ case graphql_1.OperationTypeNode.MUTATION:
131
+ return await this.handleQueryOrMutation(queryDocument, resolverContext);
132
+ case graphql_1.OperationTypeNode.SUBSCRIPTION:
133
+ return await this.handleSubscription(queryDocument, resolverContext);
134
+ }
98
135
  }
99
- const resolverContext = {
100
- connectionID: envelope.connectionID,
101
- responseHeaders: responseHeaders,
102
- requestID: envelope.requestID,
103
- user: envelope.currentUser,
104
- operation: {
105
- ...operation,
106
- },
107
- pubSub: new noop_read_model_pub_sub_1.NoopReadModelPubSub(),
108
- storeSubscriptions: true,
109
- context: envelope.context,
110
- };
111
- switch (operationData.operation) {
112
- case graphql_1.OperationTypeNode.QUERY:
113
- case graphql_1.OperationTypeNode.MUTATION:
114
- return await this.handleQueryOrMutation(queryDocument, resolverContext);
115
- case graphql_1.OperationTypeNode.SUBSCRIPTION:
116
- return await this.handleSubscription(queryDocument, resolverContext);
136
+ catch (e) {
137
+ const error = e;
138
+ logger.error(e);
139
+ const errors = Array.isArray(e) ? e.map(toGraphQLErrorWithExtensions) : [toGraphQLErrorWithExtensions(error)];
140
+ return { errors };
117
141
  }
118
142
  }
119
- catch (e) {
120
- const error = e;
121
- logger.error(e);
122
- const errors = Array.isArray(e) ? e.map(toGraphQLErrorWithExtensions) : [toGraphQLErrorWithExtensions(error)];
123
- return { errors };
143
+ async handleQueryOrMutation(queryDocument, resolverContext) {
144
+ const logger = (0, common_1.getLogger)(this.config, 'MagekGraphQLDispatcher#handleQueryOrMutation');
145
+ const result = await graphql.execute({
146
+ schema: this.graphQLSchema,
147
+ document: queryDocument,
148
+ contextValue: resolverContext,
149
+ variableValues: resolverContext.operation.variables,
150
+ operationName: resolverContext.operation.operationName,
151
+ });
152
+ result.errors = result.errors?.map(toGraphQLErrorWithExtensions);
153
+ logger.debug('GraphQL result: ', result);
154
+ return result;
124
155
  }
125
- }
126
- async handleQueryOrMutation(queryDocument, resolverContext) {
127
- var _a;
128
- const logger = (0, common_1.getLogger)(this.config, 'MagekGraphQLDispatcher#handleQueryOrMutation');
129
- const result = await graphql.execute({
130
- schema: this.graphQLSchema,
131
- document: queryDocument,
132
- contextValue: resolverContext,
133
- variableValues: resolverContext.operation.variables,
134
- operationName: resolverContext.operation.operationName,
135
- });
136
- result.errors = (_a = result.errors) === null || _a === void 0 ? void 0 : _a.map(toGraphQLErrorWithExtensions);
137
- logger.debug('GraphQL result: ', result);
138
- return result;
139
- }
140
- async handleSubscription(queryDocument, resolverContext) {
141
- const logger = (0, common_1.getLogger)(this.config, 'MagekGraphQLDispatcher#handleSubscription');
142
- if (!cameThroughSocket(resolverContext)) {
143
- throw new common_1.InvalidProtocolError('This API and protocol does not support "subscription" operations, only "query" and "mutation". Use the socket API for "subscription"');
156
+ async handleSubscription(queryDocument, resolverContext) {
157
+ const logger = (0, common_1.getLogger)(this.config, 'MagekGraphQLDispatcher#handleSubscription');
158
+ if (!cameThroughSocket(resolverContext)) {
159
+ throw new common_1.InvalidProtocolError('This API and protocol does not support "subscription" operations, only "query" and "mutation". Use the socket API for "subscription"');
160
+ }
161
+ const result = await graphql.subscribe({
162
+ schema: this.graphQLSchema,
163
+ document: queryDocument,
164
+ contextValue: resolverContext,
165
+ variableValues: resolverContext.operation.variables,
166
+ operationName: resolverContext.operation.operationName,
167
+ });
168
+ logger.debug('GraphQL subscription finished');
169
+ return result;
144
170
  }
145
- const result = await graphql.subscribe({
146
- schema: this.graphQLSchema,
147
- document: queryDocument,
148
- contextValue: resolverContext,
149
- variableValues: resolverContext.operation.variables,
150
- operationName: resolverContext.operation.operationName,
151
- });
152
- logger.debug('GraphQL subscription finished');
153
- return result;
154
- }
155
- async handleDisconnect(connectionID) {
156
- const logger = (0, common_1.getLogger)(this.config, 'MagekGraphQLDispatcher#handleDisconnect');
157
- if (!connectionID) {
158
- // This should be impossible, but just in case
159
- logger.info("Received a DISCONNECT message but field 'connectionID' is missing. Doing nothing");
160
- return;
171
+ async handleDisconnect(connectionID) {
172
+ const logger = (0, common_1.getLogger)(this.config, 'MagekGraphQLDispatcher#handleDisconnect');
173
+ if (!connectionID) {
174
+ // This should be impossible, but just in case
175
+ logger.info("Received a DISCONNECT message but field 'connectionID' is missing. Doing nothing");
176
+ return;
177
+ }
178
+ logger.debug('Deleting all subscriptions and connection data');
179
+ await this.config.sessionStore.deleteConnection(this.config, connectionID);
180
+ await this.readModelDispatcher.unsubscribeAll(connectionID);
161
181
  }
162
- logger.debug('Deleting all subscriptions and connection data');
163
- await this.config.sessionStore.deleteConnection(this.config, connectionID);
164
- await this.readModelDispatcher.unsubscribeAll(connectionID);
165
- }
166
- }
182
+ };
183
+ })();
167
184
  exports.MagekGraphQLDispatcher = MagekGraphQLDispatcher;
168
- tslib_1.__decorate([
169
- (0, instrumentation_1.Trace)(common_1.TraceActionTypes.GRAPHQL_DISPATCH),
170
- tslib_1.__metadata("design:type", Function),
171
- tslib_1.__metadata("design:paramtypes", [Object]),
172
- tslib_1.__metadata("design:returntype", Promise)
173
- ], MagekGraphQLDispatcher.prototype, "dispatch", null);
174
- tslib_1.__decorate([
175
- (0, instrumentation_1.Trace)(common_1.TraceActionTypes.GRAPHQL_RUN_OPERATION),
176
- tslib_1.__metadata("design:type", Function),
177
- tslib_1.__metadata("design:paramtypes", [Object, Object]),
178
- tslib_1.__metadata("design:returntype", Promise)
179
- ], MagekGraphQLDispatcher.prototype, "runGraphQLOperation", null);
180
185
  function cameThroughSocket(withConnectionID) {
181
186
  return withConnectionID.connectionID != undefined;
182
187
  }
@@ -184,8 +189,8 @@ function toGraphQLErrorWithExtensions(e) {
184
189
  if (e instanceof graphql_1.GraphQLError) {
185
190
  const originalError = e.originalError;
186
191
  return new graphql_1.GraphQLError(e.message, e.nodes, e.source, e.positions, e.path, originalError, {
187
- code: originalError === null || originalError === void 0 ? void 0 : originalError.code,
188
- data: originalError === null || originalError === void 0 ? void 0 : originalError.data,
192
+ code: originalError?.code,
193
+ data: originalError?.data,
189
194
  });
190
195
  }
191
196
  return new graphql_1.GraphQLError(e.message, undefined, undefined, undefined, undefined, e, {
package/dist/index.js CHANGED
@@ -9,6 +9,10 @@ exports.consumeEventStream = consumeEventStream;
9
9
  exports.produceEventStream = produceEventStream;
10
10
  exports.health = health;
11
11
  const tslib_1 = require("tslib");
12
+ // Polyfill for Symbol.metadata (required for TC39 Stage 3 decorators)
13
+ // Must be defined before any decorated code is imported
14
+ // Node.js 22.x doesn't have native Symbol.metadata yet
15
+ Symbol.metadata ??= Symbol.for('Symbol.metadata');
12
16
  const magek_1 = require("./magek");
13
17
  const event_dispatcher_1 = require("./event-dispatcher");
14
18
  const graphql_dispatcher_1 = require("./graphql-dispatcher");
@@ -6,8 +6,16 @@ interface Stage3MethodContext {
6
6
  name: string | symbol;
7
7
  static: boolean;
8
8
  private: boolean;
9
- metadata: Record<string | symbol, unknown>;
9
+ metadata?: Record<string | symbol, unknown>;
10
10
  addInitializer?: (initializer: () => void) => void;
11
11
  }
12
- export declare function Trace(actionType?: string, description?: string): (targetOrMethod: unknown, memberOrContext: string | Stage3MethodContext, descriptor?: TypedPropertyDescriptor<(...params: any[]) => Promise<any>>) => any;
13
- export {};
12
+ /**
13
+ * Decorator for tracing method execution.
14
+ *
15
+ * Uses TC39 Stage 3 decorators.
16
+ *
17
+ * @param actionType - The type of action being traced
18
+ * @param description - Optional description for the trace
19
+ */
20
+ export declare function trace(actionType?: string, description?: string): <T extends (...args: any[]) => Promise<any>>(originalMethod: T, context: Stage3MethodContext) => T;
21
+ export { trace as Trace };
@@ -1,64 +1,29 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Trace = Trace;
3
+ exports.trace = trace;
4
+ exports.Trace = trace;
4
5
  const common_1 = require("@magek/common");
5
6
  const trace_notifier_1 = require("../trace-notifier");
6
7
  const magek_1 = require("../../magek");
7
8
  /**
8
- * Type guard for Stage 3 method context
9
+ * Decorator for tracing method execution.
10
+ *
11
+ * Uses TC39 Stage 3 decorators.
12
+ *
13
+ * @param actionType - The type of action being traced
14
+ * @param description - Optional description for the trace
9
15
  */
10
- function isStage3MethodContext(arg) {
11
- return (arg !== null &&
12
- typeof arg === 'object' &&
13
- 'kind' in arg &&
14
- arg.kind === 'method' &&
15
- 'name' in arg);
16
- }
17
- function Trace(actionType = common_1.TraceActionTypes.CUSTOM, description) {
18
- // Return type is 'any' to support both legacy (returns PropertyDescriptor) and Stage 3 (returns Function) decorators
19
- return (targetOrMethod, memberOrContext, descriptor) => {
20
- // Detect Stage 3 decorator
21
- if (isStage3MethodContext(memberOrContext)) {
22
- // Stage 3: targetOrMethod is the actual method function
23
- const originalMethod = targetOrMethod;
24
- const methodName = String(memberOrContext.name);
25
- // Return a new function that wraps the original
26
- return async function (...args) {
27
- const config = magek_1.Magek.config;
28
- const tracerConfigured = (0, trace_notifier_1.isTraceEnabled)(actionType, config);
29
- if (!tracerConfigured) {
30
- return await originalMethod.apply(this, args);
31
- }
32
- const parameters = buildParametersStage3(this, methodName, args, description, config);
33
- const startTime = new Date().getTime();
34
- await (0, trace_notifier_1.notifyTrace)(common_1.TraceTypes.START, actionType, parameters, config);
35
- try {
36
- return await originalMethod.apply(this, args);
37
- }
38
- finally {
39
- parameters.elapsedInvocationMillis = new Date().getTime() - startTime;
40
- await (0, trace_notifier_1.notifyTrace)(common_1.TraceTypes.END, actionType, parameters, config);
41
- }
42
- };
43
- }
44
- // Legacy decorator
45
- const target = targetOrMethod;
46
- const member = memberOrContext;
47
- // Handle case where descriptor is undefined (can happen with certain TypeScript/ESM configurations)
48
- if (!descriptor) {
49
- return;
50
- }
51
- const originalMethod = descriptor.value;
52
- if (!originalMethod) {
53
- return descriptor;
54
- }
55
- descriptor.value = async function (...args) {
16
+ function trace(actionType = common_1.TraceActionTypes.CUSTOM, description) {
17
+ return (originalMethod, context) => {
18
+ const methodName = String(context.name);
19
+ // Return a new function that wraps the original
20
+ const wrappedMethod = async function (...args) {
56
21
  const config = magek_1.Magek.config;
57
22
  const tracerConfigured = (0, trace_notifier_1.isTraceEnabled)(actionType, config);
58
23
  if (!tracerConfigured) {
59
24
  return await originalMethod.apply(this, args);
60
25
  }
61
- const parameters = buildParameters(target, member, args, description, descriptor, config);
26
+ const parameters = buildParameters(this, methodName, args, description, config);
62
27
  const startTime = new Date().getTime();
63
28
  await (0, trace_notifier_1.notifyTrace)(common_1.TraceTypes.START, actionType, parameters, config);
64
29
  try {
@@ -69,28 +34,10 @@ function Trace(actionType = common_1.TraceActionTypes.CUSTOM, description) {
69
34
  await (0, trace_notifier_1.notifyTrace)(common_1.TraceTypes.END, actionType, parameters, config);
70
35
  }
71
36
  };
72
- return descriptor;
73
- };
74
- }
75
- function buildParameters(target, member, args, description, descriptor, config) {
76
- let internal = undefined;
77
- if (config && config.traceConfiguration.includeInternal) {
78
- internal = {
79
- target: target,
80
- descriptor: descriptor,
81
- };
82
- }
83
- const parameters = {
84
- className: getClassName(target),
85
- methodName: member,
86
- args: args,
87
- description: description,
88
- traceId: common_1.UUID.generate(),
89
- internal: internal,
37
+ return wrappedMethod;
90
38
  };
91
- return parameters;
92
39
  }
93
- function buildParametersStage3(instance, methodName, args, description, config) {
40
+ function buildParameters(instance, methodName, args, description, config) {
94
41
  let internal = undefined;
95
42
  if (config && config.traceConfiguration.includeInternal) {
96
43
  internal = {
@@ -110,7 +57,6 @@ function buildParametersStage3(instance, methodName, args, description, config)
110
57
  }
111
58
  // Get class name for instances and static methods
112
59
  function getClassName(target) {
113
- var _a, _b, _c, _d, _e;
114
60
  // @ts-ignore
115
- return (_e = (_c = (_b = (_a = target === null || target === void 0 ? void 0 : target.prototype) === null || _a === void 0 ? void 0 : _a.constructor) === null || _b === void 0 ? void 0 : _b.name) !== null && _c !== void 0 ? _c : (_d = target === null || target === void 0 ? void 0 : target.constructor) === null || _d === void 0 ? void 0 : _d.name) !== null && _e !== void 0 ? _e : '';
61
+ return target?.prototype?.constructor?.name ?? target?.constructor?.name ?? '';
116
62
  }