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
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 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