UNPKG

@notadd/graphql

Version:

notadd core none dependence

415 lines (414 loc) 16.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.isPromise = exports.isInlineFragmentNode = exports.isFragmentSpreadNode = exports.isFieldNode = exports.isArgumentNode = exports.isNullValueNode = exports.isBooleanValueNode = exports.isStringValueNode = exports.isFloatValueNode = exports.isIntValueNode = exports.isVariableNode = exports.isObjectValueNode = exports.isListValueNode = exports.isEnumValueNode = exports.Graphql = void 0; const tslib_1 = require("tslib"); const core_1 = require("@notadd/core"); const token_1 = require("./token"); const graphql_1 = require("graphql"); const rxjs_1 = require("rxjs"); const operators_1 = require("rxjs/operators"); const graphql_2 = require("graphql"); const schemaBuilder_1 = require("./schemaBuilder"); let Graphql = class Graphql { constructor(injector) { this.injector = injector; } async query(source, variables, operationName = undefined, ...middlewars) { const builder = this.injector.get(schemaBuilder_1.DefaultSchemaBuilder); const schema = await builder.buildSchema(); if (schema) { return graphql_1.graphql({ schema, source, rootValue: undefined, contextValue: middlewars, variableValues: variables, operationName }); } } async run(query, variables, operationName, ...middlewars) { this.ast = graphql_2.parse(query); const schema = await this.injector.get(token_1.GRAPHQL_SCHEMA); const operationDefinition = graphql_1.getOperationAST(this.ast, operationName); if (operationDefinition) { const rootType = graphql_1.getOperationRootType(schema, operationDefinition); const selectionSet = operationDefinition.selectionSet; const method = rootType.name; const source = await this.handlerSelectionSet(middlewars, rootType, selectionSet, variables, method); return source; } } getFragmentDefinition(name) { return this.ast.definitions.find((it) => it.name.value === name); } handlerSelectionSet(middlewars, root, set, variables, method) { middlewars.push(new core_1.Middleware('graphql', async (root) => { const injector = await root; return injector.create([{ provide: token_1.GRAPHQL_OBJECT_TYPE, useValue: root }, { provide: token_1.GRAPHQL_SELECTION_SET, useValue: set }, { provide: core_1.ARGS, useValue: variables }, { provide: token_1.GRAPHQL_SELECTIONS, useFactory: () => { if (set) { return set.selections.map(it => { if (isFieldNode(it)) { return it.name.value; } return; }).filter(it => !!it); } return []; } }], 'graphql'); })); if (set.selections && set.selections.length === 1) { const selection = set.selections[0]; return this.handlerField(middlewars, selection, set, variables, method); } throw new graphql_1.GraphQLError(`subscription support only one top selection`); } async handlerField(middlewars, field, set, variables, method) { if (isFieldNode(field)) { let { alias, name, arguments: args, directives, selectionSet } = field; alias = alias || name; const router = this.injector.get(core_1.Router); const [handler] = router.find(`/${name.value}`, method.toUpperCase()); if (handler) { const graphqlMiddlware = new core_1.Middleware('selection', async (_root) => { const injector = await _root; return injector.create([{ provide: token_1.GRAPHQL_SELECTION_SET, useValue: selectionSet }, { provide: token_1.GRAPHQL_SELECTION, useValue: field }, { provide: token_1.GRAPHQL_SELECTIONS, useFactory: () => { if (selectionSet) { return selectionSet.selections.map(it => { if (isFieldNode(it)) { return it.name.value; } return; }).filter(it => !!it); } return []; } }], 'selection'); }); middlewars.push(graphqlMiddlware); let res = await handler(middlewars); if (res instanceof core_1.Injector) { res = res.get(core_1.METHOD_RESULT); } if (selectionSet) { return this.parseSelectionSetFirst(middlewars, res, alias, name, selectionSet, variables); } else { if (isPromise(res)) { return res.then(item => { return { [alias.value]: item }; }); } return { [alias.value]: res }; } } } else if (isFragmentSpreadNode(field)) { debugger; } else if (isInlineFragmentNode(field)) { debugger; } else { throw new Error(`not support field type`); } } parseSelectionSetFirst(middlewars, source, alias, name, selectionSet, variables) { if (selectionSet) { middlewars.push(new core_1.Middleware('selection', async (root) => { const injector = await root; return injector.create([{ provide: token_1.GRAPHQL_SELECTION_SET, useValue: selectionSet }, { provide: token_1.GRAPHQL_SELECTIONS, useFactory: () => { return selectionSet.selections.map(it => { if (isFieldNode(it)) { return it.name.value; } return; }).filter(it => !!it); } }], 'selection'); })); const selections = selectionSet.selections; if (selections) { if (rxjs_1.isObservable(source)) { return source.pipe(operators_1.map((item) => { return { [alias.value]: this.parseSelectionSet(item, selectionSet, variables) }; })); } else if (isPromise(source)) { return source.then(res => ({ [alias.value]: this.parseSelectionSet(res, selectionSet, variables) })); } else if (Array.isArray(source)) { return { [alias.value]: source.map(it => this.parseSelectionSet(it, selectionSet, variables)) }; } else if (source !== null && source !== undefined) { if (selections && selections.length > 0) { let res = {}; selections.map(it => { const val = this.parseField(source, it, variables); res = { ...res, ...val }; }); return { [alias.value]: res }; } return { [alias.value]: source }; } else { return { [alias.value]: null }; } } } return source; } parseValue(value, variables) { if (isVariableNode(value)) { return Reflect.get(variables, value.name.value); } else if (isIntValueNode(value)) { return parseInt(value.value, 10); } else if (isFloatValueNode(value)) { return parseFloat(value.value); } else if (isStringValueNode(value)) { return `${value.value}`; } else if (isBooleanValueNode(value)) { return value.value; } if (isNullValueNode(value)) { return null; } else if (isEnumValueNode(value)) { console.log(`enum value`); return value.value; } else if (isListValueNode(value)) { return value.values.map(it => this.parseValue(it, variables)); } else if (isObjectValueNode(value)) { const res = {}; value.fields.map(it => { Reflect.set(res, it.name.value, this.parseValue(it.value, variables)); }); return res; } else { throw new Error(`not support value type`); } } parseField(source, selection, variables) { if (isFieldNode(selection)) { let { alias, name, arguments: args, directives, selectionSet } = selection; let value = source[name.value]; alias = alias || name; const parameters = {}; const getNger = this.injector.get(core_1.GET_INGER_DECORATOR); const type = source.constructor; const nger = getNger(type); const method = nger.methods.find(it => it.property === name.value); const _args = (args || []).map(arg => { const { name, value } = arg; const val = this.parseValue(value, variables); Reflect.set(parameters, name.value, val); return val; }); const argsInjector = this.injector.create([{ provide: token_1.GRAPHQL_SOURCE, useValue: source }, { provide: core_1.ARGS, useValue: parameters }, { provide: token_1.GRAPHQL_SELECTION_SET, useValue: selectionSet }, { provide: token_1.GRAPHQL_SELECTIONS, useFactory: () => { if (selectionSet) { return selectionSet.selections.map(it => { if (isFieldNode(it)) { return it.name.value; } return; }).filter(it => !!it); } return []; } }], 'field'); if (method) { const args = new Array(method.paramTypes); nger.properties.map(pro => { if (pro.metadataKey) { const handler = argsInjector.get(pro.metadataKey, null); if (handler) { handler.property(pro, argsInjector); } } }); method.parameters.map(par => { if (par.metadataKey) { const handler = argsInjector.get(par.metadataKey, null); if (handler) { const value = handler.methodParams(args, par, argsInjector); Reflect.set(args, par.parameterIndex, value); } } }); value = value(...args); } else { if (typeof value === 'function') { value = value(..._args); } } if (selectionSet) { const res = { [alias.value]: this.parseSelectionSet(value, selectionSet, variables) }; return res; } else { return { [alias.value]: value }; } } else if (isFragmentSpreadNode(selection)) { const fragment = this.getFragmentDefinition(selection.name.value); if (fragment) { return this.parseSelectionSet(source, fragment.selectionSet, variables); } else { throw new Error(`not found fragment ${selection.name.value}`); } } else if (isInlineFragmentNode(selection)) { debugger; } else { throw new Error(`not support field type`); } } parseSelectionSet(source, selectionSet, variables) { if (selectionSet) { const selections = selectionSet.selections; if (selections) { if (rxjs_1.isObservable(source)) { return source.pipe(operators_1.map(item => { return this.parseSelectionSet(item, selectionSet, variables); })); } else if (isPromise(source)) { return source.then(res => this.parseSelectionSet(res, selectionSet, variables)); } else if (Array.isArray(source)) { return source.map(it => this.parseSelectionSet(it, selectionSet, variables)); } else if (source !== null && source !== undefined) { if (selections && selections.length > 0) { let res = {}; selections.map(it => { const val = this.parseField(source, it, variables); res = { ...res, ...val }; }); return res; } return source; } else { return null; } } } return source; } }; Graphql = tslib_1.__decorate([ core_1.Injectable(), tslib_1.__metadata("design:paramtypes", [core_1.Injector]) ], Graphql); exports.Graphql = Graphql; function isEnumValueNode(val) { return Reflect.get(val, 'kind') === 'EnumValue'; } exports.isEnumValueNode = isEnumValueNode; function isListValueNode(val) { return Reflect.get(val, 'kind') === 'ListValue'; } exports.isListValueNode = isListValueNode; function isObjectValueNode(val) { return Reflect.get(val, 'kind') === 'ObjectValue'; } exports.isObjectValueNode = isObjectValueNode; function isVariableNode(val) { return Reflect.get(val, 'kind') === 'Variable'; } exports.isVariableNode = isVariableNode; function isIntValueNode(val) { return Reflect.get(val, 'kind') === 'IntValue'; } exports.isIntValueNode = isIntValueNode; function isFloatValueNode(val) { return Reflect.get(val, 'kind') === 'FloatValue'; } exports.isFloatValueNode = isFloatValueNode; function isStringValueNode(val) { return Reflect.get(val, 'kind') === 'StringValue'; } exports.isStringValueNode = isStringValueNode; function isBooleanValueNode(val) { return Reflect.get(val, 'kind') === 'BooleanValue'; } exports.isBooleanValueNode = isBooleanValueNode; function isNullValueNode(val) { return Reflect.get(val, 'kind') === 'NullValue'; } exports.isNullValueNode = isNullValueNode; function isArgumentNode(val) { return Reflect.get(val, 'kind') === 'Argument'; } exports.isArgumentNode = isArgumentNode; function isFieldNode(val) { return Reflect.get(val, 'kind') === 'Field'; } exports.isFieldNode = isFieldNode; function isFragmentSpreadNode(val) { return Reflect.get(val, 'kind') === 'FragmentSpread'; } exports.isFragmentSpreadNode = isFragmentSpreadNode; function isInlineFragmentNode(val) { return Reflect.get(val, 'kind') === 'InlineFragment'; } exports.isInlineFragmentNode = isInlineFragmentNode; function isPromise(val) { return val && typeof val === 'object' && Reflect.has(val, 'then') && Reflect.has(val, 'catch'); } exports.isPromise = isPromise;