@managemint-solutions/sdk 0.56.0 → 0.64.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 (53) hide show
  1. package/README.md +209 -7
  2. package/dist/audit/document-changes.d.ts +39 -0
  3. package/dist/audit/document-changes.js +332 -0
  4. package/dist/audit/index.d.ts +50 -2
  5. package/dist/audit/index.js +87 -44
  6. package/dist/client.d.ts +6 -0
  7. package/dist/client.js +9 -0
  8. package/dist/clients/dto.d.ts +18 -3
  9. package/dist/clients/dto.js +72 -2
  10. package/dist/clients/index.js +16 -0
  11. package/dist/documents/content.d.ts +39 -0
  12. package/dist/documents/content.js +443 -0
  13. package/dist/documents/document-templates.d.ts +37 -0
  14. package/dist/documents/document-templates.js +143 -0
  15. package/dist/documents/documents.d.ts +154 -0
  16. package/dist/documents/documents.js +330 -0
  17. package/dist/documents/dto.d.ts +125 -0
  18. package/dist/documents/dto.js +530 -0
  19. package/dist/documents/index.d.ts +4 -0
  20. package/dist/documents/index.js +24 -0
  21. package/dist/documents/render/html.d.ts +64 -0
  22. package/dist/documents/render/html.js +399 -0
  23. package/dist/documents/render/index.d.ts +2 -0
  24. package/dist/documents/render/index.js +23 -0
  25. package/dist/documents/render/values.d.ts +86 -0
  26. package/dist/documents/render/values.js +142 -0
  27. package/dist/index.d.ts +8 -1
  28. package/dist/index.js +27 -3
  29. package/dist/leads/index.js +1 -3
  30. package/dist/notifications/index.d.ts +6 -0
  31. package/dist/notifications/index.js +16 -0
  32. package/dist/organization-payment-methods/dto.d.ts +10 -0
  33. package/dist/organization-payment-methods/dto.js +56 -0
  34. package/dist/organization-payment-methods/index.d.ts +8 -1
  35. package/dist/organization-payment-methods/index.js +23 -0
  36. package/dist/payments/index.d.ts +67 -0
  37. package/dist/payments/index.js +137 -0
  38. package/dist/permissions/dto.d.ts +4 -0
  39. package/dist/permissions/dto.js +20 -8
  40. package/dist/service-client/index.d.ts +32 -0
  41. package/dist/service-client/index.js +60 -0
  42. package/dist/staff-client.d.ts +3 -0
  43. package/dist/staff-client.js +5 -0
  44. package/dist/supporting-files/index.js +4 -6
  45. package/dist/supporting-files/paths.d.ts +2 -0
  46. package/dist/supporting-files/paths.js +3 -1
  47. package/dist/validators.d.ts +6 -0
  48. package/dist/validators.js +14 -1
  49. package/dist/visibility/dto.d.ts +15 -0
  50. package/dist/visibility/dto.js +68 -0
  51. package/dist/visibility/index.d.ts +59 -0
  52. package/dist/visibility/index.js +165 -0
  53. package/package.json +6 -2
@@ -0,0 +1,59 @@
1
+ import type { VisibilityShare } from '@managemint-solutions/entities/visibility';
2
+ import { VisibilityEntityType, type VisibilityRole } from '@managemint-solutions/entities/visibility/enum';
3
+ import { DocumentVisibility } from '@managemint-solutions/entities/documents/enum';
4
+ import { type AuditActor, type AuditResource } from '../audit';
5
+ import type { TypedSupabaseClient } from '../client';
6
+ export * from './dto';
7
+ /** One person and their role, as a write takes them. */
8
+ export type VisibilityShareInput = {
9
+ user_id: string;
10
+ role: VisibilityRole;
11
+ };
12
+ /** A record a row is filed under: its kind (its table) and its id. */
13
+ export type VisibilityRecord = {
14
+ entityType: VisibilityEntityType;
15
+ entityId: string;
16
+ };
17
+ /**
18
+ * Who each private record is shared with: `public.visibility`, one row per person per record,
19
+ * filed under the record's kind and id. On the service client's organization scope only -
20
+ * members read their own rows through the record policies and write none. entity_id has no
21
+ * foreign key (it points at several tables), so the caller first checks the record is in this
22
+ * organization; every query here is held to the scope's organization. Each write is audited
23
+ * against the record it is about, so it shows in that record's history.
24
+ */
25
+ export declare class VisibilityResource {
26
+ private readonly supabase;
27
+ private readonly actor;
28
+ private readonly audit;
29
+ private readonly table;
30
+ constructor(supabase: TypedSupabaseClient, actor: AuditActor, audit: AuditResource);
31
+ /** A record's shares with each person, oldest first - `GET .../visibility`. */
32
+ list({ entityType, entityId }: VisibilityRecord): Promise<VisibilityShare[]>;
33
+ /**
34
+ * Makes a record's shares exactly `shares` - `PUT .../visibility`: people no longer listed lose
35
+ * their row, a changed role updates it, new people get one.
36
+ */
37
+ replace(record: VisibilityRecord, shares: VisibilityShareInput[]): Promise<void>;
38
+ /**
39
+ * Sets the record's own `visibility` column - `PUT .../visibility`. Members hold no UPDATE grant
40
+ * on it, so it is written here; audited as an update of the record itself.
41
+ */
42
+ setVisibility({ entityType, entityId }: VisibilityRecord, visibility: DocumentVisibility): Promise<void>;
43
+ /** Gives `to` the same shares as `from` - a document made from a private template. */
44
+ copy(from: VisibilityRecord, to: VisibilityRecord): Promise<void>;
45
+ /**
46
+ * Deletes a record's rows, after the record itself is deleted - nothing else would. One
47
+ * statement and unaudited: the record's own DELETE is its history's last word.
48
+ */
49
+ removeAll({ entityType, entityId }: VisibilityRecord): Promise<void>;
50
+ /**
51
+ * The owner's reassign: every record of `entityType` that `fromUserId` created and that is not
52
+ * shared with the organization becomes `toUserId`'s. Resolves to how many moved. One statement;
53
+ * `created_by` is a bookkeeping column, never in an audit diff.
54
+ */
55
+ reassign(entityType: VisibilityEntityType, fromUserId: string, toUserId: string): Promise<number>;
56
+ /** A record's rows, flat - what `replace` and `copy` work from. */
57
+ private rows;
58
+ private newRow;
59
+ }
@@ -0,0 +1,165 @@
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.VisibilityResource = void 0;
18
+ const enum_1 = require("@managemint-solutions/entities/visibility/enum");
19
+ const enum_2 = require("@managemint-solutions/entities/documents/enum");
20
+ const enum_3 = require("@managemint-solutions/entities/audit-trail/enum");
21
+ const audit_1 = require("../audit");
22
+ const errors_1 = require("../errors");
23
+ const transforms_1 = require("../transforms");
24
+ __exportStar(require("./dto"), exports);
25
+ // The person is embedded through the composite same-organization key, named: visibility points
26
+ // at users three times (the person, created_by, last_updated_by).
27
+ const SHARE_SELECT = `role, user:users!visibility_user_fkey ${transforms_1.USER_PROFILE_EMBED}`;
28
+ /** Each kind of record's own history, which a change to its visibility setting is filed in. */
29
+ const RECORD_AUDIT_TYPES = {
30
+ [enum_1.VisibilityEntityType.DOCUMENT_TEMPLATES]: enum_3.AuditTrailEntityType.DOCUMENT_TEMPLATES,
31
+ [enum_1.VisibilityEntityType.DOCUMENTS]: enum_3.AuditTrailEntityType.DOCUMENTS,
32
+ };
33
+ /**
34
+ * Who each private record is shared with: `public.visibility`, one row per person per record,
35
+ * filed under the record's kind and id. On the service client's organization scope only -
36
+ * members read their own rows through the record policies and write none. entity_id has no
37
+ * foreign key (it points at several tables), so the caller first checks the record is in this
38
+ * organization; every query here is held to the scope's organization. Each write is audited
39
+ * against the record it is about, so it shows in that record's history.
40
+ */
41
+ class VisibilityResource {
42
+ supabase;
43
+ actor;
44
+ audit;
45
+ table;
46
+ constructor(supabase, actor, audit) {
47
+ this.supabase = supabase;
48
+ this.actor = actor;
49
+ this.audit = audit;
50
+ this.table = (0, audit_1.auditedTable)(supabase, actor, audit, {
51
+ table: 'visibility',
52
+ entityType: enum_3.AuditTrailEntityType.VISIBILITY,
53
+ // Every share entry names its person, so the record's history says whose access changed.
54
+ identity: ['user_id'],
55
+ });
56
+ }
57
+ /** A record's shares with each person, oldest first - `GET .../visibility`. */
58
+ async list({ entityType, entityId }) {
59
+ const { data, error } = await this.supabase
60
+ .from('visibility')
61
+ .select(SHARE_SELECT)
62
+ .eq('organization_id', this.actor.organization_id)
63
+ .eq('entity_type', entityType)
64
+ .eq('entity_id', entityId)
65
+ .order('created_at', { ascending: true });
66
+ if (error)
67
+ throw (0, errors_1.mapPostgrestError)(error);
68
+ return data;
69
+ }
70
+ /**
71
+ * Makes a record's shares exactly `shares` - `PUT .../visibility`: people no longer listed lose
72
+ * their row, a changed role updates it, new people get one.
73
+ */
74
+ async replace(record, shares) {
75
+ const existing = await this.rows(record);
76
+ const wanted = new Map(shares.map((share) => [share.user_id, share.role]));
77
+ const now = new Date().toISOString();
78
+ for (const row of existing) {
79
+ const role = wanted.get(row.user_id);
80
+ if (role === undefined) {
81
+ await this.table.remove(row.mms_id);
82
+ }
83
+ else if (role !== row.role) {
84
+ await this.table.update(row.mms_id, { role, updated_at: now, last_updated_by: this.actor.mms_id });
85
+ }
86
+ }
87
+ const added = shares.filter((share) => !existing.some((row) => row.user_id === share.user_id));
88
+ await this.table.insertMany(added.map((share) => this.newRow(record, share, now)));
89
+ }
90
+ /**
91
+ * Sets the record's own `visibility` column - `PUT .../visibility`. Members hold no UPDATE grant
92
+ * on it, so it is written here; audited as an update of the record itself.
93
+ */
94
+ async setVisibility({ entityType, entityId }, visibility) {
95
+ const record = (0, audit_1.auditedTable)(this.supabase, this.actor, this.audit, {
96
+ table: entityType,
97
+ entityType: RECORD_AUDIT_TYPES[entityType],
98
+ });
99
+ await record.update(entityId, {
100
+ visibility,
101
+ updated_at: new Date().toISOString(),
102
+ last_updated_by: this.actor.mms_id,
103
+ });
104
+ }
105
+ /** Gives `to` the same shares as `from` - a document made from a private template. */
106
+ async copy(from, to) {
107
+ const now = new Date().toISOString();
108
+ const rows = await this.rows(from);
109
+ await this.table.insertMany(rows.map((row) => this.newRow(to, row, now)));
110
+ }
111
+ /**
112
+ * Deletes a record's rows, after the record itself is deleted - nothing else would. One
113
+ * statement and unaudited: the record's own DELETE is its history's last word.
114
+ */
115
+ async removeAll({ entityType, entityId }) {
116
+ const { error } = await this.supabase
117
+ .from('visibility')
118
+ .delete()
119
+ .eq('organization_id', this.actor.organization_id)
120
+ .eq('entity_type', entityType)
121
+ .eq('entity_id', entityId);
122
+ if (error)
123
+ throw (0, errors_1.mapPostgrestError)(error);
124
+ }
125
+ /**
126
+ * The owner's reassign: every record of `entityType` that `fromUserId` created and that is not
127
+ * shared with the organization becomes `toUserId`'s. Resolves to how many moved. One statement;
128
+ * `created_by` is a bookkeeping column, never in an audit diff.
129
+ */
130
+ async reassign(entityType, fromUserId, toUserId) {
131
+ const { error, count } = await this.supabase
132
+ .from(entityType)
133
+ .update({ created_by: toUserId }, { count: 'exact' })
134
+ .eq('organization_id', this.actor.organization_id)
135
+ .eq('created_by', fromUserId)
136
+ .neq('visibility', enum_2.DocumentVisibility.ORGANIZATION);
137
+ if (error)
138
+ throw (0, errors_1.mapPostgrestError)(error);
139
+ return count ?? 0;
140
+ }
141
+ /** A record's rows, flat - what `replace` and `copy` work from. */
142
+ async rows({ entityType, entityId }) {
143
+ const { data, error } = await this.supabase
144
+ .from('visibility')
145
+ .select('mms_id, user_id, role')
146
+ .eq('organization_id', this.actor.organization_id)
147
+ .eq('entity_type', entityType)
148
+ .eq('entity_id', entityId);
149
+ if (error)
150
+ throw (0, errors_1.mapPostgrestError)(error);
151
+ return data;
152
+ }
153
+ newRow({ entityType, entityId }, share, now) {
154
+ return {
155
+ organization_id: this.actor.organization_id,
156
+ entity_type: entityType,
157
+ entity_id: entityId,
158
+ user_id: share.user_id,
159
+ role: share.role,
160
+ created_by: this.actor.mms_id,
161
+ created_at: now,
162
+ };
163
+ }
164
+ }
165
+ exports.VisibilityResource = VisibilityResource;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@managemint-solutions/sdk",
3
- "version": "0.56.0",
3
+ "version": "0.64.0",
4
4
  "description": "Typed Supabase data-access SDK for ManageMint Solutions",
5
5
  "license": "UNLICENSED",
6
6
  "author": "Scott Bebington <scottbebington@gmail.com>",
@@ -24,6 +24,10 @@
24
24
  "./cache": {
25
25
  "types": "./dist/cache/index.d.ts",
26
26
  "default": "./dist/cache/index.js"
27
+ },
28
+ "./documents": {
29
+ "types": "./dist/documents/render/index.d.ts",
30
+ "default": "./dist/documents/render/index.js"
27
31
  }
28
32
  },
29
33
  "files": [
@@ -51,7 +55,7 @@
51
55
  "testEnvironment": "node"
52
56
  },
53
57
  "dependencies": {
54
- "@managemint-solutions/entities": "^1.37.0"
58
+ "@managemint-solutions/entities": "^1.46.0"
55
59
  },
56
60
  "peerDependencies": {
57
61
  "@nestjs/common": "^11.0.0",