From b80e252d6d613978426a92d038c4d77680aa170c Mon Sep 17 00:00:00 2001 From: CodeMash Date: Thu, 15 Oct 2026 14:16:43 +0300 Subject: [PATCH] =?UTF-8?q?feat(payments):=20useGetPaymentsWebhookLogQuery?= =?UTF-8?q?=20=E2=80=94=20the=20received=20payment=20webhooks=20of=20a=20p?= =?UTF-8?q?roject?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit hub.payments now covers all 17 core SDK payments methods (getPaymentsWebhookLog was missing; typegen coverage matrix, gateway campaign audit/payments item 8). Provides PaymentIntegrations, so it refetches when an integration changes. Co-Authored-By: Claude Opus 5.5 --- README.md | 1 + src/hooks/hub/payments.ts | 14 ++++++++-- tests/payments.test.ts | 57 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 tests/payments.test.ts diff --git a/README.md b/README.md index 27874b6..97f8ed5 100644 --- a/README.md +++ b/README.md @@ -232,6 +232,7 @@ The module enable / disable hooks were always mutations, so nothing changes in y | `useEnableFilesMutation`, `useDisableFilesMutation` | `PUT /{version}/files/enable\|disable` | invalidates `Files` | | `useEnableLoggingMutation`, `useDisableLoggingMutation` | `PUT /{version}/logs/enable\|disable` | invalidates `Logs` | | `useEnablePaymentsMutation`, `useDisablePaymentsMutation` | `PUT /{version}/payments/enable\|disable` | invalidates `Payments` | +| `useGetPaymentsWebhookLogQuery` | `GET /{version}/payments/webhooks/log` | provides `PaymentIntegrations` | | `useEnableMembershipMutation`, `useDisableMembershipMutation` | `PUT /{version}/membership/enable\|disable` | invalidates `Membership` | | `useEnableEmailMutation`, `useDisableEmailMutation` | `PUT /{version}/notifications/email/enable\|disable` | invalidates `Emails` | | `useEnableSmsMutation`, `useDisableSmsMutation` | `PUT /{version}/notifications/sms/enable\|disable` | invalidates `Sms` | diff --git a/src/hooks/hub/payments.ts b/src/hooks/hub/payments.ts index 5116ae3..6fe7191 100644 --- a/src/hooks/hub/payments.ts +++ b/src/hooks/hub/payments.ts @@ -1,4 +1,4 @@ -// AUTO-GENERATED — full coverage of `norbix.hub.payments` (16 endpoints). +// AUTO-GENERATED — full coverage of `norbix.hub.payments` (17 endpoints). // Synced from the norbix core SDK surface. Re-run the hook sync to refresh. import type { Norbix } from '@norbix.ai/ts'; @@ -21,9 +21,10 @@ type GetPaymentsIntegration = Norbix['hub']['payments']['getPaymentsIntegration' type GetPaymentsIntegrations = Norbix['hub']['payments']['getPaymentsIntegrations']; type SavePaymentsIntegration = Norbix['hub']['payments']['savePaymentsIntegration']; type TestPaymentsIntegration = Norbix['hub']['payments']['testPaymentsIntegration']; +type GetPaymentsWebhookLog = Norbix['hub']['payments']['getPaymentsWebhookLog']; /** - * `hub.payments` — 16 endpoints, 1:1 with the core SDK. + * `hub.payments` — 17 endpoints, 1:1 with the core SDK. */ export const hubPayments = (b: Builder) => ({ disablePayments: b.mutation, Arg>({ @@ -105,4 +106,13 @@ export const hubPayments = (b: Builder) => ({ query: (args) => (norbix) => norbix.hub.payments.testPaymentsIntegration(args), invalidatesTags: ['PaymentIntegrations'], }), + + // The received payment webhooks of the project (newest first). Tagged + // 'PaymentIntegrations' so it refetches when an integration changes; it is a + // log the gateway writes as callbacks arrive, so callers poll it + // (pollingInterval). + getPaymentsWebhookLog: b.query, Arg>({ + query: (args) => (norbix) => norbix.hub.payments.getPaymentsWebhookLog(args), + providesTags: ['PaymentIntegrations'], + }), }); diff --git a/tests/payments.test.ts b/tests/payments.test.ts new file mode 100644 index 0000000..d63cfa8 --- /dev/null +++ b/tests/payments.test.ts @@ -0,0 +1,57 @@ +import { describe, expect, it } from 'vitest'; + +import { hubPayments } from '../src/hooks/hub/payments.js'; + +/** + * `hub.payments` hooks (gateway campaign audit/payments, item 8). Same fake + * builder and fake client as the files tests: the hooks are a 1:1 wrapper of + * the core SDK, so "it reached the right SDK method with my arguments" and the + * cache tags are the whole contract. + */ +function fakeBuilder() { + return { + query: (def: Record) => ({ ...def, __kind: 'query' }), + mutation: (def: Record) => ({ ...def, __kind: 'mutation' }), + } as never; +} + +type Def = { + __kind: 'query' | 'mutation'; + query: (args: unknown) => (norbix: unknown) => unknown; + providesTags?: unknown; + invalidatesTags?: unknown; +}; + +function fakeNorbix() { + const calls: Array<{ method: string; args: unknown }> = []; + const payments = new Proxy( + {}, + { + get: (_t, name: string) => (args: unknown) => { + calls.push({ method: `hub.${name}`, args }); + return Promise.resolve({ ok: true }); + }, + }, + ); + return { calls, client: { hub: { payments } } }; +} + +describe('hubPayments', () => { + const endpoints = hubPayments(fakeBuilder()) as unknown as Record; + + it('covers all 17 hub Payments endpoints of the core SDK', () => { + expect(Object.keys(endpoints)).toHaveLength(17); + expect(endpoints).toHaveProperty('getPaymentsWebhookLog'); + }); + + it('getPaymentsWebhookLog is a query that reaches the SDK method with the caller args', async () => { + const { calls, client } = fakeNorbix(); + const args = { integrationId: 'int_stripe', limit: 20 }; + + await endpoints.getPaymentsWebhookLog.query(args)(client); + + expect(endpoints.getPaymentsWebhookLog.__kind).toBe('query'); + expect(endpoints.getPaymentsWebhookLog.providesTags).toEqual(['PaymentIntegrations']); + expect(calls).toEqual([{ method: 'hub.getPaymentsWebhookLog', args }]); + }); +});