From 2e0f0f4b0cd642304c24c649d0d6943043fc6505 Mon Sep 17 00:00:00 2001 From: claygeo Date: Mon, 30 Mar 2026 11:10:43 -0400 Subject: [PATCH] fix(types): widen boolean serializer to accept number and string coercions Previously the boolean serializer threw for any non-boolean input, causing UPDATE statements with JS truthy values (1, 0, "true", "false") to error unexpectedly. PostgreSQL accepts these coercions natively. Widen the serialize signature to boolean | number | string: - Strings: matches PostgreSQL's accepted true literals ('true', 't', '1', 'yes', 'on') case-insensitively - Numbers / booleans: coerced via truthiness (1 -> 't', 0 -> 'f') Fixes: https://github.com/electric-sql/pglite/issues/791 --- packages/pglite/src/types.ts | 8 +++--- packages/pglite/tests/types.test.ts | 38 ++++++++++++++++++++++++++--- 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/packages/pglite/src/types.ts b/packages/pglite/src/types.ts index dec8a9388..54f176db3 100644 --- a/packages/pglite/src/types.ts +++ b/packages/pglite/src/types.ts @@ -120,9 +120,11 @@ export const types = { boolean: { to: BOOL, from: [BOOL], - serialize: (x: boolean) => { - if (typeof x !== 'boolean') { - throw new Error('Invalid input for boolean type') + serialize: (x: boolean | number | string) => { + if (typeof x === 'string') { + return ['true', 't', '1', 'yes', 'on'].includes(x.toLowerCase()) + ? 't' + : 'f' } return x ? 't' : 'f' }, diff --git a/packages/pglite/tests/types.test.ts b/packages/pglite/tests/types.test.ts index 05aba06ff..28c55fe79 100644 --- a/packages/pglite/tests/types.test.ts +++ b/packages/pglite/tests/types.test.ts @@ -98,12 +98,44 @@ describe('serialize', () => { expect(types.serializers[20](1n)).toEqual('1') }) - it('bool', () => { + it('bool true', () => { expect(types.serializers[16](true)).toEqual('t') }) - it('not bool', () => { - expect(() => types.serializers[16]('test')).toThrow() + it('bool false', () => { + expect(types.serializers[16](false)).toEqual('f') + }) + + it('bool from number 1', () => { + expect(types.serializers[16](1)).toEqual('t') + }) + + it('bool from number 0', () => { + expect(types.serializers[16](0)).toEqual('f') + }) + + it('bool from string "true"', () => { + expect(types.serializers[16]('true')).toEqual('t') + }) + + it('bool from string "false"', () => { + expect(types.serializers[16]('false')).toEqual('f') + }) + + it('bool from string "1"', () => { + expect(types.serializers[16]('1')).toEqual('t') + }) + + it('bool from string "yes"', () => { + expect(types.serializers[16]('yes')).toEqual('t') + }) + + it('bool from string "on"', () => { + expect(types.serializers[16]('on')).toEqual('t') + }) + + it('bool from string "t"', () => { + expect(types.serializers[16]('t')).toEqual('t') }) it('date', () => {