@haathie/pgmb 0.2.10 → 0.2.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -422,7 +422,10 @@ const pgmb = new PgmbClient({
422
422
  headers: {
423
423
  // add a custom user-agent header
424
424
  'user-agent': 'my-service-client/1.0.0'
425
- }
425
+ },
426
+ // if payload is larger than 1KB, will be sent as a gzipped body
427
+ // with content-encoding: gzip header
428
+ minCompressSizeBytes: 1024,
426
429
  },
427
430
  // this function is called to obtain webhook URLs
428
431
  // for a given set of PGMB subscription IDs. These
package/lib/types.d.ts CHANGED
@@ -34,6 +34,19 @@ export type PgmbWebhookOpts<T extends IEventData> = {
34
34
  splitBy?: ISplitFn<T>;
35
35
  jsonifier?: JSONifier;
36
36
  serialiseEvent?(ev: IReadEvent, logger: Logger): SerialisedEvent;
37
+ /**
38
+ * Minimum size in bytes for the payload to be compressed.
39
+ * @default 1024
40
+ */
41
+ minCompressSizeBytes?: number;
42
+ /**
43
+ * Compress the webhook payload before sending.
44
+ * By default, uses gzip compression via the `zlib` library.
45
+ */
46
+ compress?(data: Uint8Array | string): Promise<{
47
+ data: Uint8Array | string;
48
+ contentEncoding: string;
49
+ }>;
37
50
  };
38
51
  export interface IEventData {
39
52
  topic: string;
@@ -3,4 +3,4 @@ import type { IEventData, IEventHandler, PgmbWebhookOpts } from './types.ts';
3
3
  * Create a handler that sends events to a webhook URL via HTTP POST.
4
4
  * @param url Where to send the webhook requests
5
5
  */
6
- export declare function createWebhookHandler<T extends IEventData>({ timeoutMs, headers, retryOpts, jsonifier, serialiseEvent }: Partial<PgmbWebhookOpts<T>>): IEventHandler;
6
+ export declare function createWebhookHandler<T extends IEventData>({ timeoutMs, headers, retryOpts, jsonifier, serialiseEvent, minCompressSizeBytes, compress }: Partial<PgmbWebhookOpts<T>>): IEventHandler;
@@ -1,6 +1,10 @@
1
1
  import assert from 'node:assert';
2
2
  import { createHash } from 'node:crypto';
3
+ import { promisify } from 'node:util';
4
+ import { gzip } from 'node:zlib';
3
5
  import { createRetryHandler } from "./retry-handler.js";
6
+ import { getEnvNumber } from "./utils.js";
7
+ const gzipPromise = promisify(gzip);
4
8
  /**
5
9
  * Create a handler that sends events to a webhook URL via HTTP POST.
6
10
  * @param url Where to send the webhook requests
@@ -8,7 +12,7 @@ import { createRetryHandler } from "./retry-handler.js";
8
12
  export function createWebhookHandler({ timeoutMs = 5_000, headers, retryOpts = {
9
13
  // retry after 5 minutes, then after 30 minutes
10
14
  retriesS: [5 * 60, 30 * 60]
11
- }, jsonifier = JSON, serialiseEvent = createSimpleSerialiser(jsonifier) }) {
15
+ }, jsonifier = JSON, serialiseEvent = createSimpleSerialiser(jsonifier), minCompressSizeBytes = getEnvNumber('PGMB_WEBHOOK_MIN_COMPRESS_SIZE_BYTES', 1024), compress = gzipCompress }) {
12
16
  const handler = async (ev, { logger, extra }) => {
13
17
  assert(typeof extra === 'object'
14
18
  && extra !== null
@@ -19,14 +23,18 @@ export function createWebhookHandler({ timeoutMs = 5_000, headers, retryOpts = {
19
23
  const idempotencyKey = getIdempotencyKeyHeader(ev);
20
24
  logger = logger.child({ idempotencyKey });
21
25
  const { body, contentType } = serialiseEvent(ev, logger);
26
+ const { data: compBody, contentEncoding } = body.length >= minCompressSizeBytes
27
+ ? await compress(body)
28
+ : { data: body };
22
29
  const { status, statusText, body: res } = await fetch(url, {
23
30
  method: 'POST',
24
31
  headers: {
25
32
  'content-type': contentType,
26
33
  'idempotency-key': idempotencyKey,
34
+ ...(contentEncoding ? { 'content-encoding': contentEncoding } : {}),
27
35
  ...headers
28
36
  },
29
- body,
37
+ body: compBody,
30
38
  redirect: 'manual',
31
39
  signal: AbortSignal.timeout(timeoutMs)
32
40
  });
@@ -63,3 +71,9 @@ function createSimpleSerialiser(jsonifier) {
63
71
  contentType: 'application/json'
64
72
  });
65
73
  }
74
+ async function gzipCompress(data) {
75
+ return {
76
+ data: await gzipPromise(data),
77
+ contentEncoding: 'gzip'
78
+ };
79
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@haathie/pgmb",
3
- "version": "0.2.10",
3
+ "version": "0.2.12",
4
4
  "description": "PG message broker, with a type-safe typescript client with built-in webhook & SSE support.",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org",
@@ -64,11 +64,13 @@ EXECUTE FUNCTION manage_cron_jobs_trigger_fn();
64
64
  DO $$
65
65
  BEGIN
66
66
  IF (
67
- SELECT EXISTS (
68
- SELECT 1
69
- FROM pg_available_extensions
70
- WHERE name = 'pg_cron'
71
- )
67
+ SELECT true
68
+ FROM pg_available_extensions
69
+ WHERE name = 'pg_cron'
70
+ ) AND (
71
+ -- ensure the current database is where pg_cron can be installed
72
+ current_database()
73
+ = coalesce(current_setting('cron.database_name', true), 'postgres')
72
74
  ) THEN
73
75
  CREATE EXTENSION IF NOT EXISTS pg_cron;
74
76
  INSERT INTO config(id, value) VALUES ('use_pg_cron', 'true');
package/sql/pgmb.sql CHANGED
@@ -903,11 +903,13 @@ EXECUTE FUNCTION manage_cron_jobs_trigger_fn();
903
903
  DO $$
904
904
  BEGIN
905
905
  IF (
906
- SELECT EXISTS (
907
- SELECT 1
908
- FROM pg_available_extensions
909
- WHERE name = 'pg_cron'
910
- )
906
+ SELECT true
907
+ FROM pg_available_extensions
908
+ WHERE name = 'pg_cron'
909
+ ) AND (
910
+ -- ensure the current database is where pg_cron can be installed
911
+ current_database()
912
+ = coalesce(current_setting('cron.database_name', true), 'postgres')
911
913
  ) THEN
912
914
  CREATE EXTENSION IF NOT EXISTS pg_cron;
913
915
  INSERT INTO config(id, value) VALUES ('use_pg_cron', 'true');