@sneat/extension-splitus-contract 0.2.1 → 0.2.2

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 CHANGED
@@ -2,6 +2,27 @@
2
2
 
3
3
  Splitus extension contract library.
4
4
 
5
+ ## Bill contract version 1
6
+
7
+ `ICreateSplitusBillV1Request` carries exact major-unit decimal strings,
8
+ client-stable bill identity, and separate paid/owed contact allocations. The
9
+ host must call `assertCreateSplitusBillV1Recorder` with its trusted
10
+ authenticated identity before accepting the recorder audit claim.
11
+
12
+ Parse untrusted API responses with `parseCreateSplitusBillV1Response`,
13
+ `parseGetSplitusBillV1Response`, or `parseListSplitusBillsV1Response`. This
14
+ rejects numeric money JSON, invalid posting proof, unsafe identifiers, and
15
+ unbounded list/detail arrays before a runtime renders them. Contact IDs are
16
+ resolved through the host's real Contactus data; they are not display labels.
17
+
18
+ The earlier split DTOs and `ISplitusService` remain exported as deprecated
19
+ compatibility surfaces until every consumer has moved to
20
+ `ISplitusBillServiceV1`.
21
+
22
+ The matching storage-neutral Go host contract is module
23
+ `github.com/sneat-co/sneat-ext-contracts/splitus`, package
24
+ `contract4splitus`.
25
+
5
26
  ## Provenance
6
27
 
7
28
  Migrated from sneat-co/debtus (npm continuity from @sneat/extension-splitus-contract@0.2.0).
@@ -1,10 +1,625 @@
1
1
  import { InjectionToken } from '@angular/core';
2
2
 
3
+ /** The first stable Splitus bill browser/host wire contract. */
4
+ const SPLITUS_BILL_CONTRACT_VERSION = 1;
5
+ const MAX_SPLITUS_BILL_PARTICIPANTS = 256;
6
+ const MAX_SPLITUS_BILL_LIST_PAGE_SIZE = 100;
7
+ const MAX_SPLITUS_BILL_OBLIGATIONS = 256;
8
+ const MAX_SPLITUS_OBLIGATION_IDS_PER_LINE = 256;
9
+ const MAX_EXACT_MINOR_UNITS = 9223372036854775807n;
10
+ const exactDecimalPattern = /^(?:0|[1-9][0-9]*)\.[0-9]{2}$/;
11
+ const datePattern = /^([0-9]{4})-([0-9]{2})-([0-9]{2})$/;
12
+ function parseExactDecimalString(value) {
13
+ if (typeof value !== 'string' || !exactDecimalPattern.test(value)) {
14
+ throw new TypeError('amount must be a canonical decimal string with exactly two fraction digits');
15
+ }
16
+ const minorUnits = BigInt(value.replace('.', ''));
17
+ if (minorUnits > MAX_EXACT_MINOR_UNITS) {
18
+ throw new RangeError('amount exceeds the Splitus contract limit');
19
+ }
20
+ return value;
21
+ }
22
+ function parseCreateSplitusBillV1Request(value) {
23
+ const input = record(value, 'create bill request');
24
+ if (input['contractVersion'] !== SPLITUS_BILL_CONTRACT_VERSION) {
25
+ throw new TypeError('unsupported Splitus bill contract version');
26
+ }
27
+ const billKind = enumValue(input['billKind'], ['general', 'utility'], 'billKind');
28
+ const actualAmount = positiveAmount(input['actualAmount'], 'actualAmount');
29
+ const spaceID = storageID(input['spaceID'], 'spaceID');
30
+ const billID = storageID(input['billID'], 'billID');
31
+ const recorderUserID = storageID(input['recorderUserID'], 'recorderUserID');
32
+ const request = {
33
+ contractVersion: SPLITUS_BILL_CONTRACT_VERSION,
34
+ spaceID,
35
+ billID,
36
+ recorderUserID,
37
+ title: optionalText(input['title'], 'title', 256),
38
+ billKind,
39
+ currency: currency(input['currency']),
40
+ actualAmount,
41
+ paidAllocations: allocations(input['paidAllocations'], 'paidAllocations'),
42
+ owedAllocations: allocations(input['owedAllocations'], 'owedAllocations'),
43
+ utility: input['utility'] === undefined ? undefined : utility(input['utility']),
44
+ recurringOccurrence: input['recurringOccurrence'] === undefined
45
+ ? undefined
46
+ : recurring(input['recurringOccurrence'], actualAmount, billID),
47
+ };
48
+ if ((billKind === 'utility') !== (request.utility !== undefined)) {
49
+ throw new TypeError('utility details are required only for utility bills');
50
+ }
51
+ validateAllocationTotals(request);
52
+ return request;
53
+ }
54
+ /**
55
+ * Executable host-boundary check for the request's audit claim. The trusted
56
+ * authenticated identity is supplied by the host, never derived from the
57
+ * request itself.
58
+ */
59
+ function assertCreateSplitusBillV1Recorder(request, authenticatedUserID) {
60
+ const trustedUserID = storageID(authenticatedUserID, 'authenticatedUserID');
61
+ if (request.recorderUserID !== trustedUserID) {
62
+ throw new TypeError('recorderUserID must match the trusted authenticated identity');
63
+ }
64
+ }
65
+ function parseListSplitusBillsV1Request(value) {
66
+ const input = record(value, 'list bills request');
67
+ if (input['contractVersion'] !== SPLITUS_BILL_CONTRACT_VERSION) {
68
+ throw new TypeError('unsupported Splitus bill contract version');
69
+ }
70
+ const pageSize = input['pageSize'];
71
+ if (typeof pageSize !== 'number' ||
72
+ !Number.isSafeInteger(pageSize) ||
73
+ pageSize < 1 ||
74
+ pageSize > MAX_SPLITUS_BILL_LIST_PAGE_SIZE) {
75
+ throw new RangeError(`pageSize must be an integer from 1 to ${MAX_SPLITUS_BILL_LIST_PAGE_SIZE}`);
76
+ }
77
+ return {
78
+ contractVersion: SPLITUS_BILL_CONTRACT_VERSION,
79
+ spaceID: storageID(input['spaceID'], 'spaceID'),
80
+ pageSize,
81
+ cursor: optionalText(input['cursor'], 'cursor', 2048),
82
+ utilityKind: input['utilityKind'] === undefined
83
+ ? undefined
84
+ : enumValue(input['utilityKind'], ['electricity', 'gas', 'water', 'internet', 'other'], 'utilityKind'),
85
+ period: input['period'] === undefined ? undefined : period(input['period']),
86
+ };
87
+ }
88
+ function parseGetSplitusBillV1Request(value) {
89
+ const input = versionedRecord(value, 'get bill request');
90
+ return {
91
+ contractVersion: SPLITUS_BILL_CONTRACT_VERSION,
92
+ spaceID: storageID(input['spaceID'], 'spaceID'),
93
+ billID: storageID(input['billID'], 'billID'),
94
+ };
95
+ }
96
+ function parseCreateSplitusBillV1Response(value) {
97
+ const input = versionedRecord(value, 'create bill response');
98
+ return {
99
+ contractVersion: SPLITUS_BILL_CONTRACT_VERSION,
100
+ bill: parseSplitusBillV1(input['bill']),
101
+ };
102
+ }
103
+ function parseGetSplitusBillV1Response(value) {
104
+ const input = versionedRecord(value, 'get bill response');
105
+ return {
106
+ contractVersion: SPLITUS_BILL_CONTRACT_VERSION,
107
+ bill: parseSplitusBillV1(input['bill']),
108
+ };
109
+ }
110
+ function parseListSplitusBillsV1Response(value, requestedPageSize) {
111
+ const input = versionedRecord(value, 'list bills response');
112
+ const pageSize = boundedPageSize(input['pageSize']);
113
+ if (requestedPageSize !== undefined && pageSize !== requestedPageSize) {
114
+ throw new RangeError('response pageSize does not match the accepted request');
115
+ }
116
+ if (!Array.isArray(input['items']) || input['items'].length > pageSize) {
117
+ throw new RangeError('response items exceed the bounded pageSize');
118
+ }
119
+ return {
120
+ contractVersion: SPLITUS_BILL_CONTRACT_VERSION,
121
+ pageSize,
122
+ items: input['items'].map((item) => splitusBillListItem(item)),
123
+ nextCursor: optionalText(input['nextCursor'], 'nextCursor', 2048),
124
+ };
125
+ }
126
+ function parseSplitusBillV1(value) {
127
+ const input = record(value, 'bill');
128
+ const request = parseCreateSplitusBillV1Request(input);
129
+ const revisionValue = positiveIntegerString(input['revision'], 'revision');
130
+ const createdAt = timestamp(input['createdAt'], 'createdAt');
131
+ const updatedAt = timestamp(input['updatedAt'], 'updatedAt');
132
+ if (Date.parse(updatedAt) < Date.parse(createdAt)) {
133
+ throw new RangeError('updatedAt must not precede createdAt');
134
+ }
135
+ const postingValue = posting(input['posting'], revisionValue);
136
+ const debtusValue = input['debtus'] === undefined
137
+ ? undefined
138
+ : debtusStatus(input['debtus'], request.spaceID, request.billID, request.currency);
139
+ if (debtusValue !== undefined && postingValue.status !== 'applied') {
140
+ throw new TypeError('Debtus status requires applied posting');
141
+ }
142
+ if (debtusValue !== undefined) {
143
+ const receipt = postingValue.receipt;
144
+ if (receipt === undefined) {
145
+ throw new TypeError('Debtus status requires an applied posting receipt');
146
+ }
147
+ validateDebtusMatchesReceipt(receipt, debtusValue);
148
+ }
149
+ return {
150
+ ...request,
151
+ revision: revisionValue,
152
+ posting: postingValue,
153
+ debtus: debtusValue,
154
+ createdAt,
155
+ updatedAt,
156
+ };
157
+ }
158
+ function splitusBillListItem(value) {
159
+ const input = versionedRecord(value, 'bill list item');
160
+ const billKind = enumValue(input['billKind'], ['general', 'utility'], 'billKind');
161
+ const utilityKind = input['utilityKind'] === undefined
162
+ ? undefined
163
+ : enumValue(input['utilityKind'], ['electricity', 'gas', 'water', 'internet', 'other'], 'utilityKind');
164
+ const periodValue = input['period'] === undefined ? undefined : period(input['period']);
165
+ if ((billKind === 'utility') !==
166
+ (utilityKind !== undefined && periodValue !== undefined)) {
167
+ throw new TypeError('utility list items require utilityKind and period');
168
+ }
169
+ const postingStatus = enumValue(input['postingStatus'], ['pending', 'posting', 'applied', 'attention'], 'postingStatus');
170
+ const debtusSettlementStatus = input['debtusSettlementStatus'] === undefined
171
+ ? undefined
172
+ : settlementStatus(input['debtusSettlementStatus'], 'debtusSettlementStatus');
173
+ if (debtusSettlementStatus !== undefined &&
174
+ postingStatus !== 'applied') {
175
+ throw new TypeError('Debtus settlement status requires applied posting');
176
+ }
177
+ return {
178
+ contractVersion: SPLITUS_BILL_CONTRACT_VERSION,
179
+ spaceID: storageID(input['spaceID'], 'spaceID'),
180
+ billID: storageID(input['billID'], 'billID'),
181
+ title: optionalText(input['title'], 'title', 256),
182
+ billKind,
183
+ utilityKind,
184
+ period: periodValue,
185
+ currency: currency(input['currency']),
186
+ actualAmount: positiveAmount(input['actualAmount'], 'actualAmount'),
187
+ ownPaidAmount: nonNegativeAmount(input['ownPaidAmount'], 'ownPaidAmount'),
188
+ ownOwedAmount: nonNegativeAmount(input['ownOwedAmount'], 'ownOwedAmount'),
189
+ postingStatus,
190
+ debtusSettlementStatus,
191
+ createdAt: timestamp(input['createdAt'], 'createdAt'),
192
+ };
193
+ }
194
+ function posting(value, billRevision) {
195
+ const input = record(value, 'posting');
196
+ const status = enumValue(input['status'], ['pending', 'posting', 'applied', 'attention'], 'posting.status');
197
+ const operationKey = storageID(input['operationKey'], 'posting.operationKey');
198
+ const inputDigest = digest(input['inputDigest'], 'posting.inputDigest');
199
+ const receiptValue = input['receipt'] === undefined
200
+ ? undefined
201
+ : postingReceipt(input['receipt'], billRevision, operationKey, inputDigest);
202
+ const attentionCode = input['attentionCode'] === undefined
203
+ ? undefined
204
+ : enumValue(input['attentionCode'], [
205
+ 'authorization_changed',
206
+ 'source_conflict',
207
+ 'provider_rejected',
208
+ 'invalid_provider_receipt',
209
+ 'operator_action_required',
210
+ ], 'posting.attentionCode');
211
+ if ((status === 'applied') !== (receiptValue !== undefined)) {
212
+ throw new TypeError('applied posting status requires exactly one receipt');
213
+ }
214
+ if ((status === 'attention') !== (attentionCode !== undefined)) {
215
+ throw new TypeError('attention posting status requires exactly one code');
216
+ }
217
+ return {
218
+ status,
219
+ operationKey,
220
+ inputDigest,
221
+ receipt: receiptValue,
222
+ attentionCode,
223
+ };
224
+ }
225
+ function postingReceipt(value, billRevision, operationKey, inputDigest) {
226
+ const input = record(value, 'posting.receipt');
227
+ const revisionValue = positiveIntegerString(input['revision'], 'posting.receipt.revision');
228
+ const receiptOperationKey = storageID(input['operationKey'], 'posting.receipt.operationKey');
229
+ const receiptInputDigest = digest(input['inputDigest'], 'posting.receipt.inputDigest');
230
+ if (revisionValue !== billRevision ||
231
+ receiptOperationKey !== operationKey ||
232
+ receiptInputDigest !== inputDigest) {
233
+ throw new TypeError('posting receipt does not match the accepted bill revision');
234
+ }
235
+ if (!Array.isArray(input['obligationLines']) ||
236
+ input['obligationLines'].length > MAX_SPLITUS_BILL_OBLIGATIONS) {
237
+ throw new RangeError('posting receipt obligationLines are unbounded');
238
+ }
239
+ const lineIDs = new Set();
240
+ const obligationIDs = new Set();
241
+ const obligationLines = input['obligationLines'].map((value, index) => {
242
+ const line = record(value, `posting.receipt.obligationLines[${index}]`);
243
+ const lineID = storageID(line['lineID'], `posting.receipt.obligationLines[${index}].lineID`);
244
+ if (lineIDs.has(lineID)) {
245
+ throw new TypeError('posting receipt repeats an obligation line');
246
+ }
247
+ lineIDs.add(lineID);
248
+ const ids = identifierArray(line['obligationIDs'], `posting.receipt.obligationLines[${index}].obligationIDs`, MAX_SPLITUS_OBLIGATION_IDS_PER_LINE);
249
+ for (const id of ids) {
250
+ if (obligationIDs.has(id)) {
251
+ throw new TypeError('posting receipt repeats an obligation ID');
252
+ }
253
+ obligationIDs.add(id);
254
+ }
255
+ return { lineID, obligationIDs: ids };
256
+ });
257
+ return {
258
+ receiptID: storageID(input['receiptID'], 'posting.receipt.receiptID'),
259
+ operationKey: receiptOperationKey,
260
+ inputDigest: receiptInputDigest,
261
+ revision: revisionValue,
262
+ obligationLines,
263
+ };
264
+ }
265
+ function debtusStatus(value, spaceID, billID, billCurrency) {
266
+ const input = record(value, 'debtus');
267
+ if (!Array.isArray(input['obligations']) ||
268
+ input['obligations'].length > MAX_SPLITUS_BILL_OBLIGATIONS) {
269
+ throw new RangeError('Debtus obligations are unbounded');
270
+ }
271
+ const lineIDs = new Set();
272
+ const obligations = input['obligations'].map((item, index) => {
273
+ const obligation = record(item, `debtus.obligations[${index}]`);
274
+ const lineID = storageID(obligation['lineID'], `debtus.obligations[${index}].lineID`);
275
+ if (lineIDs.has(lineID)) {
276
+ throw new TypeError('Debtus status repeats an obligation line');
277
+ }
278
+ lineIDs.add(lineID);
279
+ const obligationCurrency = currency(obligation['currency']);
280
+ if (obligationCurrency !== billCurrency) {
281
+ throw new TypeError('Debtus obligation currency differs from the bill');
282
+ }
283
+ return {
284
+ lineID,
285
+ obligationIDs: identifierArray(obligation['obligationIDs'], `debtus.obligations[${index}].obligationIDs`, MAX_SPLITUS_OBLIGATION_IDS_PER_LINE),
286
+ debtorContactID: storageID(obligation['debtorContactID'], `debtus.obligations[${index}].debtorContactID`),
287
+ creditorContactID: storageID(obligation['creditorContactID'], `debtus.obligations[${index}].creditorContactID`),
288
+ currency: obligationCurrency,
289
+ principalAmount: positiveAmount(obligation['principalAmount'], `debtus.obligations[${index}].principalAmount`),
290
+ outstandingAmount: nonNegativeAmount(obligation['outstandingAmount'], `debtus.obligations[${index}].outstandingAmount`),
291
+ repaidAmount: nonNegativeAmount(obligation['repaidAmount'], `debtus.obligations[${index}].repaidAmount`),
292
+ creditAmount: nonNegativeAmount(obligation['creditAmount'], `debtus.obligations[${index}].creditAmount`),
293
+ status: settlementStatus(obligation['status'], `debtus.obligations[${index}].status`),
294
+ settlementTarget: settlementTarget(obligation['settlementTarget'], spaceID, billID, lineID),
295
+ };
296
+ });
297
+ return {
298
+ status: settlementStatus(input['status'], 'debtus.status'),
299
+ obligations,
300
+ settlementTarget: settlementTarget(input['settlementTarget'], spaceID, billID),
301
+ };
302
+ }
303
+ function validateDebtusMatchesReceipt(receipt, debtus) {
304
+ if (receipt.obligationLines.length !== debtus.obligations.length) {
305
+ throw new TypeError('Debtus obligations do not exactly match the applied posting receipt');
306
+ }
307
+ const receiptLines = new Map(receipt.obligationLines.map((line) => [
308
+ line.lineID,
309
+ new Set(line.obligationIDs),
310
+ ]));
311
+ for (const obligation of debtus.obligations) {
312
+ const receiptIDs = receiptLines.get(obligation.lineID);
313
+ if (receiptIDs === undefined ||
314
+ receiptIDs.size !== obligation.obligationIDs.length ||
315
+ obligation.obligationIDs.some((id) => !receiptIDs.has(id))) {
316
+ throw new TypeError('Debtus obligations do not exactly match the applied posting receipt');
317
+ }
318
+ }
319
+ }
320
+ function settlementTarget(value, spaceID, billID, expectedLineID) {
321
+ const input = record(value, 'settlementTarget');
322
+ const lineID = input['lineID'] === undefined
323
+ ? undefined
324
+ : storageID(input['lineID'], 'settlementTarget.lineID');
325
+ if (input['route'] !== 'debtus.source-obligations' ||
326
+ input['sourceNamespace'] !== 'splitus' ||
327
+ input['spaceID'] !== spaceID ||
328
+ input['sourceRecordID'] !== billID ||
329
+ lineID !== expectedLineID) {
330
+ throw new TypeError('settlement target does not match the Splitus bill source');
331
+ }
332
+ return {
333
+ route: 'debtus.source-obligations',
334
+ spaceID,
335
+ sourceNamespace: 'splitus',
336
+ sourceRecordID: billID,
337
+ lineID,
338
+ };
339
+ }
340
+ function versionedRecord(value, name) {
341
+ const input = record(value, name);
342
+ if (input['contractVersion'] !== SPLITUS_BILL_CONTRACT_VERSION) {
343
+ throw new TypeError('unsupported Splitus bill contract version');
344
+ }
345
+ return input;
346
+ }
347
+ function boundedPageSize(value) {
348
+ if (typeof value !== 'number' ||
349
+ !Number.isSafeInteger(value) ||
350
+ value < 1 ||
351
+ value > MAX_SPLITUS_BILL_LIST_PAGE_SIZE) {
352
+ throw new RangeError(`pageSize must be an integer from 1 to ${MAX_SPLITUS_BILL_LIST_PAGE_SIZE}`);
353
+ }
354
+ return value;
355
+ }
356
+ function settlementStatus(value, name) {
357
+ return enumValue(value, ['unsettled', 'part_settled', 'settled'], name);
358
+ }
359
+ function identifierArray(value, name, maximum) {
360
+ if (!Array.isArray(value) || value.length < 1 || value.length > maximum) {
361
+ throw new RangeError(`${name} must contain 1 to ${maximum} identifiers`);
362
+ }
363
+ const seen = new Set();
364
+ return value.map((item, index) => {
365
+ const id = storageID(item, `${name}[${index}]`);
366
+ if (seen.has(id)) {
367
+ throw new TypeError(`${name} contains a duplicate identifier`);
368
+ }
369
+ seen.add(id);
370
+ return id;
371
+ });
372
+ }
373
+ function digest(value, name) {
374
+ if (typeof value !== 'string' || !/^[0-9a-f]{64}$/.test(value)) {
375
+ throw new TypeError(`${name} must be a lowercase SHA-256 digest`);
376
+ }
377
+ return value;
378
+ }
379
+ function positiveIntegerString(value, name) {
380
+ if (typeof value !== 'string' || !/^[1-9][0-9]*$/.test(value)) {
381
+ throw new TypeError(`${name} must be a canonical positive integer string`);
382
+ }
383
+ if (BigInt(value) > 18446744073709551615n) {
384
+ throw new RangeError(`${name} exceeds unsigned 64-bit range`);
385
+ }
386
+ return value;
387
+ }
388
+ function timestamp(value, name) {
389
+ if (typeof value !== 'string' ||
390
+ !/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/.test(value) ||
391
+ Number.isNaN(Date.parse(value))) {
392
+ throw new TypeError(`${name} must be an RFC 3339 timestamp`);
393
+ }
394
+ date(value.slice(0, 10), name);
395
+ return value;
396
+ }
397
+ function nonNegativeAmount(value, name) {
398
+ try {
399
+ return parseExactDecimalString(value);
400
+ }
401
+ catch (error) {
402
+ if (error instanceof RangeError) {
403
+ throw new RangeError(`${name}: ${error.message}`);
404
+ }
405
+ if (error instanceof Error) {
406
+ throw new TypeError(`${name}: ${error.message}`);
407
+ }
408
+ throw error;
409
+ }
410
+ }
411
+ function validateAllocationTotals(request) {
412
+ const contacts = new Set();
413
+ for (const allocation of [
414
+ ...request.paidAllocations,
415
+ ...request.owedAllocations,
416
+ ]) {
417
+ contacts.add(allocation.contactID);
418
+ }
419
+ if (contacts.size < 2 || contacts.size > MAX_SPLITUS_BILL_PARTICIPANTS) {
420
+ throw new RangeError(`bill must have 2 to ${MAX_SPLITUS_BILL_PARTICIPANTS} participants`);
421
+ }
422
+ const actual = amountToMinorUnits(request.actualAmount);
423
+ if (sumAllocations(request.paidAllocations) !== actual) {
424
+ throw new RangeError('paid allocations must reconcile to actualAmount');
425
+ }
426
+ if (sumAllocations(request.owedAllocations) !== actual) {
427
+ throw new RangeError('owed allocations must reconcile to actualAmount');
428
+ }
429
+ }
430
+ function allocations(value, name) {
431
+ if (!Array.isArray(value) || value.length < 1 || value.length > MAX_SPLITUS_BILL_PARTICIPANTS) {
432
+ throw new RangeError(`${name} must contain 1 to ${MAX_SPLITUS_BILL_PARTICIPANTS} allocations`);
433
+ }
434
+ const allocationIDs = new Set();
435
+ const contactIDs = new Set();
436
+ return value.map((item, index) => {
437
+ const input = record(item, `${name}[${index}]`);
438
+ const allocationID = storageID(input['allocationID'], `${name}[${index}].allocationID`);
439
+ const contactID = storageID(input['contactID'], `${name}[${index}].contactID`);
440
+ if (allocationIDs.has(allocationID) || contactIDs.has(contactID)) {
441
+ throw new TypeError(`${name} contains a duplicate allocation or contact`);
442
+ }
443
+ allocationIDs.add(allocationID);
444
+ contactIDs.add(contactID);
445
+ return {
446
+ allocationID,
447
+ contactID,
448
+ amount: positiveAmount(input['amount'], `${name}[${index}].amount`),
449
+ };
450
+ });
451
+ }
452
+ function sumAllocations(allocationsToSum) {
453
+ let total = 0n;
454
+ for (const allocation of allocationsToSum) {
455
+ total += amountToMinorUnits(allocation.amount);
456
+ if (total > MAX_EXACT_MINOR_UNITS) {
457
+ throw new RangeError('allocation total exceeds the Splitus contract limit');
458
+ }
459
+ }
460
+ return total;
461
+ }
462
+ function amountToMinorUnits(value) {
463
+ return BigInt(value.replace('.', ''));
464
+ }
465
+ function positiveAmount(value, name) {
466
+ const amount = parseExactDecimalString(value);
467
+ if (amountToMinorUnits(amount) === 0n) {
468
+ throw new RangeError(`${name} must be positive`);
469
+ }
470
+ return amount;
471
+ }
472
+ function utility(value) {
473
+ const input = record(value, 'utility');
474
+ return {
475
+ utilityKind: enumValue(input['utilityKind'], ['electricity', 'gas', 'water', 'internet', 'other'], 'utility.utilityKind'),
476
+ providerName: optionalText(input['providerName'], 'utility.providerName', 256),
477
+ period: period(input['period']),
478
+ };
479
+ }
480
+ function recurring(value, actualAmount, billID) {
481
+ const input = record(value, 'recurringOccurrence');
482
+ const expectedAmount = input['expectedAmount'] === undefined
483
+ ? undefined
484
+ : positiveAmount(input['expectedAmount'], 'recurringOccurrence.expectedAmount');
485
+ const standingChargeAmount = input['standingChargeAmount'] === undefined
486
+ ? undefined
487
+ : positiveAmount(input['standingChargeAmount'], 'recurringOccurrence.standingChargeAmount');
488
+ const expectedComparison = enumValue(input['expectedComparison'], ['not_available', 'matches', 'increased', 'decreased'], 'recurringOccurrence.expectedComparison');
489
+ if ((expectedAmount === undefined) !==
490
+ (expectedComparison === 'not_available')) {
491
+ throw new TypeError('comparison must be not_available exactly when expectedAmount is absent');
492
+ }
493
+ if (expectedAmount !== undefined) {
494
+ const expectedComparisonForAmounts = compareAmounts(actualAmount, expectedAmount);
495
+ if (expectedComparison !== expectedComparisonForAmounts) {
496
+ throw new TypeError('comparison does not match expected and actual amounts');
497
+ }
498
+ }
499
+ if (standingChargeAmount !== undefined &&
500
+ amountToMinorUnits(standingChargeAmount) > amountToMinorUnits(actualAmount)) {
501
+ throw new RangeError('standing charge cannot exceed actualAmount');
502
+ }
503
+ return {
504
+ happeningID: storageID(input['happeningID'], 'recurringOccurrence.happeningID'),
505
+ occurrenceID: storageID(input['occurrenceID'], 'recurringOccurrence.occurrenceID'),
506
+ expectedAmount,
507
+ standingChargeAmount,
508
+ expectedComparison,
509
+ previousComparable: input['previousComparable'] === undefined
510
+ ? undefined
511
+ : previousComparable(input['previousComparable'], actualAmount, billID),
512
+ };
513
+ }
514
+ function previousComparable(value, actualAmount, billID) {
515
+ const input = record(value, 'recurringOccurrence.previousComparable');
516
+ const previousBillID = storageID(input['billID'], 'recurringOccurrence.previousComparable.billID');
517
+ if (previousBillID === billID) {
518
+ throw new TypeError('previous comparable bill must have a different billID');
519
+ }
520
+ const previousActualAmount = positiveAmount(input['actualAmount'], 'recurringOccurrence.previousComparable.actualAmount');
521
+ const comparison = enumValue(input['comparison'], ['matches', 'increased', 'decreased'], 'recurringOccurrence.previousComparable.comparison');
522
+ const expectedComparison = compareAmounts(actualAmount, previousActualAmount);
523
+ if (comparison !== expectedComparison) {
524
+ throw new TypeError('previous comparison does not match current and prior actual amounts');
525
+ }
526
+ return {
527
+ billID: previousBillID,
528
+ actualAmount: previousActualAmount,
529
+ comparison,
530
+ };
531
+ }
532
+ function compareAmounts(current, baseline) {
533
+ const currentMinor = amountToMinorUnits(current);
534
+ const baselineMinor = amountToMinorUnits(baseline);
535
+ return currentMinor === baselineMinor
536
+ ? 'matches'
537
+ : currentMinor > baselineMinor
538
+ ? 'increased'
539
+ : 'decreased';
540
+ }
541
+ function period(value) {
542
+ const input = record(value, 'period');
543
+ const startDate = date(input['startDate'], 'period.startDate');
544
+ const endDate = date(input['endDate'], 'period.endDate');
545
+ if (endDate < startDate) {
546
+ throw new RangeError('period.endDate must not precede period.startDate');
547
+ }
548
+ return { startDate, endDate };
549
+ }
550
+ function date(value, name) {
551
+ if (typeof value !== 'string') {
552
+ throw new TypeError(`${name} must be an ISO calendar date`);
553
+ }
554
+ const match = datePattern.exec(value);
555
+ if (match === null) {
556
+ throw new TypeError(`${name} must be an ISO calendar date`);
557
+ }
558
+ const parsed = new Date(`${value}T00:00:00.000Z`);
559
+ if (Number.isNaN(parsed.valueOf()) || parsed.toISOString().slice(0, 10) !== value) {
560
+ throw new TypeError(`${name} must be a real ISO calendar date`);
561
+ }
562
+ return value;
563
+ }
564
+ function currency(value) {
565
+ return enumValue(value, ['EUR', 'GBP', 'USD'], 'currency');
566
+ }
567
+ function storageID(value, name) {
568
+ if (typeof value !== 'string' ||
569
+ value.length === 0 ||
570
+ value.trim() !== value ||
571
+ new TextEncoder().encode(value).length > 512 ||
572
+ value.includes('/') ||
573
+ hasControlCharacters(value) ||
574
+ value === '.' ||
575
+ value === '..' ||
576
+ (/^__/.test(value) && /__$/.test(value))) {
577
+ throw new TypeError(`${name} is not a safe identifier`);
578
+ }
579
+ return value;
580
+ }
581
+ function optionalText(value, name, maxBytes) {
582
+ if (value === undefined) {
583
+ return undefined;
584
+ }
585
+ if (typeof value !== 'string' ||
586
+ value.length === 0 ||
587
+ value.trim() !== value ||
588
+ new TextEncoder().encode(value).length > maxBytes ||
589
+ hasControlCharacters(value)) {
590
+ throw new TypeError(`${name} is empty, padded, too long, or contains controls`);
591
+ }
592
+ return value;
593
+ }
594
+ function hasControlCharacters(value) {
595
+ for (const character of value) {
596
+ const code = character.charCodeAt(0);
597
+ if (code < 0x20 || code === 0x7f) {
598
+ return true;
599
+ }
600
+ }
601
+ return false;
602
+ }
603
+ function record(value, name) {
604
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
605
+ throw new TypeError(`${name} must be an object`);
606
+ }
607
+ return value;
608
+ }
609
+ function enumValue(value, allowed, name) {
610
+ if (typeof value !== 'string' || !allowed.includes(value)) {
611
+ throw new TypeError(`${name} has an unsupported value`);
612
+ }
613
+ return value;
614
+ }
615
+
616
+ /** @deprecated Use `SPLITUS_BILL_SERVICE_V1`. */
3
617
  const SPLITUS_SERVICE = new InjectionToken('SplitusService');
618
+ const SPLITUS_BILL_SERVICE_V1 = new InjectionToken('SplitusBillServiceV1');
4
619
 
5
620
  /**
6
621
  * Generated bundle index. Do not edit.
7
622
  */
8
623
 
9
- export { SPLITUS_SERVICE };
624
+ export { MAX_SPLITUS_BILL_LIST_PAGE_SIZE, MAX_SPLITUS_BILL_OBLIGATIONS, MAX_SPLITUS_BILL_PARTICIPANTS, MAX_SPLITUS_OBLIGATION_IDS_PER_LINE, SPLITUS_BILL_CONTRACT_VERSION, SPLITUS_BILL_SERVICE_V1, SPLITUS_SERVICE, assertCreateSplitusBillV1Recorder, parseCreateSplitusBillV1Request, parseCreateSplitusBillV1Response, parseExactDecimalString, parseGetSplitusBillV1Request, parseGetSplitusBillV1Response, parseListSplitusBillsV1Request, parseListSplitusBillsV1Response, parseSplitusBillV1 };
10
625
  //# sourceMappingURL=sneat-extension-splitus-contract.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"sneat-extension-splitus-contract.mjs","sources":["../../../../libs/splitus/src/services.ts","../../../../libs/splitus/src/sneat-extension-splitus-contract.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\nimport { Observable } from 'rxjs';\nimport { ICreateSplitRequest, ICreateSplitResponse, ISplit, ISplitListItem } from './dto';\n\nexport interface ISplitusService {\n /** REAL: POST /api4splitus/create-split. Payer is the authenticated user. */\n createSplit(request: ICreateSplitRequest): Observable<ICreateSplitResponse>;\n /** REAL: GET /api4splitus/split?spaceID=&id= */\n getSplit(spaceID: string, id: string): Observable<ISplit>;\n /** REAL: GET /api4splitus/splits?spaceID= */\n getSplits(spaceID: string): Observable<ISplitListItem[]>;\n}\n\nexport const SPLITUS_SERVICE = new InjectionToken<ISplitusService>('SplitusService');\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;MAaa,eAAe,GAAG,IAAI,cAAc,CAAkB,gBAAgB;;ACbnF;;AAEG;;"}
1
+ {"version":3,"file":"sneat-extension-splitus-contract.mjs","sources":["../../../../libs/splitus/src/dto/bill-v1.ts","../../../../libs/splitus/src/services.ts","../../../../libs/splitus/src/sneat-extension-splitus-contract.ts"],"sourcesContent":["/** The first stable Splitus bill browser/host wire contract. */\nexport const SPLITUS_BILL_CONTRACT_VERSION = 1 as const;\n\nexport const MAX_SPLITUS_BILL_PARTICIPANTS = 256;\nexport const MAX_SPLITUS_BILL_LIST_PAGE_SIZE = 100;\nexport const MAX_SPLITUS_BILL_OBLIGATIONS = 256;\nexport const MAX_SPLITUS_OBLIGATION_IDS_PER_LINE = 256;\n\nexport type SplitusBillContractVersion =\n typeof SPLITUS_BILL_CONTRACT_VERSION;\n\n/**\n * A canonical, non-negative major-unit amount with exactly two fraction\n * digits. Examples: `0.00`, `30.00`, `90.00`.\n *\n * The alias documents the wire type; use `parseExactDecimalString()` at an\n * untrusted boundary. JavaScript numbers and minor-unit numbers are not part\n * of this contract.\n */\nexport type ExactDecimalString = string;\n\n/** Currencies whose minor unit is exactly two decimal digits in this contract. */\nexport type SplitusCurrencyCode = 'EUR' | 'GBP' | 'USD';\n\nexport type SplitusBillKind = 'general' | 'utility';\nexport type SplitusUtilityKind =\n | 'electricity'\n | 'gas'\n | 'water'\n | 'internet'\n | 'other';\n\nexport type SplitusBillPostingStatus =\n | 'pending'\n | 'posting'\n | 'applied'\n | 'attention';\n\nexport type SplitusDebtusSettlementStatus =\n | 'unsettled'\n | 'part_settled'\n | 'settled';\n\nexport type SplitusExpectedActualComparison =\n | 'not_available'\n | 'matches'\n | 'increased'\n | 'decreased';\n\nexport type SplitusBillAttentionCode =\n | 'authorization_changed'\n | 'source_conflict'\n | 'provider_rejected'\n | 'invalid_provider_receipt'\n | 'operator_action_required';\n\nexport interface ISplitusBillAllocationV1 {\n /** Stable within the bill revision, independent of array ordering. */\n readonly allocationID: string;\n /**\n * Contactus identity in this Space. Hosts resolve its real display data from\n * Contactus; this opaque ID is never a user-facing label.\n */\n readonly contactID: string;\n readonly amount: ExactDecimalString;\n}\n\nexport interface ISplitusBillingPeriodV1 {\n /** Inclusive ISO calendar date. */\n readonly startDate: string;\n /** Inclusive ISO calendar date; must not precede `startDate`. */\n readonly endDate: string;\n}\n\nexport interface ISplitusUtilityDetailsV1 {\n readonly utilityKind: SplitusUtilityKind;\n readonly providerName?: string;\n readonly period: ISplitusBillingPeriodV1;\n}\n\n/**\n * A reference to the Calendarius occurrence represented by this actual bill.\n * `expectedAmount` and `standingChargeAmount` are context only; neither is a\n * paid expense. `actualAmount` on the enclosing bill remains mandatory.\n */\nexport interface ISplitusRecurringOccurrenceV1 {\n readonly happeningID: string;\n readonly occurrenceID: string;\n readonly expectedAmount?: ExactDecimalString;\n readonly standingChargeAmount?: ExactDecimalString;\n readonly expectedComparison: SplitusExpectedActualComparison;\n readonly previousComparable?: ISplitusPreviousComparableBillV1;\n}\n\nexport interface ISplitusPreviousComparableBillV1 {\n readonly billID: string;\n readonly actualAmount: ExactDecimalString;\n readonly comparison: Exclude<\n SplitusExpectedActualComparison,\n 'not_available'\n >;\n}\n\nexport interface ICreateSplitusBillV1Request {\n readonly contractVersion: SplitusBillContractVersion;\n readonly spaceID: string;\n /**\n * Stable across duplicate submission and lost-response retries. Reusing the\n * same ID with changed paid/owed allocations is a provider conflict.\n */\n readonly billID: string;\n /**\n * Audit identity of the authenticated actor. The server must bind this to\n * its trusted authentication context. It never implies a paid or owed\n * allocation.\n */\n readonly recorderUserID: string;\n readonly title?: string;\n readonly billKind: SplitusBillKind;\n readonly currency: SplitusCurrencyCode;\n /** Actual paid amount. An expectation is never accepted in its place. */\n readonly actualAmount: ExactDecimalString;\n /** Explicit sources of payment; one contact may also owe a share. */\n readonly paidAllocations: readonly ISplitusBillAllocationV1[];\n /** Explicit responsibility shares. */\n readonly owedAllocations: readonly ISplitusBillAllocationV1[];\n /** Required exactly when `billKind` is `utility`. */\n readonly utility?: ISplitusUtilityDetailsV1;\n readonly recurringOccurrence?: ISplitusRecurringOccurrenceV1;\n}\n\nexport interface ISplitusDebtusReceiptLineV1 {\n readonly lineID: string;\n readonly obligationIDs: readonly string[];\n}\n\nexport interface ISplitusBillPostingReceiptV1 {\n readonly receiptID: string;\n readonly operationKey: string;\n readonly inputDigest: string;\n readonly revision: string;\n readonly obligationLines: readonly ISplitusDebtusReceiptLineV1[];\n}\n\nexport interface ISplitusBillPostingV1 {\n readonly status: SplitusBillPostingStatus;\n /** Durable identity of the retry-safe provider operation. */\n readonly operationKey: string;\n /** Digest of the exact accepted source revision and allocations. */\n readonly inputDigest: string;\n /** Present exactly when `status` is `applied`. */\n readonly receipt?: ISplitusBillPostingReceiptV1;\n /** Present exactly when `status` is `attention`. */\n readonly attentionCode?: SplitusBillAttentionCode;\n}\n\n/**\n * An application-relative target. The host resolves it through its injected\n * Debtus navigation adapter; contracts never hard-code debtus.app or another\n * deployment origin.\n */\nexport interface ISplitusDebtusSettlementTargetV1 {\n readonly route: 'debtus.source-obligations';\n readonly spaceID: string;\n readonly sourceNamespace: 'splitus';\n readonly sourceRecordID: string;\n readonly lineID?: string;\n}\n\nexport interface ISplitusDebtusObligationV1 {\n readonly lineID: string;\n readonly obligationIDs: readonly string[];\n readonly debtorContactID: string;\n readonly creditorContactID: string;\n readonly currency: SplitusCurrencyCode;\n readonly principalAmount: ExactDecimalString;\n readonly outstandingAmount: ExactDecimalString;\n readonly repaidAmount: ExactDecimalString;\n readonly creditAmount: ExactDecimalString;\n readonly status: SplitusDebtusSettlementStatus;\n readonly settlementTarget: ISplitusDebtusSettlementTargetV1;\n}\n\nexport interface ISplitusDebtusStatusV1 {\n /** Current state read from Debtus, never a Splitus-maintained balance. */\n readonly status: SplitusDebtusSettlementStatus;\n readonly obligations: readonly ISplitusDebtusObligationV1[];\n readonly settlementTarget: ISplitusDebtusSettlementTargetV1;\n}\n\nexport interface ISplitusBillV1 extends ICreateSplitusBillV1Request {\n /** Canonical positive decimal integer encoded as a string. */\n readonly revision: string;\n readonly posting: ISplitusBillPostingV1;\n /** Absent until a Debtus financial projection is available. */\n readonly debtus?: ISplitusDebtusStatusV1;\n readonly createdAt: string;\n readonly updatedAt: string;\n}\n\nexport interface ICreateSplitusBillV1Response {\n readonly contractVersion: SplitusBillContractVersion;\n readonly bill: ISplitusBillV1;\n}\n\nexport interface IGetSplitusBillV1Request {\n readonly contractVersion: SplitusBillContractVersion;\n readonly spaceID: string;\n readonly billID: string;\n}\n\nexport interface IGetSplitusBillV1Response {\n readonly contractVersion: SplitusBillContractVersion;\n readonly bill: ISplitusBillV1;\n}\n\nexport interface ISplitusBillListItemV1 {\n readonly contractVersion: SplitusBillContractVersion;\n readonly spaceID: string;\n readonly billID: string;\n readonly title?: string;\n readonly billKind: SplitusBillKind;\n readonly utilityKind?: SplitusUtilityKind;\n readonly period?: ISplitusBillingPeriodV1;\n readonly currency: SplitusCurrencyCode;\n readonly actualAmount: ExactDecimalString;\n readonly ownPaidAmount: ExactDecimalString;\n readonly ownOwedAmount: ExactDecimalString;\n readonly postingStatus: SplitusBillPostingStatus;\n /** Debtus-derived and absent before the bill has a financial projection. */\n readonly debtusSettlementStatus?: SplitusDebtusSettlementStatus;\n readonly createdAt: string;\n}\n\nexport interface IListSplitusBillsV1Request {\n readonly contractVersion: SplitusBillContractVersion;\n readonly spaceID: string;\n readonly pageSize: number;\n readonly cursor?: string;\n readonly utilityKind?: SplitusUtilityKind;\n readonly period?: ISplitusBillingPeriodV1;\n}\n\nexport interface IListSplitusBillsV1Response {\n readonly contractVersion: SplitusBillContractVersion;\n /** Echoes the accepted request bound so callers can verify the page. */\n readonly pageSize: number;\n /** Contains no more than `pageSize` items and never more than 100. */\n readonly items: readonly ISplitusBillListItemV1[];\n readonly nextCursor?: string;\n}\n\nconst MAX_EXACT_MINOR_UNITS = 9_223_372_036_854_775_807n;\nconst exactDecimalPattern = /^(?:0|[1-9][0-9]*)\\.[0-9]{2}$/;\nconst datePattern = /^([0-9]{4})-([0-9]{2})-([0-9]{2})$/;\n\nexport function parseExactDecimalString(value: unknown): ExactDecimalString {\n if (typeof value !== 'string' || !exactDecimalPattern.test(value)) {\n throw new TypeError(\n 'amount must be a canonical decimal string with exactly two fraction digits',\n );\n }\n const minorUnits = BigInt(value.replace('.', ''));\n if (minorUnits > MAX_EXACT_MINOR_UNITS) {\n throw new RangeError('amount exceeds the Splitus contract limit');\n }\n return value;\n}\n\nexport function parseCreateSplitusBillV1Request(\n value: unknown,\n): ICreateSplitusBillV1Request {\n const input = record(value, 'create bill request');\n if (input['contractVersion'] !== SPLITUS_BILL_CONTRACT_VERSION) {\n throw new TypeError('unsupported Splitus bill contract version');\n }\n const billKind = enumValue(\n input['billKind'],\n ['general', 'utility'] as const,\n 'billKind',\n );\n const actualAmount = positiveAmount(input['actualAmount'], 'actualAmount');\n const spaceID = storageID(input['spaceID'], 'spaceID');\n const billID = storageID(input['billID'], 'billID');\n const recorderUserID = storageID(\n input['recorderUserID'],\n 'recorderUserID',\n );\n const request: ICreateSplitusBillV1Request = {\n contractVersion: SPLITUS_BILL_CONTRACT_VERSION,\n spaceID,\n billID,\n recorderUserID,\n title: optionalText(input['title'], 'title', 256),\n billKind,\n currency: currency(input['currency']),\n actualAmount,\n paidAllocations: allocations(input['paidAllocations'], 'paidAllocations'),\n owedAllocations: allocations(input['owedAllocations'], 'owedAllocations'),\n utility:\n input['utility'] === undefined ? undefined : utility(input['utility']),\n recurringOccurrence:\n input['recurringOccurrence'] === undefined\n ? undefined\n : recurring(input['recurringOccurrence'], actualAmount, billID),\n };\n if ((billKind === 'utility') !== (request.utility !== undefined)) {\n throw new TypeError('utility details are required only for utility bills');\n }\n validateAllocationTotals(request);\n return request;\n}\n\n/**\n * Executable host-boundary check for the request's audit claim. The trusted\n * authenticated identity is supplied by the host, never derived from the\n * request itself.\n */\nexport function assertCreateSplitusBillV1Recorder(\n request: ICreateSplitusBillV1Request,\n authenticatedUserID: string,\n): void {\n const trustedUserID = storageID(\n authenticatedUserID,\n 'authenticatedUserID',\n );\n if (request.recorderUserID !== trustedUserID) {\n throw new TypeError(\n 'recorderUserID must match the trusted authenticated identity',\n );\n }\n}\n\nexport function parseListSplitusBillsV1Request(\n value: unknown,\n): IListSplitusBillsV1Request {\n const input = record(value, 'list bills request');\n if (input['contractVersion'] !== SPLITUS_BILL_CONTRACT_VERSION) {\n throw new TypeError('unsupported Splitus bill contract version');\n }\n const pageSize = input['pageSize'];\n if (\n typeof pageSize !== 'number' ||\n !Number.isSafeInteger(pageSize) ||\n pageSize < 1 ||\n pageSize > MAX_SPLITUS_BILL_LIST_PAGE_SIZE\n ) {\n throw new RangeError(\n `pageSize must be an integer from 1 to ${MAX_SPLITUS_BILL_LIST_PAGE_SIZE}`,\n );\n }\n return {\n contractVersion: SPLITUS_BILL_CONTRACT_VERSION,\n spaceID: storageID(input['spaceID'], 'spaceID'),\n pageSize,\n cursor: optionalText(input['cursor'], 'cursor', 2048),\n utilityKind:\n input['utilityKind'] === undefined\n ? undefined\n : enumValue(\n input['utilityKind'],\n ['electricity', 'gas', 'water', 'internet', 'other'] as const,\n 'utilityKind',\n ),\n period:\n input['period'] === undefined ? undefined : period(input['period']),\n };\n}\n\nexport function parseGetSplitusBillV1Request(\n value: unknown,\n): IGetSplitusBillV1Request {\n const input = versionedRecord(value, 'get bill request');\n return {\n contractVersion: SPLITUS_BILL_CONTRACT_VERSION,\n spaceID: storageID(input['spaceID'], 'spaceID'),\n billID: storageID(input['billID'], 'billID'),\n };\n}\n\nexport function parseCreateSplitusBillV1Response(\n value: unknown,\n): ICreateSplitusBillV1Response {\n const input = versionedRecord(value, 'create bill response');\n return {\n contractVersion: SPLITUS_BILL_CONTRACT_VERSION,\n bill: parseSplitusBillV1(input['bill']),\n };\n}\n\nexport function parseGetSplitusBillV1Response(\n value: unknown,\n): IGetSplitusBillV1Response {\n const input = versionedRecord(value, 'get bill response');\n return {\n contractVersion: SPLITUS_BILL_CONTRACT_VERSION,\n bill: parseSplitusBillV1(input['bill']),\n };\n}\n\nexport function parseListSplitusBillsV1Response(\n value: unknown,\n requestedPageSize?: number,\n): IListSplitusBillsV1Response {\n const input = versionedRecord(value, 'list bills response');\n const pageSize = boundedPageSize(input['pageSize']);\n if (requestedPageSize !== undefined && pageSize !== requestedPageSize) {\n throw new RangeError('response pageSize does not match the accepted request');\n }\n if (!Array.isArray(input['items']) || input['items'].length > pageSize) {\n throw new RangeError('response items exceed the bounded pageSize');\n }\n return {\n contractVersion: SPLITUS_BILL_CONTRACT_VERSION,\n pageSize,\n items: input['items'].map((item) => splitusBillListItem(item)),\n nextCursor: optionalText(input['nextCursor'], 'nextCursor', 2048),\n };\n}\n\nexport function parseSplitusBillV1(value: unknown): ISplitusBillV1 {\n const input = record(value, 'bill');\n const request = parseCreateSplitusBillV1Request(input);\n const revisionValue = positiveIntegerString(input['revision'], 'revision');\n const createdAt = timestamp(input['createdAt'], 'createdAt');\n const updatedAt = timestamp(input['updatedAt'], 'updatedAt');\n if (Date.parse(updatedAt) < Date.parse(createdAt)) {\n throw new RangeError('updatedAt must not precede createdAt');\n }\n const postingValue = posting(input['posting'], revisionValue);\n const debtusValue =\n input['debtus'] === undefined\n ? undefined\n : debtusStatus(\n input['debtus'],\n request.spaceID,\n request.billID,\n request.currency,\n );\n if (debtusValue !== undefined && postingValue.status !== 'applied') {\n throw new TypeError('Debtus status requires applied posting');\n }\n if (debtusValue !== undefined) {\n const receipt = postingValue.receipt;\n if (receipt === undefined) {\n throw new TypeError('Debtus status requires an applied posting receipt');\n }\n validateDebtusMatchesReceipt(receipt, debtusValue);\n }\n return {\n ...request,\n revision: revisionValue,\n posting: postingValue,\n debtus: debtusValue,\n createdAt,\n updatedAt,\n };\n}\n\nfunction splitusBillListItem(value: unknown): ISplitusBillListItemV1 {\n const input = versionedRecord(value, 'bill list item');\n const billKind = enumValue(\n input['billKind'],\n ['general', 'utility'] as const,\n 'billKind',\n );\n const utilityKind =\n input['utilityKind'] === undefined\n ? undefined\n : enumValue(\n input['utilityKind'],\n ['electricity', 'gas', 'water', 'internet', 'other'] as const,\n 'utilityKind',\n );\n const periodValue =\n input['period'] === undefined ? undefined : period(input['period']);\n if (\n (billKind === 'utility') !==\n (utilityKind !== undefined && periodValue !== undefined)\n ) {\n throw new TypeError('utility list items require utilityKind and period');\n }\n const postingStatus = enumValue(\n input['postingStatus'],\n ['pending', 'posting', 'applied', 'attention'] as const,\n 'postingStatus',\n );\n const debtusSettlementStatus =\n input['debtusSettlementStatus'] === undefined\n ? undefined\n : settlementStatus(\n input['debtusSettlementStatus'],\n 'debtusSettlementStatus',\n );\n if (\n debtusSettlementStatus !== undefined &&\n postingStatus !== 'applied'\n ) {\n throw new TypeError('Debtus settlement status requires applied posting');\n }\n return {\n contractVersion: SPLITUS_BILL_CONTRACT_VERSION,\n spaceID: storageID(input['spaceID'], 'spaceID'),\n billID: storageID(input['billID'], 'billID'),\n title: optionalText(input['title'], 'title', 256),\n billKind,\n utilityKind,\n period: periodValue,\n currency: currency(input['currency']),\n actualAmount: positiveAmount(input['actualAmount'], 'actualAmount'),\n ownPaidAmount: nonNegativeAmount(input['ownPaidAmount'], 'ownPaidAmount'),\n ownOwedAmount: nonNegativeAmount(input['ownOwedAmount'], 'ownOwedAmount'),\n postingStatus,\n debtusSettlementStatus,\n createdAt: timestamp(input['createdAt'], 'createdAt'),\n };\n}\n\nfunction posting(value: unknown, billRevision: string): ISplitusBillPostingV1 {\n const input = record(value, 'posting');\n const status = enumValue(\n input['status'],\n ['pending', 'posting', 'applied', 'attention'] as const,\n 'posting.status',\n );\n const operationKey = storageID(input['operationKey'], 'posting.operationKey');\n const inputDigest = digest(input['inputDigest'], 'posting.inputDigest');\n const receiptValue =\n input['receipt'] === undefined\n ? undefined\n : postingReceipt(\n input['receipt'],\n billRevision,\n operationKey,\n inputDigest,\n );\n const attentionCode =\n input['attentionCode'] === undefined\n ? undefined\n : enumValue(\n input['attentionCode'],\n [\n 'authorization_changed',\n 'source_conflict',\n 'provider_rejected',\n 'invalid_provider_receipt',\n 'operator_action_required',\n ] as const,\n 'posting.attentionCode',\n );\n if ((status === 'applied') !== (receiptValue !== undefined)) {\n throw new TypeError('applied posting status requires exactly one receipt');\n }\n if ((status === 'attention') !== (attentionCode !== undefined)) {\n throw new TypeError('attention posting status requires exactly one code');\n }\n return {\n status,\n operationKey,\n inputDigest,\n receipt: receiptValue,\n attentionCode,\n };\n}\n\nfunction postingReceipt(\n value: unknown,\n billRevision: string,\n operationKey: string,\n inputDigest: string,\n): ISplitusBillPostingReceiptV1 {\n const input = record(value, 'posting.receipt');\n const revisionValue = positiveIntegerString(\n input['revision'],\n 'posting.receipt.revision',\n );\n const receiptOperationKey = storageID(\n input['operationKey'],\n 'posting.receipt.operationKey',\n );\n const receiptInputDigest = digest(\n input['inputDigest'],\n 'posting.receipt.inputDigest',\n );\n if (\n revisionValue !== billRevision ||\n receiptOperationKey !== operationKey ||\n receiptInputDigest !== inputDigest\n ) {\n throw new TypeError('posting receipt does not match the accepted bill revision');\n }\n if (\n !Array.isArray(input['obligationLines']) ||\n input['obligationLines'].length > MAX_SPLITUS_BILL_OBLIGATIONS\n ) {\n throw new RangeError('posting receipt obligationLines are unbounded');\n }\n const lineIDs = new Set<string>();\n const obligationIDs = new Set<string>();\n const obligationLines = input['obligationLines'].map((value, index) => {\n const line = record(value, `posting.receipt.obligationLines[${index}]`);\n const lineID = storageID(\n line['lineID'],\n `posting.receipt.obligationLines[${index}].lineID`,\n );\n if (lineIDs.has(lineID)) {\n throw new TypeError('posting receipt repeats an obligation line');\n }\n lineIDs.add(lineID);\n const ids = identifierArray(\n line['obligationIDs'],\n `posting.receipt.obligationLines[${index}].obligationIDs`,\n MAX_SPLITUS_OBLIGATION_IDS_PER_LINE,\n );\n for (const id of ids) {\n if (obligationIDs.has(id)) {\n throw new TypeError('posting receipt repeats an obligation ID');\n }\n obligationIDs.add(id);\n }\n return { lineID, obligationIDs: ids };\n });\n return {\n receiptID: storageID(input['receiptID'], 'posting.receipt.receiptID'),\n operationKey: receiptOperationKey,\n inputDigest: receiptInputDigest,\n revision: revisionValue,\n obligationLines,\n };\n}\n\nfunction debtusStatus(\n value: unknown,\n spaceID: string,\n billID: string,\n billCurrency: string,\n): ISplitusDebtusStatusV1 {\n const input = record(value, 'debtus');\n if (\n !Array.isArray(input['obligations']) ||\n input['obligations'].length > MAX_SPLITUS_BILL_OBLIGATIONS\n ) {\n throw new RangeError('Debtus obligations are unbounded');\n }\n const lineIDs = new Set<string>();\n const obligations = input['obligations'].map((item, index) => {\n const obligation = record(item, `debtus.obligations[${index}]`);\n const lineID = storageID(\n obligation['lineID'],\n `debtus.obligations[${index}].lineID`,\n );\n if (lineIDs.has(lineID)) {\n throw new TypeError('Debtus status repeats an obligation line');\n }\n lineIDs.add(lineID);\n const obligationCurrency = currency(obligation['currency']);\n if (obligationCurrency !== billCurrency) {\n throw new TypeError('Debtus obligation currency differs from the bill');\n }\n return {\n lineID,\n obligationIDs: identifierArray(\n obligation['obligationIDs'],\n `debtus.obligations[${index}].obligationIDs`,\n MAX_SPLITUS_OBLIGATION_IDS_PER_LINE,\n ),\n debtorContactID: storageID(\n obligation['debtorContactID'],\n `debtus.obligations[${index}].debtorContactID`,\n ),\n creditorContactID: storageID(\n obligation['creditorContactID'],\n `debtus.obligations[${index}].creditorContactID`,\n ),\n currency: obligationCurrency,\n principalAmount: positiveAmount(\n obligation['principalAmount'],\n `debtus.obligations[${index}].principalAmount`,\n ),\n outstandingAmount: nonNegativeAmount(\n obligation['outstandingAmount'],\n `debtus.obligations[${index}].outstandingAmount`,\n ),\n repaidAmount: nonNegativeAmount(\n obligation['repaidAmount'],\n `debtus.obligations[${index}].repaidAmount`,\n ),\n creditAmount: nonNegativeAmount(\n obligation['creditAmount'],\n `debtus.obligations[${index}].creditAmount`,\n ),\n status: settlementStatus(\n obligation['status'],\n `debtus.obligations[${index}].status`,\n ),\n settlementTarget: settlementTarget(\n obligation['settlementTarget'],\n spaceID,\n billID,\n lineID,\n ),\n };\n });\n return {\n status: settlementStatus(input['status'], 'debtus.status'),\n obligations,\n settlementTarget: settlementTarget(\n input['settlementTarget'],\n spaceID,\n billID,\n ),\n };\n}\n\nfunction validateDebtusMatchesReceipt(\n receipt: ISplitusBillPostingReceiptV1,\n debtus: ISplitusDebtusStatusV1,\n): void {\n if (receipt.obligationLines.length !== debtus.obligations.length) {\n throw new TypeError(\n 'Debtus obligations do not exactly match the applied posting receipt',\n );\n }\n const receiptLines = new Map(\n receipt.obligationLines.map((line) => [\n line.lineID,\n new Set(line.obligationIDs),\n ]),\n );\n for (const obligation of debtus.obligations) {\n const receiptIDs = receiptLines.get(obligation.lineID);\n if (\n receiptIDs === undefined ||\n receiptIDs.size !== obligation.obligationIDs.length ||\n obligation.obligationIDs.some((id) => !receiptIDs.has(id))\n ) {\n throw new TypeError(\n 'Debtus obligations do not exactly match the applied posting receipt',\n );\n }\n }\n}\n\nfunction settlementTarget(\n value: unknown,\n spaceID: string,\n billID: string,\n expectedLineID?: string,\n): ISplitusDebtusSettlementTargetV1 {\n const input = record(value, 'settlementTarget');\n const lineID =\n input['lineID'] === undefined\n ? undefined\n : storageID(input['lineID'], 'settlementTarget.lineID');\n if (\n input['route'] !== 'debtus.source-obligations' ||\n input['sourceNamespace'] !== 'splitus' ||\n input['spaceID'] !== spaceID ||\n input['sourceRecordID'] !== billID ||\n lineID !== expectedLineID\n ) {\n throw new TypeError('settlement target does not match the Splitus bill source');\n }\n return {\n route: 'debtus.source-obligations',\n spaceID,\n sourceNamespace: 'splitus',\n sourceRecordID: billID,\n lineID,\n };\n}\n\nfunction versionedRecord(value: unknown, name: string): Record<string, unknown> {\n const input = record(value, name);\n if (input['contractVersion'] !== SPLITUS_BILL_CONTRACT_VERSION) {\n throw new TypeError('unsupported Splitus bill contract version');\n }\n return input;\n}\n\nfunction boundedPageSize(value: unknown): number {\n if (\n typeof value !== 'number' ||\n !Number.isSafeInteger(value) ||\n value < 1 ||\n value > MAX_SPLITUS_BILL_LIST_PAGE_SIZE\n ) {\n throw new RangeError(\n `pageSize must be an integer from 1 to ${MAX_SPLITUS_BILL_LIST_PAGE_SIZE}`,\n );\n }\n return value;\n}\n\nfunction settlementStatus(\n value: unknown,\n name: string,\n): SplitusDebtusSettlementStatus {\n return enumValue(\n value,\n ['unsettled', 'part_settled', 'settled'] as const,\n name,\n );\n}\n\nfunction identifierArray(value: unknown, name: string, maximum: number): string[] {\n if (!Array.isArray(value) || value.length < 1 || value.length > maximum) {\n throw new RangeError(`${name} must contain 1 to ${maximum} identifiers`);\n }\n const seen = new Set<string>();\n return value.map((item, index) => {\n const id = storageID(item, `${name}[${index}]`);\n if (seen.has(id)) {\n throw new TypeError(`${name} contains a duplicate identifier`);\n }\n seen.add(id);\n return id;\n });\n}\n\nfunction digest(value: unknown, name: string): string {\n if (typeof value !== 'string' || !/^[0-9a-f]{64}$/.test(value)) {\n throw new TypeError(`${name} must be a lowercase SHA-256 digest`);\n }\n return value;\n}\n\nfunction positiveIntegerString(value: unknown, name: string): string {\n if (typeof value !== 'string' || !/^[1-9][0-9]*$/.test(value)) {\n throw new TypeError(`${name} must be a canonical positive integer string`);\n }\n if (BigInt(value) > 18_446_744_073_709_551_615n) {\n throw new RangeError(`${name} exceeds unsigned 64-bit range`);\n }\n return value;\n}\n\nfunction timestamp(value: unknown, name: string): string {\n if (\n typeof value !== 'string' ||\n !/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:\\d{2})$/.test(\n value,\n ) ||\n Number.isNaN(Date.parse(value))\n ) {\n throw new TypeError(`${name} must be an RFC 3339 timestamp`);\n }\n date(value.slice(0, 10), name);\n return value;\n}\n\nfunction nonNegativeAmount(\n value: unknown,\n name: string,\n): ExactDecimalString {\n try {\n return parseExactDecimalString(value);\n } catch (error) {\n if (error instanceof RangeError) {\n throw new RangeError(`${name}: ${error.message}`);\n }\n if (error instanceof Error) {\n throw new TypeError(`${name}: ${error.message}`);\n }\n throw error;\n }\n}\n\nfunction validateAllocationTotals(request: ICreateSplitusBillV1Request): void {\n const contacts = new Set<string>();\n for (const allocation of [\n ...request.paidAllocations,\n ...request.owedAllocations,\n ]) {\n contacts.add(allocation.contactID);\n }\n if (contacts.size < 2 || contacts.size > MAX_SPLITUS_BILL_PARTICIPANTS) {\n throw new RangeError(\n `bill must have 2 to ${MAX_SPLITUS_BILL_PARTICIPANTS} participants`,\n );\n }\n const actual = amountToMinorUnits(request.actualAmount);\n if (sumAllocations(request.paidAllocations) !== actual) {\n throw new RangeError('paid allocations must reconcile to actualAmount');\n }\n if (sumAllocations(request.owedAllocations) !== actual) {\n throw new RangeError('owed allocations must reconcile to actualAmount');\n }\n}\n\nfunction allocations(value: unknown, name: string): ISplitusBillAllocationV1[] {\n if (!Array.isArray(value) || value.length < 1 || value.length > MAX_SPLITUS_BILL_PARTICIPANTS) {\n throw new RangeError(\n `${name} must contain 1 to ${MAX_SPLITUS_BILL_PARTICIPANTS} allocations`,\n );\n }\n const allocationIDs = new Set<string>();\n const contactIDs = new Set<string>();\n return value.map((item, index) => {\n const input = record(item, `${name}[${index}]`);\n const allocationID = storageID(\n input['allocationID'],\n `${name}[${index}].allocationID`,\n );\n const contactID = storageID(\n input['contactID'],\n `${name}[${index}].contactID`,\n );\n if (allocationIDs.has(allocationID) || contactIDs.has(contactID)) {\n throw new TypeError(`${name} contains a duplicate allocation or contact`);\n }\n allocationIDs.add(allocationID);\n contactIDs.add(contactID);\n return {\n allocationID,\n contactID,\n amount: positiveAmount(input['amount'], `${name}[${index}].amount`),\n };\n });\n}\n\nfunction sumAllocations(allocationsToSum: readonly ISplitusBillAllocationV1[]): bigint {\n let total = 0n;\n for (const allocation of allocationsToSum) {\n total += amountToMinorUnits(allocation.amount);\n if (total > MAX_EXACT_MINOR_UNITS) {\n throw new RangeError('allocation total exceeds the Splitus contract limit');\n }\n }\n return total;\n}\n\nfunction amountToMinorUnits(value: ExactDecimalString): bigint {\n return BigInt(value.replace('.', ''));\n}\n\nfunction positiveAmount(value: unknown, name: string): ExactDecimalString {\n const amount = parseExactDecimalString(value);\n if (amountToMinorUnits(amount) === 0n) {\n throw new RangeError(`${name} must be positive`);\n }\n return amount;\n}\n\nfunction utility(value: unknown): ISplitusUtilityDetailsV1 {\n const input = record(value, 'utility');\n return {\n utilityKind: enumValue(\n input['utilityKind'],\n ['electricity', 'gas', 'water', 'internet', 'other'] as const,\n 'utility.utilityKind',\n ),\n providerName: optionalText(\n input['providerName'],\n 'utility.providerName',\n 256,\n ),\n period: period(input['period']),\n };\n}\n\nfunction recurring(\n value: unknown,\n actualAmount: ExactDecimalString,\n billID: string,\n): ISplitusRecurringOccurrenceV1 {\n const input = record(value, 'recurringOccurrence');\n const expectedAmount =\n input['expectedAmount'] === undefined\n ? undefined\n : positiveAmount(\n input['expectedAmount'],\n 'recurringOccurrence.expectedAmount',\n );\n const standingChargeAmount =\n input['standingChargeAmount'] === undefined\n ? undefined\n : positiveAmount(\n input['standingChargeAmount'],\n 'recurringOccurrence.standingChargeAmount',\n );\n const expectedComparison = enumValue(\n input['expectedComparison'],\n ['not_available', 'matches', 'increased', 'decreased'] as const,\n 'recurringOccurrence.expectedComparison',\n );\n if (\n (expectedAmount === undefined) !==\n (expectedComparison === 'not_available')\n ) {\n throw new TypeError(\n 'comparison must be not_available exactly when expectedAmount is absent',\n );\n }\n if (expectedAmount !== undefined) {\n const expectedComparisonForAmounts = compareAmounts(\n actualAmount,\n expectedAmount,\n );\n if (expectedComparison !== expectedComparisonForAmounts) {\n throw new TypeError('comparison does not match expected and actual amounts');\n }\n }\n if (\n standingChargeAmount !== undefined &&\n amountToMinorUnits(standingChargeAmount) > amountToMinorUnits(actualAmount)\n ) {\n throw new RangeError('standing charge cannot exceed actualAmount');\n }\n return {\n happeningID: storageID(\n input['happeningID'],\n 'recurringOccurrence.happeningID',\n ),\n occurrenceID: storageID(\n input['occurrenceID'],\n 'recurringOccurrence.occurrenceID',\n ),\n expectedAmount,\n standingChargeAmount,\n expectedComparison,\n previousComparable:\n input['previousComparable'] === undefined\n ? undefined\n : previousComparable(\n input['previousComparable'],\n actualAmount,\n billID,\n ),\n };\n}\n\nfunction previousComparable(\n value: unknown,\n actualAmount: ExactDecimalString,\n billID: string,\n): ISplitusPreviousComparableBillV1 {\n const input = record(value, 'recurringOccurrence.previousComparable');\n const previousBillID = storageID(\n input['billID'],\n 'recurringOccurrence.previousComparable.billID',\n );\n if (previousBillID === billID) {\n throw new TypeError('previous comparable bill must have a different billID');\n }\n const previousActualAmount = positiveAmount(\n input['actualAmount'],\n 'recurringOccurrence.previousComparable.actualAmount',\n );\n const comparison = enumValue(\n input['comparison'],\n ['matches', 'increased', 'decreased'] as const,\n 'recurringOccurrence.previousComparable.comparison',\n );\n const expectedComparison = compareAmounts(\n actualAmount,\n previousActualAmount,\n );\n if (comparison !== expectedComparison) {\n throw new TypeError(\n 'previous comparison does not match current and prior actual amounts',\n );\n }\n return {\n billID: previousBillID,\n actualAmount: previousActualAmount,\n comparison,\n };\n}\n\nfunction compareAmounts(\n current: ExactDecimalString,\n baseline: ExactDecimalString,\n): Exclude<SplitusExpectedActualComparison, 'not_available'> {\n const currentMinor = amountToMinorUnits(current);\n const baselineMinor = amountToMinorUnits(baseline);\n return currentMinor === baselineMinor\n ? 'matches'\n : currentMinor > baselineMinor\n ? 'increased'\n : 'decreased';\n}\n\nfunction period(value: unknown): ISplitusBillingPeriodV1 {\n const input = record(value, 'period');\n const startDate = date(input['startDate'], 'period.startDate');\n const endDate = date(input['endDate'], 'period.endDate');\n if (endDate < startDate) {\n throw new RangeError('period.endDate must not precede period.startDate');\n }\n return { startDate, endDate };\n}\n\nfunction date(value: unknown, name: string): string {\n if (typeof value !== 'string') {\n throw new TypeError(`${name} must be an ISO calendar date`);\n }\n const match = datePattern.exec(value);\n if (match === null) {\n throw new TypeError(`${name} must be an ISO calendar date`);\n }\n const parsed = new Date(`${value}T00:00:00.000Z`);\n if (Number.isNaN(parsed.valueOf()) || parsed.toISOString().slice(0, 10) !== value) {\n throw new TypeError(`${name} must be a real ISO calendar date`);\n }\n return value;\n}\n\nfunction currency(value: unknown): SplitusCurrencyCode {\n return enumValue(value, ['EUR', 'GBP', 'USD'] as const, 'currency');\n}\n\nfunction storageID(value: unknown, name: string): string {\n if (\n typeof value !== 'string' ||\n value.length === 0 ||\n value.trim() !== value ||\n new TextEncoder().encode(value).length > 512 ||\n value.includes('/') ||\n hasControlCharacters(value) ||\n value === '.' ||\n value === '..' ||\n (/^__/.test(value) && /__$/.test(value))\n ) {\n throw new TypeError(`${name} is not a safe identifier`);\n }\n return value;\n}\n\nfunction optionalText(\n value: unknown,\n name: string,\n maxBytes: number,\n): string | undefined {\n if (value === undefined) {\n return undefined;\n }\n if (\n typeof value !== 'string' ||\n value.length === 0 ||\n value.trim() !== value ||\n new TextEncoder().encode(value).length > maxBytes ||\n hasControlCharacters(value)\n ) {\n throw new TypeError(`${name} is empty, padded, too long, or contains controls`);\n }\n return value;\n}\n\nfunction hasControlCharacters(value: string): boolean {\n for (const character of value) {\n const code = character.charCodeAt(0);\n if (code < 0x20 || code === 0x7f) {\n return true;\n }\n }\n return false;\n}\n\nfunction record(value: unknown, name: string): Record<string, unknown> {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw new TypeError(`${name} must be an object`);\n }\n return value as Record<string, unknown>;\n}\n\nfunction enumValue<const T extends readonly string[]>(\n value: unknown,\n allowed: T,\n name: string,\n): T[number] {\n if (typeof value !== 'string' || !allowed.includes(value)) {\n throw new TypeError(`${name} has an unsupported value`);\n }\n return value as T[number];\n}\n","import { InjectionToken } from '@angular/core';\nimport { Observable } from 'rxjs';\nimport {\n ICreateSplitRequest,\n ICreateSplitResponse,\n ICreateSplitusBillV1Request,\n ICreateSplitusBillV1Response,\n IGetSplitusBillV1Request,\n IGetSplitusBillV1Response,\n IListSplitusBillsV1Request,\n IListSplitusBillsV1Response,\n ISplit,\n ISplitListItem,\n} from './dto';\n\n/** @deprecated Use `ISplitusBillServiceV1`. */\nexport interface ISplitusService {\n /** REAL: POST /api4splitus/create-split. Payer is the authenticated user. */\n createSplit(request: ICreateSplitRequest): Observable<ICreateSplitResponse>;\n /** REAL: GET /api4splitus/split?spaceID=&id= */\n getSplit(spaceID: string, id: string): Observable<ISplit>;\n /** REAL: GET /api4splitus/splits?spaceID= */\n getSplits(spaceID: string): Observable<ISplitListItem[]>;\n}\n\n/** @deprecated Use `SPLITUS_BILL_SERVICE_V1`. */\nexport const SPLITUS_SERVICE = new InjectionToken<ISplitusService>('SplitusService');\n\nexport interface ISplitusBillServiceV1 {\n createBill(\n request: ICreateSplitusBillV1Request,\n ): Observable<ICreateSplitusBillV1Response>;\n getBill(\n request: IGetSplitusBillV1Request,\n ): Observable<IGetSplitusBillV1Response>;\n listBills(\n request: IListSplitusBillsV1Request,\n ): Observable<IListSplitusBillsV1Response>;\n}\n\nexport const SPLITUS_BILL_SERVICE_V1 =\n new InjectionToken<ISplitusBillServiceV1>('SplitusBillServiceV1');\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;AAAA;AACO,MAAM,6BAA6B,GAAG;AAEtC,MAAM,6BAA6B,GAAG;AACtC,MAAM,+BAA+B,GAAG;AACxC,MAAM,4BAA4B,GAAG;AACrC,MAAM,mCAAmC,GAAG;AAsPnD,MAAM,qBAAqB,GAAG,oBAA0B;AACxD,MAAM,mBAAmB,GAAG,+BAA+B;AAC3D,MAAM,WAAW,GAAG,oCAAoC;AAElD,SAAU,uBAAuB,CAAC,KAAc,EAAA;AACpD,IAAA,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;AACjE,QAAA,MAAM,IAAI,SAAS,CACjB,4EAA4E,CAC7E;IACH;AACA,IAAA,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;AACjD,IAAA,IAAI,UAAU,GAAG,qBAAqB,EAAE;AACtC,QAAA,MAAM,IAAI,UAAU,CAAC,2CAA2C,CAAC;IACnE;AACA,IAAA,OAAO,KAAK;AACd;AAEM,SAAU,+BAA+B,CAC7C,KAAc,EAAA;IAEd,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE,qBAAqB,CAAC;AAClD,IAAA,IAAI,KAAK,CAAC,iBAAiB,CAAC,KAAK,6BAA6B,EAAE;AAC9D,QAAA,MAAM,IAAI,SAAS,CAAC,2CAA2C,CAAC;IAClE;AACA,IAAA,MAAM,QAAQ,GAAG,SAAS,CACxB,KAAK,CAAC,UAAU,CAAC,EACjB,CAAC,SAAS,EAAE,SAAS,CAAU,EAC/B,UAAU,CACX;IACD,MAAM,YAAY,GAAG,cAAc,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,cAAc,CAAC;IAC1E,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC;IACtD,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACnD,MAAM,cAAc,GAAG,SAAS,CAC9B,KAAK,CAAC,gBAAgB,CAAC,EACvB,gBAAgB,CACjB;AACD,IAAA,MAAM,OAAO,GAAgC;AAC3C,QAAA,eAAe,EAAE,6BAA6B;QAC9C,OAAO;QACP,MAAM;QACN,cAAc;QACd,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC;QACjD,QAAQ;AACR,QAAA,QAAQ,EAAE,QAAQ,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QACrC,YAAY;QACZ,eAAe,EAAE,WAAW,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;QACzE,eAAe,EAAE,WAAW,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;QACzE,OAAO,EACL,KAAK,CAAC,SAAS,CAAC,KAAK,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;AACxE,QAAA,mBAAmB,EACjB,KAAK,CAAC,qBAAqB,CAAC,KAAK;AAC/B,cAAE;cACA,SAAS,CAAC,KAAK,CAAC,qBAAqB,CAAC,EAAE,YAAY,EAAE,MAAM,CAAC;KACpE;AACD,IAAA,IAAI,CAAC,QAAQ,KAAK,SAAS,OAAO,OAAO,CAAC,OAAO,KAAK,SAAS,CAAC,EAAE;AAChE,QAAA,MAAM,IAAI,SAAS,CAAC,qDAAqD,CAAC;IAC5E;IACA,wBAAwB,CAAC,OAAO,CAAC;AACjC,IAAA,OAAO,OAAO;AAChB;AAEA;;;;AAIG;AACG,SAAU,iCAAiC,CAC/C,OAAoC,EACpC,mBAA2B,EAAA;IAE3B,MAAM,aAAa,GAAG,SAAS,CAC7B,mBAAmB,EACnB,qBAAqB,CACtB;AACD,IAAA,IAAI,OAAO,CAAC,cAAc,KAAK,aAAa,EAAE;AAC5C,QAAA,MAAM,IAAI,SAAS,CACjB,8DAA8D,CAC/D;IACH;AACF;AAEM,SAAU,8BAA8B,CAC5C,KAAc,EAAA;IAEd,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE,oBAAoB,CAAC;AACjD,IAAA,IAAI,KAAK,CAAC,iBAAiB,CAAC,KAAK,6BAA6B,EAAE;AAC9D,QAAA,MAAM,IAAI,SAAS,CAAC,2CAA2C,CAAC;IAClE;AACA,IAAA,MAAM,QAAQ,GAAG,KAAK,CAAC,UAAU,CAAC;IAClC,IACE,OAAO,QAAQ,KAAK,QAAQ;AAC5B,QAAA,CAAC,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC;AAC/B,QAAA,QAAQ,GAAG,CAAC;QACZ,QAAQ,GAAG,+BAA+B,EAC1C;AACA,QAAA,MAAM,IAAI,UAAU,CAClB,yCAAyC,+BAA+B,CAAA,CAAE,CAC3E;IACH;IACA,OAAO;AACL,QAAA,eAAe,EAAE,6BAA6B;QAC9C,OAAO,EAAE,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC;QAC/C,QAAQ;QACR,MAAM,EAAE,YAAY,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC;AACrD,QAAA,WAAW,EACT,KAAK,CAAC,aAAa,CAAC,KAAK;AACvB,cAAE;cACA,SAAS,CACP,KAAK,CAAC,aAAa,CAAC,EACpB,CAAC,aAAa,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,CAAU,EAC7D,aAAa,CACd;QACP,MAAM,EACJ,KAAK,CAAC,QAAQ,CAAC,KAAK,SAAS,GAAG,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;KACtE;AACH;AAEM,SAAU,4BAA4B,CAC1C,KAAc,EAAA;IAEd,MAAM,KAAK,GAAG,eAAe,CAAC,KAAK,EAAE,kBAAkB,CAAC;IACxD,OAAO;AACL,QAAA,eAAe,EAAE,6BAA6B;QAC9C,OAAO,EAAE,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC;QAC/C,MAAM,EAAE,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC;KAC7C;AACH;AAEM,SAAU,gCAAgC,CAC9C,KAAc,EAAA;IAEd,MAAM,KAAK,GAAG,eAAe,CAAC,KAAK,EAAE,sBAAsB,CAAC;IAC5D,OAAO;AACL,QAAA,eAAe,EAAE,6BAA6B;AAC9C,QAAA,IAAI,EAAE,kBAAkB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;KACxC;AACH;AAEM,SAAU,6BAA6B,CAC3C,KAAc,EAAA;IAEd,MAAM,KAAK,GAAG,eAAe,CAAC,KAAK,EAAE,mBAAmB,CAAC;IACzD,OAAO;AACL,QAAA,eAAe,EAAE,6BAA6B;AAC9C,QAAA,IAAI,EAAE,kBAAkB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;KACxC;AACH;AAEM,SAAU,+BAA+B,CAC7C,KAAc,EACd,iBAA0B,EAAA;IAE1B,MAAM,KAAK,GAAG,eAAe,CAAC,KAAK,EAAE,qBAAqB,CAAC;IAC3D,MAAM,QAAQ,GAAG,eAAe,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IACnD,IAAI,iBAAiB,KAAK,SAAS,IAAI,QAAQ,KAAK,iBAAiB,EAAE;AACrE,QAAA,MAAM,IAAI,UAAU,CAAC,uDAAuD,CAAC;IAC/E;IACA,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,QAAQ,EAAE;AACtE,QAAA,MAAM,IAAI,UAAU,CAAC,4CAA4C,CAAC;IACpE;IACA,OAAO;AACL,QAAA,eAAe,EAAE,6BAA6B;QAC9C,QAAQ;AACR,QAAA,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,mBAAmB,CAAC,IAAI,CAAC,CAAC;QAC9D,UAAU,EAAE,YAAY,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,YAAY,EAAE,IAAI,CAAC;KAClE;AACH;AAEM,SAAU,kBAAkB,CAAC,KAAc,EAAA;IAC/C,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC;AACnC,IAAA,MAAM,OAAO,GAAG,+BAA+B,CAAC,KAAK,CAAC;IACtD,MAAM,aAAa,GAAG,qBAAqB,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC;IAC1E,MAAM,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC;IAC5D,MAAM,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC;AAC5D,IAAA,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE;AACjD,QAAA,MAAM,IAAI,UAAU,CAAC,sCAAsC,CAAC;IAC9D;IACA,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,aAAa,CAAC;AAC7D,IAAA,MAAM,WAAW,GACf,KAAK,CAAC,QAAQ,CAAC,KAAK;AAClB,UAAE;UACA,YAAY,CACV,KAAK,CAAC,QAAQ,CAAC,EACf,OAAO,CAAC,OAAO,EACf,OAAO,CAAC,MAAM,EACd,OAAO,CAAC,QAAQ,CACjB;IACP,IAAI,WAAW,KAAK,SAAS,IAAI,YAAY,CAAC,MAAM,KAAK,SAAS,EAAE;AAClE,QAAA,MAAM,IAAI,SAAS,CAAC,wCAAwC,CAAC;IAC/D;AACA,IAAA,IAAI,WAAW,KAAK,SAAS,EAAE;AAC7B,QAAA,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO;AACpC,QAAA,IAAI,OAAO,KAAK,SAAS,EAAE;AACzB,YAAA,MAAM,IAAI,SAAS,CAAC,mDAAmD,CAAC;QAC1E;AACA,QAAA,4BAA4B,CAAC,OAAO,EAAE,WAAW,CAAC;IACpD;IACA,OAAO;AACL,QAAA,GAAG,OAAO;AACV,QAAA,QAAQ,EAAE,aAAa;AACvB,QAAA,OAAO,EAAE,YAAY;AACrB,QAAA,MAAM,EAAE,WAAW;QACnB,SAAS;QACT,SAAS;KACV;AACH;AAEA,SAAS,mBAAmB,CAAC,KAAc,EAAA;IACzC,MAAM,KAAK,GAAG,eAAe,CAAC,KAAK,EAAE,gBAAgB,CAAC;AACtD,IAAA,MAAM,QAAQ,GAAG,SAAS,CACxB,KAAK,CAAC,UAAU,CAAC,EACjB,CAAC,SAAS,EAAE,SAAS,CAAU,EAC/B,UAAU,CACX;AACD,IAAA,MAAM,WAAW,GACf,KAAK,CAAC,aAAa,CAAC,KAAK;AACvB,UAAE;UACA,SAAS,CACP,KAAK,CAAC,aAAa,CAAC,EACpB,CAAC,aAAa,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,CAAU,EAC7D,aAAa,CACd;IACP,MAAM,WAAW,GACf,KAAK,CAAC,QAAQ,CAAC,KAAK,SAAS,GAAG,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;AACrE,IAAA,IACE,CAAC,QAAQ,KAAK,SAAS;SACtB,WAAW,KAAK,SAAS,IAAI,WAAW,KAAK,SAAS,CAAC,EACxD;AACA,QAAA,MAAM,IAAI,SAAS,CAAC,mDAAmD,CAAC;IAC1E;IACA,MAAM,aAAa,GAAG,SAAS,CAC7B,KAAK,CAAC,eAAe,CAAC,EACtB,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,CAAU,EACvD,eAAe,CAChB;AACD,IAAA,MAAM,sBAAsB,GAC1B,KAAK,CAAC,wBAAwB,CAAC,KAAK;AAClC,UAAE;UACA,gBAAgB,CACd,KAAK,CAAC,wBAAwB,CAAC,EAC/B,wBAAwB,CACzB;IACP,IACE,sBAAsB,KAAK,SAAS;QACpC,aAAa,KAAK,SAAS,EAC3B;AACA,QAAA,MAAM,IAAI,SAAS,CAAC,mDAAmD,CAAC;IAC1E;IACA,OAAO;AACL,QAAA,eAAe,EAAE,6BAA6B;QAC9C,OAAO,EAAE,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC;QAC/C,MAAM,EAAE,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC;QAC5C,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC;QACjD,QAAQ;QACR,WAAW;AACX,QAAA,MAAM,EAAE,WAAW;AACnB,QAAA,QAAQ,EAAE,QAAQ,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QACrC,YAAY,EAAE,cAAc,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,cAAc,CAAC;QACnE,aAAa,EAAE,iBAAiB,CAAC,KAAK,CAAC,eAAe,CAAC,EAAE,eAAe,CAAC;QACzE,aAAa,EAAE,iBAAiB,CAAC,KAAK,CAAC,eAAe,CAAC,EAAE,eAAe,CAAC;QACzE,aAAa;QACb,sBAAsB;QACtB,SAAS,EAAE,SAAS,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC;KACtD;AACH;AAEA,SAAS,OAAO,CAAC,KAAc,EAAE,YAAoB,EAAA;IACnD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE,SAAS,CAAC;IACtC,MAAM,MAAM,GAAG,SAAS,CACtB,KAAK,CAAC,QAAQ,CAAC,EACf,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,CAAU,EACvD,gBAAgB,CACjB;IACD,MAAM,YAAY,GAAG,SAAS,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,sBAAsB,CAAC;IAC7E,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE,qBAAqB,CAAC;AACvE,IAAA,MAAM,YAAY,GAChB,KAAK,CAAC,SAAS,CAAC,KAAK;AACnB,UAAE;AACF,UAAE,cAAc,CACZ,KAAK,CAAC,SAAS,CAAC,EAChB,YAAY,EACZ,YAAY,EACZ,WAAW,CACZ;AACP,IAAA,MAAM,aAAa,GACjB,KAAK,CAAC,eAAe,CAAC,KAAK;AACzB,UAAE;AACF,UAAE,SAAS,CACP,KAAK,CAAC,eAAe,CAAC,EACtB;YACE,uBAAuB;YACvB,iBAAiB;YACjB,mBAAmB;YACnB,0BAA0B;YAC1B,0BAA0B;SAClB,EACV,uBAAuB,CACxB;AACP,IAAA,IAAI,CAAC,MAAM,KAAK,SAAS,OAAO,YAAY,KAAK,SAAS,CAAC,EAAE;AAC3D,QAAA,MAAM,IAAI,SAAS,CAAC,qDAAqD,CAAC;IAC5E;AACA,IAAA,IAAI,CAAC,MAAM,KAAK,WAAW,OAAO,aAAa,KAAK,SAAS,CAAC,EAAE;AAC9D,QAAA,MAAM,IAAI,SAAS,CAAC,oDAAoD,CAAC;IAC3E;IACA,OAAO;QACL,MAAM;QACN,YAAY;QACZ,WAAW;AACX,QAAA,OAAO,EAAE,YAAY;QACrB,aAAa;KACd;AACH;AAEA,SAAS,cAAc,CACrB,KAAc,EACd,YAAoB,EACpB,YAAoB,EACpB,WAAmB,EAAA;IAEnB,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE,iBAAiB,CAAC;IAC9C,MAAM,aAAa,GAAG,qBAAqB,CACzC,KAAK,CAAC,UAAU,CAAC,EACjB,0BAA0B,CAC3B;IACD,MAAM,mBAAmB,GAAG,SAAS,CACnC,KAAK,CAAC,cAAc,CAAC,EACrB,8BAA8B,CAC/B;IACD,MAAM,kBAAkB,GAAG,MAAM,CAC/B,KAAK,CAAC,aAAa,CAAC,EACpB,6BAA6B,CAC9B;IACD,IACE,aAAa,KAAK,YAAY;AAC9B,QAAA,mBAAmB,KAAK,YAAY;QACpC,kBAAkB,KAAK,WAAW,EAClC;AACA,QAAA,MAAM,IAAI,SAAS,CAAC,2DAA2D,CAAC;IAClF;IACA,IACE,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;QACxC,KAAK,CAAC,iBAAiB,CAAC,CAAC,MAAM,GAAG,4BAA4B,EAC9D;AACA,QAAA,MAAM,IAAI,UAAU,CAAC,+CAA+C,CAAC;IACvE;AACA,IAAA,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU;AACjC,IAAA,MAAM,aAAa,GAAG,IAAI,GAAG,EAAU;AACvC,IAAA,MAAM,eAAe,GAAG,KAAK,CAAC,iBAAiB,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,KAAI;QACpE,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,EAAE,CAAA,gCAAA,EAAmC,KAAK,CAAA,CAAA,CAAG,CAAC;AACvE,QAAA,MAAM,MAAM,GAAG,SAAS,CACtB,IAAI,CAAC,QAAQ,CAAC,EACd,CAAA,gCAAA,EAAmC,KAAK,CAAA,QAAA,CAAU,CACnD;AACD,QAAA,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE;AACvB,YAAA,MAAM,IAAI,SAAS,CAAC,4CAA4C,CAAC;QACnE;AACA,QAAA,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC;AACnB,QAAA,MAAM,GAAG,GAAG,eAAe,CACzB,IAAI,CAAC,eAAe,CAAC,EACrB,mCAAmC,KAAK,CAAA,eAAA,CAAiB,EACzD,mCAAmC,CACpC;AACD,QAAA,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE;AACpB,YAAA,IAAI,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;AACzB,gBAAA,MAAM,IAAI,SAAS,CAAC,0CAA0C,CAAC;YACjE;AACA,YAAA,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB;AACA,QAAA,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,GAAG,EAAE;AACvC,IAAA,CAAC,CAAC;IACF,OAAO;QACL,SAAS,EAAE,SAAS,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,2BAA2B,CAAC;AACrE,QAAA,YAAY,EAAE,mBAAmB;AACjC,QAAA,WAAW,EAAE,kBAAkB;AAC/B,QAAA,QAAQ,EAAE,aAAa;QACvB,eAAe;KAChB;AACH;AAEA,SAAS,YAAY,CACnB,KAAc,EACd,OAAe,EACf,MAAc,EACd,YAAoB,EAAA;IAEpB,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC;IACrC,IACE,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QACpC,KAAK,CAAC,aAAa,CAAC,CAAC,MAAM,GAAG,4BAA4B,EAC1D;AACA,QAAA,MAAM,IAAI,UAAU,CAAC,kCAAkC,CAAC;IAC1D;AACA,IAAA,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU;AACjC,IAAA,MAAM,WAAW,GAAG,KAAK,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,KAAI;QAC3D,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,EAAE,CAAA,mBAAA,EAAsB,KAAK,CAAA,CAAA,CAAG,CAAC;AAC/D,QAAA,MAAM,MAAM,GAAG,SAAS,CACtB,UAAU,CAAC,QAAQ,CAAC,EACpB,CAAA,mBAAA,EAAsB,KAAK,CAAA,QAAA,CAAU,CACtC;AACD,QAAA,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE;AACvB,YAAA,MAAM,IAAI,SAAS,CAAC,0CAA0C,CAAC;QACjE;AACA,QAAA,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC;QACnB,MAAM,kBAAkB,GAAG,QAAQ,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;AAC3D,QAAA,IAAI,kBAAkB,KAAK,YAAY,EAAE;AACvC,YAAA,MAAM,IAAI,SAAS,CAAC,kDAAkD,CAAC;QACzE;QACA,OAAO;YACL,MAAM;AACN,YAAA,aAAa,EAAE,eAAe,CAC5B,UAAU,CAAC,eAAe,CAAC,EAC3B,CAAA,mBAAA,EAAsB,KAAK,CAAA,eAAA,CAAiB,EAC5C,mCAAmC,CACpC;YACD,eAAe,EAAE,SAAS,CACxB,UAAU,CAAC,iBAAiB,CAAC,EAC7B,CAAA,mBAAA,EAAsB,KAAK,CAAA,iBAAA,CAAmB,CAC/C;YACD,iBAAiB,EAAE,SAAS,CAC1B,UAAU,CAAC,mBAAmB,CAAC,EAC/B,CAAA,mBAAA,EAAsB,KAAK,CAAA,mBAAA,CAAqB,CACjD;AACD,YAAA,QAAQ,EAAE,kBAAkB;YAC5B,eAAe,EAAE,cAAc,CAC7B,UAAU,CAAC,iBAAiB,CAAC,EAC7B,CAAA,mBAAA,EAAsB,KAAK,CAAA,iBAAA,CAAmB,CAC/C;YACD,iBAAiB,EAAE,iBAAiB,CAClC,UAAU,CAAC,mBAAmB,CAAC,EAC/B,CAAA,mBAAA,EAAsB,KAAK,CAAA,mBAAA,CAAqB,CACjD;YACD,YAAY,EAAE,iBAAiB,CAC7B,UAAU,CAAC,cAAc,CAAC,EAC1B,CAAA,mBAAA,EAAsB,KAAK,CAAA,cAAA,CAAgB,CAC5C;YACD,YAAY,EAAE,iBAAiB,CAC7B,UAAU,CAAC,cAAc,CAAC,EAC1B,CAAA,mBAAA,EAAsB,KAAK,CAAA,cAAA,CAAgB,CAC5C;YACD,MAAM,EAAE,gBAAgB,CACtB,UAAU,CAAC,QAAQ,CAAC,EACpB,CAAA,mBAAA,EAAsB,KAAK,CAAA,QAAA,CAAU,CACtC;AACD,YAAA,gBAAgB,EAAE,gBAAgB,CAChC,UAAU,CAAC,kBAAkB,CAAC,EAC9B,OAAO,EACP,MAAM,EACN,MAAM,CACP;SACF;AACH,IAAA,CAAC,CAAC;IACF,OAAO;QACL,MAAM,EAAE,gBAAgB,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,eAAe,CAAC;QAC1D,WAAW;QACX,gBAAgB,EAAE,gBAAgB,CAChC,KAAK,CAAC,kBAAkB,CAAC,EACzB,OAAO,EACP,MAAM,CACP;KACF;AACH;AAEA,SAAS,4BAA4B,CACnC,OAAqC,EACrC,MAA8B,EAAA;AAE9B,IAAA,IAAI,OAAO,CAAC,eAAe,CAAC,MAAM,KAAK,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE;AAChE,QAAA,MAAM,IAAI,SAAS,CACjB,qEAAqE,CACtE;IACH;AACA,IAAA,MAAM,YAAY,GAAG,IAAI,GAAG,CAC1B,OAAO,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK;AACpC,QAAA,IAAI,CAAC,MAAM;AACX,QAAA,IAAI,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC;AAC5B,KAAA,CAAC,CACH;AACD,IAAA,KAAK,MAAM,UAAU,IAAI,MAAM,CAAC,WAAW,EAAE;QAC3C,MAAM,UAAU,GAAG,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC;QACtD,IACE,UAAU,KAAK,SAAS;AACxB,YAAA,UAAU,CAAC,IAAI,KAAK,UAAU,CAAC,aAAa,CAAC,MAAM;AACnD,YAAA,UAAU,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,EAC1D;AACA,YAAA,MAAM,IAAI,SAAS,CACjB,qEAAqE,CACtE;QACH;IACF;AACF;AAEA,SAAS,gBAAgB,CACvB,KAAc,EACd,OAAe,EACf,MAAc,EACd,cAAuB,EAAA;IAEvB,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE,kBAAkB,CAAC;AAC/C,IAAA,MAAM,MAAM,GACV,KAAK,CAAC,QAAQ,CAAC,KAAK;AAClB,UAAE;UACA,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,yBAAyB,CAAC;AAC3D,IAAA,IACE,KAAK,CAAC,OAAO,CAAC,KAAK,2BAA2B;AAC9C,QAAA,KAAK,CAAC,iBAAiB,CAAC,KAAK,SAAS;AACtC,QAAA,KAAK,CAAC,SAAS,CAAC,KAAK,OAAO;AAC5B,QAAA,KAAK,CAAC,gBAAgB,CAAC,KAAK,MAAM;QAClC,MAAM,KAAK,cAAc,EACzB;AACA,QAAA,MAAM,IAAI,SAAS,CAAC,0DAA0D,CAAC;IACjF;IACA,OAAO;AACL,QAAA,KAAK,EAAE,2BAA2B;QAClC,OAAO;AACP,QAAA,eAAe,EAAE,SAAS;AAC1B,QAAA,cAAc,EAAE,MAAM;QACtB,MAAM;KACP;AACH;AAEA,SAAS,eAAe,CAAC,KAAc,EAAE,IAAY,EAAA;IACnD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC;AACjC,IAAA,IAAI,KAAK,CAAC,iBAAiB,CAAC,KAAK,6BAA6B,EAAE;AAC9D,QAAA,MAAM,IAAI,SAAS,CAAC,2CAA2C,CAAC;IAClE;AACA,IAAA,OAAO,KAAK;AACd;AAEA,SAAS,eAAe,CAAC,KAAc,EAAA;IACrC,IACE,OAAO,KAAK,KAAK,QAAQ;AACzB,QAAA,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC;AAC5B,QAAA,KAAK,GAAG,CAAC;QACT,KAAK,GAAG,+BAA+B,EACvC;AACA,QAAA,MAAM,IAAI,UAAU,CAClB,yCAAyC,+BAA+B,CAAA,CAAE,CAC3E;IACH;AACA,IAAA,OAAO,KAAK;AACd;AAEA,SAAS,gBAAgB,CACvB,KAAc,EACd,IAAY,EAAA;AAEZ,IAAA,OAAO,SAAS,CACd,KAAK,EACL,CAAC,WAAW,EAAE,cAAc,EAAE,SAAS,CAAU,EACjD,IAAI,CACL;AACH;AAEA,SAAS,eAAe,CAAC,KAAc,EAAE,IAAY,EAAE,OAAe,EAAA;IACpE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,OAAO,EAAE;QACvE,MAAM,IAAI,UAAU,CAAC,CAAA,EAAG,IAAI,CAAA,mBAAA,EAAsB,OAAO,CAAA,YAAA,CAAc,CAAC;IAC1E;AACA,IAAA,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU;IAC9B,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,KAAI;AAC/B,QAAA,MAAM,EAAE,GAAG,SAAS,CAAC,IAAI,EAAE,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,KAAK,CAAA,CAAA,CAAG,CAAC;AAC/C,QAAA,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;AAChB,YAAA,MAAM,IAAI,SAAS,CAAC,GAAG,IAAI,CAAA,gCAAA,CAAkC,CAAC;QAChE;AACA,QAAA,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;AACZ,QAAA,OAAO,EAAE;AACX,IAAA,CAAC,CAAC;AACJ;AAEA,SAAS,MAAM,CAAC,KAAc,EAAE,IAAY,EAAA;AAC1C,IAAA,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;AAC9D,QAAA,MAAM,IAAI,SAAS,CAAC,GAAG,IAAI,CAAA,mCAAA,CAAqC,CAAC;IACnE;AACA,IAAA,OAAO,KAAK;AACd;AAEA,SAAS,qBAAqB,CAAC,KAAc,EAAE,IAAY,EAAA;AACzD,IAAA,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;AAC7D,QAAA,MAAM,IAAI,SAAS,CAAC,GAAG,IAAI,CAAA,4CAAA,CAA8C,CAAC;IAC5E;AACA,IAAA,IAAI,MAAM,CAAC,KAAK,CAAC,GAAG,qBAA2B,EAAE;AAC/C,QAAA,MAAM,IAAI,UAAU,CAAC,GAAG,IAAI,CAAA,8BAAA,CAAgC,CAAC;IAC/D;AACA,IAAA,OAAO,KAAK;AACd;AAEA,SAAS,SAAS,CAAC,KAAc,EAAE,IAAY,EAAA;IAC7C,IACE,OAAO,KAAK,KAAK,QAAQ;AACzB,QAAA,CAAC,sEAAsE,CAAC,IAAI,CAC1E,KAAK,CACN;QACD,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAC/B;AACA,QAAA,MAAM,IAAI,SAAS,CAAC,GAAG,IAAI,CAAA,8BAAA,CAAgC,CAAC;IAC9D;AACA,IAAA,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC;AAC9B,IAAA,OAAO,KAAK;AACd;AAEA,SAAS,iBAAiB,CACxB,KAAc,EACd,IAAY,EAAA;AAEZ,IAAA,IAAI;AACF,QAAA,OAAO,uBAAuB,CAAC,KAAK,CAAC;IACvC;IAAE,OAAO,KAAK,EAAE;AACd,QAAA,IAAI,KAAK,YAAY,UAAU,EAAE;YAC/B,MAAM,IAAI,UAAU,CAAC,CAAA,EAAG,IAAI,CAAA,EAAA,EAAK,KAAK,CAAC,OAAO,CAAA,CAAE,CAAC;QACnD;AACA,QAAA,IAAI,KAAK,YAAY,KAAK,EAAE;YAC1B,MAAM,IAAI,SAAS,CAAC,CAAA,EAAG,IAAI,CAAA,EAAA,EAAK,KAAK,CAAC,OAAO,CAAA,CAAE,CAAC;QAClD;AACA,QAAA,MAAM,KAAK;IACb;AACF;AAEA,SAAS,wBAAwB,CAAC,OAAoC,EAAA;AACpE,IAAA,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU;IAClC,KAAK,MAAM,UAAU,IAAI;QACvB,GAAG,OAAO,CAAC,eAAe;QAC1B,GAAG,OAAO,CAAC,eAAe;AAC3B,KAAA,EAAE;AACD,QAAA,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC;IACpC;AACA,IAAA,IAAI,QAAQ,CAAC,IAAI,GAAG,CAAC,IAAI,QAAQ,CAAC,IAAI,GAAG,6BAA6B,EAAE;AACtE,QAAA,MAAM,IAAI,UAAU,CAClB,uBAAuB,6BAA6B,CAAA,aAAA,CAAe,CACpE;IACH;IACA,MAAM,MAAM,GAAG,kBAAkB,CAAC,OAAO,CAAC,YAAY,CAAC;IACvD,IAAI,cAAc,CAAC,OAAO,CAAC,eAAe,CAAC,KAAK,MAAM,EAAE;AACtD,QAAA,MAAM,IAAI,UAAU,CAAC,iDAAiD,CAAC;IACzE;IACA,IAAI,cAAc,CAAC,OAAO,CAAC,eAAe,CAAC,KAAK,MAAM,EAAE;AACtD,QAAA,MAAM,IAAI,UAAU,CAAC,iDAAiD,CAAC;IACzE;AACF;AAEA,SAAS,WAAW,CAAC,KAAc,EAAE,IAAY,EAAA;IAC/C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,6BAA6B,EAAE;QAC7F,MAAM,IAAI,UAAU,CAClB,CAAA,EAAG,IAAI,CAAA,mBAAA,EAAsB,6BAA6B,CAAA,YAAA,CAAc,CACzE;IACH;AACA,IAAA,MAAM,aAAa,GAAG,IAAI,GAAG,EAAU;AACvC,IAAA,MAAM,UAAU,GAAG,IAAI,GAAG,EAAU;IACpC,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,KAAI;AAC/B,QAAA,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,EAAE,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,KAAK,CAAA,CAAA,CAAG,CAAC;AAC/C,QAAA,MAAM,YAAY,GAAG,SAAS,CAC5B,KAAK,CAAC,cAAc,CAAC,EACrB,GAAG,IAAI,CAAA,CAAA,EAAI,KAAK,CAAA,cAAA,CAAgB,CACjC;AACD,QAAA,MAAM,SAAS,GAAG,SAAS,CACzB,KAAK,CAAC,WAAW,CAAC,EAClB,GAAG,IAAI,CAAA,CAAA,EAAI,KAAK,CAAA,WAAA,CAAa,CAC9B;AACD,QAAA,IAAI,aAAa,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE;AAChE,YAAA,MAAM,IAAI,SAAS,CAAC,GAAG,IAAI,CAAA,2CAAA,CAA6C,CAAC;QAC3E;AACA,QAAA,aAAa,CAAC,GAAG,CAAC,YAAY,CAAC;AAC/B,QAAA,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC;QACzB,OAAO;YACL,YAAY;YACZ,SAAS;AACT,YAAA,MAAM,EAAE,cAAc,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,KAAK,UAAU,CAAC;SACpE;AACH,IAAA,CAAC,CAAC;AACJ;AAEA,SAAS,cAAc,CAAC,gBAAqD,EAAA;IAC3E,IAAI,KAAK,GAAG,EAAE;AACd,IAAA,KAAK,MAAM,UAAU,IAAI,gBAAgB,EAAE;AACzC,QAAA,KAAK,IAAI,kBAAkB,CAAC,UAAU,CAAC,MAAM,CAAC;AAC9C,QAAA,IAAI,KAAK,GAAG,qBAAqB,EAAE;AACjC,YAAA,MAAM,IAAI,UAAU,CAAC,qDAAqD,CAAC;QAC7E;IACF;AACA,IAAA,OAAO,KAAK;AACd;AAEA,SAAS,kBAAkB,CAAC,KAAyB,EAAA;IACnD,OAAO,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;AACvC;AAEA,SAAS,cAAc,CAAC,KAAc,EAAE,IAAY,EAAA;AAClD,IAAA,MAAM,MAAM,GAAG,uBAAuB,CAAC,KAAK,CAAC;AAC7C,IAAA,IAAI,kBAAkB,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE;AACrC,QAAA,MAAM,IAAI,UAAU,CAAC,GAAG,IAAI,CAAA,iBAAA,CAAmB,CAAC;IAClD;AACA,IAAA,OAAO,MAAM;AACf;AAEA,SAAS,OAAO,CAAC,KAAc,EAAA;IAC7B,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE,SAAS,CAAC;IACtC,OAAO;QACL,WAAW,EAAE,SAAS,CACpB,KAAK,CAAC,aAAa,CAAC,EACpB,CAAC,aAAa,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,CAAU,EAC7D,qBAAqB,CACtB;QACD,YAAY,EAAE,YAAY,CACxB,KAAK,CAAC,cAAc,CAAC,EACrB,sBAAsB,EACtB,GAAG,CACJ;AACD,QAAA,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;KAChC;AACH;AAEA,SAAS,SAAS,CAChB,KAAc,EACd,YAAgC,EAChC,MAAc,EAAA;IAEd,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE,qBAAqB,CAAC;AAClD,IAAA,MAAM,cAAc,GAClB,KAAK,CAAC,gBAAgB,CAAC,KAAK;AAC1B,UAAE;UACA,cAAc,CACZ,KAAK,CAAC,gBAAgB,CAAC,EACvB,oCAAoC,CACrC;AACP,IAAA,MAAM,oBAAoB,GACxB,KAAK,CAAC,sBAAsB,CAAC,KAAK;AAChC,UAAE;UACA,cAAc,CACZ,KAAK,CAAC,sBAAsB,CAAC,EAC7B,0CAA0C,CAC3C;IACP,MAAM,kBAAkB,GAAG,SAAS,CAClC,KAAK,CAAC,oBAAoB,CAAC,EAC3B,CAAC,eAAe,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,CAAU,EAC/D,wCAAwC,CACzC;AACD,IAAA,IACE,CAAC,cAAc,KAAK,SAAS;AAC7B,SAAC,kBAAkB,KAAK,eAAe,CAAC,EACxC;AACA,QAAA,MAAM,IAAI,SAAS,CACjB,wEAAwE,CACzE;IACH;AACA,IAAA,IAAI,cAAc,KAAK,SAAS,EAAE;QAChC,MAAM,4BAA4B,GAAG,cAAc,CACjD,YAAY,EACZ,cAAc,CACf;AACD,QAAA,IAAI,kBAAkB,KAAK,4BAA4B,EAAE;AACvD,YAAA,MAAM,IAAI,SAAS,CAAC,uDAAuD,CAAC;QAC9E;IACF;IACA,IACE,oBAAoB,KAAK,SAAS;QAClC,kBAAkB,CAAC,oBAAoB,CAAC,GAAG,kBAAkB,CAAC,YAAY,CAAC,EAC3E;AACA,QAAA,MAAM,IAAI,UAAU,CAAC,4CAA4C,CAAC;IACpE;IACA,OAAO;QACL,WAAW,EAAE,SAAS,CACpB,KAAK,CAAC,aAAa,CAAC,EACpB,iCAAiC,CAClC;QACD,YAAY,EAAE,SAAS,CACrB,KAAK,CAAC,cAAc,CAAC,EACrB,kCAAkC,CACnC;QACD,cAAc;QACd,oBAAoB;QACpB,kBAAkB;AAClB,QAAA,kBAAkB,EAChB,KAAK,CAAC,oBAAoB,CAAC,KAAK;AAC9B,cAAE;cACA,kBAAkB,CAChB,KAAK,CAAC,oBAAoB,CAAC,EAC3B,YAAY,EACZ,MAAM,CACP;KACR;AACH;AAEA,SAAS,kBAAkB,CACzB,KAAc,EACd,YAAgC,EAChC,MAAc,EAAA;IAEd,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE,wCAAwC,CAAC;IACrE,MAAM,cAAc,GAAG,SAAS,CAC9B,KAAK,CAAC,QAAQ,CAAC,EACf,+CAA+C,CAChD;AACD,IAAA,IAAI,cAAc,KAAK,MAAM,EAAE;AAC7B,QAAA,MAAM,IAAI,SAAS,CAAC,uDAAuD,CAAC;IAC9E;IACA,MAAM,oBAAoB,GAAG,cAAc,CACzC,KAAK,CAAC,cAAc,CAAC,EACrB,qDAAqD,CACtD;AACD,IAAA,MAAM,UAAU,GAAG,SAAS,CAC1B,KAAK,CAAC,YAAY,CAAC,EACnB,CAAC,SAAS,EAAE,WAAW,EAAE,WAAW,CAAU,EAC9C,mDAAmD,CACpD;IACD,MAAM,kBAAkB,GAAG,cAAc,CACvC,YAAY,EACZ,oBAAoB,CACrB;AACD,IAAA,IAAI,UAAU,KAAK,kBAAkB,EAAE;AACrC,QAAA,MAAM,IAAI,SAAS,CACjB,qEAAqE,CACtE;IACH;IACA,OAAO;AACL,QAAA,MAAM,EAAE,cAAc;AACtB,QAAA,YAAY,EAAE,oBAAoB;QAClC,UAAU;KACX;AACH;AAEA,SAAS,cAAc,CACrB,OAA2B,EAC3B,QAA4B,EAAA;AAE5B,IAAA,MAAM,YAAY,GAAG,kBAAkB,CAAC,OAAO,CAAC;AAChD,IAAA,MAAM,aAAa,GAAG,kBAAkB,CAAC,QAAQ,CAAC;IAClD,OAAO,YAAY,KAAK;AACtB,UAAE;UACA,YAAY,GAAG;AACf,cAAE;cACA,WAAW;AACnB;AAEA,SAAS,MAAM,CAAC,KAAc,EAAA;IAC5B,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC;IACrC,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,kBAAkB,CAAC;IAC9D,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,gBAAgB,CAAC;AACxD,IAAA,IAAI,OAAO,GAAG,SAAS,EAAE;AACvB,QAAA,MAAM,IAAI,UAAU,CAAC,kDAAkD,CAAC;IAC1E;AACA,IAAA,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE;AAC/B;AAEA,SAAS,IAAI,CAAC,KAAc,EAAE,IAAY,EAAA;AACxC,IAAA,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;AAC7B,QAAA,MAAM,IAAI,SAAS,CAAC,GAAG,IAAI,CAAA,6BAAA,CAA+B,CAAC;IAC7D;IACA,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC;AACrC,IAAA,IAAI,KAAK,KAAK,IAAI,EAAE;AAClB,QAAA,MAAM,IAAI,SAAS,CAAC,GAAG,IAAI,CAAA,6BAAA,CAA+B,CAAC;IAC7D;IACA,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,CAAA,EAAG,KAAK,CAAA,cAAA,CAAgB,CAAC;IACjD,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,KAAK,EAAE;AACjF,QAAA,MAAM,IAAI,SAAS,CAAC,GAAG,IAAI,CAAA,iCAAA,CAAmC,CAAC;IACjE;AACA,IAAA,OAAO,KAAK;AACd;AAEA,SAAS,QAAQ,CAAC,KAAc,EAAA;AAC9B,IAAA,OAAO,SAAS,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAU,EAAE,UAAU,CAAC;AACrE;AAEA,SAAS,SAAS,CAAC,KAAc,EAAE,IAAY,EAAA;IAC7C,IACE,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,CAAC,MAAM,KAAK,CAAC;AAClB,QAAA,KAAK,CAAC,IAAI,EAAE,KAAK,KAAK;QACtB,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,GAAG;AAC5C,QAAA,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC;QACnB,oBAAoB,CAAC,KAAK,CAAC;AAC3B,QAAA,KAAK,KAAK,GAAG;AACb,QAAA,KAAK,KAAK,IAAI;AACd,SAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EACxC;AACA,QAAA,MAAM,IAAI,SAAS,CAAC,GAAG,IAAI,CAAA,yBAAA,CAA2B,CAAC;IACzD;AACA,IAAA,OAAO,KAAK;AACd;AAEA,SAAS,YAAY,CACnB,KAAc,EACd,IAAY,EACZ,QAAgB,EAAA;AAEhB,IAAA,IAAI,KAAK,KAAK,SAAS,EAAE;AACvB,QAAA,OAAO,SAAS;IAClB;IACA,IACE,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,CAAC,MAAM,KAAK,CAAC;AAClB,QAAA,KAAK,CAAC,IAAI,EAAE,KAAK,KAAK;QACtB,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,QAAQ;AACjD,QAAA,oBAAoB,CAAC,KAAK,CAAC,EAC3B;AACA,QAAA,MAAM,IAAI,SAAS,CAAC,GAAG,IAAI,CAAA,iDAAA,CAAmD,CAAC;IACjF;AACA,IAAA,OAAO,KAAK;AACd;AAEA,SAAS,oBAAoB,CAAC,KAAa,EAAA;AACzC,IAAA,KAAK,MAAM,SAAS,IAAI,KAAK,EAAE;QAC7B,MAAM,IAAI,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC;QACpC,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,KAAK,IAAI,EAAE;AAChC,YAAA,OAAO,IAAI;QACb;IACF;AACA,IAAA,OAAO,KAAK;AACd;AAEA,SAAS,MAAM,CAAC,KAAc,EAAE,IAAY,EAAA;AAC1C,IAAA,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;AACvE,QAAA,MAAM,IAAI,SAAS,CAAC,GAAG,IAAI,CAAA,kBAAA,CAAoB,CAAC;IAClD;AACA,IAAA,OAAO,KAAgC;AACzC;AAEA,SAAS,SAAS,CAChB,KAAc,EACd,OAAU,EACV,IAAY,EAAA;AAEZ,IAAA,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE;AACzD,QAAA,MAAM,IAAI,SAAS,CAAC,GAAG,IAAI,CAAA,yBAAA,CAA2B,CAAC;IACzD;AACA,IAAA,OAAO,KAAkB;AAC3B;;AC9nCA;MACa,eAAe,GAAG,IAAI,cAAc,CAAkB,gBAAgB;MActE,uBAAuB,GAClC,IAAI,cAAc,CAAwB,sBAAsB;;ACzClE;;AAEG;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sneat/extension-splitus-contract",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -1,14 +1,229 @@
1
1
  import { InjectionToken } from '@angular/core';
2
2
  import { Observable } from 'rxjs';
3
3
 
4
- /** Mirrors models4splitus.SplitMode (backend/splitus/models4splitus). */
4
+ /** The first stable Splitus bill browser/host wire contract. */
5
+ declare const SPLITUS_BILL_CONTRACT_VERSION: 1;
6
+ declare const MAX_SPLITUS_BILL_PARTICIPANTS = 256;
7
+ declare const MAX_SPLITUS_BILL_LIST_PAGE_SIZE = 100;
8
+ declare const MAX_SPLITUS_BILL_OBLIGATIONS = 256;
9
+ declare const MAX_SPLITUS_OBLIGATION_IDS_PER_LINE = 256;
10
+ type SplitusBillContractVersion = typeof SPLITUS_BILL_CONTRACT_VERSION;
11
+ /**
12
+ * A canonical, non-negative major-unit amount with exactly two fraction
13
+ * digits. Examples: `0.00`, `30.00`, `90.00`.
14
+ *
15
+ * The alias documents the wire type; use `parseExactDecimalString()` at an
16
+ * untrusted boundary. JavaScript numbers and minor-unit numbers are not part
17
+ * of this contract.
18
+ */
19
+ type ExactDecimalString = string;
20
+ /** Currencies whose minor unit is exactly two decimal digits in this contract. */
21
+ type SplitusCurrencyCode = 'EUR' | 'GBP' | 'USD';
22
+ type SplitusBillKind = 'general' | 'utility';
23
+ type SplitusUtilityKind = 'electricity' | 'gas' | 'water' | 'internet' | 'other';
24
+ type SplitusBillPostingStatus = 'pending' | 'posting' | 'applied' | 'attention';
25
+ type SplitusDebtusSettlementStatus = 'unsettled' | 'part_settled' | 'settled';
26
+ type SplitusExpectedActualComparison = 'not_available' | 'matches' | 'increased' | 'decreased';
27
+ type SplitusBillAttentionCode = 'authorization_changed' | 'source_conflict' | 'provider_rejected' | 'invalid_provider_receipt' | 'operator_action_required';
28
+ interface ISplitusBillAllocationV1 {
29
+ /** Stable within the bill revision, independent of array ordering. */
30
+ readonly allocationID: string;
31
+ /**
32
+ * Contactus identity in this Space. Hosts resolve its real display data from
33
+ * Contactus; this opaque ID is never a user-facing label.
34
+ */
35
+ readonly contactID: string;
36
+ readonly amount: ExactDecimalString;
37
+ }
38
+ interface ISplitusBillingPeriodV1 {
39
+ /** Inclusive ISO calendar date. */
40
+ readonly startDate: string;
41
+ /** Inclusive ISO calendar date; must not precede `startDate`. */
42
+ readonly endDate: string;
43
+ }
44
+ interface ISplitusUtilityDetailsV1 {
45
+ readonly utilityKind: SplitusUtilityKind;
46
+ readonly providerName?: string;
47
+ readonly period: ISplitusBillingPeriodV1;
48
+ }
49
+ /**
50
+ * A reference to the Calendarius occurrence represented by this actual bill.
51
+ * `expectedAmount` and `standingChargeAmount` are context only; neither is a
52
+ * paid expense. `actualAmount` on the enclosing bill remains mandatory.
53
+ */
54
+ interface ISplitusRecurringOccurrenceV1 {
55
+ readonly happeningID: string;
56
+ readonly occurrenceID: string;
57
+ readonly expectedAmount?: ExactDecimalString;
58
+ readonly standingChargeAmount?: ExactDecimalString;
59
+ readonly expectedComparison: SplitusExpectedActualComparison;
60
+ readonly previousComparable?: ISplitusPreviousComparableBillV1;
61
+ }
62
+ interface ISplitusPreviousComparableBillV1 {
63
+ readonly billID: string;
64
+ readonly actualAmount: ExactDecimalString;
65
+ readonly comparison: Exclude<SplitusExpectedActualComparison, 'not_available'>;
66
+ }
67
+ interface ICreateSplitusBillV1Request {
68
+ readonly contractVersion: SplitusBillContractVersion;
69
+ readonly spaceID: string;
70
+ /**
71
+ * Stable across duplicate submission and lost-response retries. Reusing the
72
+ * same ID with changed paid/owed allocations is a provider conflict.
73
+ */
74
+ readonly billID: string;
75
+ /**
76
+ * Audit identity of the authenticated actor. The server must bind this to
77
+ * its trusted authentication context. It never implies a paid or owed
78
+ * allocation.
79
+ */
80
+ readonly recorderUserID: string;
81
+ readonly title?: string;
82
+ readonly billKind: SplitusBillKind;
83
+ readonly currency: SplitusCurrencyCode;
84
+ /** Actual paid amount. An expectation is never accepted in its place. */
85
+ readonly actualAmount: ExactDecimalString;
86
+ /** Explicit sources of payment; one contact may also owe a share. */
87
+ readonly paidAllocations: readonly ISplitusBillAllocationV1[];
88
+ /** Explicit responsibility shares. */
89
+ readonly owedAllocations: readonly ISplitusBillAllocationV1[];
90
+ /** Required exactly when `billKind` is `utility`. */
91
+ readonly utility?: ISplitusUtilityDetailsV1;
92
+ readonly recurringOccurrence?: ISplitusRecurringOccurrenceV1;
93
+ }
94
+ interface ISplitusDebtusReceiptLineV1 {
95
+ readonly lineID: string;
96
+ readonly obligationIDs: readonly string[];
97
+ }
98
+ interface ISplitusBillPostingReceiptV1 {
99
+ readonly receiptID: string;
100
+ readonly operationKey: string;
101
+ readonly inputDigest: string;
102
+ readonly revision: string;
103
+ readonly obligationLines: readonly ISplitusDebtusReceiptLineV1[];
104
+ }
105
+ interface ISplitusBillPostingV1 {
106
+ readonly status: SplitusBillPostingStatus;
107
+ /** Durable identity of the retry-safe provider operation. */
108
+ readonly operationKey: string;
109
+ /** Digest of the exact accepted source revision and allocations. */
110
+ readonly inputDigest: string;
111
+ /** Present exactly when `status` is `applied`. */
112
+ readonly receipt?: ISplitusBillPostingReceiptV1;
113
+ /** Present exactly when `status` is `attention`. */
114
+ readonly attentionCode?: SplitusBillAttentionCode;
115
+ }
116
+ /**
117
+ * An application-relative target. The host resolves it through its injected
118
+ * Debtus navigation adapter; contracts never hard-code debtus.app or another
119
+ * deployment origin.
120
+ */
121
+ interface ISplitusDebtusSettlementTargetV1 {
122
+ readonly route: 'debtus.source-obligations';
123
+ readonly spaceID: string;
124
+ readonly sourceNamespace: 'splitus';
125
+ readonly sourceRecordID: string;
126
+ readonly lineID?: string;
127
+ }
128
+ interface ISplitusDebtusObligationV1 {
129
+ readonly lineID: string;
130
+ readonly obligationIDs: readonly string[];
131
+ readonly debtorContactID: string;
132
+ readonly creditorContactID: string;
133
+ readonly currency: SplitusCurrencyCode;
134
+ readonly principalAmount: ExactDecimalString;
135
+ readonly outstandingAmount: ExactDecimalString;
136
+ readonly repaidAmount: ExactDecimalString;
137
+ readonly creditAmount: ExactDecimalString;
138
+ readonly status: SplitusDebtusSettlementStatus;
139
+ readonly settlementTarget: ISplitusDebtusSettlementTargetV1;
140
+ }
141
+ interface ISplitusDebtusStatusV1 {
142
+ /** Current state read from Debtus, never a Splitus-maintained balance. */
143
+ readonly status: SplitusDebtusSettlementStatus;
144
+ readonly obligations: readonly ISplitusDebtusObligationV1[];
145
+ readonly settlementTarget: ISplitusDebtusSettlementTargetV1;
146
+ }
147
+ interface ISplitusBillV1 extends ICreateSplitusBillV1Request {
148
+ /** Canonical positive decimal integer encoded as a string. */
149
+ readonly revision: string;
150
+ readonly posting: ISplitusBillPostingV1;
151
+ /** Absent until a Debtus financial projection is available. */
152
+ readonly debtus?: ISplitusDebtusStatusV1;
153
+ readonly createdAt: string;
154
+ readonly updatedAt: string;
155
+ }
156
+ interface ICreateSplitusBillV1Response {
157
+ readonly contractVersion: SplitusBillContractVersion;
158
+ readonly bill: ISplitusBillV1;
159
+ }
160
+ interface IGetSplitusBillV1Request {
161
+ readonly contractVersion: SplitusBillContractVersion;
162
+ readonly spaceID: string;
163
+ readonly billID: string;
164
+ }
165
+ interface IGetSplitusBillV1Response {
166
+ readonly contractVersion: SplitusBillContractVersion;
167
+ readonly bill: ISplitusBillV1;
168
+ }
169
+ interface ISplitusBillListItemV1 {
170
+ readonly contractVersion: SplitusBillContractVersion;
171
+ readonly spaceID: string;
172
+ readonly billID: string;
173
+ readonly title?: string;
174
+ readonly billKind: SplitusBillKind;
175
+ readonly utilityKind?: SplitusUtilityKind;
176
+ readonly period?: ISplitusBillingPeriodV1;
177
+ readonly currency: SplitusCurrencyCode;
178
+ readonly actualAmount: ExactDecimalString;
179
+ readonly ownPaidAmount: ExactDecimalString;
180
+ readonly ownOwedAmount: ExactDecimalString;
181
+ readonly postingStatus: SplitusBillPostingStatus;
182
+ /** Debtus-derived and absent before the bill has a financial projection. */
183
+ readonly debtusSettlementStatus?: SplitusDebtusSettlementStatus;
184
+ readonly createdAt: string;
185
+ }
186
+ interface IListSplitusBillsV1Request {
187
+ readonly contractVersion: SplitusBillContractVersion;
188
+ readonly spaceID: string;
189
+ readonly pageSize: number;
190
+ readonly cursor?: string;
191
+ readonly utilityKind?: SplitusUtilityKind;
192
+ readonly period?: ISplitusBillingPeriodV1;
193
+ }
194
+ interface IListSplitusBillsV1Response {
195
+ readonly contractVersion: SplitusBillContractVersion;
196
+ /** Echoes the accepted request bound so callers can verify the page. */
197
+ readonly pageSize: number;
198
+ /** Contains no more than `pageSize` items and never more than 100. */
199
+ readonly items: readonly ISplitusBillListItemV1[];
200
+ readonly nextCursor?: string;
201
+ }
202
+ declare function parseExactDecimalString(value: unknown): ExactDecimalString;
203
+ declare function parseCreateSplitusBillV1Request(value: unknown): ICreateSplitusBillV1Request;
204
+ /**
205
+ * Executable host-boundary check for the request's audit claim. The trusted
206
+ * authenticated identity is supplied by the host, never derived from the
207
+ * request itself.
208
+ */
209
+ declare function assertCreateSplitusBillV1Recorder(request: ICreateSplitusBillV1Request, authenticatedUserID: string): void;
210
+ declare function parseListSplitusBillsV1Request(value: unknown): IListSplitusBillsV1Request;
211
+ declare function parseGetSplitusBillV1Request(value: unknown): IGetSplitusBillV1Request;
212
+ declare function parseCreateSplitusBillV1Response(value: unknown): ICreateSplitusBillV1Response;
213
+ declare function parseGetSplitusBillV1Response(value: unknown): IGetSplitusBillV1Response;
214
+ declare function parseListSplitusBillsV1Response(value: unknown, requestedPageSize?: number): IListSplitusBillsV1Response;
215
+ declare function parseSplitusBillV1(value: unknown): ISplitusBillV1;
216
+
217
+ /** @deprecated Use the Splitus bill contract types exported from `bill-v1`. */
5
218
  type SplitMode = 'equally' | 'exact-amount' | 'percentage';
219
+ /** @deprecated Use `SplitusCurrencyCode` from the Splitus bill contract. */
6
220
  type CurrencyCode = 'EUR' | 'USD';
7
221
  /**
8
222
  * One participant's custom share for `exact-amount` / `percentage` split
9
223
  * modes. An omitted/empty `contactID` denotes the payer's own share. Ignored
10
224
  * (and may be omitted) for `equally`, which the backend computes itself.
11
225
  */
226
+ /** @deprecated Use explicit paid and owed allocations in `ICreateSplitusBillV1Request`. */
12
227
  interface ISplitShare {
13
228
  readonly contactID?: string;
14
229
  /** Decimal string, e.g. "35.00" — required for `exact-amount`. */
@@ -16,6 +231,7 @@ interface ISplitShare {
16
231
  /** Decimal string, e.g. "33.34" — required for `percentage`. */
17
232
  readonly percent?: string;
18
233
  }
234
+ /** @deprecated Use `ICreateSplitusBillV1Request`. */
19
235
  interface ICreateSplitRequest {
20
236
  readonly spaceID: string;
21
237
  readonly title?: string;
@@ -32,11 +248,13 @@ interface ICreateSplitRequest {
32
248
  /** Required for `exact-amount` / `percentage`; ignored for `equally`. */
33
249
  readonly shares?: ISplitShare[];
34
250
  }
251
+ /** @deprecated Use `ISplitusDebtusObligationV1`. */
35
252
  interface ICreateSplitTransfer {
36
253
  readonly id: string;
37
254
  readonly contactID: string;
38
255
  readonly amount: number;
39
256
  }
257
+ /** @deprecated Use `ICreateSplitusBillV1Response`. */
40
258
  interface ICreateSplitResponse {
41
259
  readonly id: string;
42
260
  /**
@@ -49,7 +267,9 @@ interface ICreateSplitResponse {
49
267
  * "settled" or "outstanding", derived server-side by reading the linked
50
268
  * Debtus transfers — never computed or cached on the client.
51
269
  */
270
+ /** @deprecated Use `SplitusDebtusSettlementStatus`. */
52
271
  type SplitShareStatus = 'settled' | 'outstanding';
272
+ /** @deprecated Use `ISplitusBillAllocationV1`. */
53
273
  interface ISplitParticipant {
54
274
  readonly contactID?: string;
55
275
  readonly userID?: string;
@@ -58,6 +278,7 @@ interface ISplitParticipant {
58
278
  readonly isPayer?: boolean;
59
279
  readonly status: SplitShareStatus;
60
280
  }
281
+ /** @deprecated Use `ISplitusBillV1`. */
61
282
  interface ISplit {
62
283
  readonly id: string;
63
284
  readonly title?: string;
@@ -66,6 +287,7 @@ interface ISplit {
66
287
  readonly status: string;
67
288
  readonly participants: ISplitParticipant[];
68
289
  }
290
+ /** @deprecated Use `ISplitusBillListItemV1`. */
69
291
  interface ISplitListItem {
70
292
  readonly id: string;
71
293
  readonly title?: string;
@@ -75,6 +297,7 @@ interface ISplitListItem {
75
297
  readonly membersCount: number;
76
298
  }
77
299
 
300
+ /** @deprecated Use `ISplitusBillServiceV1`. */
78
301
  interface ISplitusService {
79
302
  /** REAL: POST /api4splitus/create-split. Payer is the authenticated user. */
80
303
  createSplit(request: ICreateSplitRequest): Observable<ICreateSplitResponse>;
@@ -83,7 +306,14 @@ interface ISplitusService {
83
306
  /** REAL: GET /api4splitus/splits?spaceID= */
84
307
  getSplits(spaceID: string): Observable<ISplitListItem[]>;
85
308
  }
309
+ /** @deprecated Use `SPLITUS_BILL_SERVICE_V1`. */
86
310
  declare const SPLITUS_SERVICE: InjectionToken<ISplitusService>;
311
+ interface ISplitusBillServiceV1 {
312
+ createBill(request: ICreateSplitusBillV1Request): Observable<ICreateSplitusBillV1Response>;
313
+ getBill(request: IGetSplitusBillV1Request): Observable<IGetSplitusBillV1Response>;
314
+ listBills(request: IListSplitusBillsV1Request): Observable<IListSplitusBillsV1Response>;
315
+ }
316
+ declare const SPLITUS_BILL_SERVICE_V1: InjectionToken<ISplitusBillServiceV1>;
87
317
 
88
- export { SPLITUS_SERVICE };
89
- export type { CurrencyCode, ICreateSplitRequest, ICreateSplitResponse, ICreateSplitTransfer, ISplit, ISplitListItem, ISplitParticipant, ISplitShare, ISplitusService, SplitMode, SplitShareStatus };
318
+ export { MAX_SPLITUS_BILL_LIST_PAGE_SIZE, MAX_SPLITUS_BILL_OBLIGATIONS, MAX_SPLITUS_BILL_PARTICIPANTS, MAX_SPLITUS_OBLIGATION_IDS_PER_LINE, SPLITUS_BILL_CONTRACT_VERSION, SPLITUS_BILL_SERVICE_V1, SPLITUS_SERVICE, assertCreateSplitusBillV1Recorder, parseCreateSplitusBillV1Request, parseCreateSplitusBillV1Response, parseExactDecimalString, parseGetSplitusBillV1Request, parseGetSplitusBillV1Response, parseListSplitusBillsV1Request, parseListSplitusBillsV1Response, parseSplitusBillV1 };
319
+ export type { CurrencyCode, ExactDecimalString, ICreateSplitRequest, ICreateSplitResponse, ICreateSplitTransfer, ICreateSplitusBillV1Request, ICreateSplitusBillV1Response, IGetSplitusBillV1Request, IGetSplitusBillV1Response, IListSplitusBillsV1Request, IListSplitusBillsV1Response, ISplit, ISplitListItem, ISplitParticipant, ISplitShare, ISplitusBillAllocationV1, ISplitusBillListItemV1, ISplitusBillPostingReceiptV1, ISplitusBillPostingV1, ISplitusBillServiceV1, ISplitusBillV1, ISplitusBillingPeriodV1, ISplitusDebtusObligationV1, ISplitusDebtusReceiptLineV1, ISplitusDebtusSettlementTargetV1, ISplitusDebtusStatusV1, ISplitusPreviousComparableBillV1, ISplitusRecurringOccurrenceV1, ISplitusService, ISplitusUtilityDetailsV1, SplitMode, SplitShareStatus, SplitusBillAttentionCode, SplitusBillContractVersion, SplitusBillKind, SplitusBillPostingStatus, SplitusCurrencyCode, SplitusDebtusSettlementStatus, SplitusExpectedActualComparison, SplitusUtilityKind };