buckyos 0.7.138 → 0.7.142
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/cli/core/app.ts +4 -0
- package/cli/core/auth.ts +2 -3
- package/cli/dist/cli.mjs +547 -127
- package/cli/dist/cli.mjs.map +1 -1
- package/cli/modules/aiws.ts +294 -0
- package/cli/modules/executor.ts +98 -0
- package/cli/version.ts +1 -1
- package/dist/account.d.ts +0 -2
- package/dist/account.d.ts.map +1 -1
- package/dist/aiworkspace_client.d.ts +91 -0
- package/dist/aiworkspace_client.d.ts.map +1 -0
- package/dist/app-frame.cjs +1 -1
- package/dist/app-frame.cjs.map +1 -1
- package/dist/app-frame.d.ts +103 -3
- package/dist/app-frame.d.ts.map +1 -1
- package/dist/app-frame.mjs +189 -8
- package/dist/app-frame.mjs.map +1 -1
- package/dist/browser.cjs +1 -1
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.ts +2 -0
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.mjs +18 -15
- package/dist/browser.mjs.map +1 -1
- package/dist/content.cjs +1 -1
- package/dist/content.cjs.map +1 -1
- package/dist/content.d.ts +18 -0
- package/dist/content.d.ts.map +1 -1
- package/dist/content.mjs +61 -1
- package/dist/content.mjs.map +1 -1
- package/dist/executor_client-b3ff97ba.js +13 -0
- package/dist/executor_client-b3ff97ba.js.map +1 -0
- package/dist/{ndm_proxy-6b03b9ec.mjs → executor_client-eb372968.mjs} +901 -396
- package/dist/executor_client-eb372968.mjs.map +1 -0
- package/dist/executor_client.d.ts +138 -0
- package/dist/executor_client.d.ts.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +23 -15
- package/dist/index.mjs.map +1 -1
- package/dist/internal/hash_worker.d.ts +2 -1
- package/dist/internal/hash_worker.d.ts.map +1 -1
- package/dist/internal/tus_client.d.ts +3 -0
- package/dist/internal/tus_client.d.ts.map +1 -1
- package/dist/namelib.d.ts +1 -10
- package/dist/namelib.d.ts.map +1 -1
- package/dist/ndm_client.d.ts +56 -7
- package/dist/ndm_client.d.ts.map +1 -1
- package/dist/ndn_types-08dc9ef1.js +2 -0
- package/dist/ndn_types-08dc9ef1.js.map +1 -0
- package/dist/{ndn_types-ac9c1e48.mjs → ndn_types-bbb1f6a6.mjs} +53 -100
- package/dist/ndn_types-bbb1f6a6.mjs.map +1 -0
- package/dist/nfsp.cjs +1 -1
- package/dist/nfsp.cjs.map +1 -1
- package/dist/nfsp.d.ts +16 -0
- package/dist/nfsp.d.ts.map +1 -1
- package/dist/nfsp.mjs +6 -0
- package/dist/nfsp.mjs.map +1 -1
- package/dist/node.cjs +1 -1
- package/dist/node.cjs.map +1 -1
- package/dist/node.d.ts +2 -0
- package/dist/node.d.ts.map +1 -1
- package/dist/node.mjs +18 -15
- package/dist/node.mjs.map +1 -1
- package/dist/provision.cjs +2 -2
- package/dist/provision.cjs.map +1 -1
- package/dist/provision.mjs +18 -12
- package/dist/provision.mjs.map +1 -1
- package/dist/provision_activate.d.ts.map +1 -1
- package/dist/runtime.d.ts +3 -4
- package/dist/runtime.d.ts.map +1 -1
- package/dist/sdk_core.d.ts +4 -0
- package/dist/sdk_core.d.ts.map +1 -1
- package/dist/{tus_client-2b915a81.js → tus_client-65c5fc5e.js} +4 -4
- package/dist/tus_client-65c5fc5e.js.map +1 -0
- package/dist/{tus_client-19baa342.mjs → tus_client-d313689e.mjs} +40 -2
- package/dist/tus_client-d313689e.mjs.map +1 -0
- package/dist/types.d.ts +0 -9
- package/dist/types.d.ts.map +1 -1
- package/dist/verify-hub-client.d.ts +1 -9
- package/dist/verify-hub-client.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/ndm_proxy-67651066.js +0 -13
- package/dist/ndm_proxy-67651066.js.map +0 -1
- package/dist/ndm_proxy-6b03b9ec.mjs.map +0 -1
- package/dist/ndn_types-324121ae.js +0 -2
- package/dist/ndn_types-324121ae.js.map +0 -1
- package/dist/ndn_types-ac9c1e48.mjs.map +0 -1
- package/dist/tus_client-19baa342.mjs.map +0 -1
- package/dist/tus_client-2b915a81.js.map +0 -1
package/dist/app-frame.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-frame.cjs","sources":["../src/app-frame.ts"],"sourcesContent":["import { isOpenRequest, type OpenRequest } from './content'\nexport interface AppFrameMessage<T extends string = string, P = unknown> {\n protocol: 'buckyos.app-frame'; version: 1; type: T; id?: string; replyTo?: string; payload: P\n}\nexport interface FrameInit {\n nonce: string\n windowId: string\n formFactor: 'desktop' | 'mobile'\n theme: { mode: 'light' | 'dark'; accent?: string }\n locale: string\n launch?: OpenRequest\n shellCapabilities: string[]\n}\nexport type CloseDecision = 'allow' | 'deny' | 'pending'\nconst envelope = (type: string, payload: unknown, extra: { id?: string; replyTo?: string } = {}): AppFrameMessage =>\n ({ protocol: 'buckyos.app-frame', version: 1, type, payload, ...extra })\nconst isMessage = (value: unknown): value is AppFrameMessage => {\n if (!value || typeof value !== 'object') return false\n const v = value as AppFrameMessage\n return v.protocol === 'buckyos.app-frame' && v.version === 1 && typeof v.type === 'string' && !!v.payload && typeof v.payload === 'object'\n}\nexport class AppFrameHost {\n ready = false\n capabilities: string[] = []\n private pending = new Map<string, { resolve: (v: unknown) => void; reject: (e: Error) => void; timer: ReturnType<typeof setTimeout>; type: string }>()\n private listener = (event: MessageEvent) => this.receive(event)\n private opens: number[] = []\n constructor(private options: {\n target: () => Window | null; origin: string; init: FrameInit\n onReady?: () => void\n onTitle?: (title: string, dirty: boolean) => void\n onRequestClose?: () => void\n onContentOpen?: (request: OpenRequest, target: 'default' | 'preview', newWindow: boolean) => void\n }) { window.addEventListener('message', this.listener) }\n private receive(event: MessageEvent): void {\n if (event.source !== this.options.target() || event.origin !== this.options.origin || !isMessage(event.data)) return\n const m = event.data\n const p = m.payload as Record<string, unknown>\n if (m.type === 'frame.hello') {\n if (p.nonce !== this.options.init.nonce || !Array.isArray(p.appCapabilities)) return\n this.ready = true\n this.capabilities = p.appCapabilities.filter((c): c is string => typeof c === 'string')\n this.send('frame.init', this.options.init)\n this.options.onReady?.()\n return\n }\n if (!this.ready) return\n if (m.replyTo) {\n const pending = this.pending.get(m.replyTo)\n if (pending && m.type === pending.type + 'Result') {\n clearTimeout(pending.timer); this.pending.delete(m.replyTo); pending.resolve(m.payload)\n }\n return\n }\n if (m.type === 'window.setTitle' && typeof p.title === 'string') this.options.onTitle?.(p.title.slice(0, 256), p.dirty === true)\n if (m.type === 'window.requestClose') this.options.onRequestClose?.()\n if (m.type === 'content.open' && (p.target === 'default' || p.target === 'preview')) {\n const request = { ...(p.request as object), requestId: crypto.randomUUID() }\n if (!isOpenRequest(request)) return\n this.opens = this.opens.filter(t => t > Date.now() - 10000)\n if (this.opens.length >= 5) return\n this.opens.push(Date.now())\n this.options.onContentOpen?.(request, p.target, p.newWindow === true)\n }\n }\n update(init: Partial<FrameInit>): void { this.options.init = { ...this.options.init, ...init } }\n send(type: string, payload: unknown): void {\n if (this.ready) this.options.target()?.postMessage(envelope(type, payload), this.options.origin)\n }\n request(type: string, payload: unknown, timeout = 3000): Promise<unknown> {\n if (!this.ready) return Promise.reject(new Error('App frame is not ready'))\n const id = crypto.randomUUID()\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => { this.pending.delete(id); reject(new Error('App frame timed out')) }, timeout)\n this.pending.set(id, { resolve, reject, timer, type })\n this.options.target()?.postMessage(envelope(type, payload, { id }), this.options.origin)\n })\n }\n async open(request: OpenRequest): Promise<{ accepted: boolean; fallback?: 'preview' }> {\n if (!this.capabilities.includes('open')) return { accepted: false }\n return await this.request('frame.open', { request }) as { accepted: boolean; fallback?: 'preview' }\n }\n async beforeClose(reason: 'user' | 'logout' | 'shell' = 'user'): Promise<CloseDecision> {\n if (!this.ready || !this.capabilities.includes('beforeClose')) return 'allow'\n const r = await this.request('frame.beforeClose', { reason }) as { decision?: CloseDecision }\n return r.decision === 'allow' || r.decision === 'pending' ? r.decision : 'deny'\n }\n async back(): Promise<boolean> {\n if (!this.capabilities.includes('back')) return false\n return (await this.request('frame.back', {}) as { handled?: boolean }).handled === true\n }\n dispose(): void {\n window.removeEventListener('message', this.listener)\n this.pending.forEach(p => { clearTimeout(p.timer); p.reject(new Error('App frame disposed')) })\n this.pending.clear(); this.ready = false\n }\n}\nexport class AppFrameClient {\n init?: FrameInit\n private helloTimer?: ReturnType<typeof setInterval>\n private helloDeadline?: ReturnType<typeof setTimeout>\n private readonly nonce: string | null\n private readonly origin: string\n private readonly listener = (event: MessageEvent) => { void this.receive(event) }\n constructor(private options: {\n shellOrigin: string\n onInit?: (init: FrameInit) => void\n onOpen?: (request: OpenRequest) => Promise<{ accepted: boolean; fallback?: 'preview' }> | { accepted: boolean; fallback?: 'preview' }\n onBeforeClose?: (reason: 'user' | 'logout' | 'shell') => Promise<CloseDecision> | CloseDecision\n onBack?: () => Promise<boolean> | boolean\n onTheme?: (theme: FrameInit['theme']) => void\n onLocale?: (locale: string) => void\n onFocus?: (focused: boolean) => void\n }) {\n this.origin = new URL(options.shellOrigin).origin\n this.nonce = new URLSearchParams(window.location.hash.slice(1)).get('bfp')\n window.addEventListener('message', this.listener)\n if (window.parent !== window && this.nonce) {\n const hello = () => window.parent.postMessage(envelope('frame.hello', { nonce: this.nonce, appCapabilities: [\n ...options.onOpen ? ['open'] : [], ...options.onBeforeClose ? ['beforeClose'] : [], ...options.onBack ? ['back'] : [],\n ] }), this.origin)\n hello()\n this.helloTimer = setInterval(hello, 250)\n this.helloDeadline = setTimeout(() => clearInterval(this.helloTimer), 1500)\n }\n }\n private async receive(event: MessageEvent): Promise<void> {\n if (event.source !== window.parent || event.origin !== this.origin || !isMessage(event.data)) return\n const m = event.data\n const p = m.payload as Record<string, unknown>\n if (m.type === 'frame.init') {\n if (!this.nonce || p.nonce !== this.nonce || typeof p.locale !== 'string' || !p.theme || typeof p.windowId !== 'string' || p.launch && !isOpenRequest(p.launch)) return\n clearInterval(this.helloTimer); clearTimeout(this.helloDeadline)\n this.init = p as unknown as FrameInit\n this.options.onInit?.(this.init)\n return\n }\n if (!this.init) return\n const reply = (payload: unknown) => window.parent.postMessage(envelope(m.type + 'Result', payload, { replyTo: m.id }), this.origin)\n try {\n if (m.type === 'frame.open' && isOpenRequest(p.request)) reply(await this.options.onOpen?.(p.request) ?? { accepted: false })\n if (m.type === 'frame.beforeClose') reply({ decision: await this.options.onBeforeClose?.(p.reason as 'user') ?? 'allow' })\n if (m.type === 'frame.back') reply({ handled: await this.options.onBack?.() ?? false })\n if (m.type === 'frame.themeChanged' && (p.mode === 'dark' || p.mode === 'light')) this.options.onTheme?.(p as FrameInit['theme'])\n if (m.type === 'frame.localeChanged' && typeof p.locale === 'string') this.options.onLocale?.(p.locale)\n if (m.type === 'frame.focusChanged') this.options.onFocus?.(p.focused === true)\n } catch {\n if (m.type === 'frame.open') reply({ accepted: false, fallback: 'preview' })\n if (m.type === 'frame.beforeClose') reply({ decision: 'deny' })\n }\n }\n send(type: string, payload: unknown): void {\n if (this.init) window.parent.postMessage(envelope(type, payload), this.origin)\n }\n setTitle(title: string, dirty = false): void { this.send('window.setTitle', { title, dirty }) }\n requestClose(): void { this.send('window.requestClose', {}) }\n openContent(request: Omit<OpenRequest, 'requestId'>, target: 'default' | 'preview' = 'default', newWindow = false): void {\n this.send('content.open', { request, target, newWindow })\n }\n dispose(): void { clearInterval(this.helloTimer); clearTimeout(this.helloDeadline); window.removeEventListener('message', this.listener) }\n}\n"],"names":["envelope","type","payload","extra","protocol","version","isMessage","value","v","constructor","options","this","listener","event","receive","origin","URL","shellOrigin","nonce","URLSearchParams","window","location","hash","slice","get","addEventListener","parent","hello","postMessage","appCapabilities","onOpen","onBeforeClose","onBack","helloTimer","setInterval","helloDeadline","setTimeout","clearInterval","source","data","m","p","locale","theme","windowId","launch","isOpenRequest","clearTimeout","init","_b","_a","onInit","call","reply","replyTo","id","request","_d","_c","accepted","decision","_f","_e","reason","handled","_h","_g","mode","_j","_i","onTheme","_l","_k","onLocale","_n","_m","onFocus","focused","fallback","send","setTitle","title","dirty","requestClose","openContent","target","newWindow","dispose","removeEventListener","ready","capabilities","pending","Map","opens","Array","isArray","filter","c","onReady","timer","delete","resolve","onTitle","onRequestClose","requestId","crypto","randomUUID","t","Date","now","length","push","onContentOpen","update","timeout","Promise","reject","Error","set","open","includes","beforeClose","r","back","forEach","clear"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"app-frame.cjs","sources":["../src/app-frame.ts"],"sourcesContent":["import { isOpenRequest, isTransferableRef, isTransferableSession, readContentHints, systemOpenUrl, type ContentHints, type ContentOpenTarget, type OpenRequest, type TransferableContentRef, type TransferableSessionContext } from './content'\nexport interface AppFrameMessage<T extends string = string, P = unknown> {\n protocol: 'buckyos.app-frame'; version: 1; type: T; id?: string; replyTo?: string; payload: P\n}\nexport interface FrameInit {\n nonce: string\n windowId: string\n formFactor: 'desktop' | 'mobile'\n theme: { mode: 'light' | 'dark'; accent?: string }\n locale: string\n launch?: OpenRequest\n shellCapabilities: string[]\n}\nexport type CloseDecision = 'allow' | 'deny' | 'pending'\nconst envelope = (type: string, payload: unknown, extra: { id?: string; replyTo?: string } = {}): AppFrameMessage =>\n ({ protocol: 'buckyos.app-frame', version: 1, type, payload, ...extra })\nconst isMessage = (value: unknown): value is AppFrameMessage => {\n if (!value || typeof value !== 'object') return false\n const v = value as AppFrameMessage\n return v.protocol === 'buckyos.app-frame' && v.version === 1 && typeof v.type === 'string' && !!v.payload && typeof v.payload === 'object'\n}\nexport class AppFrameHost {\n ready = false\n capabilities: string[] = []\n private pending = new Map<string, { resolve: (v: unknown) => void; reject: (e: Error) => void; timer: ReturnType<typeof setTimeout>; type: string }>()\n private listener = (event: MessageEvent) => this.receive(event)\n private opens: number[] = []\n constructor(private options: {\n target: () => Window | null; origin: string; init: FrameInit\n onReady?: () => void\n onTitle?: (title: string, dirty: boolean) => void\n onRequestClose?: () => void\n onContentOpen?: (request: OpenRequest, target: ContentOpenTarget, options: { newWindow: boolean; hints: ContentHints }) => void\n }) { window.addEventListener('message', this.listener) }\n private focused?: boolean\n private receive(event: MessageEvent): void {\n if (event.source !== this.options.target() || event.origin !== this.options.origin || !isMessage(event.data)) return\n const m = event.data\n const p = m.payload as Record<string, unknown>\n if (m.type === 'frame.hello') {\n if (p.nonce !== this.options.init.nonce || !Array.isArray(p.appCapabilities)) return\n this.ready = true\n this.capabilities = p.appCapabilities.filter((c): c is string => typeof c === 'string')\n this.send('frame.init', this.options.init)\n if (this.focused !== undefined) this.send('frame.focusChanged', { focused: this.focused })\n this.options.onReady?.()\n return\n }\n if (!this.ready) return\n if (m.replyTo) {\n const pending = this.pending.get(m.replyTo)\n if (pending && m.type === pending.type + 'Result') {\n clearTimeout(pending.timer); this.pending.delete(m.replyTo); pending.resolve(m.payload)\n }\n return\n }\n if (m.type === 'window.setTitle' && typeof p.title === 'string') this.options.onTitle?.(p.title.slice(0, 256), p.dirty === true)\n if (m.type === 'window.requestClose') this.options.onRequestClose?.()\n if (m.type === 'content.open' && (p.target === 'default' || p.target === 'preview' || p.target === 'chooser')) {\n const request = { ...(p.request as object), requestId: crypto.randomUUID() }\n if (!isOpenRequest(request)) return\n this.opens = this.opens.filter(t => t > Date.now() - 10000)\n if (this.opens.length >= 5) return\n this.opens.push(Date.now())\n this.options.onContentOpen?.(request, p.target, { newWindow: p.newWindow === true, hints: readContentHints(p.hints) })\n }\n }\n update(init: Partial<FrameInit>): void { this.options.init = { ...this.options.init, ...init } }\n /** Reports whether the App's window is the focused one; only a change is sent. */\n setFocused(focused: boolean): void {\n if (this.focused === focused) return\n this.focused = focused\n this.send('frame.focusChanged', { focused })\n }\n send(type: string, payload: unknown): void {\n if (this.ready) this.options.target()?.postMessage(envelope(type, payload), this.options.origin)\n }\n request(type: string, payload: unknown, timeout = 3000): Promise<unknown> {\n if (!this.ready) return Promise.reject(new Error('App frame is not ready'))\n const id = crypto.randomUUID()\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => { this.pending.delete(id); reject(new Error('App frame timed out')) }, timeout)\n this.pending.set(id, { resolve, reject, timer, type })\n this.options.target()?.postMessage(envelope(type, payload, { id }), this.options.origin)\n })\n }\n async open(request: OpenRequest): Promise<{ accepted: boolean; fallback?: 'preview' }> {\n if (!this.capabilities.includes('open')) return { accepted: false }\n return await this.request('frame.open', { request }) as { accepted: boolean; fallback?: 'preview' }\n }\n async beforeClose(reason: 'user' | 'logout' | 'shell' = 'user'): Promise<CloseDecision> {\n if (!this.ready || !this.capabilities.includes('beforeClose')) return 'allow'\n const r = await this.request('frame.beforeClose', { reason }) as { decision?: CloseDecision }\n return r.decision === 'allow' || r.decision === 'pending' ? r.decision : 'deny'\n }\n async back(): Promise<boolean> {\n if (!this.capabilities.includes('back')) return false\n return (await this.request('frame.back', {}) as { handled?: boolean }).handled === true\n }\n dispose(): void {\n window.removeEventListener('message', this.listener)\n this.pending.forEach(p => { clearTimeout(p.timer); p.reject(new Error('App frame disposed')) })\n this.pending.clear(); this.ready = false\n }\n}\n/**\n * Origin of the window embedding this page, when `accept` admits it. `location.ancestorOrigins` names the real\n * parent even after the frame navigated through other pages (a sign-in round trip); the referrer is the fallback.\n */\nexport function embedderOrigin(accept: (origin: string) => boolean): string | null {\n if (window.parent === window) return null\n const candidates = [window.location.ancestorOrigins?.[0], document.referrer]\n for (const candidate of candidates) {\n if (!candidate) continue\n try {\n const origin = new URL(candidate).origin\n if (accept(origin)) return origin\n } catch {}\n }\n return null\n}\nexport const originInZone = (origin: string, zoneHost: string): boolean => {\n try {\n const url = new URL(origin)\n return url.protocol === window.location.protocol && (url.hostname === zoneHost || url.hostname.endsWith(`.${zoneHost}`))\n } catch { return false }\n}\nexport class AppFrameClient {\n init?: FrameInit\n private title?: string\n private focused?: boolean\n private helloTimer?: ReturnType<typeof setInterval>\n private helloDeadline?: ReturnType<typeof setTimeout>\n private readonly nonce: string | null\n private readonly origin: string\n private readonly listener = (event: MessageEvent) => { void this.receive(event) }\n constructor(private options: {\n shellOrigin: string\n /** The Zone's system entry (its root origin): where content is opened when this page is not embedded in the shell. */\n systemOrigin?: string\n /** This App's id, so the system does not offer the content back to it. */\n appId?: string\n onInit?: (init: FrameInit) => void\n onOpen?: (request: OpenRequest) => Promise<{ accepted: boolean; fallback?: 'preview' }> | { accepted: boolean; fallback?: 'preview' }\n onBeforeClose?: (reason: 'user' | 'logout' | 'shell') => Promise<CloseDecision> | CloseDecision\n onBack?: () => Promise<boolean> | boolean\n onTheme?: (theme: FrameInit['theme']) => void\n onLocale?: (locale: string) => void\n onFocus?: (focused: boolean) => void\n }) {\n this.origin = new URL(options.shellOrigin).origin\n this.nonce = new URLSearchParams(window.location.hash.slice(1)).get('bfp')\n window.addEventListener('message', this.listener)\n if (window.parent !== window && this.nonce) {\n const hello = () => window.parent.postMessage(envelope('frame.hello', { nonce: this.nonce, appCapabilities: [\n ...options.onOpen ? ['open'] : [], ...options.onBeforeClose ? ['beforeClose'] : [], ...options.onBack ? ['back'] : [],\n ] }), this.origin)\n hello()\n this.helloTimer = setInterval(hello, 250)\n this.helloDeadline = setTimeout(() => clearInterval(this.helloTimer), 1500)\n }\n }\n private async receive(event: MessageEvent): Promise<void> {\n if (event.source !== window.parent || event.origin !== this.origin || !isMessage(event.data)) return\n const m = event.data\n const p = m.payload as Record<string, unknown>\n if (m.type === 'frame.init') {\n if (!this.nonce || p.nonce !== this.nonce || typeof p.locale !== 'string' || !p.theme || typeof p.windowId !== 'string' || p.launch && !isOpenRequest(p.launch)) return\n clearInterval(this.helloTimer); clearTimeout(this.helloDeadline)\n this.init = p as unknown as FrameInit\n this.title = undefined; this.focused = undefined\n this.options.onInit?.(this.init)\n return\n }\n if (!this.init) return\n const reply = (payload: unknown) => window.parent.postMessage(envelope(m.type + 'Result', payload, { replyTo: m.id }), this.origin)\n try {\n if (m.type === 'frame.open' && isOpenRequest(p.request)) reply(await this.options.onOpen?.(p.request) ?? { accepted: false })\n if (m.type === 'frame.beforeClose') reply({ decision: await this.options.onBeforeClose?.(p.reason as 'user') ?? 'allow' })\n if (m.type === 'frame.back') reply({ handled: await this.options.onBack?.() ?? false })\n if (m.type === 'frame.themeChanged' && (p.mode === 'dark' || p.mode === 'light')) this.options.onTheme?.(p as FrameInit['theme'])\n if (m.type === 'frame.localeChanged' && typeof p.locale === 'string') this.options.onLocale?.(p.locale)\n if (m.type === 'frame.focusChanged' && this.focused !== (p.focused === true)) { this.focused = p.focused === true; this.options.onFocus?.(this.focused) }\n } catch {\n if (m.type === 'frame.open') reply({ accepted: false, fallback: 'preview' })\n if (m.type === 'frame.beforeClose') reply({ decision: 'deny' })\n }\n }\n send(type: string, payload: unknown): void {\n if (this.init) window.parent.postMessage(envelope(type, payload), this.origin)\n }\n setTitle(title: string, dirty = false): void {\n const key = JSON.stringify([title, dirty])\n if (!this.init || key === this.title) return\n this.title = key\n this.send('window.setTitle', { title, dirty })\n }\n requestClose(): void { this.send('window.requestClose', {}) }\n /**\n * Asks the system to open content: with its default app, in Preview, or by letting the user choose (`chooser`).\n * Embedded in the shell the request goes over the frame; in a standalone tab it opens the Zone's system entry\n * (`systemOrigin`) in a new tab. Returns false when neither is available.\n */\n openContent(request: Omit<OpenRequest, 'requestId'>, target: ContentOpenTarget = 'default', options: { newWindow?: boolean; hints?: ContentHints } = {}): boolean {\n const hints = options.hints ?? {}\n if (this.init) { this.send('content.open', { request, target, newWindow: options.newWindow === true, hints }); return true }\n if (!this.options.systemOrigin) return false\n window.open(systemOpenUrl(this.options.systemOrigin, { request, target, hints, from: this.options.appId }), '_blank', 'noopener')\n return true\n }\n dispose(): void { clearInterval(this.helloTimer); clearTimeout(this.helloDeadline); window.removeEventListener('message', this.listener) }\n}\n\n/**\n * Preview embed protocol (`buckyos.preview-embed` v1): an App shows the system Preview component inside its own UI.\n * The App frames `<systemOrigin>/embed/preview` (component only, no shell) and hands it a content reference; the\n * system page reads the content with its own Zone-root session, so no token crosses origins. Open With goes back\n * through the App to the shell (`AppFrameClient.openContent(…, 'chooser')`).\n */\nexport type PreviewEmbedSource = TransferableContentRef | { kind: 'blob'; blob: Blob; name: string }\nexport interface PreviewEmbedInit {\n nonce: string\n source: PreviewEmbedSource\n session?: TransferableSessionContext\n theme: 'light' | 'dark'\n locale: string\n}\nexport interface PreviewEmbedState {\n status: 'loading' | 'ready' | 'error'\n /** Preview error kind (`unsupported`, `not-found`, `permission-denied`, `timeout`, `error`, …) and code. */\n error?: { kind: string; code: string }\n title?: string\n mediaType?: string\n}\nexport interface PreviewEmbedOpenWith { request: Omit<OpenRequest, 'requestId'>; hints: ContentHints }\nconst PREVIEW_EMBED = 'buckyos.preview-embed'\nconst embedEnvelope = (type: string, payload: unknown) => ({ protocol: PREVIEW_EMBED, version: 1, type, payload })\nconst isEmbedMessage = (value: unknown): value is { type: string; payload: Record<string, unknown> } => {\n const v = value as { protocol?: unknown; version?: unknown; type?: unknown; payload?: unknown } | null\n return !!v && v.protocol === PREVIEW_EMBED && v.version === 1 && typeof v.type === 'string' && !!v.payload && typeof v.payload === 'object'\n}\nconst isEmbedSource = (value: unknown): value is PreviewEmbedSource =>\n isTransferableRef(value) || (!!value && typeof value === 'object' && (value as { kind?: unknown }).kind === 'blob' &&\n typeof Blob !== 'undefined' && (value as { blob?: unknown }).blob instanceof Blob && typeof (value as { name?: unknown }).name === 'string')\nexport const PREVIEW_EMBED_PATH = '/embed/preview'\n\n/** App side: owns the iframe that shows the system Preview. */\nexport class PreviewEmbed {\n readonly url: string\n private readonly nonce = crypto.randomUUID()\n private readonly origin: string\n private readonly listener = (event: MessageEvent) => this.receive(event)\n private init: Omit<PreviewEmbedInit, 'nonce'>\n constructor(private options: {\n systemOrigin: string\n frame: () => HTMLIFrameElement | null\n init: Omit<PreviewEmbedInit, 'nonce'>\n onState?: (state: PreviewEmbedState) => void\n onOpenWith?: (open: PreviewEmbedOpenWith) => void\n onExit?: () => void\n }) {\n this.origin = new URL(options.systemOrigin).origin\n this.init = options.init\n this.url = `${this.origin}${PREVIEW_EMBED_PATH}#bpe=${this.nonce}&po=${encodeURIComponent(window.location.origin)}`\n window.addEventListener('message', this.listener)\n }\n private post(type: string, payload: unknown): void {\n this.options.frame()?.contentWindow?.postMessage(embedEnvelope(type, payload), this.origin)\n }\n private receive(event: MessageEvent): void {\n if (event.origin !== this.origin || event.source !== this.options.frame()?.contentWindow || !isEmbedMessage(event.data)) return\n const { type, payload: p } = event.data\n if (type === 'embed.hello') { if (p.nonce === this.nonce) this.post('embed.init', { ...this.init, nonce: this.nonce }); return }\n if (type === 'embed.state' && (p.status === 'loading' || p.status === 'ready' || p.status === 'error')) {\n const error = p.error as { kind?: unknown; code?: unknown } | undefined\n this.options.onState?.({ status: p.status,\n error: error && typeof error.kind === 'string' && typeof error.code === 'string' ? { kind: error.kind, code: error.code } : undefined,\n title: typeof p.title === 'string' ? p.title.slice(0, 256) : undefined, mediaType: typeof p.mediaType === 'string' ? p.mediaType.slice(0, 128) : undefined })\n }\n if (type === 'embed.openWith') {\n const request = p.request as Omit<OpenRequest, 'requestId'> | undefined\n if (request && isTransferableRef(request.source) && (request.session === undefined || isTransferableSession(request.session))) {\n this.options.onOpenWith?.({ request: { source: request.source, session: request.session }, hints: readContentHints(p.hints) })\n }\n }\n if (type === 'embed.exit') this.options.onExit?.()\n }\n update(patch: Partial<Pick<PreviewEmbedInit, 'theme' | 'locale'>>): void {\n this.init = { ...this.init, ...patch }\n this.post('embed.update', patch)\n }\n dispose(): void { window.removeEventListener('message', this.listener) }\n}\n\n/** System side: the component-only page at `PREVIEW_EMBED_PATH`. Accepts one embedding App whose origin `accept` admits. */\nexport class PreviewEmbedHost {\n readonly parentOrigin: string | null\n private readonly nonce: string | null\n private ready = false\n private readonly hello?: ReturnType<typeof setInterval>\n private readonly listener = (event: MessageEvent) => this.receive(event)\n constructor(private options: {\n accept: (origin: string) => boolean\n onInit: (init: PreviewEmbedInit) => void\n onUpdate?: (patch: Partial<Pick<PreviewEmbedInit, 'theme' | 'locale'>>) => void\n }) {\n const params = new URLSearchParams(window.location.hash.slice(1))\n this.nonce = params.get('bpe')\n let parentOrigin: string | null = null\n try { parentOrigin = new URL(params.get('po') ?? '').origin } catch {}\n this.parentOrigin = window.parent !== window && this.nonce && parentOrigin && options.accept(parentOrigin) ? parentOrigin : null\n if (!this.parentOrigin) return\n window.addEventListener('message', this.listener)\n const hello = () => window.parent.postMessage(embedEnvelope('embed.hello', { nonce: this.nonce }), this.parentOrigin!)\n hello()\n this.hello = setInterval(() => { if (!this.ready) hello() }, 250)\n }\n private receive(event: MessageEvent): void {\n if (event.source !== window.parent || event.origin !== this.parentOrigin || !isEmbedMessage(event.data)) return\n const { type, payload: p } = event.data\n if (type === 'embed.init') {\n if (p.nonce !== this.nonce || !isEmbedSource(p.source) || (p.session !== undefined && !isTransferableSession(p.session)) || typeof p.locale !== 'string') return\n this.ready = true; clearInterval(this.hello)\n this.options.onInit({ nonce: String(p.nonce), source: p.source, session: p.session as TransferableSessionContext | undefined, theme: p.theme === 'dark' ? 'dark' : 'light', locale: p.locale })\n return\n }\n if (type === 'embed.update' && this.ready) {\n const patch: Partial<Pick<PreviewEmbedInit, 'theme' | 'locale'>> = {}\n if (p.theme === 'dark' || p.theme === 'light') patch.theme = p.theme\n if (typeof p.locale === 'string') patch.locale = p.locale\n this.options.onUpdate?.(patch)\n }\n }\n private post(type: string, payload: unknown): void {\n if (this.ready && this.parentOrigin) window.parent.postMessage(embedEnvelope(type, payload), this.parentOrigin)\n }\n state(state: PreviewEmbedState): void { this.post('embed.state', state) }\n openWith(open: PreviewEmbedOpenWith): void { this.post('embed.openWith', open) }\n exit(): void { this.post('embed.exit', {}) }\n dispose(): void { clearInterval(this.hello); window.removeEventListener('message', this.listener) }\n}\n"],"names":["envelope","type","payload","extra","protocol","version","isMessage","value","v","PREVIEW_EMBED","embedEnvelope","isEmbedMessage","PREVIEW_EMBED_PATH","constructor","options","this","listener","event","receive","origin","URL","shellOrigin","nonce","URLSearchParams","window","location","hash","slice","get","addEventListener","parent","hello","postMessage","appCapabilities","onOpen","onBeforeClose","onBack","helloTimer","setInterval","helloDeadline","setTimeout","clearInterval","source","data","m","p","locale","theme","windowId","launch","isOpenRequest","clearTimeout","init","title","focused","_b","_a","onInit","call","reply","replyTo","id","request","_d","_c","accepted","decision","_f","_e","reason","handled","_h","_g","mode","_j","_i","onTheme","_l","_k","onLocale","_n","_m","onFocus","fallback","send","setTitle","dirty","key","JSON","stringify","requestClose","openContent","target","hints","newWindow","systemOrigin","open","systemOpenUrl","from","appId","dispose","removeEventListener","ready","capabilities","pending","Map","opens","Array","isArray","filter","c","onReady","timer","delete","resolve","onTitle","onRequestClose","requestId","crypto","randomUUID","t","Date","now","length","push","onContentOpen","readContentHints","update","setFocused","timeout","Promise","reject","Error","set","includes","beforeClose","r","back","forEach","clear","url","encodeURIComponent","post","frame","contentWindow","status","error","onState","kind","code","mediaType","isTransferableRef","session","isTransferableSession","onOpenWith","onExit","patch","params","parentOrigin","accept","Blob","blob","name","String","onUpdate","state","openWith","exit","candidates","ancestorOrigins","document","referrer","candidate","zoneHost","hostname","endsWith"],"mappings":"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"}
|
package/dist/app-frame.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type OpenRequest } from './content';
|
|
1
|
+
import { type ContentHints, type ContentOpenTarget, type OpenRequest, type TransferableContentRef, type TransferableSessionContext } from './content';
|
|
2
2
|
export interface AppFrameMessage<T extends string = string, P = unknown> {
|
|
3
3
|
protocol: 'buckyos.app-frame';
|
|
4
4
|
version: 1;
|
|
@@ -34,10 +34,16 @@ export declare class AppFrameHost {
|
|
|
34
34
|
onReady?: () => void;
|
|
35
35
|
onTitle?: (title: string, dirty: boolean) => void;
|
|
36
36
|
onRequestClose?: () => void;
|
|
37
|
-
onContentOpen?: (request: OpenRequest, target:
|
|
37
|
+
onContentOpen?: (request: OpenRequest, target: ContentOpenTarget, options: {
|
|
38
|
+
newWindow: boolean;
|
|
39
|
+
hints: ContentHints;
|
|
40
|
+
}) => void;
|
|
38
41
|
});
|
|
42
|
+
private focused?;
|
|
39
43
|
private receive;
|
|
40
44
|
update(init: Partial<FrameInit>): void;
|
|
45
|
+
/** Reports whether the App's window is the focused one; only a change is sent. */
|
|
46
|
+
setFocused(focused: boolean): void;
|
|
41
47
|
send(type: string, payload: unknown): void;
|
|
42
48
|
request(type: string, payload: unknown, timeout?: number): Promise<unknown>;
|
|
43
49
|
open(request: OpenRequest): Promise<{
|
|
@@ -48,9 +54,17 @@ export declare class AppFrameHost {
|
|
|
48
54
|
back(): Promise<boolean>;
|
|
49
55
|
dispose(): void;
|
|
50
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Origin of the window embedding this page, when `accept` admits it. `location.ancestorOrigins` names the real
|
|
59
|
+
* parent even after the frame navigated through other pages (a sign-in round trip); the referrer is the fallback.
|
|
60
|
+
*/
|
|
61
|
+
export declare function embedderOrigin(accept: (origin: string) => boolean): string | null;
|
|
62
|
+
export declare const originInZone: (origin: string, zoneHost: string) => boolean;
|
|
51
63
|
export declare class AppFrameClient {
|
|
52
64
|
private options;
|
|
53
65
|
init?: FrameInit;
|
|
66
|
+
private title?;
|
|
67
|
+
private focused?;
|
|
54
68
|
private helloTimer?;
|
|
55
69
|
private helloDeadline?;
|
|
56
70
|
private readonly nonce;
|
|
@@ -58,6 +72,10 @@ export declare class AppFrameClient {
|
|
|
58
72
|
private readonly listener;
|
|
59
73
|
constructor(options: {
|
|
60
74
|
shellOrigin: string;
|
|
75
|
+
/** The Zone's system entry (its root origin): where content is opened when this page is not embedded in the shell. */
|
|
76
|
+
systemOrigin?: string;
|
|
77
|
+
/** This App's id, so the system does not offer the content back to it. */
|
|
78
|
+
appId?: string;
|
|
61
79
|
onInit?: (init: FrameInit) => void;
|
|
62
80
|
onOpen?: (request: OpenRequest) => Promise<{
|
|
63
81
|
accepted: boolean;
|
|
@@ -76,7 +94,89 @@ export declare class AppFrameClient {
|
|
|
76
94
|
send(type: string, payload: unknown): void;
|
|
77
95
|
setTitle(title: string, dirty?: boolean): void;
|
|
78
96
|
requestClose(): void;
|
|
79
|
-
|
|
97
|
+
/**
|
|
98
|
+
* Asks the system to open content: with its default app, in Preview, or by letting the user choose (`chooser`).
|
|
99
|
+
* Embedded in the shell the request goes over the frame; in a standalone tab it opens the Zone's system entry
|
|
100
|
+
* (`systemOrigin`) in a new tab. Returns false when neither is available.
|
|
101
|
+
*/
|
|
102
|
+
openContent(request: Omit<OpenRequest, 'requestId'>, target?: ContentOpenTarget, options?: {
|
|
103
|
+
newWindow?: boolean;
|
|
104
|
+
hints?: ContentHints;
|
|
105
|
+
}): boolean;
|
|
106
|
+
dispose(): void;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Preview embed protocol (`buckyos.preview-embed` v1): an App shows the system Preview component inside its own UI.
|
|
110
|
+
* The App frames `<systemOrigin>/embed/preview` (component only, no shell) and hands it a content reference; the
|
|
111
|
+
* system page reads the content with its own Zone-root session, so no token crosses origins. Open With goes back
|
|
112
|
+
* through the App to the shell (`AppFrameClient.openContent(…, 'chooser')`).
|
|
113
|
+
*/
|
|
114
|
+
export type PreviewEmbedSource = TransferableContentRef | {
|
|
115
|
+
kind: 'blob';
|
|
116
|
+
blob: Blob;
|
|
117
|
+
name: string;
|
|
118
|
+
};
|
|
119
|
+
export interface PreviewEmbedInit {
|
|
120
|
+
nonce: string;
|
|
121
|
+
source: PreviewEmbedSource;
|
|
122
|
+
session?: TransferableSessionContext;
|
|
123
|
+
theme: 'light' | 'dark';
|
|
124
|
+
locale: string;
|
|
125
|
+
}
|
|
126
|
+
export interface PreviewEmbedState {
|
|
127
|
+
status: 'loading' | 'ready' | 'error';
|
|
128
|
+
/** Preview error kind (`unsupported`, `not-found`, `permission-denied`, `timeout`, `error`, …) and code. */
|
|
129
|
+
error?: {
|
|
130
|
+
kind: string;
|
|
131
|
+
code: string;
|
|
132
|
+
};
|
|
133
|
+
title?: string;
|
|
134
|
+
mediaType?: string;
|
|
135
|
+
}
|
|
136
|
+
export interface PreviewEmbedOpenWith {
|
|
137
|
+
request: Omit<OpenRequest, 'requestId'>;
|
|
138
|
+
hints: ContentHints;
|
|
139
|
+
}
|
|
140
|
+
export declare const PREVIEW_EMBED_PATH = "/embed/preview";
|
|
141
|
+
/** App side: owns the iframe that shows the system Preview. */
|
|
142
|
+
export declare class PreviewEmbed {
|
|
143
|
+
private options;
|
|
144
|
+
readonly url: string;
|
|
145
|
+
private readonly nonce;
|
|
146
|
+
private readonly origin;
|
|
147
|
+
private readonly listener;
|
|
148
|
+
private init;
|
|
149
|
+
constructor(options: {
|
|
150
|
+
systemOrigin: string;
|
|
151
|
+
frame: () => HTMLIFrameElement | null;
|
|
152
|
+
init: Omit<PreviewEmbedInit, 'nonce'>;
|
|
153
|
+
onState?: (state: PreviewEmbedState) => void;
|
|
154
|
+
onOpenWith?: (open: PreviewEmbedOpenWith) => void;
|
|
155
|
+
onExit?: () => void;
|
|
156
|
+
});
|
|
157
|
+
private post;
|
|
158
|
+
private receive;
|
|
159
|
+
update(patch: Partial<Pick<PreviewEmbedInit, 'theme' | 'locale'>>): void;
|
|
160
|
+
dispose(): void;
|
|
161
|
+
}
|
|
162
|
+
/** System side: the component-only page at `PREVIEW_EMBED_PATH`. Accepts one embedding App whose origin `accept` admits. */
|
|
163
|
+
export declare class PreviewEmbedHost {
|
|
164
|
+
private options;
|
|
165
|
+
readonly parentOrigin: string | null;
|
|
166
|
+
private readonly nonce;
|
|
167
|
+
private ready;
|
|
168
|
+
private readonly hello?;
|
|
169
|
+
private readonly listener;
|
|
170
|
+
constructor(options: {
|
|
171
|
+
accept: (origin: string) => boolean;
|
|
172
|
+
onInit: (init: PreviewEmbedInit) => void;
|
|
173
|
+
onUpdate?: (patch: Partial<Pick<PreviewEmbedInit, 'theme' | 'locale'>>) => void;
|
|
174
|
+
});
|
|
175
|
+
private receive;
|
|
176
|
+
private post;
|
|
177
|
+
state(state: PreviewEmbedState): void;
|
|
178
|
+
openWith(open: PreviewEmbedOpenWith): void;
|
|
179
|
+
exit(): void;
|
|
80
180
|
dispose(): void;
|
|
81
181
|
}
|
|
82
182
|
//# sourceMappingURL=app-frame.d.ts.map
|
package/dist/app-frame.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-frame.d.ts","sourceRoot":"","sources":["../src/app-frame.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"app-frame.d.ts","sourceRoot":"","sources":["../src/app-frame.ts"],"names":[],"mappings":"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"}
|
package/dist/app-frame.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isOpenRequest } from "./content.mjs";
|
|
1
|
+
import { isOpenRequest, readContentHints, systemOpenUrl, isTransferableRef, isTransferableSession } from "./content.mjs";
|
|
2
2
|
const envelope = (type, payload, extra = {}) => ({ protocol: "buckyos.app-frame", version: 1, type, payload, ...extra });
|
|
3
3
|
const isMessage = (value) => {
|
|
4
4
|
if (!value || typeof value !== "object")
|
|
@@ -28,6 +28,8 @@ class AppFrameHost {
|
|
|
28
28
|
this.ready = true;
|
|
29
29
|
this.capabilities = p.appCapabilities.filter((c) => typeof c === "string");
|
|
30
30
|
this.send("frame.init", this.options.init);
|
|
31
|
+
if (this.focused !== void 0)
|
|
32
|
+
this.send("frame.focusChanged", { focused: this.focused });
|
|
31
33
|
(_b = (_a = this.options).onReady) == null ? void 0 : _b.call(_a);
|
|
32
34
|
return;
|
|
33
35
|
}
|
|
@@ -46,7 +48,7 @@ class AppFrameHost {
|
|
|
46
48
|
(_d = (_c = this.options).onTitle) == null ? void 0 : _d.call(_c, p.title.slice(0, 256), p.dirty === true);
|
|
47
49
|
if (m.type === "window.requestClose")
|
|
48
50
|
(_f = (_e = this.options).onRequestClose) == null ? void 0 : _f.call(_e);
|
|
49
|
-
if (m.type === "content.open" && (p.target === "default" || p.target === "preview")) {
|
|
51
|
+
if (m.type === "content.open" && (p.target === "default" || p.target === "preview" || p.target === "chooser")) {
|
|
50
52
|
const request = { ...p.request, requestId: crypto.randomUUID() };
|
|
51
53
|
if (!isOpenRequest(request))
|
|
52
54
|
return;
|
|
@@ -54,12 +56,19 @@ class AppFrameHost {
|
|
|
54
56
|
if (this.opens.length >= 5)
|
|
55
57
|
return;
|
|
56
58
|
this.opens.push(Date.now());
|
|
57
|
-
(_h = (_g = this.options).onContentOpen) == null ? void 0 : _h.call(_g, request, p.target, p.newWindow === true);
|
|
59
|
+
(_h = (_g = this.options).onContentOpen) == null ? void 0 : _h.call(_g, request, p.target, { newWindow: p.newWindow === true, hints: readContentHints(p.hints) });
|
|
58
60
|
}
|
|
59
61
|
}
|
|
60
62
|
update(init) {
|
|
61
63
|
this.options.init = { ...this.options.init, ...init };
|
|
62
64
|
}
|
|
65
|
+
/** Reports whether the App's window is the focused one; only a change is sent. */
|
|
66
|
+
setFocused(focused) {
|
|
67
|
+
if (this.focused === focused)
|
|
68
|
+
return;
|
|
69
|
+
this.focused = focused;
|
|
70
|
+
this.send("frame.focusChanged", { focused });
|
|
71
|
+
}
|
|
63
72
|
send(type, payload) {
|
|
64
73
|
var _a;
|
|
65
74
|
if (this.ready)
|
|
@@ -105,6 +114,31 @@ class AppFrameHost {
|
|
|
105
114
|
this.ready = false;
|
|
106
115
|
}
|
|
107
116
|
}
|
|
117
|
+
function embedderOrigin(accept) {
|
|
118
|
+
var _a;
|
|
119
|
+
if (window.parent === window)
|
|
120
|
+
return null;
|
|
121
|
+
const candidates = [(_a = window.location.ancestorOrigins) == null ? void 0 : _a[0], document.referrer];
|
|
122
|
+
for (const candidate of candidates) {
|
|
123
|
+
if (!candidate)
|
|
124
|
+
continue;
|
|
125
|
+
try {
|
|
126
|
+
const origin = new URL(candidate).origin;
|
|
127
|
+
if (accept(origin))
|
|
128
|
+
return origin;
|
|
129
|
+
} catch {
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
const originInZone = (origin, zoneHost) => {
|
|
135
|
+
try {
|
|
136
|
+
const url = new URL(origin);
|
|
137
|
+
return url.protocol === window.location.protocol && (url.hostname === zoneHost || url.hostname.endsWith(`.${zoneHost}`));
|
|
138
|
+
} catch {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
};
|
|
108
142
|
class AppFrameClient {
|
|
109
143
|
constructor(options) {
|
|
110
144
|
this.options = options;
|
|
@@ -137,6 +171,8 @@ class AppFrameClient {
|
|
|
137
171
|
clearInterval(this.helloTimer);
|
|
138
172
|
clearTimeout(this.helloDeadline);
|
|
139
173
|
this.init = p;
|
|
174
|
+
this.title = void 0;
|
|
175
|
+
this.focused = void 0;
|
|
140
176
|
(_b = (_a = this.options).onInit) == null ? void 0 : _b.call(_a, this.init);
|
|
141
177
|
return;
|
|
142
178
|
}
|
|
@@ -154,8 +190,10 @@ class AppFrameClient {
|
|
|
154
190
|
(_j = (_i = this.options).onTheme) == null ? void 0 : _j.call(_i, p);
|
|
155
191
|
if (m.type === "frame.localeChanged" && typeof p.locale === "string")
|
|
156
192
|
(_l = (_k = this.options).onLocale) == null ? void 0 : _l.call(_k, p.locale);
|
|
157
|
-
if (m.type === "frame.focusChanged")
|
|
158
|
-
|
|
193
|
+
if (m.type === "frame.focusChanged" && this.focused !== (p.focused === true)) {
|
|
194
|
+
this.focused = p.focused === true;
|
|
195
|
+
(_n = (_m = this.options).onFocus) == null ? void 0 : _n.call(_m, this.focused);
|
|
196
|
+
}
|
|
159
197
|
} catch {
|
|
160
198
|
if (m.type === "frame.open")
|
|
161
199
|
reply({ accepted: false, fallback: "preview" });
|
|
@@ -168,13 +206,30 @@ class AppFrameClient {
|
|
|
168
206
|
window.parent.postMessage(envelope(type, payload), this.origin);
|
|
169
207
|
}
|
|
170
208
|
setTitle(title, dirty = false) {
|
|
209
|
+
const key = JSON.stringify([title, dirty]);
|
|
210
|
+
if (!this.init || key === this.title)
|
|
211
|
+
return;
|
|
212
|
+
this.title = key;
|
|
171
213
|
this.send("window.setTitle", { title, dirty });
|
|
172
214
|
}
|
|
173
215
|
requestClose() {
|
|
174
216
|
this.send("window.requestClose", {});
|
|
175
217
|
}
|
|
176
|
-
|
|
177
|
-
|
|
218
|
+
/**
|
|
219
|
+
* Asks the system to open content: with its default app, in Preview, or by letting the user choose (`chooser`).
|
|
220
|
+
* Embedded in the shell the request goes over the frame; in a standalone tab it opens the Zone's system entry
|
|
221
|
+
* (`systemOrigin`) in a new tab. Returns false when neither is available.
|
|
222
|
+
*/
|
|
223
|
+
openContent(request, target = "default", options = {}) {
|
|
224
|
+
const hints = options.hints ?? {};
|
|
225
|
+
if (this.init) {
|
|
226
|
+
this.send("content.open", { request, target, newWindow: options.newWindow === true, hints });
|
|
227
|
+
return true;
|
|
228
|
+
}
|
|
229
|
+
if (!this.options.systemOrigin)
|
|
230
|
+
return false;
|
|
231
|
+
window.open(systemOpenUrl(this.options.systemOrigin, { request, target, hints, from: this.options.appId }), "_blank", "noopener");
|
|
232
|
+
return true;
|
|
178
233
|
}
|
|
179
234
|
dispose() {
|
|
180
235
|
clearInterval(this.helloTimer);
|
|
@@ -182,8 +237,134 @@ class AppFrameClient {
|
|
|
182
237
|
window.removeEventListener("message", this.listener);
|
|
183
238
|
}
|
|
184
239
|
}
|
|
240
|
+
const PREVIEW_EMBED = "buckyos.preview-embed";
|
|
241
|
+
const embedEnvelope = (type, payload) => ({ protocol: PREVIEW_EMBED, version: 1, type, payload });
|
|
242
|
+
const isEmbedMessage = (value) => {
|
|
243
|
+
const v = value;
|
|
244
|
+
return !!v && v.protocol === PREVIEW_EMBED && v.version === 1 && typeof v.type === "string" && !!v.payload && typeof v.payload === "object";
|
|
245
|
+
};
|
|
246
|
+
const isEmbedSource = (value) => isTransferableRef(value) || !!value && typeof value === "object" && value.kind === "blob" && typeof Blob !== "undefined" && value.blob instanceof Blob && typeof value.name === "string";
|
|
247
|
+
const PREVIEW_EMBED_PATH = "/embed/preview";
|
|
248
|
+
class PreviewEmbed {
|
|
249
|
+
constructor(options) {
|
|
250
|
+
this.options = options;
|
|
251
|
+
this.nonce = crypto.randomUUID();
|
|
252
|
+
this.listener = (event) => this.receive(event);
|
|
253
|
+
this.origin = new URL(options.systemOrigin).origin;
|
|
254
|
+
this.init = options.init;
|
|
255
|
+
this.url = `${this.origin}${PREVIEW_EMBED_PATH}#bpe=${this.nonce}&po=${encodeURIComponent(window.location.origin)}`;
|
|
256
|
+
window.addEventListener("message", this.listener);
|
|
257
|
+
}
|
|
258
|
+
post(type, payload) {
|
|
259
|
+
var _a, _b;
|
|
260
|
+
(_b = (_a = this.options.frame()) == null ? void 0 : _a.contentWindow) == null ? void 0 : _b.postMessage(embedEnvelope(type, payload), this.origin);
|
|
261
|
+
}
|
|
262
|
+
receive(event) {
|
|
263
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
264
|
+
if (event.origin !== this.origin || event.source !== ((_a = this.options.frame()) == null ? void 0 : _a.contentWindow) || !isEmbedMessage(event.data))
|
|
265
|
+
return;
|
|
266
|
+
const { type, payload: p } = event.data;
|
|
267
|
+
if (type === "embed.hello") {
|
|
268
|
+
if (p.nonce === this.nonce)
|
|
269
|
+
this.post("embed.init", { ...this.init, nonce: this.nonce });
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
if (type === "embed.state" && (p.status === "loading" || p.status === "ready" || p.status === "error")) {
|
|
273
|
+
const error = p.error;
|
|
274
|
+
(_c = (_b = this.options).onState) == null ? void 0 : _c.call(_b, {
|
|
275
|
+
status: p.status,
|
|
276
|
+
error: error && typeof error.kind === "string" && typeof error.code === "string" ? { kind: error.kind, code: error.code } : void 0,
|
|
277
|
+
title: typeof p.title === "string" ? p.title.slice(0, 256) : void 0,
|
|
278
|
+
mediaType: typeof p.mediaType === "string" ? p.mediaType.slice(0, 128) : void 0
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
if (type === "embed.openWith") {
|
|
282
|
+
const request = p.request;
|
|
283
|
+
if (request && isTransferableRef(request.source) && (request.session === void 0 || isTransferableSession(request.session))) {
|
|
284
|
+
(_e = (_d = this.options).onOpenWith) == null ? void 0 : _e.call(_d, { request: { source: request.source, session: request.session }, hints: readContentHints(p.hints) });
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
if (type === "embed.exit")
|
|
288
|
+
(_g = (_f = this.options).onExit) == null ? void 0 : _g.call(_f);
|
|
289
|
+
}
|
|
290
|
+
update(patch) {
|
|
291
|
+
this.init = { ...this.init, ...patch };
|
|
292
|
+
this.post("embed.update", patch);
|
|
293
|
+
}
|
|
294
|
+
dispose() {
|
|
295
|
+
window.removeEventListener("message", this.listener);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
class PreviewEmbedHost {
|
|
299
|
+
constructor(options) {
|
|
300
|
+
this.options = options;
|
|
301
|
+
this.ready = false;
|
|
302
|
+
this.listener = (event) => this.receive(event);
|
|
303
|
+
const params = new URLSearchParams(window.location.hash.slice(1));
|
|
304
|
+
this.nonce = params.get("bpe");
|
|
305
|
+
let parentOrigin = null;
|
|
306
|
+
try {
|
|
307
|
+
parentOrigin = new URL(params.get("po") ?? "").origin;
|
|
308
|
+
} catch {
|
|
309
|
+
}
|
|
310
|
+
this.parentOrigin = window.parent !== window && this.nonce && parentOrigin && options.accept(parentOrigin) ? parentOrigin : null;
|
|
311
|
+
if (!this.parentOrigin)
|
|
312
|
+
return;
|
|
313
|
+
window.addEventListener("message", this.listener);
|
|
314
|
+
const hello = () => window.parent.postMessage(embedEnvelope("embed.hello", { nonce: this.nonce }), this.parentOrigin);
|
|
315
|
+
hello();
|
|
316
|
+
this.hello = setInterval(() => {
|
|
317
|
+
if (!this.ready)
|
|
318
|
+
hello();
|
|
319
|
+
}, 250);
|
|
320
|
+
}
|
|
321
|
+
receive(event) {
|
|
322
|
+
var _a, _b;
|
|
323
|
+
if (event.source !== window.parent || event.origin !== this.parentOrigin || !isEmbedMessage(event.data))
|
|
324
|
+
return;
|
|
325
|
+
const { type, payload: p } = event.data;
|
|
326
|
+
if (type === "embed.init") {
|
|
327
|
+
if (p.nonce !== this.nonce || !isEmbedSource(p.source) || p.session !== void 0 && !isTransferableSession(p.session) || typeof p.locale !== "string")
|
|
328
|
+
return;
|
|
329
|
+
this.ready = true;
|
|
330
|
+
clearInterval(this.hello);
|
|
331
|
+
this.options.onInit({ nonce: String(p.nonce), source: p.source, session: p.session, theme: p.theme === "dark" ? "dark" : "light", locale: p.locale });
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
if (type === "embed.update" && this.ready) {
|
|
335
|
+
const patch = {};
|
|
336
|
+
if (p.theme === "dark" || p.theme === "light")
|
|
337
|
+
patch.theme = p.theme;
|
|
338
|
+
if (typeof p.locale === "string")
|
|
339
|
+
patch.locale = p.locale;
|
|
340
|
+
(_b = (_a = this.options).onUpdate) == null ? void 0 : _b.call(_a, patch);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
post(type, payload) {
|
|
344
|
+
if (this.ready && this.parentOrigin)
|
|
345
|
+
window.parent.postMessage(embedEnvelope(type, payload), this.parentOrigin);
|
|
346
|
+
}
|
|
347
|
+
state(state) {
|
|
348
|
+
this.post("embed.state", state);
|
|
349
|
+
}
|
|
350
|
+
openWith(open) {
|
|
351
|
+
this.post("embed.openWith", open);
|
|
352
|
+
}
|
|
353
|
+
exit() {
|
|
354
|
+
this.post("embed.exit", {});
|
|
355
|
+
}
|
|
356
|
+
dispose() {
|
|
357
|
+
clearInterval(this.hello);
|
|
358
|
+
window.removeEventListener("message", this.listener);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
185
361
|
export {
|
|
186
362
|
AppFrameClient,
|
|
187
|
-
AppFrameHost
|
|
363
|
+
AppFrameHost,
|
|
364
|
+
PREVIEW_EMBED_PATH,
|
|
365
|
+
PreviewEmbed,
|
|
366
|
+
PreviewEmbedHost,
|
|
367
|
+
embedderOrigin,
|
|
368
|
+
originInZone
|
|
188
369
|
};
|
|
189
370
|
//# sourceMappingURL=app-frame.mjs.map
|