@trajectonomics/sim 0.0.0-stage → 0.1.0-alpha.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/LICENSE +21 -0
- package/README.md +45 -2
- package/dist/index.cjs +1241 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +160 -0
- package/dist/index.d.mts +160 -0
- package/dist/index.mjs +1238 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +65 -5
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["DATE_SHAPE","MONTH_DAYS","isLeapYear","daysInMonth","shape"],"sources":["../src/vocab.ts","../src/check/date.ts","../src/check/shape.ts","../src/check/scalars.ts","../src/check/accounts.ts","../src/check/refs.ts","../src/check/baseline.ts","../src/check/guard.ts","../src/check/cashflow.ts","../src/check/flow-shape.ts","../src/check/flows.ts","../src/check/scenario.ts","../src/check/timeline.ts","../src/check/index.ts","../src/check/codes.ts","../src/output/opening.ts","../src/calendar/civil.ts","../src/calendar/arith.ts","../src/output/periods.ts","../src/engine/overflow.ts","../src/output/rollups.ts","../src/calendar/rows.ts","../src/output/row-dates.ts","../src/calendar/counted.ts","../src/money/pow.ts","../src/money/root.ts","../src/money/factor.ts","../src/money/round.ts","../src/money/growth.ts","../src/output/real.ts","../src/output/rows.ts","../src/output/rules.ts","../src/output/build.ts","../src/engine/dates.ts","../src/calendar/occurrence.ts","../src/engine/order.ts","../src/engine/events.ts","../src/engine/amount.ts","../src/engine/aggregate.ts","../src/engine/min.ts","../src/engine/value.ts","../src/engine/mutate.ts","../src/engine/contributions.ts","../src/engine/surplus.ts","../src/engine/withdraw.ts","../src/engine/occurrence.ts","../src/engine/snapshot.ts","../src/engine/run-step.ts","../src/engine/state.ts","../src/engine/run.ts","../src/engine/project.ts"],"sourcesContent":["export const SCHEMA_VERSION: 1 = 1\n\nexport const ACCOUNT_KINDS = [\"asset\", \"liability\"] as const\nexport const FLOW_KINDS = [\"income\", \"expense\", \"contribution\"] as const\nexport const FREQUENCIES = [\n\t\"once\",\n\t\"daily\",\n\t\"weekly\",\n\t\"biweekly\",\n\t\"monthly\",\n\t\"quarterly\",\n\t\"annual\",\n] as const\nexport const RESOLUTIONS = [\"day\", \"month\"] as const\n","const DATE_SHAPE = /^(\\d{4})-(\\d{2})-(\\d{2})$/\nconst MONTH_DAYS = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]\n\nfunction isLeapYear(year: number): boolean {\n\treturn (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0\n}\n\nfunction daysInMonth(year: number, month: number): number {\n\treturn month === 2 && isLeapYear(year) ? 29 : (MONTH_DAYS[month - 1] ?? 0)\n}\n\n/** Pure calendar arithmetic (no `Date`): a real `YYYY-MM-DD` date in years 0001-9998 (so every computed anniversary stays representable). */\nexport function isValidDate(value: unknown): value is string {\n\tif (typeof value !== \"string\") return false\n\tconst match = DATE_SHAPE.exec(value)\n\tif (!match) return false\n\tconst [year, month, day] = [Number(match[1]), Number(match[2]), Number(match[3])]\n\treturn year >= 1 && year <= 9998 && day >= 1 && day <= daysInMonth(year, month)\n}\n","import type { Check, Emit, Path } from \"./codes\"\n\nexport interface Field {\n\treadonly required: boolean\n\treadonly check: Check\n}\nexport type Shape = Readonly<Record<string, Field>>\n\nexport const req = (check: Check): Field => ({ required: true, check })\nexport const opt = (check: Check): Field => ({ required: false, check })\n\n/** Accepts any value: `schemaVersion` is validated up front by `check()`, not per object. */\nexport const anyVersion: Check = () => {}\n\nexport function isRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value)\n}\n\nfunction checkField(\n\tvalue: Readonly<Record<string, unknown>>,\n\tpath: Path,\n\tkey: string,\n\tfield: Field,\n\temit: Emit,\n): void {\n\tif (Object.hasOwn(value, key)) field.check(value[key], [...path, key], emit)\n\telse if (field.required) emit(\"MISSING_KEY\", [...path, key])\n}\n\n/** Validates an object against `shape`: not-an-object, unknown keys, missing keys, field checks. */\nexport function checkShape(\n\tvalue: unknown,\n\tpath: Path,\n\tshape: Shape,\n\temit: Emit,\n): Readonly<Record<string, unknown>> | undefined {\n\tif (!isRecord(value)) {\n\t\temit(\"NOT_AN_OBJECT\", path)\n\t\treturn undefined\n\t}\n\tfor (const key of Object.keys(value)) {\n\t\tif (!Object.hasOwn(shape, key)) emit(\"UNKNOWN_KEY\", [...path, key])\n\t}\n\tfor (const [key, field] of Object.entries(shape)) checkField(value, path, key, field, emit)\n\treturn value\n}\n\n/**\n * Builds a check that validates every element of an array with `item`. Walks every index, so a\n * sparse-array hole reaches `item` as `undefined` instead of being skipped.\n */\nexport function list(item: Check): Check {\n\treturn (value, path, emit) => {\n\t\tif (!Array.isArray(value)) return emit(\"NOT_AN_ARRAY\", path)\n\t\tfor (let index = 0; index < value.length; index++) item(value[index], [...path, index], emit)\n\t}\n}\n\nfunction scanDuplicates(\n\titems: unknown,\n\tpath: Path,\n\tsuffix: Path,\n\tidOf: (item: unknown) => unknown,\n\temit: Emit,\n): void {\n\tif (!Array.isArray(items)) return\n\tconst seen = new Set<string>()\n\tfor (let index = 0; index < items.length; index++) {\n\t\tconst id = idOf(items[index])\n\t\tif (typeof id !== \"string\" || id === \"\") continue\n\t\tif (seen.has(id)) emit(\"DUPLICATE_ID\", [...path, index, ...suffix])\n\t\tseen.add(id)\n\t}\n}\n\n/**\n * Emits `DUPLICATE_ID` at the second and later occurrences of a string `key` in `items`.\n * Empty ids are left to `EMPTY_STRING` and never count as duplicates.\n */\nexport function checkUnique(items: unknown, path: Path, key: string, emit: Emit): void {\n\tscanDuplicates(items, path, [key], (item) => (isRecord(item) ? item[key] : undefined), emit)\n}\n\n/** Like `checkUnique`, for an array of plain string ids (e.g. `cashflow.withdraw`). */\nexport function checkUniqueValues(items: unknown, path: Path, emit: Emit): void {\n\tscanDuplicates(items, path, [], (item) => item, emit)\n}\n","import type { Check, ErrorCode } from \"./codes\"\nimport { isValidDate } from \"./date\"\nimport { checkShape, isRecord, req } from \"./shape\"\n\nexport const str: Check = (value, path, emit) => {\n\tif (typeof value !== \"string\") emit(\"WRONG_TYPE\", path)\n\telse if (value === \"\") emit(\"EMPTY_STRING\", path)\n}\n\nexport const bool: Check = (value, path, emit) => {\n\tif (typeof value !== \"boolean\") emit(\"WRONG_TYPE\", path)\n}\n\n/** Any safe integer (negative allowed): basis-point rates. */\nexport const safeInt: Check = (value, path, emit) => {\n\tif (!Number.isSafeInteger(value)) emit(\"NOT_SAFE_INTEGER\", path)\n}\n\n/** A safe-integer rate above -10000 bps, so a positive growth factor always exists. */\nexport const rate: Check = (value, path, emit) => {\n\tif (!Number.isSafeInteger(value)) return emit(\"NOT_SAFE_INTEGER\", path)\n\tif ((value as number) <= -10000) emit(\"RATE_OUT_OF_RANGE\", path)\n}\n\n/** Non-negative safe integer minor units. */\nexport const amount: Check = (value, path, emit) => {\n\tif (!Number.isSafeInteger(value)) emit(\"NOT_SAFE_INTEGER\", path)\n\telse if ((value as number) < 0) emit(\"NEGATIVE_AMOUNT\", path)\n}\n\nexport const date: Check = (value, path, emit) => {\n\tif (!isValidDate(value)) emit(\"INVALID_DATE\", path)\n}\n\nexport function oneOf(allowed: readonly string[], code: ErrorCode): Check {\n\treturn (value, path, emit) => {\n\t\tif (typeof value !== \"string\" || !allowed.includes(value)) emit(code, path)\n\t}\n}\n\nexport const growth: Check = (value, path, emit) => {\n\tif (value === \"inflation\") return\n\tif (!isRecord(value)) return emit(\"INVALID_GROWTH\", path)\n\tcheckShape(value, path, { bps: req(rate) }, emit)\n}\n","import { ACCOUNT_KINDS } from \"../vocab\"\nimport type { AccountIndex, Check, Emit, Path } from \"./codes\"\nimport { date, oneOf, rate, str } from \"./scalars\"\nimport { checkShape, checkUnique, isRecord, list, opt, req } from \"./shape\"\n\nconst shape = {\n\tid: req(str),\n\tkind: req(oneOf(ACCOUNT_KINDS, \"INVALID_KIND\")),\n\trate: req(rate),\n\tlockedUntil: opt(date),\n}\n\nconst account: Check = (value, path, emit) => {\n\tconst checked = checkShape(value, path, shape, emit)\n\tif (checked?.[\"kind\"] === \"liability\" && Object.hasOwn(checked, \"lockedUntil\")) {\n\t\temit(\"LIABILITY_MISUSE\", [...path, \"lockedUntil\"])\n\t}\n}\n\nexport function checkAccounts(value: unknown, path: Path, emit: Emit): void {\n\tlist(account)(value, path, emit)\n\tcheckUnique(value, path, \"id\", emit)\n}\n\n/**\n * Declared account ids (first declaration wins) mapped to their raw `kind`. `undefined` when\n * `accounts` is not an array, so reference checks are skipped rather than flooding the output.\n */\nexport function indexAccounts(accounts: unknown): AccountIndex | undefined {\n\tif (!Array.isArray(accounts)) return undefined\n\tconst index = new Map<string, unknown>()\n\tfor (let i = 0; i < accounts.length; i++) {\n\t\tconst item: unknown = accounts[i]\n\t\tif (isRecord(item) && typeof item[\"id\"] === \"string\" && !index.has(item[\"id\"])) {\n\t\t\tindex.set(item[\"id\"], item[\"kind\"])\n\t\t}\n\t}\n\treturn index\n}\n","import type { AccountIndex, Check } from \"./codes\"\nimport { str } from \"./scalars\"\n\n/** Account id that must be declared in `scenario.accounts` (skipped when unknown). */\nexport function accountRef(accounts: AccountIndex | undefined): Check {\n\treturn (value, path, emit) => {\n\t\tstr(value, path, emit)\n\t\tif (accounts && typeof value === \"string\" && !accounts.has(value)) {\n\t\t\temit(\"UNKNOWN_ACCOUNT\", path)\n\t\t}\n\t}\n}\n\n/** Like `accountRef`, but liabilities are rejected (surplus targets and withdrawal sources). */\nexport function spendableRef(accounts: AccountIndex | undefined): Check {\n\tconst ref = accountRef(accounts)\n\treturn (value, path, emit) => {\n\t\tref(value, path, emit)\n\t\tif (typeof value === \"string\" && accounts?.get(value) === \"liability\") {\n\t\t\temit(\"LIABILITY_MISUSE\", path)\n\t\t}\n\t}\n}\n\n/** Baseline balance account: must have a rule in `scenario.accounts`. */\nexport function balanceRef(accounts: AccountIndex | undefined): Check {\n\treturn (value, path, emit) => {\n\t\tstr(value, path, emit)\n\t\tif (accounts && typeof value === \"string\" && !accounts.has(value)) {\n\t\t\temit(\"UNDECLARED_BALANCE_ACCOUNT\", path)\n\t\t}\n\t}\n}\n","import type { AccountIndex, Check, Emit, Path } from \"./codes\"\nimport { balanceRef } from \"./refs\"\nimport { amount } from \"./scalars\"\nimport { anyVersion, checkShape, checkUnique, list, req } from \"./shape\"\n\nexport function checkBaseline(\n\tvalue: unknown,\n\tpath: Path,\n\taccounts: AccountIndex | undefined,\n\temit: Emit,\n): void {\n\tconst balance: Check = (item, at, e) =>\n\t\tvoid checkShape(item, at, { account: req(balanceRef(accounts)), amount: req(amount) }, e)\n\tconst shape = { schemaVersion: req(anyVersion), balances: req(list(balance)) }\n\tconst baseline = checkShape(value, path, shape, emit)\n\tcheckUnique(baseline?.[\"balances\"], [...path, \"balances\"], \"account\", emit)\n}\n","import type { Emit } from \"./codes\"\n\nexport type Root = \"baseline\" | \"scenario\" | \"timeline\"\n\n/**\n * Runs `run`, turning an exception (a throwing getter, a revoked Proxy) into one `NOT_AN_OBJECT`\n * problem at the input's root, reported at most once per root. Returns `fallback` on failure.\n *\n * It deliberately catches EVERY exception, not only input-access ones: `check()` must never throw\n * on garbage input. The trade-off is that a genuine bug in a check surfaces as `NOT_AN_OBJECT` on\n * that input instead of crashing; the tests (not this guard) are what expose such bugs.\n */\nexport function makeGuard(emit: Emit): <T>(root: Root, fallback: T, run: () => T) => T {\n\tconst failed = new Set<Root>()\n\treturn (root, fallback, run) => {\n\t\ttry {\n\t\t\treturn run()\n\t\t} catch {\n\t\t\tif (!failed.has(root)) emit(\"NOT_AN_OBJECT\", [root])\n\t\t\tfailed.add(root)\n\t\t\treturn fallback\n\t\t}\n\t}\n}\n","import type { AccountIndex, Check, Emit, Path } from \"./codes\"\nimport { spendableRef } from \"./refs\"\nimport { amount } from \"./scalars\"\nimport { checkShape, checkUnique, checkUniqueValues, isRecord, list, opt, req } from \"./shape\"\n\nfunction checkRouting(cashflow: Readonly<Record<string, unknown>>, path: Path, emit: Emit): void {\n\tconst surplus = cashflow[\"surplus\"]\n\tif (!Array.isArray(surplus)) return\n\tif (surplus.length === 0) {\n\t\temit(\"SURPLUS_UNROUTED\", [...path, \"surplus\"])\n\t\treturn\n\t}\n\tconst last = surplus[surplus.length - 1]\n\tif (isRecord(last) && Object.hasOwn(last, \"upTo\")) {\n\t\temit(\"SURPLUS_UNROUTED\", [...path, \"surplus\", surplus.length - 1, \"upTo\"])\n\t}\n}\n\nexport function checkCashflow(\n\tvalue: unknown,\n\tpath: Path,\n\taccounts: AccountIndex | undefined,\n\temit: Emit,\n): void {\n\tconst account = spendableRef(accounts)\n\tconst step: Check = (item, at, e) =>\n\t\tvoid checkShape(item, at, { account: req(account), upTo: opt(amount) }, e)\n\tconst cashflow = checkShape(\n\t\tvalue,\n\t\tpath,\n\t\t{ surplus: req(list(step)), withdraw: req(list(account)) },\n\t\temit,\n\t)\n\tif (cashflow) checkRouting(cashflow, path, emit)\n\tcheckUnique(cashflow?.[\"surplus\"], [...path, \"surplus\"], \"account\", emit)\n\tcheckUniqueValues(cashflow?.[\"withdraw\"], [...path, \"withdraw\"], emit)\n}\n","import { FLOW_KINDS, FREQUENCIES } from \"../vocab\"\nimport type { AccountIndex } from \"./codes\"\nimport { accountRef } from \"./refs\"\nimport { amount, bool, date, growth, oneOf, str } from \"./scalars\"\nimport { opt, req, type Shape } from \"./shape\"\n\nconst base: Shape = {\n\tid: req(str),\n\tkind: req(oneOf(FLOW_KINDS, \"INVALID_KIND\")),\n\tamount: req(amount),\n\tfrequency: req(oneOf(FREQUENCIES, \"INVALID_FREQUENCY\")),\n\tstart: req(date),\n\tend: opt(date),\n\tgrowth: req(growth),\n}\n\n/** Keys allowed per flow kind; an invalid kind accepts every optional kind-specific key. */\nexport function flowShape(kind: unknown, accounts: AccountIndex | undefined): Shape {\n\tconst target = accountRef(accounts)\n\tif (kind === \"income\") return { ...base, earned: req(bool) }\n\tif (kind === \"contribution\") return { ...base, target: req(target) }\n\tif (kind === \"expense\") return base\n\treturn { ...base, earned: opt(bool), target: opt(target) }\n}\n","import type { AccountIndex, Check, Emit, Path } from \"./codes\"\nimport { isValidDate } from \"./date\"\nimport { flowShape } from \"./flow-shape\"\nimport { checkShape, checkUnique, isRecord, list } from \"./shape\"\n\n/** ISO dates compare correctly as strings once validated. */\nfunction checkDates(flow: Readonly<Record<string, unknown>>, path: Path, emit: Emit): void {\n\tconst { start, end, frequency } = flow\n\tif (!isValidDate(start) || !isValidDate(end)) return\n\tif (end < start) emit(\"END_BEFORE_START\", [...path, \"end\"])\n\telse if (frequency === \"once\" && end !== start) emit(\"ONCE_FLOW_END_MISMATCH\", [...path, \"end\"])\n}\n\nfunction flowCheck(accounts: AccountIndex | undefined): Check {\n\treturn (value, path, emit) => {\n\t\tconst kind = isRecord(value) ? value[\"kind\"] : undefined\n\t\tconst flow = checkShape(value, path, flowShape(kind, accounts), emit)\n\t\tif (flow) checkDates(flow, path, emit)\n\t}\n}\n\nexport function checkFlows(\n\tvalue: unknown,\n\tpath: Path,\n\taccounts: AccountIndex | undefined,\n\temit: Emit,\n): void {\n\tlist(flowCheck(accounts))(value, path, emit)\n\tcheckUnique(value, path, \"id\", emit)\n}\n","import { checkAccounts } from \"./accounts\"\nimport { checkCashflow } from \"./cashflow\"\nimport type { AccountIndex, Check, Emit, Path } from \"./codes\"\nimport { checkFlows } from \"./flows\"\nimport { rate, str } from \"./scalars\"\nimport { anyVersion, checkShape, req } from \"./shape\"\n\nconst economy: Check = (value, path, emit) => {\n\tcheckShape(value, path, { inflation: req(rate) }, emit)\n}\n\nexport function checkScenario(\n\tvalue: unknown,\n\tpath: Path,\n\taccounts: AccountIndex | undefined,\n\temit: Emit,\n): void {\n\tconst shape = {\n\t\tschemaVersion: req(anyVersion),\n\t\tcurrency: req(str),\n\t\teconomy: req(economy),\n\t\taccounts: req(checkAccounts),\n\t\tflows: req((v, p, e) => checkFlows(v, p, accounts, e)),\n\t\tcashflow: req((v, p, e) => checkCashflow(v, p, accounts, e)),\n\t}\n\tcheckShape(value, path, shape, emit)\n}\n","import { RESOLUTIONS } from \"../vocab\"\nimport type { Emit, Path } from \"./codes\"\nimport { isValidDate } from \"./date\"\nimport { date, oneOf } from \"./scalars\"\nimport { checkShape, req } from \"./shape\"\n\nconst shape = {\n\tstart: req(date),\n\thorizon: req(date),\n\tresolution: req(oneOf(RESOLUTIONS, \"INVALID_RESOLUTION\")),\n}\n\nexport function checkTimeline(value: unknown, path: Path, emit: Emit): void {\n\tconst timeline = checkShape(value, path, shape, emit)\n\tconst { start, horizon } = timeline ?? {}\n\tif (isValidDate(start) && isValidDate(horizon) && horizon < start) {\n\t\temit(\"HORIZON_BEFORE_START\", [...path, \"horizon\"])\n\t}\n}\n","import { SCHEMA_VERSION } from \"../vocab\"\nimport { indexAccounts } from \"./accounts\"\nimport { checkBaseline } from \"./baseline\"\nimport type { Emit, Path, Problem } from \"./codes\"\nimport { makeGuard } from \"./guard\"\nimport { checkScenario } from \"./scenario\"\nimport { isRecord } from \"./shape\"\nimport { checkTimeline } from \"./timeline\"\n\n/** True (and no problem) unless a record's `schemaVersion` is not 1: then one error is emitted. */\nfunction versionOk(value: unknown, path: Path, emit: Emit): boolean {\n\tif (!isRecord(value) || value[\"schemaVersion\"] === SCHEMA_VERSION) return true\n\temit(\"UNSUPPORTED_SCHEMA_VERSION\", [...path, \"schemaVersion\"])\n\treturn false\n}\n\n/**\n * Validates all three inputs in one pass. `[]` means valid; the engine refuses to run otherwise.\n * Accepts arbitrary values and never throws: an input that cannot be read at all (a throwing\n * getter, a revoked Proxy) yields a single `NOT_AN_OBJECT` problem at its root.\n */\nexport function check(baseline: unknown, scenario: unknown, timeline: unknown): readonly Problem[] {\n\tconst problems: Problem[] = []\n\tconst emit: Emit = (code, path) => void problems.push({ code, path })\n\tconst guard = makeGuard(emit)\n\tconst scenarioOk = guard(\"scenario\", false, () => versionOk(scenario, [\"scenario\"], emit))\n\tconst baselineOk = guard(\"baseline\", false, () => versionOk(baseline, [\"baseline\"], emit))\n\tconst accounts = guard(\"scenario\", undefined, () =>\n\t\tscenarioOk && isRecord(scenario) ? indexAccounts(scenario[\"accounts\"]) : undefined,\n\t)\n\tif (baselineOk)\n\t\tguard(\"baseline\", undefined, () => checkBaseline(baseline, [\"baseline\"], accounts, emit))\n\tif (scenarioOk)\n\t\tguard(\"scenario\", undefined, () => checkScenario(scenario, [\"scenario\"], accounts, emit))\n\tguard(\"timeline\", undefined, () => checkTimeline(timeline, [\"timeline\"], emit))\n\treturn problems\n}\n","const CODES = [\n\t\"UNSUPPORTED_SCHEMA_VERSION\",\n\t\"NOT_AN_OBJECT\",\n\t\"NOT_AN_ARRAY\",\n\t\"MISSING_KEY\",\n\t\"UNKNOWN_KEY\",\n\t\"WRONG_TYPE\",\n\t\"EMPTY_STRING\",\n\t\"NOT_SAFE_INTEGER\",\n\t\"NEGATIVE_AMOUNT\",\n\t\"INVALID_DATE\",\n\t\"INVALID_KIND\",\n\t\"INVALID_FREQUENCY\",\n\t\"INVALID_GROWTH\",\n\t\"INVALID_RESOLUTION\",\n\t\"HORIZON_BEFORE_START\",\n\t\"END_BEFORE_START\",\n\t\"ONCE_FLOW_END_MISMATCH\",\n\t\"DUPLICATE_ID\",\n\t\"UNKNOWN_ACCOUNT\",\n\t\"UNDECLARED_BALANCE_ACCOUNT\",\n\t\"LIABILITY_MISUSE\",\n\t\"SURPLUS_UNROUTED\",\n\t\"RATE_OUT_OF_RANGE\",\n] as const\n\n/** The closed set of problem codes. Frozen so consumers cannot mutate it at runtime. */\nexport const ERROR_CODES: typeof CODES = Object.freeze(CODES)\n\nexport type ErrorCode = (typeof CODES)[number]\n\n/** Location of a problem: a segment is an object key or an array index. */\nexport type Path = readonly (string | number)[]\n\nexport interface Problem {\n\treadonly code: ErrorCode\n\treadonly path: Path\n}\n\nexport type Emit = (code: ErrorCode, path: Path) => void\n\nexport type Check = (value: unknown, path: Path, emit: Emit) => void\n\n/** Declared account id -> raw `kind` value from the scenario. */\nexport type AccountIndex = ReadonlyMap<string, unknown>\n","import type { Baseline } from \"../types\"\nimport type { RuleMap } from \"./rules\"\n\n/** Net worth at the timeline start, before any start-date flows land. */\nexport function openingNetWorth(baseline: Baseline, rules: RuleMap): bigint {\n\tlet total = 0n\n\tfor (const balance of baseline.balances) {\n\t\tconst amount = BigInt(balance.amount)\n\t\ttotal += rules.get(balance.account)?.kind === \"liability\" ? -amount : amount\n\t}\n\treturn total\n}\n","import type { DateString } from \"../types\"\n\nconst DATE_SHAPE = /^(\\d{4})-(\\d{2})-(\\d{2})$/\nconst MONTH_DAYS = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]\n\nexport interface CivilDate {\n\treadonly year: number\n\treadonly month: number\n\treadonly day: number\n}\n\nexport function isLeapYear(year: number): boolean {\n\treturn (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0\n}\n\nexport function daysInMonth(year: number, month: number): number {\n\treturn month === 2 && isLeapYear(year) ? 29 : (MONTH_DAYS[month - 1] ?? 0)\n}\n\n/** Parses an already validated `YYYY-MM-DD` date. */\nexport function parseDate(value: DateString): CivilDate {\n\tconst match = DATE_SHAPE.exec(value)\n\tif (!match) throw new RangeError(`Invalid date: ${value}`)\n\treturn { year: Number(match[1]), month: Number(match[2]), day: Number(match[3]) }\n}\n\nfunction pad(value: number, width: number): string {\n\treturn String(value).padStart(width, \"0\")\n}\n\nexport function formatDate({ year, month, day }: CivilDate): DateString {\n\treturn `${pad(year, 4)}-${pad(month, 2)}-${pad(day, 2)}`\n}\n","import type { DateString } from \"../types\"\nimport { daysInMonth, formatDate, parseDate } from \"./civil\"\n\nexport function daysBeforeYear(year: number): number {\n\tconst previous = year - 1\n\treturn (\n\t\t365 * previous +\n\t\tMath.floor(previous / 4) -\n\t\tMath.floor(previous / 100) +\n\t\tMath.floor(previous / 400)\n\t)\n}\n\nfunction daysBeforeMonth(year: number, month: number): number {\n\tlet days = 0\n\tfor (let m = 1; m < month; m++) days += daysInMonth(year, m)\n\treturn days\n}\n\n/** Zero-based serial day number; 0001-01-01 is 0. */\nexport function dayNumber(date: DateString): number {\n\tconst { year, month, day } = parseDate(date)\n\treturn daysBeforeYear(year) + daysBeforeMonth(year, month) + day - 1\n}\n\nconst FIRST_DATE: DateString = \"0001-01-01\"\nconst LAST_DATE: DateString = \"9999-12-31\"\nconst LAST_DAY = dayNumber(LAST_DATE)\n\n/** Inverse of `dayNumber`, saturating at the supported range; no wall clock is involved. */\nexport function fromDayNumber(value: number): DateString {\n\tif (value <= 0) return FIRST_DATE\n\tif (value >= LAST_DAY) return LAST_DATE\n\tlet year = Math.floor(value / 366) + 1\n\twhile (daysBeforeYear(year + 1) <= value) year++\n\twhile (daysBeforeYear(year) > value) year--\n\tlet remaining = value - daysBeforeYear(year)\n\tlet month = 1\n\twhile (remaining >= daysInMonth(year, month)) {\n\t\tremaining -= daysInMonth(year, month)\n\t\tmonth++\n\t}\n\treturn formatDate({ year, month, day: remaining + 1 })\n}\n\nexport function addDays(date: DateString, days: number): DateString {\n\treturn fromDayNumber(dayNumber(date) + days)\n}\n\n/** Adds calendar months, clamping the day to the target month's last day. */\nexport function addMonthsClamped(date: DateString, months: number): DateString {\n\tconst { year, month, day } = parseDate(date)\n\tconst total = year * 12 + (month - 1) + months\n\tconst targetYear = Math.floor(total / 12)\n\tif (targetYear > 9999) return LAST_DATE\n\tconst targetMonth = (((total % 12) + 12) % 12) + 1\n\treturn formatDate({\n\t\tyear: targetYear,\n\t\tmonth: targetMonth,\n\t\tday: Math.min(day, daysInMonth(targetYear, targetMonth)),\n\t})\n}\n\n/** Number of annual growth anniversaries reached, with `Feb 29 -> Feb 28` clamping. */\nexport function growthYears(start: DateString, date: DateString): number {\n\tconst years = parseDate(date).year - parseDate(start).year\n\tif (years <= 0) return 0\n\treturn addMonthsClamped(start, years * 12) <= date ? years : years - 1\n}\n","import { addDays, addMonthsClamped } from \"../calendar/arith\"\nimport type { DateString } from \"../types\"\n\nexport interface Period {\n\treadonly index: number\n\treadonly from: DateString\n\treadonly to: DateString\n\treadonly partial: boolean\n}\n\n/** Last day of every full twelve-month period that ends on or before `end`. */\nexport function periodEndDates(start: DateString, end: DateString): readonly DateString[] {\n\tconst dates: DateString[] = []\n\tfor (let index = 1; ; index++) {\n\t\tconst last = addDays(addMonthsClamped(start, index * 12), -1)\n\t\tif (last > end) return dates\n\t\tdates.push(last)\n\t}\n}\n\n/**\n * Twelve-month periods from each anniversary of `start` to the day before the next one; the\n * final one is clipped by the projection's end and marked partial.\n */\nexport function buildPeriods(\n\tstart: DateString,\n\tend: DateString,\n\trunsOutDate: DateString | undefined,\n): readonly Period[] {\n\tconst periods: Period[] = []\n\tlet from = start\n\tlet index = 0\n\twhile (true) {\n\t\tconst next = addMonthsClamped(start, (index + 1) * 12)\n\t\tconst yearEnd = addDays(next, -1)\n\t\tconst to = end < yearEnd ? end : yearEnd\n\t\tconst partial = to < yearEnd || to === runsOutDate\n\t\tperiods.push({ index, from, to, partial })\n\t\tif (to === end) return periods\n\t\tfrom = next\n\t\tindex++\n\t}\n}\n","import type { AccountId, DateString } from \"../types\"\nimport type { ProjectionProblem } from \"../types/projection\"\n\nexport const MAX_SAFE: bigint = BigInt(Number.MAX_SAFE_INTEGER)\n\nexport function isSafeInteger(value: bigint): boolean {\n\treturn value >= -MAX_SAFE && value <= MAX_SAFE\n}\n\nexport function overflow(date: DateString, account?: AccountId): ProjectionProblem {\n\treturn account === undefined\n\t\t? { code: \"VALUE_OVERFLOW\", date }\n\t\t: { code: \"VALUE_OVERFLOW\", date, account }\n}\n","import type { DayTotals } from \"../engine/occurrence\"\nimport { isSafeInteger, overflow } from \"../engine/overflow\"\nimport type { EngineRun } from \"../engine/result\"\nimport type { EngineSnapshot } from \"../engine/snapshot\"\nimport type { AnnualRollup, ProjectionProblem } from \"../types/projection\"\nimport type { Period } from \"./periods\"\n\ninterface FlowSums {\n\treadonly income: bigint\n\treadonly expense: bigint\n\treadonly contributions: bigint\n}\n\nexport interface RollupOutcome {\n\treadonly annual: readonly AnnualRollup[] | undefined\n\treadonly problem: ProjectionProblem | undefined\n}\n\nfunction sumFlows(totals: readonly DayTotals[], period: Period): FlowSums {\n\tlet income = 0n\n\tlet expense = 0n\n\tlet contributions = 0n\n\tfor (const total of totals) {\n\t\tif (total.date < period.from || total.date > period.to) continue\n\t\tincome += total.income\n\t\texpense += total.expense\n\t\tcontributions += total.contributions\n\t}\n\treturn { income, expense, contributions }\n}\n\nfunction unsafe(values: readonly bigint[], date: string): ProjectionProblem | undefined {\n\tfor (const value of values) if (!isSafeInteger(value)) return overflow(date)\n\treturn undefined\n}\n\nexport function buildRollups(\n\trun: EngineRun,\n\tperiods: readonly Period[],\n\topening: bigint,\n): RollupOutcome {\n\tconst snapshots = new Map<string, EngineSnapshot>()\n\tfor (const snapshot of run.snapshots) snapshots.set(snapshot.date, snapshot)\n\tconst annual: AnnualRollup[] = []\n\tlet openingWorth = opening\n\tfor (const period of periods) {\n\t\tconst sums = sumFlows(run.totals, period)\n\t\tconst closing = snapshots.get(period.to)!.netWorth\n\t\tconst unmet = run.runsOut?.date === period.to ? run.runsOut.unmet : 0n\n\t\tconst interest = closing - openingWorth - sums.income + sums.expense - unmet\n\t\tconst problem = unsafe(\n\t\t\t[openingWorth, closing, sums.income, sums.expense, sums.contributions, interest, unmet],\n\t\t\tperiod.to,\n\t\t)\n\t\tif (problem !== undefined) return { annual: undefined, problem }\n\t\tannual.push({\n\t\t\tindex: period.index,\n\t\t\tfrom: period.from,\n\t\t\tto: period.to,\n\t\t\topeningNetWorth: Number(openingWorth),\n\t\t\tclosingNetWorth: Number(closing),\n\t\t\tincome: Number(sums.income),\n\t\t\texpense: Number(sums.expense),\n\t\t\tcontributions: Number(sums.contributions),\n\t\t\tinterest: Number(interest),\n\t\t\tunmet: Number(unmet),\n\t\t\tpartial: period.partial,\n\t\t})\n\t\topeningWorth = closing\n\t}\n\treturn { annual, problem: undefined }\n}\n","import type { DateString } from \"../types\"\nimport { addDays, addMonthsClamped } from \"./arith\"\n\n/** `start`, every monthly anniversary of it (clamped), and `horizon`. */\nexport function monthlyRowDates(start: DateString, horizon: DateString): readonly DateString[] {\n\tif (horizon <= start) return [start]\n\tconst dates: DateString[] = [start]\n\tlet index = 1\n\twhile (true) {\n\t\tconst date = addMonthsClamped(start, index)\n\t\tif (date >= horizon) break\n\t\tdates.push(date)\n\t\tindex++\n\t}\n\tdates.push(horizon)\n\treturn dates\n}\n\n/** Every date in `[start, horizon]`. */\nexport function dailyRowDates(start: DateString, horizon: DateString): readonly DateString[] {\n\tconst dates: DateString[] = []\n\tfor (let date = start; date <= horizon; date = addDays(date, 1)) dates.push(date)\n\treturn dates\n}\n","import { dailyRowDates, monthlyRowDates } from \"../calendar/rows\"\nimport type { DateString, Timeline } from \"../types\"\n\n/** The dates `Timeline.resolution` asks to report. */\nexport function rowDates(timeline: Timeline): readonly DateString[] {\n\treturn timeline.resolution === \"day\"\n\t\t? dailyRowDates(timeline.start, timeline.horizon)\n\t\t: monthlyRowDates(timeline.start, timeline.horizon)\n}\n","import type { DateString } from \"../types\"\nimport { dayNumber } from \"./arith\"\nimport { isLeapYear, parseDate } from \"./civil\"\n\n/** Number of Feb 29 dates in years 1..year that are not after `date`. */\nfunction leapDaysThrough(date: DateString): number {\n\tconst { year, month, day } = parseDate(date)\n\tlet count = Math.floor(year / 4) - Math.floor(year / 100) + Math.floor(year / 400)\n\tif (isLeapYear(year) && (month < 2 || (month === 2 && day < 29))) count--\n\treturn count\n}\n\n/** Actual/365 No Leap: actual days minus the Feb 29s in `(from, to]`. */\nexport function countedDays(from: DateString, to: DateString): number {\n\treturn dayNumber(to) - dayNumber(from) - (leapDaysThrough(to) - leapDaysThrough(from))\n}\n","/** Integer exponentiation by squaring; `exponent` is a non-negative safe integer. */\nexport function powBigInt(base: bigint, exponent: number): bigint {\n\tif (!Number.isSafeInteger(exponent) || exponent < 0) {\n\t\tthrow new RangeError(\"powBigInt expects a non-negative safe integer exponent\")\n\t}\n\tlet result = 1n\n\tlet factor = base\n\tlet remaining = exponent\n\twhile (remaining > 0) {\n\t\tif (remaining % 2 === 1) result *= factor\n\t\tfactor *= factor\n\t\tremaining = Math.floor(remaining / 2)\n\t}\n\treturn result\n}\n","import { powBigInt } from \"./pow\"\n\n/** Largest integer `r` with `r ** degree <= value` (`value >= 0`, `degree >= 1`). */\nexport function nthRootFloor(value: bigint, degree: number): bigint {\n\tif (value < 0n || !Number.isSafeInteger(degree) || degree < 1) {\n\t\tthrow new RangeError(\"nthRootFloor expects a non-negative value and positive degree\")\n\t}\n\tif (value < 2n) return value\n\tlet high = 1n\n\twhile (powBigInt(high, degree) <= value) high *= 2n\n\tlet low = high / 2n\n\twhile (low + 1n < high) {\n\t\tconst middle = (low + high) / 2n\n\t\tif (powBigInt(middle, degree) <= value) low = middle\n\t\telse high = middle\n\t}\n\treturn low\n}\n","import type { BasisPoints } from \"../types\"\nimport { nthRootFloor } from \"./root\"\n\nexport const RATE_SCALE: bigint = 10000n\nexport const FACTOR_SCALE: number = 30\nexport const FACTOR_BASE: bigint = 10n ** BigInt(FACTOR_SCALE)\nexport const DAYS_PER_YEAR: number = 365\n\nconst cache: Map<BasisPoints, bigint> = new Map()\n\n/**\n * Largest integer `f` with `10000 * f^365 <= (10000 + rate) * 10^(30*365)`.\n * The result is cached per rate; the cache is deterministic and purely additive.\n */\nexport function dailyFactor(rate: BasisPoints): bigint {\n\tif (!Number.isSafeInteger(rate) || rate <= -10000) {\n\t\tthrow new RangeError(`Rate must be a safe integer above -10000 bps: ${rate}`)\n\t}\n\tconst cached = cache.get(rate)\n\tif (cached !== undefined) return cached\n\tconst numerator = (RATE_SCALE + BigInt(rate)) * FACTOR_BASE ** BigInt(DAYS_PER_YEAR)\n\tconst factor = nthRootFloor(numerator / RATE_SCALE, DAYS_PER_YEAR)\n\tcache.set(rate, factor)\n\treturn factor\n}\n","/** Half-up rounding of a non-negative integer ratio. */\nexport function roundHalfUp(numerator: bigint, denominator: bigint): bigint {\n\tif (numerator < 0n) throw new RangeError(\"roundHalfUp expects a non-negative numerator\")\n\tif (denominator <= 0n) throw new RangeError(\"roundHalfUp expects a positive denominator\")\n\tconst quotient = numerator / denominator\n\tconst remainder = numerator % denominator\n\treturn remainder * 2n >= denominator ? quotient + 1n : quotient\n}\n","import type { BasisPoints } from \"../types\"\nimport { DAYS_PER_YEAR, dailyFactor, RATE_SCALE } from \"./factor\"\nimport { roundHalfUp } from \"./round\"\n\nconst factorPowers: Map<BasisPoints, bigint[]> = new Map()\nconst ratePowers: Map<BasisPoints, bigint[]> = new Map()\n\nfunction powerAt(rate: BasisPoints, exponent: number, rateBase: boolean): bigint {\n\tconst cache = rateBase ? ratePowers : factorPowers\n\tlet powers = cache.get(rate)\n\tif (powers === undefined) {\n\t\tpowers = [1n]\n\t\tcache.set(rate, powers)\n\t}\n\tconst base = rateBase ? RATE_SCALE + BigInt(rate) : dailyFactor(rate)\n\twhile (powers.length <= exponent) powers.push(powers[powers.length - 1]! * base)\n\treturn powers[exponent]!\n}\n\ninterface FactorParts {\n\treadonly numerator: bigint\n\treadonly denominator: bigint\n}\n\nfunction splitDays(days: number): readonly [years: number, remainder: number] {\n\tif (!Number.isSafeInteger(days) || days < 0) {\n\t\tthrow new RangeError(\"Growth expects a non-negative safe integer day count\")\n\t}\n\tconst years = Math.floor(days / DAYS_PER_YEAR)\n\treturn [years, days - years * DAYS_PER_YEAR]\n}\n\n/** `(10000 + rate)^years * f^remainder / (10000^years * 10^(30*remainder))`. */\nfunction factorParts(rate: BasisPoints, days: number): FactorParts {\n\tconst [years, remainder] = splitDays(days)\n\treturn {\n\t\tnumerator: powerAt(rate, years, true) * powerAt(rate, remainder, false),\n\t\tdenominator: powerAt(0, years, true) * powerAt(0, remainder, false),\n\t}\n}\n\n/** Grows `amount` over `days` counted days with one half-up rounding at the end. */\nexport function grow(amount: bigint, rate: BasisPoints, days: number): bigint {\n\tconst parts = factorParts(rate, days)\n\treturn roundHalfUp(amount * parts.numerator, parts.denominator)\n}\n\n/** Today's-money value of `amount` at `inflation`, over `days` counted days. */\nexport function deflate(amount: bigint, inflation: BasisPoints, days: number): bigint {\n\tconst parts = factorParts(inflation, days)\n\treturn roundHalfUp(amount * parts.denominator, parts.numerator)\n}\n","import { countedDays } from \"../calendar/counted\"\nimport { isSafeInteger, overflow } from \"../engine/overflow\"\nimport type { EngineSnapshot } from \"../engine/snapshot\"\nimport { deflate } from \"../money/growth\"\nimport type { BasisPoints, DateString } from \"../types\"\nimport type { AccountAmount, ProjectionProblem } from \"../types/projection\"\nimport type { RuleMap } from \"./rules\"\n\nexport interface RealValues {\n\treadonly balances: readonly AccountAmount[]\n\treadonly netWorth: bigint\n\treadonly accessibleNetWorth: bigint\n}\n\nexport interface RealOutcome {\n\treadonly values: RealValues | undefined\n\treadonly problem: ProjectionProblem | undefined\n}\n\n/** Deflates each account separately, then sums the signed real balances. */\nexport function realValues(\n\tsnapshot: EngineSnapshot,\n\trules: RuleMap,\n\tstart: DateString,\n\tinflation: BasisPoints,\n): RealOutcome {\n\tconst days = countedDays(start, snapshot.date)\n\tconst balances: AccountAmount[] = []\n\tlet net = 0n\n\tlet accessible = 0n\n\tfor (const balance of snapshot.balances) {\n\t\tconst amount = deflate(balance.amount, inflation, days)\n\t\tif (!isSafeInteger(amount))\n\t\t\treturn { values: undefined, problem: overflow(snapshot.date, balance.account) }\n\t\tbalances.push({ account: balance.account, amount: Number(amount) })\n\t\tconst rule = rules.get(balance.account)\n\t\tconst signed = rule?.kind === \"liability\" ? -amount : amount\n\t\tnet += signed\n\t\tconst unlocked =\n\t\t\trule?.kind !== \"asset\" || rule.lockedUntil === undefined || snapshot.date >= rule.lockedUntil\n\t\tif (unlocked) accessible += signed\n\t}\n\tif (!isSafeInteger(net) || !isSafeInteger(accessible)) {\n\t\treturn { values: undefined, problem: overflow(snapshot.date) }\n\t}\n\treturn { values: { balances, netWorth: net, accessibleNetWorth: accessible }, problem: undefined }\n}\n","import type { EngineSnapshot } from \"../engine/snapshot\"\nimport type { BasisPoints, Timeline } from \"../types\"\nimport type { AccountAmount, ProjectionProblem, ProjectionRow } from \"../types/projection\"\nimport { realValues } from \"./real\"\nimport type { RuleMap } from \"./rules\"\n\nexport interface RowsOutcome {\n\treadonly rows: readonly ProjectionRow[] | undefined\n\treadonly problem: ProjectionProblem | undefined\n}\n\nfunction nominalAmounts(snapshot: EngineSnapshot): readonly AccountAmount[] {\n\treturn snapshot.balances.map((balance) => ({\n\t\taccount: balance.account,\n\t\tamount: Number(balance.amount),\n\t}))\n}\n\nexport function buildRows(\n\tsnapshots: readonly EngineSnapshot[],\n\ttimeline: Timeline,\n\trules: RuleMap,\n\tinflation: BasisPoints,\n): RowsOutcome {\n\tconst rows: ProjectionRow[] = []\n\tfor (const snapshot of snapshots) {\n\t\tconst real = realValues(snapshot, rules, timeline.start, inflation)\n\t\tif (real.problem !== undefined) return { rows: undefined, problem: real.problem }\n\t\tconst values = real.values!\n\t\trows.push({\n\t\t\tdate: snapshot.date,\n\t\t\tbalances: nominalAmounts(snapshot),\n\t\t\tnetWorth: Number(snapshot.netWorth),\n\t\t\taccessibleNetWorth: Number(snapshot.accessibleNetWorth),\n\t\t\trealBalances: values.balances,\n\t\t\trealNetWorth: Number(values.netWorth),\n\t\t\trealAccessibleNetWorth: Number(values.accessibleNetWorth),\n\t\t})\n\t}\n\treturn { rows, problem: undefined }\n}\n","import type { Account, AccountId, Scenario } from \"../types\"\n\nexport type RuleMap = ReadonlyMap<AccountId, Account>\n\nexport function accountRules(scenario: Scenario): RuleMap {\n\tconst rules = new Map<AccountId, Account>()\n\tfor (const rule of scenario.accounts) rules.set(rule.id, rule)\n\treturn rules\n}\n","import type { EngineRun } from \"../engine/result\"\nimport type { Baseline, Scenario, Timeline } from \"../types\"\nimport type { Projection, ProjectionProblem } from \"../types/projection\"\nimport { openingNetWorth } from \"./opening\"\nimport { buildPeriods } from \"./periods\"\nimport { buildRollups } from \"./rollups\"\nimport { rowDates } from \"./row-dates\"\nimport { buildRows } from \"./rows\"\nimport { accountRules } from \"./rules\"\n\nexport type BuildResult =\n\t| { readonly projection: Projection }\n\t| { readonly problem: ProjectionProblem }\n\nexport function buildProjection(\n\trun: EngineRun,\n\tbaseline: Baseline,\n\tscenario: Scenario,\n\ttimeline: Timeline,\n): BuildResult {\n\tconst rules = accountRules(scenario)\n\tconst reported = new Set<string>(rowDates(timeline))\n\tconst shown = run.snapshots.filter(\n\t\t(snapshot) => reported.has(snapshot.date) || snapshot.date === run.runsOut?.date,\n\t)\n\tconst rows = buildRows(shown, timeline, rules, scenario.economy.inflation)\n\tif (rows.problem !== undefined) return { problem: rows.problem }\n\tconst end = run.runsOut?.date ?? timeline.horizon\n\tconst periods = buildPeriods(timeline.start, end, run.runsOut?.date)\n\tconst rollups = buildRollups(run, periods, openingNetWorth(baseline, rules))\n\tif (rollups.problem !== undefined) return { problem: rollups.problem }\n\tconst projection: Projection =\n\t\trun.runsOut === undefined\n\t\t\t? { rows: rows.rows!, annual: rollups.annual! }\n\t\t\t: {\n\t\t\t\t\trows: rows.rows!,\n\t\t\t\t\tannual: rollups.annual!,\n\t\t\t\t\trunsOut: { date: run.runsOut.date, unmet: Number(run.runsOut.unmet) },\n\t\t\t\t}\n\treturn { projection }\n}\n","import type { DateString } from \"../types\"\nimport type { DatedEvent } from \"./events\"\n\n/** Sorted unique union of event dates and requested observation dates. */\nexport function collectDates(\n\tevents: readonly DatedEvent[],\n\tobservations: readonly DateString[],\n): readonly DateString[] {\n\tconst dates = new Set<DateString>()\n\tfor (const event of events) dates.add(event.date)\n\tfor (const date of observations) dates.add(date)\n\treturn [...dates].sort((left, right) => (left < right ? -1 : left > right ? 1 : 0))\n}\n","import type { DateString, Frequency } from \"../types\"\nimport { addDays, addMonthsClamped, dayNumber, growthYears } from \"./arith\"\n\nexport interface Occurrence {\n\treadonly date: DateString\n\treadonly years: number\n}\n\nfunction stepDays(frequency: Frequency): number | undefined {\n\tif (frequency === \"daily\") return 1\n\tif (frequency === \"weekly\") return 7\n\tif (frequency === \"biweekly\") return 14\n\treturn undefined\n}\n\nfunction stepMonths(frequency: Frequency): number | undefined {\n\tif (frequency === \"monthly\") return 1\n\tif (frequency === \"quarterly\") return 3\n\tif (frequency === \"annual\") return 12\n\treturn undefined\n}\n\nfunction occurrenceDate(start: DateString, frequency: Frequency, index: number): DateString {\n\tconst months = stepMonths(frequency)\n\tif (months !== undefined) return addMonthsClamped(start, index * months)\n\tconst days = stepDays(frequency) ?? 1\n\treturn addDays(start, index * days)\n}\n\nfunction firstIndex(start: DateString, frequency: Frequency, from: DateString): number {\n\tif (from <= start) return 0\n\tconst months = stepMonths(frequency)\n\tif (months !== undefined) {\n\t\tconst s = start.split(\"-\")\n\t\tconst f = from.split(\"-\")\n\t\tconst diff = (Number(f[0]) - Number(s[0])) * 12 + (Number(f[1]) - Number(s[1]))\n\t\treturn Math.max(0, Math.floor(diff / months))\n\t}\n\tconst days = stepDays(frequency) ?? 1\n\treturn Math.max(0, Math.floor((dayNumber(from) - dayNumber(start)) / days))\n}\n\nfunction rangeOccurrences(\n\tstart: DateString,\n\tfrequency: Frequency,\n\tlast: DateString,\n\tfrom: DateString,\n): readonly Occurrence[] {\n\tconst result: Occurrence[] = []\n\tfor (let index = firstIndex(start, frequency, from); ; index++) {\n\t\tconst date = occurrenceDate(start, frequency, index)\n\t\tif (date > last) return result\n\t\tif (date >= from) result.push({ date, years: growthYears(start, date) })\n\t}\n}\n\n/** Occurrences in `[from, to]`, with `end` (inclusive) capping them. */\nexport function occurrences(\n\tstart: DateString,\n\tfrequency: Frequency,\n\tend: DateString | undefined,\n\tfrom: DateString,\n\tto: DateString,\n): readonly Occurrence[] {\n\tif (to < from) return []\n\tconst last = end !== undefined && end < to ? end : to\n\tif (frequency === \"once\") {\n\t\treturn start >= from && start <= last ? [{ date: start, years: 0 }] : []\n\t}\n\treturn rangeOccurrences(start, frequency, last, from)\n}\n","/** Plain UTF-16 code-unit ordering, never `localeCompare`. */\nexport function compareIds(left: string, right: string): number {\n\tif (left < right) return -1\n\tif (left > right) return 1\n\treturn 0\n}\n","import { occurrences } from \"../calendar/occurrence\"\nimport type { DateString, Flow, Scenario, Timeline } from \"../types\"\nimport { compareIds } from \"./order\"\n\nexport interface DatedEvent {\n\treadonly date: DateString\n\treadonly flow: Flow\n\treadonly years: number\n}\n\n/** All flow occurrences in the timeline, sorted by date then flow id. */\nexport function buildEvents(scenario: Scenario, timeline: Timeline): readonly DatedEvent[] {\n\tconst events: DatedEvent[] = []\n\tfor (const flow of scenario.flows) {\n\t\tconst found = occurrences(\n\t\t\tflow.start,\n\t\t\tflow.frequency,\n\t\t\tflow.end,\n\t\t\ttimeline.start,\n\t\t\ttimeline.horizon,\n\t\t)\n\t\tfor (const occurrence of found) {\n\t\t\tevents.push({ date: occurrence.date, flow, years: occurrence.years })\n\t\t}\n\t}\n\treturn events.sort((left, right) =>\n\t\tleft.date === right.date\n\t\t\t? compareIds(left.flow.id, right.flow.id)\n\t\t\t: left.date < right.date\n\t\t\t\t? -1\n\t\t\t\t: 1,\n\t)\n}\n","import { grow } from \"../money/growth\"\nimport type { BasisPoints } from \"../types\"\nimport type { DatedEvent } from \"./events\"\n\n/** Flow amount at an occurrence, grown from the original by whole annual steps. */\nexport function amountAt(event: DatedEvent, inflation: BasisPoints): bigint {\n\tconst growth = event.flow.growth\n\tconst rate = growth === \"inflation\" ? inflation : growth.bps\n\treturn grow(BigInt(event.flow.amount), rate, event.years * 365)\n}\n","import type { AccountId, BasisPoints } from \"../types\"\nimport { amountAt } from \"./amount\"\nimport type { DatedEvent } from \"./events\"\n\nexport interface DayFlows {\n\treadonly income: bigint\n\treadonly expense: bigint\n\treadonly contributions: ReadonlyMap<AccountId, bigint>\n}\n\nexport function aggregate(events: readonly DatedEvent[], inflation: BasisPoints): DayFlows {\n\tlet income = 0n\n\tlet expense = 0n\n\tconst contributions = new Map<AccountId, bigint>()\n\tfor (const event of events) {\n\t\tconst amount = amountAt(event, inflation)\n\t\tconst flow = event.flow\n\t\tif (flow.kind === \"income\") income += amount\n\t\telse if (flow.kind === \"expense\") expense += amount\n\t\telse {\n\t\t\tconst previous = contributions.get(flow.target) ?? 0n\n\t\t\tcontributions.set(flow.target, previous + amount)\n\t\t}\n\t}\n\treturn { income, expense, contributions }\n}\n","export function minBigInt(left: bigint, right: bigint): bigint {\n\tif (left < right) return left\n\treturn right\n}\n","import { countedDays } from \"../calendar/counted\"\nimport { grow } from \"../money/growth\"\nimport type { DateString } from \"../types\"\nimport type { AccountState, StateMap } from \"./state\"\n\n/** Read-only valuation; it never commits the account. */\nexport function valuation(state: AccountState, date: DateString): bigint {\n\treturn grow(state.balance, state.rule.rate, countedDays(state.asOf, date))\n}\n\nfunction signedValue(state: AccountState, date: DateString): bigint {\n\tconst value = valuation(state, date)\n\treturn state.rule.kind === \"liability\" ? -value : value\n}\n\nexport function netWorth(states: StateMap, date: DateString): bigint {\n\tlet total = 0n\n\tfor (const state of states.values()) total += signedValue(state, date)\n\treturn total\n}\n\nexport function accessibleNetWorth(states: StateMap, date: DateString): bigint {\n\tlet total = 0n\n\tfor (const state of states.values()) {\n\t\tif (state.rule.kind === \"liability\") total -= valuation(state, date)\n\t\telse if (state.rule.lockedUntil === undefined || date >= state.rule.lockedUntil) {\n\t\t\ttotal += valuation(state, date)\n\t\t}\n\t}\n\treturn total\n}\n","import type { DateString } from \"../types\"\nimport type { ProjectionProblem } from \"../types/projection\"\nimport { isSafeInteger, overflow } from \"./overflow\"\nimport type { AccountState } from \"./state\"\nimport { valuation } from \"./value\"\n\n/** Commits accrued growth, then applies `delta`; returns a problem on overflow. */\nexport function mutate(\n\tstate: AccountState,\n\tdate: DateString,\n\tdelta: bigint,\n): ProjectionProblem | undefined {\n\tconst committed = valuation(state, date)\n\tif (!isSafeInteger(committed)) return overflow(date, state.rule.id)\n\tconst next = committed + delta\n\tif (next < 0n) throw new RangeError(`Negative balance on ${state.rule.id} at ${date}`)\n\tif (!isSafeInteger(next)) return overflow(date, state.rule.id)\n\tstate.balance = next\n\tstate.asOf = date\n\treturn undefined\n}\n","import type { AccountId, DateString } from \"../types\"\nimport type { ProjectionProblem } from \"../types/projection\"\nimport { minBigInt } from \"./min\"\nimport { mutate } from \"./mutate\"\nimport { compareIds } from \"./order\"\nimport type { StateMap } from \"./state\"\nimport { valuation } from \"./value\"\n\nexport interface ContributionResult {\n\treadonly outflow: bigint\n\treadonly problem: ProjectionProblem | undefined\n}\n\nfunction applyTarget(\n\tstates: StateMap,\n\ttarget: AccountId,\n\ttotal: bigint,\n\tdate: DateString,\n): ContributionResult {\n\tconst state = states.get(target)\n\tif (total === 0n || state === undefined) return { outflow: 0n, problem: undefined }\n\tconst liability = state.rule.kind === \"liability\"\n\tconst owed = liability ? valuation(state, date) : total\n\tconst payment = minBigInt(total, owed)\n\tconst problem = mutate(state, date, liability ? -payment : payment)\n\treturn problem === undefined ? { outflow: payment, problem: undefined } : { outflow: 0n, problem }\n}\n\n/** Applies same-date contributions per target, capping liability payments at the amount owed. */\nexport function applyContributions(\n\tstates: StateMap,\n\tcontributions: ReadonlyMap<AccountId, bigint>,\n\tdate: DateString,\n): ContributionResult {\n\tlet outflow = 0n\n\tfor (const target of [...contributions.keys()].sort(compareIds)) {\n\t\tconst result = applyTarget(states, target, contributions.get(target) ?? 0n, date)\n\t\tif (result.problem !== undefined) return { outflow, problem: result.problem }\n\t\toutflow += result.outflow\n\t}\n\treturn { outflow, problem: undefined }\n}\n","import type { DateString, Scenario, SurplusStep } from \"../types\"\nimport type { ProjectionProblem } from \"../types/projection\"\nimport { minBigInt } from \"./min\"\nimport { mutate } from \"./mutate\"\nimport type { StateMap } from \"./state\"\nimport { valuation } from \"./value\"\n\ninterface FillResult {\n\treadonly remaining: bigint\n\treadonly problem: ProjectionProblem | undefined\n}\n\nfunction fillStep(\n\tstates: StateMap,\n\tstep: SurplusStep,\n\tdate: DateString,\n\tremaining: bigint,\n): FillResult {\n\tconst state = states.get(step.account)!\n\tconst headroom = step.upTo === undefined ? remaining : BigInt(step.upTo) - valuation(state, date)\n\tlet fill = 0n\n\tif (headroom > 0n) fill = minBigInt(remaining, headroom)\n\tif (fill === 0n) return { remaining, problem: undefined }\n\tconst problem = mutate(state, date, fill)\n\treturn problem === undefined\n\t\t? { remaining: remaining - fill, problem: undefined }\n\t\t: { remaining, problem }\n}\n\nexport function applySurplus(\n\tstates: StateMap,\n\tscenario: Scenario,\n\tdate: DateString,\n\tamount: bigint,\n): ProjectionProblem | undefined {\n\tlet remaining = amount\n\tfor (const step of scenario.cashflow.surplus) {\n\t\tif (remaining === 0n) return undefined\n\t\tconst result = fillStep(states, step, date, remaining)\n\t\tremaining = result.remaining\n\t\tif (result.problem !== undefined) return result.problem\n\t}\n\treturn undefined\n}\n","import type { DateString, Scenario } from \"../types\"\nimport type { ProjectionProblem } from \"../types/projection\"\nimport { minBigInt } from \"./min\"\nimport { mutate } from \"./mutate\"\nimport type { AccountState, StateMap } from \"./state\"\nimport { valuation } from \"./value\"\n\nexport interface WithdrawResult {\n\treadonly remaining: bigint\n\treadonly problem: ProjectionProblem | undefined\n}\n\nfunction isLocked(state: AccountState, date: DateString): boolean {\n\treturn (\n\t\tstate.rule.kind === \"asset\" &&\n\t\tstate.rule.lockedUntil !== undefined &&\n\t\tdate < state.rule.lockedUntil\n\t)\n}\n\nfunction takeFrom(state: AccountState, date: DateString, remaining: bigint): WithdrawResult {\n\tconst value = valuation(state, date)\n\tconst take = minBigInt(remaining, value)\n\tif (take === 0n) return { remaining, problem: undefined }\n\tconst problem = mutate(state, date, -take)\n\treturn problem === undefined\n\t\t? { remaining: remaining - take, problem: undefined }\n\t\t: { remaining, problem }\n}\n\nexport function applyWithdraw(\n\tstates: StateMap,\n\tscenario: Scenario,\n\tdate: DateString,\n\tamount: bigint,\n): WithdrawResult {\n\tlet remaining = amount\n\tfor (const account of scenario.cashflow.withdraw) {\n\t\tif (remaining === 0n) break\n\t\tconst state = states.get(account)!\n\t\tif (isLocked(state, date)) continue\n\t\tconst result = takeFrom(state, date, remaining)\n\t\tremaining = result.remaining\n\t\tif (result.problem !== undefined) return result\n\t}\n\treturn { remaining, problem: undefined }\n}\n","import type { DateString, Scenario } from \"../types\"\nimport type { ProjectionProblem } from \"../types/projection\"\nimport { aggregate } from \"./aggregate\"\nimport { applyContributions } from \"./contributions\"\nimport type { DatedEvent } from \"./events\"\nimport type { StateMap } from \"./state\"\nimport { applySurplus } from \"./surplus\"\nimport { applyWithdraw } from \"./withdraw\"\n\nexport interface DayTotals {\n\treadonly date: DateString\n\treadonly income: bigint\n\treadonly expense: bigint\n\treadonly contributions: bigint\n}\n\nexport interface EngineRunsOut {\n\treadonly date: DateString\n\treadonly unmet: bigint\n}\n\nexport interface DateOutcome {\n\treadonly totals: DayTotals\n\treadonly problem: ProjectionProblem | undefined\n\treadonly runsOut: EngineRunsOut | undefined\n}\n\n/** Applies one occurrence date in the canonical order of operations. */\nexport function processDate(\n\tstates: StateMap,\n\tscenario: Scenario,\n\tdate: DateString,\n\tevents: readonly DatedEvent[],\n): DateOutcome {\n\tconst day = aggregate(events, scenario.economy.inflation)\n\tconst applied = applyContributions(states, day.contributions, date)\n\tconst totals = {\n\t\tdate,\n\t\tincome: day.income,\n\t\texpense: day.expense,\n\t\tcontributions: applied.outflow,\n\t}\n\tif (applied.problem !== undefined) return { totals, problem: applied.problem, runsOut: undefined }\n\tconst net = day.income - day.expense - applied.outflow\n\tif (net > 0n) {\n\t\tconst problem = applySurplus(states, scenario, date, net)\n\t\treturn { totals, problem, runsOut: undefined }\n\t}\n\tif (net < 0n) {\n\t\tconst drawn = applyWithdraw(states, scenario, date, -net)\n\t\tif (drawn.problem !== undefined) {\n\t\t\treturn { totals, problem: drawn.problem, runsOut: undefined }\n\t\t}\n\t\tif (drawn.remaining > 0n) {\n\t\t\treturn { totals, problem: undefined, runsOut: { date, unmet: drawn.remaining } }\n\t\t}\n\t}\n\treturn { totals, problem: undefined, runsOut: undefined }\n}\n","import type { AccountId, DateString } from \"../types\"\nimport type { ProjectionProblem } from \"../types/projection\"\nimport { isSafeInteger, overflow } from \"./overflow\"\nimport type { StateMap } from \"./state\"\nimport { valuation } from \"./value\"\n\nexport interface EngineBalance {\n\treadonly account: AccountId\n\treadonly amount: bigint\n}\n\nexport interface EngineSnapshot {\n\treadonly date: DateString\n\treadonly balances: readonly EngineBalance[]\n\treadonly netWorth: bigint\n\treadonly accessibleNetWorth: bigint\n}\n\nexport interface SnapshotOutcome {\n\treadonly snapshot: EngineSnapshot | undefined\n\treadonly problem: ProjectionProblem | undefined\n}\n\n/** Values every account without committing, and checks all reported numbers stay safe. */\nexport function snapshot(states: StateMap, date: DateString): SnapshotOutcome {\n\tconst balances: EngineBalance[] = []\n\tlet net = 0n\n\tlet accessible = 0n\n\tfor (const state of states.values()) {\n\t\tconst amount = valuation(state, date)\n\t\tif (!isSafeInteger(amount))\n\t\t\treturn { snapshot: undefined, problem: overflow(date, state.rule.id) }\n\t\tbalances.push({ account: state.rule.id, amount })\n\t\tconst signed = state.rule.kind === \"liability\" ? -amount : amount\n\t\tnet += signed\n\t\tconst unlocked =\n\t\t\tstate.rule.kind === \"liability\" ||\n\t\t\tstate.rule.lockedUntil === undefined ||\n\t\t\tdate >= state.rule.lockedUntil\n\t\tif (unlocked) accessible += signed\n\t}\n\tif (!isSafeInteger(net) || !isSafeInteger(accessible)) {\n\t\treturn { snapshot: undefined, problem: overflow(date) }\n\t}\n\treturn {\n\t\tsnapshot: { date, balances, netWorth: net, accessibleNetWorth: accessible },\n\t\tproblem: undefined,\n\t}\n}\n","import type { DateString, Scenario } from \"../types\"\nimport type { ProjectionProblem } from \"../types/projection\"\nimport type { DatedEvent } from \"./events\"\nimport type { DayTotals, EngineRunsOut } from \"./occurrence\"\nimport { processDate } from \"./occurrence\"\nimport { isSafeInteger, overflow } from \"./overflow\"\nimport type { EngineResult } from \"./result\"\nimport { type EngineSnapshot, snapshot } from \"./snapshot\"\nimport type { StateMap } from \"./state\"\n\nexport interface RunAccumulator {\n\treadonly snapshots: EngineSnapshot[]\n\treadonly totals: DayTotals[]\n\treadonly wanted: ReadonlySet<DateString>\n}\n\nfunction addSnapshot(\n\tsnapshots: EngineSnapshot[],\n\tstates: StateMap,\n\tdate: DateString,\n): ProjectionProblem | undefined {\n\tconst outcome = snapshot(states, date)\n\tif (outcome.problem !== undefined) return outcome.problem\n\tsnapshots.push(outcome.snapshot!)\n\treturn undefined\n}\n\nfunction finishRunout(acc: RunAccumulator, states: StateMap, runsOut: EngineRunsOut): EngineResult {\n\tif (!isSafeInteger(runsOut.unmet)) return { ok: false, problem: overflow(runsOut.date) }\n\tconst problem = addSnapshot(acc.snapshots, states, runsOut.date)\n\tif (problem !== undefined) return { ok: false, problem }\n\treturn { ok: true, run: { snapshots: acc.snapshots, totals: acc.totals, runsOut } }\n}\n\nfunction handleDay(\n\tacc: RunAccumulator,\n\tstates: StateMap,\n\tscenario: Scenario,\n\tdate: DateString,\n\tevents: readonly DatedEvent[],\n): EngineResult | undefined {\n\tif (events.length === 0) return undefined\n\tconst outcome = processDate(states, scenario, date, events)\n\tacc.totals.push(outcome.totals)\n\tif (outcome.problem !== undefined) return { ok: false, problem: outcome.problem }\n\tif (outcome.runsOut !== undefined) return finishRunout(acc, states, outcome.runsOut)\n\treturn undefined\n}\n\nfunction handleSnapshot(\n\tacc: RunAccumulator,\n\tstates: StateMap,\n\tdate: DateString,\n): EngineResult | undefined {\n\tif (!acc.wanted.has(date)) return undefined\n\tconst problem = addSnapshot(acc.snapshots, states, date)\n\tif (problem !== undefined) return { ok: false, problem }\n\treturn undefined\n}\n\nexport function stepDate(\n\tacc: RunAccumulator,\n\tstates: StateMap,\n\tscenario: Scenario,\n\tdate: DateString,\n\tevents: readonly DatedEvent[],\n): EngineResult | undefined {\n\tconst dayResult = handleDay(acc, states, scenario, date, events)\n\tif (dayResult !== undefined) return dayResult\n\treturn handleSnapshot(acc, states, date)\n}\n","import type { Account, AccountId, Baseline, DateString, Scenario } from \"../types\"\nimport { compareIds } from \"./order\"\n\nexport interface AccountState {\n\treadonly rule: Account\n\tbalance: bigint\n\tasOf: DateString\n}\n\nexport type StateMap = ReadonlyMap<AccountId, AccountState>\n\n/** Every declared account gets a state; missing baseline balances open at zero. */\nexport function createStates(baseline: Baseline, scenario: Scenario, start: DateString): StateMap {\n\tconst opening = new Map<AccountId, number>()\n\tfor (const balance of baseline.balances) opening.set(balance.account, balance.amount)\n\tconst states = new Map<AccountId, AccountState>()\n\tconst rules = [...scenario.accounts].sort((a, b) => compareIds(a.id, b.id))\n\tfor (const rule of rules) {\n\t\tstates.set(rule.id, { rule, balance: BigInt(opening.get(rule.id) ?? 0), asOf: start })\n\t}\n\treturn states\n}\n","import type { Baseline, DateString, Scenario, Timeline } from \"../types\"\nimport { collectDates } from \"./dates\"\nimport { buildEvents } from \"./events\"\nimport type { EngineResult } from \"./result\"\nimport { type RunAccumulator, stepDate } from \"./run-step\"\nimport { createStates } from \"./state\"\n\nexport function runEngine(\n\tbaseline: Baseline,\n\tscenario: Scenario,\n\ttimeline: Timeline,\n\tobservations: readonly DateString[],\n): EngineResult {\n\tconst states = createStates(baseline, scenario, timeline.start)\n\tconst events = buildEvents(scenario, timeline)\n\tconst acc: RunAccumulator = {\n\t\tsnapshots: [],\n\t\ttotals: [],\n\t\twanted: new Set<DateString>(observations),\n\t}\n\tlet index = 0\n\tfor (const date of collectDates(events, observations)) {\n\t\tconst start = index\n\t\twhile (index < events.length && events[index]?.date === date) index++\n\t\tconst result = stepDate(acc, states, scenario, date, events.slice(start, index))\n\t\tif (result !== undefined) return result\n\t}\n\treturn { ok: true, run: { snapshots: acc.snapshots, totals: acc.totals } }\n}\n","import { check } from \"../check\"\nimport { buildProjection } from \"../output/build\"\nimport { periodEndDates } from \"../output/periods\"\nimport { rowDates } from \"../output/row-dates\"\nimport type { Baseline, DateString, Scenario, Timeline } from \"../types\"\nimport type { ProjectionResult } from \"../types/projection\"\nimport { runEngine } from \"./run\"\n\n/** Report rows plus the period ends the annual roll-ups close on. */\nfunction observationDates(timeline: Timeline): readonly DateString[] {\n\treturn [...rowDates(timeline), ...periodEndDates(timeline.start, timeline.horizon)]\n}\n\n/** Runs `check` first, then the deterministic engine; never throws on valid inputs. */\nexport function project(\n\tbaseline: Baseline,\n\tscenario: Scenario,\n\ttimeline: Timeline,\n): ProjectionResult {\n\tconst problems = check(baseline, scenario, timeline)\n\tif (problems.length > 0) return { ok: false, problems }\n\tconst result = runEngine(baseline, scenario, timeline, observationDates(timeline))\n\tif (!result.ok) return { ok: false, problems: [result.problem] }\n\tconst output = buildProjection(result.run, baseline, scenario, timeline)\n\tif (\"problem\" in output) return { ok: false, problems: [output.problem] }\n\treturn { ok: true, projection: output.projection }\n}\n"],"mappings":"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"}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
declare const CODES: readonly ["UNSUPPORTED_SCHEMA_VERSION", "NOT_AN_OBJECT", "NOT_AN_ARRAY", "MISSING_KEY", "UNKNOWN_KEY", "WRONG_TYPE", "EMPTY_STRING", "NOT_SAFE_INTEGER", "NEGATIVE_AMOUNT", "INVALID_DATE", "INVALID_KIND", "INVALID_FREQUENCY", "INVALID_GROWTH", "INVALID_RESOLUTION", "HORIZON_BEFORE_START", "END_BEFORE_START", "ONCE_FLOW_END_MISMATCH", "DUPLICATE_ID", "UNKNOWN_ACCOUNT", "UNDECLARED_BALANCE_ACCOUNT", "LIABILITY_MISUSE", "SURPLUS_UNROUTED", "RATE_OUT_OF_RANGE"];
|
|
2
|
+
/** The closed set of problem codes. Frozen so consumers cannot mutate it at runtime. */
|
|
3
|
+
export declare const ERROR_CODES: typeof CODES;
|
|
4
|
+
type ErrorCode = (typeof CODES)[number];
|
|
5
|
+
/** Location of a problem: a segment is an object key or an array index. */
|
|
6
|
+
type Path = readonly (string | number)[];
|
|
7
|
+
interface Problem {
|
|
8
|
+
readonly code: ErrorCode;
|
|
9
|
+
readonly path: Path;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Validates all three inputs in one pass. `[]` means valid; the engine refuses to run otherwise.
|
|
13
|
+
* Accepts arbitrary values and never throws: an input that cannot be read at all (a throwing
|
|
14
|
+
* getter, a revoked Proxy) yields a single `NOT_AN_OBJECT` problem at its root.
|
|
15
|
+
*/
|
|
16
|
+
export declare function check(baseline: unknown, scenario: unknown, timeline: unknown): readonly Problem[];
|
|
17
|
+
declare const FREQUENCIES: readonly ["once", "daily", "weekly", "biweekly", "monthly", "quarterly", "annual"];
|
|
18
|
+
declare const RESOLUTIONS: readonly ["day", "month"];
|
|
19
|
+
/** Calendar date, `YYYY-MM-DD`. */
|
|
20
|
+
type DateString = string;
|
|
21
|
+
/** Integer minor units (cents, satang). Always a safe integer. */
|
|
22
|
+
type MinorUnits = number;
|
|
23
|
+
/** Integer basis points (1 bps = 0.01%). Always a safe integer. */
|
|
24
|
+
type BasisPoints = number;
|
|
25
|
+
/** Opaque account identifier. */
|
|
26
|
+
type AccountId = string;
|
|
27
|
+
type Frequency = (typeof FREQUENCIES)[number];
|
|
28
|
+
type Resolution = (typeof RESOLUTIONS)[number];
|
|
29
|
+
/** `"inflation"` follows `economy.inflation`; `{ bps }` is a fixed yearly step (may be negative). */
|
|
30
|
+
type Growth = "inflation" | {
|
|
31
|
+
readonly bps: BasisPoints;
|
|
32
|
+
};
|
|
33
|
+
/** Asset: `rate` is the expected return. Locked money does not count until `lockedUntil`. */
|
|
34
|
+
interface AssetRule {
|
|
35
|
+
readonly id: AccountId;
|
|
36
|
+
readonly kind: "asset";
|
|
37
|
+
readonly rate: BasisPoints;
|
|
38
|
+
readonly lockedUntil?: DateString;
|
|
39
|
+
}
|
|
40
|
+
/** Liability: `rate` is the interest on the outstanding balance. Cannot be locked. */
|
|
41
|
+
interface LiabilityRule {
|
|
42
|
+
readonly id: AccountId;
|
|
43
|
+
readonly kind: "liability";
|
|
44
|
+
readonly rate: BasisPoints;
|
|
45
|
+
}
|
|
46
|
+
type Account = AssetRule | LiabilityRule;
|
|
47
|
+
/** Snapshot balance at `Timeline.start`. A liability's amount is the positive amount owed. */
|
|
48
|
+
interface Balance {
|
|
49
|
+
readonly account: AccountId;
|
|
50
|
+
readonly amount: MinorUnits;
|
|
51
|
+
}
|
|
52
|
+
interface Baseline {
|
|
53
|
+
readonly schemaVersion: 1;
|
|
54
|
+
readonly balances: readonly Balance[];
|
|
55
|
+
}
|
|
56
|
+
/** One surplus step: fill `account` (up to `upTo` if given), then move to the next step. */
|
|
57
|
+
interface SurplusStep {
|
|
58
|
+
readonly account: AccountId;
|
|
59
|
+
readonly upTo?: MinorUnits;
|
|
60
|
+
}
|
|
61
|
+
interface Cashflow {
|
|
62
|
+
readonly surplus: readonly SurplusStep[];
|
|
63
|
+
/** Ordered withdrawal sources; locked accounts are skipped. */
|
|
64
|
+
readonly withdraw: readonly AccountId[];
|
|
65
|
+
}
|
|
66
|
+
interface FlowBase {
|
|
67
|
+
readonly id: string;
|
|
68
|
+
readonly amount: MinorUnits;
|
|
69
|
+
readonly frequency: Frequency;
|
|
70
|
+
readonly start: DateString;
|
|
71
|
+
/** Omitted means the flow runs to `Timeline.horizon`. A `once` flow omits it or equals `start`. */
|
|
72
|
+
readonly end?: DateString;
|
|
73
|
+
readonly growth: Growth;
|
|
74
|
+
}
|
|
75
|
+
interface IncomeFlow extends FlowBase {
|
|
76
|
+
readonly kind: "income";
|
|
77
|
+
/** Earned (true) versus passive (false) income. */
|
|
78
|
+
readonly earned: boolean;
|
|
79
|
+
}
|
|
80
|
+
interface ExpenseFlow extends FlowBase {
|
|
81
|
+
readonly kind: "expense";
|
|
82
|
+
}
|
|
83
|
+
/** Cash moves into `target`; a liability target is a debt payment, capped at the amount owed. */
|
|
84
|
+
interface ContributionFlow extends FlowBase {
|
|
85
|
+
readonly kind: "contribution";
|
|
86
|
+
readonly target: AccountId;
|
|
87
|
+
}
|
|
88
|
+
type Flow = IncomeFlow | ExpenseFlow | ContributionFlow;
|
|
89
|
+
interface AccountAmount {
|
|
90
|
+
readonly account: AccountId;
|
|
91
|
+
readonly amount: MinorUnits;
|
|
92
|
+
}
|
|
93
|
+
interface ProjectionRow {
|
|
94
|
+
readonly date: DateString;
|
|
95
|
+
readonly balances: readonly AccountAmount[];
|
|
96
|
+
readonly netWorth: MinorUnits;
|
|
97
|
+
readonly accessibleNetWorth: MinorUnits;
|
|
98
|
+
readonly realBalances: readonly AccountAmount[];
|
|
99
|
+
readonly realNetWorth: MinorUnits;
|
|
100
|
+
readonly realAccessibleNetWorth: MinorUnits;
|
|
101
|
+
}
|
|
102
|
+
interface AnnualRollup {
|
|
103
|
+
readonly index: number;
|
|
104
|
+
readonly from: DateString;
|
|
105
|
+
readonly to: DateString;
|
|
106
|
+
readonly openingNetWorth: MinorUnits;
|
|
107
|
+
readonly closingNetWorth: MinorUnits;
|
|
108
|
+
readonly income: MinorUnits;
|
|
109
|
+
readonly expense: MinorUnits;
|
|
110
|
+
readonly contributions: MinorUnits;
|
|
111
|
+
readonly interest: MinorUnits;
|
|
112
|
+
readonly unmet: MinorUnits;
|
|
113
|
+
readonly partial: boolean;
|
|
114
|
+
}
|
|
115
|
+
interface RunsOut {
|
|
116
|
+
readonly date: DateString;
|
|
117
|
+
readonly unmet: MinorUnits;
|
|
118
|
+
}
|
|
119
|
+
interface Projection {
|
|
120
|
+
readonly rows: readonly ProjectionRow[];
|
|
121
|
+
readonly annual: readonly AnnualRollup[];
|
|
122
|
+
readonly runsOut?: RunsOut;
|
|
123
|
+
}
|
|
124
|
+
interface InputProblem {
|
|
125
|
+
readonly code: ErrorCode;
|
|
126
|
+
readonly path: Path;
|
|
127
|
+
}
|
|
128
|
+
interface ValueOverflowProblem {
|
|
129
|
+
readonly code: "VALUE_OVERFLOW";
|
|
130
|
+
readonly date: DateString;
|
|
131
|
+
readonly account?: AccountId;
|
|
132
|
+
}
|
|
133
|
+
type ProjectionProblem = InputProblem | ValueOverflowProblem;
|
|
134
|
+
type ProjectionResult = {
|
|
135
|
+
readonly ok: true;
|
|
136
|
+
readonly projection: Projection;
|
|
137
|
+
} | {
|
|
138
|
+
readonly ok: false;
|
|
139
|
+
readonly problems: readonly ProjectionProblem[];
|
|
140
|
+
};
|
|
141
|
+
interface Economy {
|
|
142
|
+
readonly inflation: BasisPoints;
|
|
143
|
+
}
|
|
144
|
+
interface Scenario {
|
|
145
|
+
readonly schemaVersion: 1;
|
|
146
|
+
readonly currency: string;
|
|
147
|
+
readonly economy: Economy;
|
|
148
|
+
readonly accounts: readonly Account[];
|
|
149
|
+
readonly flows: readonly Flow[];
|
|
150
|
+
readonly cashflow: Cashflow;
|
|
151
|
+
}
|
|
152
|
+
interface Timeline {
|
|
153
|
+
readonly start: DateString;
|
|
154
|
+
readonly horizon: DateString;
|
|
155
|
+
readonly resolution: Resolution;
|
|
156
|
+
}
|
|
157
|
+
/** Runs `check` first, then the deterministic engine; never throws on valid inputs. */
|
|
158
|
+
export declare function project(baseline: Baseline, scenario: Scenario, timeline: Timeline): ProjectionResult;
|
|
159
|
+
export type { Account, AccountAmount, AccountId, AnnualRollup, AssetRule, Balance, Baseline, BasisPoints, Cashflow, ContributionFlow, DateString, Economy, ErrorCode, ExpenseFlow, Flow, Frequency, Growth, IncomeFlow, InputProblem, LiabilityRule, MinorUnits, Path, Problem, Projection, ProjectionProblem, ProjectionResult, ProjectionRow, Resolution, RunsOut, Scenario, SurplusStep, Timeline, ValueOverflowProblem };
|
|
160
|
+
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
declare const CODES: readonly ["UNSUPPORTED_SCHEMA_VERSION", "NOT_AN_OBJECT", "NOT_AN_ARRAY", "MISSING_KEY", "UNKNOWN_KEY", "WRONG_TYPE", "EMPTY_STRING", "NOT_SAFE_INTEGER", "NEGATIVE_AMOUNT", "INVALID_DATE", "INVALID_KIND", "INVALID_FREQUENCY", "INVALID_GROWTH", "INVALID_RESOLUTION", "HORIZON_BEFORE_START", "END_BEFORE_START", "ONCE_FLOW_END_MISMATCH", "DUPLICATE_ID", "UNKNOWN_ACCOUNT", "UNDECLARED_BALANCE_ACCOUNT", "LIABILITY_MISUSE", "SURPLUS_UNROUTED", "RATE_OUT_OF_RANGE"];
|
|
2
|
+
/** The closed set of problem codes. Frozen so consumers cannot mutate it at runtime. */
|
|
3
|
+
export declare const ERROR_CODES: typeof CODES;
|
|
4
|
+
type ErrorCode = (typeof CODES)[number];
|
|
5
|
+
/** Location of a problem: a segment is an object key or an array index. */
|
|
6
|
+
type Path = readonly (string | number)[];
|
|
7
|
+
interface Problem {
|
|
8
|
+
readonly code: ErrorCode;
|
|
9
|
+
readonly path: Path;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Validates all three inputs in one pass. `[]` means valid; the engine refuses to run otherwise.
|
|
13
|
+
* Accepts arbitrary values and never throws: an input that cannot be read at all (a throwing
|
|
14
|
+
* getter, a revoked Proxy) yields a single `NOT_AN_OBJECT` problem at its root.
|
|
15
|
+
*/
|
|
16
|
+
export declare function check(baseline: unknown, scenario: unknown, timeline: unknown): readonly Problem[];
|
|
17
|
+
declare const FREQUENCIES: readonly ["once", "daily", "weekly", "biweekly", "monthly", "quarterly", "annual"];
|
|
18
|
+
declare const RESOLUTIONS: readonly ["day", "month"];
|
|
19
|
+
/** Calendar date, `YYYY-MM-DD`. */
|
|
20
|
+
type DateString = string;
|
|
21
|
+
/** Integer minor units (cents, satang). Always a safe integer. */
|
|
22
|
+
type MinorUnits = number;
|
|
23
|
+
/** Integer basis points (1 bps = 0.01%). Always a safe integer. */
|
|
24
|
+
type BasisPoints = number;
|
|
25
|
+
/** Opaque account identifier. */
|
|
26
|
+
type AccountId = string;
|
|
27
|
+
type Frequency = (typeof FREQUENCIES)[number];
|
|
28
|
+
type Resolution = (typeof RESOLUTIONS)[number];
|
|
29
|
+
/** `"inflation"` follows `economy.inflation`; `{ bps }` is a fixed yearly step (may be negative). */
|
|
30
|
+
type Growth = "inflation" | {
|
|
31
|
+
readonly bps: BasisPoints;
|
|
32
|
+
};
|
|
33
|
+
/** Asset: `rate` is the expected return. Locked money does not count until `lockedUntil`. */
|
|
34
|
+
interface AssetRule {
|
|
35
|
+
readonly id: AccountId;
|
|
36
|
+
readonly kind: "asset";
|
|
37
|
+
readonly rate: BasisPoints;
|
|
38
|
+
readonly lockedUntil?: DateString;
|
|
39
|
+
}
|
|
40
|
+
/** Liability: `rate` is the interest on the outstanding balance. Cannot be locked. */
|
|
41
|
+
interface LiabilityRule {
|
|
42
|
+
readonly id: AccountId;
|
|
43
|
+
readonly kind: "liability";
|
|
44
|
+
readonly rate: BasisPoints;
|
|
45
|
+
}
|
|
46
|
+
type Account = AssetRule | LiabilityRule;
|
|
47
|
+
/** Snapshot balance at `Timeline.start`. A liability's amount is the positive amount owed. */
|
|
48
|
+
interface Balance {
|
|
49
|
+
readonly account: AccountId;
|
|
50
|
+
readonly amount: MinorUnits;
|
|
51
|
+
}
|
|
52
|
+
interface Baseline {
|
|
53
|
+
readonly schemaVersion: 1;
|
|
54
|
+
readonly balances: readonly Balance[];
|
|
55
|
+
}
|
|
56
|
+
/** One surplus step: fill `account` (up to `upTo` if given), then move to the next step. */
|
|
57
|
+
interface SurplusStep {
|
|
58
|
+
readonly account: AccountId;
|
|
59
|
+
readonly upTo?: MinorUnits;
|
|
60
|
+
}
|
|
61
|
+
interface Cashflow {
|
|
62
|
+
readonly surplus: readonly SurplusStep[];
|
|
63
|
+
/** Ordered withdrawal sources; locked accounts are skipped. */
|
|
64
|
+
readonly withdraw: readonly AccountId[];
|
|
65
|
+
}
|
|
66
|
+
interface FlowBase {
|
|
67
|
+
readonly id: string;
|
|
68
|
+
readonly amount: MinorUnits;
|
|
69
|
+
readonly frequency: Frequency;
|
|
70
|
+
readonly start: DateString;
|
|
71
|
+
/** Omitted means the flow runs to `Timeline.horizon`. A `once` flow omits it or equals `start`. */
|
|
72
|
+
readonly end?: DateString;
|
|
73
|
+
readonly growth: Growth;
|
|
74
|
+
}
|
|
75
|
+
interface IncomeFlow extends FlowBase {
|
|
76
|
+
readonly kind: "income";
|
|
77
|
+
/** Earned (true) versus passive (false) income. */
|
|
78
|
+
readonly earned: boolean;
|
|
79
|
+
}
|
|
80
|
+
interface ExpenseFlow extends FlowBase {
|
|
81
|
+
readonly kind: "expense";
|
|
82
|
+
}
|
|
83
|
+
/** Cash moves into `target`; a liability target is a debt payment, capped at the amount owed. */
|
|
84
|
+
interface ContributionFlow extends FlowBase {
|
|
85
|
+
readonly kind: "contribution";
|
|
86
|
+
readonly target: AccountId;
|
|
87
|
+
}
|
|
88
|
+
type Flow = IncomeFlow | ExpenseFlow | ContributionFlow;
|
|
89
|
+
interface AccountAmount {
|
|
90
|
+
readonly account: AccountId;
|
|
91
|
+
readonly amount: MinorUnits;
|
|
92
|
+
}
|
|
93
|
+
interface ProjectionRow {
|
|
94
|
+
readonly date: DateString;
|
|
95
|
+
readonly balances: readonly AccountAmount[];
|
|
96
|
+
readonly netWorth: MinorUnits;
|
|
97
|
+
readonly accessibleNetWorth: MinorUnits;
|
|
98
|
+
readonly realBalances: readonly AccountAmount[];
|
|
99
|
+
readonly realNetWorth: MinorUnits;
|
|
100
|
+
readonly realAccessibleNetWorth: MinorUnits;
|
|
101
|
+
}
|
|
102
|
+
interface AnnualRollup {
|
|
103
|
+
readonly index: number;
|
|
104
|
+
readonly from: DateString;
|
|
105
|
+
readonly to: DateString;
|
|
106
|
+
readonly openingNetWorth: MinorUnits;
|
|
107
|
+
readonly closingNetWorth: MinorUnits;
|
|
108
|
+
readonly income: MinorUnits;
|
|
109
|
+
readonly expense: MinorUnits;
|
|
110
|
+
readonly contributions: MinorUnits;
|
|
111
|
+
readonly interest: MinorUnits;
|
|
112
|
+
readonly unmet: MinorUnits;
|
|
113
|
+
readonly partial: boolean;
|
|
114
|
+
}
|
|
115
|
+
interface RunsOut {
|
|
116
|
+
readonly date: DateString;
|
|
117
|
+
readonly unmet: MinorUnits;
|
|
118
|
+
}
|
|
119
|
+
interface Projection {
|
|
120
|
+
readonly rows: readonly ProjectionRow[];
|
|
121
|
+
readonly annual: readonly AnnualRollup[];
|
|
122
|
+
readonly runsOut?: RunsOut;
|
|
123
|
+
}
|
|
124
|
+
interface InputProblem {
|
|
125
|
+
readonly code: ErrorCode;
|
|
126
|
+
readonly path: Path;
|
|
127
|
+
}
|
|
128
|
+
interface ValueOverflowProblem {
|
|
129
|
+
readonly code: "VALUE_OVERFLOW";
|
|
130
|
+
readonly date: DateString;
|
|
131
|
+
readonly account?: AccountId;
|
|
132
|
+
}
|
|
133
|
+
type ProjectionProblem = InputProblem | ValueOverflowProblem;
|
|
134
|
+
type ProjectionResult = {
|
|
135
|
+
readonly ok: true;
|
|
136
|
+
readonly projection: Projection;
|
|
137
|
+
} | {
|
|
138
|
+
readonly ok: false;
|
|
139
|
+
readonly problems: readonly ProjectionProblem[];
|
|
140
|
+
};
|
|
141
|
+
interface Economy {
|
|
142
|
+
readonly inflation: BasisPoints;
|
|
143
|
+
}
|
|
144
|
+
interface Scenario {
|
|
145
|
+
readonly schemaVersion: 1;
|
|
146
|
+
readonly currency: string;
|
|
147
|
+
readonly economy: Economy;
|
|
148
|
+
readonly accounts: readonly Account[];
|
|
149
|
+
readonly flows: readonly Flow[];
|
|
150
|
+
readonly cashflow: Cashflow;
|
|
151
|
+
}
|
|
152
|
+
interface Timeline {
|
|
153
|
+
readonly start: DateString;
|
|
154
|
+
readonly horizon: DateString;
|
|
155
|
+
readonly resolution: Resolution;
|
|
156
|
+
}
|
|
157
|
+
/** Runs `check` first, then the deterministic engine; never throws on valid inputs. */
|
|
158
|
+
export declare function project(baseline: Baseline, scenario: Scenario, timeline: Timeline): ProjectionResult;
|
|
159
|
+
export type { Account, AccountAmount, AccountId, AnnualRollup, AssetRule, Balance, Baseline, BasisPoints, Cashflow, ContributionFlow, DateString, Economy, ErrorCode, ExpenseFlow, Flow, Frequency, Growth, IncomeFlow, InputProblem, LiabilityRule, MinorUnits, Path, Problem, Projection, ProjectionProblem, ProjectionResult, ProjectionRow, Resolution, RunsOut, Scenario, SurplusStep, Timeline, ValueOverflowProblem };
|
|
160
|
+
//# sourceMappingURL=index.d.mts.map
|