UNPKG

graphile-build-pg

Version:

Build a GraphQL schema by reflection over a PostgreSQL schema. Easy to customize since it's built with plugins on graphile-build

135 lines (133 loc) 5.54 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; const base64 = str => Buffer.from(String(str)).toString("base64"); var PgRecordFunctionConnectionPlugin = function PgRecordFunctionConnectionPlugin(builder, { pgForbidSetofFunctionsToReturnNull = false }) { builder.hook("init", (_, build) => { const { newWithHooks, getSafeAliasFromResolveInfo, pgIntrospectionResultsByKind: introspectionResultsByKind, getTypeByName, graphql: { GraphQLObjectType, GraphQLNonNull, GraphQLList }, inflection, pgOmit: omit, describePgEntity, sqlCommentByAddingTags, pgField } = build; const nullableIf = (condition, Type) => condition ? Type : new GraphQLNonNull(Type); const Cursor = getTypeByName("Cursor"); introspectionResultsByKind.procedure.forEach(proc => { // PERFORMANCE: These used to be .filter(...) calls if (!proc.returnsSet) return; if (!proc.namespace) return; if (omit(proc, "execute")) return; if (proc.returnTypeId !== "2249") { // Does not return a record type; defer handling to // PgTablesPlugin and PgScalarFunctionConnectionPlugin return; } // TODO: PG10 doesn't support the equivalent of pg_attribute.atttypemod // on function arguments and return types, however maybe a later // version of PG will? const NodeType = getTypeByName(inflection.recordFunctionReturnType(proc)); if (!NodeType) { throw new Error(`Do not have a node type '${inflection.recordFunctionReturnType(proc)}' for '${proc.name}' so cannot create connection type`); } const EdgeType = newWithHooks(GraphQLObjectType, { name: inflection.recordFunctionEdge(proc), description: build.wrapDescription(`A \`${NodeType.name}\` edge in the connection.`, "type"), fields: ({ fieldWithHooks }) => { return { cursor: fieldWithHooks("cursor", ({ addDataGenerator }) => { addDataGenerator(() => ({ usesCursor: [true] })); return { description: build.wrapDescription("A cursor for use in pagination.", "field"), type: Cursor, resolve(data) { return base64(JSON.stringify(data.__cursor)); } }; }, { isCursorField: true }), node: pgField(build, fieldWithHooks, "node", { description: build.wrapDescription(`The \`${NodeType.name}\` at the end of the edge.`, "field"), type: nullableIf(!pgForbidSetofFunctionsToReturnNull, NodeType), resolve(data, _args, _context, resolveInfo) { const safeAlias = getSafeAliasFromResolveInfo(resolveInfo); return data[safeAlias]; } }, {}, false) }; } }, { __origin: `Adding function result edge type for ${describePgEntity(proc)}. You can rename the function's GraphQL field (and its dependent types) via a 'Smart Comment':\n\n ${sqlCommentByAddingTags(proc, { name: "newNameHere" })}`, isEdgeType: true, nodeType: NodeType, pgIntrospection: proc }); /*const ConnectionType = */ newWithHooks(GraphQLObjectType, { name: inflection.recordFunctionConnection(proc), description: build.wrapDescription(`A connection to a list of \`${NodeType.name}\` values.`, "type"), fields: ({ fieldWithHooks }) => { return { nodes: pgField(build, fieldWithHooks, "nodes", { description: build.wrapDescription(`A list of \`${NodeType.name}\` objects.`, "field"), type: new GraphQLNonNull(new GraphQLList(nullableIf(!pgForbidSetofFunctionsToReturnNull, NodeType))), resolve(data, _args, _context, resolveInfo) { const safeAlias = getSafeAliasFromResolveInfo(resolveInfo); return data.data.map(entry => entry[safeAlias]); } }), edges: pgField(build, fieldWithHooks, "edges", { description: build.wrapDescription(`A list of edges which contains the \`${NodeType.name}\` and cursor to aid in pagination.`, "field"), type: new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(EdgeType))), resolve(data, _args, _context, resolveInfo) { const safeAlias = getSafeAliasFromResolveInfo(resolveInfo); return data.data.map(entry => ({ __cursor: entry.__cursor, ...entry[safeAlias] })); } }, {}, false, { hoistCursor: true }) }; } }, { __origin: `Adding function connection type for ${describePgEntity(proc)}. You can rename the function's GraphQL field (and its dependent types) via a 'Smart Comment':\n\n ${sqlCommentByAddingTags(proc, { name: "newNameHere" })}`, isConnectionType: true, isPgRowConnectionType: true, edgeType: EdgeType, nodeType: NodeType, pgIntrospection: proc }); }); return _; }, ["PgRecordFunctionConnection"]); }; exports.default = PgRecordFunctionConnectionPlugin; //# sourceMappingURL=PgRecordFunctionConnectionPlugin.js.map