Skip to content

Commit aa465f8

Browse files
committed
✨ feat: implement the adjust function for objects
1 parent ce8efbd commit aa465f8

File tree

1 file changed

+102
-22
lines changed

1 file changed

+102
-22
lines changed

lib/object.ts

Lines changed: 102 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,30 @@ export const createObjectImplementer = <
8282
table,
8383
refName,
8484
readAction = "read" as Action,
85-
extend,
85+
adjust,
8686
}: {
87+
/**
88+
* The table you want to be used as reference for the object creation.
89+
*/
8790
table: ExplicitTableName;
91+
/**
92+
* The name you want this object to have in your graphql schema.
93+
* Rumble will create a reasonable default if not specified.
94+
*/
8895
refName?: RefName;
96+
/**
97+
* The action used for read access to the table.
98+
* Defaults to "read".
99+
*/
89100
readAction?: Action;
90-
extend?:
101+
/**
102+
* A function which can be used to adjust the fields of the object.
103+
* You can extend the object by specifying fields that do not exist as
104+
* per your db schema, or overwrite existing fields with the same name.
105+
* In case you do overwrite, rumble will set proper nullability and
106+
* subscription properties if you do not specify them explicitly.
107+
*/
108+
adjust?:
91109
| ((
92110
t: DrizzleObjectFieldBuilder<
93111
SchemaBuilder["$inferSchemaTypes"],
@@ -184,8 +202,56 @@ export const createObjectImplementer = <
184202
}
185203
};
186204

205+
// in case the user makes adjustments we want to store away which
206+
// pothos function was called with what config
207+
// this is mapped to the ref which later can be used to
208+
// reference these parameters while iterating over the fields
209+
// and checking against the userAdjustments object
210+
const configMap = new Map<
211+
any,
212+
{
213+
creatorFunction: any;
214+
config: any;
215+
}
216+
>();
217+
// stores the results of the user adjustments
218+
// also stores all the used pothos functions and the configs
219+
// provided by the user so we can extend that if necessary
220+
const userAdjustments =
221+
adjust?.(
222+
new Proxy(t, {
223+
get: (target, prop) => {
224+
if (typeof (target as any)[prop] === "function") {
225+
return (config: any) => {
226+
const ref = (target as any)[prop](config);
227+
configMap.set(ref, {
228+
config,
229+
creatorFunction: (target as any)[prop],
230+
});
231+
return ref;
232+
};
233+
}
234+
235+
return (target as any)[prop];
236+
},
237+
}) as any,
238+
) ?? {};
239+
187240
const fields = Object.entries(columns).reduce(
188241
(acc, [key, value]) => {
242+
if (userAdjustments[key]) {
243+
const { config, creatorFunction } = configMap.get(
244+
userAdjustments[key],
245+
)!;
246+
247+
if (typeof config.nullable !== "boolean") {
248+
config.nullable = !value.notNull;
249+
}
250+
251+
userAdjustments[key] = creatorFunction(config);
252+
return acc;
253+
}
254+
189255
if (isEnumSchema(value)) {
190256
const enumImpl = enumImplementer({
191257
enumColumn: value,
@@ -234,20 +300,39 @@ export const createObjectImplementer = <
234300
filterSpecifier = "single";
235301
}
236302

303+
const subscribe = (subscriptions: any, element: any) => {
304+
relationTable.registerOnInstance({
305+
instance: subscriptions,
306+
action: "created",
307+
});
308+
relationTable.registerOnInstance({
309+
instance: subscriptions,
310+
action: "removed",
311+
});
312+
};
313+
314+
if (userAdjustments[key]) {
315+
const { config, creatorFunction } = configMap.get(
316+
userAdjustments[key],
317+
)!;
318+
319+
if (typeof config.nullable !== "boolean") {
320+
config.nullable = nullable;
321+
}
322+
323+
if (typeof config.subscribe !== "function") {
324+
config.subscribe = subscribe;
325+
}
326+
327+
userAdjustments[key] = creatorFunction(config);
328+
return acc;
329+
}
330+
237331
(acc as any)[key] = t.relation(key, {
238332
args: {
239333
where: t.arg({ type: WhereArg, required: false }),
240334
},
241-
subscribe: (subscriptions, element) => {
242-
relationTable.registerOnInstance({
243-
instance: subscriptions,
244-
action: "created",
245-
});
246-
relationTable.registerOnInstance({
247-
instance: subscriptions,
248-
action: "removed",
249-
});
250-
},
335+
subscribe,
251336
nullable,
252337
query: (args: any, ctx: any) => {
253338
return ctx.abilities[relationSchema.tsName].filter(readAction, {
@@ -263,16 +348,11 @@ export const createObjectImplementer = <
263348
>,
264349
);
265350

266-
return extend
267-
? {
268-
...fields,
269-
...relations,
270-
...(extend(t as any) ?? {}),
271-
}
272-
: {
273-
...fields,
274-
...relations,
275-
};
351+
return {
352+
...fields,
353+
...relations,
354+
...userAdjustments,
355+
};
276356
},
277357
});
278358
};

0 commit comments

Comments
 (0)