@nominalso/vibe-bridge 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENTS.md CHANGED
@@ -4,10 +4,19 @@ Instructions for AI coding agents (Claude Code, Cursor, Copilot, Lovable, etc.)
4
4
 
5
5
  ## What this package is
6
6
 
7
- `@nominalso/vibe-bridge` is the **iframe-side** SDK for a Nominal Vibe App — a standalone browser app (often built with Lovable) embedded in the Nominal platform via a cross-origin `<iframe>`. The app cannot call Nominal APIs directly; it talks to its Nominal host over a typed `postMessage` bridge. This package is that bridge. It is **browser-only** (uses `window`, `postMessage`, `crypto.randomUUID`) and bundles **`posthog-js`** (its only runtime dependency) for host-enabled in-iframe session recording.
7
+ `@nominalso/vibe-bridge` is the **iframe-side** SDK for a Nominal Vibe App — a standalone browser app (often built with Lovable) embedded in the Nominal platform via a cross-origin `<iframe>`. The app cannot call Nominal APIs directly; it talks to its Nominal host over a typed `postMessage` bridge. This package is that bridge. Its methods run in the **browser** (they use `window`, `postMessage`, `crypto.randomUUID`), and it uses **`posthog-js`** as an **optional dependency** for host-enabled in-iframe session recording.
8
8
 
9
9
  The host counterpart is `@nominalso/vibe-host` (used by Nominal's own app — you do not install it in a Vibe App).
10
10
 
11
+ ## Safe to import anywhere (SSR / RSC / edge)
12
+
13
+ **The package is import- and construction-safe in any environment.** Do not add `createClientOnlyFn`, dynamic `import()`, or `typeof window` guards.
14
+
15
+ - Top-level `import { VibeAppBridge, BridgeError, HttpBridgeError, type ContextPayload } from '@nominalso/vibe-bridge'` is safe from an SSR entry, a **React Server Component**, a Cloudflare **Worker**, a shared util, or a client component. Importing has zero side effects.
16
+ - `new VibeAppBridge()` is **pure** — no browser access at construction. Only calling a method needs the browser; doing so where there is no `window` throws `BridgeError` code `'SERVER_ENVIRONMENT'`.
17
+ - RSC / Worker / edge graphs resolve (via `react-server`/`worker`/`workerd`/`edge-light`/`deno` export conditions) to a **stub with the identical API**; plain Node and jsdom/happy-dom test runners (Vitest/Jest) get the real, self-guarding build (so component tests work with a real `window`); the client build is marked `'use client'`. `destroy()` is a no-op on the server, safe as effect cleanup.
18
+ - Pattern in a client component: construct at top level (or in a ref), `await connect()` inside `useEffect`, `destroy()` in the cleanup.
19
+
11
20
  ## The one rule
12
21
 
13
22
  **Construct → `await connect()` once → then everything else.** `connect()` establishes the session context (tenant, subsidiary, user). Every data method, `upload()`, and subroute reporting requires it to have resolved first.
@@ -40,11 +49,11 @@ bridge.destroy() // on unmount
40
49
  - `track(event: string, properties?): void` — capture a custom PostHog event. **No-op unless the host enabled recording** (see below); always safe to call.
41
50
  - `destroy()`.
42
51
 
43
- **Session recording (PostHog).** The bridge bundles `posthog-js` and, on `connect()`, initializes it **only if the host sent a `posthog` block with `enabled: true`** (cross-origin replay stitched into the host's recording, masking mirroring nom-ui — inputs unmasked, password fields masked — attributed to the same person via `identify`). If the host sends nothing, the bridge initializes nothing — `enabled` is the kill-switch. You configure nothing in the app; just call `track(...)` for custom events. If you serve the app yourself, allow `connect-src https://*.i.posthog.com https://us-assets.i.posthog.com` and `worker-src blob:` in its CSP (no `script-src` entry — posthog is bundled, not from a CDN).
52
+ **Session recording (PostHog).** `posthog-js` is an **optional dependency**, loaded lazily only when the host enables recording (so it never enters a server bundle; if it's not installed, `track()` and recording no-op without throwing). On `connect()`, the bridge initializes it **only if the host sent a `posthog` block with `enabled: true`** (cross-origin replay stitched into the host's recording, masking mirroring nom-ui — inputs unmasked, password fields masked — attributed to the same person via `identify`). If the host sends nothing, the bridge initializes nothing — `enabled` is the kill-switch. You configure nothing in the app; just call `track(...)` for custom events. If you serve the app yourself, allow `connect-src https://*.i.posthog.com https://us-assets.i.posthog.com` and `worker-src blob:` in its CSP (no `script-src` entry — posthog is bundled, not from a CDN).
44
53
 
45
- A failed operation throws a `BridgeError` (`extends Error`) with a machine-readable `code` (`'RATE_LIMITED'`, `'FILE_TOO_LARGE'`, `'TIMEOUT'`, …); branch on `err.code` rather than the message. A failed Nominal API call throws the `HttpBridgeError` subtype (`code: 'REQUEST_FAILED'`) carrying the HTTP `status` — branch on `err.status` (e.g. `404`).
54
+ A failed operation throws a `BridgeError` (`extends Error`) with a machine-readable `code` (`'RATE_LIMITED'`, `'FILE_TOO_LARGE'`, `'TIMEOUT'`, `'SERVER_ENVIRONMENT'`, …); branch on `err.code` rather than the message. A failed Nominal API call throws the `HttpBridgeError` subtype (`code: 'REQUEST_FAILED'`) carrying the HTTP `status` — branch on `err.status` (e.g. `404`). Detect them with `BridgeError.isBridgeError(err)` / `HttpBridgeError.isHttpBridgeError(err)` (cross-bundle-safe) or `instanceof` (within one bundle).
46
55
 
47
- Exported values/types: `VibeAppBridge`, `BridgeError`, `HttpBridgeError`, `BRIDGE_VERSION`, and types `VibeAppBridgeOptions`, `UploadOptions`, `ContextPayload`, `BridgeSubsidiary`, `PostHogContext`, `UploadResponse`, `UploadProgress`, `RequestRegistry`.
56
+ Exported values/types: `VibeAppBridge`, `BridgeError`, `HttpBridgeError`, `BRIDGE_VERSION`, and types `VibeAppBridgeOptions`, `UploadOptions`, `ContextPayload`, `AuthPayload`, `BridgeSubsidiary`, `PostHogContext`, `UploadResponse`, `UploadProgress`, `RequestRegistry`, `NavigateAction`, `SetSideNavPayload`, `InvalidateCachePayload`, `InvalidateResult`.
48
57
 
49
58
  `ContextPayload` shape: `{ tenant, subsidiaryId, subsidiaries: { id, displayName }[], user: { id, displayName }, subroute?, lastClosedPeriodSlug?, posthog?: { token, apiHost, distinctId, enabled }, hostVersion }`. The `posthog` block is supplied by the host only when recording is on.
50
59
 
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Iframe-side SDK for building **Nominal Vibe Apps** — standalone web apps (typically built with [Lovable](https://lovable.dev)) embedded in the Nominal platform via a cross-origin `<iframe>`. The bridge connects your app to its Nominal host over a typed `postMessage` protocol: read Nominal data, submit Close-Management task outputs, upload files, and keep deep-link routing in sync.
4
4
 
5
- > **For AI agents / Lovable:** this is a browser-only SDK. The wiring is always the same — `new VibeAppBridge()` (no config — it auto-detects the Nominal host), `await bridge.connect()` **once**, then call data methods. Copy the quickstart below verbatim; it is the complete happy path.
5
+ > **For AI agents / Lovable:** the wiring is always the same — `new VibeAppBridge()` (no config — it auto-detects the Nominal host), `await bridge.connect()` **once**, then call data methods. Copy the quickstart below verbatim; it is the complete happy path. The bridge runs in the browser, but the package is **safe to import from anywhere** (SSR / React Server Components / edge) — see [below](#safe-to-import-anywhere-ssr-rsc-edge).
6
6
 
7
7
  ## Install
8
8
 
@@ -10,7 +10,39 @@ Iframe-side SDK for building **Nominal Vibe Apps** — standalone web apps (typi
10
10
  npm install @nominalso/vibe-bridge
11
11
  ```
12
12
 
13
- Bundles [`posthog-js`](https://posthog.com/docs/libraries/js) (its only runtime dependency) so the host can enable in-iframe session recording — see [Session recording & custom events](#session-recording--custom-events). Ships ESM + CJS and self-contained TypeScript types.
13
+ Ships ESM + CJS with self-contained TypeScript types. [`posthog-js`](https://posthog.com/docs/libraries/js) is an **optional dependency** (installed automatically, but the SDK degrades gracefully if it is absent) used only when the host enables in-iframe session recording — see [Session recording & custom events](#session-recording--custom-events).
14
+
15
+ ## Safe to import anywhere (SSR, RSC, edge)
16
+
17
+ `import { VibeAppBridge, BridgeError, HttpBridgeError, type ContextPayload } from '@nominalso/vibe-bridge'` is safe from **any** file — an SSR entry, a React Server Component, a Cloudflare Worker (`workerd` + `nodejs_compat`), a shared util, or a client component. The package draws a clean server/client boundary:
18
+
19
+ - **Importing has zero side effects** and **`new VibeAppBridge()` is pure** — the constructor stores options and touches no `window`/`document`/`history`/`crypto`/`posthog-js`. Nothing runs until you call a method.
20
+ - The browser is only needed when a **method actually runs**. Calling one where there is no `window` throws a `BridgeError` with code `'SERVER_ENVIRONMENT'` (a clear, coded error — never `window is not defined`).
21
+ - RSC / edge / Worker runtimes resolve — via the `react-server`, `worker`, `workerd`, `edge-light`, and `deno` [export conditions](https://nodejs.org/api/packages.html#conditional-exports) — to a **server-safe stub** with the identical API, so a Server Component can reference the bridge without executing anything. The client build carries a `'use client'` directive so RSC bundlers place it on the client side of the boundary.
22
+ - Plain **Node** (and jsdom/happy-dom test runners like **Vitest** and **Jest**) gets the real, self-guarding build — so component tests that import the package by name work against a real `window` and can call bridge methods normally; on a real Node server (no `window`) a call throws `SERVER_ENVIRONMENT` at runtime.
23
+ - `posthog-js` is optional and loaded lazily only when recording is enabled, so it never lands in a server bundle.
24
+
25
+ You therefore do **not** need `createClientOnlyFn`, dynamic `import()` wrappers, or `typeof window` guards around construction. Construct at the top of a client component and `connect()` in an effect:
26
+
27
+ ```tsx
28
+ // A client component in any SSR framework (Next.js App Router, TanStack Start,
29
+ // Remix, SvelteKit). Top-level import is fine; no client-only wrapper needed.
30
+ 'use client' // Next.js App Router: mark your own component; the SDK is already marked.
31
+ import { useEffect, useState } from 'react'
32
+ import { VibeAppBridge, type ContextPayload } from '@nominalso/vibe-bridge'
33
+
34
+ export function useVibeBridge() {
35
+ const [ctx, setCtx] = useState<ContextPayload | null>(null)
36
+ useEffect(() => {
37
+ const bridge = new VibeAppBridge() // pure — safe even if this line runs during SSR
38
+ bridge.connect().then(setCtx).catch(console.error) // only runs in the browser
39
+ return () => bridge.destroy() // idempotent + no-op on the server
40
+ }, [])
41
+ return ctx
42
+ }
43
+ ```
44
+
45
+ > **Migrating from an earlier version?** If you wrapped construction in `createClientOnlyFn` / a dynamic `await import('@nominalso/vibe-bridge')`, guarded it with `typeof window !== 'undefined'`, or reimplemented `instanceof` checks by duck-typing `err.code`/`err.status` to avoid importing the error classes — you can delete all of it. Import `VibeAppBridge`, `BridgeError`, and `HttpBridgeError` directly, and use `BridgeError.isBridgeError(err)` / `HttpBridgeError.isHttpBridgeError(err)` (below).
14
46
 
15
47
  ## Quickstart
16
48
 
@@ -116,11 +148,15 @@ Uploads a `File` through the host (converts to `ArrayBuffer` first — sandboxed
116
148
 
117
149
  ### `destroy()`
118
150
 
119
- Removes listeners, rejects pending requests, and restores patched history methods. Call on unmount.
151
+ Removes listeners, rejects pending requests, and restores patched history methods. Call on unmount. **Idempotent and server-safe** — calling it when `connect()`/`attach()` never ran (or where there is no `window`) is a harmless no-op, so it is safe as a React effect cleanup.
152
+
153
+ ### `attach()` (advanced, optional)
154
+
155
+ Installs the browser wiring (message listener + origin resolution) without starting the handshake. **You almost never need this** — `connect()` calls it for you, and any transport method lazily attaches on first use. Use it only if you want the bridge receiving host pushes before you call `connect()`. Throws `BridgeError` code `'SERVER_ENVIRONMENT'` if there is no `window`.
120
156
 
121
157
  ### Session recording & custom events
122
158
 
123
- The cross-origin iframe is invisible to the host's own session replay (same-origin policy), so the bridge bundles `posthog-js` and initializes it **itself** — but only when the host opts in. On `connect()`, if the resolved context carries a `posthog` block with `enabled: true`, the bridge:
159
+ The cross-origin iframe is invisible to the host's own session replay (same-origin policy), so the bridge drives its **own** `posthog-js` — but only when the host opts in. `posthog-js` is an **optional dependency**, loaded lazily (`await import('posthog-js')`) the first time the host enables recording, so it is never bundled into a server build and adds nothing to apps that don't record. If it isn't installed, recording and `track()` degrade to a no-op (the bridge warns once, never throws). When the host pushes a `posthog` block with `enabled: true`, the bridge:
124
160
 
125
161
  - inits `posthog-js` with `recordCrossOriginIframes: true` (so your replay is **stitched into the host's recording**) and masking that mirrors nom-ui — `maskAllInputs: false` with `maskInputOptions: { password: true }` (inputs unmasked for richer insight, password fields kept masked);
126
162
  - calls `identify()` with the host-resolved `distinctId`, so the recording and your events attribute to the **same PostHog person** as nom-ui;
@@ -142,7 +178,7 @@ Namespace your events (e.g. `vibe:<slug>:<action>`) so they stay filterable from
142
178
 
143
179
  ### Exports
144
180
 
145
- `VibeAppBridge`, `BridgeError`, `HttpBridgeError`, `BRIDGE_VERSION`, and the types `VibeAppBridgeOptions`, `UploadOptions`, `ContextPayload`, `BridgeSubsidiary`, `PostHogContext`, `UploadResponse`, `UploadProgress`, `RequestRegistry`.
181
+ `VibeAppBridge`, `BridgeError`, `HttpBridgeError`, `BRIDGE_VERSION`, and the types `VibeAppBridgeOptions`, `UploadOptions`, `ContextPayload`, `AuthPayload`, `BridgeSubsidiary`, `PostHogContext`, `UploadResponse`, `UploadProgress`, `RequestRegistry`, `NavigateAction`, `SetSideNavPayload`, `InvalidateCachePayload`, `InvalidateResult`. The same public surface (types identical) is available at the `@nominalso/vibe-bridge/server` subpath, which always resolves to the server-safe stub.
146
182
 
147
183
  ## Common recipes
148
184
 
@@ -188,16 +224,18 @@ import { BridgeError, HttpBridgeError } from '@nominalso/vibe-bridge'
188
224
  try {
189
225
  await bridge.getAccounts({})
190
226
  } catch (err) {
191
- if (err instanceof HttpBridgeError && err.status === 404) {
227
+ if (HttpBridgeError.isHttpBridgeError(err) && err.status === 404) {
192
228
  // handle not-found
193
229
  }
194
- if (err instanceof BridgeError && err.code === 'RATE_LIMITED') {
230
+ if (BridgeError.isBridgeError(err) && err.code === 'RATE_LIMITED') {
195
231
  // back off and retry
196
232
  }
197
233
  throw err
198
234
  }
199
235
  ```
200
236
 
237
+ `instanceof BridgeError` also works within a single bundle. Prefer the static `BridgeError.isBridgeError(err)` / `HttpBridgeError.isHttpBridgeError(err)` guards when an error might cross independently-built bundles (e.g. a server bundle catching an error thrown by the client bundle) — they match a process-global brand rather than class identity, so they survive bundler realm boundaries.
238
+
201
239
  ## Common mistakes
202
240
 
203
241
  ```ts
@@ -0,0 +1,405 @@
1
+ // ../protocol-types/dist/index.js
2
+ function normalizeSubroute(subroute) {
3
+ const normalized = subroute.startsWith("/") ? subroute : `/${subroute}`;
4
+ const path = normalized.split(/[?#]/)[0];
5
+ let decoded = path;
6
+ let prev;
7
+ do {
8
+ prev = decoded;
9
+ decoded = decoded.replace(/%25/gi, "%").replace(/%2e/gi, ".").replace(/%2f/gi, "/");
10
+ } while (decoded !== prev);
11
+ if (decoded.split("/").some((segment) => segment === "..")) return null;
12
+ return normalized;
13
+ }
14
+ var PROTOCOL_ID = "nominal-vibe-bridge";
15
+ var PROTOCOL_VERSION = 2;
16
+ var BRIDGE_KINDS = ["request", "response", "push", "command", "progress"];
17
+ var CORRELATED_KINDS = ["request", "response", "progress"];
18
+ var BRIDGE_KINDS_SET = new Set(BRIDGE_KINDS);
19
+ var CORRELATED_KINDS_SET = new Set(CORRELATED_KINDS);
20
+ function isBridgeMessage(data) {
21
+ if (typeof data !== "object" || data === null) return false;
22
+ const d = data;
23
+ if (d.__protocol !== PROTOCOL_ID) return false;
24
+ if (d.__version !== PROTOCOL_VERSION) return false;
25
+ if (typeof d.kind !== "string" || !BRIDGE_KINDS_SET.has(d.kind)) return false;
26
+ if (typeof d.type !== "string") return false;
27
+ if (CORRELATED_KINDS_SET.has(d.kind) && typeof d.requestId !== "string") return false;
28
+ return true;
29
+ }
30
+ var BRIDGE_ERROR_BRAND = /* @__PURE__ */ Symbol.for("@nominalso/vibe-bridge:BridgeError");
31
+ var HTTP_BRIDGE_ERROR_BRAND = /* @__PURE__ */ Symbol.for("@nominalso/vibe-bridge:HttpBridgeError");
32
+ var BridgeError = class extends Error {
33
+ constructor(code, message) {
34
+ super(message);
35
+ this.code = code;
36
+ this.name = "BridgeError";
37
+ }
38
+ /**
39
+ * Cross-realm-safe type guard. Prefer this over `instanceof BridgeError` when
40
+ * an error may have been thrown by a differently-built copy of the SDK (e.g.
41
+ * server bundle vs client bundle) — it matches on a process-global brand
42
+ * rather than class identity.
43
+ */
44
+ static isBridgeError(err) {
45
+ return typeof err === "object" && err !== null && err[BRIDGE_ERROR_BRAND] === true;
46
+ }
47
+ };
48
+ Object.defineProperty(BridgeError.prototype, BRIDGE_ERROR_BRAND, {
49
+ value: true,
50
+ enumerable: false
51
+ });
52
+ var HttpBridgeError = class extends BridgeError {
53
+ constructor(status, message) {
54
+ super("REQUEST_FAILED", message);
55
+ this.status = status;
56
+ this.name = "HttpBridgeError";
57
+ }
58
+ /**
59
+ * Cross-realm-safe type guard (see {@link BridgeError.isBridgeError}). Returns
60
+ * `true` only for `HttpBridgeError` instances, not plain `BridgeError`s.
61
+ */
62
+ static isHttpBridgeError(err) {
63
+ return typeof err === "object" && err !== null && err[HTTP_BRIDGE_ERROR_BRAND] === true;
64
+ }
65
+ };
66
+ Object.defineProperty(HttpBridgeError.prototype, HTTP_BRIDGE_ERROR_BRAND, {
67
+ value: true,
68
+ enumerable: false
69
+ });
70
+ function isOriginPattern(entry) {
71
+ return entry.includes("*");
72
+ }
73
+ var patternCache = /* @__PURE__ */ new Map();
74
+ function patternToRegExp(pattern) {
75
+ const cached = patternCache.get(pattern);
76
+ if (cached) return cached;
77
+ const escaped = pattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
78
+ const body = escaped.replace(/\\\*/g, "[^./:@?#\\s]+");
79
+ const compiled = new RegExp(`^${body}$`);
80
+ patternCache.set(pattern, compiled);
81
+ return compiled;
82
+ }
83
+ function matchesOrigin(origin, entry) {
84
+ if (!isOriginPattern(entry)) return origin === entry;
85
+ return patternToRegExp(entry).test(origin);
86
+ }
87
+ function isOriginAllowed(origin, allowlist, { allowPatterns }) {
88
+ for (const entry of allowlist) {
89
+ if (isOriginPattern(entry)) {
90
+ if (allowPatterns && matchesOrigin(origin, entry)) return true;
91
+ } else if (origin === entry) {
92
+ return true;
93
+ }
94
+ }
95
+ return false;
96
+ }
97
+
98
+ // package.json
99
+ var version = "0.6.0";
100
+
101
+ // src/version.ts
102
+ var BRIDGE_VERSION = version;
103
+
104
+ // src/data-methods.ts
105
+ var BridgeDataMethods = class {
106
+ // ---------------------------------------------------------------------------
107
+ // Operations — Accounting: chart of accounts
108
+ //
109
+ // Each method is a typed wrapper over `request('<OP>', payload)`. The payload
110
+ // and return types come straight from the Nominal API (`RequestRegistry`).
111
+ // For any operation without a named method, call `request('<OP>', payload)`.
112
+ // ---------------------------------------------------------------------------
113
+ /**
114
+ * Fetch the flat chart of accounts for a subsidiary.
115
+ *
116
+ * @example
117
+ * ```ts
118
+ * const ctx = await bridge.connect()
119
+ * const accounts = await bridge.getChartOfAccounts({
120
+ * path: { subsidiary_id: ctx.subsidiaryId },
121
+ * })
122
+ * ```
123
+ */
124
+ getChartOfAccounts(payload) {
125
+ return this.request("GET_CHART_OF_ACCOUNTS", payload);
126
+ }
127
+ /** Fetch the chart of accounts as a hierarchical tree for a subsidiary. */
128
+ getCoaTree(payload) {
129
+ return this.request("GET_COA_TREE", payload);
130
+ }
131
+ /** Fetch a simplified flat chart of accounts for a subsidiary. */
132
+ getCoaFlatSimple(payload) {
133
+ return this.request("GET_COA_FLAT_SIMPLE", payload);
134
+ }
135
+ /** Fetch the flat chart of accounts grouped by account group. */
136
+ getCoaGrouped(payload) {
137
+ return this.request("GET_COA_GROUPED", payload);
138
+ }
139
+ /** Fetch a single chart-of-accounts account by id within a subsidiary. */
140
+ getCoaAccount(payload) {
141
+ return this.request("GET_COA_ACCOUNT", payload);
142
+ }
143
+ /** List the currencies available to a subsidiary's chart of accounts. */
144
+ getSubsidiaryAvailableCurrencies(payload) {
145
+ return this.request("GET_SUBSIDIARY_AVAILABLE_CURRENCIES", payload);
146
+ }
147
+ /** Fetch accounts at the tenant level. */
148
+ getAccounts(payload) {
149
+ return this.request("GET_ACCOUNTS", payload);
150
+ }
151
+ /** Fetch a single account by id. */
152
+ getAccount(payload) {
153
+ return this.request("GET_ACCOUNT", payload);
154
+ }
155
+ // ---------------------------------------------------------------------------
156
+ // Operations — Accounting: exchange rates
157
+ // ---------------------------------------------------------------------------
158
+ /** Fetch currency conversion rates for a currency. */
159
+ getConversionRates(payload) {
160
+ return this.request("GET_CONVERSION_RATES", payload);
161
+ }
162
+ /** Fetch the effective consolidation exchange rate. */
163
+ getEffectiveExchangeRate(payload) {
164
+ return this.request("GET_EFFECTIVE_EXCHANGE_RATE", payload);
165
+ }
166
+ /** Fetch the exchange-rate period covering a given input date. */
167
+ getExchangeRateByDate(payload) {
168
+ return this.request("GET_EXCHANGE_RATE_BY_DATE", payload);
169
+ }
170
+ // ---------------------------------------------------------------------------
171
+ // Operations — Accounting: dimensions
172
+ // ---------------------------------------------------------------------------
173
+ /** List accounting dimensions. */
174
+ getDimensions(payload) {
175
+ return this.request("GET_DIMENSIONS", payload);
176
+ }
177
+ /** List values for accounting dimensions. */
178
+ getDimensionValues(payload) {
179
+ return this.request("GET_DIMENSION_VALUES", payload);
180
+ }
181
+ /** List dimension values in hierarchical form. */
182
+ getDimensionValuesHierarchical(payload) {
183
+ return this.request("GET_DIMENSION_VALUES_HIERARCHICAL", payload);
184
+ }
185
+ /** List account assignments for a dimension/account pair. */
186
+ getDimensionAccountAssignments(payload) {
187
+ return this.request("GET_DIMENSION_ACCOUNT_ASSIGNMENTS", payload);
188
+ }
189
+ // ---------------------------------------------------------------------------
190
+ // Operations — Accounting: journal entries
191
+ // ---------------------------------------------------------------------------
192
+ /**
193
+ * Fetch journal entries for a subsidiary, optionally filtered by date range.
194
+ *
195
+ * @example
196
+ * ```ts
197
+ * const entries = await bridge.getJournalEntries({
198
+ * path: { subsidiary_id: ctx.subsidiaryId },
199
+ * query: { from_date: '2026-01-01', to_date: '2026-03-31' },
200
+ * })
201
+ * ```
202
+ */
203
+ getJournalEntries(payload) {
204
+ return this.request("GET_JOURNAL_ENTRIES", payload);
205
+ }
206
+ /** Fetch journal entry lines for a subsidiary. */
207
+ getJournalLines(payload) {
208
+ return this.request("GET_JOURNAL_LINES", payload);
209
+ }
210
+ /** Fetch a single journal entry by id within a subsidiary. */
211
+ getJournalEntry(payload) {
212
+ return this.request("GET_JOURNAL_ENTRY", payload);
213
+ }
214
+ // ---------------------------------------------------------------------------
215
+ // Operations — Activity: period instances
216
+ // ---------------------------------------------------------------------------
217
+ /** List accounting period instances. */
218
+ getPeriods(payload) {
219
+ return this.request("GET_PERIODS", payload);
220
+ }
221
+ /** Fetch a single period instance by id. */
222
+ getPeriodInstance(payload) {
223
+ return this.request("GET_PERIOD_INSTANCE", payload);
224
+ }
225
+ /** Fetch a period instance by its display slug (e.g. `"mar-2026"`). */
226
+ getPeriodInstanceBySlug(payload) {
227
+ return this.request("GET_PERIOD_INSTANCE_BY_SLUG", payload);
228
+ }
229
+ /** Fetch the close-progress breakdown for a period (by slug). */
230
+ getPeriodProgressBreakdown(payload) {
231
+ return this.request("GET_PERIOD_PROGRESS_BREAKDOWN", payload);
232
+ }
233
+ // ---------------------------------------------------------------------------
234
+ // Operations — Activity: activity definitions
235
+ // ---------------------------------------------------------------------------
236
+ /** List activity definitions. */
237
+ getActivityDefinitions(payload) {
238
+ return this.request("GET_ACTIVITY_DEFINITIONS", payload);
239
+ }
240
+ /** Fetch a single activity definition by id. */
241
+ getActivityDefinition(payload) {
242
+ return this.request("GET_ACTIVITY_DEFINITION", payload);
243
+ }
244
+ // ---------------------------------------------------------------------------
245
+ // Operations — Activity: activity instances
246
+ // ---------------------------------------------------------------------------
247
+ /** List activity instances. */
248
+ getActivityInstances(payload) {
249
+ return this.request("GET_ACTIVITY_INSTANCES", payload);
250
+ }
251
+ /** Fetch a single activity instance by id. */
252
+ getActivityInstance(payload) {
253
+ return this.request("GET_ACTIVITY_INSTANCE", payload);
254
+ }
255
+ /** Fetch an activity instance for a given period + activity definition. */
256
+ getActivityInstanceByPeriod(payload) {
257
+ return this.request("GET_ACTIVITY_INSTANCE_BY_PERIOD", payload);
258
+ }
259
+ /** List task instances for an activity instance. */
260
+ getActivityInstanceTasks(payload) {
261
+ return this.request("GET_ACTIVITY_INSTANCE_TASKS", payload);
262
+ }
263
+ /** List task instances for an activity in a given period. */
264
+ getActivityPeriodTasks(payload) {
265
+ return this.request("GET_ACTIVITY_PERIOD_TASKS", payload);
266
+ }
267
+ // ---------------------------------------------------------------------------
268
+ // Operations — Activity: task definitions
269
+ // ---------------------------------------------------------------------------
270
+ /** List task definitions. */
271
+ getTaskDefinitions(payload) {
272
+ return this.request("GET_TASK_DEFINITIONS", payload);
273
+ }
274
+ /** Fetch a single task definition by id. */
275
+ getTaskDefinition(payload) {
276
+ return this.request("GET_TASK_DEFINITION", payload);
277
+ }
278
+ /** Create a task definition. */
279
+ createTaskDefinition(payload) {
280
+ return this.request("CREATE_TASK_DEFINITION", payload);
281
+ }
282
+ /** Update a task definition by id. */
283
+ updateTaskDefinition(payload) {
284
+ return this.request("UPDATE_TASK_DEFINITION", payload);
285
+ }
286
+ /** Query task definitions by filter. */
287
+ getTaskDefinitionsByFilter(payload) {
288
+ return this.request("GET_TASK_DEFINITIONS_BY_FILTER", payload);
289
+ }
290
+ // ---------------------------------------------------------------------------
291
+ // Operations — Activity: task instances
292
+ // ---------------------------------------------------------------------------
293
+ /** List task instances. */
294
+ getTaskInstances(payload) {
295
+ return this.request("GET_TASK_INSTANCES", payload);
296
+ }
297
+ /** Fetch a single task instance by id. */
298
+ getTaskInstance(payload) {
299
+ return this.request("GET_TASK_INSTANCE", payload);
300
+ }
301
+ /**
302
+ * Submit a Close-Management task output. This is the **only write path** back
303
+ * into Nominal — Vibe Apps never write Nominal data directly.
304
+ *
305
+ * @example
306
+ * ```ts
307
+ * // `body` carries the task-specific output shape.
308
+ * await bridge.postTaskOutput({
309
+ * path: { task_instance_id: 'task-1' },
310
+ * body: {},
311
+ * })
312
+ * ```
313
+ */
314
+ postTaskOutput(payload) {
315
+ return this.request("POST_TASK_OUTPUT", payload);
316
+ }
317
+ /** Query task instances by filter. */
318
+ getTaskInstancesByFilter(payload) {
319
+ return this.request("GET_TASK_INSTANCES_BY_FILTER", payload);
320
+ }
321
+ // ---------------------------------------------------------------------------
322
+ // Operations — Audit trail
323
+ // ---------------------------------------------------------------------------
324
+ /** List audit-trail events. */
325
+ getAuditEvents(payload) {
326
+ return this.request("GET_AUDIT_EVENTS", payload);
327
+ }
328
+ /** List audit-trail events for a specific entity. */
329
+ getEntityAuditEvents(payload) {
330
+ return this.request("GET_ENTITY_AUDIT_EVENTS", payload);
331
+ }
332
+ // ---------------------------------------------------------------------------
333
+ // Operations — Period manager: fiscal calendars
334
+ // ---------------------------------------------------------------------------
335
+ /** List fiscal calendars for a subsidiary. */
336
+ getFiscalCalendars(payload) {
337
+ return this.request("GET_FISCAL_CALENDARS", payload);
338
+ }
339
+ /** Fetch a single fiscal calendar by id. */
340
+ getFiscalCalendar(payload) {
341
+ return this.request("GET_FISCAL_CALENDAR", payload);
342
+ }
343
+ // ---------------------------------------------------------------------------
344
+ // Operations — Tenancy
345
+ // ---------------------------------------------------------------------------
346
+ /** List subsidiaries for the tenant. */
347
+ getSubsidiaries(payload) {
348
+ return this.request("GET_SUBSIDIARIES", payload);
349
+ }
350
+ /** Fetch a single subsidiary by id. */
351
+ getSubsidiary(payload) {
352
+ return this.request("GET_SUBSIDIARY", payload);
353
+ }
354
+ /** List parent currencies for a subsidiary. */
355
+ getSubsidiaryParentCurrencies(payload) {
356
+ return this.request("GET_SUBSIDIARY_PARENT_CURRENCIES", payload);
357
+ }
358
+ /** List users for the tenant. */
359
+ getTenantUsers(payload) {
360
+ return this.request("GET_TENANT_USERS", payload);
361
+ }
362
+ /**
363
+ * Uploads a file through the host. Converts the `File` to an `ArrayBuffer`
364
+ * before sending — sandboxed iframes cannot pass `File` handles across
365
+ * windows. Resolves once Nominal has stored the file.
366
+ *
367
+ * @example
368
+ * ```ts
369
+ * const input = document.querySelector<HTMLInputElement>('#file')!
370
+ * const file = input.files![0]
371
+ * const result = await bridge.upload(file, {
372
+ * entityType: 'JOURNAL_ENTRY',
373
+ * entityId: '123',
374
+ * onProgress: (p) => console.log(`${p.progress}%`),
375
+ * })
376
+ * // result.attachmentId, result.name
377
+ * ```
378
+ */
379
+ async upload(file, options) {
380
+ const buffer = await file.arrayBuffer();
381
+ const payload = {
382
+ buffer,
383
+ fileName: file.name,
384
+ fileType: file.type,
385
+ entityType: options.entityType,
386
+ entityId: options.entityId
387
+ };
388
+ const onProgress = options.onProgress ? (p) => options.onProgress(p) : void 0;
389
+ return this.request("UPLOAD_FILE", payload, onProgress);
390
+ }
391
+ };
392
+
393
+ export {
394
+ normalizeSubroute,
395
+ PROTOCOL_ID,
396
+ PROTOCOL_VERSION,
397
+ isBridgeMessage,
398
+ BridgeError,
399
+ HttpBridgeError,
400
+ isOriginPattern,
401
+ isOriginAllowed,
402
+ BridgeDataMethods,
403
+ BRIDGE_VERSION
404
+ };
405
+ //# sourceMappingURL=chunk-AH2BCQVB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../protocol-types/dist/index.js","../package.json","../src/version.ts","../src/data-methods.ts"],"sourcesContent":["// src/subroute.ts\nfunction normalizeSubroute(subroute) {\n const normalized = subroute.startsWith(\"/\") ? subroute : `/${subroute}`;\n const path = normalized.split(/[?#]/)[0];\n let decoded = path;\n let prev;\n do {\n prev = decoded;\n decoded = decoded.replace(/%25/gi, \"%\").replace(/%2e/gi, \".\").replace(/%2f/gi, \"/\");\n } while (decoded !== prev);\n if (decoded.split(\"/\").some((segment) => segment === \"..\")) return null;\n return normalized;\n}\n\n// src/protocol.ts\nvar PROTOCOL_ID = \"nominal-vibe-bridge\";\nvar PROTOCOL_VERSION = 2;\nvar BRIDGE_KINDS = [\"request\", \"response\", \"push\", \"command\", \"progress\"];\nvar CORRELATED_KINDS = [\"request\", \"response\", \"progress\"];\nvar BRIDGE_KINDS_SET = new Set(BRIDGE_KINDS);\nvar CORRELATED_KINDS_SET = new Set(CORRELATED_KINDS);\nfunction isBridgeMessage(data) {\n if (typeof data !== \"object\" || data === null) return false;\n const d = data;\n if (d.__protocol !== PROTOCOL_ID) return false;\n if (d.__version !== PROTOCOL_VERSION) return false;\n if (typeof d.kind !== \"string\" || !BRIDGE_KINDS_SET.has(d.kind)) return false;\n if (typeof d.type !== \"string\") return false;\n if (CORRELATED_KINDS_SET.has(d.kind) && typeof d.requestId !== \"string\") return false;\n return true;\n}\n\n// src/errors.ts\nvar BRIDGE_ERROR_BRAND = /* @__PURE__ */ Symbol.for(\"@nominalso/vibe-bridge:BridgeError\");\nvar HTTP_BRIDGE_ERROR_BRAND = /* @__PURE__ */ Symbol.for(\"@nominalso/vibe-bridge:HttpBridgeError\");\nvar BridgeError = class extends Error {\n constructor(code, message) {\n super(message);\n this.code = code;\n this.name = \"BridgeError\";\n }\n /**\n * Cross-realm-safe type guard. Prefer this over `instanceof BridgeError` when\n * an error may have been thrown by a differently-built copy of the SDK (e.g.\n * server bundle vs client bundle) — it matches on a process-global brand\n * rather than class identity.\n */\n static isBridgeError(err) {\n return typeof err === \"object\" && err !== null && err[BRIDGE_ERROR_BRAND] === true;\n }\n};\nObject.defineProperty(BridgeError.prototype, BRIDGE_ERROR_BRAND, {\n value: true,\n enumerable: false\n});\nvar HttpBridgeError = class extends BridgeError {\n constructor(status, message) {\n super(\"REQUEST_FAILED\", message);\n this.status = status;\n this.name = \"HttpBridgeError\";\n }\n /**\n * Cross-realm-safe type guard (see {@link BridgeError.isBridgeError}). Returns\n * `true` only for `HttpBridgeError` instances, not plain `BridgeError`s.\n */\n static isHttpBridgeError(err) {\n return typeof err === \"object\" && err !== null && err[HTTP_BRIDGE_ERROR_BRAND] === true;\n }\n};\nObject.defineProperty(HttpBridgeError.prototype, HTTP_BRIDGE_ERROR_BRAND, {\n value: true,\n enumerable: false\n});\n\n// src/origins.ts\nfunction isOriginPattern(entry) {\n return entry.includes(\"*\");\n}\nvar patternCache = /* @__PURE__ */ new Map();\nfunction patternToRegExp(pattern) {\n const cached = patternCache.get(pattern);\n if (cached) return cached;\n const escaped = pattern.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const body = escaped.replace(/\\\\\\*/g, \"[^./:@?#\\\\s]+\");\n const compiled = new RegExp(`^${body}$`);\n patternCache.set(pattern, compiled);\n return compiled;\n}\nfunction matchesOrigin(origin, entry) {\n if (!isOriginPattern(entry)) return origin === entry;\n return patternToRegExp(entry).test(origin);\n}\nfunction isOriginAllowed(origin, allowlist, { allowPatterns }) {\n for (const entry of allowlist) {\n if (isOriginPattern(entry)) {\n if (allowPatterns && matchesOrigin(origin, entry)) return true;\n } else if (origin === entry) {\n return true;\n }\n }\n return false;\n}\nexport {\n BridgeError,\n HttpBridgeError,\n PROTOCOL_ID,\n PROTOCOL_VERSION,\n isBridgeMessage,\n isOriginAllowed,\n isOriginPattern,\n matchesOrigin,\n normalizeSubroute\n};\n","{\n \"name\": \"@nominalso/vibe-bridge\",\n \"version\": \"0.6.0\",\n \"description\": \"Iframe-side SDK for building Nominal Vibe Apps — connects an embedded app to its Nominal host over a typed postMessage bridge (context, data fetch, file upload, subroute deep-linking). Safe to import from SSR, React Server Components, and edge/Worker runtimes.\",\n \"license\": \"UNLICENSED\",\n \"homepage\": \"https://github.com/nominalso/vibe-apps-sdk#readme\",\n \"bugs\": {\n \"url\": \"https://github.com/nominalso/vibe-apps-sdk/issues\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"github:nominalso/vibe-apps-sdk\",\n \"directory\": \"packages/bridge\"\n },\n \"type\": \"module\",\n \"sideEffects\": false,\n \"types\": \"./dist/index.d.ts\",\n \"main\": \"./dist/index.browser.cjs\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"react-server\": \"./dist/index.server.js\",\n \"workerd\": \"./dist/index.server.js\",\n \"worker\": \"./dist/index.server.js\",\n \"edge-light\": \"./dist/index.server.js\",\n \"deno\": \"./dist/index.server.js\",\n \"browser\": {\n \"import\": \"./dist/index.browser.js\",\n \"require\": \"./dist/index.browser.cjs\"\n },\n \"default\": {\n \"import\": \"./dist/index.browser.js\",\n \"require\": \"./dist/index.browser.cjs\"\n }\n },\n \"./server\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.server.js\",\n \"require\": \"./dist/index.server.cjs\"\n },\n \"./package.json\": \"./package.json\"\n },\n \"files\": [\n \"dist\",\n \"docs\",\n \"AGENTS.md\",\n \"llms.txt\"\n ],\n \"publishConfig\": {\n \"registry\": \"https://registry.npmjs.org/\",\n \"access\": \"public\"\n },\n \"scripts\": {\n \"clean\": \"rm -rf dist node_modules\",\n \"build\": \"rm -rf dist && tsup\",\n \"lint\": \"eslint src\",\n \"typecheck\": \"tsc --noEmit\",\n \"test\": \"vitest run\"\n },\n \"optionalDependencies\": {\n \"posthog-js\": \"^1.393.5\"\n },\n \"devDependencies\": {\n \"@nominalso/vibe-api-types\": \"workspace:*\",\n \"@nominalso/vibe-protocol-types\": \"workspace:*\"\n }\n}\n","import { version } from '../package.json'\n\n/**\n * Published version of this package (`@nominalso/vibe-bridge`), sent to the host\n * in the `CONNECT` handshake. Import-safe from any environment.\n */\nexport const BRIDGE_VERSION: string = version\n","import type { RequestRegistry } from '@nominalso/vibe-protocol-types'\n\nexport interface UploadOptions {\n /** Domain entity the file attaches to, e.g. `'JOURNAL_ENTRY'`. */\n entityType: string\n /** Id of the entity the file attaches to, when applicable. */\n entityId?: string | number\n /** Called with incremental progress (`0`–`100`) while the upload streams. */\n onProgress?: (p: RequestRegistry['UPLOAD_FILE']['progress']) => void\n}\n\n/**\n * The typed Nominal data methods (~46) plus {@link BridgeDataMethods.upload},\n * factored onto a base class so {@link VibeAppBridge} stays focused on\n * connection/transport. Each method is a thin typed wrapper over `request()`;\n * `VibeAppBridge` provides the concrete `request` implementation.\n */\nexport abstract class BridgeDataMethods {\n /**\n * Low-level typed request for **any** operation in {@link RequestRegistry} —\n * implemented by {@link VibeAppBridge}. The named methods below wrap this.\n */\n abstract request<K extends keyof RequestRegistry>(\n type: K,\n payload: RequestRegistry[K]['payload'],\n onProgress?: (payload: unknown) => void,\n ): Promise<RequestRegistry[K]['data']>\n\n // ---------------------------------------------------------------------------\n // Operations — Accounting: chart of accounts\n //\n // Each method is a typed wrapper over `request('<OP>', payload)`. The payload\n // and return types come straight from the Nominal API (`RequestRegistry`).\n // For any operation without a named method, call `request('<OP>', payload)`.\n // ---------------------------------------------------------------------------\n\n /**\n * Fetch the flat chart of accounts for a subsidiary.\n *\n * @example\n * ```ts\n * const ctx = await bridge.connect()\n * const accounts = await bridge.getChartOfAccounts({\n * path: { subsidiary_id: ctx.subsidiaryId },\n * })\n * ```\n */\n getChartOfAccounts(\n payload: RequestRegistry['GET_CHART_OF_ACCOUNTS']['payload'],\n ): Promise<RequestRegistry['GET_CHART_OF_ACCOUNTS']['data']> {\n return this.request('GET_CHART_OF_ACCOUNTS', payload)\n }\n\n /** Fetch the chart of accounts as a hierarchical tree for a subsidiary. */\n getCoaTree(\n payload: RequestRegistry['GET_COA_TREE']['payload'],\n ): Promise<RequestRegistry['GET_COA_TREE']['data']> {\n return this.request('GET_COA_TREE', payload)\n }\n\n /** Fetch a simplified flat chart of accounts for a subsidiary. */\n getCoaFlatSimple(\n payload: RequestRegistry['GET_COA_FLAT_SIMPLE']['payload'],\n ): Promise<RequestRegistry['GET_COA_FLAT_SIMPLE']['data']> {\n return this.request('GET_COA_FLAT_SIMPLE', payload)\n }\n\n /** Fetch the flat chart of accounts grouped by account group. */\n getCoaGrouped(\n payload: RequestRegistry['GET_COA_GROUPED']['payload'],\n ): Promise<RequestRegistry['GET_COA_GROUPED']['data']> {\n return this.request('GET_COA_GROUPED', payload)\n }\n\n /** Fetch a single chart-of-accounts account by id within a subsidiary. */\n getCoaAccount(\n payload: RequestRegistry['GET_COA_ACCOUNT']['payload'],\n ): Promise<RequestRegistry['GET_COA_ACCOUNT']['data']> {\n return this.request('GET_COA_ACCOUNT', payload)\n }\n\n /** List the currencies available to a subsidiary's chart of accounts. */\n getSubsidiaryAvailableCurrencies(\n payload: RequestRegistry['GET_SUBSIDIARY_AVAILABLE_CURRENCIES']['payload'],\n ): Promise<RequestRegistry['GET_SUBSIDIARY_AVAILABLE_CURRENCIES']['data']> {\n return this.request('GET_SUBSIDIARY_AVAILABLE_CURRENCIES', payload)\n }\n\n /** Fetch accounts at the tenant level. */\n getAccounts(\n payload: RequestRegistry['GET_ACCOUNTS']['payload'],\n ): Promise<RequestRegistry['GET_ACCOUNTS']['data']> {\n return this.request('GET_ACCOUNTS', payload)\n }\n\n /** Fetch a single account by id. */\n getAccount(\n payload: RequestRegistry['GET_ACCOUNT']['payload'],\n ): Promise<RequestRegistry['GET_ACCOUNT']['data']> {\n return this.request('GET_ACCOUNT', payload)\n }\n\n // ---------------------------------------------------------------------------\n // Operations — Accounting: exchange rates\n // ---------------------------------------------------------------------------\n\n /** Fetch currency conversion rates for a currency. */\n getConversionRates(\n payload: RequestRegistry['GET_CONVERSION_RATES']['payload'],\n ): Promise<RequestRegistry['GET_CONVERSION_RATES']['data']> {\n return this.request('GET_CONVERSION_RATES', payload)\n }\n\n /** Fetch the effective consolidation exchange rate. */\n getEffectiveExchangeRate(\n payload: RequestRegistry['GET_EFFECTIVE_EXCHANGE_RATE']['payload'],\n ): Promise<RequestRegistry['GET_EFFECTIVE_EXCHANGE_RATE']['data']> {\n return this.request('GET_EFFECTIVE_EXCHANGE_RATE', payload)\n }\n\n /** Fetch the exchange-rate period covering a given input date. */\n getExchangeRateByDate(\n payload: RequestRegistry['GET_EXCHANGE_RATE_BY_DATE']['payload'],\n ): Promise<RequestRegistry['GET_EXCHANGE_RATE_BY_DATE']['data']> {\n return this.request('GET_EXCHANGE_RATE_BY_DATE', payload)\n }\n\n // ---------------------------------------------------------------------------\n // Operations — Accounting: dimensions\n // ---------------------------------------------------------------------------\n\n /** List accounting dimensions. */\n getDimensions(\n payload: RequestRegistry['GET_DIMENSIONS']['payload'],\n ): Promise<RequestRegistry['GET_DIMENSIONS']['data']> {\n return this.request('GET_DIMENSIONS', payload)\n }\n\n /** List values for accounting dimensions. */\n getDimensionValues(\n payload: RequestRegistry['GET_DIMENSION_VALUES']['payload'],\n ): Promise<RequestRegistry['GET_DIMENSION_VALUES']['data']> {\n return this.request('GET_DIMENSION_VALUES', payload)\n }\n\n /** List dimension values in hierarchical form. */\n getDimensionValuesHierarchical(\n payload: RequestRegistry['GET_DIMENSION_VALUES_HIERARCHICAL']['payload'],\n ): Promise<RequestRegistry['GET_DIMENSION_VALUES_HIERARCHICAL']['data']> {\n return this.request('GET_DIMENSION_VALUES_HIERARCHICAL', payload)\n }\n\n /** List account assignments for a dimension/account pair. */\n getDimensionAccountAssignments(\n payload: RequestRegistry['GET_DIMENSION_ACCOUNT_ASSIGNMENTS']['payload'],\n ): Promise<RequestRegistry['GET_DIMENSION_ACCOUNT_ASSIGNMENTS']['data']> {\n return this.request('GET_DIMENSION_ACCOUNT_ASSIGNMENTS', payload)\n }\n\n // ---------------------------------------------------------------------------\n // Operations — Accounting: journal entries\n // ---------------------------------------------------------------------------\n\n /**\n * Fetch journal entries for a subsidiary, optionally filtered by date range.\n *\n * @example\n * ```ts\n * const entries = await bridge.getJournalEntries({\n * path: { subsidiary_id: ctx.subsidiaryId },\n * query: { from_date: '2026-01-01', to_date: '2026-03-31' },\n * })\n * ```\n */\n getJournalEntries(\n payload: RequestRegistry['GET_JOURNAL_ENTRIES']['payload'],\n ): Promise<RequestRegistry['GET_JOURNAL_ENTRIES']['data']> {\n return this.request('GET_JOURNAL_ENTRIES', payload)\n }\n\n /** Fetch journal entry lines for a subsidiary. */\n getJournalLines(\n payload: RequestRegistry['GET_JOURNAL_LINES']['payload'],\n ): Promise<RequestRegistry['GET_JOURNAL_LINES']['data']> {\n return this.request('GET_JOURNAL_LINES', payload)\n }\n\n /** Fetch a single journal entry by id within a subsidiary. */\n getJournalEntry(\n payload: RequestRegistry['GET_JOURNAL_ENTRY']['payload'],\n ): Promise<RequestRegistry['GET_JOURNAL_ENTRY']['data']> {\n return this.request('GET_JOURNAL_ENTRY', payload)\n }\n\n // ---------------------------------------------------------------------------\n // Operations — Activity: period instances\n // ---------------------------------------------------------------------------\n\n /** List accounting period instances. */\n getPeriods(\n payload: RequestRegistry['GET_PERIODS']['payload'],\n ): Promise<RequestRegistry['GET_PERIODS']['data']> {\n return this.request('GET_PERIODS', payload)\n }\n\n /** Fetch a single period instance by id. */\n getPeriodInstance(\n payload: RequestRegistry['GET_PERIOD_INSTANCE']['payload'],\n ): Promise<RequestRegistry['GET_PERIOD_INSTANCE']['data']> {\n return this.request('GET_PERIOD_INSTANCE', payload)\n }\n\n /** Fetch a period instance by its display slug (e.g. `\"mar-2026\"`). */\n getPeriodInstanceBySlug(\n payload: RequestRegistry['GET_PERIOD_INSTANCE_BY_SLUG']['payload'],\n ): Promise<RequestRegistry['GET_PERIOD_INSTANCE_BY_SLUG']['data']> {\n return this.request('GET_PERIOD_INSTANCE_BY_SLUG', payload)\n }\n\n /** Fetch the close-progress breakdown for a period (by slug). */\n getPeriodProgressBreakdown(\n payload: RequestRegistry['GET_PERIOD_PROGRESS_BREAKDOWN']['payload'],\n ): Promise<RequestRegistry['GET_PERIOD_PROGRESS_BREAKDOWN']['data']> {\n return this.request('GET_PERIOD_PROGRESS_BREAKDOWN', payload)\n }\n\n // ---------------------------------------------------------------------------\n // Operations — Activity: activity definitions\n // ---------------------------------------------------------------------------\n\n /** List activity definitions. */\n getActivityDefinitions(\n payload: RequestRegistry['GET_ACTIVITY_DEFINITIONS']['payload'],\n ): Promise<RequestRegistry['GET_ACTIVITY_DEFINITIONS']['data']> {\n return this.request('GET_ACTIVITY_DEFINITIONS', payload)\n }\n\n /** Fetch a single activity definition by id. */\n getActivityDefinition(\n payload: RequestRegistry['GET_ACTIVITY_DEFINITION']['payload'],\n ): Promise<RequestRegistry['GET_ACTIVITY_DEFINITION']['data']> {\n return this.request('GET_ACTIVITY_DEFINITION', payload)\n }\n\n // ---------------------------------------------------------------------------\n // Operations — Activity: activity instances\n // ---------------------------------------------------------------------------\n\n /** List activity instances. */\n getActivityInstances(\n payload: RequestRegistry['GET_ACTIVITY_INSTANCES']['payload'],\n ): Promise<RequestRegistry['GET_ACTIVITY_INSTANCES']['data']> {\n return this.request('GET_ACTIVITY_INSTANCES', payload)\n }\n\n /** Fetch a single activity instance by id. */\n getActivityInstance(\n payload: RequestRegistry['GET_ACTIVITY_INSTANCE']['payload'],\n ): Promise<RequestRegistry['GET_ACTIVITY_INSTANCE']['data']> {\n return this.request('GET_ACTIVITY_INSTANCE', payload)\n }\n\n /** Fetch an activity instance for a given period + activity definition. */\n getActivityInstanceByPeriod(\n payload: RequestRegistry['GET_ACTIVITY_INSTANCE_BY_PERIOD']['payload'],\n ): Promise<RequestRegistry['GET_ACTIVITY_INSTANCE_BY_PERIOD']['data']> {\n return this.request('GET_ACTIVITY_INSTANCE_BY_PERIOD', payload)\n }\n\n /** List task instances for an activity instance. */\n getActivityInstanceTasks(\n payload: RequestRegistry['GET_ACTIVITY_INSTANCE_TASKS']['payload'],\n ): Promise<RequestRegistry['GET_ACTIVITY_INSTANCE_TASKS']['data']> {\n return this.request('GET_ACTIVITY_INSTANCE_TASKS', payload)\n }\n\n /** List task instances for an activity in a given period. */\n getActivityPeriodTasks(\n payload: RequestRegistry['GET_ACTIVITY_PERIOD_TASKS']['payload'],\n ): Promise<RequestRegistry['GET_ACTIVITY_PERIOD_TASKS']['data']> {\n return this.request('GET_ACTIVITY_PERIOD_TASKS', payload)\n }\n\n // ---------------------------------------------------------------------------\n // Operations — Activity: task definitions\n // ---------------------------------------------------------------------------\n\n /** List task definitions. */\n getTaskDefinitions(\n payload: RequestRegistry['GET_TASK_DEFINITIONS']['payload'],\n ): Promise<RequestRegistry['GET_TASK_DEFINITIONS']['data']> {\n return this.request('GET_TASK_DEFINITIONS', payload)\n }\n\n /** Fetch a single task definition by id. */\n getTaskDefinition(\n payload: RequestRegistry['GET_TASK_DEFINITION']['payload'],\n ): Promise<RequestRegistry['GET_TASK_DEFINITION']['data']> {\n return this.request('GET_TASK_DEFINITION', payload)\n }\n\n /** Create a task definition. */\n createTaskDefinition(\n payload: RequestRegistry['CREATE_TASK_DEFINITION']['payload'],\n ): Promise<RequestRegistry['CREATE_TASK_DEFINITION']['data']> {\n return this.request('CREATE_TASK_DEFINITION', payload)\n }\n\n /** Update a task definition by id. */\n updateTaskDefinition(\n payload: RequestRegistry['UPDATE_TASK_DEFINITION']['payload'],\n ): Promise<RequestRegistry['UPDATE_TASK_DEFINITION']['data']> {\n return this.request('UPDATE_TASK_DEFINITION', payload)\n }\n\n /** Query task definitions by filter. */\n getTaskDefinitionsByFilter(\n payload: RequestRegistry['GET_TASK_DEFINITIONS_BY_FILTER']['payload'],\n ): Promise<RequestRegistry['GET_TASK_DEFINITIONS_BY_FILTER']['data']> {\n return this.request('GET_TASK_DEFINITIONS_BY_FILTER', payload)\n }\n\n // ---------------------------------------------------------------------------\n // Operations — Activity: task instances\n // ---------------------------------------------------------------------------\n\n /** List task instances. */\n getTaskInstances(\n payload: RequestRegistry['GET_TASK_INSTANCES']['payload'],\n ): Promise<RequestRegistry['GET_TASK_INSTANCES']['data']> {\n return this.request('GET_TASK_INSTANCES', payload)\n }\n\n /** Fetch a single task instance by id. */\n getTaskInstance(\n payload: RequestRegistry['GET_TASK_INSTANCE']['payload'],\n ): Promise<RequestRegistry['GET_TASK_INSTANCE']['data']> {\n return this.request('GET_TASK_INSTANCE', payload)\n }\n\n /**\n * Submit a Close-Management task output. This is the **only write path** back\n * into Nominal — Vibe Apps never write Nominal data directly.\n *\n * @example\n * ```ts\n * // `body` carries the task-specific output shape.\n * await bridge.postTaskOutput({\n * path: { task_instance_id: 'task-1' },\n * body: {},\n * })\n * ```\n */\n postTaskOutput(\n payload: RequestRegistry['POST_TASK_OUTPUT']['payload'],\n ): Promise<RequestRegistry['POST_TASK_OUTPUT']['data']> {\n return this.request('POST_TASK_OUTPUT', payload)\n }\n\n /** Query task instances by filter. */\n getTaskInstancesByFilter(\n payload: RequestRegistry['GET_TASK_INSTANCES_BY_FILTER']['payload'],\n ): Promise<RequestRegistry['GET_TASK_INSTANCES_BY_FILTER']['data']> {\n return this.request('GET_TASK_INSTANCES_BY_FILTER', payload)\n }\n\n // ---------------------------------------------------------------------------\n // Operations — Audit trail\n // ---------------------------------------------------------------------------\n\n /** List audit-trail events. */\n getAuditEvents(\n payload: RequestRegistry['GET_AUDIT_EVENTS']['payload'],\n ): Promise<RequestRegistry['GET_AUDIT_EVENTS']['data']> {\n return this.request('GET_AUDIT_EVENTS', payload)\n }\n\n /** List audit-trail events for a specific entity. */\n getEntityAuditEvents(\n payload: RequestRegistry['GET_ENTITY_AUDIT_EVENTS']['payload'],\n ): Promise<RequestRegistry['GET_ENTITY_AUDIT_EVENTS']['data']> {\n return this.request('GET_ENTITY_AUDIT_EVENTS', payload)\n }\n\n // ---------------------------------------------------------------------------\n // Operations — Period manager: fiscal calendars\n // ---------------------------------------------------------------------------\n\n /** List fiscal calendars for a subsidiary. */\n getFiscalCalendars(\n payload: RequestRegistry['GET_FISCAL_CALENDARS']['payload'],\n ): Promise<RequestRegistry['GET_FISCAL_CALENDARS']['data']> {\n return this.request('GET_FISCAL_CALENDARS', payload)\n }\n\n /** Fetch a single fiscal calendar by id. */\n getFiscalCalendar(\n payload: RequestRegistry['GET_FISCAL_CALENDAR']['payload'],\n ): Promise<RequestRegistry['GET_FISCAL_CALENDAR']['data']> {\n return this.request('GET_FISCAL_CALENDAR', payload)\n }\n\n // ---------------------------------------------------------------------------\n // Operations — Tenancy\n // ---------------------------------------------------------------------------\n\n /** List subsidiaries for the tenant. */\n getSubsidiaries(\n payload: RequestRegistry['GET_SUBSIDIARIES']['payload'],\n ): Promise<RequestRegistry['GET_SUBSIDIARIES']['data']> {\n return this.request('GET_SUBSIDIARIES', payload)\n }\n\n /** Fetch a single subsidiary by id. */\n getSubsidiary(\n payload: RequestRegistry['GET_SUBSIDIARY']['payload'],\n ): Promise<RequestRegistry['GET_SUBSIDIARY']['data']> {\n return this.request('GET_SUBSIDIARY', payload)\n }\n\n /** List parent currencies for a subsidiary. */\n getSubsidiaryParentCurrencies(\n payload: RequestRegistry['GET_SUBSIDIARY_PARENT_CURRENCIES']['payload'],\n ): Promise<RequestRegistry['GET_SUBSIDIARY_PARENT_CURRENCIES']['data']> {\n return this.request('GET_SUBSIDIARY_PARENT_CURRENCIES', payload)\n }\n\n /** List users for the tenant. */\n getTenantUsers(\n payload: RequestRegistry['GET_TENANT_USERS']['payload'],\n ): Promise<RequestRegistry['GET_TENANT_USERS']['data']> {\n return this.request('GET_TENANT_USERS', payload)\n }\n\n /**\n * Uploads a file through the host. Converts the `File` to an `ArrayBuffer`\n * before sending — sandboxed iframes cannot pass `File` handles across\n * windows. Resolves once Nominal has stored the file.\n *\n * @example\n * ```ts\n * const input = document.querySelector<HTMLInputElement>('#file')!\n * const file = input.files![0]\n * const result = await bridge.upload(file, {\n * entityType: 'JOURNAL_ENTRY',\n * entityId: '123',\n * onProgress: (p) => console.log(`${p.progress}%`),\n * })\n * // result.attachmentId, result.name\n * ```\n */\n async upload(\n file: File,\n options: UploadOptions,\n ): Promise<RequestRegistry['UPLOAD_FILE']['data']> {\n const buffer = await file.arrayBuffer()\n const payload: RequestRegistry['UPLOAD_FILE']['payload'] = {\n buffer,\n fileName: file.name,\n fileType: file.type,\n entityType: options.entityType,\n entityId: options.entityId,\n }\n const onProgress = options.onProgress\n ? (p: unknown): void => options.onProgress!(p as RequestRegistry['UPLOAD_FILE']['progress'])\n : undefined\n return this.request('UPLOAD_FILE', payload, onProgress)\n }\n}\n"],"mappings":"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","names":[]}