vulcain-corejs
Version:
Vulcain micro-service framework
122 lines • 6.37 kB
JavaScript
;
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
Object.defineProperty(exports, "__esModule", { value: true });
const annotations_1 = require("../di/annotations");
const messageBus_1 = require("../bus/messageBus");
const annotations_2 = require("../di/annotations");
const typeBuilder_1 = require("./typeBuilder");
const applicationRequestError_1 = require("../pipeline/errors/applicationRequestError");
const conventions_1 = require("../utils/conventions");
const graphql = require('graphql');
const graphQlQuerySymbol = Symbol("[[graphqlquery]]");
let GraphQLAdapter = class GraphQLAdapter {
constructor(container) {
this.container = container;
this._subscriptions = new Map();
}
async processGraphQLQuery(context, g) {
context.requestData[graphQlQuerySymbol] = g.query || g;
if ((g.query || g).indexOf("subscription") >= 0)
throw new applicationRequestError_1.ApplicationError("Invalid subscription. Use Server Side Event on " + conventions_1.Conventions.instance.defaultGraphQLSubscriptionPath);
let result = await graphql.graphql(this.getGraphQuerySchema(context), g.query || g, null, context, g.variables);
return result;
}
enableSubscription(context, handler, entity) {
if (entity)
return entity;
// Subscription step
let g = context.requestData[graphQlQuerySymbol];
let item = { scope: handler.definition.scope, subscriptions: {} };
item.subscriptions[handler.name] = g.query || g;
this._subscriptions.set(context.requestData.correlationId, item);
}
getGraphQuerySchema(context) {
if (!this._schema) {
const builder = new typeBuilder_1.GraphQLTypeBuilder();
this._schema = builder.build(context, this);
}
return this._schema;
}
getSubscriptionHandler() {
return async (ctx) => {
let response = ctx.request.nativeResponse;
let request = ctx.request.nativeRequest;
let query = request.url.substr(request.url.indexOf('?') + 1);
let parts = query && query.split('=');
if (!parts || parts.length !== 2 || parts[0] !== "query") {
response.statusCode = 400;
response.end("query is required");
return;
}
let g = decodeURIComponent(parts[1]);
ctx.requestData[graphQlQuerySymbol] = g;
let result;
try {
result = await graphql.graphql(this.getGraphQuerySchema(ctx), g, null, ctx);
}
catch (e) {
result = { errors: e.message || e };
}
if (result.errors) {
response.statusCode = 400;
response.setHeader("ContentType", "application/json");
response.end(JSON.stringify(result.errors));
return;
}
response.setHeader('Content-Type', 'text/event-stream');
response.setHeader('Cache-Control', 'no-cache, no-store, max-age=0, must-revalidate');
response.setHeader('Pragma', 'no-cache');
response.setHeader('Access-Control-Allow-Origin', '*');
response.flushHeaders();
let self = this;
let id = ctx.requestData.correlationId;
let subscription = messageBus_1.MessageBus.localEvents.subscribe(async function onNext(evt) {
let eventHandlerName = evt[messageBus_1.MessageBus.LocalEventSymbol];
let item = self._subscriptions.get(id);
if (!item)
return;
let g = item.subscriptions[eventHandlerName];
if (!g)
return;
// Verify authorization
if (item.scope && !ctx.user.hasScope(item.scope)) {
ctx.logError(new Error(`Unauthorized for handler ${conventions_1.Conventions.instance.defaultGraphQLSubscriptionPath} with scope=${item.scope}`), () => `Current user is user=${ctx.user.name}, scopes=${ctx.user.scopes}`);
throw new applicationRequestError_1.UnauthorizedRequestError();
}
let result = await graphql.graphql(self.getGraphQuerySchema(ctx), g, evt.value, ctx);
let payload = {
[eventHandlerName]: result && result.data && result.data[eventHandlerName],
action: evt.action,
schema: evt.schema,
error: evt.error
};
//response.write("event: " + eventHandlerName + '\n');
response.write("id: " + evt.correlationId + '\n');
response.write("data: " + JSON.stringify(payload) + '\n\n');
});
request.on("close", () => {
self._subscriptions.delete(id);
if (subscription)
subscription.unsubscribe();
});
};
}
};
GraphQLAdapter = __decorate([
annotations_1.Injectable(annotations_1.LifeTime.Singleton, annotations_1.DefaultServiceNames.GraphQLAdapter),
__param(0, annotations_2.Inject(annotations_1.DefaultServiceNames.Container)),
__metadata("design:paramtypes", [Object])
], GraphQLAdapter);
exports.GraphQLAdapter = GraphQLAdapter;
//# sourceMappingURL=graphQLAdapter.js.map