@happyvertical/smrt-ledgers 0.57.2 → 0.57.3
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/AGENTS.md +9 -0
- package/README.md +73 -0
- package/dist/chunks/{Account-b0RgfbjM.js → Account-IFuMKhPt.js} +42 -8
- package/dist/chunks/Account-IFuMKhPt.js.map +1 -0
- package/dist/chunks/Ledger-DwxK6NRF.js +68 -0
- package/dist/chunks/Ledger-DwxK6NRF.js.map +1 -0
- package/dist/collections/JournalEntries.d.ts +26 -0
- package/dist/collections/JournalEntries.d.ts.map +1 -1
- package/dist/collections/Journals.d.ts.map +1 -1
- package/dist/collections/Ledgers.d.ts +6 -0
- package/dist/collections/Ledgers.d.ts.map +1 -0
- package/dist/collections/index.d.ts +1 -0
- package/dist/collections/index.d.ts.map +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +380 -17
- package/dist/index.js.map +1 -1
- package/dist/manifest.json +639 -13
- package/dist/models/Account.d.ts +4 -0
- package/dist/models/Account.d.ts.map +1 -1
- package/dist/models/Journal.d.ts +9 -0
- package/dist/models/Journal.d.ts.map +1 -1
- package/dist/models/JournalEntry.d.ts +10 -0
- package/dist/models/JournalEntry.d.ts.map +1 -1
- package/dist/models/Ledger.d.ts +18 -0
- package/dist/models/Ledger.d.ts.map +1 -0
- package/dist/models/index.d.ts +1 -0
- package/dist/models/index.d.ts.map +1 -1
- package/dist/postings.d.ts +33 -0
- package/dist/postings.d.ts.map +1 -0
- package/dist/recipes.d.ts +9 -0
- package/dist/recipes.d.ts.map +1 -1
- package/dist/smrt-knowledge.json +475 -9
- package/dist/types.d.ts +23 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +5 -5
- package/dist/chunks/Account-b0RgfbjM.js.map +0 -1
package/AGENTS.md
CHANGED
|
@@ -24,6 +24,15 @@ PII-conscious variable selection: `tenantId`, `sourceRef` (may reference custome
|
|
|
24
24
|
|
|
25
25
|
## Balance Enforcement
|
|
26
26
|
|
|
27
|
+
Named `Ledger` scopes freeze owner, currency and balance mode at creation.
|
|
28
|
+
`exact-integer` mode requires safe integer minor units and exact equality; assigned
|
|
29
|
+
accounts freeze scope/owner/type and cannot be deleted. Posted scoped journals and
|
|
30
|
+
lines are immutable, including void/delete; use compensating postings.
|
|
31
|
+
`postReceivable`/`postPayable`/`postSettlement` require exact ledgers and use one
|
|
32
|
+
transactional claim per tenant/ledger/key with payload-digest replay validation.
|
|
33
|
+
See README for ownership, reversal, aging and dialect contracts.
|
|
34
|
+
|
|
35
|
+
|
|
27
36
|
`journal.post()` validates `Math.abs(totalDebits - totalCredits) < BALANCE_EPSILON` where `BALANCE_EPSILON = 0.01` (float rounding tolerance). Unbalanced journals cannot be posted.
|
|
28
37
|
|
|
29
38
|
**This package is unit-agnostic** — `debit` / `credit` are plain DECIMAL numbers and the balance check only compares the two sides, so it holds for whatever unit the posting module uses. As of #2401, journals posted from `@happyvertical/smrt-commerce` (`Payment.recordPayment()`, `Invoice.recognizeRevenue()`) carry **integer minor units**, which balance exactly rather than merely within the epsilon. A consumer mixing modules that post in different units will get arithmetically balanced but semantically meaningless journals; pick one unit per ledger.
|
package/README.md
CHANGED
|
@@ -2,6 +2,66 @@
|
|
|
2
2
|
|
|
3
3
|
Double-entry accounting ledger for the s-m-r-t framework. Hierarchical chart of accounts, journal lifecycle with immutability after posting, and balance enforcement with epsilon tolerance.
|
|
4
4
|
|
|
5
|
+
## Exact ledgers and counterparties
|
|
6
|
+
|
|
7
|
+
Create a `Ledger` with `balanceMode: 'exact-integer'` and an ISO currency when
|
|
8
|
+
the accounting scope stores minor units. Accounts and journals assigned to that
|
|
9
|
+
ledger must share its tenant and currency; posting rejects fractional or unsafe
|
|
10
|
+
amounts and requires exactly equal debit and credit totals. Existing journals
|
|
11
|
+
without a ledger retain the compatible tolerant decimal rule. Direct entry
|
|
12
|
+
writes also require an accessible same-owner journal and matching account/journal
|
|
13
|
+
ledger scope; legacy journals cannot write movements on scoped accounts. An
|
|
14
|
+
existing account cannot change ledger scope, including adoption from an unassigned
|
|
15
|
+
account; create a fresh scoped account instead. Scoped-account creation validates
|
|
16
|
+
the referenced ledger owner. `createChild()` inherits the persisted scoped parent
|
|
17
|
+
ledger and owner and rejects conflicting overrides.
|
|
18
|
+
|
|
19
|
+
`JournalEntry` carries opaque `counterpartyKind` / `counterpartyId` values,
|
|
20
|
+
plus an optional `dueDate`. `JournalEntryCollection.getCounterpartyBalances()`
|
|
21
|
+
reports posted AR/AP movements for caller-selected accounts. Aging is an
|
|
22
|
+
open-item report: the original line needs a source reference and due date, and
|
|
23
|
+
the later settlement uses `settlesSourceRef`; do not infer aging from a net
|
|
24
|
+
counterparty balance.
|
|
25
|
+
|
|
26
|
+
Use `postReceivable`, `postPayable`, or `postSettlement` for exact ledger
|
|
27
|
+
events. They take a tenant-scoped idempotency key and create journal plus lines
|
|
28
|
+
under the framework's atomic retry claim. A replay with changed content is
|
|
29
|
+
refused. Refunds and disputes must post a separate compensating entry with a
|
|
30
|
+
new key; posted ledger journals and their lines cannot be edited, deleted, or
|
|
31
|
+
voided. Reverse the debit/credit accounts and set `settlesSourceRef` to the
|
|
32
|
+
original open item when reducing it. Partial reversals use the partial integer
|
|
33
|
+
amount; full reversals use the remaining amount. Commerce/sales owns deciding
|
|
34
|
+
that amount and retaining the external payment/refund event, including disputes
|
|
35
|
+
after payout; ledgers never initiates a money transfer. Retry the same key after
|
|
36
|
+
a crash between external payout completion and ledger posting. A failed ledger
|
|
37
|
+
transaction rolls back the journal, lines and retry receipt together. Manual
|
|
38
|
+
draft edits and posting claim the parent journal revision in their transaction;
|
|
39
|
+
a concurrent loser fails closed and must reload before retrying.
|
|
40
|
+
|
|
41
|
+
Keys are unique within `(tenantId, ledgerId)` and bind all accounting inputs,
|
|
42
|
+
including an explicitly provided date. Omitted dates use the first successful
|
|
43
|
+
posting time. Caller references must uniquely identify each open item within the
|
|
44
|
+
selected account set. Use `normalBalance: 'credit'` for AP aging/balances (AR is
|
|
45
|
+
debit-normal by default). Balance reports use `from`/`to`; aging uses `from`/`asOf`. Choose a `from`
|
|
46
|
+
that includes the original obligation. An out-of-order settlement is included
|
|
47
|
+
once its source exists; future-dated movements are excluded from historical
|
|
48
|
+
reports. Negative balances/credits remain visible in balances, not aging buckets.
|
|
49
|
+
|
|
50
|
+
Ledger currency, owner and balance mode are immutable. Amounts are safe integer
|
|
51
|
+
minor units with zero epsilon; helpers never round, allocate residuals or convert
|
|
52
|
+
currency. Sales owns deterministic allocation rounding and residual assignment;
|
|
53
|
+
commerce owns original gross/tax/fee amounts. Each boundary must pass reconciled
|
|
54
|
+
integers, e.g. a CAD 100.00 worker co-op invoice posts 10000 debit to receivables
|
|
55
|
+
and 10000 credit to project revenue. A CAD 40.00 settlement reverses 4000 of that
|
|
56
|
+
receivable, leaving 6000. Legacy unassigned journals retain their existing void
|
|
57
|
+
and decimal behavior.
|
|
58
|
+
|
|
59
|
+
The transactional posting and subledger suites cover SQLite and PostgreSQL.
|
|
60
|
+
DuckDB cannot provision this package's existing `JournalEntry` cascading foreign
|
|
61
|
+
keys: the framework explicitly rejects DuckDB's unsupported ON UPDATE CASCADE.
|
|
62
|
+
It is not a supported exact-ledger runtime; no relationship is weakened to make
|
|
63
|
+
that dialect appear compatible.
|
|
64
|
+
|
|
5
65
|
## Installation
|
|
6
66
|
|
|
7
67
|
```bash
|
|
@@ -173,3 +233,16 @@ the exported `Account` and `AccountCollection` are unchanged.
|
|
|
173
233
|
|
|
174
234
|
See [`AGENTS.md`](./AGENTS.md) for package architecture, invariants, validation,
|
|
175
235
|
and contributor guidance.
|
|
236
|
+
|
|
237
|
+
Accounting identities are insert-only on their first save: an explicit slug/context
|
|
238
|
+
collision cannot replace an existing ledger, account, journal, or line. Load the
|
|
239
|
+
existing object to update it through its lifecycle guards. This also applies to
|
|
240
|
+
legacy unassigned objects; natural-key replacement is not a supported update path.
|
|
241
|
+
Legacy tenant journals may still use shared global accounts that have no ledger;
|
|
242
|
+
scoped journals require accounts owned by their ledger.
|
|
243
|
+
|
|
244
|
+
A journal chooses its ledger scope at creation. Persisted draft journals cannot
|
|
245
|
+
move between ledgers or change between unassigned and scoped, even when empty.
|
|
246
|
+
Create a new journal for another scope; this prevents an in-flight legacy line
|
|
247
|
+
from entering an exact ledger after its validation. Ordinary same-scope draft
|
|
248
|
+
edits and legacy decimal journals retain their existing behavior.
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { t as Ledger } from "./Ledger-DwxK6NRF.js";
|
|
2
|
+
import { SmrtHierarchical, field, foreignKey, smrt } from "@happyvertical/smrt-core";
|
|
3
|
+
import { TenantScoped, getTenantId, isSuperAdminBypass, isTenancyEnabled, tenantId } from "@happyvertical/smrt-tenancy";
|
|
3
4
|
//#region src/models/Account.ts
|
|
4
5
|
var __defProp = Object.defineProperty;
|
|
5
6
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -22,6 +23,7 @@ var Account = class extends SmrtHierarchical {
|
|
|
22
23
|
name = "";
|
|
23
24
|
description = "";
|
|
24
25
|
type = "asset";
|
|
26
|
+
ledgerId = null;
|
|
25
27
|
active = true;
|
|
26
28
|
/**
|
|
27
29
|
* Extensible metadata
|
|
@@ -29,14 +31,34 @@ var Account = class extends SmrtHierarchical {
|
|
|
29
31
|
metadata = {};
|
|
30
32
|
constructor(options = {}) {
|
|
31
33
|
super(options);
|
|
34
|
+
if (options.tenantId !== void 0) this.tenantId = options.tenantId;
|
|
32
35
|
if (options.number !== void 0) this.number = options.number;
|
|
33
36
|
if (options.name !== void 0) this.name = options.name;
|
|
34
37
|
if (options.description !== void 0) this.description = options.description;
|
|
35
38
|
if (options.type !== void 0) this.type = options.type;
|
|
39
|
+
if (options.ledgerId !== void 0) this.ledgerId = options.ledgerId;
|
|
36
40
|
if (options.parentId !== void 0) this.parentId = options.parentId;
|
|
37
41
|
if (options.active !== void 0) this.active = options.active;
|
|
38
42
|
if (options.metadata !== void 0) this.metadata = options.metadata;
|
|
39
43
|
}
|
|
44
|
+
async validateBeforeSave() {
|
|
45
|
+
await super.validateBeforeSave();
|
|
46
|
+
this.requireInsertOnSave({ preserveDerivedSlug: true });
|
|
47
|
+
if (this.ledgerId) {
|
|
48
|
+
const { LedgerCollection } = await import("../index.js").then((n) => n.t);
|
|
49
|
+
const ledger = await (await LedgerCollection.create(this.options)).get({ id: this.ledgerId }, { cache: false });
|
|
50
|
+
const owner = this.tenantId ?? (isTenancyEnabled() && !isSuperAdminBypass() ? getTenantId() ?? null : null);
|
|
51
|
+
if (!ledger || ledger.tenantId !== owner) throw new Error("Scoped account requires an accessible ledger with the same owner");
|
|
52
|
+
}
|
|
53
|
+
if (this.id) {
|
|
54
|
+
const stored = await this.db.get(this.tableName, { id: this.id });
|
|
55
|
+
if (stored && (stored.ledger_id !== this.ledgerId || stored.ledger_id && (stored.tenant_id !== this.tenantId || stored.type !== this.type))) throw new Error("Ledger account scope, owner and type are immutable");
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
async delete(options = {}) {
|
|
59
|
+
if ((this.id ? await this.db.get(this.tableName, { id: this.id }) : null)?.ledger_id) throw new Error("Ledger accounts cannot be deleted; deactivate them instead");
|
|
60
|
+
await super.delete(options);
|
|
61
|
+
}
|
|
40
62
|
/**
|
|
41
63
|
* Check if this is a top-level account (no parent)
|
|
42
64
|
*/
|
|
@@ -79,7 +101,7 @@ var Account = class extends SmrtHierarchical {
|
|
|
79
101
|
*/
|
|
80
102
|
async getBalance(asOfDate) {
|
|
81
103
|
if (!this.id) return 0;
|
|
82
|
-
const { JournalEntryCollection } = await import("../index.js").then((n) => n.
|
|
104
|
+
const { JournalEntryCollection } = await import("../index.js").then((n) => n.n);
|
|
83
105
|
return await (await JournalEntryCollection.create(this.options)).getAccountBalance(this.id, asOfDate);
|
|
84
106
|
}
|
|
85
107
|
/**
|
|
@@ -87,11 +109,19 @@ var Account = class extends SmrtHierarchical {
|
|
|
87
109
|
*/
|
|
88
110
|
async createChild(options) {
|
|
89
111
|
if (!this.id) throw new Error("Account must be saved before creating children");
|
|
90
|
-
const { AccountCollection } = await import("../index.js").then((n) => n.
|
|
91
|
-
const
|
|
112
|
+
const { AccountCollection } = await import("../index.js").then((n) => n.r);
|
|
113
|
+
const collection = await AccountCollection.create(this.options);
|
|
114
|
+
const parent = await collection.get({ id: this.id }, { cache: false });
|
|
115
|
+
if (!parent) throw new Error("Parent account must be persisted and accessible");
|
|
116
|
+
if (parent.ledgerId && (options.ledgerId !== void 0 && options.ledgerId !== parent.ledgerId || options.tenantId !== void 0 && options.tenantId !== parent.tenantId)) throw new Error("Scoped children must inherit the parent ledger and owner");
|
|
117
|
+
const account = await collection.create({
|
|
92
118
|
...options,
|
|
93
|
-
|
|
94
|
-
|
|
119
|
+
...parent.ledgerId ? {
|
|
120
|
+
ledgerId: parent.ledgerId,
|
|
121
|
+
tenantId: parent.tenantId
|
|
122
|
+
} : {},
|
|
123
|
+
parentId: parent.id,
|
|
124
|
+
type: parent.type
|
|
95
125
|
});
|
|
96
126
|
await account.save();
|
|
97
127
|
return account;
|
|
@@ -103,6 +133,10 @@ __decorateClass([field({ description: "The account number in your chart of accou
|
|
|
103
133
|
__decorateClass([field({ description: "What the account is called." })], Account.prototype, "name", 2);
|
|
104
134
|
__decorateClass([field({ description: "What the account is used for." })], Account.prototype, "description", 2);
|
|
105
135
|
__decorateClass([field({ description: "asset, liability, equity, revenue or expense." })], Account.prototype, "type", 2);
|
|
136
|
+
__decorateClass([field({
|
|
137
|
+
description: "The ledger policy this account belongs to.",
|
|
138
|
+
nullable: true
|
|
139
|
+
}), foreignKey(Ledger)], Account.prototype, "ledgerId", 2);
|
|
106
140
|
__decorateClass([field({ description: "Whether the account is in use; deactivate it instead of deleting it." })], Account.prototype, "active", 2);
|
|
107
141
|
Account = __decorateClass([TenantScoped({ mode: "optional" }), smrt({
|
|
108
142
|
tableName: "ledger_accounts",
|
|
@@ -123,4 +157,4 @@ Account = __decorateClass([TenantScoped({ mode: "optional" }), smrt({
|
|
|
123
157
|
//#endregion
|
|
124
158
|
export { Account as t };
|
|
125
159
|
|
|
126
|
-
//# sourceMappingURL=Account-
|
|
160
|
+
//# sourceMappingURL=Account-IFuMKhPt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Account-IFuMKhPt.js","names":[],"sources":["../../src/models/Account.ts"],"sourcesContent":["/**\n * Account model - Chart of accounts entry\n *\n * Represents a single account in the chart of accounts.\n * The 5 core types: Asset, Liability, Equity, Revenue, Expense\n */\n\nimport {\n field,\n foreignKey,\n SmrtHierarchical,\n smrt,\n} from '@happyvertical/smrt-core';\nimport {\n getTenantId,\n isSuperAdminBypass,\n isTenancyEnabled,\n TenantScoped,\n tenantId,\n} from '@happyvertical/smrt-tenancy';\nimport type { AccountOptions, AccountTreeNode, AccountType } from '../types';\nimport { Ledger } from './Ledger';\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n // Own table, never the derived `accounts`: smrt-messages declares an\n // unrelated `Account` on that table (#3098). Existing `accounts`-hosted\n // ledgers move with `smrt db:migrate-ledger-accounts`.\n tableName: 'ledger_accounts',\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n mcp: { include: ['list', 'get', 'create'] },\n cli: { skipApiCheck: true },\n})\nexport class Account extends SmrtHierarchical { static __smrtPackage__ = \"@happyvertical/smrt-ledgers\";\n /**\n * Tenant ID for multi-tenancy support (nullable for global accounts)\n */\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n /**\n * Account number (e.g., \"1000\", \"5030\")\n */\n @field({ description: 'The account number in your chart of accounts.' })\n number: string = '';\n\n /**\n * Account name (e.g., \"Cash\", \"Coffee Expense\")\n */\n @field({ description: 'What the account is called.' })\n name: string = '';\n\n /**\n * Account description\n */\n @field({ description: 'What the account is used for.' })\n description: string = '';\n\n /**\n * Account type - one of the 5 core types\n */\n @field({ description: 'asset, liability, equity, revenue or expense.' })\n type: AccountType = 'asset';\n\n /** Accounting scope; null is a legacy account usable only by legacy journals. */\n @field({\n description: 'The ledger policy this account belongs to.',\n nullable: true,\n })\n @foreignKey(Ledger)\n ledgerId: string | null = null;\n\n // parentId inherited from SmrtHierarchical (null = top-level)\n\n /**\n * Whether the account is active\n */\n @field({\n description:\n 'Whether the account is in use; deactivate it instead of deleting it.',\n })\n active: boolean = true;\n\n /**\n * Extensible metadata\n */\n metadata: Record<string, unknown> = {};\n\n constructor(options: AccountOptions = {}) {\n super(options);\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.number !== undefined) this.number = options.number;\n if (options.name !== undefined) this.name = options.name;\n if (options.description !== undefined)\n this.description = options.description;\n if (options.type !== undefined) this.type = options.type;\n if (options.ledgerId !== undefined) this.ledgerId = options.ledgerId;\n if (options.parentId !== undefined) this.parentId = options.parentId;\n if (options.active !== undefined) this.active = options.active;\n if (options.metadata !== undefined) this.metadata = options.metadata;\n }\n\n protected async validateBeforeSave(): Promise<void> {\n await super.validateBeforeSave();\n // A fresh accounting identity must never adopt another row by natural key.\n // Core enforces this with INSERT uniqueness, including concurrent callers.\n this.requireInsertOnSave({ preserveDerivedSlug: true });\n if (this.ledgerId) {\n const { LedgerCollection } = await import('../collections/Ledgers');\n const ledger = await (await LedgerCollection.create(this.options)).get(\n { id: this.ledgerId },\n { cache: false },\n );\n // Model validation precedes optional tenancy auto-population.\n const owner =\n this.tenantId ??\n (isTenancyEnabled() && !isSuperAdminBypass()\n ? (getTenantId() ?? null)\n : null);\n if (!ledger || ledger.tenantId !== owner)\n throw new Error(\n 'Scoped account requires an accessible ledger with the same owner',\n );\n }\n if (this.id) {\n const stored = await this.db.get(this.tableName, { id: this.id });\n if (\n stored &&\n (stored.ledger_id !== this.ledgerId ||\n (stored.ledger_id &&\n (stored.tenant_id !== this.tenantId || stored.type !== this.type)))\n )\n throw new Error('Ledger account scope, owner and type are immutable');\n }\n }\n\n async delete(\n options: Parameters<SmrtHierarchical['delete']>[0] = {},\n ): Promise<void> {\n const stored = this.id\n ? await this.db.get(this.tableName, { id: this.id })\n : null;\n if (stored?.ledger_id)\n throw new Error(\n 'Ledger accounts cannot be deleted; deactivate them instead',\n );\n await super.delete(options);\n }\n\n /**\n * Check if this is a top-level account (no parent)\n */\n isTopLevel(): boolean {\n return this.parentId === null;\n }\n\n /**\n * Check if this is a debit-normal account (Asset, Expense)\n * Debit-normal accounts increase with debits\n */\n isDebitNormal(): boolean {\n return this.type === 'asset' || this.type === 'expense';\n }\n\n /**\n * Check if this is a credit-normal account (Liability, Equity, Revenue)\n * Credit-normal accounts increase with credits\n */\n isCreditNormal(): boolean {\n return (\n this.type === 'liability' ||\n this.type === 'equity' ||\n this.type === 'revenue'\n );\n }\n\n // Hierarchy traversal (getParent / getChildren / getAncestors /\n // getDescendants / getHierarchy / moveTo) provided by SmrtHierarchical.\n // Account-specific helpers (getFullPath / getBalance / createChild /\n // toTreeNode) remain below.\n\n /**\n * Get full account path (e.g., \"Assets > Current > Cash\")\n */\n async getFullPath(): Promise<string> {\n const ancestors = await this.getAncestors();\n const names = [...ancestors.map((a) => a.name), this.name];\n return names.join(' > ');\n }\n\n /**\n * Build tree node for this account and its children\n */\n async toTreeNode(): Promise<AccountTreeNode> {\n const children = await this.getChildren();\n const childNodes = await Promise.all(children.map((c) => c.toTreeNode()));\n return {\n account: this,\n children: childNodes,\n };\n }\n\n /**\n * Get the current balance of this account\n */\n async getBalance(asOfDate?: Date): Promise<number> {\n if (!this.id) return 0;\n const { JournalEntryCollection } = await import(\n '../collections/JournalEntries'\n );\n const collection = await JournalEntryCollection.create(this.options);\n return await collection.getAccountBalance(this.id, asOfDate);\n }\n\n /**\n * Create a sub-account under this account\n */\n async createChild(\n options: Omit<AccountOptions, 'parentId' | 'type'>,\n ): Promise<Account> {\n if (!this.id) {\n throw new Error('Account must be saved before creating children');\n }\n const { AccountCollection } = await import('../collections/Accounts');\n const collection = await AccountCollection.create(this.options);\n const parent = await collection.get({ id: this.id }, { cache: false });\n if (!parent)\n throw new Error('Parent account must be persisted and accessible');\n if (\n parent.ledgerId &&\n ((options.ledgerId !== undefined &&\n options.ledgerId !== parent.ledgerId) ||\n (options.tenantId !== undefined &&\n options.tenantId !== parent.tenantId))\n )\n throw new Error(\n 'Scoped children must inherit the parent ledger and owner',\n );\n const account = await collection.create({\n ...options,\n ...(parent.ledgerId\n ? { ledgerId: parent.ledgerId, tenantId: parent.tenantId }\n : {}),\n parentId: parent.id,\n type: parent.type, // Inherit persisted type from parent\n });\n await account.save();\n return account;\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { SmrtObject, field, smrt } from "@happyvertical/smrt-core";
|
|
2
|
+
import { TenantScoped, tenantId } from "@happyvertical/smrt-tenancy";
|
|
3
|
+
//#region src/models/Ledger.ts
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
configurable: true,
|
|
9
|
+
writable: true,
|
|
10
|
+
value
|
|
11
|
+
}) : obj[key] = value;
|
|
12
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
13
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
14
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
15
|
+
if (kind && result) __defProp(target, key, result);
|
|
16
|
+
return result;
|
|
17
|
+
};
|
|
18
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
19
|
+
var Ledger = class extends SmrtObject {
|
|
20
|
+
tenantId = null;
|
|
21
|
+
name = "";
|
|
22
|
+
currency = "USD";
|
|
23
|
+
balanceMode = "tolerant";
|
|
24
|
+
constructor(options = {}) {
|
|
25
|
+
super(options);
|
|
26
|
+
if (options.tenantId !== void 0) this.tenantId = options.tenantId;
|
|
27
|
+
if (options.name !== void 0) this.name = options.name;
|
|
28
|
+
if (options.currency !== void 0) this.currency = options.currency;
|
|
29
|
+
if (options.balanceMode !== void 0) this.balanceMode = options.balanceMode;
|
|
30
|
+
}
|
|
31
|
+
async delete() {
|
|
32
|
+
throw new Error("Ledgers cannot be deleted");
|
|
33
|
+
}
|
|
34
|
+
async validateBeforeSave() {
|
|
35
|
+
await super.validateBeforeSave();
|
|
36
|
+
this.requireInsertOnSave({ preserveDerivedSlug: true });
|
|
37
|
+
if (!["tolerant", "exact-integer"].includes(this.balanceMode)) throw new Error("Unknown ledger balance mode");
|
|
38
|
+
if (this.id) {
|
|
39
|
+
const stored = await this.db.get(this.tableName, { id: this.id });
|
|
40
|
+
if (stored && (stored.currency !== this.currency || stored.balance_mode !== this.balanceMode || stored.tenant_id !== this.tenantId)) throw new Error("Ledger currency, balance mode and owner are immutable");
|
|
41
|
+
}
|
|
42
|
+
if (!this.name.trim()) throw new Error("Ledger name is required");
|
|
43
|
+
if (!/^[A-Z]{3}$/.test(this.currency)) throw new Error("Ledger currency must be an uppercase ISO 4217 code");
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
__publicField(Ledger, "__smrtPackage__", "@happyvertical/smrt-ledgers");
|
|
47
|
+
__decorateClass([tenantId({ nullable: true })], Ledger.prototype, "tenantId", 2);
|
|
48
|
+
__decorateClass([field({ description: "The accounting scope name." })], Ledger.prototype, "name", 2);
|
|
49
|
+
__decorateClass([field({ description: "ISO 4217 currency used by this ledger." })], Ledger.prototype, "currency", 2);
|
|
50
|
+
__decorateClass([field({ description: "tolerant accepts decimal units; exact requires integer minor units." })], Ledger.prototype, "balanceMode", 2);
|
|
51
|
+
Ledger = __decorateClass([TenantScoped({ mode: "optional" }), smrt({
|
|
52
|
+
api: { include: [
|
|
53
|
+
"list",
|
|
54
|
+
"get",
|
|
55
|
+
"create",
|
|
56
|
+
"update"
|
|
57
|
+
] },
|
|
58
|
+
mcp: { include: [
|
|
59
|
+
"list",
|
|
60
|
+
"get",
|
|
61
|
+
"create"
|
|
62
|
+
] },
|
|
63
|
+
cli: { skipApiCheck: true }
|
|
64
|
+
})], Ledger);
|
|
65
|
+
//#endregion
|
|
66
|
+
export { Ledger as t };
|
|
67
|
+
|
|
68
|
+
//# sourceMappingURL=Ledger-DwxK6NRF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Ledger-DwxK6NRF.js","names":[],"sources":["../../src/models/Ledger.ts"],"sourcesContent":["import { field, SmrtObject, smrt } from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport type { LedgerOptions } from '../types';\n\n/**\n * A named accounting scope. Exact ledgers store one currency's minor units and\n * reject fractional entries; legacy journals without a ledger retain the\n * tolerant balance rule for backwards compatibility.\n */\n@TenantScoped({ mode: 'optional' })\n@smrt({\n api: { include: ['list', 'get', 'create', 'update'] },\n mcp: { include: ['list', 'get', 'create'] },\n cli: { skipApiCheck: true },\n})\nexport class Ledger extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-ledgers\";\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n @field({ description: 'The accounting scope name.' })\n name = '';\n\n /** ISO 4217 currency for this ledger's entries. */\n @field({ description: 'ISO 4217 currency used by this ledger.' })\n currency = 'USD';\n\n @field({\n description:\n 'tolerant accepts decimal units; exact requires integer minor units.',\n })\n balanceMode: 'tolerant' | 'exact-integer' = 'tolerant';\n\n constructor(options: LedgerOptions = {}) {\n super(options);\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.name !== undefined) this.name = options.name;\n if (options.currency !== undefined) this.currency = options.currency;\n if (options.balanceMode !== undefined)\n this.balanceMode = options.balanceMode;\n }\n\n async delete(): Promise<void> {\n throw new Error('Ledgers cannot be deleted');\n }\n\n protected async validateBeforeSave(): Promise<void> {\n await super.validateBeforeSave();\n // A fresh accounting identity must never adopt another row by natural key.\n // Core enforces this with INSERT uniqueness, including concurrent callers.\n this.requireInsertOnSave({ preserveDerivedSlug: true });\n if (!['tolerant', 'exact-integer'].includes(this.balanceMode))\n throw new Error('Unknown ledger balance mode');\n if (this.id) {\n const stored = await this.db.get(this.tableName, { id: this.id });\n if (\n stored &&\n (stored.currency !== this.currency ||\n stored.balance_mode !== this.balanceMode ||\n stored.tenant_id !== this.tenantId)\n )\n throw new Error(\n 'Ledger currency, balance mode and owner are immutable',\n );\n }\n if (!this.name.trim()) throw new Error('Ledger name is required');\n if (!/^[A-Z]{3}$/.test(this.currency))\n throw new Error('Ledger currency must be an uppercase ISO 4217 code');\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAeO,IAAM,SAAN,cAAqB,WAAW;CAErC,WAA0B;CAG1B,OAAO;CAIP,WAAW;CAMX,cAA4C;CAE5C,YAAY,UAAyB,CAAC,GAAG;EACvC,MAAM,OAAO;EACb,IAAI,QAAQ,aAAa,KAAA,GAAW,KAAK,WAAW,QAAQ;EAC5D,IAAI,QAAQ,SAAS,KAAA,GAAW,KAAK,OAAO,QAAQ;EACpD,IAAI,QAAQ,aAAa,KAAA,GAAW,KAAK,WAAW,QAAQ;EAC5D,IAAI,QAAQ,gBAAgB,KAAA,GAC1B,KAAK,cAAc,QAAQ;CAC/B;CAEA,MAAM,SAAwB;EAC5B,MAAM,IAAI,MAAM,2BAA2B;CAC7C;CAEA,MAAgB,qBAAoC;EAClD,MAAM,MAAM,mBAAmB;EAG/B,KAAK,oBAAoB,EAAE,qBAAqB,KAAK,CAAC;EACtD,IAAI,CAAC,CAAC,YAAY,eAAe,CAAA,CAAE,SAAS,KAAK,WAAW,GAC1D,MAAM,IAAI,MAAM,6BAA6B;EAC/C,IAAI,KAAK,IAAI;GACX,MAAM,SAAS,MAAM,KAAK,GAAG,IAAI,KAAK,WAAW,EAAE,IAAI,KAAK,GAAG,CAAC;GAChE,IACE,WACC,OAAO,aAAa,KAAK,YACxB,OAAO,iBAAiB,KAAK,eAC7B,OAAO,cAAc,KAAK,WAE5B,MAAM,IAAI,MACR,uDACF;EACJ;EACA,IAAI,CAAC,KAAK,KAAK,KAAK,GAAG,MAAM,IAAI,MAAM,yBAAyB;EAChE,IAAI,CAAC,aAAa,KAAK,KAAK,QAAQ,GAClC,MAAM,IAAI,MAAM,oDAAoD;CACxE;AACF;AArDyC,cAA5B,QAAmC,mBAAkB,6BAAA;AAEhE,gBAAA,CADC,SAAS,EAAE,UAAU,KAAK,CAAC,CAAA,GADjB,OAEX,WAAA,YAAA,CAAA;AAGA,gBAAA,CADC,MAAM,EAAE,aAAa,6BAA6B,CAAC,CAAA,GAJzC,OAKX,WAAA,QAAA,CAAA;AAIA,gBAAA,CADC,MAAM,EAAE,aAAa,yCAAyC,CAAC,CAAA,GARrD,OASX,WAAA,YAAA,CAAA;AAMA,gBAAA,CAJC,MAAM,EACL,aACE,sEACJ,CAAC,CAAA,GAdU,OAeX,WAAA,eAAA,CAAA;AAfW,SAAN,gBAAA,CANN,aAAa,EAAE,MAAM,WAAW,CAAC,GACjC,KAAK;CACJ,KAAK,EAAE,SAAS;EAAC;EAAQ;EAAO;EAAU;CAAQ,EAAE;CACpD,KAAK,EAAE,SAAS;EAAC;EAAQ;EAAO;CAAQ,EAAE;CAC1C,KAAK,EAAE,cAAc,KAAK;AAC5B,CAAC,CAAA,GACY,MAAA"}
|
|
@@ -29,6 +29,24 @@ export interface PostedJournalMovementOptions {
|
|
|
29
29
|
from: Date;
|
|
30
30
|
to: Date;
|
|
31
31
|
currency: string;
|
|
32
|
+
/** Select credit-normal AP balances; default is debit-normal AR. */
|
|
33
|
+
normalBalance?: 'debit' | 'credit';
|
|
34
|
+
}
|
|
35
|
+
export interface CounterpartyBalance {
|
|
36
|
+
counterpartyKind: string;
|
|
37
|
+
counterpartyId: string;
|
|
38
|
+
currency: string;
|
|
39
|
+
/** Debit minus credit for asset AR accounts; callers choose the account set. */
|
|
40
|
+
balance: number;
|
|
41
|
+
}
|
|
42
|
+
export interface CounterpartyAgingRow extends CounterpartyBalance {
|
|
43
|
+
sourceRef: string;
|
|
44
|
+
dueDate: Date;
|
|
45
|
+
current: number;
|
|
46
|
+
days1To30: number;
|
|
47
|
+
days31To60: number;
|
|
48
|
+
days61To90: number;
|
|
49
|
+
daysOver90: number;
|
|
32
50
|
}
|
|
33
51
|
export declare class JournalEntryCollection extends SmrtCollection<JournalEntry> {
|
|
34
52
|
static readonly _itemClass: typeof JournalEntry;
|
|
@@ -46,6 +64,14 @@ export declare class JournalEntryCollection extends SmrtCollection<JournalEntry>
|
|
|
46
64
|
* @returns Array of entries
|
|
47
65
|
*/
|
|
48
66
|
findByAccount(accountId: string): Promise<JournalEntry[]>;
|
|
67
|
+
/** Posted AR/AP net balances by opaque counterparty for selected accounts. */
|
|
68
|
+
getCounterpartyBalances(options: PostedJournalMovementOptions): Promise<CounterpartyBalance[]>;
|
|
69
|
+
/**
|
|
70
|
+
* Open-item aging. An invoice/allocation line needs a dueDate and sourceRef;
|
|
71
|
+
* a settlement line names that source in settlesSourceRef. This avoids
|
|
72
|
+
* pretending that net counterparty movements are aging.
|
|
73
|
+
*/
|
|
74
|
+
getCounterpartyAging(options: PostedJournalMovementOptions, asOf: Date): Promise<CounterpartyAgingRow[]>;
|
|
49
75
|
/**
|
|
50
76
|
* Get account balance
|
|
51
77
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JournalEntries.d.ts","sourceRoot":"","sources":["../../src/collections/JournalEntries.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"JournalEntries.d.ts","sourceRoot":"","sources":["../../src/collections/JournalEntries.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Journals.d.ts","sourceRoot":"","sources":["../../src/collections/Journals.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE1D,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAmB,CAAC;AAC5C,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,aAAa,EACnB,MAAM,aAAU,CAAC;AAElB,qBAAa,iBAAkB,SAAQ,cAAc,CAAC,OAAO,CAAC;IAC5D,MAAM,CAAC,QAAQ,CAAC,UAAU,iBAAW;IAErC;;;;;OAKG;IACH,OAAO,CAAC,qBAAqB;IAM7B;;;;;OAKG;IACG,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAQ3D;;;;;;OAMG;IACG,eAAe,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAUjE;;;;;OAKG;IACG,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAO5D;;;;;OAKG;IACG,YAAY,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAO7D;;;;OAIG;IACG,UAAU,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAItC;;;;OAIG;IACG,UAAU,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAItC;;;;;OAKG;IACG,iBAAiB,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"Journals.d.ts","sourceRoot":"","sources":["../../src/collections/Journals.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE1D,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAmB,CAAC;AAC5C,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,aAAa,EACnB,MAAM,aAAU,CAAC;AAElB,qBAAa,iBAAkB,SAAQ,cAAc,CAAC,OAAO,CAAC;IAC5D,MAAM,CAAC,QAAQ,CAAC,UAAU,iBAAW;IAErC;;;;;OAKG;IACH,OAAO,CAAC,qBAAqB;IAM7B;;;;;OAKG;IACG,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAQ3D;;;;;;OAMG;IACG,eAAe,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAUjE;;;;;OAKG;IACG,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAO5D;;;;;OAKG;IACG,YAAY,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAO7D;;;;OAIG;IACG,UAAU,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAItC;;;;OAIG;IACG,UAAU,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAItC;;;;;OAKG;IACG,iBAAiB,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC;IA4ClE;;;;;OAKG;IACG,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAS/C;;;;;;OAMG;IACG,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAS/D;;;;;OAKG;IACG,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAO5D;;;;;;OAMG;IACG,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAUlE;;;;;OAKG;IACG,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAIxD;;;;;;;OAOG;IACG,UAAU,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAItC;;;;;;;;OAQG;IACG,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;CAG5D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Ledgers.d.ts","sourceRoot":"","sources":["../../src/collections/Ledgers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAkB,CAAC;AAE1C,qBAAa,gBAAiB,SAAQ,cAAc,CAAC,MAAM,CAAC;IAC1D,MAAM,CAAC,QAAQ,CAAC,UAAU,gBAAU;CACrC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/collections/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAY,CAAC;AAC/C,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAkB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/collections/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAY,CAAC;AAC/C,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAkB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAY,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAW,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -62,13 +62,16 @@
|
|
|
62
62
|
import './__smrt-register__.js';
|
|
63
63
|
import './prompts.js';
|
|
64
64
|
export { AccountCollection } from "./collections/Accounts.js";
|
|
65
|
-
export { JournalEntryCollection, type PostedJournalMovement, type PostedJournalMovementOptions, } from "./collections/JournalEntries.js";
|
|
65
|
+
export { type CounterpartyAgingRow, type CounterpartyBalance, JournalEntryCollection, type PostedJournalMovement, type PostedJournalMovementOptions, } from "./collections/JournalEntries.js";
|
|
66
66
|
export { JournalCollection } from "./collections/Journals.js";
|
|
67
|
+
export { LedgerCollection } from "./collections/Ledgers.js";
|
|
67
68
|
export { LEDGER_ACCOUNTS_TABLE, LEDGER_ACCOUNTS_TABLE_MOVE, LEGACY_ACCOUNTS_TABLE, LedgerAccountsTableMoveError, type LedgerAccountsTableMoveOptions, type LedgerAccountsTableMovePlan, type LedgerAccountsTableMoveResult, migrateLedgerAccountsTable, planLedgerAccountsTableMove, } from "./migrations/ledger-accounts-table.js";
|
|
68
69
|
export { Account } from "./models/Account.js";
|
|
69
70
|
export { Journal } from "./models/Journal.js";
|
|
70
71
|
export { JournalEntry } from "./models/JournalEntry.js";
|
|
72
|
+
export { Ledger } from "./models/Ledger.js";
|
|
73
|
+
export { type Counterparty, type LedgerPostingInput, postLedgerEntry, postPayable, postReceivable, postSettlement, } from "./postings.js";
|
|
71
74
|
export { promptMessageOptions, smrtLedgersJournalSummarizePrompt, } from "./prompts.js";
|
|
72
75
|
export { BookkeepingRecipe } from "./recipes.js";
|
|
73
|
-
export type { AccountOptions, AccountTree, AccountTreeNode, AccountType, CreateJournalData, JournalEntryData, JournalEntryOptions, JournalOptions, JournalStatus, TrialBalanceRow, } from "./types.js";
|
|
76
|
+
export type { AccountOptions, AccountTree, AccountTreeNode, AccountType, CreateJournalData, JournalEntryData, JournalEntryOptions, JournalOptions, JournalStatus, LedgerBalanceMode, LedgerOptions, TrialBalanceRow, } from "./types.js";
|
|
74
77
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4DG;AAKH,OAAO,wBAAwB,CAAC;AAGhC,OAAO,cAAc,CAAC;AAGtB,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAAwB,CAAC;AAC3D,OAAO,EACL,sBAAsB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,4BAA4B,GAClC,MAAM,iCAA8B,CAAC;AACtC,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4DG;AAKH,OAAO,wBAAwB,CAAC;AAGhC,OAAO,cAAc,CAAC;AAGtB,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAAwB,CAAC;AAC3D,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,sBAAsB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,4BAA4B,GAClC,MAAM,iCAA8B,CAAC;AACtC,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAAwB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAAuB,CAAC;AAEzD,OAAO,EACL,qBAAqB,EACrB,0BAA0B,EAC1B,qBAAqB,EACrB,4BAA4B,EAC5B,KAAK,8BAA8B,EACnC,KAAK,2BAA2B,EAChC,KAAK,6BAA6B,EAClC,0BAA0B,EAC1B,2BAA2B,GAC5B,MAAM,uCAAoC,CAAC;AAE5C,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAkB,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAkB,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,0BAAuB,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAiB,CAAC;AACzC,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,kBAAkB,EACvB,eAAe,EACf,WAAW,EACX,cAAc,EACd,cAAc,GACf,MAAM,eAAY,CAAC;AAGpB,OAAO,EACL,oBAAoB,EACpB,iCAAiC,GAClC,MAAM,cAAW,CAAC;AACnB,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAW,CAAC;AAE9C,YAAY,EACV,cAAc,EACd,WAAW,EACX,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,gBAAgB,EAChB,mBAAmB,EACnB,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,aAAa,EACb,eAAe,GAChB,MAAM,YAAS,CAAC"}
|