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

164 lines (163 loc) 7.26 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _debugSql = _interopRequireDefault(require("./debugSql")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var PgAllRows = async function PgAllRows(builder, { pgViewUniqueKey, pgSimpleCollections, subscriptions }) { builder.hook("GraphQLObjectType:fields", (fields, build, context) => { const { parseResolveInfo, extend, getTypeByName, pgGetGqlTypeByTypeIdAndModifier, pgSql: sql, pgIntrospectionResultsByKind: introspectionResultsByKind, inflection, graphql: { GraphQLList, GraphQLNonNull }, pgQueryFromResolveData: queryFromResolveData, pgAddStartEndCursor: addStartEndCursor, pgOmit: omit, pgPrepareAndRun } = build; const { fieldWithHooks, scope: { isRootQuery } } = context; if (!isRootQuery) { return fields; } return extend(fields, introspectionResultsByKind.class.reduce((memo, table) => { // PERFORMANCE: These used to be .filter(...) calls if (!table.isSelectable) return memo; if (!table.namespace) return memo; if (omit(table, "all")) return memo; const TableType = pgGetGqlTypeByTypeIdAndModifier(table.type.id, null); if (!TableType) { return memo; } const tableTypeName = TableType.name; const ConnectionType = getTypeByName(inflection.connection(TableType.name)); if (!TableType) { throw new Error(`Could not find GraphQL type for table '${table.name}'`); } const attributes = table.attributes; const primaryKeyConstraint = table.primaryKeyConstraint; const primaryKeys = primaryKeyConstraint && primaryKeyConstraint.keyAttributes; const isView = t => t.classKind === "v"; const viewUniqueKey = table.tags.uniqueKey || pgViewUniqueKey; const uniqueIdAttribute = viewUniqueKey ? attributes.find(attr => attr.name === viewUniqueKey) : undefined; if (isView(table) && table.tags.uniqueKey && !uniqueIdAttribute) { throw new Error(`Could not find the named unique key '${table.tags.uniqueKey}' on view '${table.namespaceName}.${table.name}'`); } if (!ConnectionType) { throw new Error(`Could not find GraphQL connection type for table '${table.name}'`); } const schema = table.namespace; const sqlFullTableName = sql.identifier(schema.name, table.name); function makeField(isConnection) { const fieldName = isConnection ? inflection.allRows(table) : inflection.allRowsSimple(table); memo[fieldName] = fieldWithHooks(fieldName, ({ getDataFromParsedResolveInfoFragment }) => { return { description: build.wrapDescription(isConnection ? `Reads and enables pagination through a set of \`${tableTypeName}\`.` : `Reads a set of \`${tableTypeName}\`.`, "field"), type: isConnection ? ConnectionType : new GraphQLList(new GraphQLNonNull(TableType)), args: {}, async resolve(parent, args, resolveContext, resolveInfo) { const { pgClient } = resolveContext; const parsedResolveInfoFragment = parseResolveInfo(resolveInfo); parsedResolveInfoFragment.args = args; // Allow overriding via makeWrapResolversPlugin const resolveData = getDataFromParsedResolveInfoFragment(parsedResolveInfoFragment, resolveInfo.returnType); let checkerGenerator; const query = queryFromResolveData(sqlFullTableName, undefined, resolveData, { useAsterisk: table.canUseAsterisk, withPaginationAsFields: isConnection }, queryBuilder => { if (subscriptions) { queryBuilder.makeLiveCollection(table, _checkerGenerator => { checkerGenerator = _checkerGenerator; }); } if (primaryKeys) { if (subscriptions && !isConnection) { queryBuilder.selectIdentifiers(table); } queryBuilder.beforeLock("orderBy", () => { if (!queryBuilder.isOrderUnique(false)) { // Order by PK if no order specified queryBuilder.data.cursorPrefix = ["primary_key_asc"]; primaryKeys.forEach(key => { queryBuilder.orderBy(sql.fragment`${queryBuilder.getTableAlias()}.${sql.identifier(key.name)}`, true); }); queryBuilder.setOrderIsUnique(); } }); } else if (isView(table) && !!uniqueIdAttribute) { queryBuilder.beforeLock("orderBy", () => { if (!queryBuilder.isOrderUnique(false)) { queryBuilder.data.cursorPrefix = ["view_unique_key_asc"]; queryBuilder.orderBy(sql.fragment`${queryBuilder.getTableAlias()}.${sql.identifier(uniqueIdAttribute.name)}`, true); queryBuilder.setOrderIsUnique(); } }); } }, resolveContext, resolveInfo.rootValue); const { text, values } = sql.compile(query); if (_debugSql.default.enabled) (0, _debugSql.default)(text); const result = await pgPrepareAndRun(pgClient, text, values); const liveCollection = resolveInfo.rootValue && resolveInfo.rootValue.liveCollection; if (subscriptions && liveCollection && checkerGenerator) { const checker = checkerGenerator(); liveCollection("pg", table, checker); } if (isConnection) { const { rows: [row] } = result; return addStartEndCursor(row); } else { const liveRecord = resolveInfo.rootValue && resolveInfo.rootValue.liveRecord; if (subscriptions && !isConnection && primaryKeys && liveRecord) { result.rows.forEach(row => row && liveRecord("pg", table, row.__identifiers)); } return result.rows; } } }; }, { isPgFieldConnection: isConnection, isPgFieldSimpleCollection: !isConnection, pgFieldIntrospection: table }); } const simpleCollections = table.tags.simpleCollections || pgSimpleCollections; const hasConnections = simpleCollections !== "only"; const hasSimpleCollections = simpleCollections === "only" || simpleCollections === "both"; if (TableType && ConnectionType && hasConnections) { makeField(true); } if (TableType && hasSimpleCollections) { makeField(false); } return memo; }, {}), `Adding 'all*' relations to root Query`); }, ["PgAllRows"], [], ["PgTables"]); }; exports.default = PgAllRows; //# sourceMappingURL=PgAllRows.js.map