@mulmoclaude/accounting-plugin 1.3.0 → 2.1.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.
Files changed (46) hide show
  1. package/dist/server/bodyFields.d.ts +2 -2
  2. package/dist/server/bodyFields.d.ts.map +1 -1
  3. package/dist/server/journal.d.ts +5 -5
  4. package/dist/server/journal.d.ts.map +1 -1
  5. package/dist/server/report.d.ts +2 -2
  6. package/dist/server/report.d.ts.map +1 -1
  7. package/dist/server/service.d.ts +24 -24
  8. package/dist/server/service.d.ts.map +1 -1
  9. package/dist/server/timeSeries.d.ts +1 -1
  10. package/dist/server/timeSeries.d.ts.map +1 -1
  11. package/dist/server.cjs +3 -2
  12. package/dist/server.cjs.map +1 -1
  13. package/dist/server.js +2 -1
  14. package/dist/server.js.map +1 -1
  15. package/dist/shared/types.d.ts +14 -14
  16. package/dist/shared/types.d.ts.map +1 -1
  17. package/dist/shared-BZAAF-I4.js.map +1 -1
  18. package/dist/shared-BpFVwa6Y.cjs.map +1 -1
  19. package/dist/style.css +7 -7
  20. package/dist/vue/api.d.ts +16 -16
  21. package/dist/vue/api.d.ts.map +1 -1
  22. package/dist/vue/components/AccountEditor.vue.d.ts +2 -2
  23. package/dist/vue/components/AccountRow.vue.d.ts +2 -2
  24. package/dist/vue/components/AccountsList.vue.d.ts +2 -2
  25. package/dist/vue/components/AccountsModal.vue.d.ts +2 -2
  26. package/dist/vue/components/BalanceSheet.vue.d.ts +1 -1
  27. package/dist/vue/components/BookSettings.vue.d.ts +4 -4
  28. package/dist/vue/components/BookSettings.vue.d.ts.map +1 -1
  29. package/dist/vue/components/BookSwitcher.vue.d.ts +3 -3
  30. package/dist/vue/components/DateRangePicker.vue.d.ts +2 -2
  31. package/dist/vue/components/DateRangePicker.vue.d.ts.map +1 -1
  32. package/dist/vue/components/JournalEntryForm.vue.d.ts +4 -4
  33. package/dist/vue/components/JournalEntryForm.vue.d.ts.map +1 -1
  34. package/dist/vue/components/JournalList.vue.d.ts +6 -6
  35. package/dist/vue/components/JournalList.vue.d.ts.map +1 -1
  36. package/dist/vue/components/Ledger.vue.d.ts +3 -3
  37. package/dist/vue/components/Ledger.vue.d.ts.map +1 -1
  38. package/dist/vue/components/NewBookForm.vue.d.ts +2 -2
  39. package/dist/vue/components/OpeningBalancesForm.vue.d.ts +1 -1
  40. package/dist/vue/components/ProfitLoss.vue.d.ts +3 -3
  41. package/dist/vue/components/ProfitLoss.vue.d.ts.map +1 -1
  42. package/dist/vue.cjs +4 -3
  43. package/dist/vue.cjs.map +1 -1
  44. package/dist/vue.js +4 -3
  45. package/dist/vue.js.map +1 -1
  46. package/package.json +7 -7
@@ -1 +1 @@
1
- {"version":3,"file":"shared-BpFVwa6Y.cjs","names":[],"sources":["../src/shared/actions.ts","../src/shared/api.ts","../src/shared/types.ts","../src/shared/channels.ts","../../../common/dist/index.js","../src/shared/paths.ts","../src/shared/fiscalYear.ts","../src/shared/countries.ts","../src/shared/currencies.ts","../src/shared/dates.ts","../src/shared/timeSeriesEnums.ts"],"sourcesContent":["// Single source of truth for the manageAccounting LLM-facing action\n// names. Used by:\n// - definition.ts (the JSON-schema action enum exposed to the LLM)\n// - api.ts (the View's REST helpers — `call(action, args)`)\n// - server/api/routes/accounting.ts (handler-table keys, PREVIEW\n// and MESSAGE_BUILDERS membership)\n// - e2e/fixtures/accounting.ts (mock dispatcher's handler-table)\n//\n// Stays in its own module so server-side callers can import the\n// const without pulling in apiPost / Vue plumbing from `api.ts`.\n//\n// CLAUDE.md \"no magic literals — use existing `as const` objects\"\n// applies here: never reference an action by raw string at any of\n// the call sites above.\n\nexport const ACCOUNTING_ACTIONS = {\n openBook: \"openBook\",\n getBooks: \"getBooks\",\n createBook: \"createBook\",\n updateBook: \"updateBook\",\n deleteBook: \"deleteBook\",\n getAccounts: \"getAccounts\",\n upsertAccount: \"upsertAccount\",\n addEntries: \"addEntries\",\n voidEntry: \"voidEntry\",\n getJournalEntries: \"getJournalEntries\",\n getOpeningBalances: \"getOpeningBalances\",\n setOpeningBalances: \"setOpeningBalances\",\n getReport: \"getReport\",\n getTimeSeries: \"getTimeSeries\",\n rebuildSnapshots: \"rebuildSnapshots\",\n} as const;\n\nexport type AccountingAction = (typeof ACCOUNTING_ACTIONS)[keyof typeof ACCOUNTING_ACTIONS];\n","// Single source of truth for the accounting REST contract — the one\n// dispatch route the plugin owns. Consumed by BOTH the Vue api client\n// (./vue/api.ts) and the server router (./server/router.ts) so the path\n// can't drift between them. Mirrors the host META's\n// `{ apiNamespace: \"accounting\", dispatch: { method: \"POST\", path: \"\" } }`\n// resolved to a full URL.\n//\n// (CLAUDE.md: API routes go through `as const` objects, never hardcoded\n// strings at the call site.)\n\nexport const ACCOUNTING_API = {\n dispatch: {\n path: \"/api/accounting\",\n method: \"POST\",\n },\n} as const;\n","// Single source of truth for the accounting domain + report shapes that\n// cross the server ↔ Vue boundary. Isomorphic (browser-safe): no `node:`\n// or Vue imports reach this graph, so both surfaces `import type` the SAME\n// declaration instead of hand-mirroring it. Adding a field here is seen by\n// server tsc and Vue tsc at once — the drift that lets an API response grow\n// while the frontend type stays stale (#2334) cannot happen.\n//\n// Server-only persistence shapes (AccountingConfig, MonthSnapshot) stay in\n// ./server/types.ts; those never reach the browser.\n\nimport type { SupportedCountryCode } from \"./countries\";\nimport type { FiscalYearEnd } from \"./fiscalYear\";\n\nexport const ACCOUNT_TYPES = [\"asset\", \"liability\", \"equity\", \"income\", \"expense\"] as const;\nexport type AccountType = (typeof ACCOUNT_TYPES)[number];\n\n/** B/S accounts (assets / liabilities / equity). Used by opening\n * balance validation: opening entries reference balance-sheet\n * accounts only. */\nexport const BALANCE_SHEET_ACCOUNT_TYPES: readonly AccountType[] = [\"asset\", \"liability\", \"equity\"];\n\nexport interface Account {\n /** Stable identifier the journal lines reference. Typically a\n * numeric string (\"1000\" / \"2000\" …) but free-form is allowed\n * so the user can adopt their existing numbering. */\n code: string;\n name: string;\n type: AccountType;\n /** Optional free-form note (tax bucket, parent group, …). Not\n * interpreted by the engine — passes through verbatim. */\n note?: string;\n /** Soft-delete flag. When `false`, the account is hidden from\n * entry/ledger dropdowns but stays visible in Manage Accounts\n * and historical entries — accounting integrity requires that\n * a code referenced by a journal line never disappears. Omitted\n * (treated as active) by default to keep the JSON files clean\n * for books created before this field existed. */\n active?: boolean;\n}\n\nexport interface BookSummary {\n id: string;\n name: string;\n /** ISO 4217 (e.g. \"USD\" / \"JPY\"). Single-currency per book — no\n * cross-book aggregation. */\n currency: string;\n /** ISO 3166-1 alpha-2 country code (e.g. \"US\" / \"JP\" / \"GB\").\n * Identifies the tax jurisdiction the book is kept under so the\n * Accounting role can give country-aware advice (Japanese T-number\n * under インボイス制度, EU VAT ID, GSTIN, ABN, etc.). Constrained\n * to `SupportedCountryCode` (the curated list shared with the UI\n * dropdown and the LLM tool's JSON-schema enum) so a typo from any\n * ingress path is rejected at the service layer rather than silently\n * persisted. Optional for backward compatibility with books created\n * before the field was introduced; the UI prompts existing books\n * to set it. */\n country?: SupportedCountryCode;\n /** Calendar month (1-12) on whose LAST DAY the book's fiscal year\n * closes — e.g. 8 = August 31, 12 = December 31 (calendar year).\n * Drives the UI's \"current quarter / current year\" date-range\n * shortcuts. Optional in the persisted shape for backward\n * compatibility with books written before this field existed (and\n * with the earlier \"Q1\"..\"Q4\" token form) — read-side code\n * normalises both via `resolveFiscalYearEnd`, treating an absent\n * value as December. New books require it at the create boundary;\n * the default is 12 (December). */\n fiscalYearEnd?: FiscalYearEnd;\n createdAt: string;\n}\n\nexport const JOURNAL_ENTRY_KINDS = [\"normal\", \"opening\", \"void\", \"void-marker\"] as const;\nexport type JournalEntryKind = (typeof JOURNAL_ENTRY_KINDS)[number];\n\nexport interface JournalLine {\n accountCode: string;\n /** Use exactly one of debit / credit per line, both as positive\n * numbers. The engine treats them as separate fields rather than\n * a single signed amount so the input matches a standard\n * bookkeeping form. */\n debit?: number;\n credit?: number;\n /** Per-line memo (the entry-level memo lives on JournalEntry). */\n memo?: string;\n /** Counterparty's tax-authority-issued registration ID for this\n * line — Japanese 適格請求書発行事業者登録番号 (T-number), EU\n * VAT identification number, UK VAT registration number, India\n * GSTIN, Australia ABN, etc. Required for input-tax-credit\n * eligibility under the Japanese インボイス制度 (effective\n * 2023-10-01) and equivalent regimes elsewhere. Free-form string;\n * format validation belongs upstream (per-jurisdiction). */\n taxRegistrationId?: string;\n}\n\nexport interface JournalEntry {\n /** Globally unique within a book — ULID-style; ordering by id\n * reproduces creation order. */\n id: string;\n /** Calendar date the entry is booked for (YYYY-MM-DD). The month\n * part decides which `journal/YYYY-MM.jsonl` file the entry lives\n * in; entries can be for any past / future date. */\n date: string;\n kind: JournalEntryKind;\n lines: JournalLine[];\n /** Entry-level memo. */\n memo?: string;\n /** When `kind === \"void-marker\"`: id of the entry being voided.\n * When `kind === \"void\"`: the system-generated reverse entry\n * references the original via this field. */\n voidedEntryId?: string;\n /** Reason supplied by the user when voiding. */\n voidReason?: string;\n /** When this entry was posted via the \"edit\" flow (void-then-add),\n * this is the id of the entry it replaces. The void + new-entry\n * pair is *not* atomic on the server — the client issues two\n * sequential calls — but recording the link here makes the\n * edit chain queryable later (e.g. \"what corrected entry X?\"). */\n replacesEntryId?: string;\n /** ISO timestamp the entry was appended to the journal — the\n * authoritative \"when did this hit the books\" clock. Distinct\n * from `date`, which is the user-visible booking date. */\n createdAt: string;\n}\n\n/** Aggregated balance per account at a point in time. The signed\n * number is debit − credit; downstream display logic converts to\n * natural sign per account type (assets debit-positive, liabilities\n * credit-positive). */\nexport interface AccountBalance {\n accountCode: string;\n /** Σ debit − Σ credit across all entries up to and including the\n * snapshot's period end. */\n netDebit: number;\n}\n\n/** Period selector for reports. Either a single closing month or a\n * date range. Always inclusive on both ends. */\nexport type ReportPeriod = { kind: \"month\"; period: string } | { kind: \"range\"; from: string; to: string };\n\n// ── Report result shapes (server computes, Vue renders) ──────────────\n\nexport interface BalanceSheetSection {\n type: AccountType;\n rows: { accountCode: string; accountName: string; balance: number }[];\n total: number;\n}\n\nexport interface BalanceSheet {\n asOf: string; // ISO date; period end\n sections: BalanceSheetSection[];\n /** Σ assets − Σ (liabilities + equity). Should be 0 (the\n * accounting equation); a non-zero here indicates either a\n * rounding artefact or a data problem. */\n imbalance: number;\n}\n\nexport interface ProfitLoss {\n from: string; // inclusive ISO date\n to: string; // inclusive ISO date\n income: { rows: { accountCode: string; accountName: string; amount: number }[]; total: number };\n expense: { rows: { accountCode: string; accountName: string; amount: number }[]; total: number };\n netIncome: number; // income − expense\n}\n\nexport interface LedgerRow {\n entryId: string;\n date: string;\n kind: JournalEntryKind;\n memo?: string;\n debit: number;\n credit: number;\n /** Running netDebit balance for this account, in entry order. */\n runningBalance: number;\n /** Counterparty tax-registration ID copied from the source\n * journal line (T-number / VAT ID / GSTIN / ABN). Surfaced as a\n * Ledger column when the active account is in the input-tax\n * band (14xx — see `isTaxAccountCode` in\n * src/vue/components/accountNumbering.ts). Carried per row even on\n * non-tax accounts so a future view that wants to show it\n * elsewhere doesn't need a server change. */\n taxRegistrationId?: string;\n}\n\nexport interface Ledger {\n accountCode: string;\n accountName: string;\n rows: LedgerRow[];\n /** Closing netDebit balance — the sum at the bottom of `rows`. */\n closingBalance: number;\n}\n","// Per-book event-stream contract for the accounting plugin — the\n// reusable channel-name factory + event-kind enum + payload shape.\n// Single source of truth for both publishers (the package's server\n// surface, `eventPublisher`) and subscribers (the Vue View's\n// `useAccountingChannel`), so anyone branching on event kind imports\n// from here and the type system catches drift on either side.\n//\n// Lives in the package's `./shared` (browser-safe) rather than the\n// host META because the backend needs it too — keeping it host-side\n// would force an uphill import. The host-wiring META (toolName /\n// apiNamespace / workspaceDirs / staticChannels) stays in the host's\n// `src/plugins/accounting/meta.ts` so the plugin-barrel codegen\n// discovers it.\n//\n// Browser-safe: no Vue imports, no server-only imports.\n\n/** Channel factory for per-book event streams. Subscribers:\n * `useAccountingChannel(bookId)`. Publisher: the package's server\n * surface `eventPublisher`. */\nexport function bookChannel(bookId: string): string {\n return `accounting:${bookId}`;\n}\n\n/** Book-list-level channel — a book was created / deleted. Subscribers\n * refetch the BookSwitcher dropdown. Mirrors the host META's\n * `staticChannels.accountingBooks` literal (kept in sync by value;\n * the host META stays the codegen-discoverable source for the\n * aggregator merge). */\nexport const ACCOUNTING_BOOKS_CHANNEL = \"accounting:books\";\n\n/** Event kinds that ride `bookChannel(bookId)`. Single source of\n * truth for both publishers (server/accounting) and subscribers\n * (the View) — anyone branching on event kind imports from here\n * and the type system catches drift on either side.\n *\n * - `journal` — addEntry / voidEntry hit the books at `period`.\n * Refetch the journal list and (if the View is\n * showing balances at or after `period`) the\n * relevant report.\n * - `opening` — setOpeningBalances. Affects every period from\n * the opening date forward; refetch everything.\n * - `accounts` — chart-of-accounts mutation that may affect\n * aggregation (account type changed). Refetch\n * accounts and the active report.\n * - `snapshotsRebuilding` / `snapshotsReady` — purely informational;\n * the View can show a \"calculating\" spinner\n * during rebuild, but the lazy-rebuild safety\n * net means a refetch always returns the right\n * answer regardless. */\nexport const BOOK_EVENT_KINDS = {\n journal: \"journal\",\n opening: \"opening\",\n accounts: \"accounts\",\n snapshotsRebuilding: \"snapshots-rebuilding\",\n snapshotsReady: \"snapshots-ready\",\n} as const;\n\nexport type BookEventKind = (typeof BOOK_EVENT_KINDS)[keyof typeof BOOK_EVENT_KINDS];\n\n/** Payload published on `bookChannel(bookId)`. */\nexport interface BookChannelPayload {\n kind: BookEventKind;\n /** YYYY-MM. Present for `journal` (entry month) and the snapshot\n * events (the earliest invalidated month). Absent for `opening`\n * (which invalidates everything) and `accounts`. */\n period?: string;\n}\n","// General-purpose runtime type guards, shared across the MulmoClaude host,\n// bridges, and plugins. This is a leaf package — pure and dependency-free — so\n// any tier can import it without creating an uphill edge.\n//\n// These originated as `server/utils/types.ts` (#504), which centralised 40+\n// hand-written inline `typeof x === \"object\"` checks. They are promoted here so\n// the same guards stop being re-hand-written in every bridge and plugin too.\n/** Narrow `unknown` to a plain object (not null, not array). */\nexport function isRecord(value) {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n/** Narrow `unknown` to any object (not null, arrays allowed).\n * Use `isRecord` when you need to access string keys. */\nexport function isObj(value) {\n return typeof value === \"object\" && value !== null;\n}\n/** Non-empty string after trimming whitespace. */\nexport function isNonEmptyString(value) {\n return typeof value === \"string\" && value.trim().length > 0;\n}\n/** Record whose values are all strings. */\nexport function isStringRecord(value) {\n if (!isRecord(value))\n return false;\n return Object.values(value).every((val) => typeof val === \"string\");\n}\n/** String array (every element is a string). */\nexport function isStringArray(value) {\n return Array.isArray(value) && value.every((val) => typeof val === \"string\");\n}\n/** An array of unknowns. Prefer this over a bare `Array.isArray` in typed code:\n * `Array.isArray(x: unknown)` narrows to `any[]`, silently reintroducing\n * `any`, whereas this keeps the element type `unknown`. */\nexport function isUnknownArray(value) {\n return Array.isArray(value);\n}\n/** Error-like object with a `code` property (e.g. Node.js fs errors). */\nexport function isErrorWithCode(value) {\n return isRecord(value) && typeof value.code === \"string\";\n}\n/** Check that a record has a specific key with a string value. */\nexport function hasStringProp(value, key) {\n return isRecord(value) && typeof value[key] === \"string\";\n}\n/** Check that a record has a specific key with a number value. */\nexport function hasNumberProp(value, key) {\n return isRecord(value) && typeof value[key] === \"number\";\n}\n/** Split a comma-separated env value into trimmed, non-empty entries.\n * `lowercase` folds case for identifiers compared case-insensitively\n * (JIDs, email addresses, hex pubkeys). Absent/empty input → empty list. */\nexport function parseCsvList(raw, opts) {\n return (raw ?? \"\")\n .split(\",\")\n .map((entry) => (opts?.lowercase ? entry.trim().toLowerCase() : entry.trim()))\n .filter(Boolean);\n}\n/** A comma-separated env value as a Set — the canonical allowlist shape,\n * where an empty set is the \"allow all\" sentinel (`set.size === 0`). */\nexport function parseCsvSet(raw, opts) {\n return new Set(parseCsvList(raw, opts));\n}\n/** Normalise an unknown thrown value into a human-readable string. Isomorphic\n * (host, bridges, plugins, Vue) — this is the single home for the helper that\n * #2217 could only consolidate for server code, since `@mulmoclaude/core/utils`\n * is server-only.\n *\n * A non-Error object with a non-empty string `details` (gRPC convention) or\n * `message` field surfaces that field — `details` wins — instead of the\n * `[object Object]` a bare `String(err)` would print; an empty-string field\n * falls through. `fallback` covers the error-boundary idiom where a thrown\n * non-Error should read as a descriptive message rather than `String(err)`\n * noise; omit it in logging contexts where `String(err)` is fine. */\nexport function errorMessage(err, fallback) {\n if (err instanceof Error)\n return err.message;\n if (hasStringProp(err, \"details\") && err.details)\n return err.details;\n if (hasStringProp(err, \"message\") && err.message)\n return err.message;\n if (fallback !== undefined)\n return fallback;\n return String(err);\n}\n/** `Date` → `YYYY-MM-DD` in UTC — for dates that must not shift with the\n * host's local timezone (tool-trace search dirs, API date keys). Isomorphic\n * single source (#2480): the host re-exports it from `server/utils/date.ts`,\n * x-plugin imports it directly. The `@receptron/task-scheduler` copy stays\n * local on purpose — that leaf package is published independently and kept\n * dependency-free. Wall-clock questions use the host's `toLocalIsoDate`. */\nexport function toUtcIsoDate(timestamp) {\n const year = timestamp.getUTCFullYear();\n const month = String(timestamp.getUTCMonth() + 1).padStart(2, \"0\");\n const day = String(timestamp.getUTCDate()).padStart(2, \"0\");\n return `${year}-${month}-${day}`;\n}\n// A Map, not an object literal: `{}[char]` reads through the prototype chain,\n// so a future caller widening the regex would silently get `[object Object]`\n// for keys like `constructor`.\nconst HTML_ESCAPES = new Map([\n [\"&\", \"&amp;\"],\n [\"<\", \"&lt;\"],\n [\">\", \"&gt;\"],\n ['\"', \"&quot;\"],\n [\"'\", \"&#39;\"],\n]);\n/** HTML-escape text destined for markup or an attribute value — the fixed\n * five-character map, nothing more. Lives here rather than in\n * `@mulmoclaude/core/wiki` (#2483) because `@mulmoclaude/markdown-utils` is a\n * leaf that core depends on and so cannot import back up; core/wiki\n * re-exports this, keeping its consumers' import path unchanged.\n *\n * Escaping `&` first is what makes a single pass safe — the entities this\n * introduces contain none of the other four characters, so nothing is\n * double-escaped. Not a sanitiser: it neither strips tags nor validates URLs. */\nexport function escapeHtml(value) {\n return value.replace(/[&<>\"']/g, (char) => HTML_ESCAPES.get(char) ?? char);\n}\nexport { scanEnvOptions, snakeToLowerCamel } from \"./envScan.js\";\n","// Workspace-relative directories this plugin owns. Single source of\n// truth, consumed by BOTH the server io layer (./server/io.ts) and the\n// host META (src/plugins/accounting/meta.ts → the WORKSPACE_DIRS\n// aggregator), so the on-disk layout can't drift between the backend\n// and the rest of the app.\n//\n// Browser-safe: no node:* imports.\n\nexport const ACCOUNTING_DIRS = {\n /** `data/accounting/config.json` + the books tree below. */\n accounting: \"data/accounting\",\n /** `data/accounting/books/<bookId>/{accounts.json, journal/, snapshots/}`. */\n accountingBooks: \"data/accounting/books\",\n} as const;\n","// Fiscal-year arithmetic for the accounting plugin.\n//\n// Each book stores a `fiscalYearEnd` = the calendar month (1-12) on\n// whose LAST DAY the book's fiscal year closes:\n//\n// 3 → fiscal year ends March 31 (FY runs Apr 1 → Mar 31)\n// 6 → fiscal year ends June 30 (FY runs Jul 1 → Jun 30)\n// 8 → fiscal year ends August 31 (FY runs Sep 1 → Aug 31)\n// 12 → fiscal year ends December 31 (FY runs Jan 1 → Dec 31; default)\n//\n// Any month is allowed — a corporation whose statutory closing date\n// is August 31 stores 8. The quarter / year arithmetic below is fully\n// parametric on the closing month, so a non-calendar-quarter close\n// (e.g. 8) just shifts the fiscal quarters accordingly.\n//\n// \"Current quarter\" / \"current year\" everywhere in the UI refer to\n// the *fiscal* quarter / *fiscal* year that contains today, under the\n// active book's `fiscalYearEnd`. For a December (12) book fiscal\n// quarters and fiscal years coincide with calendar quarters / calendar\n// years; for any other close a shift applies.\n//\n// Legacy books (written when the field was a calendar-quarter token\n// \"Q1\"..\"Q4\") are absorbed by `resolveFiscalYearEnd`, which maps the\n// old tokens to their closing month (Q1→3, Q2→6, Q3→9, Q4→12). The\n// on-disk value is only rewritten the next time the user saves the\n// book — same no-auto-migrate policy the field has always had.\n//\n// All helpers return `YYYY-MM-DD` strings in the user's local\n// timezone — same convention as `dates.ts`.\n\nexport const FISCAL_YEAR_END_MONTHS = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] as const;\nexport type FiscalYearEnd = (typeof FISCAL_YEAR_END_MONTHS)[number];\n\nexport const DEFAULT_FISCAL_YEAR_END: FiscalYearEnd = 12;\n\n/** Legacy calendar-quarter tokens → closing month, for books written\n * before the field became a month number. */\n// A Map rather than a plain record: the key is caller-supplied, and a\n// record lookup would resolve inherited prototype members (\"constructor\")\n// as if they were stored quarters.\nconst LEGACY_QUARTER_MONTHS = new Map<string, FiscalYearEnd>([\n [\"Q1\", 3],\n [\"Q2\", 6],\n [\"Q3\", 9],\n [\"Q4\", 12],\n]);\n\nexport function isFiscalYearEnd(value: unknown): value is FiscalYearEnd {\n return typeof value === \"number\" && Number.isInteger(value) && value >= 1 && value <= 12;\n}\n\n/** Normalise any stored / inbound value to a concrete closing month.\n * Absent or unrecognised → the default (December); a legacy \"Q1\"..\"Q4\"\n * token → its closing month; a valid 1-12 number → itself. Kept\n * tolerant (unknown input) so a legacy book read from disk — or shared\n * with an older MulmoTerminal — never breaks the UI or a report. */\nexport function resolveFiscalYearEnd(value: unknown): FiscalYearEnd {\n if (isFiscalYearEnd(value)) return value;\n const legacy = typeof value === \"string\" ? LEGACY_QUARTER_MONTHS.get(value) : undefined;\n return legacy ?? DEFAULT_FISCAL_YEAR_END;\n}\n\n/** Last calendar month (1-12) of the fiscal year. The stored token IS\n * the closing month now, so this reads as `resolveFiscalYearEnd` under\n * a name that states intent at the call sites (and still absorbs a\n * stray legacy token defensively). */\nexport function fiscalYearEndMonth(end: FiscalYearEnd): number {\n return resolveFiscalYearEnd(end);\n}\n\n/** Localised label for a fiscal-year-end month, showing that month's\n * last day — e.g. 8 → \"August 31\" / \"8月31日\" / \"31 de agosto\". Uses a\n * fixed non-leap reference year, so February reads as the 28th; this\n * is display only — the engine still computes the real last day\n * (Feb 29 in a leap year) at runtime. */\nexport function fiscalYearEndMonthLabel(month: FiscalYearEnd, locale: string): string {\n // UTC day 0 of the *next* month = last day of `month`, in a fixed\n // non-leap reference year (2001) so the label is stable and\n // timezone-independent.\n const lastDay = new Date(Date.UTC(2001, month, 0));\n try {\n return new Intl.DateTimeFormat(locale, { month: \"long\", day: \"numeric\", timeZone: \"UTC\" }).format(lastDay);\n } catch {\n return String(month);\n }\n}\n\nexport interface DateRange {\n /** Inclusive lower bound (YYYY-MM-DD). Empty string = unbounded. */\n from: string;\n /** Inclusive upper bound (YYYY-MM-DD). Empty string = unbounded. */\n to: string;\n}\n\nfunction pad2(num: number): string {\n return String(num).padStart(2, \"0\");\n}\n\nfunction lastDayOfMonth(year: number, monthZeroBased: number): number {\n // Day 0 of next month = last day of this month, all in local time.\n return new Date(year, monthZeroBased + 1, 0).getDate();\n}\n\nfunction ymd(year: number, monthOneBased: number, day: number): string {\n return `${year}-${pad2(monthOneBased)}-${pad2(day)}`;\n}\n\n/** Fiscal quarter index (0..3) of the given local date under `end`,\n * where 0 is the first quarter of the fiscal year (right after the\n * prior year's close) and 3 is the closing quarter. */\nfunction fiscalQuarterIndex(end: FiscalYearEnd, today: Date): number {\n const closingMonth = fiscalYearEndMonth(end); // 1-based\n const month = today.getMonth() + 1; // 1-based local month\n // Months past the close of the prior fiscal year, mod 12.\n const offset = (month - closingMonth - 1 + 12) % 12;\n return Math.floor(offset / 3);\n}\n\n/** Calendar (year, monthOneBased) of the *first* month of the fiscal\n * quarter at index `index` in the fiscal year that *contains*\n * `today`. Returned both as the first day of that month and as the\n * count of months covered (always 3 — exposed as a constant). */\nfunction fiscalQuarterStart(end: FiscalYearEnd, today: Date, index: number): { year: number; month: number } {\n const closingMonth = fiscalYearEndMonth(end);\n const todayMonth = today.getMonth() + 1;\n const todayYear = today.getFullYear();\n // Month after the close of the prior fiscal year — fiscal-year start month.\n const startMonth = (closingMonth % 12) + 1;\n // The fiscal year that contains `today` started in the calendar\n // year ≤ today's year. Specifically: if today's calendar month is\n // ≥ startMonth (or startMonth is 1, which is the Q4 case), the FY\n // started this calendar year; otherwise it started last year.\n const fyStartYear = todayMonth >= startMonth ? todayYear : todayYear - 1;\n // Month of the requested fiscal quarter's first month, expressed\n // as a 1-based offset from January of fyStartYear.\n const flatMonth = startMonth + index * 3; // 1-based, may exceed 12\n const year = fyStartYear + Math.floor((flatMonth - 1) / 12);\n const month = ((flatMonth - 1) % 12) + 1;\n return { year, month };\n}\n\nfunction quarterRangeAt(end: FiscalYearEnd, today: Date, index: number): DateRange {\n const start = fiscalQuarterStart(end, today, index);\n // Quarter spans 3 calendar months starting at `start`.\n const lastMonthFlat = start.month - 1 + 2; // 0-based offset of the third month\n const lastMonthYear = start.year + Math.floor(lastMonthFlat / 12);\n const lastMonth = (lastMonthFlat % 12) + 1; // 1-based\n const lastDay = lastDayOfMonth(lastMonthYear, lastMonth - 1);\n return {\n from: ymd(start.year, start.month, 1),\n to: ymd(lastMonthYear, lastMonth, lastDay),\n };\n}\n\nexport function currentQuarterRange(end: FiscalYearEnd, today: Date = new Date()): DateRange {\n return quarterRangeAt(end, today, fiscalQuarterIndex(end, today));\n}\n\nexport function previousQuarterRange(end: FiscalYearEnd, today: Date = new Date()): DateRange {\n const idx = fiscalQuarterIndex(end, today);\n if (idx > 0) return quarterRangeAt(end, today, idx - 1);\n // Wrap to Q4 of the prior fiscal year. Step `today` back 3 months\n // — that lands inside the prior fiscal year regardless of `end`,\n // and Q4 (closing) is index 3 within whichever FY contains it.\n const stepped = new Date(today.getFullYear(), today.getMonth() - 3, 1);\n return quarterRangeAt(end, stepped, 3);\n}\n\n/** Current fiscal year — Q0 start through Q3 close. */\nexport function currentFiscalYearRange(end: FiscalYearEnd, today: Date = new Date()): DateRange {\n const first = quarterRangeAt(end, today, 0);\n const last = quarterRangeAt(end, today, 3);\n return { from: first.from, to: last.to };\n}\n\nexport function previousFiscalYearRange(end: FiscalYearEnd, today: Date = new Date()): DateRange {\n // Step a year back so `quarterRangeAt` resolves the prior FY.\n const stepped = new Date(today.getFullYear() - 1, today.getMonth(), today.getDate());\n return currentFiscalYearRange(end, stepped);\n}\n","// Country utilities for the accounting plugin.\n//\n// The book's country (ISO 3166-1 alpha-2) identifies the tax\n// jurisdiction the book is kept under. The Accounting role uses it\n// to give country-aware advice — Japanese T-number under\n// インボイス制度, EU VAT ID, UK VAT, GSTIN, ABN, etc.\n//\n// Curated against the supported currency list and the tax-regime\n// guidance in `src/config/roles.ts` (Accounting role prompt).\n// Intl.DisplayNames provides the localized human name at render\n// time, so this stays a flat list of codes.\n\n/** ISO 3166-1 alpha-2 country codes shown in the book country\n * dropdown. Curated to cover every jurisdiction the Accounting role\n * has explicit tax-registration advice for, plus the major economies\n * represented in `SUPPORTED_CURRENCY_CODES`. */\nexport const SUPPORTED_COUNTRY_CODES = [\n \"US\",\n \"JP\",\n \"GB\",\n \"CA\",\n \"AU\",\n \"NZ\",\n \"DE\",\n \"FR\",\n \"IT\",\n \"ES\",\n \"NL\",\n \"BE\",\n \"AT\",\n \"IE\",\n \"PT\",\n \"FI\",\n \"SE\",\n \"DK\",\n \"PL\",\n \"CH\",\n \"NO\",\n \"CN\",\n \"KR\",\n \"TW\",\n \"HK\",\n \"SG\",\n \"IN\",\n \"BR\",\n \"MX\",\n] as const;\n\nexport type SupportedCountryCode = (typeof SUPPORTED_COUNTRY_CODES)[number];\n\n/** EU member states as of 2026. Used by the role-prompt advice path\n * to recommend a VAT identification number when the book country is\n * in the EU. */\nexport const EU_COUNTRY_CODES: ReadonlySet<string> = new Set([\n \"AT\",\n \"BE\",\n \"BG\",\n \"CY\",\n \"CZ\",\n \"DE\",\n \"DK\",\n \"EE\",\n \"ES\",\n \"FI\",\n \"FR\",\n \"GR\",\n \"HR\",\n \"HU\",\n \"IE\",\n \"IT\",\n \"LT\",\n \"LU\",\n \"LV\",\n \"MT\",\n \"NL\",\n \"PL\",\n \"PT\",\n \"RO\",\n \"SE\",\n \"SI\",\n \"SK\",\n]);\n\n/** Localized human name for a country code. Falls back to the code\n * itself if the runtime can't resolve the name. */\nexport function localizedCountryName(code: string, locale: string): string {\n try {\n return new Intl.DisplayNames([locale], { type: \"region\" }).of(code) ?? code;\n } catch {\n return code;\n }\n}\n\n/** Runtime guard for `BookSummary.country`. The type is the union\n * `SupportedCountryCode`, but every entry point that takes user /\n * LLM input arrives as raw `string` (form submit, JSON-RPC body),\n * so the service layer narrows here before persisting. */\nexport function isSupportedCountryCode(value: unknown): value is SupportedCountryCode {\n return SUPPORTED_COUNTRY_CODES.some((code) => code === value);\n}\n\n/** Country-gated UI features. Each key is a feature name; the value\n * is the set of country codes for which the feature is enabled.\n * Components ask `countryHasFeature(\"...\", country)` instead of\n * hard-coding country lists at the call site.\n *\n * Add a new country-specific feature by adding a new key here and\n * reading it via `countryHasFeature`. An unknown / undefined\n * country never has any feature — components fall back to neutral\n * default UI rather than guessing.\n *\n * Mirrors the \"Country-aware tax behaviour\" prose in the\n * Accounting role prompt (`src/config/roles.ts`). The two MUST\n * stay in sync — drift means the LLM and the form give the user\n * contradictory advice. The prompt is the source of truth for\n * agent behaviour; this table is structured-data sibling for the\n * form. */\nexport const COUNTRY_FEATURES = {\n /** Show an amber \"missing tax ID\" warning + helper text on a\n * postable 14xx (input-tax) line whose taxRegistrationId is\n * blank. Limited to jurisdictions where the role prompt\n * explicitly requires the counterparty registration number\n * (JP T-number, EU VAT ID, GB VAT, GSTIN, ABN, NZ GST, CA BN).\n * The \"other countries\" bucket and US (no federal sales-tax\n * registration) intentionally stay quiet. 24xx output-tax\n * lines don't trigger the warning — see `isTaxAccountCode`. */\n warnMissingTaxRegistrationId: new Set<SupportedCountryCode>([\n \"JP\",\n \"GB\",\n \"DE\",\n \"FR\",\n \"IT\",\n \"ES\",\n \"NL\",\n \"BE\",\n \"AT\",\n \"IE\",\n \"PT\",\n \"FI\",\n \"SE\",\n \"DK\",\n \"PL\",\n \"IN\",\n \"AU\",\n \"NZ\",\n \"CA\",\n ]),\n} as const;\n\nexport type CountryFeature = keyof typeof COUNTRY_FEATURES;\n\n/** Resolve a country-gated feature flag. Returns `false` when the\n * country is undefined / unsupported — components default to the\n * neutral path (no warning, no extra UI) rather than guessing. */\nexport function countryHasFeature(feature: CountryFeature, country: SupportedCountryCode | undefined): boolean {\n if (!country) return false;\n return COUNTRY_FEATURES[feature].has(country);\n}\n","// Currency utilities for the accounting plugin.\n//\n// We expose a curated list of ISO 4217 codes for the New Book\n// dropdown — covering the major reserve currencies plus the most\n// requested Asian / regional ones — plus per-currency formatting\n// helpers built on Intl.NumberFormat.\n//\n// The book's currency is per-book metadata (BookSummary.currency)\n// and only matters once the user has opened the book; cross-book\n// aggregation isn't supported.\n\n/** ISO 4217 codes shown in the New Book dropdown. Curated for\n * recognisability — Intl.DisplayNames provides the localised\n * human name at render time, so this stays a flat list of codes. */\nexport const SUPPORTED_CURRENCY_CODES = [\"USD\", \"EUR\", \"JPY\", \"GBP\", \"CNY\", \"KRW\", \"TWD\", \"HKD\", \"SGD\", \"AUD\", \"CAD\", \"CHF\", \"INR\", \"BRL\", \"MXN\"] as const;\n\nexport type SupportedCurrencyCode = (typeof SUPPORTED_CURRENCY_CODES)[number];\n\nconst DEFAULT_FALLBACK_DIGITS = 2;\n\n/** Localised human name for a currency code. Falls back to the\n * code itself if the runtime can't resolve the name. */\nexport function localizedCurrencyName(code: string, locale: string): string {\n try {\n return new Intl.DisplayNames([locale], { type: \"currency\" }).of(code) ?? code;\n } catch {\n return code;\n }\n}\n\n/** Number of fraction digits ISO 4217 specifies for a currency.\n * JPY = 0, USD = 2, KWD = 3. Used both for amount formatting and\n * for the HTML input step on debit/credit fields. */\nexport function fractionDigitsFor(currency: string): number {\n try {\n const opts = new Intl.NumberFormat(\"en\", { style: \"currency\", currency }).resolvedOptions();\n return opts.maximumFractionDigits ?? DEFAULT_FALLBACK_DIGITS;\n } catch {\n return DEFAULT_FALLBACK_DIGITS;\n }\n}\n\n/** \"1\" for JPY, \"0.01\" for USD, \"0.001\" for KWD. Used as the HTML\n * input step on debit/credit fields so a JPY book doesn't let the\n * user type cents that would just round-trip back through the\n * decimal validator. */\nexport function inputStepFor(currency: string): string {\n const digits = fractionDigitsFor(currency);\n if (digits === 0) return \"1\";\n return (1 / 10 ** digits).toFixed(digits);\n}\n\n/** Locale-aware currency formatter — returns \"¥1,130\" / \"$1,130.00\"\n * etc. Falls back to fixed-point formatting if the runtime can't\n * resolve the currency code; the fallback still respects the\n * currency's natural fraction-digit count so JPY shows whole\n * numbers even on the slow path. */\nexport function formatAmount(value: number, currency: string, locale?: string): string {\n try {\n return new Intl.NumberFormat(locale, { style: \"currency\", currency }).format(value);\n } catch {\n return value.toFixed(fractionDigitsFor(currency));\n }\n}\n\n/** Currency-agnostic amount formatter — \"1,130.00\" — for places that\n * don't carry the currency code on the data path (compact preview\n * envelopes etc.). Use `formatAmount(value, currency)` whenever the\n * currency IS available — the currency-aware path picks the right\n * fraction-digit count automatically (JPY = 0, USD = 2).\n *\n * `locale` mirrors `formatAmount`'s signature: pass an explicit BCP-47\n * locale (`\"en-US\"`, `\"ja-JP\"`, …) when the caller knows the desired\n * grouping / digit-shape; omit to fall back to the runtime default. */\nexport function formatAmountNumeric(value: number, decimals = 2, locale?: string): string {\n return value.toLocaleString(locale, { minimumFractionDigits: decimals, maximumFractionDigits: decimals });\n}\n","// Local-calendar date helpers for the accounting forms.\n//\n// Why not `new Date().toISOString().slice(0, 10)`? `toISOString` is\n// UTC. In a negative-offset zone (US Pacific, Eastern, …) the UTC\n// date crosses to \"tomorrow\" several hours before midnight local,\n// so a naively prefilled date input would post entries into the\n// wrong accounting day. Same mistake near month boundaries flips\n// the default Balance Sheet period to the next month.\n//\n// All four helpers below are pure local-calendar formatters built\n// from `getFullYear` / `getMonth` / `getDate`, which the JS engine\n// resolves in the user's local timezone.\n\nfunction pad2(num: number): string {\n return String(num).padStart(2, \"0\");\n}\n\n/** Today as `YYYY-MM-DD` in the user's local timezone. */\nexport function localDateString(now: Date = new Date()): string {\n return `${now.getFullYear()}-${pad2(now.getMonth() + 1)}-${pad2(now.getDate())}`;\n}\n\n/** Current month as `YYYY-MM` in the user's local timezone. */\nexport function localMonthString(now: Date = new Date()): string {\n return `${now.getFullYear()}-${pad2(now.getMonth() + 1)}`;\n}\n\n/** First day of the current calendar year as `YYYY-MM-DD`. */\nexport function localStartOfYearString(now: Date = new Date()): string {\n return `${now.getFullYear()}-01-01`;\n}\n\n/** Previous calendar month as `YYYY-MM` in the user's local timezone. */\nexport function previousMonthString(now: Date = new Date()): string {\n const target = new Date(now.getFullYear(), now.getMonth() - 1, 1);\n return `${target.getFullYear()}-${pad2(target.getMonth() + 1)}`;\n}\n\n/** Last month of the previous calendar quarter as `YYYY-MM`. Calendar\n * quarters: Q1=Jan–Mar, Q2=Apr–Jun, Q3=Jul–Sep, Q4=Oct–Dec. When the\n * current month is in Q1, this rolls back to December of last year. */\nexport function lastMonthOfPreviousQuarterString(now: Date = new Date()): string {\n const firstMonthOfCurrentQuarter = Math.floor(now.getMonth() / 3) * 3;\n const target = new Date(now.getFullYear(), firstMonthOfCurrentQuarter - 1, 1);\n return `${target.getFullYear()}-${pad2(target.getMonth() + 1)}`;\n}\n\n/** December of the previous calendar year as `YYYY-MM`. */\nexport function decemberOfPreviousYearString(now: Date = new Date()): string {\n return `${now.getFullYear() - 1}-12`;\n}\n","// Single source of truth for the `getTimeSeries` action's enum\n// surfaces — kept outside the server module so the frontend tool\n// definition (`definition.ts`) and the server validator\n// (`server/accounting/timeSeries.ts`) can both import without\n// crossing the src ↔ server boundary in the wrong direction.\n//\n// Adding a new metric / granularity: extend the array here, then\n// extend the corresponding switch / aggregation in\n// `server/accounting/timeSeries.ts`. The LLM tool schema picks up\n// the new value automatically via `definition.ts`'s `enum` field.\n\nexport const TIME_SERIES_METRICS = [\"revenue\", \"expense\", \"netIncome\", \"accountBalance\"] as const;\nexport type TimeSeriesMetric = (typeof TIME_SERIES_METRICS)[number];\n\nexport const TIME_SERIES_GRANULARITIES = [\"month\", \"quarter\", \"year\"] as const;\nexport type TimeSeriesGranularity = (typeof TIME_SERIES_GRANULARITIES)[number];\n"],"mappings":"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"}
1
+ {"version":3,"file":"shared-BpFVwa6Y.cjs","names":[],"sources":["../src/shared/actions.ts","../src/shared/api.ts","../src/shared/types.ts","../src/shared/channels.ts","../../../common/dist/index.js","../src/shared/paths.ts","../src/shared/fiscalYear.ts","../src/shared/countries.ts","../src/shared/currencies.ts","../src/shared/dates.ts","../src/shared/timeSeriesEnums.ts"],"sourcesContent":["// Single source of truth for the manageAccounting LLM-facing action\n// names. Used by:\n// - definition.ts (the JSON-schema action enum exposed to the LLM)\n// - api.ts (the View's REST helpers — `call(action, args)`)\n// - server/api/routes/accounting.ts (handler-table keys, PREVIEW\n// and MESSAGE_BUILDERS membership)\n// - e2e/fixtures/accounting.ts (mock dispatcher's handler-table)\n//\n// Stays in its own module so server-side callers can import the\n// const without pulling in apiPost / Vue plumbing from `api.ts`.\n//\n// CLAUDE.md \"no magic literals — use existing `as const` objects\"\n// applies here: never reference an action by raw string at any of\n// the call sites above.\n\nexport const ACCOUNTING_ACTIONS = {\n openBook: \"openBook\",\n getBooks: \"getBooks\",\n createBook: \"createBook\",\n updateBook: \"updateBook\",\n deleteBook: \"deleteBook\",\n getAccounts: \"getAccounts\",\n upsertAccount: \"upsertAccount\",\n addEntries: \"addEntries\",\n voidEntry: \"voidEntry\",\n getJournalEntries: \"getJournalEntries\",\n getOpeningBalances: \"getOpeningBalances\",\n setOpeningBalances: \"setOpeningBalances\",\n getReport: \"getReport\",\n getTimeSeries: \"getTimeSeries\",\n rebuildSnapshots: \"rebuildSnapshots\",\n} as const;\n\nexport type AccountingAction = (typeof ACCOUNTING_ACTIONS)[keyof typeof ACCOUNTING_ACTIONS];\n","// Single source of truth for the accounting REST contract — the one\n// dispatch route the plugin owns. Consumed by BOTH the Vue api client\n// (./vue/api.ts) and the server router (./server/router.ts) so the path\n// can't drift between them. Mirrors the host META's\n// `{ apiNamespace: \"accounting\", dispatch: { method: \"POST\", path: \"\" } }`\n// resolved to a full URL.\n//\n// (CLAUDE.md: API routes go through `as const` objects, never hardcoded\n// strings at the call site.)\n\nexport const ACCOUNTING_API = {\n dispatch: {\n path: \"/api/accounting\",\n method: \"POST\",\n },\n} as const;\n","// Single source of truth for the accounting domain + report shapes that\n// cross the server ↔ Vue boundary. Isomorphic (browser-safe): no `node:`\n// or Vue imports reach this graph, so both surfaces `import type` the SAME\n// declaration instead of hand-mirroring it. Adding a field here is seen by\n// server tsc and Vue tsc at once — the drift that lets an API response grow\n// while the frontend type stays stale (#2334) cannot happen.\n//\n// Server-only persistence shapes (AccountingConfig, MonthSnapshot) stay in\n// ./server/types.ts; those never reach the browser.\n\nimport type { SupportedCountryCode } from \"./countries\";\nimport type { FiscalYearEnd } from \"./fiscalYear\";\n\nexport const ACCOUNT_TYPES = [\"asset\", \"liability\", \"equity\", \"income\", \"expense\"] as const;\nexport type AccountType = (typeof ACCOUNT_TYPES)[number];\n\n/** B/S accounts (assets / liabilities / equity). Used by opening\n * balance validation: opening entries reference balance-sheet\n * accounts only. */\nexport const BALANCE_SHEET_ACCOUNT_TYPES: readonly AccountType[] = [\"asset\", \"liability\", \"equity\"];\n\nexport interface Account {\n /** Stable identifier the journal lines reference. Typically a\n * numeric string (\"1000\" / \"2000\" …) but free-form is allowed\n * so the user can adopt their existing numbering. */\n code: string;\n name: string;\n type: AccountType;\n /** Optional free-form note (tax bucket, parent group, …). Not\n * interpreted by the engine — passes through verbatim. */\n note?: string | undefined;\n /** Soft-delete flag. When `false`, the account is hidden from\n * entry/ledger dropdowns but stays visible in Manage Accounts\n * and historical entries — accounting integrity requires that\n * a code referenced by a journal line never disappears. Omitted\n * (treated as active) by default to keep the JSON files clean\n * for books created before this field existed. */\n active?: boolean | undefined;\n}\n\nexport interface BookSummary {\n id: string;\n name: string;\n /** ISO 4217 (e.g. \"USD\" / \"JPY\"). Single-currency per book — no\n * cross-book aggregation. */\n currency: string;\n /** ISO 3166-1 alpha-2 country code (e.g. \"US\" / \"JP\" / \"GB\").\n * Identifies the tax jurisdiction the book is kept under so the\n * Accounting role can give country-aware advice (Japanese T-number\n * under インボイス制度, EU VAT ID, GSTIN, ABN, etc.). Constrained\n * to `SupportedCountryCode` (the curated list shared with the UI\n * dropdown and the LLM tool's JSON-schema enum) so a typo from any\n * ingress path is rejected at the service layer rather than silently\n * persisted. Optional for backward compatibility with books created\n * before the field was introduced; the UI prompts existing books\n * to set it. */\n country?: SupportedCountryCode | undefined;\n /** Calendar month (1-12) on whose LAST DAY the book's fiscal year\n * closes — e.g. 8 = August 31, 12 = December 31 (calendar year).\n * Drives the UI's \"current quarter / current year\" date-range\n * shortcuts. Optional in the persisted shape for backward\n * compatibility with books written before this field existed (and\n * with the earlier \"Q1\"..\"Q4\" token form) — read-side code\n * normalises both via `resolveFiscalYearEnd`, treating an absent\n * value as December. New books require it at the create boundary;\n * the default is 12 (December). */\n fiscalYearEnd?: FiscalYearEnd | undefined;\n createdAt: string;\n}\n\nexport const JOURNAL_ENTRY_KINDS = [\"normal\", \"opening\", \"void\", \"void-marker\"] as const;\nexport type JournalEntryKind = (typeof JOURNAL_ENTRY_KINDS)[number];\n\nexport interface JournalLine {\n accountCode: string;\n /** Use exactly one of debit / credit per line, both as positive\n * numbers. The engine treats them as separate fields rather than\n * a single signed amount so the input matches a standard\n * bookkeeping form. */\n debit?: number | undefined;\n credit?: number | undefined;\n /** Per-line memo (the entry-level memo lives on JournalEntry). */\n memo?: string | undefined;\n /** Counterparty's tax-authority-issued registration ID for this\n * line — Japanese 適格請求書発行事業者登録番号 (T-number), EU\n * VAT identification number, UK VAT registration number, India\n * GSTIN, Australia ABN, etc. Required for input-tax-credit\n * eligibility under the Japanese インボイス制度 (effective\n * 2023-10-01) and equivalent regimes elsewhere. Free-form string;\n * format validation belongs upstream (per-jurisdiction). */\n taxRegistrationId?: string | undefined;\n}\n\nexport interface JournalEntry {\n /** Globally unique within a book — ULID-style; ordering by id\n * reproduces creation order. */\n id: string;\n /** Calendar date the entry is booked for (YYYY-MM-DD). The month\n * part decides which `journal/YYYY-MM.jsonl` file the entry lives\n * in; entries can be for any past / future date. */\n date: string;\n kind: JournalEntryKind;\n lines: JournalLine[];\n /** Entry-level memo. */\n memo?: string | undefined;\n /** When `kind === \"void-marker\"`: id of the entry being voided.\n * When `kind === \"void\"`: the system-generated reverse entry\n * references the original via this field. */\n voidedEntryId?: string | undefined;\n /** Reason supplied by the user when voiding. */\n voidReason?: string | undefined;\n /** When this entry was posted via the \"edit\" flow (void-then-add),\n * this is the id of the entry it replaces. The void + new-entry\n * pair is *not* atomic on the server — the client issues two\n * sequential calls — but recording the link here makes the\n * edit chain queryable later (e.g. \"what corrected entry X?\"). */\n replacesEntryId?: string | undefined;\n /** ISO timestamp the entry was appended to the journal — the\n * authoritative \"when did this hit the books\" clock. Distinct\n * from `date`, which is the user-visible booking date. */\n createdAt: string;\n}\n\n/** Aggregated balance per account at a point in time. The signed\n * number is debit − credit; downstream display logic converts to\n * natural sign per account type (assets debit-positive, liabilities\n * credit-positive). */\nexport interface AccountBalance {\n accountCode: string;\n /** Σ debit − Σ credit across all entries up to and including the\n * snapshot's period end. */\n netDebit: number;\n}\n\n/** Period selector for reports. Either a single closing month or a\n * date range. Always inclusive on both ends. */\nexport type ReportPeriod = { kind: \"month\"; period: string } | { kind: \"range\"; from: string; to: string };\n\n// ── Report result shapes (server computes, Vue renders) ──────────────\n\nexport interface BalanceSheetSection {\n type: AccountType;\n rows: { accountCode: string; accountName: string; balance: number }[];\n total: number;\n}\n\nexport interface BalanceSheet {\n asOf: string; // ISO date; period end\n sections: BalanceSheetSection[];\n /** Σ assets − Σ (liabilities + equity). Should be 0 (the\n * accounting equation); a non-zero here indicates either a\n * rounding artefact or a data problem. */\n imbalance: number;\n}\n\nexport interface ProfitLoss {\n from: string; // inclusive ISO date\n to: string; // inclusive ISO date\n income: { rows: { accountCode: string; accountName: string; amount: number }[]; total: number };\n expense: { rows: { accountCode: string; accountName: string; amount: number }[]; total: number };\n netIncome: number; // income − expense\n}\n\nexport interface LedgerRow {\n entryId: string;\n date: string;\n kind: JournalEntryKind;\n memo?: string | undefined;\n debit: number;\n credit: number;\n /** Running netDebit balance for this account, in entry order. */\n runningBalance: number;\n /** Counterparty tax-registration ID copied from the source\n * journal line (T-number / VAT ID / GSTIN / ABN). Surfaced as a\n * Ledger column when the active account is in the input-tax\n * band (14xx — see `isTaxAccountCode` in\n * src/vue/components/accountNumbering.ts). Carried per row even on\n * non-tax accounts so a future view that wants to show it\n * elsewhere doesn't need a server change. */\n taxRegistrationId?: string | undefined;\n}\n\nexport interface Ledger {\n accountCode: string;\n accountName: string;\n rows: LedgerRow[];\n /** Closing netDebit balance — the sum at the bottom of `rows`. */\n closingBalance: number;\n}\n","// Per-book event-stream contract for the accounting plugin — the\n// reusable channel-name factory + event-kind enum + payload shape.\n// Single source of truth for both publishers (the package's server\n// surface, `eventPublisher`) and subscribers (the Vue View's\n// `useAccountingChannel`), so anyone branching on event kind imports\n// from here and the type system catches drift on either side.\n//\n// Lives in the package's `./shared` (browser-safe) rather than the\n// host META because the backend needs it too — keeping it host-side\n// would force an uphill import. The host-wiring META (toolName /\n// apiNamespace / workspaceDirs / staticChannels) stays in the host's\n// `src/plugins/accounting/meta.ts` so the plugin-barrel codegen\n// discovers it.\n//\n// Browser-safe: no Vue imports, no server-only imports.\n\n/** Channel factory for per-book event streams. Subscribers:\n * `useAccountingChannel(bookId)`. Publisher: the package's server\n * surface `eventPublisher`. */\nexport function bookChannel(bookId: string): string {\n return `accounting:${bookId}`;\n}\n\n/** Book-list-level channel — a book was created / deleted. Subscribers\n * refetch the BookSwitcher dropdown. Mirrors the host META's\n * `staticChannels.accountingBooks` literal (kept in sync by value;\n * the host META stays the codegen-discoverable source for the\n * aggregator merge). */\nexport const ACCOUNTING_BOOKS_CHANNEL = \"accounting:books\";\n\n/** Event kinds that ride `bookChannel(bookId)`. Single source of\n * truth for both publishers (server/accounting) and subscribers\n * (the View) — anyone branching on event kind imports from here\n * and the type system catches drift on either side.\n *\n * - `journal` — addEntry / voidEntry hit the books at `period`.\n * Refetch the journal list and (if the View is\n * showing balances at or after `period`) the\n * relevant report.\n * - `opening` — setOpeningBalances. Affects every period from\n * the opening date forward; refetch everything.\n * - `accounts` — chart-of-accounts mutation that may affect\n * aggregation (account type changed). Refetch\n * accounts and the active report.\n * - `snapshotsRebuilding` / `snapshotsReady` — purely informational;\n * the View can show a \"calculating\" spinner\n * during rebuild, but the lazy-rebuild safety\n * net means a refetch always returns the right\n * answer regardless. */\nexport const BOOK_EVENT_KINDS = {\n journal: \"journal\",\n opening: \"opening\",\n accounts: \"accounts\",\n snapshotsRebuilding: \"snapshots-rebuilding\",\n snapshotsReady: \"snapshots-ready\",\n} as const;\n\nexport type BookEventKind = (typeof BOOK_EVENT_KINDS)[keyof typeof BOOK_EVENT_KINDS];\n\n/** Payload published on `bookChannel(bookId)`. */\nexport interface BookChannelPayload {\n kind: BookEventKind;\n /** YYYY-MM. Present for `journal` (entry month) and the snapshot\n * events (the earliest invalidated month). Absent for `opening`\n * (which invalidates everything) and `accounts`. */\n period?: string;\n}\n","// General-purpose runtime type guards, shared across the MulmoClaude host,\n// bridges, and plugins. This is a leaf package — pure and dependency-free — so\n// any tier can import it without creating an uphill edge.\n//\n// These originated as `server/utils/types.ts` (#504), which centralised 40+\n// hand-written inline `typeof x === \"object\"` checks. They are promoted here so\n// the same guards stop being re-hand-written in every bridge and plugin too.\n/** Narrow `unknown` to a plain object (not null, not array). */\nexport function isRecord(value) {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n/** Narrow `unknown` to any object (not null, arrays allowed).\n * Use `isRecord` when you need to access string keys. */\nexport function isObj(value) {\n return typeof value === \"object\" && value !== null;\n}\n/** Non-empty string after trimming whitespace. */\nexport function isNonEmptyString(value) {\n return typeof value === \"string\" && value.trim().length > 0;\n}\n/** Record whose values are all strings. */\nexport function isStringRecord(value) {\n if (!isRecord(value))\n return false;\n return Object.values(value).every((val) => typeof val === \"string\");\n}\n/** String array (every element is a string). */\nexport function isStringArray(value) {\n return Array.isArray(value) && value.every((val) => typeof val === \"string\");\n}\n/** An array of unknowns. Prefer this over a bare `Array.isArray` in typed code:\n * `Array.isArray(x: unknown)` narrows to `any[]`, silently reintroducing\n * `any`, whereas this keeps the element type `unknown`. */\nexport function isUnknownArray(value) {\n return Array.isArray(value);\n}\n/** Error-like object with a `code` property (e.g. Node.js fs errors). */\nexport function isErrorWithCode(value) {\n return isRecord(value) && typeof value.code === \"string\";\n}\n/** Check that a record has a specific key with a string value. */\nexport function hasStringProp(value, key) {\n return isRecord(value) && typeof value[key] === \"string\";\n}\n/** Check that a record has a specific key with a number value. */\nexport function hasNumberProp(value, key) {\n return isRecord(value) && typeof value[key] === \"number\";\n}\n/** Split a comma-separated env value into trimmed, non-empty entries.\n * `lowercase` folds case for identifiers compared case-insensitively\n * (JIDs, email addresses, hex pubkeys). Absent/empty input → empty list. */\nexport function parseCsvList(raw, opts) {\n return (raw ?? \"\")\n .split(\",\")\n .map((entry) => (opts?.lowercase ? entry.trim().toLowerCase() : entry.trim()))\n .filter(Boolean);\n}\n/** A comma-separated env value as a Set — the canonical allowlist shape,\n * where an empty set is the \"allow all\" sentinel (`set.size === 0`). */\nexport function parseCsvSet(raw, opts) {\n return new Set(parseCsvList(raw, opts));\n}\n/** Normalise an unknown thrown value into a human-readable string. Isomorphic\n * (host, bridges, plugins, Vue) — this is the single home for the helper that\n * #2217 could only consolidate for server code, since `@mulmoclaude/core/utils`\n * is server-only.\n *\n * A non-Error object with a non-empty string `details` (gRPC convention) or\n * `message` field surfaces that field — `details` wins — instead of the\n * `[object Object]` a bare `String(err)` would print; an empty-string field\n * falls through. `fallback` covers the error-boundary idiom where a thrown\n * non-Error should read as a descriptive message rather than `String(err)`\n * noise; omit it in logging contexts where `String(err)` is fine. */\nexport function errorMessage(err, fallback) {\n if (err instanceof Error)\n return err.message;\n if (hasStringProp(err, \"details\") && err.details)\n return err.details;\n if (hasStringProp(err, \"message\") && err.message)\n return err.message;\n if (fallback !== undefined)\n return fallback;\n return String(err);\n}\n/** `Date` → `YYYY-MM-DD` in UTC — for dates that must not shift with the\n * host's local timezone (tool-trace search dirs, API date keys). Isomorphic\n * single source (#2480): the host re-exports it from `server/utils/date.ts`,\n * x-plugin imports it directly. The `@receptron/task-scheduler` copy stays\n * local on purpose — that leaf package is published independently and kept\n * dependency-free. Wall-clock questions use the host's `toLocalIsoDate`. */\nexport function toUtcIsoDate(timestamp) {\n const year = timestamp.getUTCFullYear();\n const month = String(timestamp.getUTCMonth() + 1).padStart(2, \"0\");\n const day = String(timestamp.getUTCDate()).padStart(2, \"0\");\n return `${year}-${month}-${day}`;\n}\n// A Map, not an object literal: `{}[char]` reads through the prototype chain,\n// so a future caller widening the regex would silently get `[object Object]`\n// for keys like `constructor`.\nconst HTML_ESCAPES = new Map([\n [\"&\", \"&amp;\"],\n [\"<\", \"&lt;\"],\n [\">\", \"&gt;\"],\n ['\"', \"&quot;\"],\n [\"'\", \"&#39;\"],\n]);\n/** HTML-escape text destined for markup or an attribute value — the fixed\n * five-character map, nothing more. Lives here rather than in\n * `@mulmoclaude/core/wiki` (#2483) because `@mulmoclaude/markdown-utils` is a\n * leaf that core depends on and so cannot import back up; core/wiki\n * re-exports this, keeping its consumers' import path unchanged.\n *\n * Escaping `&` first is what makes a single pass safe — the entities this\n * introduces contain none of the other four characters, so nothing is\n * double-escaped. Not a sanitiser: it neither strips tags nor validates URLs. */\nexport function escapeHtml(value) {\n return value.replace(/[&<>\"']/g, (char) => HTML_ESCAPES.get(char) ?? char);\n}\n/** Split a JWS compact serialization into its three segments, or `null` when the\n * token isn't well-formed. Pure string work, so the Node bridges and the\n * Cloudflare Workers relay — which decode the segments differently (`Buffer` vs\n * `atob`) — can still share this one guard.\n *\n * A JWS compact serialization is EXACTLY three segments. Both a short token and\n * a longer one (a five-segment JWE, or an attacker appending `.junk`) are\n * rejected outright — never parsed from their first three segments, which would\n * let the signed input disagree with the token. */\nexport function splitJwtSegments(token) {\n const [headerSegment, payloadSegment, signatureSegment, ...extraSegments] = token.split(\".\");\n if (headerSegment === undefined || payloadSegment === undefined || signatureSegment === undefined)\n return null;\n if (extraSegments.length > 0)\n return null;\n return { headerSegment, payloadSegment, signatureSegment };\n}\nexport { scanEnvOptions, snakeToLowerCamel } from \"./envScan.js\";\n","// Workspace-relative directories this plugin owns. Single source of\n// truth, consumed by BOTH the server io layer (./server/io.ts) and the\n// host META (src/plugins/accounting/meta.ts → the WORKSPACE_DIRS\n// aggregator), so the on-disk layout can't drift between the backend\n// and the rest of the app.\n//\n// Browser-safe: no node:* imports.\n\nexport const ACCOUNTING_DIRS = {\n /** `data/accounting/config.json` + the books tree below. */\n accounting: \"data/accounting\",\n /** `data/accounting/books/<bookId>/{accounts.json, journal/, snapshots/}`. */\n accountingBooks: \"data/accounting/books\",\n} as const;\n","// Fiscal-year arithmetic for the accounting plugin.\n//\n// Each book stores a `fiscalYearEnd` = the calendar month (1-12) on\n// whose LAST DAY the book's fiscal year closes:\n//\n// 3 → fiscal year ends March 31 (FY runs Apr 1 → Mar 31)\n// 6 → fiscal year ends June 30 (FY runs Jul 1 → Jun 30)\n// 8 → fiscal year ends August 31 (FY runs Sep 1 → Aug 31)\n// 12 → fiscal year ends December 31 (FY runs Jan 1 → Dec 31; default)\n//\n// Any month is allowed — a corporation whose statutory closing date\n// is August 31 stores 8. The quarter / year arithmetic below is fully\n// parametric on the closing month, so a non-calendar-quarter close\n// (e.g. 8) just shifts the fiscal quarters accordingly.\n//\n// \"Current quarter\" / \"current year\" everywhere in the UI refer to\n// the *fiscal* quarter / *fiscal* year that contains today, under the\n// active book's `fiscalYearEnd`. For a December (12) book fiscal\n// quarters and fiscal years coincide with calendar quarters / calendar\n// years; for any other close a shift applies.\n//\n// Legacy books (written when the field was a calendar-quarter token\n// \"Q1\"..\"Q4\") are absorbed by `resolveFiscalYearEnd`, which maps the\n// old tokens to their closing month (Q1→3, Q2→6, Q3→9, Q4→12). The\n// on-disk value is only rewritten the next time the user saves the\n// book — same no-auto-migrate policy the field has always had.\n//\n// All helpers return `YYYY-MM-DD` strings in the user's local\n// timezone — same convention as `dates.ts`.\n\nexport const FISCAL_YEAR_END_MONTHS = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] as const;\nexport type FiscalYearEnd = (typeof FISCAL_YEAR_END_MONTHS)[number];\n\nexport const DEFAULT_FISCAL_YEAR_END: FiscalYearEnd = 12;\n\n/** Legacy calendar-quarter tokens → closing month, for books written\n * before the field became a month number. */\n// A Map rather than a plain record: the key is caller-supplied, and a\n// record lookup would resolve inherited prototype members (\"constructor\")\n// as if they were stored quarters.\nconst LEGACY_QUARTER_MONTHS = new Map<string, FiscalYearEnd>([\n [\"Q1\", 3],\n [\"Q2\", 6],\n [\"Q3\", 9],\n [\"Q4\", 12],\n]);\n\nexport function isFiscalYearEnd(value: unknown): value is FiscalYearEnd {\n return typeof value === \"number\" && Number.isInteger(value) && value >= 1 && value <= 12;\n}\n\n/** Normalise any stored / inbound value to a concrete closing month.\n * Absent or unrecognised → the default (December); a legacy \"Q1\"..\"Q4\"\n * token → its closing month; a valid 1-12 number → itself. Kept\n * tolerant (unknown input) so a legacy book read from disk — or shared\n * with an older MulmoTerminal — never breaks the UI or a report. */\nexport function resolveFiscalYearEnd(value: unknown): FiscalYearEnd {\n if (isFiscalYearEnd(value)) return value;\n const legacy = typeof value === \"string\" ? LEGACY_QUARTER_MONTHS.get(value) : undefined;\n return legacy ?? DEFAULT_FISCAL_YEAR_END;\n}\n\n/** Last calendar month (1-12) of the fiscal year. The stored token IS\n * the closing month now, so this reads as `resolveFiscalYearEnd` under\n * a name that states intent at the call sites (and still absorbs a\n * stray legacy token defensively). */\nexport function fiscalYearEndMonth(end: FiscalYearEnd): number {\n return resolveFiscalYearEnd(end);\n}\n\n/** Localised label for a fiscal-year-end month, showing that month's\n * last day — e.g. 8 → \"August 31\" / \"8月31日\" / \"31 de agosto\". Uses a\n * fixed non-leap reference year, so February reads as the 28th; this\n * is display only — the engine still computes the real last day\n * (Feb 29 in a leap year) at runtime. */\nexport function fiscalYearEndMonthLabel(month: FiscalYearEnd, locale: string): string {\n // UTC day 0 of the *next* month = last day of `month`, in a fixed\n // non-leap reference year (2001) so the label is stable and\n // timezone-independent.\n const lastDay = new Date(Date.UTC(2001, month, 0));\n try {\n return new Intl.DateTimeFormat(locale, { month: \"long\", day: \"numeric\", timeZone: \"UTC\" }).format(lastDay);\n } catch {\n return String(month);\n }\n}\n\nexport interface DateRange {\n /** Inclusive lower bound (YYYY-MM-DD). Empty string = unbounded. */\n from: string;\n /** Inclusive upper bound (YYYY-MM-DD). Empty string = unbounded. */\n to: string;\n}\n\nfunction pad2(num: number): string {\n return String(num).padStart(2, \"0\");\n}\n\nfunction lastDayOfMonth(year: number, monthZeroBased: number): number {\n // Day 0 of next month = last day of this month, all in local time.\n return new Date(year, monthZeroBased + 1, 0).getDate();\n}\n\nfunction ymd(year: number, monthOneBased: number, day: number): string {\n return `${year}-${pad2(monthOneBased)}-${pad2(day)}`;\n}\n\n/** Fiscal quarter index (0..3) of the given local date under `end`,\n * where 0 is the first quarter of the fiscal year (right after the\n * prior year's close) and 3 is the closing quarter. */\nfunction fiscalQuarterIndex(end: FiscalYearEnd, today: Date): number {\n const closingMonth = fiscalYearEndMonth(end); // 1-based\n const month = today.getMonth() + 1; // 1-based local month\n // Months past the close of the prior fiscal year, mod 12.\n const offset = (month - closingMonth - 1 + 12) % 12;\n return Math.floor(offset / 3);\n}\n\n/** Calendar (year, monthOneBased) of the *first* month of the fiscal\n * quarter at index `index` in the fiscal year that *contains*\n * `today`. Returned both as the first day of that month and as the\n * count of months covered (always 3 — exposed as a constant). */\nfunction fiscalQuarterStart(end: FiscalYearEnd, today: Date, index: number): { year: number; month: number } {\n const closingMonth = fiscalYearEndMonth(end);\n const todayMonth = today.getMonth() + 1;\n const todayYear = today.getFullYear();\n // Month after the close of the prior fiscal year — fiscal-year start month.\n const startMonth = (closingMonth % 12) + 1;\n // The fiscal year that contains `today` started in the calendar\n // year ≤ today's year. Specifically: if today's calendar month is\n // ≥ startMonth (or startMonth is 1, which is the Q4 case), the FY\n // started this calendar year; otherwise it started last year.\n const fyStartYear = todayMonth >= startMonth ? todayYear : todayYear - 1;\n // Month of the requested fiscal quarter's first month, expressed\n // as a 1-based offset from January of fyStartYear.\n const flatMonth = startMonth + index * 3; // 1-based, may exceed 12\n const year = fyStartYear + Math.floor((flatMonth - 1) / 12);\n const month = ((flatMonth - 1) % 12) + 1;\n return { year, month };\n}\n\nfunction quarterRangeAt(end: FiscalYearEnd, today: Date, index: number): DateRange {\n const start = fiscalQuarterStart(end, today, index);\n // Quarter spans 3 calendar months starting at `start`.\n const lastMonthFlat = start.month - 1 + 2; // 0-based offset of the third month\n const lastMonthYear = start.year + Math.floor(lastMonthFlat / 12);\n const lastMonth = (lastMonthFlat % 12) + 1; // 1-based\n const lastDay = lastDayOfMonth(lastMonthYear, lastMonth - 1);\n return {\n from: ymd(start.year, start.month, 1),\n to: ymd(lastMonthYear, lastMonth, lastDay),\n };\n}\n\nexport function currentQuarterRange(end: FiscalYearEnd, today: Date = new Date()): DateRange {\n return quarterRangeAt(end, today, fiscalQuarterIndex(end, today));\n}\n\nexport function previousQuarterRange(end: FiscalYearEnd, today: Date = new Date()): DateRange {\n const idx = fiscalQuarterIndex(end, today);\n if (idx > 0) return quarterRangeAt(end, today, idx - 1);\n // Wrap to Q4 of the prior fiscal year. Step `today` back 3 months\n // — that lands inside the prior fiscal year regardless of `end`,\n // and Q4 (closing) is index 3 within whichever FY contains it.\n const stepped = new Date(today.getFullYear(), today.getMonth() - 3, 1);\n return quarterRangeAt(end, stepped, 3);\n}\n\n/** Current fiscal year — Q0 start through Q3 close. */\nexport function currentFiscalYearRange(end: FiscalYearEnd, today: Date = new Date()): DateRange {\n const first = quarterRangeAt(end, today, 0);\n const last = quarterRangeAt(end, today, 3);\n return { from: first.from, to: last.to };\n}\n\nexport function previousFiscalYearRange(end: FiscalYearEnd, today: Date = new Date()): DateRange {\n // Step a year back so `quarterRangeAt` resolves the prior FY.\n const stepped = new Date(today.getFullYear() - 1, today.getMonth(), today.getDate());\n return currentFiscalYearRange(end, stepped);\n}\n","// Country utilities for the accounting plugin.\n//\n// The book's country (ISO 3166-1 alpha-2) identifies the tax\n// jurisdiction the book is kept under. The Accounting role uses it\n// to give country-aware advice — Japanese T-number under\n// インボイス制度, EU VAT ID, UK VAT, GSTIN, ABN, etc.\n//\n// Curated against the supported currency list and the tax-regime\n// guidance in `src/config/roles.ts` (Accounting role prompt).\n// Intl.DisplayNames provides the localized human name at render\n// time, so this stays a flat list of codes.\n\n/** ISO 3166-1 alpha-2 country codes shown in the book country\n * dropdown. Curated to cover every jurisdiction the Accounting role\n * has explicit tax-registration advice for, plus the major economies\n * represented in `SUPPORTED_CURRENCY_CODES`. */\nexport const SUPPORTED_COUNTRY_CODES = [\n \"US\",\n \"JP\",\n \"GB\",\n \"CA\",\n \"AU\",\n \"NZ\",\n \"DE\",\n \"FR\",\n \"IT\",\n \"ES\",\n \"NL\",\n \"BE\",\n \"AT\",\n \"IE\",\n \"PT\",\n \"FI\",\n \"SE\",\n \"DK\",\n \"PL\",\n \"CH\",\n \"NO\",\n \"CN\",\n \"KR\",\n \"TW\",\n \"HK\",\n \"SG\",\n \"IN\",\n \"BR\",\n \"MX\",\n] as const;\n\nexport type SupportedCountryCode = (typeof SUPPORTED_COUNTRY_CODES)[number];\n\n/** EU member states as of 2026. Used by the role-prompt advice path\n * to recommend a VAT identification number when the book country is\n * in the EU. */\nexport const EU_COUNTRY_CODES: ReadonlySet<string> = new Set([\n \"AT\",\n \"BE\",\n \"BG\",\n \"CY\",\n \"CZ\",\n \"DE\",\n \"DK\",\n \"EE\",\n \"ES\",\n \"FI\",\n \"FR\",\n \"GR\",\n \"HR\",\n \"HU\",\n \"IE\",\n \"IT\",\n \"LT\",\n \"LU\",\n \"LV\",\n \"MT\",\n \"NL\",\n \"PL\",\n \"PT\",\n \"RO\",\n \"SE\",\n \"SI\",\n \"SK\",\n]);\n\n/** Localized human name for a country code. Falls back to the code\n * itself if the runtime can't resolve the name. */\nexport function localizedCountryName(code: string, locale: string): string {\n try {\n return new Intl.DisplayNames([locale], { type: \"region\" }).of(code) ?? code;\n } catch {\n return code;\n }\n}\n\n/** Runtime guard for `BookSummary.country`. The type is the union\n * `SupportedCountryCode`, but every entry point that takes user /\n * LLM input arrives as raw `string` (form submit, JSON-RPC body),\n * so the service layer narrows here before persisting. */\nexport function isSupportedCountryCode(value: unknown): value is SupportedCountryCode {\n return SUPPORTED_COUNTRY_CODES.some((code) => code === value);\n}\n\n/** Country-gated UI features. Each key is a feature name; the value\n * is the set of country codes for which the feature is enabled.\n * Components ask `countryHasFeature(\"...\", country)` instead of\n * hard-coding country lists at the call site.\n *\n * Add a new country-specific feature by adding a new key here and\n * reading it via `countryHasFeature`. An unknown / undefined\n * country never has any feature — components fall back to neutral\n * default UI rather than guessing.\n *\n * Mirrors the \"Country-aware tax behaviour\" prose in the\n * Accounting role prompt (`src/config/roles.ts`). The two MUST\n * stay in sync — drift means the LLM and the form give the user\n * contradictory advice. The prompt is the source of truth for\n * agent behaviour; this table is structured-data sibling for the\n * form. */\nexport const COUNTRY_FEATURES = {\n /** Show an amber \"missing tax ID\" warning + helper text on a\n * postable 14xx (input-tax) line whose taxRegistrationId is\n * blank. Limited to jurisdictions where the role prompt\n * explicitly requires the counterparty registration number\n * (JP T-number, EU VAT ID, GB VAT, GSTIN, ABN, NZ GST, CA BN).\n * The \"other countries\" bucket and US (no federal sales-tax\n * registration) intentionally stay quiet. 24xx output-tax\n * lines don't trigger the warning — see `isTaxAccountCode`. */\n warnMissingTaxRegistrationId: new Set<SupportedCountryCode>([\n \"JP\",\n \"GB\",\n \"DE\",\n \"FR\",\n \"IT\",\n \"ES\",\n \"NL\",\n \"BE\",\n \"AT\",\n \"IE\",\n \"PT\",\n \"FI\",\n \"SE\",\n \"DK\",\n \"PL\",\n \"IN\",\n \"AU\",\n \"NZ\",\n \"CA\",\n ]),\n} as const;\n\nexport type CountryFeature = keyof typeof COUNTRY_FEATURES;\n\n/** Resolve a country-gated feature flag. Returns `false` when the\n * country is undefined / unsupported — components default to the\n * neutral path (no warning, no extra UI) rather than guessing. */\nexport function countryHasFeature(feature: CountryFeature, country: SupportedCountryCode | undefined): boolean {\n if (!country) return false;\n return COUNTRY_FEATURES[feature].has(country);\n}\n","// Currency utilities for the accounting plugin.\n//\n// We expose a curated list of ISO 4217 codes for the New Book\n// dropdown — covering the major reserve currencies plus the most\n// requested Asian / regional ones — plus per-currency formatting\n// helpers built on Intl.NumberFormat.\n//\n// The book's currency is per-book metadata (BookSummary.currency)\n// and only matters once the user has opened the book; cross-book\n// aggregation isn't supported.\n\n/** ISO 4217 codes shown in the New Book dropdown. Curated for\n * recognisability — Intl.DisplayNames provides the localised\n * human name at render time, so this stays a flat list of codes. */\nexport const SUPPORTED_CURRENCY_CODES = [\"USD\", \"EUR\", \"JPY\", \"GBP\", \"CNY\", \"KRW\", \"TWD\", \"HKD\", \"SGD\", \"AUD\", \"CAD\", \"CHF\", \"INR\", \"BRL\", \"MXN\"] as const;\n\nexport type SupportedCurrencyCode = (typeof SUPPORTED_CURRENCY_CODES)[number];\n\nconst DEFAULT_FALLBACK_DIGITS = 2;\n\n/** Localised human name for a currency code. Falls back to the\n * code itself if the runtime can't resolve the name. */\nexport function localizedCurrencyName(code: string, locale: string): string {\n try {\n return new Intl.DisplayNames([locale], { type: \"currency\" }).of(code) ?? code;\n } catch {\n return code;\n }\n}\n\n/** Number of fraction digits ISO 4217 specifies for a currency.\n * JPY = 0, USD = 2, KWD = 3. Used both for amount formatting and\n * for the HTML input step on debit/credit fields. */\nexport function fractionDigitsFor(currency: string): number {\n try {\n const opts = new Intl.NumberFormat(\"en\", { style: \"currency\", currency }).resolvedOptions();\n return opts.maximumFractionDigits ?? DEFAULT_FALLBACK_DIGITS;\n } catch {\n return DEFAULT_FALLBACK_DIGITS;\n }\n}\n\n/** \"1\" for JPY, \"0.01\" for USD, \"0.001\" for KWD. Used as the HTML\n * input step on debit/credit fields so a JPY book doesn't let the\n * user type cents that would just round-trip back through the\n * decimal validator. */\nexport function inputStepFor(currency: string): string {\n const digits = fractionDigitsFor(currency);\n if (digits === 0) return \"1\";\n return (1 / 10 ** digits).toFixed(digits);\n}\n\n/** Locale-aware currency formatter — returns \"¥1,130\" / \"$1,130.00\"\n * etc. Falls back to fixed-point formatting if the runtime can't\n * resolve the currency code; the fallback still respects the\n * currency's natural fraction-digit count so JPY shows whole\n * numbers even on the slow path. */\nexport function formatAmount(value: number, currency: string, locale?: string): string {\n try {\n return new Intl.NumberFormat(locale, { style: \"currency\", currency }).format(value);\n } catch {\n return value.toFixed(fractionDigitsFor(currency));\n }\n}\n\n/** Currency-agnostic amount formatter — \"1,130.00\" — for places that\n * don't carry the currency code on the data path (compact preview\n * envelopes etc.). Use `formatAmount(value, currency)` whenever the\n * currency IS available — the currency-aware path picks the right\n * fraction-digit count automatically (JPY = 0, USD = 2).\n *\n * `locale` mirrors `formatAmount`'s signature: pass an explicit BCP-47\n * locale (`\"en-US\"`, `\"ja-JP\"`, …) when the caller knows the desired\n * grouping / digit-shape; omit to fall back to the runtime default. */\nexport function formatAmountNumeric(value: number, decimals = 2, locale?: string): string {\n return value.toLocaleString(locale, { minimumFractionDigits: decimals, maximumFractionDigits: decimals });\n}\n","// Local-calendar date helpers for the accounting forms.\n//\n// Why not `new Date().toISOString().slice(0, 10)`? `toISOString` is\n// UTC. In a negative-offset zone (US Pacific, Eastern, …) the UTC\n// date crosses to \"tomorrow\" several hours before midnight local,\n// so a naively prefilled date input would post entries into the\n// wrong accounting day. Same mistake near month boundaries flips\n// the default Balance Sheet period to the next month.\n//\n// All four helpers below are pure local-calendar formatters built\n// from `getFullYear` / `getMonth` / `getDate`, which the JS engine\n// resolves in the user's local timezone.\n\nfunction pad2(num: number): string {\n return String(num).padStart(2, \"0\");\n}\n\n/** Today as `YYYY-MM-DD` in the user's local timezone. */\nexport function localDateString(now: Date = new Date()): string {\n return `${now.getFullYear()}-${pad2(now.getMonth() + 1)}-${pad2(now.getDate())}`;\n}\n\n/** Current month as `YYYY-MM` in the user's local timezone. */\nexport function localMonthString(now: Date = new Date()): string {\n return `${now.getFullYear()}-${pad2(now.getMonth() + 1)}`;\n}\n\n/** First day of the current calendar year as `YYYY-MM-DD`. */\nexport function localStartOfYearString(now: Date = new Date()): string {\n return `${now.getFullYear()}-01-01`;\n}\n\n/** Previous calendar month as `YYYY-MM` in the user's local timezone. */\nexport function previousMonthString(now: Date = new Date()): string {\n const target = new Date(now.getFullYear(), now.getMonth() - 1, 1);\n return `${target.getFullYear()}-${pad2(target.getMonth() + 1)}`;\n}\n\n/** Last month of the previous calendar quarter as `YYYY-MM`. Calendar\n * quarters: Q1=Jan–Mar, Q2=Apr–Jun, Q3=Jul–Sep, Q4=Oct–Dec. When the\n * current month is in Q1, this rolls back to December of last year. */\nexport function lastMonthOfPreviousQuarterString(now: Date = new Date()): string {\n const firstMonthOfCurrentQuarter = Math.floor(now.getMonth() / 3) * 3;\n const target = new Date(now.getFullYear(), firstMonthOfCurrentQuarter - 1, 1);\n return `${target.getFullYear()}-${pad2(target.getMonth() + 1)}`;\n}\n\n/** December of the previous calendar year as `YYYY-MM`. */\nexport function decemberOfPreviousYearString(now: Date = new Date()): string {\n return `${now.getFullYear() - 1}-12`;\n}\n","// Single source of truth for the `getTimeSeries` action's enum\n// surfaces — kept outside the server module so the frontend tool\n// definition (`definition.ts`) and the server validator\n// (`server/accounting/timeSeries.ts`) can both import without\n// crossing the src ↔ server boundary in the wrong direction.\n//\n// Adding a new metric / granularity: extend the array here, then\n// extend the corresponding switch / aggregation in\n// `server/accounting/timeSeries.ts`. The LLM tool schema picks up\n// the new value automatically via `definition.ts`'s `enum` field.\n\nexport const TIME_SERIES_METRICS = [\"revenue\", \"expense\", \"netIncome\", \"accountBalance\"] as const;\nexport type TimeSeriesMetric = (typeof TIME_SERIES_METRICS)[number];\n\nexport const TIME_SERIES_GRANULARITIES = [\"month\", \"quarter\", \"year\"] as const;\nexport type TimeSeriesGranularity = (typeof TIME_SERIES_GRANULARITIES)[number];\n"],"mappings":"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"}
package/dist/style.css CHANGED
@@ -1206,12 +1206,12 @@
1206
1206
  step attribute still controls validation; this is purely UI.
1207
1207
  Accounting amount fields don't benefit from a spinner — users
1208
1208
  type the number and the up/down arrows just clutter the row. */
1209
- input[type="number"][data-v-ba23c744]::-webkit-outer-spin-button,
1210
- input[type="number"][data-v-ba23c744]::-webkit-inner-spin-button {
1209
+ input[type="number"][data-v-d5dcae53]::-webkit-outer-spin-button,
1210
+ input[type="number"][data-v-d5dcae53]::-webkit-inner-spin-button {
1211
1211
  -webkit-appearance: none;
1212
1212
  margin: 0;
1213
1213
  }
1214
- input[type="number"][data-v-ba23c744] {
1214
+ input[type="number"][data-v-d5dcae53] {
1215
1215
  -moz-appearance: textfield;
1216
1216
  appearance: textfield;
1217
1217
  }
@@ -1223,17 +1223,17 @@ input[type="number"][data-v-ba23c744] {
1223
1223
  left/right/bottom, so together they read as one rectangle around
1224
1224
  the selection. Color matches the focus-ring blue used elsewhere
1225
1225
  in this list. */
1226
- .row-selected > td[data-v-7446c210] {
1226
+ .row-selected > td[data-v-8ec9519f] {
1227
1227
  background-color: rgb(239 246 255); /* tailwind blue-50 */
1228
1228
  border-top: 2px solid rgb(59 130 246); /* tailwind blue-500 */
1229
1229
  }
1230
- .row-selected > td[data-v-7446c210]:first-child {
1230
+ .row-selected > td[data-v-8ec9519f]:first-child {
1231
1231
  border-left: 2px solid rgb(59 130 246);
1232
1232
  }
1233
- .row-selected > td[data-v-7446c210]:last-child {
1233
+ .row-selected > td[data-v-8ec9519f]:last-child {
1234
1234
  border-right: 2px solid rgb(59 130 246);
1235
1235
  }
1236
- .detail-selected > td[data-v-7446c210] {
1236
+ .detail-selected > td[data-v-8ec9519f] {
1237
1237
  background-color: rgb(239 246 255);
1238
1238
  border-left: 2px solid rgb(59 130 246);
1239
1239
  border-right: 2px solid rgb(59 130 246);
package/dist/vue/api.d.ts CHANGED
@@ -6,32 +6,32 @@ export interface OpenAppPayload {
6
6
  /** `null` when the workspace has zero books — the View renders the
7
7
  * empty state and prompts for book creation. */
8
8
  bookId: string | null;
9
- initialTab?: string;
9
+ initialTab?: string | undefined;
10
10
  }
11
11
  export declare function getBooks(): Promise<ApiResult<{
12
12
  books: BookSummary[];
13
13
  }>>;
14
14
  export declare function createBook(input: {
15
15
  name: string;
16
- currency?: string;
17
- country?: SupportedCountryCode;
16
+ currency?: string | undefined;
17
+ country?: SupportedCountryCode | undefined;
18
18
  /** Closing month 1-12 — required at the form boundary, but the
19
19
  * server silently defaults an absent value to 12 (December). */
20
- fiscalYearEnd?: FiscalYearEnd;
20
+ fiscalYearEnd?: FiscalYearEnd | undefined;
21
21
  }): Promise<ApiResult<{
22
22
  book: BookSummary;
23
23
  }>>;
24
24
  export declare function updateBook(input: {
25
25
  bookId: string;
26
- name?: string;
26
+ name?: string | undefined;
27
27
  /** Pass `""` to explicitly clear the country (server treats it as
28
28
  * the "drop the field" sentinel). Any other value must be one of
29
29
  * the curated `SupportedCountryCode`s. */
30
- country?: SupportedCountryCode | "";
30
+ country?: SupportedCountryCode | "" | undefined;
31
31
  /** Closing month 1-12 — pure metadata, only changes how the
32
32
  * date-range shortcuts resolve. No "clear" path; absence leaves the
33
33
  * existing value untouched. */
34
- fiscalYearEnd?: FiscalYearEnd;
34
+ fiscalYearEnd?: FiscalYearEnd | undefined;
35
35
  }): Promise<ApiResult<{
36
36
  book: BookSummary;
37
37
  }>>;
@@ -51,12 +51,12 @@ export declare function upsertAccount(account: Account, bookId: string): Promise
51
51
  export interface AddEntriesItemInput {
52
52
  date: string;
53
53
  lines: JournalLine[];
54
- memo?: string;
54
+ memo?: string | undefined;
55
55
  /** When set, marks this entry as the replacement posted via the
56
56
  * "edit" flow. The caller is expected to have voided
57
57
  * `replacesEntryId` separately just before this call — there is
58
58
  * no atomic transaction. */
59
- replacesEntryId?: string;
59
+ replacesEntryId?: string | undefined;
60
60
  }
61
61
  export declare function addEntries(input: {
62
62
  bookId: string;
@@ -70,7 +70,7 @@ export declare function addEntries(input: {
70
70
  }>>;
71
71
  export declare function voidEntry(input: {
72
72
  entryId: string;
73
- reason?: string;
73
+ reason?: string | undefined;
74
74
  bookId: string;
75
75
  }): Promise<ApiResult<{
76
76
  bookId: string;
@@ -78,9 +78,9 @@ export declare function voidEntry(input: {
78
78
  markerEntry: JournalEntry;
79
79
  }>>;
80
80
  export declare function getJournalEntries(input: {
81
- from?: string;
82
- to?: string;
83
- accountCode?: string;
81
+ from?: string | undefined;
82
+ to?: string | undefined;
83
+ accountCode?: string | undefined;
84
84
  bookId: string;
85
85
  }): Promise<ApiResult<{
86
86
  bookId: string;
@@ -94,7 +94,7 @@ export declare function getOpeningBalances(bookId: string): Promise<ApiResult<{
94
94
  export declare function setOpeningBalances(input: {
95
95
  asOfDate: string;
96
96
  lines: JournalLine[];
97
- memo?: string;
97
+ memo?: string | undefined;
98
98
  bookId: string;
99
99
  }): Promise<ApiResult<{
100
100
  bookId: string;
@@ -131,7 +131,7 @@ export interface TimeSeriesInput {
131
131
  to: string;
132
132
  /** Required when metric === "accountBalance"; forbidden otherwise.
133
133
  * The server returns a 400 either way. */
134
- accountCode?: string;
134
+ accountCode?: string | undefined;
135
135
  }
136
136
  export interface TimeSeriesResult {
137
137
  bookId: string;
@@ -139,7 +139,7 @@ export interface TimeSeriesResult {
139
139
  granularity: TimeSeriesGranularity;
140
140
  from: string;
141
141
  to: string;
142
- accountCode?: string;
142
+ accountCode?: string | undefined;
143
143
  points: TimeSeriesPoint[];
144
144
  }
145
145
  export declare function getTimeSeries(input: TimeSeriesInput): Promise<ApiResult<TimeSeriesResult>>;
@@ -1 +1 @@
1
- {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/vue/api.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/vue/api.ts"],"names":[],"mappings":"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"}
@@ -11,8 +11,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
11
11
  cancel: () => any;
12
12
  save: (draft: AccountDraft) => any;
13
13
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
14
- onCancel?: (() => any) | undefined;
15
- onSave?: ((draft: AccountDraft) => any) | undefined;
14
+ onCancel?: () => any;
15
+ onSave?: (draft: AccountDraft) => any;
16
16
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
17
17
  declare const _default: typeof __VLS_export;
18
18
  export default _default;
@@ -6,8 +6,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
6
6
  edit: () => any;
7
7
  toggleActive: () => any;
8
8
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
9
- onEdit?: (() => any) | undefined;
10
- onToggleActive?: (() => any) | undefined;
9
+ onEdit?: () => any;
10
+ onToggleActive?: () => any;
11
11
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
12
12
  declare const _default: typeof __VLS_export;
13
13
  export default _default;
@@ -7,8 +7,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
7
7
  changed: () => any;
8
8
  selectAccount: (code: string) => any;
9
9
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
10
- onChanged?: (() => any) | undefined;
11
- onSelectAccount?: ((code: string) => any) | undefined;
10
+ onChanged?: () => any;
11
+ onSelectAccount?: (code: string) => any;
12
12
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
13
13
  declare const _default: typeof __VLS_export;
14
14
  export default _default;
@@ -7,8 +7,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
7
7
  close: () => any;
8
8
  changed: () => any;
9
9
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
10
- onClose?: (() => any) | undefined;
11
- onChanged?: (() => any) | undefined;
10
+ onClose?: () => any;
11
+ onChanged?: () => any;
12
12
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
13
13
  declare const _default: typeof __VLS_export;
14
14
  export default _default;
@@ -6,7 +6,7 @@ type __VLS_Props = {
6
6
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
7
7
  selectAccount: (code: string) => any;
8
8
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
9
- onSelectAccount?: ((code: string) => any) | undefined;
9
+ onSelectAccount?: (code: string) => any;
10
10
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
11
11
  declare const _default: typeof __VLS_export;
12
12
  export default _default;
@@ -3,15 +3,15 @@ type __VLS_Props = {
3
3
  bookId: string;
4
4
  bookName: string;
5
5
  currency: string;
6
- country?: SupportedCountryCode;
7
- fiscalYearEnd?: FiscalYearEnd;
6
+ country?: SupportedCountryCode | undefined;
7
+ fiscalYearEnd?: FiscalYearEnd | undefined;
8
8
  };
9
9
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
10
10
  "books-changed": () => any;
11
11
  deleted: (bookName: string) => any;
12
12
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
13
- "onBooks-changed"?: (() => any) | undefined;
14
- onDeleted?: ((bookName: string) => any) | undefined;
13
+ "onBooks-changed"?: () => any;
14
+ onDeleted?: (bookName: string) => any;
15
15
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
16
16
  declare const _default: typeof __VLS_export;
17
17
  export default _default;
@@ -1 +1 @@
1
- {"version":3,"file":"BookSettings.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/components/BookSettings.vue"],"names":[],"mappings":"AA2SA,OAAO,EAIL,KAAK,oBAAoB,EAIzB,KAAK,aAAa,EACnB,MAAM,cAAc,CAAC;AAItB,KAAK,WAAW,GAAG;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,oBAAoB,CAAC;IAC/B,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B,CAAC;AAkiBF,QAAA,MAAM,YAAY;;;;;;kFAGhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
1
+ {"version":3,"file":"BookSettings.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/components/BookSettings.vue"],"names":[],"mappings":"AA2SA,OAAO,EAIL,KAAK,oBAAoB,EAIzB,KAAK,aAAa,EACnB,MAAM,cAAc,CAAC;AAItB,KAAK,WAAW,GAAG;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,oBAAoB,GAAG,SAAS,CAAC;IAC3C,aAAa,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;CAC3C,CAAC;AAkiBF,QAAA,MAAM,YAAY;;;;;;kFAGhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
@@ -8,9 +8,9 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
8
8
  "books-changed": () => any;
9
9
  "book-created": (book: BookSummary) => any;
10
10
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
11
- "onUpdate:modelValue"?: ((bookId: string) => any) | undefined;
12
- "onBooks-changed"?: (() => any) | undefined;
13
- "onBook-created"?: ((book: BookSummary) => any) | undefined;
11
+ "onUpdate:modelValue"?: (bookId: string) => any;
12
+ "onBooks-changed"?: () => any;
13
+ "onBook-created"?: (book: BookSummary) => any;
14
14
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
15
15
  declare const _default: typeof __VLS_export;
16
16
  export default _default;
@@ -7,12 +7,12 @@ type __VLS_Props = {
7
7
  * absent the Lifetime option is hidden from the menu. The opening
8
8
  * gate prevents the tabs that mount this picker from rendering
9
9
  * before an opening exists, so in normal use this stays defined. */
10
- openingDate?: string;
10
+ openingDate?: string | undefined;
11
11
  };
12
12
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
13
13
  "update:modelValue": (args_0: DateRange) => any;
14
14
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
15
- "onUpdate:modelValue"?: ((args_0: DateRange) => any) | undefined;
15
+ "onUpdate:modelValue"?: (args_0: DateRange) => any;
16
16
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
17
17
  declare const _default: typeof __VLS_export;
18
18
  export default _default;
@@ -1 +1 @@
1
- {"version":3,"file":"DateRangePicker.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/components/DateRangePicker.vue"],"names":[],"mappings":"AA+JA,OAAO,EAKL,KAAK,SAAS,EACd,KAAK,aAAa,EAEnB,MAAM,cAAc,CAAC;AAItB,KAAK,WAAW,GAAG;IACjB,UAAU,EAAE,SAAS,CAAC;IACtB,aAAa,EAAE,aAAa,CAAC;IAC7B;;;;yEAIqE;IACrE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAsNF,QAAA,MAAM,YAAY;;;;kFAGhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
1
+ {"version":3,"file":"DateRangePicker.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/components/DateRangePicker.vue"],"names":[],"mappings":"AA+JA,OAAO,EAKL,KAAK,SAAS,EACd,KAAK,aAAa,EAEnB,MAAM,cAAc,CAAC;AAItB,KAAK,WAAW,GAAG;IACjB,UAAU,EAAE,SAAS,CAAC;IACtB,aAAa,EAAE,aAAa,CAAC;IAC7B;;;;yEAIqE;IACrE,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAClC,CAAC;AAsNF,QAAA,MAAM,YAAY;;;;kFAGhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
@@ -4,15 +4,15 @@ type __VLS_Props = {
4
4
  bookId: string;
5
5
  accounts: Account[];
6
6
  currency: string;
7
- country?: SupportedCountryCode;
8
- entryToEdit?: JournalEntry | null;
7
+ country?: SupportedCountryCode | undefined;
8
+ entryToEdit?: JournalEntry | null | undefined;
9
9
  };
10
10
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
11
11
  cancel: () => any;
12
12
  submitted: () => any;
13
13
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
14
- onCancel?: (() => any) | undefined;
15
- onSubmitted?: (() => any) | undefined;
14
+ onCancel?: () => any;
15
+ onSubmitted?: () => any;
16
16
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
17
17
  declare const _default: typeof __VLS_export;
18
18
  export default _default;
@@ -1 +1 @@
1
- {"version":3,"file":"JournalEntryForm.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/components/JournalEntryForm.vue"],"names":[],"mappings":"AA4fA,OAAO,EAAyB,KAAK,OAAO,EAAE,KAAK,YAAY,EAAoB,MAAM,QAAQ,CAAC;AAClG,OAAO,EAAkE,KAAK,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAOzH,KAAK,WAAW,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,oBAAoB,CAAC;IAAC,WAAW,CAAC,EAAE,YAAY,GAAG,IAAI,CAAA;CAAE,CAAC;AAkzBhJ,QAAA,MAAM,YAAY;;;;;;kFAGhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
1
+ {"version":3,"file":"JournalEntryForm.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/components/JournalEntryForm.vue"],"names":[],"mappings":"AAkgBA,OAAO,EAAyB,KAAK,OAAO,EAAE,KAAK,YAAY,EAAoB,MAAM,QAAQ,CAAC;AAClG,OAAO,EAAkE,KAAK,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAOzH,KAAK,WAAW,GAAG;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,oBAAoB,GAAG,SAAS,CAAC;IAC3C,WAAW,CAAC,EAAE,YAAY,GAAG,IAAI,GAAG,SAAS,CAAC;CAC/C,CAAC;AAkzBF,QAAA,MAAM,YAAY;;;;;;kFAGhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
@@ -4,26 +4,26 @@ type __VLS_Props = {
4
4
  bookId: string;
5
5
  accounts: Account[];
6
6
  currency: string;
7
- country?: SupportedCountryCode;
7
+ country?: SupportedCountryCode | undefined;
8
8
  version: number;
9
- fiscalYearEnd?: FiscalYearEnd;
9
+ fiscalYearEnd?: FiscalYearEnd | undefined;
10
10
  /** Opening-balance date for the active book — drives the "Lifetime"
11
11
  * shortcut in the date picker (from = openingDate, to = today).
12
12
  * When absent, the picker hides Lifetime; "All" still works. */
13
- openingDate?: string;
13
+ openingDate?: string | undefined;
14
14
  /** Entry id to auto-expand and scroll into view. Surfaced by the
15
15
  * parent when an `addEntries` tool result lands so the user sees
16
16
  * the freshly-posted row highlighted. Captured into
17
17
  * `pendingPreselectId` and consumed once the entry actually
18
18
  * appears in the fetched list — refetch can race the prop. */
19
- preselectEntryId?: string;
19
+ preselectEntryId?: string | undefined;
20
20
  };
21
21
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
22
22
  editOpening: () => any;
23
23
  preselectConsumed: () => any;
24
24
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
25
- onEditOpening?: (() => any) | undefined;
26
- onPreselectConsumed?: (() => any) | undefined;
25
+ onEditOpening?: () => any;
26
+ onPreselectConsumed?: () => any;
27
27
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
28
28
  declare const _default: typeof __VLS_export;
29
29
  export default _default;
@@ -1 +1 @@
1
- {"version":3,"file":"JournalList.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/components/JournalList.vue"],"names":[],"mappings":"AA6iBA,OAAO,EAAgC,KAAK,OAAO,EAA8D,MAAM,QAAQ,CAAC;AAChI,OAAO,EAA8E,KAAK,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAQzJ,KAAK,WAAW,GAAG;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,oBAAoB,CAAC;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B;;qEAEiE;IACjE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;mEAI+D;IAC/D,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,CAAC;AAmgCF,QAAA,MAAM,YAAY;;;;;;kFAGhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
1
+ {"version":3,"file":"JournalList.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/components/JournalList.vue"],"names":[],"mappings":"AA6iBA,OAAO,EAAgC,KAAK,OAAO,EAA8D,MAAM,QAAQ,CAAC;AAChI,OAAO,EAA8E,KAAK,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAQzJ,KAAK,WAAW,GAAG;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,oBAAoB,GAAG,SAAS,CAAC;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;IAC1C;;qEAEiE;IACjE,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC;;;;mEAI+D;IAC/D,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACvC,CAAC;AAmgCF,QAAA,MAAM,YAAY;;;;;;kFAGhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}