UNPKG

postgraphile-plugin-connection-filter

Version:
150 lines 8.24 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PgConnectionArgFilterForwardRelationsPlugin = void 0; const utils_1 = require("./utils"); const EXPORTABLE_1 = require("./EXPORTABLE"); const version_1 = require("./version"); const pgConnectionFilterApplySingleRelation = (0, EXPORTABLE_1.EXPORTABLE)(() => (assertAllowed, foreignTable, foreignTableExpression, localAttributes, remoteAttributes, sql, $where, value) => { assertAllowed(value, "object"); if (value == null) return; const $subQuery = $where.existsPlan({ tableExpression: foreignTableExpression, alias: foreignTable.name, }); localAttributes.forEach((localAttribute, i) => { const remoteAttribute = remoteAttributes[i]; $subQuery.where(sql `${$where.alias}.${sql.identifier(localAttribute)} = ${$subQuery.alias}.${sql.identifier(remoteAttribute)}`); }); $subQuery.ignoreUnlessAmended(); return $subQuery; }, [], "pgConnectionFilterApplySingleRelation"); const pgConnectionFilterApplyForwardRelationExists = (0, EXPORTABLE_1.EXPORTABLE)(() => (assertAllowed, foreignTable, foreignTableExpression, localAttributes, remoteAttributes, sql, $where, value) => { assertAllowed(value, "scalar"); if (value == null) return; const $subQuery = $where.existsPlan({ tableExpression: foreignTableExpression, alias: foreignTable.name, equals: value, }); localAttributes.forEach((localAttribute, i) => { const remoteAttribute = remoteAttributes[i]; $subQuery.where(sql `${$where.alias}.${sql.identifier(localAttribute)} = ${$subQuery.alias}.${sql.identifier(remoteAttribute)}`); }); }, [], "pgConnectionFilterApplyForwardRelationExists"); exports.PgConnectionArgFilterForwardRelationsPlugin = { name: "PgConnectionArgFilterForwardRelationsPlugin", version: version_1.version, inflection: { add: { filterForwardRelationExistsFieldName(_preset, relationFieldName) { return `${relationFieldName}Exists`; }, filterSingleRelationFieldName(_preset, fieldName) { return fieldName; }, }, }, schema: { behaviorRegistry: { add: { filterBy: { description: "Can we filter by the results of this relation?", entities: ["pgCodecRelation"], }, }, }, entityBehavior: { pgCodecRelation: "filterBy", }, hooks: { GraphQLInputObjectType_fields(fields, build, context) { const { extend, inflection, graphql: { GraphQLBoolean }, sql, options: { pgIgnoreReferentialIntegrity }, EXPORTABLE, } = build; const { fieldWithHooks, scope: { pgCodec, isPgConnectionFilter }, } = context; const assertAllowed = (0, utils_1.makeAssertAllowed)(build); const source = pgCodec && Object.values(build.input.pgRegistry.pgResources).find((s) => s.codec === pgCodec && !s.parameters); if (!isPgConnectionFilter || !pgCodec || !pgCodec.attributes || !source) { return fields; } const forwardRelations = Object.entries(source.getRelations()).filter(([_relationName, relation]) => { return !relation.isReferencee; }); for (const [relationName, relation] of forwardRelations) { const foreignTable = relation.remoteResource; // Deliberate shadowing // Used to use 'read' behavior too if (!build.behavior.pgCodecRelationMatches(relation, "filterBy")) { continue; } const fieldName = inflection.singleRelation({ registry: source.registry, codec: source.codec, relationName, }); const filterFieldName = inflection.filterSingleRelationFieldName(fieldName); const foreignTableTypeName = inflection.tableType(foreignTable.codec); const foreignTableFilterTypeName = inflection.filterType(foreignTableTypeName); const ForeignTableFilterType = build.getTypeByName(foreignTableFilterTypeName); if (!ForeignTableFilterType) continue; if (typeof foreignTable.from === "function") { continue; } const foreignTableExpression = foreignTable.from; const localAttributes = relation.localAttributes; const remoteAttributes = relation.remoteAttributes; fields = extend(fields, { [filterFieldName]: fieldWithHooks({ fieldName: filterFieldName, isPgConnectionFilterField: true, }, () => ({ description: `Filter by the object’s \`${fieldName}\` relation.`, type: ForeignTableFilterType, apply: EXPORTABLE((assertAllowed, foreignTable, foreignTableExpression, localAttributes, pgConnectionFilterApplySingleRelation, remoteAttributes, sql) => function ($where, value) { return pgConnectionFilterApplySingleRelation(assertAllowed, foreignTable, foreignTableExpression, localAttributes, remoteAttributes, sql, $where, value); }, [ assertAllowed, foreignTable, foreignTableExpression, localAttributes, pgConnectionFilterApplySingleRelation, remoteAttributes, sql, ]), })), }, `Adding connection filter forward relation field from ${source.name} to ${foreignTable.name}`); const keyIsNullable = relation.localAttributes.some((col) => !source.codec.attributes[col].notNull); if (keyIsNullable || pgIgnoreReferentialIntegrity) { const existsFieldName = inflection.filterForwardRelationExistsFieldName(fieldName); fields = extend(fields, { [existsFieldName]: fieldWithHooks({ fieldName: existsFieldName, isPgConnectionFilterField: true, }, () => ({ description: `A related \`${fieldName}\` exists.`, type: GraphQLBoolean, apply: EXPORTABLE((assertAllowed, foreignTable, foreignTableExpression, localAttributes, pgConnectionFilterApplyForwardRelationExists, remoteAttributes, sql) => function ($where, value) { return pgConnectionFilterApplyForwardRelationExists(assertAllowed, foreignTable, foreignTableExpression, localAttributes, remoteAttributes, sql, $where, value); }, [ assertAllowed, foreignTable, foreignTableExpression, localAttributes, pgConnectionFilterApplyForwardRelationExists, remoteAttributes, sql, ]), })), }, `Adding connection filter forward relation exists field from ${source.name} to ${foreignTable.name}`); } } return fields; }, }, }, }; //# sourceMappingURL=PgConnectionArgFilterForwardRelationsPlugin.js.map