Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,18 @@ const version = '1.0.0';
/**
* ConnectionFilterArgPlugin
*
* Adds the filter argument (configurable name, default 'where') to connection
* and simple collection fields. Uses `applyPlan` to create a PgCondition that
* child filter fields can add WHERE clauses to.
* Adds the `where` argument (name configurable via
* `connectionFilterArgumentName`, default `'where'`) to connection and
* simple collection fields. Uses `applyPlan` to create a PgCondition
* that child filter fields can add WHERE clauses to.
*
* This runs before PgConnectionArgOrderByPlugin so that filters are applied
* before ordering (important for e.g. full-text search rank ordering).
*/
export const ConnectionFilterArgPlugin: GraphileConfig.Plugin = {
name: 'ConnectionFilterArgPlugin',
version,
description: 'Adds the filter argument to connection and list fields',
description: 'Adds the `where` argument to connection and list fields',
before: ['PgConnectionArgOrderByPlugin'],

schema: {
Expand Down Expand Up @@ -100,7 +101,7 @@ export const ConnectionFilterArgPlugin: GraphileConfig.Plugin = {
fieldArg.apply(
$pgSelect,
(queryBuilder: any, value: any) => {
// If filter is null/undefined or empty {}, treat as "no filter" — skip
// If where is null/undefined or empty {}, treat as "no filter" — skip
if (value == null || isEmpty(value)) return;
const condition = new PgCondition(queryBuilder);
if (attributeCodec) {
Expand All @@ -126,7 +127,7 @@ export const ConnectionFilterArgPlugin: GraphileConfig.Plugin = {
fieldArg.apply(
$pgSelect,
(queryBuilder: any, value: any) => {
// If filter is null/undefined or empty {}, treat as "no filter" — skip
// If where is null/undefined or empty {}, treat as "no filter" — skip
if (value == null || isEmpty(value)) return;
const condition = new PgCondition(queryBuilder);
if (attributeCodec) {
Expand All @@ -143,7 +144,7 @@ export const ConnectionFilterArgPlugin: GraphileConfig.Plugin = {
}),
},
},
`Adding connection filter '${argName}' arg to field '${fieldName}' of '${Self.name}'`
`Adding connection where arg '${argName}' to field '${fieldName}' of '${Self.name}'`
);
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ export const ConnectionFilterAttributesPlugin: GraphileConfig.Plugin = {
if (isEmpty(value)) {
throw Object.assign(
new Error(
'Empty objects are forbidden in filter argument input.'
'Empty objects are forbidden in where argument input.'
),
{}
);
Expand All @@ -107,7 +107,7 @@ export const ConnectionFilterAttributesPlugin: GraphileConfig.Plugin = {
) {
throw Object.assign(
new Error(
'Null literals are forbidden in filter argument input.'
'Null literals are forbidden in where argument input.'
),
{}
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ const version = '1.0.0';
*
* For unique backward relations (one-to-one), a single filter field is added:
* ```graphql
* allClients(filter: {
* allClients(where: {
* profileByClientId: { bio: { includes: "engineer" } }
* }) { ... }
* ```
*
* For non-unique backward relations (one-to-many), a "many" filter type is added
* with `some`, `every`, and `none` sub-fields:
* ```graphql
* allClients(filter: {
* allClients(where: {
* ordersByClientId: { some: { total: { greaterThan: 1000 } } }
* }) { ... }
* ```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const version = '1.0.0';
*
* This plugin adds a `fullName` filter field to `PersonFilter`, typed as `StringFilter`,
* allowing queries like:
* { people(filter: { fullName: { startsWith: "John" } }) { ... } }
* { people(where: { fullName: { startsWith: "John" } }) { ... } }
*
* Controlled by the `connectionFilterComputedColumns` schema option (default: true).
* Requires the `filterBy` behavior on the pgResource to be enabled.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const version = '1.0.0';
* allowing queries like:
*
* ```graphql
* allOrders(filter: {
* allOrders(where: {
* clientByClientId: { name: { startsWith: "Acme" } }
* }) { ... }
* ```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export function makeApplyFromOperatorSpec(
}
if (!connectionFilterAllowNullInput && value === null) {
throw Object.assign(
new Error('Null literals are forbidden in filter argument input.'),
new Error('Null literals are forbidden in where argument input.'),
{}
);
}
Expand Down
8 changes: 4 additions & 4 deletions graphile/graphile-connection-filter/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,11 @@ export function makeAssertAllowed(build: any): (value: unknown, mode: 'object' |
isEmpty: (o: unknown) => boolean
) =>
function (value: unknown, mode: 'object' | 'list') {
// Reject empty objects in nested filter contexts (and/or/not, relation filters)
// Reject empty objects in nested where contexts (and/or/not, relation filters)
if (mode === 'object' && isEmpty(value)) {
throw Object.assign(
new Error(
'Empty objects are forbidden in filter argument input.'
'Empty objects are forbidden in where argument input.'
),
{}
);
Expand All @@ -134,7 +134,7 @@ export function makeAssertAllowed(build: any): (value: unknown, mode: 'object' |
if (isEmpty(arr[i])) {
throw Object.assign(
new Error(
'Empty objects are forbidden in filter argument input.'
'Empty objects are forbidden in where argument input.'
),
{}
);
Expand All @@ -147,7 +147,7 @@ export function makeAssertAllowed(build: any): (value: unknown, mode: 'object' |
if (!connectionFilterAllowNullInput && value === null) {
throw Object.assign(
new Error(
'Null literals are forbidden in filter argument input.'
'Null literals are forbidden in where argument input.'
),
{}
);
Expand Down
2 changes: 1 addition & 1 deletion graphile/graphile-postgis/src/plugins/spatial-relations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ import type { PostgisExtensionInfo } from './detect-extension';
* Generated GraphQL (for the `st_dwithin` case):
*
* ```graphql
* telemedicineClinics(filter: {
* telemedicineClinics(where: {
* nearbyClinic: {
* distance: 5000,
* some: { specialty: { eq: "pediatrics" } }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ describe('Schema introspection', () => {
expect(fieldNames).toContain('embedding');
});

it('locations connection exists and has filter argument but no condition', async () => {
it('locations connection exists and has where argument but no condition', async () => {
const result = await query<{ __type: { fields: { name: string; args: { name: string }[] }[] } | null }>({
query: `
query {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import type { GraphileConfig } from 'graphile-config';
* and adds `+attribute:filterBy` and `+attribute:orderBy` back to ALL columns, regardless of index status.
*
* This means:
* - All columns will appear in the connection filter's filter argument
* - All columns will appear in the connection filter's `where` argument
* - All columns will appear in the connection's orderBy enum
* - Developers can filter and sort by any column
* - It's the developer's/DBA's responsibility to add indexes for frequently filtered/sorted columns
Expand Down
18 changes: 10 additions & 8 deletions graphile/graphile-settings/src/presets/constructive-preset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ import { getBucketProvisionerConnection } from '../bucket-provisioner-resolver';
*
* RELATION FILTERS:
* - Enabled via connectionFilterRelations: true
* - Forward: filter child by parent (e.g. allOrders(filter: { clientByClientId: { name: { startsWith: "Acme" } } }))
* - Backward: filter parent by children (e.g. allClients(filter: { ordersByClientId: { some: { total: { greaterThan: 1000 } } } }))
* - Forward: filter child by parent (e.g. allOrders(where: { clientByClientId: { name: { startsWith: "Acme" } } }))
* - Backward: filter parent by children (e.g. allClients(where: { ordersByClientId: { some: { total: { greaterThan: 1000 } } } }))
*
* USAGE:
* ```typescript
Expand Down Expand Up @@ -105,9 +105,11 @@ export const ConstructivePreset: GraphileConfig.Preset = {
],
/**
* Disable PostGraphile core's condition argument entirely.
* All filtering now lives under the `filter` argument via our v5-native
* graphile-connection-filter plugin. Search, BM25, pgvector, and PostGIS
* filter fields all hook into `isPgConnectionFilter` instead of `isPgCondition`.
* All filtering now lives under the `where` argument via our v5-native
* graphile-connection-filter plugin (which renames the default `filter`
* argument to `where` via `connectionFilterArgumentName: 'where'`).
* Search, BM25, pgvector, and PostGIS filter fields all hook into
* `isPgConnectionFilter` instead of `isPgCondition`.
*/
disablePlugins: [
'PgConditionArgumentPlugin',
Expand All @@ -116,7 +118,7 @@ export const ConstructivePreset: GraphileConfig.Preset = {
/**
* Connection Filter Plugin Configuration
*
* These options control what fields appear in the `filter` argument on connections.
* These options control what fields appear in the `where` argument on connections.
* Our v5-native graphile-connection-filter plugin controls relation filters via the
* `connectionFilterRelations` option passed to ConnectionFilterPreset().
*
Expand Down Expand Up @@ -144,14 +146,14 @@ export const ConstructivePreset: GraphileConfig.Preset = {
/**
* connectionFilterLogicalOperators: true (default)
* Keeps `and`, `or`, `not` operators for combining filter conditions.
* Example: filter: { or: [{ name: { eq: "foo" } }, { name: { eq: "bar" } }] }
* Example: where: { or: [{ name: { eq: "foo" } }, { name: { eq: "bar" } }] }
*/
connectionFilterLogicalOperators: true,

/**
* connectionFilterArrays: true (default)
* Allows filtering on PostgreSQL array columns.
* Example: filter: { tags: { contains: ["important"] } }
* Example: where: { tags: { contains: ["important"] } }
*/
connectionFilterArrays: true,

Expand Down
Loading