UNPKG

api-core

Version:

Model-based dynamic multi-level APIs for any provider, plus multiple consumption channels

164 lines (138 loc) 5.12 kB
import {ApiEdgeDefinition} from "./edge/ApiEdgeDefinition"; import {ApiEdgeMetadata} from "./edge/ApiEdgeMetadata"; import {ApiRequestParser} from "./request/ApiRequestParser"; import {ApiQueryBuilder} from "./query/ApiQueryBuilder"; import {ApiRequest, ApiRequestType} from "./request/ApiRequest"; import {ApiQuery, ApiQueryScope} from "./query/ApiQuery"; import {ApiEdgeRelation, ExportedApiEdgeRelation} from "./relations/ApiEdgeRelation"; import {ApiAction, ApiActionTriggerKind} from "./query/ApiAction"; import {ExternalApiEdge} from "./edge/ExternalApiEdge"; import {ApiResolver} from "./resolver/ApiResolver"; import {LocalApiResolver} from "./resolver/LocalApiResolver"; const pkg = require('../../package.json'); export interface ApiInfo { title: string description?: string termsOfService?: string contact?: { name?: string url?: string email?: string } license?: { name: string, url?: string } } export interface ApiMetadata { info: ApiInfo version: string edges: ApiEdgeMetadata[] relations: ExportedApiEdgeRelation[] services: ApiService[] } export interface ApiService { name: string version: string } export class Api { static defaultIdPostfix: string = "Id"; static defaultIdField: string = "id"; url?: string; info?: ApiInfo; service: ApiService; edges: ApiEdgeDefinition[] = []; relations: ApiEdgeRelation[] = []; actions: ApiAction[] = []; private parser: ApiRequestParser; private queryBuilder: ApiQueryBuilder; resolver: ApiResolver; constructor(service: ApiService, ...edges: ApiEdgeDefinition[]) { this.service = service; this.edges = edges; this.parser = new ApiRequestParser(this); this.queryBuilder = new ApiQueryBuilder(this); this.resolver = new LocalApiResolver(this) } findEdge = (name: string, plural = true) => { return this.resolver.resolveEdge(name, plural) }; findRelation(name: string) { return this.resolver.resolveRelation(name) } findRelationOfEdge(edge: string|ApiEdgeDefinition, name: string) { const edgeName = (edge as any).name || edge; return this.resolver.resolveRelationOfEdge(edgeName, name) } findRelationTo(edge: string|ApiEdgeDefinition, name: string) { const edgeName = (edge as any).name || edge; return this.resolver.resolveRelationTo(edgeName, name) } findRelationFrom(edge: string|ApiEdgeDefinition, name: string) { const edgeName = (edge as any).name || edge; return this.resolver.resolveRelationFrom(edgeName, name) } parseRequest = async (requestParts: string[], type: ApiRequestType|null = null) => { const result = await this.parser.parse(requestParts); if(type) result.type = type; return result }; buildQuery = (request: ApiRequest): ApiQuery => { const query = this.queryBuilder.build(request); query.request = request; return query }; edge(edge: ApiEdgeDefinition) { this.edges.push(edge); edge.api = this; return this }; relation(relation: ApiEdgeRelation) { relation.from.relations.push(relation); relation.to.relations.push(relation); this.relations.push(relation); return this } use = (action: ApiAction) => { this.actions.unshift(action); return this }; action = (name: string, execute: (scope: ApiQueryScope) => Promise<ApiQueryScope>, triggerKind: ApiActionTriggerKind = ApiActionTriggerKind.OnInput): Api => { this.actions.unshift(new ApiAction(name, execute, triggerKind)); return this }; metadata = (): ApiMetadata => { return { info: this.info || { title: 'API' }, version: pkg.version, services: [ this.service ], edges: this.edges .filter(edge => !edge.external) .map(edge => edge.metadata()), relations: this.relations .map(relation => relation.toJSON()) } }; static async fromMetadata(metadata: ApiMetadata): Promise<Api> { const api = new Api(metadata.services[0] || {}); api.info = metadata.info; for(let edge of metadata.edges) { //if(edge.external) continue; -- TODO api.edge(new ExternalApiEdge(edge, api)) } for(let relation of metadata.relations) { api.relation(await ApiEdgeRelation.fromJSON(relation, api)) } return api } async prepare() { for(let edge of this.edges) { await edge.prepare(this) } } private extension: { [key: string]: any } = {}; get = (key: string) => this.extension[key]; set = (key: string, value: any) => this.extension[key] = value; }