@managemint-solutions/sdk 0.38.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 (65) hide show
  1. package/README.md +27 -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/nest/index.d.ts +5 -5
  29. package/dist/nest/index.js +4 -4
  30. package/dist/notifications/index.d.ts +8 -8
  31. package/dist/notifications/index.js +8 -8
  32. package/dist/organization-invites/index.d.ts +3 -3
  33. package/dist/organization-invites/index.js +2 -2
  34. package/dist/organization-payment-methods/index.d.ts +3 -3
  35. package/dist/organization-payment-methods/index.js +3 -3
  36. package/dist/organizations/index.d.ts +7 -7
  37. package/dist/organizations/index.js +7 -7
  38. package/dist/permissions/index.d.ts +6 -6
  39. package/dist/permissions/index.js +6 -6
  40. package/dist/pricebooks/index.d.ts +2 -2
  41. package/dist/pricebooks/index.js +3 -3
  42. package/dist/projects/dto.js +2 -2
  43. package/dist/projects/index.d.ts +1 -1
  44. package/dist/projects/index.js +2 -2
  45. package/dist/service-client/index.d.ts +5 -5
  46. package/dist/service-client/index.js +5 -5
  47. package/dist/support/dto.js +1 -1
  48. package/dist/supporting-files/dto.js +1 -1
  49. package/dist/supporting-files/index.js +5 -5
  50. package/dist/supporting-files/paths.d.ts +3 -3
  51. package/dist/supporting-files/paths.js +4 -4
  52. package/dist/tasks/dto.js +4 -4
  53. package/dist/tasks/index.d.ts +1 -1
  54. package/dist/tasks/index.js +2 -2
  55. package/dist/transforms.d.ts +6 -6
  56. package/dist/transforms.js +8 -8
  57. package/dist/users/dto.d.ts +3 -3
  58. package/dist/users/dto.js +4 -4
  59. package/dist/users/index.d.ts +2 -2
  60. package/dist/users/index.js +2 -2
  61. package/dist/users/paths.d.ts +2 -2
  62. package/dist/users/paths.js +2 -2
  63. package/dist/webhook-events/index.d.ts +3 -3
  64. package/dist/webhook-events/index.js +3 -3
  65. package/package.json +1 -1
@@ -9,7 +9,7 @@ export type PermissionFlags = {
9
9
  } & Record<string, boolean>;
10
10
  /**
11
11
  * The `permissions` table. Rows are created by the `on_auth_user_created` trigger and deleted
12
- * with the user — INSERT and DELETE are `false` for `authenticated` — so this resource only
12
+ * with the user - INSERT and DELETE are `false` for `authenticated` - so this resource only
13
13
  * reads and updates.
14
14
  */
15
15
  export declare class PermissionsResource {
@@ -18,8 +18,8 @@ export declare class PermissionsResource {
18
18
  private readonly table;
19
19
  constructor(supabase: TypedSupabaseClient, auth: AuditActor, audit: AuditResource);
20
20
  /**
21
- * The whole permissions row. `*` rather than a select string — the alternative is naming the
22
- * two role flags and all 78 permission flags — so the internal `id` is dropped on the way out.
21
+ * The whole permissions row. `*` rather than a select string - the alternative is naming the
22
+ * two role flags and all 78 permission flags - so the internal `id` is dropped on the way out.
23
23
  */
24
24
  getForUser(userId: string): Promise<PermissionsEntity>;
25
25
  /**
@@ -28,13 +28,13 @@ export declare class PermissionsResource {
28
28
  * guard treats as a denial.
29
29
  *
30
30
  * `flag` is interpolated into the select string, so it is checked against the shape a column
31
- * name can take first — a flag never comes from a request, only from a route's own decorator,
31
+ * name can take first - a flag never comes from a request, only from a route's own decorator,
32
32
  * so anything else is a bug rather than a bad request.
33
33
  */
34
34
  flagsFor(userId: string, flag: string): Promise<PermissionFlags | null>;
35
- /** Whether a user owns the organization — the guard behind "you cannot deactivate the owner". */
35
+ /** Whether a user owns the organization - the guard behind "you cannot deactivate the owner". */
36
36
  isOwner(userId: string): Promise<boolean>;
37
- /** Who owns the organization. Null when there is no owner row yet — signup is mid-flight. */
37
+ /** Who owns the organization. Null when there is no owner row yet - signup is mid-flight. */
38
38
  ownerUserId(): Promise<string | null>;
39
39
  /**
40
40
  * Permissions are keyed by `user_id` on the wire but audited by the row's own `mms_id`, so
@@ -25,7 +25,7 @@ const PERMISSIONS_TABLE = {
25
25
  };
26
26
  /**
27
27
  * The `permissions` table. Rows are created by the `on_auth_user_created` trigger and deleted
28
- * with the user — INSERT and DELETE are `false` for `authenticated` — so this resource only
28
+ * with the user - INSERT and DELETE are `false` for `authenticated` - so this resource only
29
29
  * reads and updates.
30
30
  */
31
31
  class PermissionsResource {
@@ -38,8 +38,8 @@ class PermissionsResource {
38
38
  this.table = (0, audit_1.auditedTable)(supabase, auth, audit, PERMISSIONS_TABLE);
39
39
  }
40
40
  /**
41
- * The whole permissions row. `*` rather than a select string — the alternative is naming the
42
- * two role flags and all 78 permission flags — so the internal `id` is dropped on the way out.
41
+ * The whole permissions row. `*` rather than a select string - the alternative is naming the
42
+ * two role flags and all 78 permission flags - so the internal `id` is dropped on the way out.
43
43
  */
44
44
  async getForUser(userId) {
45
45
  const { data, error } = await this.supabase
@@ -58,7 +58,7 @@ class PermissionsResource {
58
58
  * guard treats as a denial.
59
59
  *
60
60
  * `flag` is interpolated into the select string, so it is checked against the shape a column
61
- * name can take first — a flag never comes from a request, only from a route's own decorator,
61
+ * name can take first - a flag never comes from a request, only from a route's own decorator,
62
62
  * so anything else is a bug rather than a bad request.
63
63
  */
64
64
  async flagsFor(userId, flag) {
@@ -79,7 +79,7 @@ class PermissionsResource {
79
79
  throw (0, errors_1.mapPostgrestError)(error);
80
80
  return (data ?? null);
81
81
  }
82
- /** Whether a user owns the organization — the guard behind "you cannot deactivate the owner". */
82
+ /** Whether a user owns the organization - the guard behind "you cannot deactivate the owner". */
83
83
  async isOwner(userId) {
84
84
  const { data, error } = await this.supabase
85
85
  .from('permissions')
@@ -91,7 +91,7 @@ class PermissionsResource {
91
91
  throw (0, errors_1.mapPostgrestError)(error);
92
92
  return data?.is_owner === true;
93
93
  }
94
- /** Who owns the organization. Null when there is no owner row yet — signup is mid-flight. */
94
+ /** Who owns the organization. Null when there is no owner row yet - signup is mid-flight. */
95
95
  async ownerUserId() {
96
96
  const { data, error } = await this.supabase
97
97
  .from('permissions')
@@ -2,7 +2,7 @@ import type { SupabaseClient as SupabaseJsClient } from '@supabase/supabase-js';
2
2
  import type { PricebookWithModules } from '@managemint-solutions/entities/modules';
3
3
  /**
4
4
  * The public price catalog. `pricebooks`, `pricebook_modules` and `billing_modules` are readable
5
- * by `anon` by design — unauthenticated signup prices against them — so this resource takes no
5
+ * by `anon` by design - unauthenticated signup prices against them - so this resource takes no
6
6
  * auth context and scopes by nothing.
7
7
  */
8
8
  export declare class PricebooksResource {
@@ -13,7 +13,7 @@ export declare class PricebooksResource {
13
13
  }
14
14
  /**
15
15
  * What the given modules cost per month, in minor units: every module's unit price summed and
16
- * multiplied by the seat count. A module the pricebook does not price is a 400 — the caller
16
+ * multiplied by the seat count. A module the pricebook does not price is a 400 - the caller
17
17
  * asked for something that cannot be billed.
18
18
  */
19
19
  export declare const monthlyTotalMinor: (pricebook: PricebookWithModules, moduleKeys: string[], seatCount: number) => number;
@@ -19,7 +19,7 @@ const PRICEBOOK_SELECT = `
19
19
  )
20
20
  )
21
21
  `;
22
- // A pricebook_modules row whose catalog entry did not come back leaves `module_key` undefined —
22
+ // A pricebook_modules row whose catalog entry did not come back leaves `module_key` undefined -
23
23
  // the cast keeps the mapping honest about that rather than inventing a key.
24
24
  const toPricebookWithModules = (row) => ({
25
25
  mms_id: row.mms_id,
@@ -35,7 +35,7 @@ const toPricebookWithModules = (row) => ({
35
35
  });
36
36
  /**
37
37
  * The public price catalog. `pricebooks`, `pricebook_modules` and `billing_modules` are readable
38
- * by `anon` by design — unauthenticated signup prices against them — so this resource takes no
38
+ * by `anon` by design - unauthenticated signup prices against them - so this resource takes no
39
39
  * auth context and scopes by nothing.
40
40
  */
41
41
  class PricebooksResource {
@@ -67,7 +67,7 @@ class PricebooksResource {
67
67
  exports.PricebooksResource = PricebooksResource;
68
68
  /**
69
69
  * What the given modules cost per month, in minor units: every module's unit price summed and
70
- * multiplied by the seat count. A module the pricebook does not price is a 400 — the caller
70
+ * multiplied by the seat count. A module the pricebook does not price is a 400 - the caller
71
71
  * asked for something that cannot be billed.
72
72
  */
73
73
  const monthlyTotalMinor = (pricebook, moduleKeys, seatCount) => {
@@ -196,7 +196,7 @@ __decorate([
196
196
  (0, class_validator_1.IsOptional)(),
197
197
  (0, validators_1.IsNullable)()
198
198
  // Still v4: a manager is a `users.mms_id`, and that column carries the GoTrue auth uid the
199
- // signup trigger copies out of `auth.users.id` — the table's uuidv7 default never fires.
199
+ // signup trigger copies out of `auth.users.id` - the table's uuidv7 default never fires.
200
200
  ,
201
201
  (0, class_validator_1.IsUUID)('4', { message: 'Invalid manager ID format' }),
202
202
  __metadata("design:type", Object)
@@ -256,7 +256,7 @@ __decorate([
256
256
  __decorate([
257
257
  (0, class_validator_1.IsOptional)(),
258
258
  (0, validators_1.IsNullable)()
259
- // Still v4 — a manager is a `users.mms_id`, the GoTrue auth uid (see CreateProjectDto).
259
+ // Still v4 - a manager is a `users.mms_id`, the GoTrue auth uid (see CreateProjectDto).
260
260
  ,
261
261
  (0, class_validator_1.IsUUID)('4', { message: 'Invalid manager ID format' }),
262
262
  __metadata("design:type", Object)
@@ -17,6 +17,6 @@ export declare class ProjectsResource {
17
17
  archive(projectId: string): Promise<ProjectEntity>;
18
18
  unarchive(projectId: string): Promise<ProjectEntity>;
19
19
  restore(projectId: string): Promise<ProjectEntity>;
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(projectId: string): Promise<void>;
22
22
  }
@@ -126,7 +126,7 @@ class ProjectsResource {
126
126
  }
127
127
  // Excluding statuses has to be spelled out as "no status OR not one of these": PostgREST can
128
128
  // only filter a parent row by an embedded column with `!inner`, which would drop projects that
129
- // have no status at all — and a project with no status is not complete, so it belongs in the
129
+ // have no status at all - and a project with no status is not complete, so it belongs in the
130
130
  // default view. SQL's `NOT IN` drops nulls for the same reason, hence the explicit null arm.
131
131
  // The ids are `@IsUUID('7')`-validated by the DTO, so interpolating them is safe. Repeated
132
132
  // `or` params are ANDed by PostgREST, so this composes with the search filter above.
@@ -205,7 +205,7 @@ class ProjectsResource {
205
205
  await this.table.transition(projectId, enum_1.AuditTrailAction.RESTORE, (0, transforms_1.restoredPatch)(this.auth.mms_id));
206
206
  return this.getById(projectId);
207
207
  }
208
- /** Soft delete — the row stays, flagged `deleted`, and `restore()` brings it back. */
208
+ /** Soft delete - the row stays, flagged `deleted`, and `restore()` brings it back. */
209
209
  async remove(projectId) {
210
210
  await this.table.transition(projectId, enum_1.AuditTrailAction.DELETE, (0, transforms_1.deletedPatch)(this.auth.mms_id));
211
211
  }
@@ -13,14 +13,14 @@ import { UsersResource } from '../users';
13
13
  import { WebhookEventsResource } from '../webhook-events';
14
14
  export type SupabaseServiceClientConfig = {
15
15
  url: string;
16
- /** Service-role key — every query bypasses RLS. */
16
+ /** Service-role key - every query bypasses RLS. */
17
17
  serviceRoleKey: string;
18
18
  /** Where a failed audit insert is reported. Defaults to `console.error`. */
19
19
  onAuditError?: AuditErrorHandler;
20
20
  };
21
21
  /**
22
22
  * The organization-scoped half of the service client. Everything here is attributed to one
23
- * `AuditActor`, so writes land in `audit_logs` the same way a caller's own would — with
23
+ * `AuditActor`, so writes land in `audit_logs` the same way a caller's own would - with
24
24
  * `mms_id: null` when the actor is the system (a webhook, a queue worker, provisioning).
25
25
  */
26
26
  export declare class SupabaseOrganizationScope {
@@ -36,7 +36,7 @@ export declare class SupabaseOrganizationScope {
36
36
  readonly users: UsersResource;
37
37
  constructor(supabase: TypedSupabaseClient, actor: AuditActor, onAuditError?: AuditErrorHandler);
38
38
  /**
39
- * An audited table bound to this organization and actor — the shape the api hand-rolls today
39
+ * An audited table bound to this organization and actor - the shape the api hand-rolls today
40
40
  * as a local `auditedTables(client, organizationId)` factory in billing, provisioning,
41
41
  * subscriptions and both webhook handler services.
42
42
  */
@@ -46,7 +46,7 @@ export declare class SupabaseOrganizationScope {
46
46
  * The client for work that has no caller and no RLS context to run under: inbound webhooks
47
47
  * (Paystack, Resend, the Supabase `send_email` hook), the notification queue worker, unauthenticated
48
48
  * signup, the website's feature-request intake, and the writes RLS reserves for the service role
49
- * outright — the ledger, the outbox, the webhook event logs, `organizations` INSERT, `permissions`
49
+ * outright - the ledger, the outbox, the webhook event logs, `organizations` INSERT, `permissions`
50
50
  * INSERT/DELETE.
51
51
  *
52
52
  * It decodes no JWT, because there is none. Cross-org lookups (find the organization behind a
@@ -64,7 +64,7 @@ export declare class SupabaseServiceClient {
64
64
  readonly resendEvents: WebhookEventsResource;
65
65
  constructor(config: SupabaseServiceClientConfig);
66
66
  /**
67
- * Scope to one organization once it is known. `actorMmsId` stays `null` for system work —
67
+ * Scope to one organization once it is known. `actorMmsId` stays `null` for system work -
68
68
  * `audit_logs.created_by` is nullable precisely so an unattributed write is still recorded.
69
69
  */
70
70
  forOrganization(organizationId: string, actorMmsId?: string | null): SupabaseOrganizationScope;
@@ -18,7 +18,7 @@ const users_1 = require("../users");
18
18
  const webhook_events_1 = require("../webhook-events");
19
19
  /**
20
20
  * The organization-scoped half of the service client. Everything here is attributed to one
21
- * `AuditActor`, so writes land in `audit_logs` the same way a caller's own would — with
21
+ * `AuditActor`, so writes land in `audit_logs` the same way a caller's own would - with
22
22
  * `mms_id: null` when the actor is the system (a webhook, a queue worker, provisioning).
23
23
  */
24
24
  class SupabaseOrganizationScope {
@@ -45,7 +45,7 @@ class SupabaseOrganizationScope {
45
45
  this.users = new users_1.UsersResource(supabase, actor, this.audit);
46
46
  }
47
47
  /**
48
- * An audited table bound to this organization and actor — the shape the api hand-rolls today
48
+ * An audited table bound to this organization and actor - the shape the api hand-rolls today
49
49
  * as a local `auditedTables(client, organizationId)` factory in billing, provisioning,
50
50
  * subscriptions and both webhook handler services.
51
51
  */
@@ -58,7 +58,7 @@ exports.SupabaseOrganizationScope = SupabaseOrganizationScope;
58
58
  * The client for work that has no caller and no RLS context to run under: inbound webhooks
59
59
  * (Paystack, Resend, the Supabase `send_email` hook), the notification queue worker, unauthenticated
60
60
  * signup, the website's feature-request intake, and the writes RLS reserves for the service role
61
- * outright — the ledger, the outbox, the webhook event logs, `organizations` INSERT, `permissions`
61
+ * outright - the ledger, the outbox, the webhook event logs, `organizations` INSERT, `permissions`
62
62
  * INSERT/DELETE.
63
63
  *
64
64
  * It decodes no JWT, because there is none. Cross-org lookups (find the organization behind a
@@ -85,7 +85,7 @@ class SupabaseServiceClient {
85
85
  this.featureRequests = new feature_requests_1.FeatureRequestsResource(this.supabase);
86
86
  this.configs = new configs_1.ConfigsResource(this.supabase);
87
87
  this.signup = new organizations_1.OrganizationSignupResource(this.supabase, (organizationId) => this.forOrganization(organizationId).audit);
88
- // The outbox spans organizations — the row it is about carries its own — so it takes a
88
+ // The outbox spans organizations - the row it is about carries its own - so it takes a
89
89
  // factory and scopes per write rather than being built inside one organization's scope.
90
90
  this.notifications = new notifications_1.NotificationsOutboxResource(this.supabase, (organizationId) => this.forOrganization(organizationId).table({
91
91
  table: 'notifications',
@@ -93,7 +93,7 @@ class SupabaseServiceClient {
93
93
  }));
94
94
  }
95
95
  /**
96
- * Scope to one organization once it is known. `actorMmsId` stays `null` for system work —
96
+ * Scope to one organization once it is known. `actorMmsId` stays `null` for system work -
97
97
  * `audit_logs.created_by` is nullable precisely so an unattributed write is still recorded.
98
98
  */
99
99
  forOrganization(organizationId, actorMmsId = null) {
@@ -18,7 +18,7 @@ const validators_1 = require("../validators");
18
18
  // wire contract cannot drift.
19
19
  /**
20
20
  * Whitespace on either side of a pasted value is not part of the answer. Trimming here rather
21
- * than in the api means the length rules below measure what will actually be sent — a name of
21
+ * than in the api means the length rules below measure what will actually be sent - a name of
22
22
  * three spaces is empty, not three characters long.
23
23
  */
24
24
  const Trim = () => (0, class_transformer_1.Transform)(({ value }) => (typeof value === 'string' ? value.trim() : value), {
@@ -14,7 +14,7 @@ const class_validator_1 = require("class-validator");
14
14
  const enum_1 = require("@managemint-solutions/entities/supporting-files/enum");
15
15
  // class-validator versions of the shared DTO types from @managemint-solutions/entities.
16
16
  // Each class `implements` its entities type so the wire contract cannot drift. There is no class
17
- // for the upload payload — it arrives as multipart and is not validated by class-validator.
17
+ // for the upload payload - it arrives as multipart and is not validated by class-validator.
18
18
  class SupportingFileIdDto {
19
19
  supportingFileId;
20
20
  }
@@ -33,7 +33,7 @@ const fileNameOf = (file) => file.extension ? `${file.name}.${file.extension}` :
33
33
  // casts at the returns declare the shape the select strings below produce (the columns are
34
34
  // defined in the api's supabase/migrations).
35
35
  //
36
- // Object keys are `organizationId/entityType/entityId/file` — the organization leads so a storage
36
+ // Object keys are `organizationId/entityType/entityId/file` - the organization leads so a storage
37
37
  // policy can scope by tenant. A data migration renames the pre-existing objects, which have no
38
38
  // organization segment, into that prefix.
39
39
  class SupportingFilesResource {
@@ -87,13 +87,13 @@ class SupportingFilesResource {
87
87
  throw (0, errors_1.mapPostgrestError)(existingError);
88
88
  const existingFileNames = existing.map(fileNameOf);
89
89
  // Each client name is validated once here, and the object key, the duplicate check and the
90
- // row are all built from that same split — so what is stored is what presign and remove
90
+ // row are all built from that same split - so what is stored is what presign and remove
91
91
  // rebuild later.
92
92
  const uploads = input.files.map((file) => ({
93
93
  file,
94
94
  ...(0, paths_1.splitFileName)((0, paths_1.sanitizeFileName)(file.name)),
95
95
  }));
96
- // Every file is written to the bucket, duplicates included — an upsert refreshes the object.
96
+ // Every file is written to the bucket, duplicates included - an upsert refreshes the object.
97
97
  for (let index = 0; index < uploads.length; index += UPLOAD_BATCH_SIZE) {
98
98
  await Promise.all(uploads.slice(index, index + UPLOAD_BATCH_SIZE).map(async ({ file, name, extension }) => {
99
99
  const { error } = await this.supabase.storage
@@ -104,7 +104,7 @@ class SupportingFilesResource {
104
104
  }
105
105
  }));
106
106
  }
107
- // Only files without an existing row get one — the rest were refreshed in place above.
107
+ // Only files without an existing row get one - the rest were refreshed in place above.
108
108
  const newFiles = uploads.filter((file) => !existingFileNames.includes(fileNameOf(file)));
109
109
  if (newFiles.length > 0) {
110
110
  await this.table.insertMany(newFiles.map(({ name, extension }) => ({
@@ -120,7 +120,7 @@ class SupportingFilesResource {
120
120
  return this.list(entity, entityId);
121
121
  }
122
122
  async remove(supportingFileId) {
123
- // The row goes first — the helper's pre-read hands back what the object path is built from.
123
+ // The row goes first - the helper's pre-read hands back what the object path is built from.
124
124
  const data = await this.table.remove(supportingFileId);
125
125
  const { error: storageError } = await this.supabase.storage
126
126
  .from(BUCKET)
@@ -2,13 +2,13 @@
2
2
  * The client-supplied file name, checked before it is allowed anywhere near an object key.
3
3
  *
4
4
  * The name is half of the key, so a separator or a `..` in it would let an upload escape its
5
- * entity's folder — and, now that the key starts with the organization, its tenant's folder.
5
+ * entity's folder - and, now that the key starts with the organization, its tenant's folder.
6
6
  * Anything that is not a plain file name is rejected outright rather than rewritten, so what the
7
7
  * `supporting_files` row records is exactly what was stored.
8
8
  */
9
9
  export declare const sanitizeFileName: (fileName: string) => string;
10
10
  /**
11
- * Splits an uploaded file name into the `name` / `extension` columns, on the *last* dot — so
11
+ * Splits an uploaded file name into the `name` / `extension` columns, on the *last* dot - so
12
12
  * `archive.tar.gz` is name `archive.tar`, extension `gz`, and `storagePath` rebuilds the key it
13
13
  * was stored under. A name with no dot has no extension.
14
14
  */
@@ -18,7 +18,7 @@ export declare const splitFileName: (fileName: string) => {
18
18
  };
19
19
  /**
20
20
  * Where an object lives in the `supporting-files` bucket. The organization leads the key so a
21
- * storage policy can scope objects by tenant — nothing below it is trusted for that.
21
+ * storage policy can scope objects by tenant - nothing below it is trusted for that.
22
22
  *
23
23
  * A data migration renames the existing objects (keyed `entity/entityId/file`) into their
24
24
  * organization's prefix; keys written from here already carry it.
@@ -4,14 +4,14 @@ exports.storagePath = exports.splitFileName = exports.sanitizeFileName = void 0;
4
4
  const errors_1 = require("../errors");
5
5
  /** Longest object-key segment a file name may become. */
6
6
  const MAX_FILE_NAME_LENGTH = 255;
7
- /** What a file name may be made of — no separators, no control characters, no leading dot. */
7
+ /** What a file name may be made of - no separators, no control characters, no leading dot. */
8
8
  const SAFE_FILE_NAME = /^[A-Za-z0-9][A-Za-z0-9 ._()\-]*$/;
9
9
  const invalidFileName = () => new errors_1.SupabaseClientError({ status: 400, error: 'Storage Error', message: 'Invalid file name' });
10
10
  /**
11
11
  * The client-supplied file name, checked before it is allowed anywhere near an object key.
12
12
  *
13
13
  * The name is half of the key, so a separator or a `..` in it would let an upload escape its
14
- * entity's folder — and, now that the key starts with the organization, its tenant's folder.
14
+ * entity's folder - and, now that the key starts with the organization, its tenant's folder.
15
15
  * Anything that is not a plain file name is rejected outright rather than rewritten, so what the
16
16
  * `supporting_files` row records is exactly what was stored.
17
17
  */
@@ -31,7 +31,7 @@ const sanitizeFileName = (fileName) => {
31
31
  };
32
32
  exports.sanitizeFileName = sanitizeFileName;
33
33
  /**
34
- * Splits an uploaded file name into the `name` / `extension` columns, on the *last* dot — so
34
+ * Splits an uploaded file name into the `name` / `extension` columns, on the *last* dot - so
35
35
  * `archive.tar.gz` is name `archive.tar`, extension `gz`, and `storagePath` rebuilds the key it
36
36
  * was stored under. A name with no dot has no extension.
37
37
  */
@@ -44,7 +44,7 @@ const splitFileName = (fileName) => {
44
44
  exports.splitFileName = splitFileName;
45
45
  /**
46
46
  * Where an object lives in the `supporting-files` bucket. The organization leads the key so a
47
- * storage policy can scope objects by tenant — nothing below it is trusted for that.
47
+ * storage policy can scope objects by tenant - nothing below it is trusted for that.
48
48
  *
49
49
  * A data migration renames the existing objects (keyed `entity/entityId/file`) into their
50
50
  * organization's prefix; keys written from here already carry it.
package/dist/tasks/dto.js CHANGED
@@ -21,7 +21,7 @@ class TaskIdDto {
21
21
  }
22
22
  exports.TaskIdDto = TaskIdDto;
23
23
  __decorate([
24
- (0, class_validator_1.IsUUID)('7', { message: 'Invalid project ID format' }) // sic — the api's message, kept for parity
24
+ (0, class_validator_1.IsUUID)('7', { message: 'Invalid project ID format' }) // sic - the api's message, kept for parity
25
25
  ,
26
26
  __metadata("design:type", String)
27
27
  ], TaskIdDto.prototype, "taskId", void 0);
@@ -92,7 +92,7 @@ __decorate([
92
92
  (0, class_validator_1.IsOptional)(),
93
93
  (0, validators_1.IsNullable)()
94
94
  // Still v4: the assignee is a `users.mms_id`, and that column carries the GoTrue auth uid the
95
- // signup trigger copies out of `auth.users.id` — the table's uuidv7 default never fires.
95
+ // signup trigger copies out of `auth.users.id` - the table's uuidv7 default never fires.
96
96
  ,
97
97
  (0, class_validator_1.IsUUID)('4', { message: 'Invalid assigned to ID format' }),
98
98
  __metadata("design:type", Object)
@@ -222,7 +222,7 @@ __decorate([
222
222
  __decorate([
223
223
  (0, class_validator_1.IsOptional)(),
224
224
  (0, validators_1.IsNullable)()
225
- // Still v4 — an assignee is a `users.mms_id`, the GoTrue auth uid (see GetTasksDto).
225
+ // Still v4 - an assignee is a `users.mms_id`, the GoTrue auth uid (see GetTasksDto).
226
226
  ,
227
227
  (0, class_validator_1.IsUUID)('4', { message: 'Invalid assigned to ID format' }),
228
228
  __metadata("design:type", Object)
@@ -295,7 +295,7 @@ __decorate([
295
295
  __decorate([
296
296
  (0, class_validator_1.IsOptional)(),
297
297
  (0, validators_1.IsNullable)()
298
- // Still v4 — an assignee is a `users.mms_id`, the GoTrue auth uid (see GetTasksDto).
298
+ // Still v4 - an assignee is a `users.mms_id`, the GoTrue auth uid (see GetTasksDto).
299
299
  ,
300
300
  (0, class_validator_1.IsUUID)('4', { message: 'Invalid assigned to ID format' }),
301
301
  __metadata("design:type", Object)
@@ -17,6 +17,6 @@ export declare class TasksResource {
17
17
  archive(taskId: string): Promise<TaskEntity>;
18
18
  unarchive(taskId: string): Promise<TaskEntity>;
19
19
  restore(taskId: string): Promise<TaskEntity>;
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(taskId: string): Promise<void>;
22
22
  }
@@ -140,7 +140,7 @@ class TasksResource {
140
140
  }
141
141
  // Excluding statuses has to be spelled out as "no status OR not one of these": PostgREST can
142
142
  // only filter a parent row by an embedded column with `!inner`, which would drop tasks that
143
- // have no status at all — and a task with no status is not complete, so it belongs in the
143
+ // have no status at all - and a task with no status is not complete, so it belongs in the
144
144
  // default view. SQL's `NOT IN` drops nulls for the same reason, hence the explicit null arm.
145
145
  // The ids are `@IsUUID('7')`-validated by the DTO, so interpolating them is safe. Repeated
146
146
  // `or` params are ANDed by PostgREST, so this composes with the search filter above.
@@ -197,7 +197,7 @@ class TasksResource {
197
197
  await this.table.transition(taskId, enum_1.AuditTrailAction.RESTORE, (0, transforms_1.restoredPatch)(this.auth.mms_id));
198
198
  return this.getById(taskId);
199
199
  }
200
- /** Soft delete — the row stays, flagged `deleted`, and `restore()` brings it back. */
200
+ /** Soft delete - the row stays, flagged `deleted`, and `restore()` brings it back. */
201
201
  async remove(taskId) {
202
202
  await this.table.transition(taskId, enum_1.AuditTrailAction.DELETE, (0, transforms_1.deletedPatch)(this.auth.mms_id));
203
203
  }
@@ -2,24 +2,24 @@ import type { MmsList } from '@managemint-solutions/entities/common';
2
2
  /**
3
3
  * The `client_id` / `project_id` list filters accept either a plain UUID v7 or the base64-JSON
4
4
  * option value the portal's selects send (`{ mms_id }`, or `{ id }` as a fallback). Anything that
5
- * is not one of those — including a value that decodes to JSON without a UUID v7 — cannot filter
5
+ * is not one of those - including a value that decodes to JSON without a UUID v7 - cannot filter
6
6
  * anything, so it becomes `null` and the filter is skipped.
7
7
  */
8
8
  export declare const parseEntityIdFilter: (value: unknown) => string | null;
9
9
  /**
10
10
  * A `%value%` ilike pattern, double-quoted for PostgREST's `or=(...)` grammar so `,`, `(`, `)`,
11
11
  * `.`, `"` and `\` in the search stay literal instead of being read as more filters. Inside the
12
- * quotes only `"` and `\` need escaping, which is what PostgREST defines — the `\,` the list
12
+ * quotes only `"` and `\` need escaping, which is what PostgREST defines - the `\,` the list
13
13
  * endpoints used to emit was never an escape at all. LIKE's own wildcards `%` and `_` are left
14
14
  * alone and still match as wildcards; they only widen the caller's own search, never its scope.
15
15
  */
16
16
  export declare const ilikeContains: (value: string) => string;
17
- /** The `or=(...)` argument matching `search` against any of `columns` — `name.ilike."%x%",…`. */
17
+ /** The `or=(...)` argument matching `search` against any of `columns` - `name.ilike."%x%",…`. */
18
18
  export declare const orIlike: (columns: readonly string[], search: string) => string;
19
19
  /**
20
20
  * `date` columns take an ISO string. The shared `CreateProjectDto`/`UpdateProjectDto` types
21
- * declare `Date`, but over the wire the value is the validated `@IsDateString` string — which
22
- * must reach Postgres byte-identical ('2026-04-22' is a plain date, not an instant) — so only a
21
+ * declare `Date`, but over the wire the value is the validated `@IsDateString` string - which
22
+ * must reach Postgres byte-identical ('2026-04-22' is a plain date, not an instant) - so only a
23
23
  * real `Date` (a portal caller) is serialized.
24
24
  */
25
25
  export declare const toDateInput: (value: Date | string | null | undefined) => string | null | undefined;
@@ -31,7 +31,7 @@ export declare const toDateInput: (value: Date | string | null | undefined) => s
31
31
  export declare const USER_PROFILE_EMBED: "(\n mms_id,\n name,\n surname,\n email,\n profile_image\n )";
32
32
  /**
33
33
  * The `MmsList` envelope every paginated read returns. `rows` is `unknown` because each select
34
- * string produces its own row shape — the caller's `T` is what declares it. `count` is
34
+ * string produces its own row shape - the caller's `T` is what declares it. `count` is
35
35
  * PostgREST's estimate, so an empty page reports 0 total pages rather than 1.
36
36
  */
37
37
  export declare const toMmsList: <T>(rows: unknown, page: number, pageSize: number, count: number | null) => MmsList<T>;
@@ -3,7 +3,7 @@
3
3
  // select strings and their list results.
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
5
  exports.restoredPatch = exports.deletedPatch = exports.unarchivedPatch = exports.archivedPatch = exports.toMmsList = exports.USER_PROFILE_EMBED = exports.toDateInput = exports.orIlike = exports.ilikeContains = exports.parseEntityIdFilter = void 0;
6
- // v7, to match the `mms_id` columns these filters compare against — `public.uuidv7()` is the
6
+ // v7, to match the `mms_id` columns these filters compare against - `public.uuidv7()` is the
7
7
  // default on every table. This is the gate in front of `@IsUUID('7')`, so a stricter version
8
8
  // here would null the id out before validation ever saw it, and a looser one would let a value
9
9
  // through that the DTO then rejects.
@@ -11,7 +11,7 @@ const UUID_V7 = /^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f
11
11
  /**
12
12
  * The `client_id` / `project_id` list filters accept either a plain UUID v7 or the base64-JSON
13
13
  * option value the portal's selects send (`{ mms_id }`, or `{ id }` as a fallback). Anything that
14
- * is not one of those — including a value that decodes to JSON without a UUID v7 — cannot filter
14
+ * is not one of those - including a value that decodes to JSON without a UUID v7 - cannot filter
15
15
  * anything, so it becomes `null` and the filter is skipped.
16
16
  */
17
17
  const parseEntityIdFilter = (value) => {
@@ -35,19 +35,19 @@ exports.parseEntityIdFilter = parseEntityIdFilter;
35
35
  /**
36
36
  * A `%value%` ilike pattern, double-quoted for PostgREST's `or=(...)` grammar so `,`, `(`, `)`,
37
37
  * `.`, `"` and `\` in the search stay literal instead of being read as more filters. Inside the
38
- * quotes only `"` and `\` need escaping, which is what PostgREST defines — the `\,` the list
38
+ * quotes only `"` and `\` need escaping, which is what PostgREST defines - the `\,` the list
39
39
  * endpoints used to emit was never an escape at all. LIKE's own wildcards `%` and `_` are left
40
40
  * alone and still match as wildcards; they only widen the caller's own search, never its scope.
41
41
  */
42
42
  const ilikeContains = (value) => `"%${value.replace(/[\\"]/g, '\\$&')}%"`;
43
43
  exports.ilikeContains = ilikeContains;
44
- /** The `or=(...)` argument matching `search` against any of `columns` — `name.ilike."%x%",…`. */
44
+ /** The `or=(...)` argument matching `search` against any of `columns` - `name.ilike."%x%",…`. */
45
45
  const orIlike = (columns, search) => columns.map((column) => `${column}.ilike.${(0, exports.ilikeContains)(search)}`).join(',');
46
46
  exports.orIlike = orIlike;
47
47
  /**
48
48
  * `date` columns take an ISO string. The shared `CreateProjectDto`/`UpdateProjectDto` types
49
- * declare `Date`, but over the wire the value is the validated `@IsDateString` string — which
50
- * must reach Postgres byte-identical ('2026-04-22' is a plain date, not an instant) — so only a
49
+ * declare `Date`, but over the wire the value is the validated `@IsDateString` string - which
50
+ * must reach Postgres byte-identical ('2026-04-22' is a plain date, not an instant) - so only a
51
51
  * real `Date` (a portal caller) is serialized.
52
52
  */
53
53
  const toDateInput = (value) => value instanceof Date ? value.toISOString() : value;
@@ -66,7 +66,7 @@ exports.USER_PROFILE_EMBED = `(
66
66
  )`;
67
67
  /**
68
68
  * The `MmsList` envelope every paginated read returns. `rows` is `unknown` because each select
69
- * string produces its own row shape — the caller's `T` is what declares it. `count` is
69
+ * string produces its own row shape - the caller's `T` is what declares it. `count` is
70
70
  * PostgREST's estimate, so an empty page reports 0 total pages rather than 1.
71
71
  */
72
72
  const toMmsList = (rows, page, pageSize, count) => {
@@ -85,7 +85,7 @@ const toMmsList = (rows, page, pageSize, count) => {
85
85
  exports.toMmsList = toMmsList;
86
86
  // The soft archive/delete patches projects, tasks and clients all write: the flag the transition
87
87
  // sets, plus the who/when stamps named after it. `unarchived`/`restored` clear the flag their
88
- // counterpart set and stamp their own columns — the earlier ones stay as the history.
88
+ // counterpart set and stamp their own columns - the earlier ones stay as the history.
89
89
  const archivedPatch = (by) => ({
90
90
  archived: true,
91
91
  archived_at: new Date().toISOString(),
@@ -16,7 +16,7 @@ export declare class AddUserDto implements CreateUserDtoType {
16
16
  * Optional: an internally created user - the owner at signup - has no client
17
17
  * request behind it, and one is generated for it.
18
18
  *
19
- * Still v4: the key is not an `mms_id` — the column is `text` — and the api fills a missing
19
+ * Still v4: the key is not an `mms_id` - the column is `text` - and the api fills a missing
20
20
  * one with `randomUUID()`, which is v4.
21
21
  */
22
22
  readonly idempotency_key?: string;
@@ -50,13 +50,13 @@ export declare class UpdateUserDto implements UpdateUserDtoType {
50
50
  readonly emergency_contact_email?: string | null;
51
51
  }
52
52
  /**
53
- * `PATCH /users/me` — what a member may change about themselves.
53
+ * `PATCH /users/me` - what a member may change about themselves.
54
54
  *
55
55
  * Every field here also appears on UpdateUserDto with the same constraints; what makes
56
56
  * this a separate class is what it *omits*. The api's ValidationPipe runs
57
57
  * `whitelist + forbidNonWhitelisted`, so a self-service request carrying `job_title`,
58
58
  * `manager_id`, `employment_type`, `start_date`, `end_date` or `profile_image` is
59
- * rejected with a 400 rather than silently ignored — the narrowing is the guard.
59
+ * rejected with a 400 rather than silently ignored - the narrowing is the guard.
60
60
  */
61
61
  export declare class UpdateMyProfileDto implements UpdateMyProfileDtoType {
62
62
  readonly name: string;
package/dist/users/dto.js CHANGED
@@ -38,7 +38,7 @@ class AddUserDto {
38
38
  * Optional: an internally created user - the owner at signup - has no client
39
39
  * request behind it, and one is generated for it.
40
40
  *
41
- * Still v4: the key is not an `mms_id` — the column is `text` — and the api fills a missing
41
+ * Still v4: the key is not an `mms_id` - the column is `text` - and the api fills a missing
42
42
  * one with `randomUUID()`, which is v4.
43
43
  */
44
44
  idempotency_key;
@@ -87,7 +87,7 @@ __decorate([
87
87
  __metadata("design:type", String)
88
88
  ], AddUserDto.prototype, "idempotency_key", void 0);
89
89
  // `active_in` arrives as a CSV string and is transformed to booleans, so it is omitted from the
90
- // implemented contract — the same exception GetClientsDto makes for status_id_in.
90
+ // implemented contract - the same exception GetClientsDto makes for status_id_in.
91
91
  class GetUsersQueryDto {
92
92
  search;
93
93
  page = 1;
@@ -284,13 +284,13 @@ __decorate([
284
284
  __metadata("design:type", Object)
285
285
  ], UpdateUserDto.prototype, "emergency_contact_email", void 0);
286
286
  /**
287
- * `PATCH /users/me` — what a member may change about themselves.
287
+ * `PATCH /users/me` - what a member may change about themselves.
288
288
  *
289
289
  * Every field here also appears on UpdateUserDto with the same constraints; what makes
290
290
  * this a separate class is what it *omits*. The api's ValidationPipe runs
291
291
  * `whitelist + forbidNonWhitelisted`, so a self-service request carrying `job_title`,
292
292
  * `manager_id`, `employment_type`, `start_date`, `end_date` or `profile_image` is
293
- * rejected with a 400 rather than silently ignored — the narrowing is the guard.
293
+ * rejected with a 400 rather than silently ignored - the narrowing is the guard.
294
294
  */
295
295
  class UpdateMyProfileDto {
296
296
  name;