@nominalso/vibe-bridge 0.1.0 → 0.3.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.
@@ -25,6 +25,8 @@ Sandboxed cross-origin iframes cannot pass `File` handles across windows, so the
25
25
  ## Example — file input with a progress bar
26
26
 
27
27
  ```ts
28
+ import { BridgeError } from '@nominalso/vibe-bridge'
29
+
28
30
  const input = document.querySelector<HTMLInputElement>('#file-input')!
29
31
 
30
32
  input.addEventListener('change', async () => {
@@ -40,9 +42,14 @@ input.addEventListener('change', async () => {
40
42
  })
41
43
  console.log('Uploaded:', result.attachmentId, result.name)
42
44
  } catch (err) {
45
+ // A failed upload throws a BridgeError with a code, e.g. 'FILE_TOO_LARGE'
46
+ // (host limit is 50 MB), 'RATE_LIMITED', or 'TIMEOUT' (uploads allow 120 s).
47
+ if (err instanceof BridgeError && err.code === 'FILE_TOO_LARGE') {
48
+ alert('That file is too large (50 MB max).')
49
+ }
43
50
  console.error('Upload failed:', err instanceof Error ? err.message : err)
44
51
  }
45
52
  })
46
53
  ```
47
54
 
48
- `upload()` resolves only after the host has fully stored the file; progress ticks arrive before it resolves.
55
+ `upload()` resolves only after the host has fully stored the file; progress ticks arrive before it resolves. Import `BridgeError` from `@nominalso/vibe-bridge` to branch on `err.code`.
@@ -15,9 +15,7 @@ No runtime dependencies. Ships ESM + CJS with self-contained TypeScript types.
15
15
  ```ts
16
16
  import { VibeAppBridge, type ContextPayload } from '@nominalso/vibe-bridge'
17
17
 
18
- const bridge = new VibeAppBridge({
19
- parentOrigin: import.meta.env.VITE_PARENT_ORIGIN,
20
- })
18
+ const bridge = new VibeAppBridge() // auto-detects the embedding Nominal host
21
19
 
22
20
  async function main() {
23
21
  const ctx: ContextPayload = await bridge.connect()
@@ -32,20 +30,24 @@ async function main() {
32
30
  main().catch(console.error)
33
31
  ```
34
32
 
35
- ## `parentOrigin`
33
+ ## `parentOrigin` (optional)
36
34
 
37
- `parentOrigin` is the **origin** (scheme + host + port, no path, no trailing slash) of the Nominal app that embeds your iframe. It must match exactly the bridge ignores messages from any other origin and only posts to this one.
35
+ By default you pass **nothing** the bridge auto-detects the Nominal app that embeds your iframe and talks only to it. This is safe because Nominal serves Vibe Apps behind a `frame-ancestors` CSP, so only nom-ui can frame the app. Most apps need nothing here.
38
36
 
39
- Drive it from an environment variable so the same code works locally and in production:
37
+ Pass `parentOrigin` to **pin the host origin** explicitly (defense in depth, or when running outside Nominal's edge). It's an **origin** — scheme + host + port, no path, no trailing slash. Drive it from an env var, or use a list / **glob patterns** for dynamic preview deployments:
40
38
 
41
- ```sh
42
- # .env (committed standalone/dev default)
43
- VITE_PARENT_ORIGIN=http://localhost:5173
39
+ ```ts
40
+ new VibeAppBridge({ parentOrigin: import.meta.env.VITE_PARENT_ORIGIN })
41
+ new VibeAppBridge({ parentOrigin: ['https://app.nominal.so', 'https://*.vercel.app'] })
42
+ ```
44
43
 
45
- # .env.local (git-ignored — when testing inside nom-ui locally)
44
+ ```sh
45
+ # .env.local — when pinning explicitly while testing inside nom-ui locally
46
46
  VITE_PARENT_ORIGIN=http://localhost:3000
47
47
  ```
48
48
 
49
+ A pattern's `*` matches exactly one DNS label or port (anchored, scheme literal). Patterns are honoured **only when the app's own page is served from a recognised preview host** (`*.vercel.app`, `*.lovable.app`, `localhost`, …); on a production custom domain they are ignored and only exact origins match. Keep at least one exact origin in the list.
50
+
49
51
  ## Next
50
52
 
51
53
  - [`connect-lifecycle.md`](./connect-lifecycle.md) — how `connect()` works and the connection lifecycle.
package/llms.txt CHANGED
@@ -2,12 +2,12 @@
2
2
 
3
3
  > Iframe-side TypeScript SDK for building Nominal Vibe Apps — standalone browser apps (often built with Lovable) embedded in the Nominal platform via a cross-origin iframe. Connects the 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. Browser-only, zero runtime dependencies.
4
4
 
5
- The integration is always the same: construct `VibeAppBridge` with the host `parentOrigin`, `await bridge.connect()` once (it returns the tenant/user `ContextPayload`), then call any of the ~46 typed data methods, `upload(file, options)`, or `postTaskOutput(...)`. Tear down with `bridge.destroy()`. The only write path into Nominal is `postTaskOutput`.
5
+ The integration is always the same: `new VibeAppBridge()` (no config `parentOrigin` is optional and the bridge auto-detects the embedding Nominal host; pass it only to pin explicitly or to allow preview origins), `await bridge.connect()` once (it returns the tenant/user `ContextPayload`), then call any of the ~46 typed data methods, `upload(file, options)`, or `postTaskOutput(...)`. Tear down with `bridge.destroy()`. The only write path into Nominal is `postTaskOutput`.
6
6
 
7
7
  ## Docs
8
8
 
9
9
  - [README](./README.md): install, quickstart, full API, common mistakes, and the operation catalog.
10
- - [Getting started](./docs/getting-started.md): install + minimal app + `parentOrigin` setup.
10
+ - [Getting started](./docs/getting-started.md): install + minimal app + optional `parentOrigin` pinning.
11
11
  - [Connection lifecycle](./docs/connect-lifecycle.md): `connect()` semantics, `ContextPayload`, timeout, subroute sync, teardown.
12
12
  - [Fetching data](./docs/data-fetching.md): named methods vs the typed `request()` escape hatch, payload shapes, errors/timeouts, operation list.
13
13
  - [File upload](./docs/file-upload.md): `upload(file, options)`, progress events, constraints.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nominalso/vibe-bridge",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "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).",
5
5
  "license": "UNLICENSED",
6
6
  "homepage": "https://github.com/nominalso/vibe-apps-sdk#readme",