api-core
Version:
Model-based dynamic multi-level APIs for any provider, plus multiple consumption channels
700 lines • 35.5 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ApiQueryBuilder = exports.ExtendContextLiveQueryStep = exports.ExtendContextQueryStep = exports.ProvideIdQueryStep = exports.SetBodyQueryStep = exports.SetResponseQueryStep = exports.RelateBackwardsChangeQueryStep = exports.RelateChangeQueryStep = exports.RelateBackwardsQueryStep = exports.RelateQueryStep = exports.CallMethodQueryStep = exports.QueryEdgeQueryStep = exports.EmbedQueryQueryStep = void 0;
const ApiQuery_1 = require("./ApiQuery");
const ApiEdgeQuery_1 = require("../edge/ApiEdgeQuery");
const ApiEdgeQueryContext_1 = require("../edge/ApiEdgeQueryContext");
const ApiEdgeError_1 = require("./ApiEdgeError");
const ApiEdgeQueryFilter_1 = require("../edge/ApiEdgeQueryFilter");
const ApiRequest_1 = require("../request/ApiRequest");
const ApiEdgeQueryResponse_1 = require("../edge/ApiEdgeQueryResponse");
const ApiEdgeQueryType_1 = require("../edge/ApiEdgeQueryType");
const OneToOneRelation_1 = require("../relations/OneToOneRelation");
const Api_1 = require("../Api");
const ApiEdgeMethod_1 = require("../edge/ApiEdgeMethod");
const ApiEdgeAction_1 = require("../edge/ApiEdgeAction");
const ApiAction_1 = require("./ApiAction");
const OneToManyRelation_1 = require("../relations/OneToManyRelation");
const parse = require('obj-parse');
const debug = require('debug')('api-core');
class EmbedQueryQueryStep {
constructor(query, segment, request) {
this.execute = (scope) => {
return new Promise((resolve, reject) => {
debug(`[${scope.query.id}]`, this.inspect());
if (scope.response) {
const target = scope.response.data;
if (Array.isArray(target)) {
const targetIndex = {}, targetArrayIndex = {}, ids = [];
for (let entry of target) {
const id = entry[this.sourceField];
if (id) {
if (Array.isArray(id)) {
let index = 0;
for (let _id of id) {
if (targetArrayIndex[_id])
targetArrayIndex[_id].push({ entry, index });
else
targetArrayIndex[_id] = [{ entry, index }];
ids.push(_id);
index++;
}
entry[this.sourceField] = [];
}
else {
if (targetIndex[id])
targetIndex[id].push(entry);
else
targetIndex[id] = [entry];
ids.push(id);
if (this.forceArray)
entry[this.targetField] = [];
}
}
}
this.request.context.filters = [
new ApiEdgeQueryFilter_1.ApiEdgeQueryFilter(this.idField, ApiEdgeQueryFilter_1.ApiEdgeQueryFilterType.In, ids)
];
this.query.execute(scope.identity).then((response) => {
if (response.data && response.data.length) {
for (let entry of response.data) {
let ids = entry[this.idField];
if (!Array.isArray(ids)) {
ids = [ids];
}
for (let id of ids) {
if (targetIndex[id]) {
for (let subEntry of targetIndex[id]) {
if (this.forceArray)
subEntry[this.targetField].push(entry);
else
subEntry[this.targetField] = entry;
}
}
if (targetArrayIndex[id]) {
for (let { entry: subEntry, index } of targetArrayIndex[id]) {
subEntry[this.targetField][index] = entry;
}
}
}
}
}
resolve(scope);
}).catch(reject);
}
else {
const sourceId = target[this.sourceField];
if (!sourceId) {
resolve(scope);
return;
}
if (Array.isArray(sourceId)) {
this.request.context.filters = [
new ApiEdgeQueryFilter_1.ApiEdgeQueryFilter(this.idField, ApiEdgeQueryFilter_1.ApiEdgeQueryFilterType.In, sourceId)
];
}
else if (this.forceArray) {
this.request.context.filters = [
new ApiEdgeQueryFilter_1.ApiEdgeQueryFilter(this.idField, ApiEdgeQueryFilter_1.ApiEdgeQueryFilterType.Equals, sourceId)
];
}
else {
this.segment.id = sourceId;
}
this.query.execute(scope.identity).then((response) => {
if (Array.isArray(sourceId)) {
const unordered_data = response.data;
response.data = [];
for (const id of sourceId) {
const item = unordered_data.find((item) => {
return item.id.toString() == id.toString();
});
if (item)
response.data.push(item);
else
console.warn("WARNING: can\'t find in embed results this id: " + id);
}
}
target[this.targetField] = response.data;
resolve(scope);
}).catch(e => {
console.warn(e);
resolve(scope);
});
}
}
else
resolve(scope);
});
};
this.inspect = () => `EMBED QUERY /${this.sourceField} -> ${this.targetField}`;
this.query = query;
this.query.request = this.request = request;
this.segment = segment;
if (!this.segment.relation)
throw new Error('Invalid relation provided.');
this.sourceField = this.segment.relation.relationId;
this.targetField = this.segment.relation.name;
this.idField = this.segment.relation.relatedId;
this.forceArray = this.segment.relation instanceof OneToManyRelation_1.OneToManyRelation;
this.isMultiMulti = this.segment.relation.hasPair;
}
}
exports.EmbedQueryQueryStep = EmbedQueryQueryStep;
class QueryEdgeQueryStep {
constructor(query) {
this.execute = (scope) => {
return new Promise((resolve, reject) => {
debug(`[${scope.query.id}]`, this.inspect());
if (this.query.type !== ApiEdgeQueryType_1.ApiEdgeQueryType.Get && this.query.type !== ApiEdgeQueryType_1.ApiEdgeQueryType.List) {
this.query.body = scope.body;
}
this.query.context = scope.context;
this.query.context.populatedRelations = [];
this.query.context.identity = scope.identity;
this.query.execute().then((response) => {
scope.context = new ApiEdgeQueryContext_1.ApiEdgeQueryContext();
scope.response = response;
resolve(scope);
}).catch(reject);
});
};
this.inspect = () => `QUERY /${this.query.edge.pluralName}`;
this.query = query;
}
}
exports.QueryEdgeQueryStep = QueryEdgeQueryStep;
class CallMethodQueryStep {
constructor(method, edge) {
this.execute = (scope) => {
return new Promise((resolve, reject) => {
debug(`[${scope.query.id}]`, this.inspect());
scope.context.method = this.method.name;
this.method.execute(scope)
.then((response) => {
scope.response = response;
resolve(scope);
}).catch((e) => {
debug(`failed to execute ${this.method.name} method`, e);
reject(e);
});
});
};
this.inspect = () => `call{${this.method.name}}`;
this.method = method;
this.edge = edge;
}
}
exports.CallMethodQueryStep = CallMethodQueryStep;
class RelateQueryStep {
constructor(relation) {
this.execute = (scope) => {
return new Promise((resolve, reject) => {
debug(`[${scope.query.id}]`, this.inspect());
if (!scope.response)
return reject(new ApiEdgeError_1.ApiEdgeError(404, "Missing Related Entry"));
scope.context.filter(this.relation.relationId, ApiEdgeQueryFilter_1.ApiEdgeQueryFilterType.Equals, scope.response.data[this.relation.relatedId]);
resolve(scope);
});
};
this.inspect = () => `RELATE ${this.relation.relationId} = ${this.relation.relatedId}`;
this.relation = relation;
}
}
exports.RelateQueryStep = RelateQueryStep;
class RelateBackwardsQueryStep {
constructor(relation) {
this.execute = (scope) => {
return new Promise((resolve, reject) => {
debug(`[${scope.query.id}]`, this.inspect());
if (!scope.response)
return reject(new ApiEdgeError_1.ApiEdgeError(404, "Missing Related Entry"));
scope.context.filter(this.relation.relatedId, ApiEdgeQueryFilter_1.ApiEdgeQueryFilterType.Equals, scope.response.data[this.relation.relationId]);
resolve(scope);
});
};
this.inspect = () => `RELATE ${this.relation.relatedId} = ${this.relation.relationId}`;
this.relation = relation;
}
}
exports.RelateBackwardsQueryStep = RelateBackwardsQueryStep;
class RelateChangeQueryStep {
constructor(relation) {
this.execute = (scope) => {
return new Promise((resolve, reject) => {
debug(`[${scope.query.id}]`, this.inspect());
if (!scope.body)
return reject(new ApiEdgeError_1.ApiEdgeError(404, "Missing Body"));
if (!scope.response)
return reject(new ApiEdgeError_1.ApiEdgeError(404, "Missing Related Entry"));
parse(this.relation.relationId).assign(scope.body, scope.response.data[this.relation.relatedId].toString());
resolve(scope);
});
};
this.inspect = () => `RELATE CHANGE ${this.relation.relationId}`;
this.relation = relation;
}
}
exports.RelateChangeQueryStep = RelateChangeQueryStep;
class RelateBackwardsChangeQueryStep {
constructor(relation) {
this.execute = (scope) => {
return new Promise((resolve, reject) => {
debug(`[${scope.query.id}]`, this.inspect());
if (!scope.body)
return reject(new ApiEdgeError_1.ApiEdgeError(404, "Missing Body"));
if (!scope.response)
return reject(new ApiEdgeError_1.ApiEdgeError(404, "Missing Related Entry"));
parse(this.relation.relatedId).assign(scope.body, scope.response.data[this.relation.relationId].toString());
resolve(scope);
});
};
this.inspect = () => `RELATE CHANGE BACKWARD ${this.relation.relatedId}`;
this.relation = relation;
}
}
exports.RelateBackwardsChangeQueryStep = RelateBackwardsChangeQueryStep;
class SetResponseQueryStep {
constructor(response) {
this.execute = (scope) => {
return new Promise(resolve => {
debug(`[${scope.query.id}]`, this.inspect());
scope.response = this.response;
scope.context = new ApiEdgeQueryContext_1.ApiEdgeQueryContext();
resolve(scope);
});
};
this.inspect = () => `SET RESPONSE`;
this.response = response;
}
}
exports.SetResponseQueryStep = SetResponseQueryStep;
class SetBodyQueryStep {
constructor(body, stream = null) {
this.execute = (scope) => {
return new Promise(resolve => {
debug(`[${scope.query.id}]`, this.inspect());
scope.body = this.body;
scope.stream = this.stream;
resolve(scope);
});
};
this.inspect = () => `SET BODY`;
this.body = body;
this.stream = stream;
}
}
exports.SetBodyQueryStep = SetBodyQueryStep;
class ProvideIdQueryStep {
constructor(fieldName = Api_1.Api.defaultIdField) {
this.execute = (scope) => {
return new Promise((resolve, reject) => {
debug(`[${scope.query.id}]`, this.inspect());
if (!scope.response)
return reject(new ApiEdgeError_1.ApiEdgeError(404, "Missing Entry"));
scope.context.id = scope.response.data[this.fieldName];
resolve(scope);
});
};
this.inspect = () => `PROVIDE ID: ${this.fieldName}`;
this.fieldName = fieldName;
}
}
exports.ProvideIdQueryStep = ProvideIdQueryStep;
class ExtendContextQueryStep {
constructor(context) {
this.execute = (scope) => {
return new Promise(resolve => {
debug(`[${scope.query.id}]`, this.inspect());
scope.context.id = this.context.id || scope.context.id;
if (this.context.pagination) {
scope.context.pagination = this.context.pagination;
}
this.context.fields.forEach(f => scope.context.fields.push(f));
this.context.populatedRelations.forEach(f => scope.context.populatedRelations.push(f));
this.context.filters.forEach(f => scope.context.filters.push(f));
this.context.sortBy.forEach(f => scope.context.sortBy.push(f));
resolve(scope);
});
};
this.inspect = () => {
if (this.context.id) {
return `EXTEND CONTEXT (id=${this.context.id})`;
}
else {
return `APPLY PARAMETERS`;
}
};
this.context = context;
}
}
exports.ExtendContextQueryStep = ExtendContextQueryStep;
class ExtendContextLiveQueryStep {
constructor(func) {
this.execute = (scope) => {
return new Promise(resolve => {
debug(`[${scope.query.id}]`, this.inspect());
this.apply(scope.context);
resolve(scope);
});
};
this.inspect = () => {
return `EXTEND CONTEXT LIVE`;
};
this.apply = func;
}
}
exports.ExtendContextLiveQueryStep = ExtendContextLiveQueryStep;
class ApiQueryBuilder {
constructor(api) {
this.buildReadQuery = (request) => {
let query = new ApiQuery_1.ApiQuery();
let segments = request.path.segments, lastSegment = segments[segments.length - 1];
this.buildEmbedSteps(query, request, lastSegment);
let readMode = true;
let baseQuery;
if (lastSegment instanceof ApiRequest_1.EdgePathSegment) {
baseQuery = new ApiEdgeQuery_1.ApiEdgeQuery(lastSegment.edge, ApiEdgeQueryType_1.ApiEdgeQueryType.List);
this.addQueryStep(query, new QueryEdgeQueryStep(baseQuery), null, true);
}
else if (lastSegment instanceof ApiRequest_1.RelatedFieldPathSegment) {
baseQuery = new ApiEdgeQuery_1.ApiEdgeQuery(lastSegment.relation.to, ApiEdgeQueryType_1.ApiEdgeQueryType.Get);
this.addQueryStep(query, new QueryEdgeQueryStep(baseQuery), lastSegment.relation, true);
}
else if (lastSegment instanceof ApiRequest_1.MethodPathSegment) {
this.addMethodCallStep(request, query, lastSegment.method, lastSegment.edge, true);
if (lastSegment.method.scope === ApiEdgeMethod_1.ApiEdgeMethodScope.Entry) {
query.unshift(new ProvideIdQueryStep(lastSegment.edge.idField));
}
readMode = lastSegment.method.requiresData;
}
else {
baseQuery = new ApiEdgeQuery_1.ApiEdgeQuery(lastSegment.edge, ApiEdgeQueryType_1.ApiEdgeQueryType.Get);
this.addQueryStep(query, new QueryEdgeQueryStep(baseQuery), null, true);
}
query.unshift(new ExtendContextQueryStep(request.context));
if (lastSegment instanceof ApiRequest_1.EntryPathSegment) {
const _segment = lastSegment;
query.unshift(new ExtendContextLiveQueryStep(context => context.id = _segment.id));
}
else if (lastSegment instanceof ApiRequest_1.RelatedFieldPathSegment) {
if (lastSegment.relation.relatedId !== lastSegment.relation.to.idField) {
query.unshift(new RelateBackwardsQueryStep(lastSegment.relation));
}
else {
query.unshift(new ProvideIdQueryStep(lastSegment.relation.relationId));
}
}
else {
}
for (let i = segments.length - 2; i >= 0; i--) {
let currentSegment = segments[i];
let relation = segments[i + 1].relation;
let edge = segments[i + 1].edge;
if (relation && !(relation instanceof OneToOneRelation_1.OneToOneRelation)) {
if (edge === relation.to) {
query.unshift(new RelateBackwardsQueryStep(relation));
}
else {
query.unshift(new RelateQueryStep(relation));
}
}
if (readMode) {
readMode = this.buildReadStep(query, currentSegment);
}
else {
readMode = this.buildCheckStep(query, currentSegment);
}
}
this.api.actions
.filter((action) => action.triggerKind == ApiAction_1.ApiActionTriggerKind.OnInput)
.forEach((action) => query.unshift(action));
return query;
};
this.buildChangeQuery = (request) => {
let query = new ApiQuery_1.ApiQuery();
let segments = request.path.segments, lastSegment = segments[segments.length - 1], readMode = true;
this.buildEmbedSteps(query, request, lastSegment);
let baseQuery;
if (lastSegment instanceof ApiRequest_1.RelatedFieldPathSegment) {
if (request.type === ApiRequest_1.ApiRequestType.Update) {
baseQuery = new ApiEdgeQuery_1.ApiEdgeQuery(lastSegment.edge, ApiEdgeQueryType_1.ApiEdgeQueryType.Patch);
request.body = { [lastSegment.relation.relationId]: request.body.id || request.body._id };
this.addQueryStep(query, new QueryEdgeQueryStep(baseQuery), null, true);
}
else if (request.type === ApiRequest_1.ApiRequestType.Patch) {
baseQuery = new ApiEdgeQuery_1.ApiEdgeQuery(lastSegment.relation.to, ApiEdgeQueryType_1.ApiEdgeQueryType.Patch);
this.addQueryStep(query, new QueryEdgeQueryStep(baseQuery), null, true);
}
else {
throw new ApiEdgeError_1.ApiEdgeError(400, "Invalid Delete Query");
}
}
else if (lastSegment instanceof ApiRequest_1.MethodPathSegment) {
this.addMethodCallStep(request, query, lastSegment.method, lastSegment.edge, true);
if (lastSegment.method.scope === ApiEdgeMethod_1.ApiEdgeMethodScope.Entry) {
query.unshift(new ProvideIdQueryStep(lastSegment.edge.idField));
}
readMode = lastSegment.method.requiresData;
}
else {
if (request.type === ApiRequest_1.ApiRequestType.Update) {
baseQuery = new ApiEdgeQuery_1.ApiEdgeQuery(lastSegment.edge, ApiEdgeQueryType_1.ApiEdgeQueryType.Update);
this.addQueryStep(query, new QueryEdgeQueryStep(baseQuery), null, true);
}
else if (request.type === ApiRequest_1.ApiRequestType.Patch) {
baseQuery = new ApiEdgeQuery_1.ApiEdgeQuery(lastSegment.edge, ApiEdgeQueryType_1.ApiEdgeQueryType.Patch);
this.addQueryStep(query, new QueryEdgeQueryStep(baseQuery), null, true);
}
else {
baseQuery = new ApiEdgeQuery_1.ApiEdgeQuery(lastSegment.edge, ApiEdgeQueryType_1.ApiEdgeQueryType.Delete);
this.addQueryStep(query, new QueryEdgeQueryStep(baseQuery), null, true);
}
}
query.unshift(new ExtendContextQueryStep(request.context));
if (lastSegment instanceof ApiRequest_1.EntryPathSegment) {
const _segment = lastSegment;
query.unshift(new ExtendContextLiveQueryStep(context => context.id = _segment.id));
}
else if (lastSegment instanceof ApiRequest_1.RelatedFieldPathSegment) {
if (request.type === ApiRequest_1.ApiRequestType.Update) {
let previousSegment = segments[segments.length - 2];
query.unshift(new ProvideIdQueryStep(previousSegment.edge.idField || Api_1.Api.defaultIdField));
readMode = false;
}
else {
query.unshift(new ProvideIdQueryStep(lastSegment.relation.relationId));
}
}
else {
}
for (let i = segments.length - 2; i >= 0; i--) {
let currentSegment = segments[i];
let relation = segments[i + 1].relation;
let edge = segments[i + 1].edge;
if (relation && !(relation instanceof OneToOneRelation_1.OneToOneRelation)) {
if (edge === relation.to) {
query.unshift(new RelateBackwardsQueryStep(relation));
}
else {
query.unshift(new RelateQueryStep(relation));
}
if (request.type !== ApiRequest_1.ApiRequestType.Delete) {
if (edge === relation.to) {
query.unshift(new RelateBackwardsChangeQueryStep(relation));
}
else {
query.unshift(new RelateChangeQueryStep(relation));
}
}
}
if (readMode) {
readMode = this.buildReadStep(query, currentSegment);
}
else {
readMode = this.buildCheckStep(query, currentSegment);
}
}
if (request.body || request.stream)
query.unshift(new SetBodyQueryStep(request.body, request.stream));
this.api.actions
.filter((action) => action.triggerKind == ApiAction_1.ApiActionTriggerKind.OnInput)
.forEach((action) => query.unshift(action));
return query;
};
this.buildCreateQuery = (request) => {
let query = new ApiQuery_1.ApiQuery();
let segments = request.path.segments, lastSegment = segments[segments.length - 1], readMode = true;
this.buildEmbedSteps(query, request, lastSegment);
if (lastSegment instanceof ApiRequest_1.MethodPathSegment) {
this.addMethodCallStep(request, query, lastSegment.method, lastSegment.edge, true);
if (lastSegment.method.scope === ApiEdgeMethod_1.ApiEdgeMethodScope.Entry) {
query.unshift(new ProvideIdQueryStep(lastSegment.edge.idField));
}
readMode = lastSegment.method.requiresData;
}
else {
this.addQueryStep(query, new QueryEdgeQueryStep(new ApiEdgeQuery_1.ApiEdgeQuery(lastSegment.edge, ApiEdgeQueryType_1.ApiEdgeQueryType.Create)));
}
for (let i = segments.length - 2; i >= 0; i--) {
let currentSegment = segments[i];
let relation = segments[i + 1].relation;
let edge = segments[i + 1].edge;
if (relation && !(relation instanceof OneToOneRelation_1.OneToOneRelation)) {
if (edge === relation.to) {
query.unshift(new RelateBackwardsChangeQueryStep(relation));
}
else {
query.unshift(new RelateChangeQueryStep(relation));
}
}
if (readMode) {
readMode = this.buildReadStep(query, currentSegment);
}
else {
readMode = this.buildCheckStep(query, currentSegment);
}
}
query.unshift(new SetBodyQueryStep(request.body, request.stream));
this.api.actions
.filter((action) => action.triggerKind == ApiAction_1.ApiActionTriggerKind.OnInput)
.forEach((action) => query.unshift(action));
return query;
};
this.build = (request) => {
switch (request.type) {
case ApiRequest_1.ApiRequestType.Read:
return this.buildReadQuery(request);
case ApiRequest_1.ApiRequestType.Update:
case ApiRequest_1.ApiRequestType.Patch:
case ApiRequest_1.ApiRequestType.Delete:
return this.buildChangeQuery(request);
case ApiRequest_1.ApiRequestType.Create:
return this.buildCreateQuery(request);
default:
throw new ApiEdgeError_1.ApiEdgeError(400, "Unsupported Query Type");
}
};
this.api = api;
}
addQueryActions(triggerKind, query, edgeQuery, relation, output = false) {
const edge = edgeQuery.edge, queryType = edgeQuery.type, trigger = relation ?
ApiEdgeAction_1.ApiEdgeActionTrigger.Relation :
(output ? ApiEdgeAction_1.ApiEdgeActionTrigger.OutputQuery : ApiEdgeAction_1.ApiEdgeActionTrigger.SubQuery);
let actions;
if (relation) {
actions = edge.actions.filter((action) => action.triggerKind == triggerKind &&
(action.targetTypes & queryType) &&
(action.triggers & trigger) &&
(!action.triggerNames.length || action.triggerNames.indexOf(relation.name) == -1));
}
else {
actions = edge.actions.filter((action) => action.triggerKind == triggerKind &&
(action.targetTypes & queryType) &&
(action.triggers & trigger));
}
actions.forEach((action) => query.unshift(action));
if (output) {
const apiTrigger = triggerKind == ApiEdgeAction_1.ApiEdgeActionTriggerKind.BeforeEvent ?
ApiAction_1.ApiActionTriggerKind.BeforeOutput : ApiAction_1.ApiActionTriggerKind.AfterOutput;
this.api.actions
.filter((action) => action.triggerKind == apiTrigger)
.forEach((action) => query.unshift(action));
}
}
addMethodActions(triggerKind, query, method, queryType, edge, output = false) {
const trigger = ApiEdgeAction_1.ApiEdgeActionTrigger.Method;
let actions = edge.actions.filter((action) => action.triggerKind == triggerKind &&
(action.targetTypes & queryType) &&
(action.triggers & trigger) &&
(!action.triggerNames.length || action.triggerNames.indexOf(method.name) == -1));
actions.forEach((action) => query.unshift(action));
if (output) {
const apiTrigger = triggerKind == ApiEdgeAction_1.ApiEdgeActionTriggerKind.BeforeEvent ?
ApiAction_1.ApiActionTriggerKind.BeforeOutput : ApiAction_1.ApiActionTriggerKind.AfterOutput;
this.api.actions
.filter((action) => action.triggerKind == apiTrigger)
.forEach((action) => query.unshift(action));
}
}
addMethodCallStep(request, query, method, edge, output) {
if (method.acceptedTypes & request.type) {
let queryType = ApiEdgeQueryType_1.ApiEdgeQueryType.Any;
if (request.type === ApiRequest_1.ApiRequestType.Create) {
queryType = ApiEdgeQueryType_1.ApiEdgeQueryType.Create;
}
else if (request.type === ApiRequest_1.ApiRequestType.Read) {
queryType = ApiEdgeQueryType_1.ApiEdgeQueryType.Read;
}
else if (request.type === ApiRequest_1.ApiRequestType.Update) {
queryType = ApiEdgeQueryType_1.ApiEdgeQueryType.Update;
}
else if (request.type === ApiRequest_1.ApiRequestType.Patch) {
queryType = ApiEdgeQueryType_1.ApiEdgeQueryType.Patch;
}
else if (request.type === ApiRequest_1.ApiRequestType.Delete) {
queryType = ApiEdgeQueryType_1.ApiEdgeQueryType.Delete;
}
else if (request.type === ApiRequest_1.ApiRequestType.Exists) {
queryType = ApiEdgeQueryType_1.ApiEdgeQueryType.Exists;
}
else if (request.type === ApiRequest_1.ApiRequestType.Change) {
queryType = ApiEdgeQueryType_1.ApiEdgeQueryType.Change;
}
this.addMethodActions(ApiEdgeAction_1.ApiEdgeActionTriggerKind.AfterEvent, query, method, queryType, edge, output);
query.unshift(new CallMethodQueryStep(method, edge));
this.addMethodActions(ApiEdgeAction_1.ApiEdgeActionTriggerKind.BeforeEvent, query, method, queryType, edge, output);
}
else {
throw new ApiEdgeError_1.ApiEdgeError(405, "Method Not Allowed");
}
}
addQueryStep(query, step, relation = null, output = false) {
this.addQueryActions(ApiEdgeAction_1.ApiEdgeActionTriggerKind.AfterEvent, query, step.query, relation, output);
query.unshift(step);
this.addQueryActions(ApiEdgeAction_1.ApiEdgeActionTriggerKind.BeforeEvent, query, step.query, relation, output);
}
static buildProvideIdStep(query, currentSegment) {
if (currentSegment instanceof ApiRequest_1.EntryPathSegment) {
query.unshift(new ExtendContextLiveQueryStep(context => context.id = currentSegment.id));
return false;
}
else if (currentSegment instanceof ApiRequest_1.RelatedFieldPathSegment) {
query.unshift(new ProvideIdQueryStep(currentSegment.relation.relationId));
return true;
}
else {
return false;
}
}
buildCheckStep(query, currentSegment) {
if (currentSegment instanceof ApiRequest_1.EntryPathSegment) {
query.unshift(new SetResponseQueryStep(new ApiEdgeQueryResponse_1.ApiEdgeQueryResponse({ [currentSegment.edge.idField || Api_1.Api.defaultIdField]: currentSegment.id })));
return false;
}
else if (currentSegment instanceof ApiRequest_1.RelatedFieldPathSegment) {
this.addQueryStep(query, new QueryEdgeQueryStep(new ApiEdgeQuery_1.ApiEdgeQuery(currentSegment.relation.to, ApiEdgeQueryType_1.ApiEdgeQueryType.Get)), currentSegment.relation);
}
else {
throw new ApiEdgeError_1.ApiEdgeError(500, "Not Implemented");
}
return ApiQueryBuilder.buildProvideIdStep(query, currentSegment);
}
buildReadStep(query, currentSegment) {
if (currentSegment instanceof ApiRequest_1.RelatedFieldPathSegment) {
this.addQueryStep(query, new QueryEdgeQueryStep(new ApiEdgeQuery_1.ApiEdgeQuery(currentSegment.relation.to, ApiEdgeQueryType_1.ApiEdgeQueryType.Get)), currentSegment.relation);
}
else {
this.addQueryStep(query, new QueryEdgeQueryStep(new ApiEdgeQuery_1.ApiEdgeQuery(currentSegment.edge, ApiEdgeQueryType_1.ApiEdgeQueryType.Get)));
}
return ApiQueryBuilder.buildProvideIdStep(query, currentSegment);
}
buildEmbedSteps(query, request, lastSegment) {
if (request.type === ApiRequest_1.ApiRequestType.Read
&& (lastSegment instanceof ApiRequest_1.EdgePathSegment
|| (lastSegment instanceof ApiRequest_1.MethodPathSegment && lastSegment.method.output === ApiEdgeMethod_1.ApiEdgeMethodOutput.List))) {
for (let relation of request.context.populatedRelations) {
const segment = new ApiRequest_1.EdgePathSegment(relation.to, relation);
const embedRequest = new ApiRequest_1.ApiRequest(request.api);
embedRequest.path.add(segment);
query.unshift(new EmbedQueryQueryStep(this.build(embedRequest), segment, embedRequest));
}
}
else {
for (let relation of request.context.populatedRelations) {
let segment;
if (relation instanceof OneToManyRelation_1.OneToManyRelation) {
segment = new ApiRequest_1.EdgePathSegment(relation.to, relation);
}
else {
segment = new ApiRequest_1.EntryPathSegment(relation.to, 'TBD', relation);
}
const embedRequest = new ApiRequest_1.ApiRequest(request.api);
embedRequest.path.add(segment);
query.unshift(new EmbedQueryQueryStep(this.build(embedRequest), segment, embedRequest));
}
}
}
}
exports.ApiQueryBuilder = ApiQueryBuilder;
//# sourceMappingURL=ApiQueryBuilder.js.map