@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.
- package/dist/authorizer.js +1 -1
- package/dist/command-dispatcher.js +47 -41
- package/dist/core-concepts/data-migration/entities/data-migration-entity.js +5 -2
- package/dist/core-concepts/data-migration/events/data-migration-finished.js +3 -1
- package/dist/core-concepts/data-migration/events/data-migration-started.js +3 -1
- package/dist/core-concepts/data-migration/events/entity-migrated.js +4 -0
- package/dist/core-concepts/touch-entity/events/entity-touched.js +2 -0
- package/dist/data-migrations.js +59 -54
- package/dist/decorators/command.d.ts +4 -11
- package/dist/decorators/command.js +10 -18
- package/dist/decorators/data-migration.d.ts +4 -1
- package/dist/decorators/data-migration.js +3 -1
- package/dist/decorators/decorator-types.d.ts +50 -0
- package/dist/decorators/decorator-types.js +11 -0
- package/dist/decorators/decorator-utils.d.ts +1 -0
- package/dist/decorators/decorator-utils.js +2 -0
- package/dist/decorators/entity.d.ts +7 -15
- package/dist/decorators/entity.js +27 -37
- package/dist/decorators/event-handler.d.ts +11 -1
- package/dist/decorators/event-handler.js +13 -1
- package/dist/decorators/event.d.ts +4 -1
- package/dist/decorators/event.js +3 -2
- package/dist/decorators/field-metadata-reader.d.ts +8 -3
- package/dist/decorators/field-metadata-reader.js +50 -62
- package/dist/decorators/field.d.ts +23 -0
- package/dist/decorators/field.js +41 -0
- package/dist/decorators/global-error-handler.d.ts +10 -1
- package/dist/decorators/global-error-handler.js +9 -1
- package/dist/decorators/global-event-handler.d.ts +10 -1
- package/dist/decorators/global-event-handler.js +9 -1
- package/dist/decorators/health-sensor.d.ts +4 -1
- package/dist/decorators/health-sensor.js +3 -2
- package/dist/decorators/index.d.ts +3 -0
- package/dist/decorators/index.js +2 -0
- package/dist/decorators/metadata.d.ts +17 -1
- package/dist/decorators/metadata.js +22 -22
- package/dist/decorators/non-exposed.d.ts +13 -2
- package/dist/decorators/non-exposed.js +22 -20
- package/dist/decorators/notification.d.ts +6 -18
- package/dist/decorators/notification.js +10 -50
- package/dist/decorators/projects.d.ts +5 -18
- package/dist/decorators/projects.js +23 -54
- package/dist/decorators/query.d.ts +11 -1
- package/dist/decorators/query.js +18 -4
- package/dist/decorators/read-model.d.ts +13 -27
- package/dist/decorators/read-model.js +45 -77
- package/dist/decorators/role.d.ts +9 -3
- package/dist/decorators/role.js +8 -3
- package/dist/decorators/scheduled-command.d.ts +4 -1
- package/dist/decorators/scheduled-command.js +3 -1
- package/dist/decorators/schema-migration.d.ts +11 -27
- package/dist/decorators/schema-migration.js +32 -77
- package/dist/decorators/sequenced-by.d.ts +7 -25
- package/dist/decorators/sequenced-by.js +11 -71
- package/dist/event-dispatcher.js +29 -24
- package/dist/event-processor.js +106 -103
- package/dist/event-stream-consumer.js +25 -20
- package/dist/event-stream-producer.js +22 -17
- package/dist/events-reader.js +1 -0
- package/dist/global-error-dispatcher.js +3 -2
- package/dist/graphql-dispatcher.js +161 -156
- package/dist/index.js +4 -0
- package/dist/instrumentation/decorator/trace.d.ts +11 -3
- package/dist/instrumentation/decorator/trace.js +17 -71
- package/dist/magek.js +2 -2
- package/dist/query-dispatcher.js +2 -0
- package/dist/read-model-schema-migrator.js +71 -68
- package/dist/read-models-reader.js +178 -180
- package/dist/register-handler.js +3 -3
- package/dist/scheduled-command-dispatcher.js +48 -42
- package/dist/schema-migrator.js +63 -59
- package/dist/sensor/health/health-service.js +2 -1
- package/dist/services/event-store.js +221 -224
- package/dist/services/graphql/graphql-generator.js +11 -8
- package/dist/services/graphql/graphql-mutation-generator.js +4 -0
- package/dist/services/graphql/graphql-query-generator.js +14 -0
- package/dist/services/graphql/graphql-subcriptions-generator.js +7 -0
- package/dist/services/graphql/graphql-type-informer.js +4 -3
- package/dist/services/graphql/query-generators/graphql-query-by-keys-generator.js +4 -0
- package/dist/services/graphql/query-generators/graphql-query-events-generator.js +3 -0
- package/dist/services/graphql/query-generators/graphql-query-filters-generator.js +6 -0
- package/dist/services/graphql/query-generators/graphql-query-generator.js +4 -0
- package/dist/services/graphql/query-generators/graphql-query-listed-generator.js +7 -0
- package/dist/services/graphql/query-helpers/graphql-handled-fields-generator.js +5 -2
- package/dist/services/graphql/query-helpers/graphql-query-filter-arguments-builder.js +3 -0
- package/dist/services/graphql/query-helpers/graphql-query-filter-fields-builder.js +4 -0
- package/dist/services/graphql/query-helpers/graphql-query-sort-builder.js +4 -2
- package/dist/services/graphql/websocket-protocol/graphql-websocket-protocol.js +5 -3
- package/dist/services/pub-sub/read-model-pub-sub.js +1 -0
- package/dist/services/raw-events-parser.js +1 -1
- package/dist/services/read-model-store.js +16 -17
- package/dist/services/token-verifiers/jwks-uri-token-verifier.js +8 -4
- package/dist/services/token-verifiers/public-key-token-verifier.js +4 -2
- package/dist/services/token-verifiers/role-based-token-verifier.js +2 -1
- package/dist/services/token-verifiers/utilities.js +1 -1
- package/dist/subscribers-notifier.js +98 -92
- package/dist/token-verifier.js +2 -1
- package/package.json +4 -4
- package/dist/decorators/stage3-utils.d.ts +0 -6
- package/dist/decorators/stage3-utils.js +0 -25
|
@@ -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
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
-
|
|
26
|
-
logger
|
|
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
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const
|
|
17
|
-
|
|
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
|
-
|
|
20
|
-
logger
|
|
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);
|
package/dist/events-reader.js
CHANGED
|
@@ -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 =
|
|
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
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
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
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
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
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
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
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
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
|
-
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
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
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
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
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
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
|
-
|
|
163
|
-
|
|
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
|
|
188
|
-
data: originalError
|
|
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
|
|
9
|
+
metadata?: Record<string | symbol, unknown>;
|
|
10
10
|
addInitializer?: (initializer: () => void) => void;
|
|
11
11
|
}
|
|
12
|
-
|
|
13
|
-
|
|
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.
|
|
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
|
-
*
|
|
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
|
|
11
|
-
return (
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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(
|
|
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
|
|
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
|
|
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
|
|
61
|
+
return target?.prototype?.constructor?.name ?? target?.constructor?.name ?? '';
|
|
116
62
|
}
|