@managemint-solutions/sdk 0.37.0 → 0.38.1

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 (70) hide show
  1. package/README.md +32 -27
  2. package/dist/audit/dto.js +1 -1
  3. package/dist/audit/index.d.ts +12 -12
  4. package/dist/audit/index.js +9 -9
  5. package/dist/auth-client/index.d.ts +2 -2
  6. package/dist/auth-client/index.js +2 -2
  7. package/dist/auth.d.ts +3 -3
  8. package/dist/auth.js +3 -3
  9. package/dist/billing/dto.js +1 -1
  10. package/dist/billing/index.d.ts +4 -4
  11. package/dist/billing/index.js +5 -5
  12. package/dist/billing/invoices/dto.js +1 -1
  13. package/dist/billing/invoices/index.d.ts +6 -6
  14. package/dist/billing/invoices/index.js +7 -7
  15. package/dist/client.d.ts +3 -3
  16. package/dist/client.js +1 -1
  17. package/dist/clients/index.d.ts +1 -1
  18. package/dist/clients/index.js +1 -1
  19. package/dist/configs/dto.js +3 -3
  20. package/dist/configs/index.d.ts +3 -3
  21. package/dist/configs/index.js +3 -3
  22. package/dist/errors.d.ts +2 -2
  23. package/dist/errors.js +2 -2
  24. package/dist/feature-requests/dto.js +1 -1
  25. package/dist/feature-requests/index.d.ts +3 -3
  26. package/dist/feature-requests/index.js +2 -2
  27. package/dist/index.js +2 -2
  28. package/dist/leave/dto.d.ts +1 -0
  29. package/dist/leave/dto.js +7 -0
  30. package/dist/leave/leave-entitlements.d.ts +6 -0
  31. package/dist/leave/leave-entitlements.js +22 -0
  32. package/dist/leave/leave-requests.js +3 -0
  33. package/dist/nest/index.d.ts +5 -5
  34. package/dist/nest/index.js +4 -4
  35. package/dist/notifications/index.d.ts +8 -8
  36. package/dist/notifications/index.js +8 -8
  37. package/dist/organization-invites/index.d.ts +3 -3
  38. package/dist/organization-invites/index.js +2 -2
  39. package/dist/organization-payment-methods/index.d.ts +3 -3
  40. package/dist/organization-payment-methods/index.js +3 -3
  41. package/dist/organizations/index.d.ts +7 -7
  42. package/dist/organizations/index.js +7 -7
  43. package/dist/permissions/index.d.ts +6 -6
  44. package/dist/permissions/index.js +6 -6
  45. package/dist/pricebooks/index.d.ts +2 -2
  46. package/dist/pricebooks/index.js +3 -3
  47. package/dist/projects/dto.js +2 -2
  48. package/dist/projects/index.d.ts +1 -1
  49. package/dist/projects/index.js +2 -2
  50. package/dist/service-client/index.d.ts +5 -5
  51. package/dist/service-client/index.js +5 -5
  52. package/dist/support/dto.js +1 -1
  53. package/dist/supporting-files/dto.js +1 -1
  54. package/dist/supporting-files/index.js +5 -5
  55. package/dist/supporting-files/paths.d.ts +3 -3
  56. package/dist/supporting-files/paths.js +4 -4
  57. package/dist/tasks/dto.js +4 -4
  58. package/dist/tasks/index.d.ts +1 -1
  59. package/dist/tasks/index.js +2 -2
  60. package/dist/transforms.d.ts +6 -6
  61. package/dist/transforms.js +8 -8
  62. package/dist/users/dto.d.ts +3 -3
  63. package/dist/users/dto.js +4 -4
  64. package/dist/users/index.d.ts +2 -2
  65. package/dist/users/index.js +2 -2
  66. package/dist/users/paths.d.ts +2 -2
  67. package/dist/users/paths.js +2 -2
  68. package/dist/webhook-events/index.d.ts +3 -3
  69. package/dist/webhook-events/index.js +3 -3
  70. package/package.json +2 -2
@@ -24,13 +24,13 @@ const INVOICES_TABLE = {
24
24
  table: 'invoices',
25
25
  entityType: enum_1.AuditTrailEntityType.INVOICE,
26
26
  };
27
- /** The wire shape of an invoice list row — never the internal bigint id. */
27
+ /** The wire shape of an invoice list row - never the internal bigint id. */
28
28
  const INVOICE_SUMMARY_SELECT = 'mms_id, invoice_number, transaction_type, status, issued_at, paid_at, amount_minor, currency';
29
29
  /** InvoiceEntity, column for column: the summary plus the frozen document data. */
30
30
  const INVOICE_ENTITY_SELECT = `${INVOICE_SUMMARY_SELECT}, billing_transaction_id, paystack_reference, period_start, period_end, line_items, billed_to`;
31
31
  /**
32
32
  * The readable half. `invoices` is SELECT-only for `authenticated` with an org-predicate
33
- * policy — the same posture as the ledger it mirrors — so reads run on the caller's own
33
+ * policy - the same posture as the ledger it mirrors - so reads run on the caller's own
34
34
  * client and RLS is what scopes them.
35
35
  */
36
36
  class InvoicesReadsResource {
@@ -61,7 +61,7 @@ class InvoicesReadsResource {
61
61
  throw (0, errors_1.mapPostgrestError)(error);
62
62
  return (0, transforms_1.toMmsList)(data, page, pageSize, count);
63
63
  }
64
- /** The full invoice document data, or null — RLS makes another tenant's id look missing. */
64
+ /** The full invoice document data, or null - RLS makes another tenant's id look missing. */
65
65
  async byId(invoiceId) {
66
66
  const { data, error } = await this.supabase
67
67
  .from('invoices')
@@ -76,10 +76,10 @@ class InvoicesReadsResource {
76
76
  }
77
77
  exports.InvoicesReadsResource = InvoicesReadsResource;
78
78
  /**
79
- * The document writes, on the service client only — every write policy on `invoices` is
79
+ * The document writes, on the service client only - every write policy on `invoices` is
80
80
  * `false` for `authenticated`. Rows are written by the api's billing service beside a
81
- * renewal's ledger write — a renewal is inserted already paid, so an invoice never moves
82
- * status after it is issued — never by a caller.
81
+ * renewal's ledger write - a renewal is inserted already paid, so an invoice never moves
82
+ * status after it is issued - never by a caller.
83
83
  */
84
84
  class InvoicesResource extends InvoicesReadsResource {
85
85
  invoices;
@@ -94,7 +94,7 @@ class InvoicesResource extends InvoicesReadsResource {
94
94
  /**
95
95
  * The organization's highest invoice number, 0 when it has none. The api assigns
96
96
  * `max + 1` and lets the `(organization_id, invoice_number)` unique index arbitrate a
97
- * concurrent insert — the retry lives there, not here.
97
+ * concurrent insert - the retry lives there, not here.
98
98
  */
99
99
  async maxNumber() {
100
100
  const { data, error } = await this.supabase
package/dist/client.d.ts CHANGED
@@ -24,20 +24,20 @@ export type SupabaseClientConfig = {
24
24
  accessToken: string;
25
25
  /**
26
26
  * Who the request runs as. The caller must already have **verified** the token this came from
27
- * (`verifyAccessToken`) — the client trusts this outright and scopes every query to it.
27
+ * (`verifyAccessToken`) - the client trusts this outright and scopes every query to it.
28
28
  */
29
29
  auth: AuthContext;
30
30
  /** Where a failed audit insert is reported. Defaults to `console.error`. */
31
31
  onAuditError?: AuditErrorHandler;
32
32
  /**
33
- * A raw client already built for this url/key/token — what `verifyAccessToken` was handed, so
33
+ * A raw client already built for this url/key/token - what `verifyAccessToken` was handed, so
34
34
  * one request builds one supabase-js client. Defaults to building its own.
35
35
  */
36
36
  client?: TypedSupabaseClient;
37
37
  };
38
38
  /**
39
39
  * The caller's data client: every query carries their bearer token, so RLS decides what they
40
- * may see. It performs no authentication of its own — build it from a `VerifiedAuth`, never from
40
+ * may see. It performs no authentication of its own - build it from a `VerifiedAuth`, never from
41
41
  * a token you have only decoded.
42
42
  */
43
43
  export declare class SupabaseClient {
package/dist/client.js CHANGED
@@ -21,7 +21,7 @@ const tasks_1 = require("./tasks");
21
21
  const users_1 = require("./users");
22
22
  /**
23
23
  * The caller's data client: every query carries their bearer token, so RLS decides what they
24
- * may see. It performs no authentication of its own — build it from a `VerifiedAuth`, never from
24
+ * may see. It performs no authentication of its own - build it from a `VerifiedAuth`, never from
25
25
  * a token you have only decoded.
26
26
  */
27
27
  class SupabaseClient {
@@ -17,6 +17,6 @@ export declare class ClientsResource {
17
17
  archive(clientId: string): Promise<ClientEntity>;
18
18
  unarchive(clientId: string): Promise<ClientEntity>;
19
19
  restore(clientId: string): Promise<ClientEntity>;
20
- /** Soft delete — the row stays, flagged `deleted`, and `restore()` brings it back. */
20
+ /** Soft delete - the row stays, flagged `deleted`, and `restore()` brings it back. */
21
21
  remove(clientId: string): Promise<void>;
22
22
  }
@@ -164,7 +164,7 @@ class ClientsResource {
164
164
  await this.table.transition(clientId, enum_1.AuditTrailAction.RESTORE, (0, transforms_1.restoredPatch)(this.auth.mms_id));
165
165
  return this.getById(clientId);
166
166
  }
167
- /** Soft delete — the row stays, flagged `deleted`, and `restore()` brings it back. */
167
+ /** Soft delete - the row stays, flagged `deleted`, and `restore()` brings it back. */
168
168
  async remove(clientId) {
169
169
  await this.table.transition(clientId, enum_1.AuditTrailAction.DELETE, (0, transforms_1.deletedPatch)(this.auth.mms_id));
170
170
  }
@@ -16,7 +16,7 @@ const class_transformer_1 = require("class-transformer");
16
16
  // wire contract cannot drift.
17
17
  /**
18
18
  * Whitespace on either side of a pasted value is not part of the answer. Trimming here rather
19
- * than in the api means the length rules below measure what will actually be stored — a name of
19
+ * than in the api means the length rules below measure what will actually be stored - a name of
20
20
  * three spaces is empty, not three characters long.
21
21
  */
22
22
  const Trim = () => (0, class_transformer_1.Transform)(({ value }) => (typeof value === 'string' ? value.trim() : value), {
@@ -25,11 +25,11 @@ const Trim = () => (0, class_transformer_1.Transform)(({ value }) => (typeof val
25
25
  class CreateConfigDto {
26
26
  name;
27
27
  description;
28
- // This DTO is the only place the object shape is enforced — the column has no CHECK by
28
+ // This DTO is the only place the object shape is enforced - the column has no CHECK by
29
29
  // design, so a config may hold whatever keys the row's author named. class-validator's
30
30
  // isObject rejects arrays and scalars, which is exactly the line: one JSON object, nothing
31
31
  // else. `@ValidateIf` rather than `@IsOptional` because the latter skips an explicit null
32
- // too, and null is not a config value — an omitted `value` becomes `{}` at the insert.
32
+ // too, and null is not a config value - an omitted `value` becomes `{}` at the insert.
33
33
  value;
34
34
  }
35
35
  exports.CreateConfigDto = CreateConfigDto;
@@ -3,7 +3,7 @@ import type { CreateConfigDto as CreateConfigDtoType, UpdateConfigDto as UpdateC
3
3
  import type { TypedSupabaseClient } from '../client';
4
4
  export * from './dto';
5
5
  /**
6
- * Global named JSON configs. Every signed-in caller may read (the READ policy is `true` — there
6
+ * Global named JSON configs. Every signed-in caller may read (the READ policy is `true` - there
7
7
  * is no tenant on the row), so this hangs off the user client and the service client alike;
8
8
  * only the service role may write, and a write on the user client fails at the database.
9
9
  * Not audited: Studio is the other writer, and nothing would see its edits anyway.
@@ -15,10 +15,10 @@ export declare class ConfigsResource {
15
15
  getByName(name: string): Promise<ConfigEntity>;
16
16
  getById(configId: string): Promise<ConfigEntity>;
17
17
  create(input: CreateConfigDtoType): Promise<ConfigEntity>;
18
- /** `value` replaces the whole object — it is not merged. */
18
+ /** `value` replaces the whole object - it is not merged. */
19
19
  update(name: string, patch: UpdateConfigDtoType): Promise<ConfigEntity>;
20
20
  /**
21
- * Hard delete — there is nothing to soft-delete into and nothing references a config row.
21
+ * Hard delete - there is nothing to soft-delete into and nothing references a config row.
22
22
  * Service role only, like every write here; a call on the user client fails at the database.
23
23
  */
24
24
  remove(name: string): Promise<void>;
@@ -22,7 +22,7 @@ __exportStar(require("./dto"), exports);
22
22
  // supabase/migrations). `id` never leaves SQL.
23
23
  const CONFIG_SELECT = 'mms_id, created_at, updated_at, name, description, value';
24
24
  /**
25
- * Global named JSON configs. Every signed-in caller may read (the READ policy is `true` — there
25
+ * Global named JSON configs. Every signed-in caller may read (the READ policy is `true` - there
26
26
  * is no tenant on the row), so this hangs off the user client and the service client alike;
27
27
  * only the service role may write, and a write on the user client fails at the database.
28
28
  * Not audited: Studio is the other writer, and nothing would see its edits anyway.
@@ -76,7 +76,7 @@ class ConfigsResource {
76
76
  throw (0, errors_1.mapPostgrestError)(error);
77
77
  return data;
78
78
  }
79
- /** `value` replaces the whole object — it is not merged. */
79
+ /** `value` replaces the whole object - it is not merged. */
80
80
  async update(name, patch) {
81
81
  const { data, error } = await this.supabase
82
82
  .from('configs')
@@ -89,7 +89,7 @@ class ConfigsResource {
89
89
  return data;
90
90
  }
91
91
  /**
92
- * Hard delete — there is nothing to soft-delete into and nothing references a config row.
92
+ * Hard delete - there is nothing to soft-delete into and nothing references a config row.
93
93
  * Service role only, like every write here; a call on the user client fails at the database.
94
94
  */
95
95
  async remove(name) {
package/dist/errors.d.ts CHANGED
@@ -28,7 +28,7 @@ export declare class SupabaseClientError extends Error {
28
28
  }
29
29
  /**
30
30
  * Converts a raw Postgrest error into the SupabaseClientError the SDK throws. The message is
31
- * Postgrest's own — RLS denials say what the policy said, and nothing rewrites it.
31
+ * Postgrest's own - RLS denials say what the policy said, and nothing rewrites it.
32
32
  */
33
33
  export declare const mapPostgrestError: (error: PostgrestError) => SupabaseClientError;
34
34
  /**
@@ -38,7 +38,7 @@ export declare const mapPostgrestError: (error: PostgrestError) => SupabaseClien
38
38
  */
39
39
  export declare const mapStorageError: (error: StorageError, message?: string) => SupabaseClientError;
40
40
  /**
41
- * Converts a Supabase Auth (GoTrue) error into the SupabaseClientError the SDK throws — the
41
+ * Converts a Supabase Auth (GoTrue) error into the SupabaseClientError the SDK throws - the
42
42
  * SDK-side equivalent of the api's `throwAuthErrorResponse`. `AuthError.status` is the HTTP
43
43
  * status GoTrue answered with; network/unknown failures carry none, hence the 500 fallback.
44
44
  */
package/dist/errors.js CHANGED
@@ -75,7 +75,7 @@ const POSTGREST_CODE_TO_HTTP_STATUS = {
75
75
  };
76
76
  /**
77
77
  * Converts a raw Postgrest error into the SupabaseClientError the SDK throws. The message is
78
- * Postgrest's own — RLS denials say what the policy said, and nothing rewrites it.
78
+ * Postgrest's own - RLS denials say what the policy said, and nothing rewrites it.
79
79
  */
80
80
  const mapPostgrestError = (error) => new SupabaseClientError({
81
81
  status: POSTGREST_CODE_TO_HTTP_STATUS[error.code] || 500,
@@ -96,7 +96,7 @@ const mapStorageError = (error, message = error.message) => new SupabaseClientEr
96
96
  }, { cause: error });
97
97
  exports.mapStorageError = mapStorageError;
98
98
  /**
99
- * Converts a Supabase Auth (GoTrue) error into the SupabaseClientError the SDK throws — the
99
+ * Converts a Supabase Auth (GoTrue) error into the SupabaseClientError the SDK throws - the
100
100
  * SDK-side equivalent of the api's `throwAuthErrorResponse`. `AuthError.status` is the HTTP
101
101
  * status GoTrue answered with; network/unknown failures carry none, hence the 500 fallback.
102
102
  */
@@ -17,7 +17,7 @@ const validators_1 = require("../validators");
17
17
  // wire contract cannot drift.
18
18
  /**
19
19
  * Whitespace on either side of a pasted value is not part of the answer. Trimming here rather
20
- * than in the api means the length rules below measure what will actually be stored — a name of
20
+ * than in the api means the length rules below measure what will actually be stored - a name of
21
21
  * three spaces is empty, not three characters long.
22
22
  */
23
23
  const Trim = () => (0, class_transformer_1.Transform)(({ value }) => (typeof value === 'string' ? value.trim() : value), {
@@ -9,13 +9,13 @@ export type CreateFeatureRequestRow = {
9
9
  requester_email: string;
10
10
  source: FeatureRequestSource;
11
11
  };
12
- /** All the insert hands back — the id the endpoint answers with. */
12
+ /** All the insert hands back - the id the endpoint answers with. */
13
13
  export type CreatedFeatureRequest = {
14
14
  mms_id: string;
15
15
  };
16
16
  /**
17
17
  * The `feature_requests` table: "I need something" submissions from the marketing website's
18
- * roadmap page. There is no reader here by design — the rows are read in Supabase Studio, and
18
+ * roadmap page. There is no reader here by design - the rows are read in Supabase Studio, and
19
19
  * nothing renders a visitor's words back to anyone.
20
20
  *
21
21
  * Service-role only, like `organization_invites`: the table has RLS enabled with no policies and
@@ -25,7 +25,7 @@ export type CreatedFeatureRequest = {
25
25
  * No organization: a feature request belongs to nobody's tenant, which is why the resource hangs
26
26
  * off the client itself rather than off `forOrganization`.
27
27
  *
28
- * Not audited — `audit_logs` rows carry an organization and an actor, and this write has neither.
28
+ * Not audited - `audit_logs` rows carry an organization and an actor, and this write has neither.
29
29
  */
30
30
  export declare class FeatureRequestsResource {
31
31
  private readonly supabase;
@@ -19,7 +19,7 @@ const errors_1 = require("../errors");
19
19
  __exportStar(require("./dto"), exports);
20
20
  /**
21
21
  * The `feature_requests` table: "I need something" submissions from the marketing website's
22
- * roadmap page. There is no reader here by design — the rows are read in Supabase Studio, and
22
+ * roadmap page. There is no reader here by design - the rows are read in Supabase Studio, and
23
23
  * nothing renders a visitor's words back to anyone.
24
24
  *
25
25
  * Service-role only, like `organization_invites`: the table has RLS enabled with no policies and
@@ -29,7 +29,7 @@ __exportStar(require("./dto"), exports);
29
29
  * No organization: a feature request belongs to nobody's tenant, which is why the resource hangs
30
30
  * off the client itself rather than off `forOrganization`.
31
31
  *
32
- * Not audited — `audit_logs` rows carry an organization and an actor, and this write has neither.
32
+ * Not audited - `audit_logs` rows carry an organization and an actor, and this write has neither.
33
33
  */
34
34
  class FeatureRequestsResource {
35
35
  supabase;
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
- // The package's public surface, spelled out. Anything not listed here is the SDK's own plumbing —
3
- // the audit diff, the row helpers, the select-string fragments, the error mappers — and stays
2
+ // The package's public surface, spelled out. Anything not listed here is the SDK's own plumbing -
3
+ // the audit diff, the row helpers, the select-string fragments, the error mappers - and stays
4
4
  // reachable only from inside. The `./nest` entrypoint is listed separately, in src/nest/index.ts.
5
5
  //
6
6
  // Resources are reached through the three clients (`supabase.tasks`, `scope.invoices`, ...), so
@@ -51,6 +51,7 @@ export declare class GetLeaveRequestsDto implements GetLeaveRequestsDtoType {
51
51
  readonly page: number;
52
52
  readonly page_size: number;
53
53
  readonly user_id?: string | null;
54
+ readonly leave_type_id?: string | null;
54
55
  readonly status?: LeaveRequestStatus | null;
55
56
  readonly start_date_after?: string | null;
56
57
  readonly start_date_before?: string | null;
package/dist/leave/dto.js CHANGED
@@ -249,6 +249,7 @@ class GetLeaveRequestsDto {
249
249
  page = 1;
250
250
  page_size = 10;
251
251
  user_id;
252
+ leave_type_id;
252
253
  status;
253
254
  start_date_after;
254
255
  start_date_before;
@@ -275,6 +276,12 @@ __decorate([
275
276
  (0, class_validator_1.IsUUID)('4', { message: 'Invalid user ID format' }),
276
277
  __metadata("design:type", Object)
277
278
  ], GetLeaveRequestsDto.prototype, "user_id", void 0);
279
+ __decorate([
280
+ (0, class_validator_1.IsOptional)(),
281
+ (0, validators_1.IsNullable)(),
282
+ (0, class_validator_1.IsUUID)('7', { message: 'Invalid leave type ID format' }),
283
+ __metadata("design:type", Object)
284
+ ], GetLeaveRequestsDto.prototype, "leave_type_id", void 0);
278
285
  __decorate([
279
286
  (0, class_validator_1.IsOptional)(),
280
287
  (0, validators_1.IsNullable)(),
@@ -29,6 +29,12 @@ export declare class LeaveEntitlementsResource {
29
29
  * table's exclusion constraint), so there is at most one.
30
30
  */
31
31
  findFor(userId: string, leaveTypeId: string, date: string): Promise<LeaveEntitlementCover | null>;
32
+ /**
33
+ * Whether `userId` already has an entitlement of `leaveTypeId` touching any day of
34
+ * `start`..`end`. The readable half of the rule; the table's exclusion constraint is the half
35
+ * that survives a race. `excludeId` leaves out the entitlement being edited.
36
+ */
37
+ overlaps(userId: string, leaveTypeId: string, start: string, end: string, excludeId?: string): Promise<boolean>;
32
38
  create(input: CreateLeaveEntitlementInput): Promise<LeaveEntitlementEntity>;
33
39
  update(leaveEntitlementId: string, input: UpdateLeaveEntitlementDto): Promise<LeaveEntitlementEntity>;
34
40
  /** Hard delete: the type simply becomes untracked for that user and period. */
@@ -94,6 +94,28 @@ class LeaveEntitlementsResource {
94
94
  const cover = data;
95
95
  return { ...cover, days_entitled: Number(cover.days_entitled) };
96
96
  }
97
+ /**
98
+ * Whether `userId` already has an entitlement of `leaveTypeId` touching any day of
99
+ * `start`..`end`. The readable half of the rule; the table's exclusion constraint is the half
100
+ * that survives a race. `excludeId` leaves out the entitlement being edited.
101
+ */
102
+ async overlaps(userId, leaveTypeId, start, end, excludeId) {
103
+ let overlapQuery = this.supabase
104
+ .from('leave_entitlements')
105
+ .select('mms_id', { count: 'exact', head: true })
106
+ .eq('organization_id', this.auth.organization_id)
107
+ .eq('user_id', userId)
108
+ .eq('leave_type_id', leaveTypeId)
109
+ .lte('period_start', end)
110
+ .gte('period_end', start);
111
+ if (excludeId) {
112
+ overlapQuery = overlapQuery.neq('mms_id', excludeId);
113
+ }
114
+ const { count, error } = await overlapQuery;
115
+ if (error)
116
+ throw (0, errors_1.mapPostgrestError)(error);
117
+ return (count ?? 0) > 0;
118
+ }
97
119
  async create(input) {
98
120
  const row = await this.table.insert({
99
121
  user_id: input.user_id,
@@ -60,6 +60,9 @@ class LeaveRequestsResource {
60
60
  if (query.user_id) {
61
61
  requestsQuery = requestsQuery.eq('user_id', query.user_id);
62
62
  }
63
+ if (query.leave_type_id) {
64
+ requestsQuery = requestsQuery.eq('leave_type_id', query.leave_type_id);
65
+ }
63
66
  if (query.status) {
64
67
  requestsQuery = requestsQuery.eq('status', query.status);
65
68
  }
@@ -12,7 +12,7 @@ import { type SupabaseServiceClient } from '../service-client';
12
12
  */
13
13
  export declare const toHttpException: (error: SupabaseClientError) => HttpException;
14
14
  export type SupabaseUserClientOptions = {
15
- /** Where a failed audit insert is reported — e.g. `(error) => Sentry.captureException(error)`. */
15
+ /** Where a failed audit insert is reported - e.g. `(error) => Sentry.captureException(error)`. */
16
16
  onAuditError?: AuditErrorHandler;
17
17
  };
18
18
  /**
@@ -25,12 +25,12 @@ export type SupabaseRequestContext = {
25
25
  client: SupabaseClient;
26
26
  auth: VerifiedAuth;
27
27
  };
28
- /** Where on the request the context is stored — `request[SUPABASE_REQUEST_KEY]`. */
28
+ /** Where on the request the context is stored - `request[SUPABASE_REQUEST_KEY]`. */
29
29
  export declare const SUPABASE_REQUEST_KEY = "supabase";
30
30
  /**
31
31
  * Verifies the bearer token on `request`, builds the caller's client from it and stores both on
32
32
  * the request. This is the one place a token is authenticated, so it belongs in the api's auth
33
- * guard — a param decorator cannot be async and must not be where identity is established.
33
+ * guard - a param decorator cannot be async and must not be where identity is established.
34
34
  *
35
35
  * Idempotent: a second call hands back the context the first one attached.
36
36
  */
@@ -43,7 +43,7 @@ export declare const getSupabaseRequestContext: (request: Request) => SupabaseRe
43
43
  /** The caller's data client, from the context the auth guard attached. */
44
44
  export declare const SupabaseUserClient: (...dataOrPipes: unknown[]) => ParameterDecorator;
45
45
  /**
46
- * A `SupabaseServiceClient` from the ambient env — the SDK-side replacement for the api's
46
+ * A `SupabaseServiceClient` from the ambient env - the SDK-side replacement for the api's
47
47
  * `createSupabaseAdminClient()`.
48
48
  *
49
49
  * Deliberately a factory rather than a param decorator: a service client carries no per-request
@@ -54,7 +54,7 @@ export declare const SupabaseUserClient: (...dataOrPipes: unknown[]) => Paramete
54
54
  export declare const createSupabaseServiceClientFromEnv: (options?: SupabaseUserClientOptions) => SupabaseServiceClient;
55
55
  /**
56
56
  * A `SupabaseAuthClient` for routes a logged-out caller hits (sign-in, refresh, password
57
- * reset) — built from the publishable key alone, with no bearer token involved.
57
+ * reset) - built from the publishable key alone, with no bearer token involved.
58
58
  *
59
59
  * Deliberately a fresh client per request, not a module-level singleton: supabase-js keeps the
60
60
  * session `signIn`, `verifyOtp` and `setSession` produce in the client's own memory, so one
@@ -39,12 +39,12 @@ const configureSupabaseUserClient = (options) => {
39
39
  userClientOptions = options;
40
40
  };
41
41
  exports.configureSupabaseUserClient = configureSupabaseUserClient;
42
- /** Where on the request the context is stored — `request[SUPABASE_REQUEST_KEY]`. */
42
+ /** Where on the request the context is stored - `request[SUPABASE_REQUEST_KEY]`. */
43
43
  exports.SUPABASE_REQUEST_KEY = 'supabase';
44
44
  /**
45
45
  * Verifies the bearer token on `request`, builds the caller's client from it and stores both on
46
46
  * the request. This is the one place a token is authenticated, so it belongs in the api's auth
47
- * guard — a param decorator cannot be async and must not be where identity is established.
47
+ * guard - a param decorator cannot be async and must not be where identity is established.
48
48
  *
49
49
  * Idempotent: a second call hands back the context the first one attached.
50
50
  */
@@ -97,7 +97,7 @@ exports.getSupabaseRequestContext = getSupabaseRequestContext;
97
97
  /** The caller's data client, from the context the auth guard attached. */
98
98
  exports.SupabaseUserClient = (0, common_1.createParamDecorator)((_, ctx) => (0, exports.getSupabaseRequestContext)(ctx.switchToHttp().getRequest()).client);
99
99
  /**
100
- * A `SupabaseServiceClient` from the ambient env — the SDK-side replacement for the api's
100
+ * A `SupabaseServiceClient` from the ambient env - the SDK-side replacement for the api's
101
101
  * `createSupabaseAdminClient()`.
102
102
  *
103
103
  * Deliberately a factory rather than a param decorator: a service client carries no per-request
@@ -113,7 +113,7 @@ const createSupabaseServiceClientFromEnv = (options = {}) => (0, service_client_
113
113
  exports.createSupabaseServiceClientFromEnv = createSupabaseServiceClientFromEnv;
114
114
  /**
115
115
  * A `SupabaseAuthClient` for routes a logged-out caller hits (sign-in, refresh, password
116
- * reset) — built from the publishable key alone, with no bearer token involved.
116
+ * reset) - built from the publishable key alone, with no bearer token involved.
117
117
  *
118
118
  * Deliberately a fresh client per request, not a module-level singleton: supabase-js keeps the
119
119
  * session `signIn`, `verifyOtp` and `setSession` produce in the client's own memory, so one
@@ -47,7 +47,7 @@ export type NotificationContentRow = {
47
47
  };
48
48
  /**
49
49
  * The recipient's own inbox. Every method is scoped to the caller by `recipient_id`, matching
50
- * the RLS policies (`auth.uid() = recipient_id`) rather than by organization — a notification
50
+ * the RLS policies (`auth.uid() = recipient_id`) rather than by organization - a notification
51
51
  * belongs to a person, not a tenant.
52
52
  */
53
53
  export declare class NotificationsResource {
@@ -62,7 +62,7 @@ export declare class NotificationsResource {
62
62
  markRead(notificationId: string): Promise<void>;
63
63
  /**
64
64
  * Deliberately one statement and unaudited. It is a bulk update with no single row to key on,
65
- * so auditing it would mean a select-then-loop and one audit row per unread notification —
65
+ * so auditing it would mean a select-then-loop and one audit row per unread notification -
66
66
  * for the reader's own UI state, not an entity change.
67
67
  */
68
68
  markAllRead(): Promise<void>;
@@ -72,7 +72,7 @@ export declare class NotificationsResource {
72
72
  * `rendered_content`.
73
73
  */
74
74
  contentRow(notificationId: string): Promise<NotificationContentRow>;
75
- /** Soft delete — the outbox row stays, flagged `deleted`, so the send record survives. */
75
+ /** Soft delete - the outbox row stays, flagged `deleted`, so the send record survives. */
76
76
  remove(notificationId: string): Promise<void>;
77
77
  }
78
78
  /** How the outbox reaches an audited table once it knows which organization a row belongs to. */
@@ -83,7 +83,7 @@ export type OrganizationTableFactory = (organizationId: string) => AuditedTable;
83
83
  * `rendered_content`.
84
84
  *
85
85
  * Writes are audited against the row's own organization. Auth mail (signup confirmation,
86
- * password recovery) has none — it precedes any tenant — and `audit_logs.organization_id` is
86
+ * password recovery) has none - it precedes any tenant - and `audit_logs.organization_id` is
87
87
  * not nullable, so those rows are written unaudited. Their lifecycle columns are the record.
88
88
  */
89
89
  export declare class NotificationsOutboxResource {
@@ -102,15 +102,15 @@ export declare class NotificationsOutboxResource {
102
102
  * Stamps a delivery rollup on first occurrence only. A provider that reports `delivered`
103
103
  * twice must not move the timestamp, so the guard is the column still being null.
104
104
  *
105
- * Only the rollup columns are ever touched here — `status` belongs to the send lifecycle,
105
+ * Only the rollup columns are ever touched here - `status` belongs to the send lifecycle,
106
106
  * not to what the provider reports afterwards.
107
107
  */
108
108
  stampRollup(notification: Pick<NotificationContentRow, 'mms_id' | 'organization_id'>, column: 'delivered_at' | 'delivery_failure_reason', value: string): Promise<void>;
109
- /** The worker's load. Returns null when the row is gone rather than throwing — see `processQueuedNotification`. */
109
+ /** The worker's load. Returns null when the row is gone rather than throwing - see `processQueuedNotification`. */
110
110
  loadForDelivery(notificationId: string): Promise<QueuedNotification | null>;
111
111
  /**
112
112
  * Stamps a successful send. Guarded on `sent_at is null` so a duplicate delivery of the same
113
- * queue message changes nothing instead of double-stamping — the email has already gone.
113
+ * queue message changes nothing instead of double-stamping - the email has already gone.
114
114
  */
115
115
  stampSent(notification: QueuedNotification, patch: {
116
116
  providerMessageId: string | null;
@@ -124,7 +124,7 @@ export declare class NotificationsOutboxResource {
124
124
  failureReason: string;
125
125
  terminal: boolean;
126
126
  }): Promise<void>;
127
- /** Retires a row nothing can rescue — an unknown template, no address, an unsupported channel. */
127
+ /** Retires a row nothing can rescue - an unknown template, no address, an unsupported channel. */
128
128
  stampFailed(notification: QueuedNotification, patch: {
129
129
  attempts: number;
130
130
  at: string;
@@ -91,7 +91,7 @@ const NOTIFICATIONS_TABLE = {
91
91
  };
92
92
  /**
93
93
  * The recipient's own inbox. Every method is scoped to the caller by `recipient_id`, matching
94
- * the RLS policies (`auth.uid() = recipient_id`) rather than by organization — a notification
94
+ * the RLS policies (`auth.uid() = recipient_id`) rather than by organization - a notification
95
95
  * belongs to a person, not a tenant.
96
96
  */
97
97
  class NotificationsResource {
@@ -157,7 +157,7 @@ class NotificationsResource {
157
157
  }
158
158
  /**
159
159
  * Deliberately one statement and unaudited. It is a bulk update with no single row to key on,
160
- * so auditing it would mean a select-then-loop and one audit row per unread notification —
160
+ * so auditing it would mean a select-then-loop and one audit row per unread notification -
161
161
  * for the reader's own UI state, not an entity change.
162
162
  */
163
163
  async markAllRead() {
@@ -187,7 +187,7 @@ class NotificationsResource {
187
187
  throw (0, errors_1.mapPostgrestError)(error);
188
188
  return data;
189
189
  }
190
- /** Soft delete — the outbox row stays, flagged `deleted`, so the send record survives. */
190
+ /** Soft delete - the outbox row stays, flagged `deleted`, so the send record survives. */
191
191
  async remove(notificationId) {
192
192
  await this.table.transition(notificationId, enum_2.AuditTrailAction.DELETE, {
193
193
  deleted: true,
@@ -202,7 +202,7 @@ exports.NotificationsResource = NotificationsResource;
202
202
  * `rendered_content`.
203
203
  *
204
204
  * Writes are audited against the row's own organization. Auth mail (signup confirmation,
205
- * password recovery) has none — it precedes any tenant — and `audit_logs.organization_id` is
205
+ * password recovery) has none - it precedes any tenant - and `audit_logs.organization_id` is
206
206
  * not nullable, so those rows are written unaudited. Their lifecycle columns are the record.
207
207
  */
208
208
  class NotificationsOutboxResource {
@@ -257,7 +257,7 @@ class NotificationsOutboxResource {
257
257
  * Stamps a delivery rollup on first occurrence only. A provider that reports `delivered`
258
258
  * twice must not move the timestamp, so the guard is the column still being null.
259
259
  *
260
- * Only the rollup columns are ever touched here — `status` belongs to the send lifecycle,
260
+ * Only the rollup columns are ever touched here - `status` belongs to the send lifecycle,
261
261
  * not to what the provider reports afterwards.
262
262
  */
263
263
  async stampRollup(notification, column, value) {
@@ -274,7 +274,7 @@ class NotificationsOutboxResource {
274
274
  if (error)
275
275
  throw (0, errors_1.mapPostgrestError)(error);
276
276
  }
277
- /** The worker's load. Returns null when the row is gone rather than throwing — see `processQueuedNotification`. */
277
+ /** The worker's load. Returns null when the row is gone rather than throwing - see `processQueuedNotification`. */
278
278
  async loadForDelivery(notificationId) {
279
279
  const { data, error } = await this.supabase
280
280
  .from('notifications')
@@ -287,7 +287,7 @@ class NotificationsOutboxResource {
287
287
  }
288
288
  /**
289
289
  * Stamps a successful send. Guarded on `sent_at is null` so a duplicate delivery of the same
290
- * queue message changes nothing instead of double-stamping — the email has already gone.
290
+ * queue message changes nothing instead of double-stamping - the email has already gone.
291
291
  */
292
292
  async stampSent(notification, patch) {
293
293
  const payload = {
@@ -328,7 +328,7 @@ class NotificationsOutboxResource {
328
328
  }
329
329
  await this.rawUpdate(notification.mms_id, payload);
330
330
  }
331
- /** Retires a row nothing can rescue — an unknown template, no address, an unsupported channel. */
331
+ /** Retires a row nothing can rescue - an unknown template, no address, an unsupported channel. */
332
332
  async stampFailed(notification, patch) {
333
333
  await this.stampAttempt(notification, { ...patch, terminal: true });
334
334
  }
@@ -1,20 +1,20 @@
1
1
  import type { AuditActor } from '../audit';
2
2
  import type { TypedSupabaseClient } from '../client';
3
- /** The row an invite hands back — the id to send with the sign-up link, and when it lapses. */
3
+ /** The row an invite hands back - the id to send with the sign-up link, and when it lapses. */
4
4
  export type OrganizationInvite = {
5
5
  mms_id: string;
6
6
  expires_at: string;
7
7
  };
8
8
  /**
9
9
  * The `organization_invites` table: the record that says a given address is allowed to sign up
10
- * into a given organization. The `on_auth_user_created` trigger reads it — it requires an
10
+ * into a given organization. The `on_auth_user_created` trigger reads it - it requires an
11
11
  * unconsumed, unexpired invite matching the new auth user's email and takes the new user's
12
12
  * `organization_id` from it, so tenancy is never taken from anything the sign-up supplied.
13
13
  *
14
14
  * Service-role only: the table carries no `authenticated` grants, so this lives on the service
15
15
  * client and never on a caller's client.
16
16
  *
17
- * Not audited — there is no `AuditTrailEntityType` for an invite, so these writes leave no
17
+ * Not audited - there is no `AuditTrailEntityType` for an invite, so these writes leave no
18
18
  * `audit_logs` row. Add one to the entities package before making it audited.
19
19
  */
20
20
  export declare class OrganizationInvitesResource {
@@ -6,14 +6,14 @@ const errors_1 = require("../errors");
6
6
  const DEFAULT_TTL_MINUTES = 60;
7
7
  /**
8
8
  * The `organization_invites` table: the record that says a given address is allowed to sign up
9
- * into a given organization. The `on_auth_user_created` trigger reads it — it requires an
9
+ * into a given organization. The `on_auth_user_created` trigger reads it - it requires an
10
10
  * unconsumed, unexpired invite matching the new auth user's email and takes the new user's
11
11
  * `organization_id` from it, so tenancy is never taken from anything the sign-up supplied.
12
12
  *
13
13
  * Service-role only: the table carries no `authenticated` grants, so this lives on the service
14
14
  * client and never on a caller's client.
15
15
  *
16
- * Not audited — there is no `AuditTrailEntityType` for an invite, so these writes leave no
16
+ * Not audited - there is no `AuditTrailEntityType` for an invite, so these writes leave no
17
17
  * `audit_logs` row. Add one to the entities package before making it audited.
18
18
  */
19
19
  class OrganizationInvitesResource {
@@ -25,12 +25,12 @@ export type PaymentMethodLookupColumn = 'paystack_customer_code' | 'paystack_sub
25
25
  /**
26
26
  * The `organization_payment_methods` table: the organization's Paystack identity in one row
27
27
  * beside the `organizations` row, rather than as columns on it. The organizations READ policy
28
- * hands the whole row to every member of the tenant, and nothing here is a member's business —
28
+ * hands the whole row to every member of the tenant, and nothing here is a member's business -
29
29
  * the customer, plan and subscription codes are the provider's identifiers and the authorization
30
- * code and email token are credentials — so the table carries no `authenticated` grant and no
30
+ * code and email token are credentials - so the table carries no `authenticated` grant and no
31
31
  * policy. Only the service role can reach it.
32
32
  *
33
- * Service-role only, like the invites — this lives on the organization scope of the service
33
+ * Service-role only, like the invites - this lives on the organization scope of the service
34
34
  * client and never on a caller's client. Writes are audited against the organization (the row
35
35
  * has no identity of its own), and the audit diff redacts every `paystack_*` column, so the trail
36
36
  * records that a value changed and never what it changed to.