@managemint-solutions/sdk 0.8.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 (74) hide show
  1. package/README.md +73 -1
  2. package/dist/additional-details/index.d.ts +3 -1
  3. package/dist/additional-details/index.js +15 -28
  4. package/dist/additional-details/index.js.map +1 -1
  5. package/dist/audit/dto.d.ts +13 -0
  6. package/dist/audit/dto.js +90 -0
  7. package/dist/audit/dto.js.map +1 -0
  8. package/dist/audit/index.d.ts +104 -0
  9. package/dist/audit/index.js +308 -0
  10. package/dist/audit/index.js.map +1 -0
  11. package/dist/billing/dto.d.ts +33 -0
  12. package/dist/billing/dto.js +71 -0
  13. package/dist/billing/dto.js.map +1 -0
  14. package/dist/billing/index.d.ts +35 -0
  15. package/dist/billing/index.js +115 -0
  16. package/dist/billing/index.js.map +1 -0
  17. package/dist/client.d.ts +12 -0
  18. package/dist/client.js +23 -7
  19. package/dist/client.js.map +1 -1
  20. package/dist/clients/index.d.ts +3 -1
  21. package/dist/clients/index.js +25 -62
  22. package/dist/clients/index.js.map +1 -1
  23. package/dist/index.d.ts +8 -0
  24. package/dist/index.js +8 -0
  25. package/dist/index.js.map +1 -1
  26. package/dist/nest/index.d.ts +22 -0
  27. package/dist/nest/index.js +28 -1
  28. package/dist/nest/index.js.map +1 -1
  29. package/dist/notes/index.d.ts +3 -1
  30. package/dist/notes/index.js +16 -27
  31. package/dist/notes/index.js.map +1 -1
  32. package/dist/notifications/dto.d.ts +10 -0
  33. package/dist/notifications/dto.js +63 -0
  34. package/dist/notifications/dto.js.map +1 -0
  35. package/dist/notifications/index.d.ts +139 -0
  36. package/dist/notifications/index.js +354 -0
  37. package/dist/notifications/index.js.map +1 -0
  38. package/dist/organizations/dto.d.ts +62 -0
  39. package/dist/organizations/dto.js +445 -0
  40. package/dist/organizations/dto.js.map +1 -0
  41. package/dist/organizations/index.d.ts +72 -0
  42. package/dist/organizations/index.js +221 -0
  43. package/dist/organizations/index.js.map +1 -0
  44. package/dist/permissions/dto.d.ts +27 -0
  45. package/dist/permissions/dto.js +215 -0
  46. package/dist/permissions/dto.js.map +1 -0
  47. package/dist/permissions/index.d.ts +36 -0
  48. package/dist/permissions/index.js +110 -0
  49. package/dist/permissions/index.js.map +1 -0
  50. package/dist/projects/index.d.ts +3 -1
  51. package/dist/projects/index.js +25 -62
  52. package/dist/projects/index.js.map +1 -1
  53. package/dist/service-client/index.d.ts +72 -0
  54. package/dist/service-client/index.js +119 -0
  55. package/dist/service-client/index.js.map +1 -0
  56. package/dist/statuses/index.d.ts +3 -1
  57. package/dist/statuses/index.js +17 -28
  58. package/dist/statuses/index.js.map +1 -1
  59. package/dist/supporting-files/index.d.ts +3 -1
  60. package/dist/supporting-files/index.js +14 -20
  61. package/dist/supporting-files/index.js.map +1 -1
  62. package/dist/tasks/index.d.ts +3 -1
  63. package/dist/tasks/index.js +21 -50
  64. package/dist/tasks/index.js.map +1 -1
  65. package/dist/users/dto.d.ts +48 -0
  66. package/dist/users/dto.js +267 -0
  67. package/dist/users/dto.js.map +1 -0
  68. package/dist/users/index.d.ts +38 -0
  69. package/dist/users/index.js +144 -0
  70. package/dist/users/index.js.map +1 -0
  71. package/dist/webhook-events/index.d.ts +65 -0
  72. package/dist/webhook-events/index.js +109 -0
  73. package/dist/webhook-events/index.js.map +1 -0
  74. package/package.json +2 -2
@@ -0,0 +1,139 @@
1
+ import type { NotificationContent, NotificationEntity, NotificationSummary, NotificationUnreadCount } from '@managemint-solutions/entities/notifications';
2
+ import { NotificationChannel, NotificationStatus, type NotificationType } from '@managemint-solutions/entities/notifications/enum';
3
+ import type { MmsList } from '@managemint-solutions/entities/common';
4
+ import type { AuthContext } from '../auth';
5
+ import { type AuditedTable, type AuditResource } from '../audit';
6
+ import type { TypedSupabaseClient } from '../client';
7
+ import type { GetNotificationsDto } from './dto';
8
+ export * from './dto';
9
+ /** The outbox row a caller writes. `organization_id` is absent for auth mail, which precedes any tenant. */
10
+ export type CreateNotificationInput = {
11
+ created_by?: string | null;
12
+ organization_id?: string;
13
+ type: NotificationType;
14
+ channel: NotificationChannel;
15
+ template_id: string;
16
+ template_variables: Record<string, string>;
17
+ recipient_id?: string;
18
+ recipient_email?: string;
19
+ recipient_phone?: string;
20
+ };
21
+ export type CreatedNotification = NotificationEntity & {
22
+ organization_id: string | null;
23
+ provider_message_id: string | null;
24
+ };
25
+ /** The columns the queue worker needs to decide whether and how to send. */
26
+ export type QueuedNotification = {
27
+ mms_id: string;
28
+ organization_id: string | null;
29
+ status: NotificationStatus;
30
+ channel: NotificationChannel;
31
+ template_id: string | null;
32
+ template_variables: Record<string, string>;
33
+ recipient_email: string | null;
34
+ attempts: number;
35
+ sent_at: string | null;
36
+ deleted: boolean;
37
+ };
38
+ export type NotificationContentRow = {
39
+ mms_id: string;
40
+ organization_id: string | null;
41
+ channel: NotificationChannel;
42
+ provider_message_id: string | null;
43
+ rendered_content: Omit<NotificationContent, 'channel'> | null;
44
+ };
45
+ /**
46
+ * The recipient's own inbox. Every method is scoped to the caller by `recipient_id`, matching
47
+ * the RLS policies (`auth.uid() = recipient_id`) rather than by organization — a notification
48
+ * belongs to a person, not a tenant.
49
+ */
50
+ export declare class NotificationsResource {
51
+ private readonly supabase;
52
+ private readonly auth;
53
+ private readonly table;
54
+ constructor(supabase: TypedSupabaseClient, auth: AuthContext, audit: AuditResource);
55
+ list(query: GetNotificationsDto): Promise<MmsList<NotificationSummary>>;
56
+ getById(notificationId: string): Promise<NotificationEntity>;
57
+ unreadCount(): Promise<NotificationUnreadCount>;
58
+ /** Idempotent: re-reading an already read notification matches nothing and changes nothing. */
59
+ markRead(notificationId: string): Promise<void>;
60
+ /**
61
+ * Deliberately one statement and unaudited. It is a bulk update with no single row to key on,
62
+ * so auditing it would mean a select-then-loop and one audit row per unread notification —
63
+ * for the reader's own UI state, not an entity change.
64
+ */
65
+ markAllRead(): Promise<void>;
66
+ /**
67
+ * The ownership-checked read behind `GET /:id/content`. The caller decides whether to fall
68
+ * back to the provider; caching the result needs the service client's grant on
69
+ * `rendered_content`.
70
+ */
71
+ contentRow(notificationId: string): Promise<NotificationContentRow>;
72
+ /** Soft delete — the outbox row stays, flagged `deleted`, so the send record survives. */
73
+ remove(notificationId: string): Promise<void>;
74
+ }
75
+ /** How the outbox reaches an audited table once it knows which organization a row belongs to. */
76
+ export type OrganizationTableFactory = (organizationId: string) => AuditedTable;
77
+ /**
78
+ * The outbox and the queue worker's side of the table, on the service client: RLS reserves
79
+ * `notifications` INSERT and DELETE to the service role, and `authenticated` has no grant on
80
+ * `rendered_content`.
81
+ *
82
+ * Writes are audited against the row's own organization. Auth mail (signup confirmation,
83
+ * password recovery) has none — it precedes any tenant — and `audit_logs.organization_id` is
84
+ * not nullable, so those rows are written unaudited. Their lifecycle columns are the record.
85
+ */
86
+ export declare class NotificationsOutboxResource {
87
+ private readonly supabase;
88
+ private readonly tableFor;
89
+ constructor(supabase: TypedSupabaseClient, tableFor: OrganizationTableFactory);
90
+ private auditedFor;
91
+ private rawUpdate;
92
+ create(input: CreateNotificationInput): Promise<CreatedNotification>;
93
+ /**
94
+ * The outbox row behind a provider message id. The Resend webhook arrives knowing only that
95
+ * id, and needs the organization before it can attribute anything.
96
+ */
97
+ findByProviderMessageId(providerMessageId: string): Promise<Pick<NotificationContentRow, 'mms_id' | 'organization_id'> | null>;
98
+ /**
99
+ * Stamps a delivery rollup on first occurrence only. A provider that reports `delivered`
100
+ * twice must not move the timestamp, so the guard is the column still being null.
101
+ *
102
+ * Only the rollup columns are ever touched here — `status` belongs to the send lifecycle,
103
+ * not to what the provider reports afterwards.
104
+ */
105
+ stampRollup(notification: Pick<NotificationContentRow, 'mms_id' | 'organization_id'>, column: 'delivered_at' | 'delivery_failure_reason', value: string): Promise<void>;
106
+ /** The worker's load. Returns null when the row is gone rather than throwing — see `processQueuedNotification`. */
107
+ loadForDelivery(notificationId: string): Promise<QueuedNotification | null>;
108
+ /**
109
+ * Stamps a successful send. Guarded on `sent_at is null` so a duplicate delivery of the same
110
+ * queue message changes nothing instead of double-stamping — the email has already gone.
111
+ */
112
+ stampSent(notification: QueuedNotification, patch: {
113
+ providerMessageId: string | null;
114
+ attempts: number;
115
+ at: string;
116
+ }): Promise<void>;
117
+ /** Records an attempt, retiring the row when the caller says this was the last delivery. */
118
+ stampAttempt(notification: QueuedNotification, patch: {
119
+ attempts: number;
120
+ at: string;
121
+ failureReason: string;
122
+ terminal: boolean;
123
+ }): Promise<void>;
124
+ /** Retires a row nothing can rescue — an unknown template, no address, an unsupported channel. */
125
+ stampFailed(notification: QueuedNotification, patch: {
126
+ attempts: number;
127
+ at: string;
128
+ failureReason: string;
129
+ }): Promise<void>;
130
+ /**
131
+ * Caches the provider's rendered email on the row. Guarded on `rendered_content is null` so
132
+ * concurrent first-opens settle on one write.
133
+ */
134
+ cacheContent(notification: Pick<NotificationContentRow, 'mms_id' | 'organization_id'>, content: {
135
+ subject: string | null;
136
+ html: string | null;
137
+ }): Promise<void>;
138
+ }
139
+ export { NotificationChannel, NotificationStatus };
@@ -0,0 +1,354 @@
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.NotificationStatus = exports.NotificationChannel = exports.NotificationsOutboxResource = exports.NotificationsResource = void 0;
18
+ const enum_1 = require("@managemint-solutions/entities/notifications/enum");
19
+ Object.defineProperty(exports, "NotificationChannel", { enumerable: true, get: function () { return enum_1.NotificationChannel; } });
20
+ Object.defineProperty(exports, "NotificationStatus", { enumerable: true, get: function () { return enum_1.NotificationStatus; } });
21
+ const enum_2 = require("@managemint-solutions/entities/audit-trail/enum");
22
+ const audit_1 = require("../audit");
23
+ const errors_1 = require("../errors");
24
+ __exportStar(require("./dto"), exports);
25
+ // The public contract is the shared entities types; the casts at the returns declare the shape
26
+ // these select strings produce (the columns are defined in the api's supabase/migrations).
27
+ const NOTIFICATION_LIST_SELECT = `
28
+ mms_id,
29
+ created_at,
30
+ type,
31
+ channel,
32
+ status,
33
+ template_id,
34
+ recipient_email,
35
+ sent_at,
36
+ failed_at,
37
+ delivered_at,
38
+ read_at
39
+ `;
40
+ const NOTIFICATION_DETAIL_SELECT = `
41
+ mms_id,
42
+ created_at,
43
+ type,
44
+ channel,
45
+ status,
46
+ template_id,
47
+ template_variables,
48
+ recipient_email,
49
+ sent_at,
50
+ failed_at,
51
+ failure_reason,
52
+ provider,
53
+ delivered_at,
54
+ delivery_failure_reason,
55
+ read_at
56
+ `;
57
+ // What `create` hands back to the caller, which then publishes it to the queue.
58
+ const NOTIFICATION_CREATED_SELECT = `
59
+ mms_id,
60
+ organization_id,
61
+ created_at,
62
+ type,
63
+ channel,
64
+ status,
65
+ template_id,
66
+ template_variables,
67
+ recipient_email,
68
+ sent_at,
69
+ failed_at,
70
+ failure_reason,
71
+ provider,
72
+ provider_message_id,
73
+ delivered_at
74
+ `;
75
+ const NOTIFICATIONS_TABLE = {
76
+ table: 'notifications',
77
+ entityType: enum_2.AuditTrailEntityType.NOTIFICATION,
78
+ };
79
+ /**
80
+ * The recipient's own inbox. Every method is scoped to the caller by `recipient_id`, matching
81
+ * the RLS policies (`auth.uid() = recipient_id`) rather than by organization — a notification
82
+ * belongs to a person, not a tenant.
83
+ */
84
+ class NotificationsResource {
85
+ supabase;
86
+ auth;
87
+ table;
88
+ constructor(supabase, auth, audit) {
89
+ this.supabase = supabase;
90
+ this.auth = auth;
91
+ this.table = (0, audit_1.auditedTable)(supabase, auth, audit, NOTIFICATIONS_TABLE);
92
+ }
93
+ async list(query) {
94
+ const page = query.page;
95
+ const pageSize = query.page_size;
96
+ const offset = (page - 1) * pageSize;
97
+ const trimmedSearch = query.search?.trim();
98
+ // `order`/`range` return `this`, so the builder stays a filter builder and the conditional
99
+ // filters below can be reassigned onto it without a cast.
100
+ let notificationsQuery = this.supabase
101
+ .from('notifications')
102
+ .select(NOTIFICATION_LIST_SELECT, { count: 'estimated' })
103
+ .eq('recipient_id', this.auth.mms_id)
104
+ .eq('deleted', false)
105
+ .order('created_at', { ascending: false })
106
+ .range(offset, offset + pageSize - 1);
107
+ if (query.unread) {
108
+ notificationsQuery = notificationsQuery.is('read_at', null);
109
+ }
110
+ if (trimmedSearch) {
111
+ const escapedSearch = trimmedSearch.replace(/,/g, '\\,');
112
+ notificationsQuery = notificationsQuery.or(`template_id.ilike.%${escapedSearch}%,type.ilike.%${escapedSearch}%`);
113
+ }
114
+ const { data, error, count } = await notificationsQuery;
115
+ if (error)
116
+ throw (0, errors_1.mapPostgrestError)(error);
117
+ const totalEstimated = count ?? 0;
118
+ const totalPages = totalEstimated > 0 ? Math.ceil(totalEstimated / pageSize) : 0;
119
+ return {
120
+ results: (data ?? []),
121
+ page,
122
+ per_page: pageSize,
123
+ count: totalEstimated,
124
+ total_pages: totalPages,
125
+ has_next_page: page < totalPages,
126
+ has_previous_page: page > 1,
127
+ };
128
+ }
129
+ async getById(notificationId) {
130
+ const { data, error } = await this.supabase
131
+ .from('notifications')
132
+ .select(NOTIFICATION_DETAIL_SELECT)
133
+ .eq('mms_id', notificationId)
134
+ .eq('recipient_id', this.auth.mms_id)
135
+ .eq('deleted', false)
136
+ .single();
137
+ if (error)
138
+ throw (0, errors_1.mapPostgrestError)(error);
139
+ return data;
140
+ }
141
+ async unreadCount() {
142
+ const { count, error } = await this.supabase
143
+ .from('notifications')
144
+ .select('mms_id', { count: 'estimated', head: true })
145
+ .eq('recipient_id', this.auth.mms_id)
146
+ .eq('deleted', false)
147
+ .is('read_at', null);
148
+ if (error)
149
+ throw (0, errors_1.mapPostgrestError)(error);
150
+ return { count: count ?? 0 };
151
+ }
152
+ /** Idempotent: re-reading an already read notification matches nothing and changes nothing. */
153
+ async markRead(notificationId) {
154
+ await this.table.updateWhere(notificationId, (query) => query.is('read_at', null), { read_at: new Date().toISOString() });
155
+ }
156
+ /**
157
+ * Deliberately one statement and unaudited. It is a bulk update with no single row to key on,
158
+ * so auditing it would mean a select-then-loop and one audit row per unread notification —
159
+ * for the reader's own UI state, not an entity change.
160
+ */
161
+ async markAllRead() {
162
+ const { error } = await this.supabase
163
+ .from('notifications')
164
+ .update({ read_at: new Date().toISOString() })
165
+ .eq('recipient_id', this.auth.mms_id)
166
+ .eq('deleted', false)
167
+ .is('read_at', null);
168
+ if (error)
169
+ throw (0, errors_1.mapPostgrestError)(error);
170
+ }
171
+ /**
172
+ * The ownership-checked read behind `GET /:id/content`. The caller decides whether to fall
173
+ * back to the provider; caching the result needs the service client's grant on
174
+ * `rendered_content`.
175
+ */
176
+ async contentRow(notificationId) {
177
+ const { data, error } = await this.supabase
178
+ .from('notifications')
179
+ .select('mms_id, organization_id, channel, provider_message_id, rendered_content')
180
+ .eq('mms_id', notificationId)
181
+ .eq('recipient_id', this.auth.mms_id)
182
+ .eq('deleted', false)
183
+ .single();
184
+ if (error)
185
+ throw (0, errors_1.mapPostgrestError)(error);
186
+ return data;
187
+ }
188
+ /** Soft delete — the outbox row stays, flagged `deleted`, so the send record survives. */
189
+ async remove(notificationId) {
190
+ await this.table.transition(notificationId, enum_2.AuditTrailAction.DELETE, {
191
+ deleted: true,
192
+ deleted_at: new Date().toISOString(),
193
+ });
194
+ }
195
+ }
196
+ exports.NotificationsResource = NotificationsResource;
197
+ /**
198
+ * The outbox and the queue worker's side of the table, on the service client: RLS reserves
199
+ * `notifications` INSERT and DELETE to the service role, and `authenticated` has no grant on
200
+ * `rendered_content`.
201
+ *
202
+ * Writes are audited against the row's own organization. Auth mail (signup confirmation,
203
+ * password recovery) has none — it precedes any tenant — and `audit_logs.organization_id` is
204
+ * not nullable, so those rows are written unaudited. Their lifecycle columns are the record.
205
+ */
206
+ class NotificationsOutboxResource {
207
+ supabase;
208
+ tableFor;
209
+ constructor(supabase, tableFor) {
210
+ this.supabase = supabase;
211
+ this.tableFor = tableFor;
212
+ }
213
+ auditedFor(organizationId) {
214
+ return organizationId ? this.tableFor(organizationId) : null;
215
+ }
216
+ async rawUpdate(notificationId, payload) {
217
+ const { error } = await this.supabase
218
+ .from('notifications')
219
+ .update(payload)
220
+ .eq('mms_id', notificationId);
221
+ if (error)
222
+ throw (0, errors_1.mapPostgrestError)(error);
223
+ }
224
+ async create(input) {
225
+ const payload = { ...input, created_by: input.created_by ?? null };
226
+ const audited = this.auditedFor(input.organization_id);
227
+ if (audited) {
228
+ const row = await audited.insert(payload);
229
+ return row;
230
+ }
231
+ const { data, error } = await this.supabase
232
+ .from('notifications')
233
+ .insert([payload])
234
+ .select(NOTIFICATION_CREATED_SELECT)
235
+ .single();
236
+ if (error)
237
+ throw (0, errors_1.mapPostgrestError)(error);
238
+ return data;
239
+ }
240
+ /**
241
+ * The outbox row behind a provider message id. The Resend webhook arrives knowing only that
242
+ * id, and needs the organization before it can attribute anything.
243
+ */
244
+ async findByProviderMessageId(providerMessageId) {
245
+ const { data, error } = await this.supabase
246
+ .from('notifications')
247
+ .select('mms_id, organization_id')
248
+ .eq('provider_message_id', providerMessageId)
249
+ .maybeSingle();
250
+ if (error)
251
+ throw (0, errors_1.mapPostgrestError)(error);
252
+ return (data ?? null);
253
+ }
254
+ /**
255
+ * Stamps a delivery rollup on first occurrence only. A provider that reports `delivered`
256
+ * twice must not move the timestamp, so the guard is the column still being null.
257
+ *
258
+ * Only the rollup columns are ever touched here — `status` belongs to the send lifecycle,
259
+ * not to what the provider reports afterwards.
260
+ */
261
+ async stampRollup(notification, column, value) {
262
+ const audited = this.auditedFor(notification.organization_id);
263
+ if (audited) {
264
+ await audited.updateWhere(notification.mms_id, (query) => query.is(column, null), { [column]: value });
265
+ return;
266
+ }
267
+ const { error } = await this.supabase
268
+ .from('notifications')
269
+ .update({ [column]: value })
270
+ .eq('mms_id', notification.mms_id)
271
+ .is(column, null);
272
+ if (error)
273
+ throw (0, errors_1.mapPostgrestError)(error);
274
+ }
275
+ /** The worker's load. Returns null when the row is gone rather than throwing — see `processQueuedNotification`. */
276
+ async loadForDelivery(notificationId) {
277
+ const { data, error } = await this.supabase
278
+ .from('notifications')
279
+ .select('mms_id, organization_id, status, channel, template_id, template_variables, recipient_email, attempts, sent_at, deleted')
280
+ .eq('mms_id', notificationId)
281
+ .maybeSingle();
282
+ if (error)
283
+ throw (0, errors_1.mapPostgrestError)(error);
284
+ return (data ?? null);
285
+ }
286
+ /**
287
+ * Stamps a successful send. Guarded on `sent_at is null` so a duplicate delivery of the same
288
+ * queue message changes nothing instead of double-stamping — the email has already gone.
289
+ */
290
+ async stampSent(notification, patch) {
291
+ const payload = {
292
+ status: enum_1.NotificationStatus.SENT,
293
+ sent_at: patch.at,
294
+ provider: 'resend',
295
+ provider_message_id: patch.providerMessageId,
296
+ attempts: patch.attempts,
297
+ last_attempted_at: patch.at,
298
+ };
299
+ const audited = this.auditedFor(notification.organization_id);
300
+ if (audited) {
301
+ await audited.updateWhere(notification.mms_id, (query) => query.is('sent_at', null), payload);
302
+ return;
303
+ }
304
+ const { error } = await this.supabase
305
+ .from('notifications')
306
+ .update(payload)
307
+ .eq('mms_id', notification.mms_id)
308
+ .is('sent_at', null);
309
+ if (error)
310
+ throw (0, errors_1.mapPostgrestError)(error);
311
+ }
312
+ /** Records an attempt, retiring the row when the caller says this was the last delivery. */
313
+ async stampAttempt(notification, patch) {
314
+ const payload = {
315
+ attempts: patch.attempts,
316
+ last_attempted_at: patch.at,
317
+ failure_reason: patch.failureReason,
318
+ ...(patch.terminal
319
+ ? { status: enum_1.NotificationStatus.FAILED, failed_at: patch.at }
320
+ : {}),
321
+ };
322
+ const audited = this.auditedFor(notification.organization_id);
323
+ if (audited) {
324
+ await audited.update(notification.mms_id, payload);
325
+ return;
326
+ }
327
+ await this.rawUpdate(notification.mms_id, payload);
328
+ }
329
+ /** Retires a row nothing can rescue — an unknown template, no address, an unsupported channel. */
330
+ async stampFailed(notification, patch) {
331
+ await this.stampAttempt(notification, { ...patch, terminal: true });
332
+ }
333
+ /**
334
+ * Caches the provider's rendered email on the row. Guarded on `rendered_content is null` so
335
+ * concurrent first-opens settle on one write.
336
+ */
337
+ async cacheContent(notification, content) {
338
+ const payload = { rendered_content: content };
339
+ const audited = this.auditedFor(notification.organization_id);
340
+ if (audited) {
341
+ await audited.updateWhere(notification.mms_id, (query) => query.is('rendered_content', null), payload);
342
+ return;
343
+ }
344
+ const { error } = await this.supabase
345
+ .from('notifications')
346
+ .update(payload)
347
+ .eq('mms_id', notification.mms_id)
348
+ .is('rendered_content', null);
349
+ if (error)
350
+ throw (0, errors_1.mapPostgrestError)(error);
351
+ }
352
+ }
353
+ exports.NotificationsOutboxResource = NotificationsOutboxResource;
354
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/notifications/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ import type { CreateOrganizationDto as CreateOrganizationDtoType, UpdateOrganizationDto as UpdateOrganizationDtoType } from '@managemint-solutions/entities/organization/dto';
2
+ import { OrganizationTypes } from '@managemint-solutions/entities/organization/enum';
3
+ export declare class CreateOrganizationDto implements CreateOrganizationDtoType {
4
+ readonly org_type: OrganizationTypes;
5
+ readonly org_name: string;
6
+ readonly org_trading_name?: string | null;
7
+ readonly org_vat_number?: string | null;
8
+ readonly org_registration_number?: string | null;
9
+ readonly org_email: string;
10
+ readonly org_website?: string | null;
11
+ readonly org_phone?: string | null;
12
+ readonly org_address_line_1?: string | null;
13
+ readonly org_address_line_2?: string | null;
14
+ readonly org_city?: string | null;
15
+ readonly org_state?: string | null;
16
+ readonly org_postal_code?: string | null;
17
+ readonly org_country?: string | null;
18
+ readonly use_address_for_billing: boolean;
19
+ readonly org_billing_address_line_1?: string | null;
20
+ readonly org_billing_address_line_2?: string | null;
21
+ readonly org_billing_city?: string | null;
22
+ readonly org_billing_state?: string | null;
23
+ readonly org_billing_postal_code?: string | null;
24
+ readonly org_billing_country?: string | null;
25
+ readonly org_consent_given: true;
26
+ readonly org_industry?: string | null;
27
+ readonly org_marketting_consent_given: boolean;
28
+ readonly org_currency: string;
29
+ readonly owner_first_name: string;
30
+ readonly owner_last_name: string;
31
+ readonly owner_email: string;
32
+ readonly owner_country_code: string;
33
+ readonly owner_phone: string;
34
+ readonly owner_profile_image?: string | null;
35
+ readonly module_ids: string[];
36
+ }
37
+ export declare class UpdateOrganizationDto implements UpdateOrganizationDtoType {
38
+ readonly type?: OrganizationTypes;
39
+ readonly name?: string;
40
+ readonly trading_name?: string | null;
41
+ readonly vat_number?: string | null;
42
+ readonly registration_number?: string | null;
43
+ readonly email?: string;
44
+ readonly website?: string | null;
45
+ readonly phone?: string | null;
46
+ readonly address_line_1?: string | null;
47
+ readonly address_line_2?: string | null;
48
+ readonly city?: string | null;
49
+ readonly state?: string | null;
50
+ readonly post_code?: string | null;
51
+ readonly country?: string | null;
52
+ readonly use_address_for_billing?: boolean;
53
+ readonly billing_address_line_1?: string | null;
54
+ readonly billing_address_line_2?: string | null;
55
+ readonly billing_city?: string | null;
56
+ readonly billing_state?: string | null;
57
+ readonly billing_post_code?: string | null;
58
+ readonly billing_country?: string | null;
59
+ readonly industry?: string | null;
60
+ readonly marketing_consent?: boolean;
61
+ readonly currency?: string;
62
+ }