diff --git a/.changeset/busy-beans-change.md b/.changeset/busy-beans-change.md new file mode 100644 index 00000000000..400f55454e2 --- /dev/null +++ b/.changeset/busy-beans-change.md @@ -0,0 +1,5 @@ +--- +"@effect/sql-drizzle": minor +--- + +Fix JSONB deserialization for db.insert in Effect + Drizzle integration diff --git a/packages/sql-drizzle/src/internal/patch.ts b/packages/sql-drizzle/src/internal/patch.ts index d84a37748e0..6ad29511cbf 100644 --- a/packages/sql-drizzle/src/internal/patch.ts +++ b/packages/sql-drizzle/src/internal/patch.ts @@ -47,7 +47,20 @@ export const makeRemoteCallback = Effect.gen(function*() { const constructionRuntime = yield* Effect.runtime() return (sql: string, params: Array, method: "all" | "execute" | "get" | "values" | "run") => { const runPromise = Runtime.runPromise(currentRuntime ? currentRuntime : constructionRuntime) - const statement = client.unsafe(sql, params) + + const finalParams = params.map((e) => { + if (e === null || e === undefined) return e + if (typeof e !== "string") return e + const s = e.trim() + if (!(s.startsWith("{") || s.startsWith("["))) return e + try { + return JSON.parse(s) + } catch { + return e + } + }) + + const statement = client.unsafe(sql, finalParams) if (method === "execute") { return runPromise(Effect.either(Effect.map(statement.raw, (header) => ({ rows: [header] })))).then((res) => { if (res._tag === "Left") { diff --git a/packages/sql-drizzle/test/Pg.test.ts b/packages/sql-drizzle/test/Pg.test.ts index 1a21aee5969..4e11ecdd6e3 100644 --- a/packages/sql-drizzle/test/Pg.test.ts +++ b/packages/sql-drizzle/test/Pg.test.ts @@ -91,4 +91,30 @@ describe.sequential("Pg", () => { Effect.catchTag("ContainerError", () => Effect.void) ) }, { timeout: 60000 }) + + it.effect("supports object params (auto JSON serialization)", () => + Effect.gen(function*() { + const sql = yield* SqlClient.SqlClient + const db = yield* Pg.PgDrizzle + + yield* sql`CREATE TABLE data_objects (id SERIAL PRIMARY KEY, payload JSONB NOT NULL)` + + const payload = { foo: "bar", count: 42 } + + yield* db.insert(D.pgTable("data_objects", { + id: D.serial("id").primaryKey(), + payload: D.jsonb("payload").notNull() + })).values({ payload }) + + const rows = yield* sql`SELECT id, payload FROM data_objects ORDER BY id` + + assert.deepStrictEqual(rows, [ + { id: 1, payload } + ]) + }).pipe( + Effect.provide(DrizzlePgLive), + Effect.catchTag("ContainerError", () => Effect.void) + ), { + timeout: 60000 + }) })