Loading README.md +7 −0 Original line number Diff line number Diff line Loading @@ -68,6 +68,13 @@ Changelog To be released. ### Version 0.2.2 Released on November 18, 2024. - Fixed a bug where binding parameters have not been properly escaped with some settings of Postgres.js. ### Version 0.2.1 Released on November 3, 2024. Loading src/kv.ts +10 −2 Original line number Diff line number Diff line import type { KvKey, KvStore, KvStoreSetOptions } from "@fedify/fedify"; import type { Sql } from "postgres"; import type { JSONValue, Parameter, Sql } from "postgres"; import { driverSerializesJson } from "./utils.ts"; /** * Options for the PostgreSQL key-value store. Loading Loading @@ -39,6 +40,7 @@ export class PostgresKvStore implements KvStore { readonly #sql: Sql<{}>; readonly #tableName: string; #initialized: boolean; #driverSerializesJson = false; /** * Creates a new PostgreSQL key-value store. Loading Loading @@ -84,7 +86,7 @@ export class PostgresKvStore implements KvStore { INSERT INTO ${this.#sql(this.#tableName)} (key, value, ttl) VALUES ( ${key}, (${{ value } as unknown as string}::jsonb) -> 'value', ${this.#json(value)}, ${ttl} ) ON CONFLICT (key) Loading Loading @@ -116,6 +118,7 @@ export class PostgresKvStore implements KvStore { ttl interval ); `; this.#driverSerializesJson = await driverSerializesJson(this.#sql); this.#initialized = true; } Loading @@ -126,4 +129,9 @@ export class PostgresKvStore implements KvStore { async drop(): Promise<void> { await this.#sql`DROP TABLE IF EXISTS ${this.#sql(this.#tableName)};`; } #json(value: unknown): Parameter { if (this.#driverSerializesJson) return this.#sql.json(value as JSONValue); return this.#sql.json(JSON.stringify(value)); } } src/mq.ts +10 −2 Original line number Diff line number Diff line Loading @@ -3,8 +3,9 @@ import type { MessageQueueEnqueueOptions, MessageQueueListenOptions, } from "@fedify/fedify"; import type { Sql } from "postgres"; import type { JSONValue, Parameter, Sql } from "postgres"; import postgres from "postgres"; import { driverSerializesJson } from "./utils.ts"; /** * Options for the PostgreSQL message queue. Loading Loading @@ -61,6 +62,7 @@ export class PostgresMessageQueue implements MessageQueue { readonly #channelName: string; readonly #pollIntervalMs: number; #initialized: boolean; #driverSerializesJson = false; constructor( // deno-lint-ignore ban-types Loading @@ -86,7 +88,7 @@ export class PostgresMessageQueue implements MessageQueue { await this.#sql` INSERT INTO ${this.#sql(this.#tableName)} (message, delay) VALUES ( (${{ message } as unknown as string}::jsonb) -> 'message', ${this.#json(message)}, ${delay.toString()} ); `; Loading Loading @@ -181,6 +183,7 @@ export class PostgresMessageQueue implements MessageQueue { throw e; } } this.#driverSerializesJson = await driverSerializesJson(this.#sql); this.#initialized = true; } Loading @@ -190,6 +193,11 @@ export class PostgresMessageQueue implements MessageQueue { async drop(): Promise<void> { await this.#sql`DROP TABLE IF EXISTS ${this.#sql(this.#tableName)};`; } #json(value: unknown): Parameter { if (this.#driverSerializesJson) return this.#sql.json(value as JSONValue); return this.#sql.json(JSON.stringify(value)); } } // cSpell: ignore typname src/utils.ts 0 → 100644 +7 −0 Original line number Diff line number Diff line import type { Sql } from "postgres"; // deno-lint-ignore ban-types export async function driverSerializesJson(sql: Sql<{}>): Promise<boolean> { const result = await sql`SELECT ${sql.json('{"foo":1}')}::jsonb AS test;`; return result[0].test === '{"foo":1}'; } Loading
README.md +7 −0 Original line number Diff line number Diff line Loading @@ -68,6 +68,13 @@ Changelog To be released. ### Version 0.2.2 Released on November 18, 2024. - Fixed a bug where binding parameters have not been properly escaped with some settings of Postgres.js. ### Version 0.2.1 Released on November 3, 2024. Loading
src/kv.ts +10 −2 Original line number Diff line number Diff line import type { KvKey, KvStore, KvStoreSetOptions } from "@fedify/fedify"; import type { Sql } from "postgres"; import type { JSONValue, Parameter, Sql } from "postgres"; import { driverSerializesJson } from "./utils.ts"; /** * Options for the PostgreSQL key-value store. Loading Loading @@ -39,6 +40,7 @@ export class PostgresKvStore implements KvStore { readonly #sql: Sql<{}>; readonly #tableName: string; #initialized: boolean; #driverSerializesJson = false; /** * Creates a new PostgreSQL key-value store. Loading Loading @@ -84,7 +86,7 @@ export class PostgresKvStore implements KvStore { INSERT INTO ${this.#sql(this.#tableName)} (key, value, ttl) VALUES ( ${key}, (${{ value } as unknown as string}::jsonb) -> 'value', ${this.#json(value)}, ${ttl} ) ON CONFLICT (key) Loading Loading @@ -116,6 +118,7 @@ export class PostgresKvStore implements KvStore { ttl interval ); `; this.#driverSerializesJson = await driverSerializesJson(this.#sql); this.#initialized = true; } Loading @@ -126,4 +129,9 @@ export class PostgresKvStore implements KvStore { async drop(): Promise<void> { await this.#sql`DROP TABLE IF EXISTS ${this.#sql(this.#tableName)};`; } #json(value: unknown): Parameter { if (this.#driverSerializesJson) return this.#sql.json(value as JSONValue); return this.#sql.json(JSON.stringify(value)); } }
src/mq.ts +10 −2 Original line number Diff line number Diff line Loading @@ -3,8 +3,9 @@ import type { MessageQueueEnqueueOptions, MessageQueueListenOptions, } from "@fedify/fedify"; import type { Sql } from "postgres"; import type { JSONValue, Parameter, Sql } from "postgres"; import postgres from "postgres"; import { driverSerializesJson } from "./utils.ts"; /** * Options for the PostgreSQL message queue. Loading Loading @@ -61,6 +62,7 @@ export class PostgresMessageQueue implements MessageQueue { readonly #channelName: string; readonly #pollIntervalMs: number; #initialized: boolean; #driverSerializesJson = false; constructor( // deno-lint-ignore ban-types Loading @@ -86,7 +88,7 @@ export class PostgresMessageQueue implements MessageQueue { await this.#sql` INSERT INTO ${this.#sql(this.#tableName)} (message, delay) VALUES ( (${{ message } as unknown as string}::jsonb) -> 'message', ${this.#json(message)}, ${delay.toString()} ); `; Loading Loading @@ -181,6 +183,7 @@ export class PostgresMessageQueue implements MessageQueue { throw e; } } this.#driverSerializesJson = await driverSerializesJson(this.#sql); this.#initialized = true; } Loading @@ -190,6 +193,11 @@ export class PostgresMessageQueue implements MessageQueue { async drop(): Promise<void> { await this.#sql`DROP TABLE IF EXISTS ${this.#sql(this.#tableName)};`; } #json(value: unknown): Parameter { if (this.#driverSerializesJson) return this.#sql.json(value as JSONValue); return this.#sql.json(JSON.stringify(value)); } } // cSpell: ignore typname
src/utils.ts 0 → 100644 +7 −0 Original line number Diff line number Diff line import type { Sql } from "postgres"; // deno-lint-ignore ban-types export async function driverSerializesJson(sql: Sql<{}>): Promise<boolean> { const result = await sql`SELECT ${sql.json('{"foo":1}')}::jsonb AS test;`; return result[0].test === '{"foo":1}'; }