@orangecheck/me-client 0.27.3 → 0.27.4

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/dist/popup.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/popup.ts"],"names":[],"mappings":"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","file":"popup.js","sourcesContent":["/**\n * @orangecheck/me-client/popup\n *\n * Browser-side helper that opens the OC sign-in popup, listens for the\n * postMessage from me.ochk.io, and resolves with the verified session.\n *\n * import { signInWithOc } from '@orangecheck/me-client/popup';\n *\n * document.querySelector('#oc-signin')!.addEventListener('click', async () => {\n * const result = await signInWithOc();\n * if (result) {\n * localStorage.setItem('oc-session-token', result.token);\n * location.assign('/app');\n * }\n * });\n *\n * Why this lives in a separate entry point: it's browser-only (uses\n * window.open / addEventListener) and integrators that only need the\n * server-side verifier shouldn't pull popup orchestration into their\n * server bundle.\n */\n\nconst DEFAULT_POPUP_ORIGIN = 'https://me.ochk.io';\nconst DEFAULT_POPUP_PATH = '/popup/signin';\nconst DEFAULT_FEATURES = 'width=480,height=720,resizable=yes,scrollbars=yes';\n\nexport interface OcPopupAccount {\n id?: string;\n /** Opaque public identity · `did:oc:<32-hex>`. Stable across linking\n * events. The canonical identifier post auth-refactor (Dec 2025\n * +). */\n did_oc?: string;\n /** Primary linked Bitcoin address, if the user has one and is\n * surfacing it (same-origin family integrators get it inline;\n * cross-domain integrators need the bitcoin_address scope). */\n primary_btc?: string | null;\n /** Whether the user has a primary email linked (plaintext stays\n * on auth host; only the boolean reaches integrators). */\n has_email?: boolean;\n /** Legacy fields kept for back-compat with pre-refactor consumers.\n * Prefer did_oc + primary_btc. Removed in a future major. */\n address?: string;\n btc_address?: string;\n display_name?: string | null;\n nostr_npub?: string | null;\n wallet_provisioned?: boolean;\n email?: string;\n}\n\nexport interface OcPopupResult {\n /** Account payload from the auth host. `did_oc` is the canonical\n * opaque identifier post auth-refactor (Dec 2025). Underlying\n * email + BTC stay private; integrators get a per-project\n * anonymous identifier unless they explicitly request a scope. */\n account: OcPopupAccount;\n /** The session JWT. Cross-domain integrators store this and send\n * it as `Authorization: Bearer <token>` on subsequent calls.\n * Family integrators (*.ochk.io) can ignore it — the cookie set\n * Domain=.ochk.io rides home automatically. */\n token: string;\n}\n\nexport interface SignInWithOcOptions {\n /** Origin of the OC popup page. Defaults to https://me.ochk.io.\n * Override only for staging / preview environments. */\n popupOrigin?: string;\n /** Path on the popup origin. Defaults to /popup/signin. */\n popupPath?: string;\n /** window.open features string. Defaults to a 480x720 resizable\n * popup with scrollbars. */\n features?: string;\n /** AbortSignal that cancels the wait and closes the popup. */\n signal?: AbortSignal;\n}\n\n/**\n * Open the OC signin popup and resolve with the session result. Returns\n * `null` if the user closed the popup without completing signin, or if\n * the AbortSignal fired.\n *\n * MUST be called inside a user-gesture handler (e.g. a button onClick).\n * Browsers block `window.open` outside of user gestures.\n */\nexport function signInWithOc(options: SignInWithOcOptions = {}): Promise<OcPopupResult | null> {\n const popupOrigin = options.popupOrigin ?? DEFAULT_POPUP_ORIGIN;\n const popupPath = options.popupPath ?? DEFAULT_POPUP_PATH;\n const features = options.features ?? DEFAULT_FEATURES;\n\n return new Promise((resolve) => {\n if (typeof window === 'undefined') {\n resolve(null);\n return;\n }\n\n const url = new URL(popupPath, popupOrigin);\n url.searchParams.set('opener_origin', window.location.origin);\n const popup = window.open(url.toString(), 'oc-signin', features);\n if (!popup) {\n // Popup blocked. Caller can detect a null result and fall\n // back to a full-page redirect if desired.\n resolve(null);\n return;\n }\n popup.focus();\n\n let settled = false;\n const cleanup = () => {\n window.removeEventListener('message', onMessage);\n clearInterval(closedTimer);\n if (options.signal) options.signal.removeEventListener('abort', onAbort);\n };\n\n function settle(value: OcPopupResult | null) {\n if (settled) return;\n settled = true;\n cleanup();\n try {\n if (popup && !popup.closed) popup.close();\n } catch {\n /* popup may have closed itself first */\n }\n resolve(value);\n }\n\n function onMessage(event: MessageEvent) {\n // Origin pinning is necessary but not sufficient — same-origin\n // pages other than our popup can post the same shape. Pin both\n // origin AND source window so only the popup we opened can\n // settle this promise.\n if (event.origin !== popupOrigin) return;\n if (event.source !== popup) return;\n const data = event.data as\n | { type?: string; account?: OcPopupAccount; token?: string }\n | null;\n if (!data || data.type !== 'oc-signin-success') return;\n if (!data.account || !data.token) {\n // Malformed payload — treat as not-signed-in.\n settle(null);\n return;\n }\n settle({ account: data.account, token: data.token });\n }\n\n function onAbort() {\n settle(null);\n }\n\n window.addEventListener('message', onMessage);\n if (options.signal) {\n if (options.signal.aborted) {\n settle(null);\n return;\n }\n options.signal.addEventListener('abort', onAbort);\n }\n\n // Detect the user closing the popup without completing signin.\n const closedTimer = setInterval(() => {\n if (popup && popup.closed) settle(null);\n }, 500);\n });\n}\n"]}
1
+ {"version":3,"sources":["../src/popup.ts"],"names":[],"mappings":"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","file":"popup.js","sourcesContent":["/**\n * @orangecheck/me-client/popup\n *\n * Browser-side helper that opens the OC sign-in popup, listens for the\n * postMessage from me.ochk.io, and resolves with the verified session.\n *\n * import { signInWithOc } from '@orangecheck/me-client/popup';\n *\n * document.querySelector('#oc-signin')!.addEventListener('click', async () => {\n * const result = await signInWithOc();\n * if (result) {\n * localStorage.setItem('oc-session-token', result.token);\n * location.assign('/app');\n * }\n * });\n *\n * Why this lives in a separate entry point: it's browser-only (uses\n * window.open / addEventListener) and integrators that only need the\n * server-side verifier shouldn't pull popup orchestration into their\n * server bundle.\n */\n\nconst DEFAULT_POPUP_ORIGIN = 'https://me.ochk.io';\nconst DEFAULT_POPUP_PATH = '/popup/signin';\nconst DEFAULT_FEATURES = 'width=480,height=720,resizable=yes,scrollbars=yes';\n\nexport interface OcPopupAccount {\n id?: string;\n /** Opaque public identity · `did:oc:<32-hex>`. Stable across linking\n * events. The canonical identifier post auth-refactor (Dec 2025\n * +). */\n did_oc?: string;\n /** Primary linked Bitcoin address, if the user has one and is\n * surfacing it (same-origin family integrators get it inline;\n * cross-domain integrators need the bitcoin_address scope). */\n primary_btc?: string | null;\n /** Whether the user has a primary email linked (plaintext stays\n * on auth host; only the boolean reaches integrators). */\n has_email?: boolean;\n /** Legacy fields kept for back-compat with pre-refactor consumers.\n * Prefer did_oc + primary_btc. Removed in a future major. */\n address?: string;\n btc_address?: string;\n display_name?: string | null;\n nostr_npub?: string | null;\n wallet_provisioned?: boolean;\n email?: string;\n}\n\nexport interface OcPopupResult {\n /** Account payload from the auth host, unsigned: trust only the\n * verified token. `did_oc` is the account's opaque identifier, the\n * same at every site; the email and Bitcoin address stay private\n * unless the user grants a scope. */\n account: OcPopupAccount;\n /** The session JWT. Cross-domain integrators store this and send\n * it as `Authorization: Bearer <token>` on subsequent calls.\n * Family integrators (*.ochk.io) can ignore it — the cookie set\n * Domain=.ochk.io rides home automatically. */\n token: string;\n}\n\nexport interface SignInWithOcOptions {\n /** Origin of the OC popup page. Defaults to https://me.ochk.io.\n * Override only for staging / preview environments. */\n popupOrigin?: string;\n /** Path on the popup origin. Defaults to /popup/signin. */\n popupPath?: string;\n /** window.open features string. Defaults to a 480x720 resizable\n * popup with scrollbars. */\n features?: string;\n /** AbortSignal that cancels the wait and closes the popup. */\n signal?: AbortSignal;\n}\n\n/**\n * Open the OC signin popup and resolve with the session result. Returns\n * `null` if the user closed the popup without completing signin, or if\n * the AbortSignal fired.\n *\n * MUST be called inside a user-gesture handler (e.g. a button onClick).\n * Browsers block `window.open` outside of user gestures.\n */\nexport function signInWithOc(options: SignInWithOcOptions = {}): Promise<OcPopupResult | null> {\n const popupOrigin = options.popupOrigin ?? DEFAULT_POPUP_ORIGIN;\n const popupPath = options.popupPath ?? DEFAULT_POPUP_PATH;\n const features = options.features ?? DEFAULT_FEATURES;\n\n return new Promise((resolve) => {\n if (typeof window === 'undefined') {\n resolve(null);\n return;\n }\n\n const url = new URL(popupPath, popupOrigin);\n url.searchParams.set('opener_origin', window.location.origin);\n const popup = window.open(url.toString(), 'oc-signin', features);\n if (!popup) {\n // Popup blocked. Caller can detect a null result and fall\n // back to a full-page redirect if desired.\n resolve(null);\n return;\n }\n popup.focus();\n\n let settled = false;\n const cleanup = () => {\n window.removeEventListener('message', onMessage);\n clearInterval(closedTimer);\n if (options.signal) options.signal.removeEventListener('abort', onAbort);\n };\n\n function settle(value: OcPopupResult | null) {\n if (settled) return;\n settled = true;\n cleanup();\n try {\n if (popup && !popup.closed) popup.close();\n } catch {\n /* popup may have closed itself first */\n }\n resolve(value);\n }\n\n function onMessage(event: MessageEvent) {\n // Origin pinning is necessary but not sufficient — same-origin\n // pages other than our popup can post the same shape. Pin both\n // origin AND source window so only the popup we opened can\n // settle this promise.\n if (event.origin !== popupOrigin) return;\n if (event.source !== popup) return;\n const data = event.data as\n | { type?: string; account?: OcPopupAccount; token?: string }\n | null;\n if (!data || data.type !== 'oc-signin-success') return;\n if (!data.account || !data.token) {\n // Malformed payload — treat as not-signed-in.\n settle(null);\n return;\n }\n settle({ account: data.account, token: data.token });\n }\n\n function onAbort() {\n settle(null);\n }\n\n window.addEventListener('message', onMessage);\n if (options.signal) {\n if (options.signal.aborted) {\n settle(null);\n return;\n }\n options.signal.addEventListener('abort', onAbort);\n }\n\n // Detect the user closing the popup without completing signin.\n const closedTimer = setInterval(() => {\n if (popup && popup.closed) settle(null);\n }, 500);\n });\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/popup.ts"],"names":[],"mappings":"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","file":"popup.mjs","sourcesContent":["/**\n * @orangecheck/me-client/popup\n *\n * Browser-side helper that opens the OC sign-in popup, listens for the\n * postMessage from me.ochk.io, and resolves with the verified session.\n *\n * import { signInWithOc } from '@orangecheck/me-client/popup';\n *\n * document.querySelector('#oc-signin')!.addEventListener('click', async () => {\n * const result = await signInWithOc();\n * if (result) {\n * localStorage.setItem('oc-session-token', result.token);\n * location.assign('/app');\n * }\n * });\n *\n * Why this lives in a separate entry point: it's browser-only (uses\n * window.open / addEventListener) and integrators that only need the\n * server-side verifier shouldn't pull popup orchestration into their\n * server bundle.\n */\n\nconst DEFAULT_POPUP_ORIGIN = 'https://me.ochk.io';\nconst DEFAULT_POPUP_PATH = '/popup/signin';\nconst DEFAULT_FEATURES = 'width=480,height=720,resizable=yes,scrollbars=yes';\n\nexport interface OcPopupAccount {\n id?: string;\n /** Opaque public identity · `did:oc:<32-hex>`. Stable across linking\n * events. The canonical identifier post auth-refactor (Dec 2025\n * +). */\n did_oc?: string;\n /** Primary linked Bitcoin address, if the user has one and is\n * surfacing it (same-origin family integrators get it inline;\n * cross-domain integrators need the bitcoin_address scope). */\n primary_btc?: string | null;\n /** Whether the user has a primary email linked (plaintext stays\n * on auth host; only the boolean reaches integrators). */\n has_email?: boolean;\n /** Legacy fields kept for back-compat with pre-refactor consumers.\n * Prefer did_oc + primary_btc. Removed in a future major. */\n address?: string;\n btc_address?: string;\n display_name?: string | null;\n nostr_npub?: string | null;\n wallet_provisioned?: boolean;\n email?: string;\n}\n\nexport interface OcPopupResult {\n /** Account payload from the auth host. `did_oc` is the canonical\n * opaque identifier post auth-refactor (Dec 2025). Underlying\n * email + BTC stay private; integrators get a per-project\n * anonymous identifier unless they explicitly request a scope. */\n account: OcPopupAccount;\n /** The session JWT. Cross-domain integrators store this and send\n * it as `Authorization: Bearer <token>` on subsequent calls.\n * Family integrators (*.ochk.io) can ignore it — the cookie set\n * Domain=.ochk.io rides home automatically. */\n token: string;\n}\n\nexport interface SignInWithOcOptions {\n /** Origin of the OC popup page. Defaults to https://me.ochk.io.\n * Override only for staging / preview environments. */\n popupOrigin?: string;\n /** Path on the popup origin. Defaults to /popup/signin. */\n popupPath?: string;\n /** window.open features string. Defaults to a 480x720 resizable\n * popup with scrollbars. */\n features?: string;\n /** AbortSignal that cancels the wait and closes the popup. */\n signal?: AbortSignal;\n}\n\n/**\n * Open the OC signin popup and resolve with the session result. Returns\n * `null` if the user closed the popup without completing signin, or if\n * the AbortSignal fired.\n *\n * MUST be called inside a user-gesture handler (e.g. a button onClick).\n * Browsers block `window.open` outside of user gestures.\n */\nexport function signInWithOc(options: SignInWithOcOptions = {}): Promise<OcPopupResult | null> {\n const popupOrigin = options.popupOrigin ?? DEFAULT_POPUP_ORIGIN;\n const popupPath = options.popupPath ?? DEFAULT_POPUP_PATH;\n const features = options.features ?? DEFAULT_FEATURES;\n\n return new Promise((resolve) => {\n if (typeof window === 'undefined') {\n resolve(null);\n return;\n }\n\n const url = new URL(popupPath, popupOrigin);\n url.searchParams.set('opener_origin', window.location.origin);\n const popup = window.open(url.toString(), 'oc-signin', features);\n if (!popup) {\n // Popup blocked. Caller can detect a null result and fall\n // back to a full-page redirect if desired.\n resolve(null);\n return;\n }\n popup.focus();\n\n let settled = false;\n const cleanup = () => {\n window.removeEventListener('message', onMessage);\n clearInterval(closedTimer);\n if (options.signal) options.signal.removeEventListener('abort', onAbort);\n };\n\n function settle(value: OcPopupResult | null) {\n if (settled) return;\n settled = true;\n cleanup();\n try {\n if (popup && !popup.closed) popup.close();\n } catch {\n /* popup may have closed itself first */\n }\n resolve(value);\n }\n\n function onMessage(event: MessageEvent) {\n // Origin pinning is necessary but not sufficient — same-origin\n // pages other than our popup can post the same shape. Pin both\n // origin AND source window so only the popup we opened can\n // settle this promise.\n if (event.origin !== popupOrigin) return;\n if (event.source !== popup) return;\n const data = event.data as\n | { type?: string; account?: OcPopupAccount; token?: string }\n | null;\n if (!data || data.type !== 'oc-signin-success') return;\n if (!data.account || !data.token) {\n // Malformed payload — treat as not-signed-in.\n settle(null);\n return;\n }\n settle({ account: data.account, token: data.token });\n }\n\n function onAbort() {\n settle(null);\n }\n\n window.addEventListener('message', onMessage);\n if (options.signal) {\n if (options.signal.aborted) {\n settle(null);\n return;\n }\n options.signal.addEventListener('abort', onAbort);\n }\n\n // Detect the user closing the popup without completing signin.\n const closedTimer = setInterval(() => {\n if (popup && popup.closed) settle(null);\n }, 500);\n });\n}\n"]}
1
+ {"version":3,"sources":["../src/popup.ts"],"names":[],"mappings":"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","file":"popup.mjs","sourcesContent":["/**\n * @orangecheck/me-client/popup\n *\n * Browser-side helper that opens the OC sign-in popup, listens for the\n * postMessage from me.ochk.io, and resolves with the verified session.\n *\n * import { signInWithOc } from '@orangecheck/me-client/popup';\n *\n * document.querySelector('#oc-signin')!.addEventListener('click', async () => {\n * const result = await signInWithOc();\n * if (result) {\n * localStorage.setItem('oc-session-token', result.token);\n * location.assign('/app');\n * }\n * });\n *\n * Why this lives in a separate entry point: it's browser-only (uses\n * window.open / addEventListener) and integrators that only need the\n * server-side verifier shouldn't pull popup orchestration into their\n * server bundle.\n */\n\nconst DEFAULT_POPUP_ORIGIN = 'https://me.ochk.io';\nconst DEFAULT_POPUP_PATH = '/popup/signin';\nconst DEFAULT_FEATURES = 'width=480,height=720,resizable=yes,scrollbars=yes';\n\nexport interface OcPopupAccount {\n id?: string;\n /** Opaque public identity · `did:oc:<32-hex>`. Stable across linking\n * events. The canonical identifier post auth-refactor (Dec 2025\n * +). */\n did_oc?: string;\n /** Primary linked Bitcoin address, if the user has one and is\n * surfacing it (same-origin family integrators get it inline;\n * cross-domain integrators need the bitcoin_address scope). */\n primary_btc?: string | null;\n /** Whether the user has a primary email linked (plaintext stays\n * on auth host; only the boolean reaches integrators). */\n has_email?: boolean;\n /** Legacy fields kept for back-compat with pre-refactor consumers.\n * Prefer did_oc + primary_btc. Removed in a future major. */\n address?: string;\n btc_address?: string;\n display_name?: string | null;\n nostr_npub?: string | null;\n wallet_provisioned?: boolean;\n email?: string;\n}\n\nexport interface OcPopupResult {\n /** Account payload from the auth host, unsigned: trust only the\n * verified token. `did_oc` is the account's opaque identifier, the\n * same at every site; the email and Bitcoin address stay private\n * unless the user grants a scope. */\n account: OcPopupAccount;\n /** The session JWT. Cross-domain integrators store this and send\n * it as `Authorization: Bearer <token>` on subsequent calls.\n * Family integrators (*.ochk.io) can ignore it — the cookie set\n * Domain=.ochk.io rides home automatically. */\n token: string;\n}\n\nexport interface SignInWithOcOptions {\n /** Origin of the OC popup page. Defaults to https://me.ochk.io.\n * Override only for staging / preview environments. */\n popupOrigin?: string;\n /** Path on the popup origin. Defaults to /popup/signin. */\n popupPath?: string;\n /** window.open features string. Defaults to a 480x720 resizable\n * popup with scrollbars. */\n features?: string;\n /** AbortSignal that cancels the wait and closes the popup. */\n signal?: AbortSignal;\n}\n\n/**\n * Open the OC signin popup and resolve with the session result. Returns\n * `null` if the user closed the popup without completing signin, or if\n * the AbortSignal fired.\n *\n * MUST be called inside a user-gesture handler (e.g. a button onClick).\n * Browsers block `window.open` outside of user gestures.\n */\nexport function signInWithOc(options: SignInWithOcOptions = {}): Promise<OcPopupResult | null> {\n const popupOrigin = options.popupOrigin ?? DEFAULT_POPUP_ORIGIN;\n const popupPath = options.popupPath ?? DEFAULT_POPUP_PATH;\n const features = options.features ?? DEFAULT_FEATURES;\n\n return new Promise((resolve) => {\n if (typeof window === 'undefined') {\n resolve(null);\n return;\n }\n\n const url = new URL(popupPath, popupOrigin);\n url.searchParams.set('opener_origin', window.location.origin);\n const popup = window.open(url.toString(), 'oc-signin', features);\n if (!popup) {\n // Popup blocked. Caller can detect a null result and fall\n // back to a full-page redirect if desired.\n resolve(null);\n return;\n }\n popup.focus();\n\n let settled = false;\n const cleanup = () => {\n window.removeEventListener('message', onMessage);\n clearInterval(closedTimer);\n if (options.signal) options.signal.removeEventListener('abort', onAbort);\n };\n\n function settle(value: OcPopupResult | null) {\n if (settled) return;\n settled = true;\n cleanup();\n try {\n if (popup && !popup.closed) popup.close();\n } catch {\n /* popup may have closed itself first */\n }\n resolve(value);\n }\n\n function onMessage(event: MessageEvent) {\n // Origin pinning is necessary but not sufficient — same-origin\n // pages other than our popup can post the same shape. Pin both\n // origin AND source window so only the popup we opened can\n // settle this promise.\n if (event.origin !== popupOrigin) return;\n if (event.source !== popup) return;\n const data = event.data as\n | { type?: string; account?: OcPopupAccount; token?: string }\n | null;\n if (!data || data.type !== 'oc-signin-success') return;\n if (!data.account || !data.token) {\n // Malformed payload — treat as not-signed-in.\n settle(null);\n return;\n }\n settle({ account: data.account, token: data.token });\n }\n\n function onAbort() {\n settle(null);\n }\n\n window.addEventListener('message', onMessage);\n if (options.signal) {\n if (options.signal.aborted) {\n settle(null);\n return;\n }\n options.signal.addEventListener('abort', onAbort);\n }\n\n // Detect the user closing the popup without completing signin.\n const closedTimer = setInterval(() => {\n if (popup && popup.closed) settle(null);\n }, 500);\n });\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orangecheck/me-client",
3
- "version": "0.27.3",
3
+ "version": "0.27.4",
4
4
  "description": "Drop-in client for me.ochk.io. Three entry points: React surface (OcSignInButton, useOcSession), server-side verification (withOcAuth for Next.js, ocAuthExpress, ocAuthHono — zero env vars, zero JWK handling), and a browser-only popup orchestrator (signInWithOc). Plus session lifecycle hooks, payment authorization, and the canonical billable-event taxonomy as types.",
5
5
  "keywords": [
6
6
  "orangecheck",