@managemint-solutions/sdk 0.8.0 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +73 -1
- package/dist/additional-details/index.d.ts +3 -1
- package/dist/additional-details/index.js +15 -28
- package/dist/additional-details/index.js.map +1 -1
- package/dist/audit/dto.d.ts +13 -0
- package/dist/audit/dto.js +90 -0
- package/dist/audit/dto.js.map +1 -0
- package/dist/audit/index.d.ts +104 -0
- package/dist/audit/index.js +308 -0
- package/dist/audit/index.js.map +1 -0
- package/dist/billing/dto.d.ts +33 -0
- package/dist/billing/dto.js +71 -0
- package/dist/billing/dto.js.map +1 -0
- package/dist/billing/index.d.ts +35 -0
- package/dist/billing/index.js +115 -0
- package/dist/billing/index.js.map +1 -0
- package/dist/client.d.ts +12 -0
- package/dist/client.js +23 -7
- package/dist/client.js.map +1 -1
- package/dist/clients/index.d.ts +3 -1
- package/dist/clients/index.js +25 -62
- package/dist/clients/index.js.map +1 -1
- package/dist/index.d.ts +8 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/nest/index.d.ts +22 -0
- package/dist/nest/index.js +28 -1
- package/dist/nest/index.js.map +1 -1
- package/dist/notes/index.d.ts +3 -1
- package/dist/notes/index.js +16 -27
- package/dist/notes/index.js.map +1 -1
- package/dist/notifications/dto.d.ts +10 -0
- package/dist/notifications/dto.js +63 -0
- package/dist/notifications/dto.js.map +1 -0
- package/dist/notifications/index.d.ts +139 -0
- package/dist/notifications/index.js +354 -0
- package/dist/notifications/index.js.map +1 -0
- package/dist/organizations/dto.d.ts +62 -0
- package/dist/organizations/dto.js +445 -0
- package/dist/organizations/dto.js.map +1 -0
- package/dist/organizations/index.d.ts +72 -0
- package/dist/organizations/index.js +221 -0
- package/dist/organizations/index.js.map +1 -0
- package/dist/permissions/dto.d.ts +27 -0
- package/dist/permissions/dto.js +215 -0
- package/dist/permissions/dto.js.map +1 -0
- package/dist/permissions/index.d.ts +36 -0
- package/dist/permissions/index.js +110 -0
- package/dist/permissions/index.js.map +1 -0
- package/dist/projects/index.d.ts +3 -1
- package/dist/projects/index.js +25 -62
- package/dist/projects/index.js.map +1 -1
- package/dist/service-client/index.d.ts +72 -0
- package/dist/service-client/index.js +119 -0
- package/dist/service-client/index.js.map +1 -0
- package/dist/statuses/index.d.ts +3 -1
- package/dist/statuses/index.js +17 -28
- package/dist/statuses/index.js.map +1 -1
- package/dist/supporting-files/index.d.ts +3 -1
- package/dist/supporting-files/index.js +14 -20
- package/dist/supporting-files/index.js.map +1 -1
- package/dist/tasks/index.d.ts +3 -1
- package/dist/tasks/index.js +21 -50
- package/dist/tasks/index.js.map +1 -1
- package/dist/users/dto.d.ts +48 -0
- package/dist/users/dto.js +267 -0
- package/dist/users/dto.js.map +1 -0
- package/dist/users/index.d.ts +38 -0
- package/dist/users/index.js +144 -0
- package/dist/users/index.js.map +1 -0
- package/dist/webhook-events/index.d.ts +65 -0
- package/dist/webhook-events/index.js +109 -0
- package/dist/webhook-events/index.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,308 @@
|
|
|
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.auditedTable = exports.AuditResource = exports.snapshotChanges = exports.diffChanges = exports.AUDIT_EXCLUDED_COLUMNS = void 0;
|
|
18
|
+
const enum_1 = require("@managemint-solutions/entities/audit-trail/enum");
|
|
19
|
+
const errors_1 = require("../errors");
|
|
20
|
+
__exportStar(require("./dto"), exports);
|
|
21
|
+
/**
|
|
22
|
+
* Bookkeeping columns a diff never reports: identity, tenancy and the who/when stamps of the
|
|
23
|
+
* transition itself (the action already says what happened), plus the `entity_type`/`entity_id`
|
|
24
|
+
* pair, which becomes `related_entity_*` on the audit row instead.
|
|
25
|
+
*/
|
|
26
|
+
exports.AUDIT_EXCLUDED_COLUMNS = new Set([
|
|
27
|
+
'id',
|
|
28
|
+
'mms_id',
|
|
29
|
+
'organization_id',
|
|
30
|
+
'created_at',
|
|
31
|
+
'created_by',
|
|
32
|
+
'user_id',
|
|
33
|
+
'updated_at',
|
|
34
|
+
'last_updated_by',
|
|
35
|
+
'archived_at',
|
|
36
|
+
'archived_by',
|
|
37
|
+
'unarchived_at',
|
|
38
|
+
'unarchived_by',
|
|
39
|
+
'deleted_at',
|
|
40
|
+
'deleted_by',
|
|
41
|
+
'restored_at',
|
|
42
|
+
'restored_by',
|
|
43
|
+
'entity_type',
|
|
44
|
+
'entity_id',
|
|
45
|
+
]);
|
|
46
|
+
/** `undefined` and `null` are the same absent value as far as a row diff is concerned. */
|
|
47
|
+
const normalize = (value) => value ?? null;
|
|
48
|
+
/**
|
|
49
|
+
* The fields that differ between two flat rows, as `{ field: { old, new } }`. Values stay real
|
|
50
|
+
* JSON (booleans stay booleans, jsonb stays an object) and are compared by serialized value, so
|
|
51
|
+
* arrays and objects are equal when their contents are.
|
|
52
|
+
*/
|
|
53
|
+
const diffChanges = (before, after) => {
|
|
54
|
+
const changes = {};
|
|
55
|
+
for (const key of new Set([...Object.keys(before), ...Object.keys(after)])) {
|
|
56
|
+
if (exports.AUDIT_EXCLUDED_COLUMNS.has(key))
|
|
57
|
+
continue;
|
|
58
|
+
const oldValue = normalize(before[key]);
|
|
59
|
+
const newValue = normalize(after[key]);
|
|
60
|
+
if (JSON.stringify(oldValue) === JSON.stringify(newValue))
|
|
61
|
+
continue;
|
|
62
|
+
changes[key] = { old: oldValue, new: newValue };
|
|
63
|
+
}
|
|
64
|
+
return changes;
|
|
65
|
+
};
|
|
66
|
+
exports.diffChanges = diffChanges;
|
|
67
|
+
/**
|
|
68
|
+
* A whole row as a change set — `'new'` for an insert, `'old'` for a hard delete — so the trail
|
|
69
|
+
* stays self-contained once the row is gone. Columns that hold nothing are left out.
|
|
70
|
+
*/
|
|
71
|
+
const snapshotChanges = (row, side) => {
|
|
72
|
+
const changes = {};
|
|
73
|
+
for (const [key, value] of Object.entries(row)) {
|
|
74
|
+
if (exports.AUDIT_EXCLUDED_COLUMNS.has(key) || value === null || value === undefined)
|
|
75
|
+
continue;
|
|
76
|
+
changes[key] = side === 'new' ? { old: null, new: value } : { old: value, new: null };
|
|
77
|
+
}
|
|
78
|
+
return changes;
|
|
79
|
+
};
|
|
80
|
+
exports.snapshotChanges = snapshotChanges;
|
|
81
|
+
const AUDIT_TRAIL_SELECT = `
|
|
82
|
+
mms_id,
|
|
83
|
+
created_at,
|
|
84
|
+
action,
|
|
85
|
+
entity_type,
|
|
86
|
+
entity_id,
|
|
87
|
+
created_by:user_profiles!created_by (*),
|
|
88
|
+
related_entity_type,
|
|
89
|
+
related_entity_id,
|
|
90
|
+
changes
|
|
91
|
+
`;
|
|
92
|
+
/**
|
|
93
|
+
* The `audit_logs` table. Reads are the audit trail endpoint; writes go through `record`, which
|
|
94
|
+
* every audited write calls for itself — no feature ever writes an audit line by hand.
|
|
95
|
+
*/
|
|
96
|
+
class AuditResource {
|
|
97
|
+
supabase;
|
|
98
|
+
actor;
|
|
99
|
+
onError;
|
|
100
|
+
constructor(supabase, actor, onError) {
|
|
101
|
+
this.supabase = supabase;
|
|
102
|
+
this.actor = actor;
|
|
103
|
+
this.onError = onError;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Writes the audit row(s) — one insert, however many entries. **Never throws**: a logging
|
|
107
|
+
* problem must not fail the business write, so a failure goes to `onAuditError`
|
|
108
|
+
* (default `console.error`) instead.
|
|
109
|
+
*/
|
|
110
|
+
async record(entry) {
|
|
111
|
+
const entries = Array.isArray(entry) ? entry : [entry];
|
|
112
|
+
if (entries.length === 0)
|
|
113
|
+
return;
|
|
114
|
+
try {
|
|
115
|
+
const { error } = await this.supabase.from('audit_logs').insert(entries.map((item) => ({
|
|
116
|
+
created_by: this.actor.mms_id,
|
|
117
|
+
organization_id: this.actor.organization_id,
|
|
118
|
+
action: item.action,
|
|
119
|
+
entity_type: item.entityType,
|
|
120
|
+
entity_id: item.entityId,
|
|
121
|
+
related_entity_type: item.relatedEntityType ?? null,
|
|
122
|
+
related_entity_id: item.relatedEntityId ?? null,
|
|
123
|
+
changes: item.changes,
|
|
124
|
+
})));
|
|
125
|
+
if (error)
|
|
126
|
+
throw (0, errors_1.mapPostgrestError)(error);
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
const handle = this.onError ?? ((thrown, failed) => console.error(thrown, failed));
|
|
130
|
+
handle(error, entries);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
async list(query) {
|
|
134
|
+
const page = query.page;
|
|
135
|
+
const pageSize = query.page_size;
|
|
136
|
+
const offset = (page - 1) * pageSize;
|
|
137
|
+
// `order`/`range` return `this`, so the builder stays a filter builder and the conditional
|
|
138
|
+
// filters below can be reassigned onto it without a cast.
|
|
139
|
+
let auditTrailQuery = this.supabase
|
|
140
|
+
.from('audit_logs')
|
|
141
|
+
.select(AUDIT_TRAIL_SELECT, { count: 'estimated' })
|
|
142
|
+
.eq('organization_id', this.actor.organization_id)
|
|
143
|
+
.order('created_at', { ascending: false })
|
|
144
|
+
.range(offset, offset + pageSize - 1);
|
|
145
|
+
if (query.created_after) {
|
|
146
|
+
auditTrailQuery = auditTrailQuery.gte('created_at', query.created_after);
|
|
147
|
+
}
|
|
148
|
+
if (query.created_before) {
|
|
149
|
+
auditTrailQuery = auditTrailQuery.lte('created_at', query.created_before);
|
|
150
|
+
}
|
|
151
|
+
if (query.created_by) {
|
|
152
|
+
auditTrailQuery = auditTrailQuery.eq('created_by', query.created_by);
|
|
153
|
+
}
|
|
154
|
+
if (query.action) {
|
|
155
|
+
auditTrailQuery = auditTrailQuery.eq('action', query.action);
|
|
156
|
+
}
|
|
157
|
+
if (query.entity_type) {
|
|
158
|
+
auditTrailQuery = auditTrailQuery.eq('entity_type', query.entity_type);
|
|
159
|
+
}
|
|
160
|
+
if (query.entity_id) {
|
|
161
|
+
auditTrailQuery = auditTrailQuery.eq('entity_id', query.entity_id);
|
|
162
|
+
}
|
|
163
|
+
const { data, error, count } = await auditTrailQuery;
|
|
164
|
+
if (error)
|
|
165
|
+
throw (0, errors_1.mapPostgrestError)(error);
|
|
166
|
+
const totalEstimated = count ?? 0;
|
|
167
|
+
const totalPages = totalEstimated > 0 ? Math.ceil(totalEstimated / pageSize) : 0;
|
|
168
|
+
return {
|
|
169
|
+
results: (data ?? []),
|
|
170
|
+
page,
|
|
171
|
+
per_page: pageSize,
|
|
172
|
+
count: totalEstimated,
|
|
173
|
+
total_pages: totalPages,
|
|
174
|
+
has_next_page: page < totalPages,
|
|
175
|
+
has_previous_page: page > 1,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
exports.AuditResource = AuditResource;
|
|
180
|
+
/** The keyed update every audited write builds, before any caller-supplied guard. */
|
|
181
|
+
const buildUpdate = (supabase, table, id, payload, organizationId) => {
|
|
182
|
+
// `eq` returns `this`, so the org filter can be reassigned onto the builder without a cast.
|
|
183
|
+
let query = supabase.from(table).update(payload).eq('mms_id', id);
|
|
184
|
+
if (organizationId !== null)
|
|
185
|
+
query = query.eq('organization_id', organizationId);
|
|
186
|
+
return query;
|
|
187
|
+
};
|
|
188
|
+
/**
|
|
189
|
+
* The audited write helper every resource writes through: it does the pre-read, the write, the
|
|
190
|
+
* diff and the `audit_logs` insert itself, so no feature carries audit code. The write fails
|
|
191
|
+
* loudly (`SupabaseClientError`); only the audit insert is swallowed.
|
|
192
|
+
*/
|
|
193
|
+
const auditedTable = (supabase, actor, audit, options) => {
|
|
194
|
+
const scoped = options.scopeByOrganization !== false;
|
|
195
|
+
// Tables that hang off another entity (notes, additional details, supporting files) carry the
|
|
196
|
+
// owner in `entity_type`/`entity_id`; the audit row records it as the related entity.
|
|
197
|
+
const relatedOf = (row) => ({
|
|
198
|
+
relatedEntityType: row.entity_type ?? null,
|
|
199
|
+
relatedEntityId: row.entity_id ?? null,
|
|
200
|
+
});
|
|
201
|
+
const read = async (id) => {
|
|
202
|
+
// `eq` returns `this`, so the org filter can be reassigned onto the builder without a cast.
|
|
203
|
+
let query = supabase.from(options.table).select('*').eq('mms_id', id);
|
|
204
|
+
if (scoped)
|
|
205
|
+
query = query.eq('organization_id', actor.organization_id);
|
|
206
|
+
const { data, error } = await query.single();
|
|
207
|
+
if (error)
|
|
208
|
+
throw (0, errors_1.mapPostgrestError)(error);
|
|
209
|
+
return data;
|
|
210
|
+
};
|
|
211
|
+
const organizationFilter = scoped ? actor.organization_id : null;
|
|
212
|
+
const updateOf = (id, before, payload) => buildUpdate(supabase, options.table, id, typeof payload === 'function' ? payload(before) : payload, organizationFilter);
|
|
213
|
+
const recordWrite = (id, action, before, after) => audit.record({
|
|
214
|
+
action,
|
|
215
|
+
entityType: options.entityType,
|
|
216
|
+
entityId: id,
|
|
217
|
+
changes: (0, exports.diffChanges)(before, after),
|
|
218
|
+
...relatedOf(before),
|
|
219
|
+
});
|
|
220
|
+
const write = async (id, action, payload) => {
|
|
221
|
+
const before = await read(id);
|
|
222
|
+
const { data, error } = await updateOf(id, before, payload).select('*').single();
|
|
223
|
+
if (error)
|
|
224
|
+
throw (0, errors_1.mapPostgrestError)(error);
|
|
225
|
+
const after = data;
|
|
226
|
+
await recordWrite(id, action, before, after);
|
|
227
|
+
return after;
|
|
228
|
+
};
|
|
229
|
+
const writeWhere = async (id, guard, payload) => {
|
|
230
|
+
const before = await read(id);
|
|
231
|
+
// `maybeSingle`, not `single`: matching nothing is the guard doing its job, not an error.
|
|
232
|
+
const { data, error } = await guard(updateOf(id, before, payload))
|
|
233
|
+
.select('*')
|
|
234
|
+
.maybeSingle();
|
|
235
|
+
if (error)
|
|
236
|
+
throw (0, errors_1.mapPostgrestError)(error);
|
|
237
|
+
// The guard lost the race — the row is untouched, so there is nothing to audit.
|
|
238
|
+
if (!data)
|
|
239
|
+
return null;
|
|
240
|
+
const after = data;
|
|
241
|
+
await recordWrite(id, enum_1.AuditTrailAction.UPDATE, before, after);
|
|
242
|
+
return after;
|
|
243
|
+
};
|
|
244
|
+
return {
|
|
245
|
+
async insert(payload) {
|
|
246
|
+
const { data, error } = await supabase
|
|
247
|
+
.from(options.table)
|
|
248
|
+
.insert(payload)
|
|
249
|
+
.select('*')
|
|
250
|
+
.single();
|
|
251
|
+
if (error)
|
|
252
|
+
throw (0, errors_1.mapPostgrestError)(error);
|
|
253
|
+
const row = data;
|
|
254
|
+
await audit.record({
|
|
255
|
+
action: enum_1.AuditTrailAction.INSERT,
|
|
256
|
+
entityType: options.entityType,
|
|
257
|
+
entityId: row.mms_id,
|
|
258
|
+
changes: (0, exports.snapshotChanges)(row, 'new'),
|
|
259
|
+
...relatedOf(row),
|
|
260
|
+
});
|
|
261
|
+
return row;
|
|
262
|
+
},
|
|
263
|
+
async insertMany(payloads) {
|
|
264
|
+
if (payloads.length === 0)
|
|
265
|
+
return [];
|
|
266
|
+
const { data, error } = await supabase.from(options.table).insert(payloads).select('*');
|
|
267
|
+
if (error)
|
|
268
|
+
throw (0, errors_1.mapPostgrestError)(error);
|
|
269
|
+
const rows = (data ?? []);
|
|
270
|
+
await audit.record(rows.map((row) => ({
|
|
271
|
+
action: enum_1.AuditTrailAction.INSERT,
|
|
272
|
+
entityType: options.entityType,
|
|
273
|
+
entityId: row.mms_id,
|
|
274
|
+
changes: (0, exports.snapshotChanges)(row, 'new'),
|
|
275
|
+
...relatedOf(row),
|
|
276
|
+
})));
|
|
277
|
+
return rows;
|
|
278
|
+
},
|
|
279
|
+
update(id, payload) {
|
|
280
|
+
return write(id, enum_1.AuditTrailAction.UPDATE, payload);
|
|
281
|
+
},
|
|
282
|
+
updateWhere(id, guard, payload) {
|
|
283
|
+
return writeWhere(id, guard, payload);
|
|
284
|
+
},
|
|
285
|
+
transition(id, action, payload) {
|
|
286
|
+
return write(id, action, payload);
|
|
287
|
+
},
|
|
288
|
+
async remove(id) {
|
|
289
|
+
const before = await read(id);
|
|
290
|
+
let query = supabase.from(options.table).delete().eq('mms_id', id);
|
|
291
|
+
if (scoped)
|
|
292
|
+
query = query.eq('organization_id', actor.organization_id);
|
|
293
|
+
const { error } = await query;
|
|
294
|
+
if (error)
|
|
295
|
+
throw (0, errors_1.mapPostgrestError)(error);
|
|
296
|
+
await audit.record({
|
|
297
|
+
action: enum_1.AuditTrailAction.DELETE,
|
|
298
|
+
entityType: options.entityType,
|
|
299
|
+
entityId: id,
|
|
300
|
+
changes: (0, exports.snapshotChanges)(before, 'old'),
|
|
301
|
+
...relatedOf(before),
|
|
302
|
+
});
|
|
303
|
+
return before;
|
|
304
|
+
},
|
|
305
|
+
};
|
|
306
|
+
};
|
|
307
|
+
exports.auditedTable = auditedTable;
|
|
308
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/audit/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The client supplies the idempotency key for every money operation
|
|
3
|
+
* (docs/billing/00-overview.md principle 1). A uuid v4 keeps it unique per
|
|
4
|
+
* (organization, key) without the API having to hand one out first.
|
|
5
|
+
*/
|
|
6
|
+
export declare class InitialPaymentDto {
|
|
7
|
+
readonly idempotency_key: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Cancellation moves no money, but it is a subscription-level operation and
|
|
11
|
+
* carries a key like every other one, so a client retry after a dropped
|
|
12
|
+
* connection replays the original answer (docs/billing/09-cancellation.md).
|
|
13
|
+
*/
|
|
14
|
+
export declare class CancelSubscriptionDto {
|
|
15
|
+
readonly idempotency_key: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* A reinstatement may or may not move money - the caller cannot know which
|
|
19
|
+
* branch it will get - so the key is always required
|
|
20
|
+
* (docs/billing/10-reinstatement.md).
|
|
21
|
+
*/
|
|
22
|
+
export declare class ReinstateSubscriptionDto {
|
|
23
|
+
readonly idempotency_key: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* A purchase names the module by *id*, which is checked against the active
|
|
27
|
+
* pricebook - never a module key from a hardcoded enum
|
|
28
|
+
* (docs/billing/07-modules-and-pricebooks.md section 2).
|
|
29
|
+
*/
|
|
30
|
+
export declare class PurchaseModuleDto {
|
|
31
|
+
readonly module_id: string;
|
|
32
|
+
readonly idempotency_key: string;
|
|
33
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.PurchaseModuleDto = exports.ReinstateSubscriptionDto = exports.CancelSubscriptionDto = exports.InitialPaymentDto = void 0;
|
|
13
|
+
const class_validator_1 = require("class-validator");
|
|
14
|
+
/**
|
|
15
|
+
* The client supplies the idempotency key for every money operation
|
|
16
|
+
* (docs/billing/00-overview.md principle 1). A uuid v4 keeps it unique per
|
|
17
|
+
* (organization, key) without the API having to hand one out first.
|
|
18
|
+
*/
|
|
19
|
+
class InitialPaymentDto {
|
|
20
|
+
idempotency_key;
|
|
21
|
+
}
|
|
22
|
+
exports.InitialPaymentDto = InitialPaymentDto;
|
|
23
|
+
__decorate([
|
|
24
|
+
(0, class_validator_1.IsUUID)('4', { message: 'An idempotency key is required and must be a v4 uuid' }),
|
|
25
|
+
__metadata("design:type", String)
|
|
26
|
+
], InitialPaymentDto.prototype, "idempotency_key", void 0);
|
|
27
|
+
/**
|
|
28
|
+
* Cancellation moves no money, but it is a subscription-level operation and
|
|
29
|
+
* carries a key like every other one, so a client retry after a dropped
|
|
30
|
+
* connection replays the original answer (docs/billing/09-cancellation.md).
|
|
31
|
+
*/
|
|
32
|
+
class CancelSubscriptionDto {
|
|
33
|
+
idempotency_key;
|
|
34
|
+
}
|
|
35
|
+
exports.CancelSubscriptionDto = CancelSubscriptionDto;
|
|
36
|
+
__decorate([
|
|
37
|
+
(0, class_validator_1.IsUUID)('4', { message: 'An idempotency key is required and must be a v4 uuid' }),
|
|
38
|
+
__metadata("design:type", String)
|
|
39
|
+
], CancelSubscriptionDto.prototype, "idempotency_key", void 0);
|
|
40
|
+
/**
|
|
41
|
+
* A reinstatement may or may not move money - the caller cannot know which
|
|
42
|
+
* branch it will get - so the key is always required
|
|
43
|
+
* (docs/billing/10-reinstatement.md).
|
|
44
|
+
*/
|
|
45
|
+
class ReinstateSubscriptionDto {
|
|
46
|
+
idempotency_key;
|
|
47
|
+
}
|
|
48
|
+
exports.ReinstateSubscriptionDto = ReinstateSubscriptionDto;
|
|
49
|
+
__decorate([
|
|
50
|
+
(0, class_validator_1.IsUUID)('4', { message: 'An idempotency key is required and must be a v4 uuid' }),
|
|
51
|
+
__metadata("design:type", String)
|
|
52
|
+
], ReinstateSubscriptionDto.prototype, "idempotency_key", void 0);
|
|
53
|
+
/**
|
|
54
|
+
* A purchase names the module by *id*, which is checked against the active
|
|
55
|
+
* pricebook - never a module key from a hardcoded enum
|
|
56
|
+
* (docs/billing/07-modules-and-pricebooks.md section 2).
|
|
57
|
+
*/
|
|
58
|
+
class PurchaseModuleDto {
|
|
59
|
+
module_id;
|
|
60
|
+
idempotency_key;
|
|
61
|
+
}
|
|
62
|
+
exports.PurchaseModuleDto = PurchaseModuleDto;
|
|
63
|
+
__decorate([
|
|
64
|
+
(0, class_validator_1.IsUUID)('4', { message: 'A module id is required and must be a v4 uuid' }),
|
|
65
|
+
__metadata("design:type", String)
|
|
66
|
+
], PurchaseModuleDto.prototype, "module_id", void 0);
|
|
67
|
+
__decorate([
|
|
68
|
+
(0, class_validator_1.IsUUID)('4', { message: 'An idempotency key is required and must be a v4 uuid' }),
|
|
69
|
+
__metadata("design:type", String)
|
|
70
|
+
], PurchaseModuleDto.prototype, "idempotency_key", void 0);
|
|
71
|
+
//# sourceMappingURL=dto.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dto.js","sourceRoot":"","sources":["../../src/billing/dto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qDAAyC;AAEzC;;;;GAIG;AACH,MAAa,iBAAiB;IAEnB,eAAe,CAAU;CACnC;AAHD,8CAGC;AADU;IADR,IAAA,wBAAM,EAAC,GAAG,EAAE,EAAE,OAAO,EAAE,sDAAsD,EAAE,CAAC;;0DAC/C;AAGpC;;;;GAIG;AACH,MAAa,qBAAqB;IAEvB,eAAe,CAAU;CACnC;AAHD,sDAGC;AADU;IADR,IAAA,wBAAM,EAAC,GAAG,EAAE,EAAE,OAAO,EAAE,sDAAsD,EAAE,CAAC;;8DAC/C;AAGpC;;;;GAIG;AACH,MAAa,wBAAwB;IAE1B,eAAe,CAAU;CACnC;AAHD,4DAGC;AADU;IADR,IAAA,wBAAM,EAAC,GAAG,EAAE,EAAE,OAAO,EAAE,sDAAsD,EAAE,CAAC;;iEAC/C;AAGpC;;;;GAIG;AACH,MAAa,iBAAiB;IAEnB,SAAS,CAAU;IAGnB,eAAe,CAAU;CACnC;AAND,8CAMC;AAJU;IADR,IAAA,wBAAM,EAAC,GAAG,EAAE,EAAE,OAAO,EAAE,+CAA+C,EAAE,CAAC;;oDAC9C;AAGnB;IADR,IAAA,wBAAM,EAAC,GAAG,EAAE,EAAE,OAAO,EAAE,sDAAsD,EAAE,CAAC;;0DAC/C"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { BillingTransactionRow, CreateBillingEventDto } from '@managemint-solutions/entities/billing';
|
|
2
|
+
import { type AuditActor, type AuditResource, type AuditRow } from '../audit';
|
|
3
|
+
import type { TypedSupabaseClient } from '../client';
|
|
4
|
+
export * from './dto';
|
|
5
|
+
/**
|
|
6
|
+
* The ledger and its narrative log. Every policy here is `false` for `authenticated` except
|
|
7
|
+
* READ, so this only ever runs on the service client — the ledger is written by the billing
|
|
8
|
+
* service and by webhooks, never by a caller.
|
|
9
|
+
*/
|
|
10
|
+
export declare class BillingResource {
|
|
11
|
+
private readonly supabase;
|
|
12
|
+
private readonly actor;
|
|
13
|
+
private readonly transactions;
|
|
14
|
+
constructor(supabase: TypedSupabaseClient, actor: AuditActor, audit: AuditResource);
|
|
15
|
+
createTransaction(payload: AuditRow): Promise<BillingTransactionRow>;
|
|
16
|
+
updateTransaction(transactionId: string, patch: AuditRow): Promise<AuditRow>;
|
|
17
|
+
/**
|
|
18
|
+
* Claims a transaction for processing, but only while it is not already paid. This is the
|
|
19
|
+
* send-exactly-once gate on the webhook path: a redelivered `charge.success` must not settle
|
|
20
|
+
* the same row twice. Resolves to null when the guard finds it already settled.
|
|
21
|
+
*/
|
|
22
|
+
claimTransactionForProcessing(transactionId: string, patch: AuditRow): Promise<AuditRow | null>;
|
|
23
|
+
getTransaction(transactionId: string): Promise<BillingTransactionRow | null>;
|
|
24
|
+
/** The one open transaction, if the organization has one. */
|
|
25
|
+
openTransaction(openStatuses: string[]): Promise<BillingTransactionRow | null>;
|
|
26
|
+
/** The replay lookup: the same key must never raise a second charge. */
|
|
27
|
+
transactionByIdempotencyKey(idempotencyKey: string): Promise<BillingTransactionRow | null>;
|
|
28
|
+
/**
|
|
29
|
+
* Appends to `billing_events`. Deliberately unaudited: the table *is* an append-only
|
|
30
|
+
* narrative of the billing state machine, so an audit row per event would log the log.
|
|
31
|
+
*/
|
|
32
|
+
recordEvent(event: CreateBillingEventDto): Promise<void>;
|
|
33
|
+
/** Whether a catalog module is still on sale. */
|
|
34
|
+
isModuleActive(moduleId: string): Promise<boolean>;
|
|
35
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
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.BillingResource = void 0;
|
|
18
|
+
const enum_1 = require("@managemint-solutions/entities/audit-trail/enum");
|
|
19
|
+
const enum_2 = require("@managemint-solutions/entities/billing/enum");
|
|
20
|
+
const audit_1 = require("../audit");
|
|
21
|
+
const errors_1 = require("../errors");
|
|
22
|
+
__exportStar(require("./dto"), exports);
|
|
23
|
+
const BILLING_TRANSACTIONS_TABLE = {
|
|
24
|
+
table: 'billing_transactions',
|
|
25
|
+
entityType: enum_1.AuditTrailEntityType.BILLING_TRANSACTIONS,
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* The ledger and its narrative log. Every policy here is `false` for `authenticated` except
|
|
29
|
+
* READ, so this only ever runs on the service client — the ledger is written by the billing
|
|
30
|
+
* service and by webhooks, never by a caller.
|
|
31
|
+
*/
|
|
32
|
+
class BillingResource {
|
|
33
|
+
supabase;
|
|
34
|
+
actor;
|
|
35
|
+
transactions;
|
|
36
|
+
constructor(supabase, actor, audit) {
|
|
37
|
+
this.supabase = supabase;
|
|
38
|
+
this.actor = actor;
|
|
39
|
+
this.transactions = (0, audit_1.auditedTable)(supabase, actor, audit, BILLING_TRANSACTIONS_TABLE);
|
|
40
|
+
}
|
|
41
|
+
async createTransaction(payload) {
|
|
42
|
+
const row = await this.transactions.insert(payload);
|
|
43
|
+
return row;
|
|
44
|
+
}
|
|
45
|
+
async updateTransaction(transactionId, patch) {
|
|
46
|
+
return this.transactions.update(transactionId, {
|
|
47
|
+
...patch,
|
|
48
|
+
updated_at: new Date().toISOString(),
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Claims a transaction for processing, but only while it is not already paid. This is the
|
|
53
|
+
* send-exactly-once gate on the webhook path: a redelivered `charge.success` must not settle
|
|
54
|
+
* the same row twice. Resolves to null when the guard finds it already settled.
|
|
55
|
+
*/
|
|
56
|
+
async claimTransactionForProcessing(transactionId, patch) {
|
|
57
|
+
return this.transactions.updateWhere(transactionId, (query) => query.neq('transaction_status', enum_2.BillingTransactionStatus.PAID), { ...patch, updated_at: new Date().toISOString() });
|
|
58
|
+
}
|
|
59
|
+
async getTransaction(transactionId) {
|
|
60
|
+
const { data, error } = await this.supabase
|
|
61
|
+
.from('billing_transactions')
|
|
62
|
+
.select('*')
|
|
63
|
+
.eq('mms_id', transactionId)
|
|
64
|
+
.maybeSingle();
|
|
65
|
+
if (error)
|
|
66
|
+
throw (0, errors_1.mapPostgrestError)(error);
|
|
67
|
+
return (data ?? null);
|
|
68
|
+
}
|
|
69
|
+
/** The one open transaction, if the organization has one. */
|
|
70
|
+
async openTransaction(openStatuses) {
|
|
71
|
+
const { data, error } = await this.supabase
|
|
72
|
+
.from('billing_transactions')
|
|
73
|
+
.select('*')
|
|
74
|
+
.eq('organization_id', this.actor.organization_id)
|
|
75
|
+
.in('transaction_status', openStatuses)
|
|
76
|
+
.maybeSingle();
|
|
77
|
+
if (error)
|
|
78
|
+
throw (0, errors_1.mapPostgrestError)(error);
|
|
79
|
+
return (data ?? null);
|
|
80
|
+
}
|
|
81
|
+
/** The replay lookup: the same key must never raise a second charge. */
|
|
82
|
+
async transactionByIdempotencyKey(idempotencyKey) {
|
|
83
|
+
const { data, error } = await this.supabase
|
|
84
|
+
.from('billing_transactions')
|
|
85
|
+
.select('*')
|
|
86
|
+
.eq('organization_id', this.actor.organization_id)
|
|
87
|
+
.eq('idempotency_key', idempotencyKey)
|
|
88
|
+
.maybeSingle();
|
|
89
|
+
if (error)
|
|
90
|
+
throw (0, errors_1.mapPostgrestError)(error);
|
|
91
|
+
return (data ?? null);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Appends to `billing_events`. Deliberately unaudited: the table *is* an append-only
|
|
95
|
+
* narrative of the billing state machine, so an audit row per event would log the log.
|
|
96
|
+
*/
|
|
97
|
+
async recordEvent(event) {
|
|
98
|
+
const { error } = await this.supabase.from('billing_events').insert(event);
|
|
99
|
+
if (error)
|
|
100
|
+
throw (0, errors_1.mapPostgrestError)(error);
|
|
101
|
+
}
|
|
102
|
+
/** Whether a catalog module is still on sale. */
|
|
103
|
+
async isModuleActive(moduleId) {
|
|
104
|
+
const { data, error } = await this.supabase
|
|
105
|
+
.from('billing_modules')
|
|
106
|
+
.select('active')
|
|
107
|
+
.eq('mms_id', moduleId)
|
|
108
|
+
.maybeSingle();
|
|
109
|
+
if (error)
|
|
110
|
+
throw (0, errors_1.mapPostgrestError)(error);
|
|
111
|
+
return data?.active === true;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
exports.BillingResource = BillingResource;
|
|
115
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/billing/index.ts"],"names":[],"mappings":"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"}
|
package/dist/client.d.ts
CHANGED
|
@@ -1,24 +1,36 @@
|
|
|
1
1
|
import { type SupabaseClient as SupabaseJsClient } from '@supabase/supabase-js';
|
|
2
2
|
import { type AuthContext } from './auth';
|
|
3
|
+
import { AuditResource, type AuditErrorHandler } from './audit';
|
|
3
4
|
import { AdditionalDetailsResource } from './additional-details';
|
|
4
5
|
import { ClientsResource } from './clients';
|
|
5
6
|
import { NotesResource } from './notes';
|
|
7
|
+
import { NotificationsResource } from './notifications';
|
|
8
|
+
import { OrganizationsResource } from './organizations';
|
|
9
|
+
import { PermissionsResource } from './permissions';
|
|
6
10
|
import { ProjectsResource } from './projects';
|
|
7
11
|
import { StatusesResource } from './statuses';
|
|
8
12
|
import { SupportingFilesResource } from './supporting-files';
|
|
9
13
|
import { TasksResource } from './tasks';
|
|
14
|
+
import { UsersResource } from './users';
|
|
10
15
|
export type TypedSupabaseClient = SupabaseJsClient;
|
|
11
16
|
export type SupabaseClientConfig = {
|
|
12
17
|
url: string;
|
|
13
18
|
key: string;
|
|
14
19
|
accessToken: string;
|
|
20
|
+
/** Where a failed audit insert is reported. Defaults to `console.error`. */
|
|
21
|
+
onAuditError?: AuditErrorHandler;
|
|
15
22
|
};
|
|
16
23
|
export declare class SupabaseClient {
|
|
17
24
|
readonly supabase: TypedSupabaseClient;
|
|
18
25
|
readonly auth: AuthContext;
|
|
26
|
+
readonly audit: AuditResource;
|
|
19
27
|
readonly statuses: StatusesResource;
|
|
20
28
|
readonly additionalDetails: AdditionalDetailsResource;
|
|
21
29
|
readonly notes: NotesResource;
|
|
30
|
+
readonly notifications: NotificationsResource;
|
|
31
|
+
readonly organizations: OrganizationsResource;
|
|
32
|
+
readonly permissions: PermissionsResource;
|
|
33
|
+
readonly users: UsersResource;
|
|
22
34
|
readonly supportingFiles: SupportingFilesResource;
|
|
23
35
|
readonly clients: ClientsResource;
|
|
24
36
|
readonly projects: ProjectsResource;
|