Skip to content

Commit 5a57888

Browse files
committed
Hoist big functions
1 parent 621e70a commit 5a57888

6 files changed

+299
-151
lines changed

src/EXPORTABLE.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
export function EXPORTABLE<T, TScope extends any[]>(
2+
factory: (...args: TScope) => T,
3+
args: [...TScope],
4+
nameHint?: string
5+
): T {
6+
const fn: T = factory(...args);
7+
if (
8+
((typeof fn === "object" && fn !== null) || typeof fn === "function") &&
9+
!("$exporter$factory" in fn)
10+
) {
11+
Object.defineProperties(fn, {
12+
$exporter$args: { value: args },
13+
$exporter$factory: { value: factory },
14+
$exporter$name: { writable: true, value: nameHint },
15+
});
16+
}
17+
return fn;
18+
}

src/PgConnectionArgFilterAttributesPlugin.ts

Lines changed: 52 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,55 @@
11
import type {
2+
PgCodecAttribute,
23
PgCodecWithAttributes,
34
PgConditionCapableParent,
45
} from "@dataplan/pg";
56
import type { GraphQLInputObjectType } from "graphql";
67
import { isEmpty } from "./utils";
8+
import { EXPORTABLE } from "./EXPORTABLE";
79

810
import { version } from "./version";
911

12+
const pgConnectionFilterApplyAttribute = EXPORTABLE(
13+
(isEmpty) =>
14+
(
15+
PgCondition: GraphileBuild.Build["dataplanPg"]["PgCondition"],
16+
colSpec: {
17+
fieldName: string;
18+
attributeName: string;
19+
attribute: PgCodecAttribute;
20+
},
21+
connectionFilterAllowEmptyObjectInput: boolean | undefined,
22+
connectionFilterAllowNullInput: boolean | undefined,
23+
queryBuilder: PgConditionCapableParent,
24+
value: unknown
25+
) => {
26+
if (value === undefined) {
27+
return;
28+
}
29+
if (!connectionFilterAllowEmptyObjectInput && isEmpty(value)) {
30+
throw Object.assign(
31+
new Error("Empty objects are forbidden in filter argument input."),
32+
{
33+
//TODO: mark this error as safe
34+
}
35+
);
36+
}
37+
if (!connectionFilterAllowNullInput && value === null) {
38+
throw Object.assign(
39+
new Error("Null literals are forbidden in filter argument input."),
40+
{
41+
//TODO: mark this error as safe
42+
}
43+
);
44+
}
45+
const condition = new PgCondition(queryBuilder);
46+
condition.extensions.pgFilterAttribute = colSpec;
47+
return condition;
48+
},
49+
[isEmpty],
50+
"pgConnectionFilterApplyAttribute"
51+
);
52+
1053
export const PgConnectionArgFilterAttributesPlugin: GraphileConfig.Plugin = {
1154
name: "PgConnectionArgFilterAttributesPlugin",
1255
version,
@@ -78,49 +121,26 @@ export const PgConnectionArgFilterAttributesPlugin: GraphileConfig.Plugin = {
78121
PgCondition,
79122
colSpec,
80123
connectionFilterAllowEmptyObjectInput,
81-
connectionFilterAllowNullInput,
82-
isEmpty
124+
connectionFilterAllowNullInput
83125
) =>
84126
function (
85127
queryBuilder: PgConditionCapableParent,
86128
value: unknown
87129
) {
88-
if (value === undefined) {
89-
return;
90-
}
91-
if (
92-
!connectionFilterAllowEmptyObjectInput &&
93-
isEmpty(value)
94-
) {
95-
throw Object.assign(
96-
new Error(
97-
"Empty objects are forbidden in filter argument input."
98-
),
99-
{
100-
//TODO: mark this error as safe
101-
}
102-
);
103-
}
104-
if (!connectionFilterAllowNullInput && value === null) {
105-
throw Object.assign(
106-
new Error(
107-
"Null literals are forbidden in filter argument input."
108-
),
109-
{
110-
//TODO: mark this error as safe
111-
}
112-
);
113-
}
114-
const condition = new PgCondition(queryBuilder);
115-
condition.extensions.pgFilterAttribute = colSpec;
116-
return condition;
130+
return pgConnectionFilterApplyAttribute(
131+
PgCondition,
132+
colSpec,
133+
connectionFilterAllowEmptyObjectInput,
134+
connectionFilterAllowNullInput,
135+
queryBuilder,
136+
value
137+
);
117138
},
118139
[
119140
PgCondition,
120141
colSpec,
121142
connectionFilterAllowEmptyObjectInput,
122143
connectionFilterAllowNullInput,
123-
isEmpty,
124144
]
125145
),
126146
})

src/PgConnectionArgFilterBackwardRelationsPlugin.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,7 @@ export const PgConnectionArgFilterBackwardRelationsPlugin: GraphileConfig.Plugin
367367
() => ({
368368
description: `Filter by the object’s \`${fieldName}\` relation.`,
369369
type: FilterManyType,
370+
// $where.alias represents source; we need a condition that references the relational target
370371
apply: EXPORTABLE(
371372
(
372373
assertAllowed,
@@ -380,7 +381,6 @@ export const PgConnectionArgFilterBackwardRelationsPlugin: GraphileConfig.Plugin
380381
value: object | null
381382
) {
382383
assertAllowed(value, "object");
383-
// $where.alias represents source; we need a condition that references the relational target
384384
const $rel = $where.andPlan();
385385
$rel.extensions.pgFilterRelation = {
386386
tableExpression: foreignTableExpression,

src/PgConnectionArgFilterComputedAttributesPlugin.ts

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
import type { PgCondition } from "@dataplan/pg";
1+
import type { PgCodec, PgCondition, PgResource } from "@dataplan/pg";
22
import {
33
getComputedAttributeResources,
44
isComputedScalarAttributeResource,
55
} from "./utils";
66
import type { GraphQLInputObjectType } from "graphql";
7+
import { EXPORTABLE } from "./EXPORTABLE";
78

89
import { version } from "./version";
910

@@ -15,6 +16,36 @@ declare global {
1516
}
1617
}
1718

19+
const pgConnectionFilterApplyComputedAttribute = EXPORTABLE(
20+
() =>
21+
(
22+
PgCondition: GraphileBuild.Build["dataplanPg"]["PgCondition"],
23+
computedAttributeResource: PgResource,
24+
fieldName: string,
25+
functionResultCodec: PgCodec,
26+
$where: PgCondition,
27+
value: object | null
28+
) => {
29+
if (typeof computedAttributeResource.from !== "function") {
30+
throw new Error(`Unexpected...`);
31+
}
32+
// TODO: assertAllowed?
33+
if (value == null) return;
34+
const expression = computedAttributeResource.from({
35+
placeholder: $where.alias,
36+
});
37+
const $col = new PgCondition($where);
38+
$col.extensions.pgFilterAttribute = {
39+
fieldName,
40+
codec: functionResultCodec,
41+
expression,
42+
};
43+
return $col;
44+
},
45+
[],
46+
"pgConnectionFilterApplyComputedAttribute "
47+
);
48+
1849
export const PgConnectionArgFilterComputedAttributesPlugin: GraphileConfig.Plugin =
1950
{
2051
name: "PgConnectionArgFilterComputedAttributesPlugin",
@@ -152,23 +183,14 @@ export const PgConnectionArgFilterComputedAttributesPlugin: GraphileConfig.Plugi
152183
functionResultCodec
153184
) =>
154185
function ($where: PgCondition, value: object | null) {
155-
if (
156-
typeof computedAttributeResource.from !== "function"
157-
) {
158-
throw new Error(`Unexpected...`);
159-
}
160-
// TODO: assertAllowed?
161-
if (value == null) return;
162-
const expression = computedAttributeResource.from({
163-
placeholder: $where.alias,
164-
});
165-
const $col = new PgCondition($where);
166-
$col.extensions.pgFilterAttribute = {
186+
return pgConnectionFilterApplyComputedAttribute(
187+
PgCondition,
188+
computedAttributeResource,
167189
fieldName,
168-
codec: functionResultCodec,
169-
expression,
170-
};
171-
return $col;
190+
functionResultCodec,
191+
$where,
192+
value
193+
);
172194
},
173195
[
174196
PgCondition,

src/PgConnectionArgFilterForwardRelationsPlugin.ts

Lines changed: 86 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,75 @@ import type {
77
} from "@dataplan/pg";
88
import { makeAssertAllowed } from "./utils";
99
import type { GraphQLInputObjectType } from "graphql";
10+
import { EXPORTABLE } from "./EXPORTABLE";
11+
import type { SQL } from "pg-sql2";
1012

1113
import { version } from "./version";
1214

15+
const pgConnectionFilterApplySingleRelation = EXPORTABLE(
16+
() =>
17+
(
18+
assertAllowed: ReturnType<typeof makeAssertAllowed>,
19+
foreignTable: PgResource,
20+
foreignTableExpression: SQL,
21+
localAttributes: string[],
22+
remoteAttributes: string[],
23+
sql: GraphileBuild.Build["sql"],
24+
$where: PgCondition,
25+
value: object | null
26+
) => {
27+
assertAllowed(value, "object");
28+
if (value == null) return;
29+
const $subQuery = $where.existsPlan({
30+
tableExpression: foreignTableExpression,
31+
alias: foreignTable.name,
32+
});
33+
localAttributes.forEach((localAttribute, i) => {
34+
const remoteAttribute = remoteAttributes[i];
35+
$subQuery.where(
36+
sql`${$where.alias}.${sql.identifier(localAttribute as string)} = ${
37+
$subQuery.alias
38+
}.${sql.identifier(remoteAttribute as string)}`
39+
);
40+
});
41+
return $subQuery;
42+
},
43+
[],
44+
"pgConnectionFilterApplySingleRelation"
45+
);
46+
47+
const pgConnectionFilterApplyForwardRelationExists = EXPORTABLE(
48+
() =>
49+
(
50+
assertAllowed: ReturnType<typeof makeAssertAllowed>,
51+
foreignTable: PgResource,
52+
foreignTableExpression: SQL,
53+
localAttributes: string[],
54+
remoteAttributes: string[],
55+
sql: GraphileBuild.Build["sql"],
56+
$where: PgCondition,
57+
value: boolean | null
58+
) => {
59+
assertAllowed(value, "scalar");
60+
if (value == null) return;
61+
const $subQuery = $where.existsPlan({
62+
tableExpression: foreignTableExpression,
63+
alias: foreignTable.name,
64+
equals: value,
65+
});
66+
localAttributes.forEach((localAttribute, i) => {
67+
const remoteAttribute = remoteAttributes[i];
68+
$subQuery.where(
69+
sql`${$where.alias}.${sql.identifier(localAttribute as string)} = ${
70+
$subQuery.alias
71+
}.${sql.identifier(remoteAttribute as string)}`
72+
);
73+
});
74+
},
75+
[],
76+
"pgConnectionFilterApplyForwardRelationExists"
77+
);
78+
1379
export const PgConnectionArgFilterForwardRelationsPlugin: GraphileConfig.Plugin =
1480
{
1581
name: "PgConnectionArgFilterForwardRelationsPlugin",
@@ -132,23 +198,16 @@ export const PgConnectionArgFilterForwardRelationsPlugin: GraphileConfig.Plugin
132198
sql
133199
) =>
134200
function ($where: PgCondition, value: object | null) {
135-
assertAllowed(value, "object");
136-
if (value == null) return;
137-
const $subQuery = $where.existsPlan({
138-
tableExpression: foreignTableExpression,
139-
alias: foreignTable.name,
140-
});
141-
localAttributes.forEach((localAttribute, i) => {
142-
const remoteAttribute = remoteAttributes[i];
143-
$subQuery.where(
144-
sql`${$where.alias}.${sql.identifier(
145-
localAttribute as string
146-
)} = ${$subQuery.alias}.${sql.identifier(
147-
remoteAttribute as string
148-
)}`
149-
);
150-
});
151-
return $subQuery;
201+
return pgConnectionFilterApplySingleRelation(
202+
assertAllowed,
203+
foreignTable,
204+
foreignTableExpression,
205+
localAttributes,
206+
remoteAttributes,
207+
sql,
208+
$where,
209+
value
210+
);
152211
},
153212
[
154213
assertAllowed,
@@ -196,23 +255,16 @@ export const PgConnectionArgFilterForwardRelationsPlugin: GraphileConfig.Plugin
196255
$where: PgCondition,
197256
value: boolean | null
198257
) {
199-
assertAllowed(value, "scalar");
200-
if (value == null) return;
201-
const $subQuery = $where.existsPlan({
202-
tableExpression: foreignTableExpression,
203-
alias: foreignTable.name,
204-
equals: value,
205-
});
206-
localAttributes.forEach((localAttribute, i) => {
207-
const remoteAttribute = remoteAttributes[i];
208-
$subQuery.where(
209-
sql`${$where.alias}.${sql.identifier(
210-
localAttribute as string
211-
)} = ${$subQuery.alias}.${sql.identifier(
212-
remoteAttribute as string
213-
)}`
214-
);
215-
});
258+
return pgConnectionFilterApplyForwardRelationExists(
259+
assertAllowed,
260+
foreignTable,
261+
foreignTableExpression,
262+
localAttributes,
263+
remoteAttributes,
264+
sql,
265+
$where,
266+
value
267+
);
216268
},
217269
[
218270
assertAllowed,

0 commit comments

Comments
 (0)