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
136 lines (134 loc) • 5.37 kB
JavaScript
;
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 PgRowByUniqueConstraint = async function PgRowByUniqueConstraint(builder, {
subscriptions
}) {
builder.hook("GraphQLObjectType:fields", (fields, build, context) => {
const {
extend,
parseResolveInfo,
pgGetGqlTypeByTypeIdAndModifier,
pgGetGqlInputTypeByTypeIdAndModifier,
gql2pg,
pgIntrospectionResultsByKind: introspectionResultsByKind,
pgSql: sql,
graphql: {
GraphQLNonNull
},
inflection,
pgQueryFromResolveData: queryFromResolveData,
pgOmit: omit,
pgPrepareAndRun
} = build;
const {
scope: {
isRootQuery
},
fieldWithHooks
} = context;
if (!isRootQuery) {
return fields;
}
return extend(fields, introspectionResultsByKind.class.reduce((memo, table) => {
// PERFORMANCE: These used to be .filter(...) calls
if (!table.namespace) return memo;
if (omit(table, "read")) return memo;
const TableType = pgGetGqlTypeByTypeIdAndModifier(table.type.id, null);
const sqlFullTableName = sql.identifier(table.namespace.name, table.name);
if (TableType) {
const uniqueConstraints = table.constraints.filter(con => con.type === "u" || con.type === "p");
uniqueConstraints.forEach(constraint => {
if (omit(constraint, "read")) {
return;
}
const keys = constraint.keyAttributes;
if (keys.some(key => omit(key, "read"))) {
return;
}
if (!keys.every(_ => _)) {
throw new Error("Consistency error: could not find an attribute!");
}
const fieldName = inflection.rowByUniqueKeys(keys, table, constraint);
const keysIncludingMeta = keys.map(key => ({
...key,
sqlIdentifier: sql.identifier(key.name),
columnName: inflection.column(key)
}));
// Precomputation for performance
const queryFromResolveDataOptions = {
useAsterisk: false // Because it's only a single relation, no need
};
const queryFromResolveDataCallback = (queryBuilder, args) => {
if (subscriptions && table.primaryKeyConstraint) {
queryBuilder.selectIdentifiers(table);
}
const sqlTableAlias = queryBuilder.getTableAlias();
keysIncludingMeta.forEach(({
sqlIdentifier,
columnName,
type,
typeModifier
}) => {
queryBuilder.where(sql.fragment`${sqlTableAlias}.${sqlIdentifier} = ${gql2pg(args[columnName], type, typeModifier)}`);
});
};
memo[fieldName] = fieldWithHooks(fieldName, ({
getDataFromParsedResolveInfoFragment
}) => {
return {
type: TableType,
args: keysIncludingMeta.reduce((memo, {
typeId,
typeModifier,
columnName,
name
}) => {
const InputType = pgGetGqlInputTypeByTypeIdAndModifier(typeId, typeModifier);
if (!InputType) {
throw new Error(`Could not find input type for key '${name}' on type '${TableType.name}'`);
}
memo[columnName] = {
type: new GraphQLNonNull(InputType)
};
return memo;
}, {}),
async resolve(parent, args, resolveContext, resolveInfo) {
const {
pgClient
} = resolveContext;
const liveRecord = resolveInfo.rootValue && resolveInfo.rootValue.liveRecord;
const parsedResolveInfoFragment = parseResolveInfo(resolveInfo);
parsedResolveInfoFragment.args = args; // Allow overriding via makeWrapResolversPlugin
const resolveData = getDataFromParsedResolveInfoFragment(parsedResolveInfoFragment, TableType);
const query = queryFromResolveData(sqlFullTableName, undefined, resolveData, queryFromResolveDataOptions, queryBuilder => queryFromResolveDataCallback(queryBuilder, args), resolveContext, resolveInfo.rootValue);
const {
text,
values
} = sql.compile(query);
if (_debugSql.default.enabled) (0, _debugSql.default)(text);
const {
rows: [row]
} = await pgPrepareAndRun(pgClient, text, values);
if (subscriptions && liveRecord && row) {
liveRecord("pg", table, row.__identifiers);
}
return row;
}
};
}, {
isPgRowByUniqueConstraintField: true,
pgFieldIntrospection: constraint
});
});
}
return memo;
}, {}), `Adding "row by unique constraint" fields to root Query type`);
}, ["PgRowByUniqueConstraint"]);
};
exports.default = PgRowByUniqueConstraint;
//# sourceMappingURL=PgRowByUniqueConstraint.js.map