@mulmoclaude/accounting-plugin 0.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 (112) hide show
  1. package/dist/server/accountNormalize.d.ts +3 -0
  2. package/dist/server/accountNormalize.d.ts.map +1 -0
  3. package/dist/server/atomic.d.ts +13 -0
  4. package/dist/server/atomic.d.ts.map +1 -0
  5. package/dist/server/context.d.ts +39 -0
  6. package/dist/server/context.d.ts.map +1 -0
  7. package/dist/server/defaultAccounts.d.ts +3 -0
  8. package/dist/server/defaultAccounts.d.ts.map +1 -0
  9. package/dist/server/eventPublisher.d.ts +14 -0
  10. package/dist/server/eventPublisher.d.ts.map +1 -0
  11. package/dist/server/http.d.ts +3 -0
  12. package/dist/server/http.d.ts.map +1 -0
  13. package/dist/server/index.d.ts +6 -0
  14. package/dist/server/index.d.ts.map +1 -0
  15. package/dist/server/io.d.ts +67 -0
  16. package/dist/server/io.d.ts.map +1 -0
  17. package/dist/server/journal.d.ts +74 -0
  18. package/dist/server/journal.d.ts.map +1 -0
  19. package/dist/server/openingBalances.d.ts +30 -0
  20. package/dist/server/openingBalances.d.ts.map +1 -0
  21. package/dist/server/report.d.ts +98 -0
  22. package/dist/server/report.d.ts.map +1 -0
  23. package/dist/server/router.d.ts +7 -0
  24. package/dist/server/router.d.ts.map +1 -0
  25. package/dist/server/service.d.ts +148 -0
  26. package/dist/server/service.d.ts.map +1 -0
  27. package/dist/server/snapshotCache.d.ts +52 -0
  28. package/dist/server/snapshotCache.d.ts.map +1 -0
  29. package/dist/server/timeSeries.d.ts +47 -0
  30. package/dist/server/timeSeries.d.ts.map +1 -0
  31. package/dist/server/types.d.ts +134 -0
  32. package/dist/server/types.d.ts.map +1 -0
  33. package/dist/server.cjs +2101 -0
  34. package/dist/server.cjs.map +1 -0
  35. package/dist/server.js +2074 -0
  36. package/dist/server.js.map +1 -0
  37. package/dist/shared/actions.d.ts +19 -0
  38. package/dist/shared/actions.d.ts.map +1 -0
  39. package/dist/shared/channels.d.ts +46 -0
  40. package/dist/shared/channels.d.ts.map +1 -0
  41. package/dist/shared/countries.d.ts +51 -0
  42. package/dist/shared/countries.d.ts.map +1 -0
  43. package/dist/shared/currencies.d.ts +34 -0
  44. package/dist/shared/currencies.d.ts.map +1 -0
  45. package/dist/shared/dates.d.ts +15 -0
  46. package/dist/shared/dates.d.ts.map +1 -0
  47. package/dist/shared/errors.d.ts +2 -0
  48. package/dist/shared/errors.d.ts.map +1 -0
  49. package/dist/shared/fiscalYear.d.ts +22 -0
  50. package/dist/shared/fiscalYear.d.ts.map +1 -0
  51. package/dist/shared/index.d.ts +9 -0
  52. package/dist/shared/index.d.ts.map +1 -0
  53. package/dist/shared/timeSeriesEnums.d.ts +5 -0
  54. package/dist/shared/timeSeriesEnums.d.ts.map +1 -0
  55. package/dist/shared.cjs +466 -0
  56. package/dist/shared.cjs.map +1 -0
  57. package/dist/shared.js +432 -0
  58. package/dist/shared.js.map +1 -0
  59. package/dist/style.css +1255 -0
  60. package/dist/vue/Preview.vue.d.ts +8 -0
  61. package/dist/vue/Preview.vue.d.ts.map +1 -0
  62. package/dist/vue/View.vue.d.ts +30 -0
  63. package/dist/vue/View.vue.d.ts.map +1 -0
  64. package/dist/vue/api.d.ts +269 -0
  65. package/dist/vue/api.d.ts.map +1 -0
  66. package/dist/vue/components/AccountEditor.vue.d.ts +19 -0
  67. package/dist/vue/components/AccountEditor.vue.d.ts.map +1 -0
  68. package/dist/vue/components/AccountRow.vue.d.ts +14 -0
  69. package/dist/vue/components/AccountRow.vue.d.ts.map +1 -0
  70. package/dist/vue/components/AccountsList.vue.d.ts +15 -0
  71. package/dist/vue/components/AccountsList.vue.d.ts.map +1 -0
  72. package/dist/vue/components/AccountsModal.vue.d.ts +15 -0
  73. package/dist/vue/components/AccountsModal.vue.d.ts.map +1 -0
  74. package/dist/vue/components/BalanceSheet.vue.d.ts +13 -0
  75. package/dist/vue/components/BalanceSheet.vue.d.ts.map +1 -0
  76. package/dist/vue/components/BookSettings.vue.d.ts +18 -0
  77. package/dist/vue/components/BookSettings.vue.d.ts.map +1 -0
  78. package/dist/vue/components/BookSwitcher.vue.d.ts +17 -0
  79. package/dist/vue/components/BookSwitcher.vue.d.ts.map +1 -0
  80. package/dist/vue/components/DateRangePicker.vue.d.ts +19 -0
  81. package/dist/vue/components/DateRangePicker.vue.d.ts.map +1 -0
  82. package/dist/vue/components/JournalEntryForm.vue.d.ts +19 -0
  83. package/dist/vue/components/JournalEntryForm.vue.d.ts.map +1 -0
  84. package/dist/vue/components/JournalList.vue.d.ts +30 -0
  85. package/dist/vue/components/JournalList.vue.d.ts.map +1 -0
  86. package/dist/vue/components/Ledger.vue.d.ts +21 -0
  87. package/dist/vue/components/Ledger.vue.d.ts.map +1 -0
  88. package/dist/vue/components/NewBookForm.vue.d.ts +20 -0
  89. package/dist/vue/components/NewBookForm.vue.d.ts.map +1 -0
  90. package/dist/vue/components/OpeningBalancesForm.vue.d.ts +15 -0
  91. package/dist/vue/components/OpeningBalancesForm.vue.d.ts.map +1 -0
  92. package/dist/vue/components/ProfitLoss.vue.d.ts +19 -0
  93. package/dist/vue/components/ProfitLoss.vue.d.ts.map +1 -0
  94. package/dist/vue/components/accountDraft.d.ts +8 -0
  95. package/dist/vue/components/accountDraft.d.ts.map +1 -0
  96. package/dist/vue/components/accountNumbering.d.ts +20 -0
  97. package/dist/vue/components/accountNumbering.d.ts.map +1 -0
  98. package/dist/vue/components/accountValidation.d.ts +34 -0
  99. package/dist/vue/components/accountValidation.d.ts.map +1 -0
  100. package/dist/vue/components/useLatestRequest.d.ts +10 -0
  101. package/dist/vue/components/useLatestRequest.d.ts.map +1 -0
  102. package/dist/vue/hostContext.d.ts +31 -0
  103. package/dist/vue/hostContext.d.ts.map +1 -0
  104. package/dist/vue/index.d.ts +7 -0
  105. package/dist/vue/index.d.ts.map +1 -0
  106. package/dist/vue/useAccountingChannel.d.ts +13 -0
  107. package/dist/vue/useAccountingChannel.d.ts.map +1 -0
  108. package/dist/vue.cjs +3641 -0
  109. package/dist/vue.cjs.map +1 -0
  110. package/dist/vue.js +3638 -0
  111. package/dist/vue.js.map +1 -0
  112. package/package.json +74 -0
@@ -0,0 +1,34 @@
1
+ /** ISO 4217 codes shown in the New Book dropdown. Curated for
2
+ * recognisability — Intl.DisplayNames provides the localised
3
+ * human name at render time, so this stays a flat list of codes. */
4
+ export declare const SUPPORTED_CURRENCY_CODES: readonly ["USD", "EUR", "JPY", "GBP", "CNY", "KRW", "TWD", "HKD", "SGD", "AUD", "CAD", "CHF", "INR", "BRL", "MXN"];
5
+ export type SupportedCurrencyCode = (typeof SUPPORTED_CURRENCY_CODES)[number];
6
+ /** Localised human name for a currency code. Falls back to the
7
+ * code itself if the runtime can't resolve the name. */
8
+ export declare function localizedCurrencyName(code: string, locale: string): string;
9
+ /** Number of fraction digits ISO 4217 specifies for a currency.
10
+ * JPY = 0, USD = 2, KWD = 3. Used both for amount formatting and
11
+ * for the HTML input step on debit/credit fields. */
12
+ export declare function fractionDigitsFor(currency: string): number;
13
+ /** "1" for JPY, "0.01" for USD, "0.001" for KWD. Used as the HTML
14
+ * input step on debit/credit fields so a JPY book doesn't let the
15
+ * user type cents that would just round-trip back through the
16
+ * decimal validator. */
17
+ export declare function inputStepFor(currency: string): string;
18
+ /** Locale-aware currency formatter — returns "¥1,130" / "$1,130.00"
19
+ * etc. Falls back to fixed-point formatting if the runtime can't
20
+ * resolve the currency code; the fallback still respects the
21
+ * currency's natural fraction-digit count so JPY shows whole
22
+ * numbers even on the slow path. */
23
+ export declare function formatAmount(value: number, currency: string, locale?: string): string;
24
+ /** Currency-agnostic amount formatter — "1,130.00" — for places that
25
+ * don't carry the currency code on the data path (compact preview
26
+ * envelopes etc.). Use `formatAmount(value, currency)` whenever the
27
+ * currency IS available — the currency-aware path picks the right
28
+ * fraction-digit count automatically (JPY = 0, USD = 2).
29
+ *
30
+ * `locale` mirrors `formatAmount`'s signature: pass an explicit BCP-47
31
+ * locale (`"en-US"`, `"ja-JP"`, …) when the caller knows the desired
32
+ * grouping / digit-shape; omit to fall back to the runtime default. */
33
+ export declare function formatAmountNumeric(value: number, decimals?: number, locale?: string): string;
34
+ //# sourceMappingURL=currencies.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"currencies.d.ts","sourceRoot":"","sources":["../../src/shared/currencies.ts"],"names":[],"mappings":"AAWA;;qEAEqE;AACrE,eAAO,MAAM,wBAAwB,oHAAqH,CAAC;AAE3J,MAAM,MAAM,qBAAqB,GAAG,CAAC,OAAO,wBAAwB,CAAC,CAAC,MAAM,CAAC,CAAC;AAI9E;yDACyD;AACzD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAM1E;AAED;;sDAEsD;AACtD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAO1D;AAED;;;yBAGyB;AACzB,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAIrD;AAED;;;;qCAIqC;AACrC,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAMrF;AAED;;;;;;;;wEAQwE;AACxE,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,SAAI,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAExF"}
@@ -0,0 +1,15 @@
1
+ /** Today as `YYYY-MM-DD` in the user's local timezone. */
2
+ export declare function localDateString(now?: Date): string;
3
+ /** Current month as `YYYY-MM` in the user's local timezone. */
4
+ export declare function localMonthString(now?: Date): string;
5
+ /** First day of the current calendar year as `YYYY-MM-DD`. */
6
+ export declare function localStartOfYearString(now?: Date): string;
7
+ /** Previous calendar month as `YYYY-MM` in the user's local timezone. */
8
+ export declare function previousMonthString(now?: Date): string;
9
+ /** Last month of the previous calendar quarter as `YYYY-MM`. Calendar
10
+ * quarters: Q1=Jan–Mar, Q2=Apr–Jun, Q3=Jul–Sep, Q4=Oct–Dec. When the
11
+ * current month is in Q1, this rolls back to December of last year. */
12
+ export declare function lastMonthOfPreviousQuarterString(now?: Date): string;
13
+ /** December of the previous calendar year as `YYYY-MM`. */
14
+ export declare function decemberOfPreviousYearString(now?: Date): string;
15
+ //# sourceMappingURL=dates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dates.d.ts","sourceRoot":"","sources":["../../src/shared/dates.ts"],"names":[],"mappings":"AAiBA,0DAA0D;AAC1D,wBAAgB,eAAe,CAAC,GAAG,GAAE,IAAiB,GAAG,MAAM,CAE9D;AAED,+DAA+D;AAC/D,wBAAgB,gBAAgB,CAAC,GAAG,GAAE,IAAiB,GAAG,MAAM,CAE/D;AAED,8DAA8D;AAC9D,wBAAgB,sBAAsB,CAAC,GAAG,GAAE,IAAiB,GAAG,MAAM,CAErE;AAED,yEAAyE;AACzE,wBAAgB,mBAAmB,CAAC,GAAG,GAAE,IAAiB,GAAG,MAAM,CAGlE;AAED;;wEAEwE;AACxE,wBAAgB,gCAAgC,CAAC,GAAG,GAAE,IAAiB,GAAG,MAAM,CAI/E;AAED,2DAA2D;AAC3D,wBAAgB,4BAA4B,CAAC,GAAG,GAAE,IAAiB,GAAG,MAAM,CAE3E"}
@@ -0,0 +1,2 @@
1
+ export declare function errorMessage(err: unknown, fallback?: string): string;
2
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/shared/errors.ts"],"names":[],"mappings":"AAMA,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CASpE"}
@@ -0,0 +1,22 @@
1
+ export declare const FISCAL_YEAR_ENDS: readonly ["Q1", "Q2", "Q3", "Q4"];
2
+ export type FiscalYearEnd = (typeof FISCAL_YEAR_ENDS)[number];
3
+ export declare const DEFAULT_FISCAL_YEAR_END: FiscalYearEnd;
4
+ export declare function isFiscalYearEnd(value: unknown): value is FiscalYearEnd;
5
+ /** Books written before the field existed are treated as Q4 in code
6
+ * but never auto-rewritten on disk. The settings UI persists through
7
+ * the field the next time the user saves anything on the book. */
8
+ export declare function resolveFiscalYearEnd(value: FiscalYearEnd | undefined): FiscalYearEnd;
9
+ /** Last calendar month (1-12) of the fiscal year for the given Q. */
10
+ export declare function fiscalYearEndMonth(end: FiscalYearEnd): 3 | 6 | 9 | 12;
11
+ export interface DateRange {
12
+ /** Inclusive lower bound (YYYY-MM-DD). Empty string = unbounded. */
13
+ from: string;
14
+ /** Inclusive upper bound (YYYY-MM-DD). Empty string = unbounded. */
15
+ to: string;
16
+ }
17
+ export declare function currentQuarterRange(end: FiscalYearEnd, today?: Date): DateRange;
18
+ export declare function previousQuarterRange(end: FiscalYearEnd, today?: Date): DateRange;
19
+ /** Current fiscal year — Q0 start through Q3 close. */
20
+ export declare function currentFiscalYearRange(end: FiscalYearEnd, today?: Date): DateRange;
21
+ export declare function previousFiscalYearRange(end: FiscalYearEnd, today?: Date): DateRange;
22
+ //# sourceMappingURL=fiscalYear.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fiscalYear.d.ts","sourceRoot":"","sources":["../../src/shared/fiscalYear.ts"],"names":[],"mappings":"AAmBA,eAAO,MAAM,gBAAgB,mCAAoC,CAAC;AAClE,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE9D,eAAO,MAAM,uBAAuB,EAAE,aAAoB,CAAC;AAE3D,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,aAAa,CAEtE;AAED;;mEAEmE;AACnE,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,aAAa,GAAG,SAAS,GAAG,aAAa,CAEpF;AAED,qEAAqE;AACrE,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,aAAa,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAKrE;AAED,MAAM,WAAW,SAAS;IACxB,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,oEAAoE;IACpE,EAAE,EAAE,MAAM,CAAC;CACZ;AA8DD,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,aAAa,EAAE,KAAK,GAAE,IAAiB,GAAG,SAAS,CAE3F;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,aAAa,EAAE,KAAK,GAAE,IAAiB,GAAG,SAAS,CAQ5F;AAED,uDAAuD;AACvD,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,aAAa,EAAE,KAAK,GAAE,IAAiB,GAAG,SAAS,CAI9F;AAED,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,aAAa,EAAE,KAAK,GAAE,IAAiB,GAAG,SAAS,CAI/F"}
@@ -0,0 +1,9 @@
1
+ export * from "./actions";
2
+ export * from "./channels";
3
+ export * from "./errors";
4
+ export * from "./fiscalYear";
5
+ export * from "./countries";
6
+ export * from "./currencies";
7
+ export * from "./dates";
8
+ export * from "./timeSeriesEnums";
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/shared/index.ts"],"names":[],"mappings":"AAKA,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC;AACxB,cAAc,mBAAmB,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare const TIME_SERIES_METRICS: readonly ["revenue", "expense", "netIncome", "accountBalance"];
2
+ export type TimeSeriesMetric = (typeof TIME_SERIES_METRICS)[number];
3
+ export declare const TIME_SERIES_GRANULARITIES: readonly ["month", "quarter", "year"];
4
+ export type TimeSeriesGranularity = (typeof TIME_SERIES_GRANULARITIES)[number];
5
+ //# sourceMappingURL=timeSeriesEnums.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeSeriesEnums.d.ts","sourceRoot":"","sources":["../../src/shared/timeSeriesEnums.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,mBAAmB,gEAAiE,CAAC;AAClG,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEpE,eAAO,MAAM,yBAAyB,uCAAwC,CAAC;AAC/E,MAAM,MAAM,qBAAqB,GAAG,CAAC,OAAO,yBAAyB,CAAC,CAAC,MAAM,CAAC,CAAC"}
@@ -0,0 +1,466 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region src/shared/actions.ts
3
+ var ACCOUNTING_ACTIONS = {
4
+ openBook: "openBook",
5
+ getBooks: "getBooks",
6
+ createBook: "createBook",
7
+ updateBook: "updateBook",
8
+ deleteBook: "deleteBook",
9
+ getAccounts: "getAccounts",
10
+ upsertAccount: "upsertAccount",
11
+ addEntries: "addEntries",
12
+ voidEntry: "voidEntry",
13
+ getJournalEntries: "getJournalEntries",
14
+ getOpeningBalances: "getOpeningBalances",
15
+ setOpeningBalances: "setOpeningBalances",
16
+ getReport: "getReport",
17
+ getTimeSeries: "getTimeSeries",
18
+ rebuildSnapshots: "rebuildSnapshots"
19
+ };
20
+ //#endregion
21
+ //#region src/shared/channels.ts
22
+ /** Channel factory for per-book event streams. Subscribers:
23
+ * `useAccountingChannel(bookId)`. Publisher: the package's server
24
+ * surface `eventPublisher`. */
25
+ function bookChannel(bookId) {
26
+ return `accounting:${bookId}`;
27
+ }
28
+ /** Book-list-level channel — a book was created / deleted. Subscribers
29
+ * refetch the BookSwitcher dropdown. Mirrors the host META's
30
+ * `staticChannels.accountingBooks` literal (kept in sync by value;
31
+ * the host META stays the codegen-discoverable source for the
32
+ * aggregator merge). */
33
+ var ACCOUNTING_BOOKS_CHANNEL = "accounting:books";
34
+ /** Event kinds that ride `bookChannel(bookId)`. Single source of
35
+ * truth for both publishers (server/accounting) and subscribers
36
+ * (the View) — anyone branching on event kind imports from here
37
+ * and the type system catches drift on either side.
38
+ *
39
+ * - `journal` — addEntry / voidEntry hit the books at `period`.
40
+ * Refetch the journal list and (if the View is
41
+ * showing balances at or after `period`) the
42
+ * relevant report.
43
+ * - `opening` — setOpeningBalances. Affects every period from
44
+ * the opening date forward; refetch everything.
45
+ * - `accounts` — chart-of-accounts mutation that may affect
46
+ * aggregation (account type changed). Refetch
47
+ * accounts and the active report.
48
+ * - `snapshotsRebuilding` / `snapshotsReady` — purely informational;
49
+ * the View can show a "calculating" spinner
50
+ * during rebuild, but the lazy-rebuild safety
51
+ * net means a refetch always returns the right
52
+ * answer regardless. */
53
+ var BOOK_EVENT_KINDS = {
54
+ journal: "journal",
55
+ opening: "opening",
56
+ accounts: "accounts",
57
+ snapshotsRebuilding: "snapshots-rebuilding",
58
+ snapshotsReady: "snapshots-ready"
59
+ };
60
+ //#endregion
61
+ //#region src/shared/errors.ts
62
+ function errorMessage(err, fallback) {
63
+ if (err instanceof Error) return err.message;
64
+ if (err !== null && typeof err === "object") {
65
+ const obj = err;
66
+ if (typeof obj.details === "string" && obj.details) return obj.details;
67
+ if (typeof obj.message === "string" && obj.message) return obj.message;
68
+ }
69
+ if (fallback !== void 0) return fallback;
70
+ return String(err);
71
+ }
72
+ //#endregion
73
+ //#region src/shared/fiscalYear.ts
74
+ var FISCAL_YEAR_ENDS = [
75
+ "Q1",
76
+ "Q2",
77
+ "Q3",
78
+ "Q4"
79
+ ];
80
+ var DEFAULT_FISCAL_YEAR_END = "Q4";
81
+ function isFiscalYearEnd(value) {
82
+ return typeof value === "string" && FISCAL_YEAR_ENDS.includes(value);
83
+ }
84
+ /** Books written before the field existed are treated as Q4 in code
85
+ * but never auto-rewritten on disk. The settings UI persists through
86
+ * the field the next time the user saves anything on the book. */
87
+ function resolveFiscalYearEnd(value) {
88
+ return value ?? "Q4";
89
+ }
90
+ /** Last calendar month (1-12) of the fiscal year for the given Q. */
91
+ function fiscalYearEndMonth(end) {
92
+ if (end === "Q1") return 3;
93
+ if (end === "Q2") return 6;
94
+ if (end === "Q3") return 9;
95
+ return 12;
96
+ }
97
+ function pad2$1(num) {
98
+ return String(num).padStart(2, "0");
99
+ }
100
+ function lastDayOfMonth(year, monthZeroBased) {
101
+ return new Date(year, monthZeroBased + 1, 0).getDate();
102
+ }
103
+ function ymd(year, monthOneBased, day) {
104
+ return `${year}-${pad2$1(monthOneBased)}-${pad2$1(day)}`;
105
+ }
106
+ /** Fiscal quarter index (0..3) of the given local date under `end`,
107
+ * where 0 is the first quarter of the fiscal year (right after the
108
+ * prior year's close) and 3 is the closing quarter. */
109
+ function fiscalQuarterIndex(end, today) {
110
+ const closingMonth = fiscalYearEndMonth(end);
111
+ const offset = (today.getMonth() + 1 - closingMonth - 1 + 12) % 12;
112
+ return Math.floor(offset / 3);
113
+ }
114
+ /** Calendar (year, monthOneBased) of the *first* month of the fiscal
115
+ * quarter at index `index` in the fiscal year that *contains*
116
+ * `today`. Returned both as the first day of that month and as the
117
+ * count of months covered (always 3 — exposed as a constant). */
118
+ function fiscalQuarterStart(end, today, index) {
119
+ const closingMonth = fiscalYearEndMonth(end);
120
+ const todayMonth = today.getMonth() + 1;
121
+ const todayYear = today.getFullYear();
122
+ const startMonth = closingMonth % 12 + 1;
123
+ const fyStartYear = todayMonth >= startMonth ? todayYear : todayYear - 1;
124
+ const flatMonth = startMonth + index * 3;
125
+ return {
126
+ year: fyStartYear + Math.floor((flatMonth - 1) / 12),
127
+ month: (flatMonth - 1) % 12 + 1
128
+ };
129
+ }
130
+ function quarterRangeAt(end, today, index) {
131
+ const start = fiscalQuarterStart(end, today, index);
132
+ const lastMonthFlat = start.month - 1 + 2;
133
+ const lastMonthYear = start.year + Math.floor(lastMonthFlat / 12);
134
+ const lastMonth = lastMonthFlat % 12 + 1;
135
+ const lastDay = lastDayOfMonth(lastMonthYear, lastMonth - 1);
136
+ return {
137
+ from: ymd(start.year, start.month, 1),
138
+ to: ymd(lastMonthYear, lastMonth, lastDay)
139
+ };
140
+ }
141
+ function currentQuarterRange(end, today = /* @__PURE__ */ new Date()) {
142
+ return quarterRangeAt(end, today, fiscalQuarterIndex(end, today));
143
+ }
144
+ function previousQuarterRange(end, today = /* @__PURE__ */ new Date()) {
145
+ const idx = fiscalQuarterIndex(end, today);
146
+ if (idx > 0) return quarterRangeAt(end, today, idx - 1);
147
+ return quarterRangeAt(end, new Date(today.getFullYear(), today.getMonth() - 3, 1), 3);
148
+ }
149
+ /** Current fiscal year — Q0 start through Q3 close. */
150
+ function currentFiscalYearRange(end, today = /* @__PURE__ */ new Date()) {
151
+ const first = quarterRangeAt(end, today, 0);
152
+ const last = quarterRangeAt(end, today, 3);
153
+ return {
154
+ from: first.from,
155
+ to: last.to
156
+ };
157
+ }
158
+ function previousFiscalYearRange(end, today = /* @__PURE__ */ new Date()) {
159
+ return currentFiscalYearRange(end, new Date(today.getFullYear() - 1, today.getMonth(), today.getDate()));
160
+ }
161
+ //#endregion
162
+ //#region src/shared/countries.ts
163
+ /** ISO 3166-1 alpha-2 country codes shown in the book country
164
+ * dropdown. Curated to cover every jurisdiction the Accounting role
165
+ * has explicit tax-registration advice for, plus the major economies
166
+ * represented in `SUPPORTED_CURRENCY_CODES`. */
167
+ var SUPPORTED_COUNTRY_CODES = [
168
+ "US",
169
+ "JP",
170
+ "GB",
171
+ "CA",
172
+ "AU",
173
+ "NZ",
174
+ "DE",
175
+ "FR",
176
+ "IT",
177
+ "ES",
178
+ "NL",
179
+ "BE",
180
+ "AT",
181
+ "IE",
182
+ "PT",
183
+ "FI",
184
+ "SE",
185
+ "DK",
186
+ "PL",
187
+ "CH",
188
+ "NO",
189
+ "CN",
190
+ "KR",
191
+ "TW",
192
+ "HK",
193
+ "SG",
194
+ "IN",
195
+ "BR",
196
+ "MX"
197
+ ];
198
+ /** EU member states as of 2026. Used by the role-prompt advice path
199
+ * to recommend a VAT identification number when the book country is
200
+ * in the EU. */
201
+ var EU_COUNTRY_CODES = /* @__PURE__ */ new Set([
202
+ "AT",
203
+ "BE",
204
+ "BG",
205
+ "CY",
206
+ "CZ",
207
+ "DE",
208
+ "DK",
209
+ "EE",
210
+ "ES",
211
+ "FI",
212
+ "FR",
213
+ "GR",
214
+ "HR",
215
+ "HU",
216
+ "IE",
217
+ "IT",
218
+ "LT",
219
+ "LU",
220
+ "LV",
221
+ "MT",
222
+ "NL",
223
+ "PL",
224
+ "PT",
225
+ "RO",
226
+ "SE",
227
+ "SI",
228
+ "SK"
229
+ ]);
230
+ /** Localized human name for a country code. Falls back to the code
231
+ * itself if the runtime can't resolve the name. */
232
+ function localizedCountryName(code, locale) {
233
+ try {
234
+ return new Intl.DisplayNames([locale], { type: "region" }).of(code) ?? code;
235
+ } catch {
236
+ return code;
237
+ }
238
+ }
239
+ /** Runtime guard for `BookSummary.country`. The type is the union
240
+ * `SupportedCountryCode`, but every entry point that takes user /
241
+ * LLM input arrives as raw `string` (form submit, JSON-RPC body),
242
+ * so the service layer narrows here before persisting. */
243
+ function isSupportedCountryCode(value) {
244
+ return typeof value === "string" && SUPPORTED_COUNTRY_CODES.includes(value);
245
+ }
246
+ /** Country-gated UI features. Each key is a feature name; the value
247
+ * is the set of country codes for which the feature is enabled.
248
+ * Components ask `countryHasFeature("...", country)` instead of
249
+ * hard-coding country lists at the call site.
250
+ *
251
+ * Add a new country-specific feature by adding a new key here and
252
+ * reading it via `countryHasFeature`. An unknown / undefined
253
+ * country never has any feature — components fall back to neutral
254
+ * default UI rather than guessing.
255
+ *
256
+ * Mirrors the "Country-aware tax behaviour" prose in the
257
+ * Accounting role prompt (`src/config/roles.ts`). The two MUST
258
+ * stay in sync — drift means the LLM and the form give the user
259
+ * contradictory advice. The prompt is the source of truth for
260
+ * agent behaviour; this table is structured-data sibling for the
261
+ * form. */
262
+ var COUNTRY_FEATURES = {
263
+ /** Show an amber "missing tax ID" warning + helper text on a
264
+ * postable 14xx (input-tax) line whose taxRegistrationId is
265
+ * blank. Limited to jurisdictions where the role prompt
266
+ * explicitly requires the counterparty registration number
267
+ * (JP T-number, EU VAT ID, GB VAT, GSTIN, ABN, NZ GST, CA BN).
268
+ * The "other countries" bucket and US (no federal sales-tax
269
+ * registration) intentionally stay quiet. 24xx output-tax
270
+ * lines don't trigger the warning — see `isTaxAccountCode`. */
271
+ warnMissingTaxRegistrationId: /* @__PURE__ */ new Set([
272
+ "JP",
273
+ "GB",
274
+ "DE",
275
+ "FR",
276
+ "IT",
277
+ "ES",
278
+ "NL",
279
+ "BE",
280
+ "AT",
281
+ "IE",
282
+ "PT",
283
+ "FI",
284
+ "SE",
285
+ "DK",
286
+ "PL",
287
+ "IN",
288
+ "AU",
289
+ "NZ",
290
+ "CA"
291
+ ]) };
292
+ /** Resolve a country-gated feature flag. Returns `false` when the
293
+ * country is undefined / unsupported — components default to the
294
+ * neutral path (no warning, no extra UI) rather than guessing. */
295
+ function countryHasFeature(feature, country) {
296
+ if (!country) return false;
297
+ return COUNTRY_FEATURES[feature].has(country);
298
+ }
299
+ //#endregion
300
+ //#region src/shared/currencies.ts
301
+ /** ISO 4217 codes shown in the New Book dropdown. Curated for
302
+ * recognisability — Intl.DisplayNames provides the localised
303
+ * human name at render time, so this stays a flat list of codes. */
304
+ var SUPPORTED_CURRENCY_CODES = [
305
+ "USD",
306
+ "EUR",
307
+ "JPY",
308
+ "GBP",
309
+ "CNY",
310
+ "KRW",
311
+ "TWD",
312
+ "HKD",
313
+ "SGD",
314
+ "AUD",
315
+ "CAD",
316
+ "CHF",
317
+ "INR",
318
+ "BRL",
319
+ "MXN"
320
+ ];
321
+ var DEFAULT_FALLBACK_DIGITS = 2;
322
+ /** Localised human name for a currency code. Falls back to the
323
+ * code itself if the runtime can't resolve the name. */
324
+ function localizedCurrencyName(code, locale) {
325
+ try {
326
+ return new Intl.DisplayNames([locale], { type: "currency" }).of(code) ?? code;
327
+ } catch {
328
+ return code;
329
+ }
330
+ }
331
+ /** Number of fraction digits ISO 4217 specifies for a currency.
332
+ * JPY = 0, USD = 2, KWD = 3. Used both for amount formatting and
333
+ * for the HTML input step on debit/credit fields. */
334
+ function fractionDigitsFor(currency) {
335
+ try {
336
+ return new Intl.NumberFormat("en", {
337
+ style: "currency",
338
+ currency
339
+ }).resolvedOptions().maximumFractionDigits ?? DEFAULT_FALLBACK_DIGITS;
340
+ } catch {
341
+ return DEFAULT_FALLBACK_DIGITS;
342
+ }
343
+ }
344
+ /** "1" for JPY, "0.01" for USD, "0.001" for KWD. Used as the HTML
345
+ * input step on debit/credit fields so a JPY book doesn't let the
346
+ * user type cents that would just round-trip back through the
347
+ * decimal validator. */
348
+ function inputStepFor(currency) {
349
+ const digits = fractionDigitsFor(currency);
350
+ if (digits === 0) return "1";
351
+ return (1 / 10 ** digits).toFixed(digits);
352
+ }
353
+ /** Locale-aware currency formatter — returns "¥1,130" / "$1,130.00"
354
+ * etc. Falls back to fixed-point formatting if the runtime can't
355
+ * resolve the currency code; the fallback still respects the
356
+ * currency's natural fraction-digit count so JPY shows whole
357
+ * numbers even on the slow path. */
358
+ function formatAmount(value, currency, locale) {
359
+ try {
360
+ return new Intl.NumberFormat(locale, {
361
+ style: "currency",
362
+ currency
363
+ }).format(value);
364
+ } catch {
365
+ return value.toFixed(fractionDigitsFor(currency));
366
+ }
367
+ }
368
+ /** Currency-agnostic amount formatter — "1,130.00" — for places that
369
+ * don't carry the currency code on the data path (compact preview
370
+ * envelopes etc.). Use `formatAmount(value, currency)` whenever the
371
+ * currency IS available — the currency-aware path picks the right
372
+ * fraction-digit count automatically (JPY = 0, USD = 2).
373
+ *
374
+ * `locale` mirrors `formatAmount`'s signature: pass an explicit BCP-47
375
+ * locale (`"en-US"`, `"ja-JP"`, …) when the caller knows the desired
376
+ * grouping / digit-shape; omit to fall back to the runtime default. */
377
+ function formatAmountNumeric(value, decimals = 2, locale) {
378
+ return value.toLocaleString(locale, {
379
+ minimumFractionDigits: decimals,
380
+ maximumFractionDigits: decimals
381
+ });
382
+ }
383
+ //#endregion
384
+ //#region src/shared/dates.ts
385
+ function pad2(num) {
386
+ return String(num).padStart(2, "0");
387
+ }
388
+ /** Today as `YYYY-MM-DD` in the user's local timezone. */
389
+ function localDateString(now = /* @__PURE__ */ new Date()) {
390
+ return `${now.getFullYear()}-${pad2(now.getMonth() + 1)}-${pad2(now.getDate())}`;
391
+ }
392
+ /** Current month as `YYYY-MM` in the user's local timezone. */
393
+ function localMonthString(now = /* @__PURE__ */ new Date()) {
394
+ return `${now.getFullYear()}-${pad2(now.getMonth() + 1)}`;
395
+ }
396
+ /** First day of the current calendar year as `YYYY-MM-DD`. */
397
+ function localStartOfYearString(now = /* @__PURE__ */ new Date()) {
398
+ return `${now.getFullYear()}-01-01`;
399
+ }
400
+ /** Previous calendar month as `YYYY-MM` in the user's local timezone. */
401
+ function previousMonthString(now = /* @__PURE__ */ new Date()) {
402
+ const target = new Date(now.getFullYear(), now.getMonth() - 1, 1);
403
+ return `${target.getFullYear()}-${pad2(target.getMonth() + 1)}`;
404
+ }
405
+ /** Last month of the previous calendar quarter as `YYYY-MM`. Calendar
406
+ * quarters: Q1=Jan–Mar, Q2=Apr–Jun, Q3=Jul–Sep, Q4=Oct–Dec. When the
407
+ * current month is in Q1, this rolls back to December of last year. */
408
+ function lastMonthOfPreviousQuarterString(now = /* @__PURE__ */ new Date()) {
409
+ const firstMonthOfCurrentQuarter = Math.floor(now.getMonth() / 3) * 3;
410
+ const target = new Date(now.getFullYear(), firstMonthOfCurrentQuarter - 1, 1);
411
+ return `${target.getFullYear()}-${pad2(target.getMonth() + 1)}`;
412
+ }
413
+ /** December of the previous calendar year as `YYYY-MM`. */
414
+ function decemberOfPreviousYearString(now = /* @__PURE__ */ new Date()) {
415
+ return `${now.getFullYear() - 1}-12`;
416
+ }
417
+ //#endregion
418
+ //#region src/shared/timeSeriesEnums.ts
419
+ var TIME_SERIES_METRICS = [
420
+ "revenue",
421
+ "expense",
422
+ "netIncome",
423
+ "accountBalance"
424
+ ];
425
+ var TIME_SERIES_GRANULARITIES = [
426
+ "month",
427
+ "quarter",
428
+ "year"
429
+ ];
430
+ //#endregion
431
+ exports.ACCOUNTING_ACTIONS = ACCOUNTING_ACTIONS;
432
+ exports.ACCOUNTING_BOOKS_CHANNEL = ACCOUNTING_BOOKS_CHANNEL;
433
+ exports.BOOK_EVENT_KINDS = BOOK_EVENT_KINDS;
434
+ exports.COUNTRY_FEATURES = COUNTRY_FEATURES;
435
+ exports.DEFAULT_FISCAL_YEAR_END = DEFAULT_FISCAL_YEAR_END;
436
+ exports.EU_COUNTRY_CODES = EU_COUNTRY_CODES;
437
+ exports.FISCAL_YEAR_ENDS = FISCAL_YEAR_ENDS;
438
+ exports.SUPPORTED_COUNTRY_CODES = SUPPORTED_COUNTRY_CODES;
439
+ exports.SUPPORTED_CURRENCY_CODES = SUPPORTED_CURRENCY_CODES;
440
+ exports.TIME_SERIES_GRANULARITIES = TIME_SERIES_GRANULARITIES;
441
+ exports.TIME_SERIES_METRICS = TIME_SERIES_METRICS;
442
+ exports.bookChannel = bookChannel;
443
+ exports.countryHasFeature = countryHasFeature;
444
+ exports.currentFiscalYearRange = currentFiscalYearRange;
445
+ exports.currentQuarterRange = currentQuarterRange;
446
+ exports.decemberOfPreviousYearString = decemberOfPreviousYearString;
447
+ exports.errorMessage = errorMessage;
448
+ exports.fiscalYearEndMonth = fiscalYearEndMonth;
449
+ exports.formatAmount = formatAmount;
450
+ exports.formatAmountNumeric = formatAmountNumeric;
451
+ exports.fractionDigitsFor = fractionDigitsFor;
452
+ exports.inputStepFor = inputStepFor;
453
+ exports.isFiscalYearEnd = isFiscalYearEnd;
454
+ exports.isSupportedCountryCode = isSupportedCountryCode;
455
+ exports.lastMonthOfPreviousQuarterString = lastMonthOfPreviousQuarterString;
456
+ exports.localDateString = localDateString;
457
+ exports.localMonthString = localMonthString;
458
+ exports.localStartOfYearString = localStartOfYearString;
459
+ exports.localizedCountryName = localizedCountryName;
460
+ exports.localizedCurrencyName = localizedCurrencyName;
461
+ exports.previousFiscalYearRange = previousFiscalYearRange;
462
+ exports.previousMonthString = previousMonthString;
463
+ exports.previousQuarterRange = previousQuarterRange;
464
+ exports.resolveFiscalYearEnd = resolveFiscalYearEnd;
465
+
466
+ //# sourceMappingURL=shared.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.cjs","names":[],"sources":["../src/shared/actions.ts","../src/shared/channels.ts","../src/shared/errors.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","// 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","// Normalise an unknown thrown value into a human-readable string.\n// Isomorphic (used by both the Vue surface and the server surface) so\n// it lives in ./shared. Mirrors the host's `src/utils/errors.ts`\n// `errorMessage` — kept in the package so neither surface reaches\n// uphill into the host for it.\n\nexport function errorMessage(err: unknown, fallback?: string): string {\n if (err instanceof Error) return err.message;\n if (err !== null && typeof err === \"object\") {\n const obj = err as { details?: unknown; message?: unknown };\n if (typeof obj.details === \"string\" && obj.details) return obj.details;\n if (typeof obj.message === \"string\" && obj.message) return obj.message;\n }\n if (fallback !== undefined) return fallback;\n return String(err);\n}\n","// Fiscal-year arithmetic for the accounting plugin.\n//\n// Each book stores a `fiscalYearEnd` token (Q1..Q4) that says which\n// calendar-quarter end is the book's fiscal year end:\n//\n// Q1 → fiscal year ends March 31 (FY runs Apr 1 → Mar 31)\n// Q2 → fiscal year ends June 30 (FY runs Jul 1 → Jun 30)\n// Q3 → fiscal year ends September 30 (FY runs Oct 1 → Sep 30)\n// Q4 → fiscal year ends December 31 (FY runs Jan 1 → Dec 31; default)\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 Q4 books fiscal quarters and\n// fiscal years coincide with calendar quarters / calendar years; for\n// the other three a shift applies.\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_ENDS = [\"Q1\", \"Q2\", \"Q3\", \"Q4\"] as const;\nexport type FiscalYearEnd = (typeof FISCAL_YEAR_ENDS)[number];\n\nexport const DEFAULT_FISCAL_YEAR_END: FiscalYearEnd = \"Q4\";\n\nexport function isFiscalYearEnd(value: unknown): value is FiscalYearEnd {\n return typeof value === \"string\" && (FISCAL_YEAR_ENDS as readonly string[]).includes(value);\n}\n\n/** Books written before the field existed are treated as Q4 in code\n * but never auto-rewritten on disk. The settings UI persists through\n * the field the next time the user saves anything on the book. */\nexport function resolveFiscalYearEnd(value: FiscalYearEnd | undefined): FiscalYearEnd {\n return value ?? DEFAULT_FISCAL_YEAR_END;\n}\n\n/** Last calendar month (1-12) of the fiscal year for the given Q. */\nexport function fiscalYearEndMonth(end: FiscalYearEnd): 3 | 6 | 9 | 12 {\n if (end === \"Q1\") return 3;\n if (end === \"Q2\") return 6;\n if (end === \"Q3\") return 9;\n return 12;\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 typeof value === \"string\" && (SUPPORTED_COUNTRY_CODES as readonly string[]).includes(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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"}