Pack reference
A pack adds declarations to an existing model. It can contribute preconditions, entities, accounts, phases, flows, agreements, events, options, components, calculations, reportGroups, and metrics. It cannot replace the model's name, currency, or timeline.
import { cashflow, currencies, defineModel, definePack, entity, extractPacks, inflow, periods, schedule } from "deccf";
const property = entity.asset();
const rent = cashflow({ owner: property, direction: inflow, schedule: schedule.monthly(), amount: 1_000 });
const model = defineModel({
name: "tax-rule-example",
currency: currencies.SEK,
timeline: periods.monthly({ from: "2026-01", count: 12 }),
entities: { property },
flows: { rent },
});
const pack = definePack({
name: "tax-rule",
version: "1.2.0",
extract: ({ model, api }) => ({
preconditions: { taxRate: api.input.rate(0.2) },
}),
});
const extractedModel = extractPacks(model, [pack]);
return extractedModel;name must match ^[a-z][a-z0-9-]*$. version uses semantic-version syntax. extract must be synchronous and return an object whose values are declaration maps. A pack can contribute metric callbacks in metrics; it can also inspect existing model declarations and capture their references in those callbacks. extractPacks sorts packs by name and version, rejects duplicate pack names and declaration-key conflicts, and creates a new frozen model.
To check determinism, extract is called twice with the same frozen model and API, then the contributions are compared. A source scan rejects common clock, randomness, and external-I/O APIs. This is a limited determinism check, not an isolated or secure JavaScript sandbox.
Domain packs can live under domainpacks/. They can provide ready references and metadata without being definePack contributions. For example, account plans provide categories with account codes and can be used alongside tax-base mappings. Use definePack and extractPacks when a pack translates a domain abstraction into model declarations.
Plan-backed accounts used by built-in domain packs are registered during compilation. A model author only needs to list accounts explicitly when setting an opening balance or chosen account name, or when a callback refers to an account that is otherwise not visible in the declarations.
The Business Metrics pack requires the Business account plan. It uses account-plan tags and debit-minus-credit postings to publish company KPIs, including the 22 measures mirrored from the supplied KPI calculator and debt service.
The Business base forecast pack uses the Business account plan. businessForecast() creates a whole-model starting point with straightforward, growth, downside, historical, automatic, and industry templates. Industry forecasts accept an SNI 2025 main-group input or infer a broad profile from account history. The result includes a text metric explaining the method and its selection reason. The pack also exports composable flow-group sections, function-based formulas, and opening-asset depreciation methods.
The Financial formulas pack groups reusable rate, growth, savings-target, valuation, business, working-capital, usage, accounting, date and report formulas. It returns ordinary functions and metric declarations that fit existing model slots; it does not introduce new engine concepts.
The Loans pack composes recurring loan fields, calculations and cashflows. It supports fixed, interest-only, bullet and annuity payment rules, additional drawdowns, rate curves and limited payments. It requires Financial formulas.
The Savings pack composes savings balances with deposits, returns, fees, capped withdrawals and separately reported shortfalls. It requires Financial formulas.
The Household pack requires the Personal account plan. Selecting the module makes its constructors available; householdBudget({ household, members, funding? }) explicitly creates the selected household's monthly budget component. Optional funding composes the shared funding() allocation and transfer primitives.
The SIE import pack requires the Business account plan. Its sieStatement({ owner, sieContent }) declaration reads the latest period from a textfile input and posts one balanced statement at the period end. Accounts outside the plan retain their original numbers and inherit a parent title in parentheses. A previous-year result demonstrably missing from opening equity is imported on 2098, separately from the current result handled by bookClosing().