@managemint-solutions/sdk 0.9.0 → 0.16.0

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.
Files changed (49) hide show
  1. package/dist/audit/index.d.ts +15 -0
  2. package/dist/audit/index.js +37 -14
  3. package/dist/audit/index.js.map +1 -1
  4. package/dist/billing/dto.d.ts +33 -0
  5. package/dist/billing/dto.js +71 -0
  6. package/dist/billing/dto.js.map +1 -0
  7. package/dist/billing/index.d.ts +35 -0
  8. package/dist/billing/index.js +115 -0
  9. package/dist/billing/index.js.map +1 -0
  10. package/dist/client.d.ts +8 -0
  11. package/dist/client.js +12 -0
  12. package/dist/client.js.map +1 -1
  13. package/dist/index.d.ts +7 -0
  14. package/dist/index.js +7 -0
  15. package/dist/index.js.map +1 -1
  16. package/dist/nest/index.d.ts +11 -0
  17. package/dist/nest/index.js +17 -1
  18. package/dist/nest/index.js.map +1 -1
  19. package/dist/notifications/dto.d.ts +10 -0
  20. package/dist/notifications/dto.js +63 -0
  21. package/dist/notifications/dto.js.map +1 -0
  22. package/dist/notifications/index.d.ts +139 -0
  23. package/dist/notifications/index.js +354 -0
  24. package/dist/notifications/index.js.map +1 -0
  25. package/dist/organizations/dto.d.ts +62 -0
  26. package/dist/organizations/dto.js +445 -0
  27. package/dist/organizations/dto.js.map +1 -0
  28. package/dist/organizations/index.d.ts +72 -0
  29. package/dist/organizations/index.js +221 -0
  30. package/dist/organizations/index.js.map +1 -0
  31. package/dist/permissions/dto.d.ts +27 -0
  32. package/dist/permissions/dto.js +215 -0
  33. package/dist/permissions/dto.js.map +1 -0
  34. package/dist/permissions/index.d.ts +36 -0
  35. package/dist/permissions/index.js +110 -0
  36. package/dist/permissions/index.js.map +1 -0
  37. package/dist/service-client/index.d.ts +72 -0
  38. package/dist/service-client/index.js +119 -0
  39. package/dist/service-client/index.js.map +1 -0
  40. package/dist/users/dto.d.ts +48 -0
  41. package/dist/users/dto.js +267 -0
  42. package/dist/users/dto.js.map +1 -0
  43. package/dist/users/index.d.ts +38 -0
  44. package/dist/users/index.js +144 -0
  45. package/dist/users/index.js.map +1 -0
  46. package/dist/webhook-events/index.d.ts +65 -0
  47. package/dist/webhook-events/index.js +109 -0
  48. package/dist/webhook-events/index.js.map +1 -0
  49. package/package.json +2 -2
@@ -0,0 +1,144 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.UsersResource = void 0;
18
+ const enum_1 = require("@managemint-solutions/entities/audit-trail/enum");
19
+ const audit_1 = require("../audit");
20
+ const errors_1 = require("../errors");
21
+ __exportStar(require("./dto"), exports);
22
+ const USERS_TABLE = {
23
+ table: 'users',
24
+ entityType: enum_1.AuditTrailEntityType.USER,
25
+ };
26
+ const USER_LIST_SELECT = 'mms_id, name, surname, email, active, created_at, profile_image, last_logged_in';
27
+ class UsersResource {
28
+ supabase;
29
+ auth;
30
+ table;
31
+ constructor(supabase, auth, audit) {
32
+ this.supabase = supabase;
33
+ this.auth = auth;
34
+ this.table = (0, audit_1.auditedTable)(supabase, auth, audit, USERS_TABLE);
35
+ }
36
+ async list(query) {
37
+ const page = query.page;
38
+ const pageSize = query.page_size;
39
+ const offset = (page - 1) * pageSize;
40
+ const trimmedSearch = query.search?.trim();
41
+ // `order`/`range` return `this`, so the builder stays a filter builder and the conditional
42
+ // filters below can be reassigned onto it without a cast.
43
+ let usersQuery = this.supabase
44
+ .from('users')
45
+ .select(USER_LIST_SELECT, { count: 'estimated' })
46
+ .eq('organization_id', this.auth.organization_id)
47
+ .order('created_at', { ascending: false })
48
+ .range(offset, offset + pageSize - 1);
49
+ // No filter shows everyone: inactive users must stay reachable so they can
50
+ // be reactivated from their detail page.
51
+ if (query.active_in && query.active_in.length > 0) {
52
+ usersQuery = usersQuery.in('active', query.active_in);
53
+ }
54
+ if (trimmedSearch) {
55
+ const escapedSearch = trimmedSearch.replace(/,/g, '\\,');
56
+ usersQuery = usersQuery.or(`name.ilike.%${escapedSearch}%,surname.ilike.%${escapedSearch}%,email.ilike.%${escapedSearch}%`);
57
+ }
58
+ const { data, error, count } = await usersQuery;
59
+ if (error)
60
+ throw (0, errors_1.mapPostgrestError)(error);
61
+ const totalEstimated = count ?? 0;
62
+ const totalPages = totalEstimated > 0 ? Math.ceil(totalEstimated / pageSize) : 0;
63
+ return {
64
+ results: (data ?? []),
65
+ page,
66
+ per_page: pageSize,
67
+ count: totalEstimated,
68
+ total_pages: totalPages,
69
+ has_next_page: page < totalPages,
70
+ has_previous_page: page > 1,
71
+ };
72
+ }
73
+ async getRow(userId) {
74
+ const { data, error } = await this.supabase
75
+ .from('users')
76
+ .select('*')
77
+ .eq('mms_id', userId)
78
+ .eq('organization_id', this.auth.organization_id)
79
+ .single();
80
+ if (error)
81
+ throw (0, errors_1.mapPostgrestError)(error);
82
+ return data;
83
+ }
84
+ /**
85
+ * The public profile behind a `*_by` / `manager_id` column. `user_profiles` is a
86
+ * `security_invoker = off` view granted to `authenticated`, so this runs on the caller's own
87
+ * client — it needs no service role.
88
+ */
89
+ async identityById(userId) {
90
+ if (!userId)
91
+ return null;
92
+ const { data, error } = await this.supabase
93
+ .from('user_profiles')
94
+ .select('*')
95
+ .eq('mms_id', userId)
96
+ .single();
97
+ if (error)
98
+ throw (0, errors_1.mapPostgrestError)(error);
99
+ return data;
100
+ }
101
+ /** Seats in use. Counts rows rather than fetching them. */
102
+ async activeCount() {
103
+ const { count, error } = await this.supabase
104
+ .from('users')
105
+ .select('mms_id', { count: 'exact', head: true })
106
+ .eq('organization_id', this.auth.organization_id)
107
+ .eq('active', true);
108
+ if (error)
109
+ throw (0, errors_1.mapPostgrestError)(error);
110
+ return count ?? 0;
111
+ }
112
+ async isActive(userId) {
113
+ const { data, error } = await this.supabase
114
+ .from('users')
115
+ .select('active')
116
+ .eq('mms_id', userId)
117
+ .eq('organization_id', this.auth.organization_id)
118
+ .single();
119
+ if (error)
120
+ throw (0, errors_1.mapPostgrestError)(error);
121
+ return data.active;
122
+ }
123
+ async update(userId, patch) {
124
+ await this.table.update(userId, {
125
+ ...patch,
126
+ updated_at: new Date().toISOString(),
127
+ last_updated_by: this.auth.mms_id,
128
+ });
129
+ return this.getRow(userId);
130
+ }
131
+ /** `active` is not an archive flag, so a deactivation is recorded as a plain UPDATE. */
132
+ async setActive(userId, active) {
133
+ return this.update(userId, { active });
134
+ }
135
+ /**
136
+ * Stamps who created a user. Runs on the service client during signup: the row is written by
137
+ * the `on_auth_user_created` trigger, so there is nothing to attribute it to until afterwards.
138
+ */
139
+ async stampCreatedBy(userId, createdBy) {
140
+ return this.table.update(userId, { created_by: createdBy });
141
+ }
142
+ }
143
+ exports.UsersResource = UsersResource;
144
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/users/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,0EAAuF;AAGvF,oCAMkB;AAElB,sCAA8C;AAG9C,wCAAsB;AAEtB,MAAM,WAAW,GAAG;IAClB,KAAK,EAAE,OAAO;IACd,UAAU,EAAE,2BAAoB,CAAC,IAAI;CAC7B,CAAC;AAEX,MAAM,gBAAgB,GACpB,iFAA0F,CAAC;AAU7F,MAAa,aAAa;IAIL;IACA;IAJF,KAAK,CAAe;IAErC,YACmB,QAA6B,EAC7B,IAAgB,EACjC,KAAoB;QAFH,aAAQ,GAAR,QAAQ,CAAqB;QAC7B,SAAI,GAAJ,IAAI,CAAY;QAGjC,IAAI,CAAC,KAAK,GAAG,IAAA,oBAAY,EAAC,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC;IAChE,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,KAAuB;QAChC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;QACxB,MAAM,QAAQ,GAAG,KAAK,CAAC,SAAS,CAAC;QACjC,MAAM,MAAM,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC;QACrC,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC;QAE3C,2FAA2F;QAC3F,0DAA0D;QAC1D,IAAI,UAAU,GAAG,IAAI,CAAC,QAAQ;aAC3B,IAAI,CAAC,OAAO,CAAC;aACb,MAAM,CAAC,gBAAgB,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC;aAChD,EAAE,CAAC,iBAAiB,EAAE,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC;aAChD,KAAK,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;aACzC,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,CAAC,CAAC,CAAC;QAExC,2EAA2E;QAC3E,yCAAyC;QACzC,IAAI,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAClD,UAAU,GAAG,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;QACxD,CAAC;QAED,IAAI,aAAa,EAAE,CAAC;YAClB,MAAM,aAAa,GAAG,aAAa,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YACzD,UAAU,GAAG,UAAU,CAAC,EAAE,CACxB,eAAe,aAAa,oBAAoB,aAAa,kBAAkB,aAAa,GAAG,CAChG,CAAC;QACJ,CAAC;QAED,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,MAAM,UAAU,CAAC;QAChD,IAAI,KAAK;YAAE,MAAM,IAAA,0BAAiB,EAAC,KAAK,CAAC,CAAC;QAE1C,MAAM,cAAc,GAAG,KAAK,IAAI,CAAC,CAAC;QAClC,MAAM,UAAU,GAAG,cAAc,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAEjF,OAAO;YACL,OAAO,EAAE,CAAC,IAAI,IAAI,EAAE,CAA6B;YACjD,IAAI;YACJ,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,cAAc;YACrB,WAAW,EAAE,UAAU;YACvB,aAAa,EAAE,IAAI,GAAG,UAAU;YAChC,iBAAiB,EAAE,IAAI,GAAG,CAAC;SAC5B,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,MAAc;QACzB,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,QAAQ;aACxC,IAAI,CAAC,OAAO,CAAC;aACb,MAAM,CAAC,GAAG,CAAC;aACX,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC;aACpB,EAAE,CAAC,iBAAiB,EAAE,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC;aAChD,MAAM,EAAE,CAAC;QACZ,IAAI,KAAK;YAAE,MAAM,IAAA,0BAAiB,EAAC,KAAK,CAAC,CAAC;QAE1C,OAAO,IAA0B,CAAC;IACpC,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,YAAY,CAAC,MAAsB;QACvC,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QAEzB,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,QAAQ;aACxC,IAAI,CAAC,eAAe,CAAC;aACrB,MAAM,CAAC,GAAG,CAAC;aACX,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC;aACpB,MAAM,EAAE,CAAC;QACZ,IAAI,KAAK;YAAE,MAAM,IAAA,0BAAiB,EAAC,KAAK,CAAC,CAAC;QAE1C,OAAO,IAA+B,CAAC;IACzC,CAAC;IAED,2DAA2D;IAC3D,KAAK,CAAC,WAAW;QACf,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,QAAQ;aACzC,IAAI,CAAC,OAAO,CAAC;aACb,MAAM,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;aAChD,EAAE,CAAC,iBAAiB,EAAE,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC;aAChD,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACtB,IAAI,KAAK;YAAE,MAAM,IAAA,0BAAiB,EAAC,KAAK,CAAC,CAAC;QAE1C,OAAO,KAAK,IAAI,CAAC,CAAC;IACpB,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,MAAc;QAC3B,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,QAAQ;aACxC,IAAI,CAAC,OAAO,CAAC;aACb,MAAM,CAAC,QAAQ,CAAC;aAChB,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC;aACpB,EAAE,CAAC,iBAAiB,EAAE,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC;aAChD,MAAM,EAAE,CAAC;QACZ,IAAI,KAAK;YAAE,MAAM,IAAA,0BAAiB,EAAC,KAAK,CAAC,CAAC;QAE1C,OAAQ,IAA4B,CAAC,MAAM,CAAC;IAC9C,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,MAAc,EAAE,KAAe;QAC1C,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE;YAC9B,GAAG,KAAK;YACR,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACpC,eAAe,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM;SAClC,CAAC,CAAC;QAEH,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC7B,CAAC;IAED,wFAAwF;IACxF,KAAK,CAAC,SAAS,CAAC,MAAc,EAAE,MAAe;QAC7C,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;IACzC,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,cAAc,CAAC,MAAc,EAAE,SAAwB;QAC3D,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC,CAAC;IAC9D,CAAC;CACF;AApID,sCAoIC"}
@@ -0,0 +1,65 @@
1
+ import type { TypedSupabaseClient } from '../client';
2
+ import { SupabaseClientError } from '../errors';
3
+ /** The two provider event logs. Both have the same shape and the same claim protocol. */
4
+ export type WebhookEventsTable = 'paystack_webhook_events' | 'resend_webhook_events';
5
+ export type WebhookEventRow = {
6
+ mms_id: string;
7
+ processing_status: string;
8
+ };
9
+ /** What a claim attempt resolved to. `claimed` is the only outcome that runs a handler. */
10
+ export type ClaimOutcome = {
11
+ kind: 'claimed';
12
+ mms_id: string;
13
+ } | {
14
+ kind: 'duplicate';
15
+ existing: WebhookEventRow;
16
+ } | {
17
+ kind: 'vanished';
18
+ };
19
+ /**
20
+ * The provider event logs — `paystack_webhook_events` and `resend_webhook_events`. Every policy
21
+ * on both is `false` for `authenticated`, including READ: the raw payloads are never exposed to
22
+ * end users, and an inbound webhook has no caller to run as.
23
+ *
24
+ * Deliberately unaudited. These tables *are* an append-only log with their own
25
+ * `processing_status` lifecycle, so an audit row per delivery would log the log. The domain
26
+ * writes the handlers make off the back of them are audited as usual.
27
+ */
28
+ export declare class WebhookEventsResource {
29
+ private readonly supabase;
30
+ private readonly table;
31
+ constructor(supabase: TypedSupabaseClient, table: WebhookEventsTable);
32
+ /**
33
+ * The dedup test. One insert, straight to `processing` — there is no useful window in which
34
+ * the row would sit at `received`.
35
+ *
36
+ * The unique index is partial (`where processing_status <> 'ignored_duplicate'`), so at
37
+ * insert time it cannot tell a failed key from a processed one. A unique violation resolves
38
+ * to the canonical row and the caller decides what it means; `vanished` means the row that
39
+ * caused the violation is already gone, and the caller should let the provider redeliver
40
+ * rather than guess.
41
+ */
42
+ claim(payload: Record<string, unknown>, eventKey: string): Promise<ClaimOutcome>;
43
+ /** The canonical row for a key, ignoring the duplicate log rows that never collide. */
44
+ findByEventKey(eventKey: string): Promise<WebhookEventRow | null>;
45
+ /**
46
+ * Reclaims a `failed` row for reprocessing, clearing the previous failure. Guarded on the
47
+ * row still being failed, because another redelivery may have reclaimed it first — resolves
48
+ * to null when it did.
49
+ *
50
+ * This is the single most important detail in the pipeline: swallowing a redelivery of a
51
+ * failed key loses the event forever.
52
+ */
53
+ takeOverFailed(eventId: string, patch: Record<string, unknown>): Promise<WebhookEventRow | null>;
54
+ /**
55
+ * Duplicate deliveries are recorded rather than dropped. The partial unique index excludes
56
+ * `ignored_duplicate`, so these rows never collide with each other.
57
+ */
58
+ logIgnoredDuplicate(payload: Record<string, unknown>): Promise<void>;
59
+ markProcessed(eventId: string, patch: Record<string, unknown>): Promise<void>;
60
+ /**
61
+ * Never throws: the handler's own failure is the one the caller needs to report, and a
62
+ * webhook the provider will redeliver is a better outcome than an error about the log.
63
+ */
64
+ markFailed(eventId: string, patch: Record<string, unknown>, onError?: (error: SupabaseClientError) => void): Promise<void>;
65
+ }
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WebhookEventsResource = void 0;
4
+ const errors_1 = require("../errors");
5
+ const UNIQUE_VIOLATION = '23505';
6
+ /**
7
+ * The provider event logs — `paystack_webhook_events` and `resend_webhook_events`. Every policy
8
+ * on both is `false` for `authenticated`, including READ: the raw payloads are never exposed to
9
+ * end users, and an inbound webhook has no caller to run as.
10
+ *
11
+ * Deliberately unaudited. These tables *are* an append-only log with their own
12
+ * `processing_status` lifecycle, so an audit row per delivery would log the log. The domain
13
+ * writes the handlers make off the back of them are audited as usual.
14
+ */
15
+ class WebhookEventsResource {
16
+ supabase;
17
+ table;
18
+ constructor(supabase, table) {
19
+ this.supabase = supabase;
20
+ this.table = table;
21
+ }
22
+ /**
23
+ * The dedup test. One insert, straight to `processing` — there is no useful window in which
24
+ * the row would sit at `received`.
25
+ *
26
+ * The unique index is partial (`where processing_status <> 'ignored_duplicate'`), so at
27
+ * insert time it cannot tell a failed key from a processed one. A unique violation resolves
28
+ * to the canonical row and the caller decides what it means; `vanished` means the row that
29
+ * caused the violation is already gone, and the caller should let the provider redeliver
30
+ * rather than guess.
31
+ */
32
+ async claim(payload, eventKey) {
33
+ const { data, error } = await this.supabase
34
+ .from(this.table)
35
+ .insert(payload)
36
+ .select('mms_id')
37
+ .single();
38
+ if (!error) {
39
+ return { kind: 'claimed', mms_id: data.mms_id };
40
+ }
41
+ if (error.code !== UNIQUE_VIOLATION)
42
+ throw (0, errors_1.mapPostgrestError)(error);
43
+ const existing = await this.findByEventKey(eventKey);
44
+ return existing ? { kind: 'duplicate', existing } : { kind: 'vanished' };
45
+ }
46
+ /** The canonical row for a key, ignoring the duplicate log rows that never collide. */
47
+ async findByEventKey(eventKey) {
48
+ const { data, error } = await this.supabase
49
+ .from(this.table)
50
+ .select('mms_id, processing_status')
51
+ .eq('event_key', eventKey)
52
+ .neq('processing_status', 'ignored_duplicate')
53
+ .maybeSingle();
54
+ if (error)
55
+ throw (0, errors_1.mapPostgrestError)(error);
56
+ return (data ?? null);
57
+ }
58
+ /**
59
+ * Reclaims a `failed` row for reprocessing, clearing the previous failure. Guarded on the
60
+ * row still being failed, because another redelivery may have reclaimed it first — resolves
61
+ * to null when it did.
62
+ *
63
+ * This is the single most important detail in the pipeline: swallowing a redelivery of a
64
+ * failed key loses the event forever.
65
+ */
66
+ async takeOverFailed(eventId, patch) {
67
+ const { data, error } = await this.supabase
68
+ .from(this.table)
69
+ .update(patch)
70
+ .eq('mms_id', eventId)
71
+ .eq('processing_status', 'failed')
72
+ .select('mms_id')
73
+ .maybeSingle();
74
+ if (error)
75
+ throw (0, errors_1.mapPostgrestError)(error);
76
+ return (data ?? null);
77
+ }
78
+ /**
79
+ * Duplicate deliveries are recorded rather than dropped. The partial unique index excludes
80
+ * `ignored_duplicate`, so these rows never collide with each other.
81
+ */
82
+ async logIgnoredDuplicate(payload) {
83
+ const { error } = await this.supabase.from(this.table).insert(payload);
84
+ if (error)
85
+ throw (0, errors_1.mapPostgrestError)(error);
86
+ }
87
+ async markProcessed(eventId, patch) {
88
+ const { error } = await this.supabase
89
+ .from(this.table)
90
+ .update(patch)
91
+ .eq('mms_id', eventId);
92
+ if (error)
93
+ throw (0, errors_1.mapPostgrestError)(error);
94
+ }
95
+ /**
96
+ * Never throws: the handler's own failure is the one the caller needs to report, and a
97
+ * webhook the provider will redeliver is a better outcome than an error about the log.
98
+ */
99
+ async markFailed(eventId, patch, onError) {
100
+ const { error } = await this.supabase
101
+ .from(this.table)
102
+ .update(patch)
103
+ .eq('mms_id', eventId);
104
+ if (error)
105
+ onError?.((0, errors_1.mapPostgrestError)(error));
106
+ }
107
+ }
108
+ exports.WebhookEventsResource = WebhookEventsResource;
109
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/webhook-events/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@managemint-solutions/sdk",
3
- "version": "0.9.0",
3
+ "version": "0.16.0",
4
4
  "description": "Typed Supabase data-access SDK for ManageMint Solutions",
5
5
  "license": "UNLICENSED",
6
6
  "author": "Scott Bebington <scottbebington@gmail.com>",
@@ -40,7 +40,7 @@
40
40
  "testEnvironment": "node"
41
41
  },
42
42
  "dependencies": {
43
- "@managemint-solutions/entities": "^1.1.43"
43
+ "@managemint-solutions/entities": "^1.2.0"
44
44
  },
45
45
  "peerDependencies": {
46
46
  "@nestjs/common": "^11.0.0",