UNPKG

shyft

Version:

Model driven GraphQL API framework

336 lines (335 loc) 17.3 kB
"use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.generateGraphQLSchema = exports.registerActions = exports.extendModelsForGql = exports.getTypeForEntityFromGraphRegistry = void 0; var graphql_1 = require("graphql"); var graphql_relay_1 = require("graphql-relay"); var json_shaper_1 = require("json-shaper"); var Action_1 = require("../engine/action/Action"); var Configuration_1 = require("../engine/configuration/Configuration"); var dataTypes_1 = require("../engine/datatype/dataTypes"); var Entity_1 = require("../engine/entity/Entity"); var ShadowEntity_1 = require("../engine/entity/ShadowEntity"); var ViewEntity_1 = require("../engine/entity/ViewEntity"); var action_1 = require("./action"); var connection_1 = require("./connection"); var graphRegistry_1 = require("./graphRegistry"); var mutation_1 = require("./mutation"); var operation_1 = require("./operation"); var ProtocolGraphQL_1 = require("./ProtocolGraphQL"); var protocolGraphqlConstants_1 = require("./protocolGraphqlConstants"); var query_1 = require("./query"); var registry_1 = require("./registry"); var resolver_1 = require("./resolver"); var subscription_1 = require("./subscription"); var getTypeForEntityFromGraphRegistry = function (entity) { var typeName = registry_1.getRegisteredEntity(entity.name).typeName; return graphRegistry_1.graphRegistry.types[typeName]; }; exports.getTypeForEntityFromGraphRegistry = getTypeForEntityFromGraphRegistry; // prepare models for graphql var extendModelsForGql = function (entities) { var protocolConfiguration = ProtocolGraphQL_1.ProtocolGraphQL.getProtocolConfiguration(); var _loop_1 = function (entity) { var dataShaperMap = {}; var reverseDataShaperMap = {}; var attributes = {}; for (var _b = 0, _c = Object.values(entity.getAttributes()); _b < _c.length; _b++) { var attribute = _c[_b]; var fieldName = attribute.primary ? 'id' : protocolConfiguration.generateFieldName(attribute); // TODO: name does not exist on AttributeBase // eslint-disable-next-line dot-notation dataShaperMap[fieldName] = attribute['name']; // TODO: name does not exist on AttributeBase // eslint-disable-next-line dot-notation reverseDataShaperMap[attribute['name']] = fieldName; var fieldNameI18n = void 0; var fieldNameI18nJson = void 0; if (attribute.i18n) { fieldNameI18n = protocolConfiguration.generateI18nFieldName(attribute); // TODO: name does not exist on AttributeBase // eslint-disable-next-line dot-notation dataShaperMap[fieldNameI18n] = attribute['name'] + ".i18n"; // TODO: name does not exist on AttributeBase // eslint-disable-next-line dot-notation reverseDataShaperMap[attribute['name'] + ".i18n"] = fieldNameI18n; fieldNameI18nJson = protocolConfiguration.generateI18nJsonFieldName(attribute); // TODO: name does not exist on AttributeBase // eslint-disable-next-line dot-notation dataShaperMap[fieldNameI18nJson] = attribute['name'] + ".i18n"; // no i18n JSON output mapping for reverse shaper map // so it doesn't overwrite values in mutation inputs } // TODO: name does not exist on AttributeBase // eslint-disable-next-line dot-notation attributes[attribute['name']] = { fieldName: fieldName, fieldNameI18n: fieldNameI18n, fieldNameI18nJson: fieldNameI18nJson, }; } // forward relay type promoter field as well dataShaperMap[protocolGraphqlConstants_1.RELAY_TYPE_PROMOTER_FIELD] = protocolGraphqlConstants_1.RELAY_TYPE_PROMOTER_FIELD; reverseDataShaperMap[protocolGraphqlConstants_1.RELAY_TYPE_PROMOTER_FIELD] = protocolGraphqlConstants_1.RELAY_TYPE_PROMOTER_FIELD; // generate json shaper - translate schema attribute names to graphql attribute names var dataShaper = json_shaper_1.shaper(dataShaperMap); var reverseDataShaper = json_shaper_1.shaper(reverseDataShaperMap); registry_1.registerEntity({ entity: entity, typeName: protocolConfiguration.generateEntityTypeName(entity), typeNamePlural: protocolConfiguration.generateEntityTypeNamePlural(entity), typeNamePascalCase: protocolConfiguration.generateEntityTypeNamePascalCase(entity), typeNamePluralPascalCase: protocolConfiguration.generateEntityTypeNamePluralPascalCase(entity), attributes: attributes, dataShaper: function (data) { return data ? dataShaper(data) : data; }, dataSetShaper: function (set) { return set.map(dataShaper); }, reverseDataShaper: function (data) { return data ? reverseDataShaper(data) : data; }, }); }; for (var _i = 0, _a = Object.values(entities); _i < _a.length; _i++) { var entity = _a[_i]; _loop_1(entity); } }; exports.extendModelsForGql = extendModelsForGql; // get node definitions for relay var getNodeDefinitions = function () { var idFetcher = function (globalId, context) { var _a = graphql_relay_1.fromGlobalId(globalId), type = _a.type, id = _a.id; // resolve based on type and id var entity = graphRegistry_1.graphRegistry.types[type] ? graphRegistry_1.graphRegistry.types[type].entity : null; if (entity) { var resolver = resolver_1.resolveByFindOne(entity, function () { return id; }); return resolver(null, null, context); } return null; }; var typeResolver = function (obj) { var typeName = obj[protocolGraphqlConstants_1.RELAY_TYPE_PROMOTER_FIELD]; return graphRegistry_1.graphRegistry.types[typeName] ? graphRegistry_1.graphRegistry.types[typeName].type : null; }; return __assign(__assign({}, graphql_relay_1.nodeDefinitions(idFetcher, typeResolver)), { idFetcher: idFetcher }); }; var registerAction = function (action) { var actionName = action.name; graphRegistry_1.graphRegistry.actions[actionName] = { action: action, }; }; var registerActions = function (actions) { for (var _i = 0, _a = Object.values(actions); _i < _a.length; _i++) { var action = _a[_i]; registerAction(action); } }; exports.registerActions = registerActions; var generateGraphQLSchema = function (configuration) { if (!Configuration_1.isConfiguration(configuration)) { throw new Error('Invalid configuration object provided to generateGraphQLSchema()'); } var schema = configuration.getSchema(); var protocolConfiguration = configuration.getProtocolConfiguration(); ProtocolGraphQL_1.ProtocolGraphQL.setProtocolConfiguration(protocolConfiguration); var _a = getNodeDefinitions(), nodeInterface = _a.nodeInterface, nodeField = _a.nodeField, idFetcher = _a.idFetcher; exports.registerActions(schema.getActions()); // prepare models for graphql exports.extendModelsForGql(schema.getEntities()); var _loop_2 = function (entity) { var typeName = registry_1.getRegisteredEntity(entity.name).typeName; var objectType = new graphql_1.GraphQLObjectType({ name: protocolConfiguration.generateEntityTypeNamePascalCase(entity), description: entity.description, interfaces: [nodeInterface], fields: function () { var fields = { id: { type: new graphql_1.GraphQLNonNull(graphql_1.GraphQLID), }, nodeId: { description: 'The node ID of an object', type: new graphql_1.GraphQLNonNull(graphql_1.GraphQLID), resolve: function (obj) { return graphql_relay_1.toGlobalId(typeName, obj.id); }, }, }; var fieldsReference = {}; var fieldsI18n = {}; var _loop_3 = function (attribute) { if (attribute.hidden || attribute.mutationInput) { return "continue"; } var _b = registry_1.getRegisteredEntityAttribute(entity.name, attribute['name']), gqlFieldName = _b.fieldName, gqlFieldNameI18nJson = _b.fieldNameI18nJson; // const field = { // description: attribute.description, // }; var attributeType = attribute.type; // it's a reference if (Entity_1.isEntity(attributeType) || ShadowEntity_1.isShadowEntity(attributeType)) { var targetEntity = attributeType; var primaryAttribute = targetEntity.getPrimaryAttribute(); attributeType = primaryAttribute.type; // const reference = { // description: attribute.description, // }; var targetTypeName = registry_1.getRegisteredEntity(targetEntity.name).typeName; // reference.type = graphRegistry.types[targetTypeName].type; // reference.resolve = resolveByFindOne( // targetEntity, // ({ source }) => source[gqlFieldName], // ); var reference = { description: attribute.description, type: graphRegistry_1.graphRegistry.types[targetTypeName].type, resolve: resolver_1.resolveByFindOne(targetEntity, function (_a) { var source = _a.source; return source[gqlFieldName]; }), }; var referenceFieldName = protocolConfiguration.generateReferenceFieldName(targetEntity, attribute); fieldsReference[referenceFieldName] = reference; } var fieldType = ProtocolGraphQL_1.ProtocolGraphQL.convertToProtocolDataType(attributeType, entity.name, false); // make it non-nullable if it's required // if (attribute.required) { // field.type = new GraphQLNonNull(fieldType); // } else { // field.type = fieldType; // } // use computed value's function as the field resolver // if (attribute.resolve) { // field.resolve = attribute.resolve; // } var field = { description: attribute.description, type: attribute.required ? new graphql_1.GraphQLNonNull(fieldType) : fieldType, resolve: attribute.resolve ? function (obj, args, context, info) { return attribute.resolve({ obj: obj, args: args, context: context, info: info }); } : undefined, }; fields[gqlFieldName] = field; if (attribute.i18n) { // JSON i18n output var i18nJsonFieldType = ProtocolGraphQL_1.ProtocolGraphQL.convertToProtocolDataType(dataTypes_1.DataTypeI18n, entity.name, false); var i18nJsonField = { type: attribute.required ? new graphql_1.GraphQLNonNull(i18nJsonFieldType) : i18nJsonFieldType, description: "Translations of **`" + gqlFieldName + "`** in JSON format", }; fieldsI18n[gqlFieldNameI18nJson] = i18nJsonField; // Object Type i18n output var i18nFieldType = new graphql_1.GraphQLObjectType({ name: protocolConfiguration.generateI18nFieldTypeName(entity, attribute), description: "Translations of **`" + gqlFieldName + "`**", fields: function () { var languages = configuration.getLanguages(); var i18nFields = {}; languages.map(function (language, langIdx) { var type = langIdx === 0 && attribute.required ? new graphql_1.GraphQLNonNull(fieldType) : fieldType; i18nFields[language] = { type: type, }; }); return i18nFields; }, }); var gqlFieldNameI18n = registry_1.getRegisteredEntityAttribute(entity.name, attribute['name']).fieldNameI18n; fieldsI18n[gqlFieldNameI18n] = { type: attribute.required ? new graphql_1.GraphQLNonNull(i18nFieldType) : i18nFieldType, }; } }; for (var _i = 0, _a = Object.values(entity.getAttributes()); _i < _a.length; _i++) { var attribute = _a[_i]; _loop_3(attribute); } Object.assign(fields, fieldsI18n, fieldsReference, Entity_1.isEntity(entity) ? connection_1.generateReverseConnections(configuration, graphRegistry_1.graphRegistry, entity) : {}); return fields; }, }); graphRegistry_1.graphRegistry.types[typeName] = { entity: entity, type: objectType, }; if (Entity_1.isEntity(entity) || ViewEntity_1.isViewEntity(entity)) { connection_1.registerConnection(graphRegistry_1.graphRegistry, entity); } }; for (var _i = 0, _b = Object.values(schema.getEntities()); _i < _b.length; _i++) { var entity = _b[_i]; _loop_2(entity); } operation_1.generateInstanceUniquenessInputs(graphRegistry_1.graphRegistry); // build the query type var queryType = new graphql_1.GraphQLObjectType({ name: 'Query', // root: 'The root query type', fields: function () { var listQueries = query_1.generateListQueries(graphRegistry_1.graphRegistry); var instanceQueries = query_1.generateInstanceQueries(graphRegistry_1.graphRegistry, idFetcher); var actions = action_1.generateActions(graphRegistry_1.graphRegistry, Action_1.ACTION_TYPE_QUERY); // override args.id of relay to args.nodeId nodeField.args.nodeId = nodeField.args.id; nodeField.resolve = function (_obj, _a, context, info) { var nodeId = _a.nodeId; return idFetcher(nodeId, context, info); }; delete nodeField.args.id; return __assign(__assign(__assign({ node: nodeField }, instanceQueries), listQueries), actions); }, }); var mutationType = new graphql_1.GraphQLObjectType({ name: 'Mutation', // root: 'The root mutation type', fields: function () { var mutations = mutation_1.generateMutations(graphRegistry_1.graphRegistry); var actions = action_1.generateActions(graphRegistry_1.graphRegistry, Action_1.ACTION_TYPE_MUTATION); return __assign(__assign({}, mutations), actions); }, }); var subscriptionType = new graphql_1.GraphQLObjectType({ name: 'Subscription', // root: 'The root subscription type', fields: function () { var subscriptions = subscription_1.generateSubscriptions(graphRegistry_1.graphRegistry); return subscriptions; }, }); // put it all together into a graphQL schema return new graphql_1.GraphQLSchema({ query: queryType, mutation: mutationType, subscription: subscriptionType, }); }; exports.generateGraphQLSchema = generateGraphQLSchema;