Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save tshddx/7ba7730c4cfa599a214e5145e687a9e3 to your computer and use it in GitHub Desktop.
Save tshddx/7ba7730c4cfa599a214e5145e687a9e3 to your computer and use it in GitHub Desktop.
PostGraphile plugin to disable all filtering and sorting by default, and require you to opt in to each table and column you want to filter or sort.
import { Plugin } from 'postgraphile';
import type { PgClass, PgAttribute } from 'graphile-build-pg';
//
// This plugin disables all filtering and sorting by default, and requires you
// to opt in to each table and column you want to filter or sort.
//
// PostGraphile's default behavior is:
// - Every GraphQL type and connection has `condition` and `orderBy` args.
// - All columns are filterable and sortable.
// - To disable filtering or sorting on a table or column, you need to use the
// @omit smart tag.
//
// The behavior with this plugin is:
// - There are no `condition` or `orderBy` args by default.
// - To enable filtering or sorting for a certain table, you must add the
// @filterable or @sortable smart tag to the table.
// - You must also add the @filterable or @sortable smart tag to EACH column
// you want to be filterable or sortable.
// - Note that you must add the @filterable smart tag to a table in order to
// add custom filters to that table (e.g. our
// ValidationConsensusStatusFilter.ts plugin)
//
export const DisableFilteringAndSortingByDefaultPlugin: Plugin = (builder) => {
builder.hook('build', (build) => {
const { pgIntrospectionResultsByKind } = build;
const tables: PgClass[] = pgIntrospectionResultsByKind.class;
tables
.filter((table) => table.isSelectable && table.namespace)
.forEach((table) => {
//
// Omit filtering from every table and column that does not have @filterable
//
if (table.tags.filterable === true) {
let attributes: PgAttribute[] =
pgIntrospectionResultsByKind.attribute;
attributes = attributes.filter(
(attribute) => attribute.class.id === table.id
);
attributes.forEach((attribute) => {
if (attribute.tags.filterable !== true) {
omit('filter', attribute.tags);
}
});
} else {
// @omit filtering from the table.
omit('filter', table.tags);
}
//
// Omit sorting from every table and column that does not have @sortable
//
if (table.tags.sortable === true) {
let attributes: PgAttribute[] =
pgIntrospectionResultsByKind.attribute;
attributes = attributes.filter(
(attribute) => attribute.class.id === table.id
);
attributes.forEach((attribute) => {
if (attribute.tags.sortable !== true) {
omit('order', attribute.tags);
}
});
} else {
// @omit sorting from the table.
omit('order', table.tags);
}
});
return build;
});
};
function omit(valueToOmit: string, tags: { omit?: string | boolean }) {
if (typeof tags.omit === 'boolean') {
if (!tags.omit) {
tags.omit = valueToOmit;
}
} else if (typeof tags.omit === 'string') {
if (
tags.omit !== 'all' &&
!tags.omit.split(',').some((o) => o === valueToOmit)
) {
tags.omit += `,${valueToOmit}`;
}
} else {
tags.omit = valueToOmit;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment