@classytic/ledger 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bridges/index.d.mts +2 -0
- package/dist/bridges/index.mjs +1 -0
- package/dist/constants/index.d.mts +1 -1
- package/dist/constants/index.mjs +2 -2
- package/dist/country/index.d.mts +1 -1
- package/dist/errors-BI5k4iak.mjs +121 -0
- package/dist/events/index.d.mts +2 -0
- package/dist/events/index.mjs +2 -0
- package/dist/exports/index.d.mts +1 -1
- package/dist/exports/index.mjs +1 -1
- package/dist/{fx-realization.plugin-DDVK-oYO.mjs → fx-realization.plugin-Bxlb8cIx.mjs} +2 -2
- package/dist/{index-RNZsX0Yo.d.mts → index-08IpHhrU.d.mts} +1 -1
- package/dist/index-dqkjgpII.d.mts +104 -0
- package/dist/index.d.mts +227 -65
- package/dist/index.mjs +385 -99
- package/dist/{journals-Dd4A9TN3.d.mts → journals-DUpWwFt1.d.mts} +1 -1
- package/dist/outbox-store-DQbL-KYT.mjs +132 -0
- package/dist/outbox-store-UYC4eZpI.d.mts +249 -0
- package/dist/{partner-ledger-D9H5hegI.mjs → partner-ledger-BoebloHk.mjs} +2 -2
- package/dist/plugins/index.d.mts +1 -1
- package/dist/plugins/index.mjs +1 -1
- package/dist/reports/index.d.mts +1 -1
- package/dist/reports/index.mjs +1 -1
- package/dist/sync/index.d.mts +1 -1
- package/dist/sync/index.mjs +1 -1
- package/dist/{sync-CnuVf441.d.mts → sync-JvchM3FO.d.mts} +1 -1
- package/dist/{trial-balance-DTj-c21f.d.mts → trial-balance-DyNm5bFu.d.mts} +2 -2
- package/package.json +14 -4
- package/dist/errors-CSDQPNyt.mjs +0 -33
- /package/dist/{categories-BkKdv16V.mjs → categories-FJlrvzcl.mjs} +0 -0
- /package/dist/{core-MpgjCqK0.d.mts → core-DwjkrRkJ.d.mts} +0 -0
- /package/dist/{currencies-CsuBGfgs.mjs → currencies-Jo5oaM_4.mjs} +0 -0
- /package/dist/{exports-B3whucXe.mjs → exports-C30yRapf.mjs} +0 -0
- /package/dist/{index-BSsvrf3m.d.mts → index-Db0n_6Z8.d.mts} +0 -0
- /package/dist/{index-bCEeSzdO.d.mts → index-J-XIbXH-.d.mts} +0 -0
- /package/dist/{opening-balance-DPXmAIzN.mjs → opening-balance-1cixYh6Y.mjs} +0 -0
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as EntryReversedNotification, c as PeriodLockedNotification, i as SourceRef, l as ReconciliationMismatchNotification, n as SourceBridge, o as NotificationBridge, r as SourceBridgeContext, s as NotificationBridgeContext, t as LedgerBridges } from "../index-dqkjgpII.mjs";
|
|
2
|
+
export { EntryReversedNotification, LedgerBridges, NotificationBridge, NotificationBridgeContext, PeriodLockedNotification, ReconciliationMismatchNotification, SourceBridge, SourceBridgeContext, SourceRef };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { S as isValidCategory, _ as getCategoryMainType, a as getJournalTypeCodes, b as isBalanceSheet, c as CURRENCIES, d as isValidCurrency, f as CATEGORIES, g as extractStatementType, h as extractMainType, i as getJournalType, l as getCurrency, m as categoryKey, n as JOURNAL_TYPES, o as isValidJournalType, p as CATEGORY_KEYS, r as getCustomJournalTypes, s as registerJournalType, t as JOURNAL_CODES, u as getMinorUnit, v as getCategoryStatementType, x as isIncomeStatement, y as getNormalBalance } from "../journals-
|
|
1
|
+
import { S as isValidCategory, _ as getCategoryMainType, a as getJournalTypeCodes, b as isBalanceSheet, c as CURRENCIES, d as isValidCurrency, f as CATEGORIES, g as extractStatementType, h as extractMainType, i as getJournalType, l as getCurrency, m as categoryKey, n as JOURNAL_TYPES, o as isValidJournalType, p as CATEGORY_KEYS, r as getCustomJournalTypes, s as registerJournalType, t as JOURNAL_CODES, u as getMinorUnit, v as getCategoryStatementType, x as isIncomeStatement, y as getNormalBalance } from "../journals-DUpWwFt1.mjs";
|
|
2
2
|
export { CATEGORIES, CATEGORY_KEYS, CURRENCIES, JOURNAL_CODES, JOURNAL_TYPES, categoryKey, extractMainType, extractStatementType, getCategoryMainType, getCategoryStatementType, getCurrency, getCustomJournalTypes, getJournalType, getJournalTypeCodes, getMinorUnit, getNormalBalance, isBalanceSheet, isIncomeStatement, isValidCategory, isValidCurrency, isValidJournalType, registerJournalType };
|
package/dist/constants/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { a as JOURNAL_CODES, c as getCustomJournalTypes, d as isValidJournalType, f as registerJournalType, i as isValidCurrency, l as getJournalType, n as getCurrency, o as JOURNAL_TYPES, r as getMinorUnit, t as CURRENCIES, u as getJournalTypeCodes } from "../currencies-
|
|
2
|
-
import { a as extractStatementType, c as getNormalBalance, d as isValidCategory, i as extractMainType, l as isBalanceSheet, n as CATEGORY_KEYS, o as getCategoryMainType, r as categoryKey, s as getCategoryStatementType, t as CATEGORIES, u as isIncomeStatement } from "../categories-
|
|
1
|
+
import { a as JOURNAL_CODES, c as getCustomJournalTypes, d as isValidJournalType, f as registerJournalType, i as isValidCurrency, l as getJournalType, n as getCurrency, o as JOURNAL_TYPES, r as getMinorUnit, t as CURRENCIES, u as getJournalTypeCodes } from "../currencies-Jo5oaM_4.mjs";
|
|
2
|
+
import { a as extractStatementType, c as getNormalBalance, d as isValidCategory, i as extractMainType, l as isBalanceSheet, n as CATEGORY_KEYS, o as getCategoryMainType, r as categoryKey, s as getCategoryStatementType, t as CATEGORIES, u as isIncomeStatement } from "../categories-FJlrvzcl.mjs";
|
|
3
3
|
export { CATEGORIES, CATEGORY_KEYS, CURRENCIES, JOURNAL_CODES, JOURNAL_TYPES, categoryKey, extractMainType, extractStatementType, getCategoryMainType, getCategoryStatementType, getCurrency, getCustomJournalTypes, getJournalType, getJournalTypeCodes, getMinorUnit, getNormalBalance, isBalanceSheet, isIncomeStatement, isValidCategory, isValidCurrency, isValidJournalType, registerJournalType };
|
package/dist/country/index.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as defineCountryPack, n as CountryPackInput, r as JournalTemplate, t as CountryPack } from "../index-
|
|
1
|
+
import { i as defineCountryPack, n as CountryPackInput, r as JournalTemplate, t as CountryPack } from "../index-08IpHhrU.mjs";
|
|
2
2
|
export { CountryPack, CountryPackInput, JournalTemplate, defineCountryPack };
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
//#region src/utils/errors.ts
|
|
2
|
+
var AccountingError = class extends Error {
|
|
3
|
+
status;
|
|
4
|
+
code;
|
|
5
|
+
fields;
|
|
6
|
+
constructor(message, status = 400, code = "ACCOUNTING_ERROR", fields) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = "AccountingError";
|
|
9
|
+
this.status = status;
|
|
10
|
+
this.code = code;
|
|
11
|
+
if (fields && fields.length > 0) this.fields = Object.freeze([...fields]);
|
|
12
|
+
}
|
|
13
|
+
/** Serialize to a plain object for API responses and logs. */
|
|
14
|
+
toJSON() {
|
|
15
|
+
return {
|
|
16
|
+
name: this.name,
|
|
17
|
+
message: this.message,
|
|
18
|
+
status: this.status,
|
|
19
|
+
code: this.code,
|
|
20
|
+
...this.fields ? { fields: this.fields } : {}
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
const Errors = {
|
|
25
|
+
validation: (msg, fields) => new AccountingError(msg, 400, "VALIDATION_ERROR", fields),
|
|
26
|
+
notFound: (msg, fields) => new AccountingError(msg, 404, "NOT_FOUND", fields),
|
|
27
|
+
conflict: (msg, fields) => new AccountingError(msg, 409, "CONFLICT", fields),
|
|
28
|
+
immutable: (msg, _fields) => new AccountingError(msg, 403, "IMMUTABLE_ENTRY"),
|
|
29
|
+
locked: (scope, msg, fields) => new AccountingError(msg, 409, `PERIOD_LOCKED_${scope.toUpperCase()}`, fields)
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Thrown when an idempotent create was attempted with a key that already
|
|
33
|
+
* resolved to a different winner (not the common "same winner, same payload"
|
|
34
|
+
* replay — that returns the existing doc without throwing).
|
|
35
|
+
*
|
|
36
|
+
* Typically surfaces when the host supplies an `idempotencyKey` that collides
|
|
37
|
+
* with a logically-different prior write.
|
|
38
|
+
*/
|
|
39
|
+
var IdempotencyConflictError = class extends AccountingError {
|
|
40
|
+
idempotencyKey;
|
|
41
|
+
existingId;
|
|
42
|
+
constructor(idempotencyKey, existingId, message) {
|
|
43
|
+
super(message ?? `Idempotency key "${idempotencyKey}" already resolved to entry ${String(existingId)}.`, 409, "IDEMPOTENCY_CONFLICT");
|
|
44
|
+
this.name = "IdempotencyConflictError";
|
|
45
|
+
this.idempotencyKey = idempotencyKey;
|
|
46
|
+
this.existingId = existingId;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Thrown when the unique `referenceNumber` index fires. With the new atomic
|
|
51
|
+
* counter this should be effectively impossible — if it ever throws, it
|
|
52
|
+
* indicates either a pre-atomic-counter doc that was hand-inserted OR a bug
|
|
53
|
+
* in the counter partitioning.
|
|
54
|
+
*/
|
|
55
|
+
var DuplicateReferenceError = class extends AccountingError {
|
|
56
|
+
referenceNumber;
|
|
57
|
+
constructor(referenceNumber, message) {
|
|
58
|
+
super(message ?? `Duplicate reference number "${referenceNumber}".`, 409, "DUPLICATE_REFERENCE_NUMBER");
|
|
59
|
+
this.name = "DuplicateReferenceError";
|
|
60
|
+
this.referenceNumber = referenceNumber;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Thrown when an optimistic-concurrency FSM transition fails because another
|
|
65
|
+
* writer advanced the state or version between our read and our write.
|
|
66
|
+
*
|
|
67
|
+
* Callers should re-fetch the doc and decide whether to retry or surface.
|
|
68
|
+
*/
|
|
69
|
+
var ConcurrencyError = class extends AccountingError {
|
|
70
|
+
resource;
|
|
71
|
+
resourceId;
|
|
72
|
+
constructor(resource, resourceId, message) {
|
|
73
|
+
super(message ?? `${resource} ${String(resourceId)} was modified by another writer — retry after re-fetch.`, 409, "CONCURRENCY_CONFLICT");
|
|
74
|
+
this.name = "ConcurrencyError";
|
|
75
|
+
this.resource = resource;
|
|
76
|
+
this.resourceId = resourceId;
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* Thrown when a mutation targets an entry that is protected by immutability —
|
|
81
|
+
* either `strictness.immutable` or the double-entry plugin's posted-entry
|
|
82
|
+
* guard. Factory `Errors.immutable(msg)` returns this subclass so callers
|
|
83
|
+
* can `instanceof`-match without sniffing the `code` field.
|
|
84
|
+
*/
|
|
85
|
+
var ImmutableViolationError = class extends AccountingError {
|
|
86
|
+
entryId;
|
|
87
|
+
constructor(entryId, message, fields) {
|
|
88
|
+
super(message ?? `Entry ${String(entryId)} is posted and immutable. Use reverse() to correct it.`, 403, "IMMUTABLE_ENTRY", fields);
|
|
89
|
+
this.name = "ImmutableViolationError";
|
|
90
|
+
this.entryId = entryId;
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
Errors.immutable = (msg, fields) => new ImmutableViolationError(null, msg, fields);
|
|
94
|
+
/**
|
|
95
|
+
* Detect a Mongo duplicate-key error (11000) and return the index name the
|
|
96
|
+
* conflict hit on, so callers can switch on which unique key fired.
|
|
97
|
+
*
|
|
98
|
+
* Handles both driver-style and mongoose-style error shapes. Safe to call
|
|
99
|
+
* with any `unknown` — returns `null` when the error is not a dup-key.
|
|
100
|
+
*/
|
|
101
|
+
function classifyDuplicateKey(err) {
|
|
102
|
+
if (!err || typeof err !== "object") return null;
|
|
103
|
+
const e = err;
|
|
104
|
+
const code = typeof e.code === "number" ? e.code : typeof e.code === "string" ? Number(e.code) : void 0;
|
|
105
|
+
const isDriverDup = code === 11e3 || e.name === "MongoServerError" && code === 11e3 || Array.isArray(e.writeErrors) && e.writeErrors.some((w) => w?.code === 11e3);
|
|
106
|
+
const wrappedMsgMatch = typeof e.message === "string" ? e.message.match(/^Duplicate value for ([a-zA-Z_.0-9,\s]+?)(?:\s*\(|$)/) : null;
|
|
107
|
+
const isMongokitDup = e.status === 409 && !!wrappedMsgMatch;
|
|
108
|
+
if (!isDriverDup && !isMongokitDup) return null;
|
|
109
|
+
let keyPattern = e.keyPattern;
|
|
110
|
+
if (!keyPattern && Array.isArray(e.writeErrors)) keyPattern = e.writeErrors.find((w) => w?.code === 11e3)?.keyPattern;
|
|
111
|
+
if (!keyPattern && wrappedMsgMatch) {
|
|
112
|
+
const fields = wrappedMsgMatch[1].split(",").map((f) => f.trim()).filter(Boolean);
|
|
113
|
+
keyPattern = Object.fromEntries(fields.map((f) => [f, 1]));
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
indexName: keyPattern ? Object.keys(keyPattern).join("_") : typeof e.message === "string" && e.message.match(/index: ([^\s]+)/)?.[1] ? e.message.match(/index: ([^\s]+)/)[1] : "unknown",
|
|
117
|
+
keyPattern
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
//#endregion
|
|
121
|
+
export { IdempotencyConflictError as a, Errors as i, ConcurrencyError as n, ImmutableViolationError as o, DuplicateReferenceError as r, classifyDuplicateKey as s, AccountingError as t };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { C as EntryReversedPayload, D as ReconciliationUnmatchedPayload, E as ReconciliationMatchedPayload, O as LEDGER_EVENTS, S as EntryPostedPayload, T as JournalSeededPayload, _ as AccountBulkCreatedPayload, a as OutboxOwnershipError, b as EntryCreatedPayload, c as InProcessLedgerBus, d as createEvent, f as DomainEvent, g as PublishManyResult, h as EventTransport, i as OutboxFailOptions, k as LedgerEventName, l as InProcessLedgerBusOptions, m as EventLogger, n as OutboxClaimOptions, o as OutboxStore, p as EventHandler, r as OutboxErrorInfo, s as OutboxWriteOptions, t as OutboxAcknowledgeOptions, u as EventContext, v as AccountSeededPayload, w as EntryUnpostedPayload, x as EntryDuplicatedPayload, y as EntryArchivedPayload } from "../outbox-store-UYC4eZpI.mjs";
|
|
2
|
+
export { type AccountBulkCreatedPayload, type AccountSeededPayload, type DomainEvent, type EntryArchivedPayload, type EntryCreatedPayload, type EntryDuplicatedPayload, type EntryPostedPayload, type EntryReversedPayload, type EntryUnpostedPayload, type EventContext, type EventHandler, type EventLogger, type EventTransport, InProcessLedgerBus, type InProcessLedgerBusOptions, type JournalSeededPayload, LEDGER_EVENTS, type LedgerEventName, type OutboxAcknowledgeOptions, type OutboxClaimOptions, type OutboxErrorInfo, type OutboxFailOptions, OutboxOwnershipError, type OutboxStore, type OutboxWriteOptions, type PublishManyResult, type ReconciliationMatchedPayload, type ReconciliationUnmatchedPayload, createEvent };
|
package/dist/exports/index.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { _ as PopulatedJournalEntry, a as exportToCsv, c as getHeaders, d as serializeCsv, f as CsvOptions, g as PopulatedAccount, h as FlatJournalRow, i as quickbooksFieldMap, l as buildCsv, m as ExportFieldMap, n as flattenJournalEntry, o as extractAllRows, p as ExportField, r as universalFieldMap, s as extractRow, t as flattenJournalEntries, u as escapeCell, v as PopulatedJournalItem } from "../index-
|
|
1
|
+
import { _ as PopulatedJournalEntry, a as exportToCsv, c as getHeaders, d as serializeCsv, f as CsvOptions, g as PopulatedAccount, h as FlatJournalRow, i as quickbooksFieldMap, l as buildCsv, m as ExportFieldMap, n as flattenJournalEntry, o as extractAllRows, p as ExportField, r as universalFieldMap, s as extractRow, t as flattenJournalEntries, u as escapeCell, v as PopulatedJournalItem } from "../index-J-XIbXH-.mjs";
|
|
2
2
|
export { CsvOptions, ExportField, ExportFieldMap, FlatJournalRow, PopulatedAccount, PopulatedJournalEntry, PopulatedJournalItem, buildCsv, escapeCell, exportToCsv, extractAllRows, extractRow, flattenJournalEntries, flattenJournalEntry, getHeaders, quickbooksFieldMap, serializeCsv, universalFieldMap };
|
package/dist/exports/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as exportToCsv, c as getHeaders, d as serializeCsv, i as quickbooksFieldMap, l as buildCsv, n as flattenJournalEntry, o as extractAllRows, r as universalFieldMap, s as extractRow, t as flattenJournalEntries, u as escapeCell } from "../exports-
|
|
1
|
+
import { a as exportToCsv, c as getHeaders, d as serializeCsv, i as quickbooksFieldMap, l as buildCsv, n as flattenJournalEntry, o as extractAllRows, r as universalFieldMap, s as extractRow, t as flattenJournalEntries, u as escapeCell } from "../exports-C30yRapf.mjs";
|
|
2
2
|
export { buildCsv, escapeCell, exportToCsv, extractAllRows, extractRow, flattenJournalEntries, flattenJournalEntry, getHeaders, quickbooksFieldMap, serializeCsv, universalFieldMap };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as IdempotencyConflictError, i as Errors, t as AccountingError } from "./errors-BI5k4iak.mjs";
|
|
2
2
|
//#region src/plugins/double-entry.plugin.ts
|
|
3
3
|
function doubleEntryPlugin(options = {}) {
|
|
4
4
|
const { onlyOnPost = true, JournalEntryModel, AccountModel, orgField } = options;
|
|
@@ -166,7 +166,7 @@ function idempotencyPlugin(options) {
|
|
|
166
166
|
const query = { idempotencyKey: data.idempotencyKey };
|
|
167
167
|
if (orgField && data[orgField]) query[orgField] = data[orgField];
|
|
168
168
|
const existing = await JournalEntryModel.findOne(query).select("_id").session(context.session ?? null).lean();
|
|
169
|
-
if (existing) throw
|
|
169
|
+
if (existing) throw new IdempotencyConflictError(data.idempotencyKey, existing._id);
|
|
170
170
|
});
|
|
171
171
|
repo.on("before:createMany", async (context) => {
|
|
172
172
|
const docs = context.dataArray;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
//#region src/bridges/notification.bridge.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* NotificationBridge — host-implemented delivery for ledger-originated alerts.
|
|
4
|
+
*
|
|
5
|
+
* The ledger generates operational alerts that hosts may want to route to
|
|
6
|
+
* email, Slack, in-app notifications, or an audit/compliance system:
|
|
7
|
+
*
|
|
8
|
+
* - `periodLocked` — a fiscal period was locked (audit sign-off)
|
|
9
|
+
* - `periodUnlocked` — a locked period was re-opened (requires elevated role)
|
|
10
|
+
* - `entryReversed` — a posted entry was reversed (accounting correction)
|
|
11
|
+
* - `reconciliationMismatch` — match debit/credit totals differ (FX gain/loss)
|
|
12
|
+
*
|
|
13
|
+
* This is deliberately thin — richer integrations should subscribe to the
|
|
14
|
+
* EventTransport (§11-14) and route via their own notification stack.
|
|
15
|
+
* NotificationBridge exists for hosts that want a direct callback without
|
|
16
|
+
* owning an event bus.
|
|
17
|
+
*
|
|
18
|
+
* All methods are optional. Skip the bridge entirely if the host uses events.
|
|
19
|
+
*/
|
|
20
|
+
interface NotificationBridgeContext {
|
|
21
|
+
organizationId?: unknown;
|
|
22
|
+
actorId?: unknown;
|
|
23
|
+
correlationId?: string;
|
|
24
|
+
}
|
|
25
|
+
interface PeriodLockedNotification {
|
|
26
|
+
periodId: unknown;
|
|
27
|
+
startDate: Date;
|
|
28
|
+
endDate: Date;
|
|
29
|
+
lockedBy?: unknown;
|
|
30
|
+
}
|
|
31
|
+
interface EntryReversedNotification {
|
|
32
|
+
originalEntryId: unknown;
|
|
33
|
+
reversalEntryId: unknown;
|
|
34
|
+
reversalDate: Date;
|
|
35
|
+
reversedBy?: unknown;
|
|
36
|
+
reason?: string;
|
|
37
|
+
}
|
|
38
|
+
interface ReconciliationMismatchNotification {
|
|
39
|
+
matchingNumber: string;
|
|
40
|
+
account: unknown;
|
|
41
|
+
debitTotal: number;
|
|
42
|
+
creditTotal: number;
|
|
43
|
+
difference: number;
|
|
44
|
+
currency: string | null;
|
|
45
|
+
}
|
|
46
|
+
interface NotificationBridge {
|
|
47
|
+
onPeriodLocked?(payload: PeriodLockedNotification, ctx: NotificationBridgeContext): Promise<void>;
|
|
48
|
+
onPeriodUnlocked?(payload: PeriodLockedNotification, ctx: NotificationBridgeContext): Promise<void>;
|
|
49
|
+
onEntryReversed?(payload: EntryReversedNotification, ctx: NotificationBridgeContext): Promise<void>;
|
|
50
|
+
onReconciliationMismatch?(payload: ReconciliationMismatchNotification, ctx: NotificationBridgeContext): Promise<void>;
|
|
51
|
+
}
|
|
52
|
+
//#endregion
|
|
53
|
+
//#region src/bridges/source.bridge.d.ts
|
|
54
|
+
/**
|
|
55
|
+
* SourceBridge — host-implemented resolver for polymorphic external references.
|
|
56
|
+
*
|
|
57
|
+
* Ledger journal entries commonly carry a `reference`/`externalRef` pointing
|
|
58
|
+
* at a source document that lives outside the ledger package — an Invoice,
|
|
59
|
+
* Payment, Payroll Run, Stripe Charge, ERP voucher, etc. Storing these as
|
|
60
|
+
* opaque `String + sourceModel` (per PACKAGE_RULES §7) keeps the ledger
|
|
61
|
+
* transport-agnostic: the same schema works whether the source lives in the
|
|
62
|
+
* same Mongo, a different Mongo, Postgres, or an external REST API.
|
|
63
|
+
*
|
|
64
|
+
* Hosts implement `SourceBridge` to hydrate those refs when building
|
|
65
|
+
* enriched views (partner ledger with invoice details, audit trail with
|
|
66
|
+
* payment metadata, reconciliation UI with source documents, etc.).
|
|
67
|
+
*
|
|
68
|
+
* All methods are optional. Features that need resolution degrade gracefully
|
|
69
|
+
* when a bridge is not provided.
|
|
70
|
+
*/
|
|
71
|
+
interface SourceRef {
|
|
72
|
+
sourceId: string;
|
|
73
|
+
sourceModel: string;
|
|
74
|
+
}
|
|
75
|
+
interface SourceBridgeContext {
|
|
76
|
+
organizationId?: unknown;
|
|
77
|
+
actorId?: unknown;
|
|
78
|
+
[key: string]: unknown;
|
|
79
|
+
}
|
|
80
|
+
interface SourceBridge {
|
|
81
|
+
/**
|
|
82
|
+
* Resolve a single external reference.
|
|
83
|
+
*
|
|
84
|
+
* Return `null` when the source cannot be found (deleted, permission
|
|
85
|
+
* denied, wrong model). Do not throw for missing sources — callers
|
|
86
|
+
* expect `null` for graceful degradation.
|
|
87
|
+
*/
|
|
88
|
+
resolve?(sourceId: string, sourceModel: string, ctx: SourceBridgeContext): Promise<unknown | null>;
|
|
89
|
+
/**
|
|
90
|
+
* Batch resolver — avoids N+1 round-trips when enriching a list.
|
|
91
|
+
* Key the returned map by `sourceId`. Missing sources may be omitted or
|
|
92
|
+
* mapped to `null` at the implementer's discretion.
|
|
93
|
+
*/
|
|
94
|
+
resolveMany?(refs: ReadonlyArray<SourceRef>, ctx: SourceBridgeContext): Promise<Map<string, unknown>>;
|
|
95
|
+
}
|
|
96
|
+
//#endregion
|
|
97
|
+
//#region src/bridges/index.d.ts
|
|
98
|
+
/** Collected bridges exposed as `engine.bridges`. */
|
|
99
|
+
interface LedgerBridges {
|
|
100
|
+
source?: SourceBridge;
|
|
101
|
+
notification?: NotificationBridge;
|
|
102
|
+
}
|
|
103
|
+
//#endregion
|
|
104
|
+
export { EntryReversedNotification as a, PeriodLockedNotification as c, SourceRef as i, ReconciliationMismatchNotification as l, SourceBridge as n, NotificationBridge as o, SourceBridgeContext as r, NotificationBridgeContext as s, LedgerBridges as t };
|