drizzle-graphql
drizzle-graphql copied to clipboard
impossible to define array of objects (aka jsonb) + no support for custom fields
Seems like there is no easy way to define a field as array of objects.
one way is to define with jsonb:
interface PreviousOwner {
name: string
}
export const owners = pgTable('owners', {
id: serial('id').primaryKey(),
previousOwners: jsonb('previous_owners')
.$type<PreviousOwner[]>()
.notNull()
.default([]),
})
Checking Apollo sandbox Introspection Schema. drizzle-graphql generates the following SDL schema:
input OwnersInsertInput {
id: Int
"""JSON"""
previousOwners: String
}
So, the mutation will accept String only:
mutation InsertIntoOwnersSingle {
insertIntoOwnersSingle(
values: {
previousOwners: "[{\"name\": \"jon doe3\"}]"
}
) {
id
previousOwners
}
}
Checking in drizzle studio. the record has been created:
Now, lets execute the query:
query Owners {
owners {
id
previousOwners
}
}
And here is the error:
{
"errors": [
{
"message": "String cannot represent value: [\"{\\\"name\\\":\\\"jon doe3\\\"}\"]",
"locations": [
{
"line": 4,
"column": 5
}
],
"path": [
"owners",
0,
"previousOwners"
],
"extensions": {
"code": "INTERNAL_SERVER_ERROR",
"stacktrace": [
"GraphQLError: String cannot represent value: [\"{\\\"name\\\":\\\"jon doe3\\\"}\"]",
" at GraphQLScalarType.serialize (/Users/myuser/Desktop/projects/my-turborepo/node_modules/.pnpm/[email protected]/node_modules/graphql/type/scalars.js:202:11)",
" at completeLeafValue (/Users/myuser/Desktop/projects/my-turborepo/node_modules/.pnpm/[email protected]/node_modules/graphql/execution/execute.js:749:39)",
" at completeValue (/Users/myuser/Desktop/projects/my-turborepo/node_modules/.pnpm/[email protected]/node_modules/graphql/execution/execute.js:630:12)",
" at completeValue (/Users/myuser/Desktop/projects/my-turborepo/node_modules/.pnpm/[email protected]/node_modules/graphql/execution/execute.js:595:23)",
" at executeField (/Users/myuser/Desktop/projects/my-turborepo/node_modules/.pnpm/[email protected]/node_modules/graphql/execution/execute.js:500:19)",
" at executeFields (/Users/myuser/Desktop/projects/my-turborepo/node_modules/.pnpm/[email protected]/node_modules/graphql/execution/execute.js:414:22)",
" at completeObjectValue (/Users/myuser/Desktop/projects/my-turborepo/node_modules/.pnpm/[email protected]/node_modules/graphql/execution/execute.js:925:10)",
" at completeValue (/Users/myuser/Desktop/projects/my-turborepo/node_modules/.pnpm/[email protected]/node_modules/graphql/execution/execute.js:646:12)",
" at completeValue (/Users/myuser/Desktop/projects/my-turborepo/node_modules/.pnpm/[email protected]/node_modules/graphql/execution/execute.js:595:23)",
" at /Users/myuser/Desktop/projects/my-turborepo/node_modules/.pnpm/[email protected]/node_modules/graphql/execution/execute.js:707:25"
]
}
}
],
"data": null
}
Tried to fix it with custom field:
const customJsonB = customType<{
data: PreviousOwner[]
}>({
dataType: () => 'jsonb',
fromDriver: (val) => JSON.parse(val as string),
toDriver: (val: PreviousOwner[]) => JSON.stringify(val),
})
But there is no support for custom field:
throw new Error(`Drizzle-GraphQL Error: Type ${column.dataType} is not implemented!`);
https://github.com/drizzle-team/drizzle-graphql/blob/c558249fadcc7bd1af8ec17faf292d8cf2d365c5/src/util/type-converter/index.ts#L121
I'm also stuck with no support for custom fields. In my case I'm trying to simply define some postgres like types, such as:
export const tstzrange = customType<TsTzRange>({
dataType() {
return "tstzrange";
},
toDriver(value: TsTzRange["data"]): string {
return `[${value.from},${value.to})`;
},
fromDriver(value: string): TsTzRange["data"] {
const [from, to] = value.slice(1, -1).split(",");
return {
from,
to,
};
},
});
but I get
/node_modules/src/util/type-converter/index.ts:121
throw new Error(`Drizzle-GraphQL Error: Type ${column.dataType} is not implemented!`);
^
Error: Drizzle-GraphQL Error: Type custom is not implemented!
Is it something I'm doing wrong or simply there's still not a support for this use case? Any idea how to move forward?
@chemalopezp I forked the repo and added support for array of objects and partial support for custom fields. Will push PR soon.
@ruslan-primesec that's amazing! Thank you so much, let me know if I can be of any help 🎉 Looking forward to test it ;)
@ruslan-primesec I hope everything is going well! Is there any way I could help with the custom fields PR? Or do you already have a timeline? Thank you so much!
I'm also interested in support for custom types. I have a SHA256 field like:
import { sql } from "drizzle-orm";
import { customType } from "drizzle-orm/mysql-core";
export const sha256 = customType<{
data: Uint8Array;
notNull: true;
driverData: string;
}>({
dataType() {
return "binary(32)";
},
fromDriver(value): Uint8Array {
return typeof value === "string"
? new Uint8Array(Array.from(value).map((char) => char.charCodeAt(0)))
: new Uint8Array(value as ArrayBufferLike);
},
toDriver(value) {
return sql`UNHEX(SHA2(${value}, 256))`;
},
});
and it cannot be used with the generator due to it throwing on the custom type
@ruslan-primesec The issue with implementing custom is that the underlying datatype is hidden. Right now, I have hack (below) but the right behavior would be to add a field like underlyingType to Column.
index 5225f1d..eb3c7d1 100644
--- a/src/util/type-converter/index.ts
+++ b/src/util/type-converter/index.ts
@@ -55,13 +55,20 @@ const geoXyInputType = new GraphQLInputObjectType({
},
});
+const getColumnDataType = (column: Column) => {
+ if (column.dataType !== 'custom') { return column.dataType};
+ return typeof column.mapFromDriverValue('');
+
+}
+
const columnToGraphQLCore = (
column: Column,
columnName: string,
tableName: string,
isInput: boolean,
): ConvertedColumn<boolean> => {
- switch (column.dataType) {
+ const dataType = getColumnDataType(column);
+ switch (dataType) {
case 'boolean':
return { type: GraphQLBoolean, description: 'Boolean' };
case 'json':
@@ -116,9 +123,8 @@ const columnToGraphQLCore = (
description: `Array<${innerType.description}>`,
};
}
- case 'custom':
default:
- throw new Error(`Drizzle-GraphQL Error: Type ${column.dataType} is not implemented!`);
+ throw new Error(`Drizzle-GraphQL Error: Type ${dataType} is not implemented!`);
}
};
+1 on fixing this, we're currently blocked on adding a custom scalar for storing polygons in postgres