@opengeni/connect 0.3.1 → 0.3.2-canary.37090756480001

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/index.js CHANGED
@@ -241,10 +241,10 @@ function reserveBrowserConnectNavigation(browser) {
241
241
  validateDestination(url);
242
242
  popup.location.replace(url);
243
243
  return {
244
- close,
245
- get closed() {
246
- return popup.closed;
247
- }
244
+ close
245
+ // Browser COOP can sever this WindowProxy and report closed while
246
+ // the provider window is still open. Keep polling durable completion;
247
+ // the host's Stop control and bounded timeout end observation.
248
248
  };
249
249
  },
250
250
  redirect(url) {
@@ -270,10 +270,9 @@ function createBrowserConnectNavigation(browser) {
270
270
  throw new Error("Connect popup could not navigate safely; retry with redirect mode");
271
271
  }
272
272
  return {
273
- close: () => closeIsolatedPopup(popup),
274
- get closed() {
275
- return popup.closed;
276
- }
273
+ close: () => closeIsolatedPopup(popup)
274
+ // WindowProxy.closed is not a reliable user-cancellation signal after
275
+ // a provider moves the popup into a different browsing context group.
277
276
  };
278
277
  },
279
278
  redirect(url) {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/device.ts","../src/recovery.ts","../src/poll.ts","../src/authorization.ts","../src/browser-navigation.ts","../src/index.ts"],"sourcesContent":["/** Shared device-code behavior for model-account domains. These accounts keep\n * their existing APIs and ownership semantics; they are not generic credentials.\n * Keep opaque provider state on the host backend when reload recovery is needed. */\nexport async function pollDeviceAuthorization<\n T extends { status: string; intervalSeconds?: number },\n>(options: {\n poll: () => Promise<T>;\n expired: T;\n initialIntervalSeconds: number;\n expiresAtMs: number;\n signal: AbortSignal;\n retryable?: (error: unknown) => boolean;\n now?: () => number;\n wait?: (delayMs: number, signal: AbortSignal) => Promise<boolean>;\n maxRetryDelaySeconds?: number;\n}): Promise<T | null> {\n const now = options.now ?? Date.now;\n if (\n !Number.isFinite(options.expiresAtMs) ||\n !Number.isFinite(options.initialIntervalSeconds) ||\n options.initialIntervalSeconds <= 0 ||\n (options.maxRetryDelaySeconds !== undefined &&\n (!Number.isFinite(options.maxRetryDelaySeconds) || options.maxRetryDelaySeconds <= 0))\n )\n throw new Error(\"Device authorization requires a finite expiry and polling interval\");\n const wait = options.wait ?? waitForDeviceDelay;\n const initial = Math.max(1, options.initialIntervalSeconds);\n const maximum = Math.max(initial, options.maxRetryDelaySeconds ?? 30);\n let delay = initial;\n while (!options.signal.aborted) {\n const remaining = options.expiresAtMs - now();\n if (remaining <= 0) return options.expired;\n if (!(await wait(Math.min(delay * 1000, remaining), options.signal)) || options.signal.aborted)\n return null;\n if (now() >= options.expiresAtMs) return options.expired;\n let result: T;\n try {\n const observed = await observeDevicePoll(\n options.poll,\n options.expiresAtMs - now(),\n options.signal,\n );\n if (observed.kind === \"aborted\") return null;\n if (observed.kind === \"expired\") return options.expired;\n result = observed.result;\n } catch (error) {\n if (!options.retryable?.(error)) throw error;\n delay = Math.min(maximum, Math.max(initial, delay * 2));\n continue;\n }\n if (options.signal.aborted) return null;\n if (result.status !== \"pending\" && result.status !== \"slow_down\") return result;\n if (\n result.intervalSeconds !== undefined &&\n (!Number.isFinite(result.intervalSeconds) || result.intervalSeconds <= 0)\n )\n throw new Error(\"Provider returned an invalid device polling interval\");\n delay = Math.max(\n 1,\n result.intervalSeconds ?? (result.status === \"slow_down\" ? delay + 5 : delay),\n );\n }\n return null;\n}\n\n/** A transport may ignore cancellation. Bound observation without retrying an\n * in-flight request or treating the loss of observation as provider success. */\nasync function observeDevicePoll<T>(\n poll: () => Promise<T>,\n remainingMs: number,\n signal: AbortSignal,\n): Promise<{ kind: \"result\"; result: T } | { kind: \"aborted\" } | { kind: \"expired\" }> {\n if (signal.aborted) return { kind: \"aborted\" };\n if (remainingMs <= 0) return { kind: \"expired\" };\n let timer: ReturnType<typeof setTimeout> | undefined;\n let abort: (() => void) | undefined;\n try {\n const stopped = new Promise<{ kind: \"aborted\" } | { kind: \"expired\" }>((resolve) => {\n abort = () => resolve({ kind: \"aborted\" });\n signal.addEventListener(\"abort\", abort, { once: true });\n timer = setTimeout(() => resolve({ kind: \"expired\" }), remainingMs);\n });\n return await Promise.race([\n Promise.resolve()\n .then(poll)\n .then((result) => ({ kind: \"result\" as const, result })),\n stopped,\n ]);\n } finally {\n if (timer) clearTimeout(timer);\n if (abort) signal.removeEventListener(\"abort\", abort);\n }\n}\n\nasync function waitForDeviceDelay(delayMs: number, signal: AbortSignal): Promise<boolean> {\n if (signal.aborted) return false;\n return new Promise((resolve) => {\n const abort = () => {\n clearTimeout(timer);\n resolve(false);\n };\n const timer = setTimeout(() => {\n signal.removeEventListener(\"abort\", abort);\n resolve(true);\n }, delayMs);\n signal.addEventListener(\"abort\", abort, { once: true });\n if (signal.aborted) abort();\n });\n}\n","import type { ConnectAccount } from \"./types\";\n\n/** A provider/domain match is not account identity. Never silently substitute\n * another account when the original connection has disappeared. */\nexport function findConnectRecoveryAccount(\n accounts: readonly ConnectAccount[],\n connectionId: string | null | undefined,\n): ConnectAccount | null {\n if (!connectionId) return null;\n const matches = accounts.filter(\n (account) => account.id === connectionId || account.id === `social:${connectionId}`,\n );\n if (matches.length > 1)\n throw new Error(\"Connection recovery is ambiguous; choose the exact account.\");\n return matches[0] ?? null;\n}\n","import type { ConnectAttempt, ConnectTransport } from \"./types\";\n\n/** Read-only continuation. The backend remains authoritative for expiry and\n * completion; redirects and popup messages are never completion evidence. */\nexport async function pollConnectAttempt(\n transport: Pick<ConnectTransport, \"get\">,\n workspaceId: string,\n attemptId: string,\n options: { signal?: AbortSignal; timeoutMs?: number; minimumRevision?: number } = {},\n): Promise<ConnectAttempt> {\n const timeoutMs = options.timeoutMs ?? 120_000;\n if (\n !workspaceId ||\n !attemptId ||\n !Number.isFinite(timeoutMs) ||\n timeoutMs < 1 ||\n timeoutMs > 600_000 ||\n !Number.isSafeInteger(options.minimumRevision ?? 1) ||\n (options.minimumRevision ?? 1) < 1\n ) {\n throw new Error(\"Connect polling requires a scope and a bounded timeout\");\n }\n const abort = new AbortController();\n const cancel = () => abort.abort(options.signal?.reason);\n options.signal?.addEventListener(\"abort\", cancel, { once: true });\n if (options.signal?.aborted) cancel();\n const timer = setTimeout(() => abort.abort(new Error(\"Connect polling timed out\")), timeoutMs);\n let revision = options.minimumRevision ?? 1;\n try {\n while (true) {\n abort.signal.throwIfAborted();\n const result = await abortable(\n transport.get(workspaceId, attemptId, { signal: abort.signal }),\n abort.signal,\n );\n if (\n result.workspaceId !== workspaceId ||\n result.id !== attemptId ||\n !Number.isSafeInteger(result.revision) ||\n result.revision < Math.max(1, revision)\n ) {\n throw new Error(\"Connect polling response scope or revision mismatch\");\n }\n revision = result.revision;\n if (\n [\"complete\", \"cancelled\", \"expired\", \"failed\", \"uncertain\"].includes(result.state) ||\n ![\"authorize\", \"wait\"].includes(result.nextAction.type)\n )\n return result;\n const requested = result.nextAction.type === \"wait\" ? result.nextAction.pollAfterMs : 1000;\n const delay = Number.isFinite(requested) ? Math.min(60_000, Math.max(250, requested)) : 1000;\n await new Promise<void>((resolve, reject) => {\n const stop = () => {\n clearTimeout(wait);\n reject(abort.signal.reason);\n };\n const wait = setTimeout(() => {\n abort.signal.removeEventListener(\"abort\", stop);\n resolve();\n }, delay);\n abort.signal.addEventListener(\"abort\", stop, { once: true });\n if (abort.signal.aborted) stop();\n });\n }\n } finally {\n clearTimeout(timer);\n options.signal?.removeEventListener(\"abort\", cancel);\n }\n}\n\nfunction abortable<T>(pending: Promise<T>, signal: AbortSignal): Promise<T> {\n return new Promise((resolve, reject) => {\n const stop = () => reject(signal.reason);\n signal.addEventListener(\"abort\", stop, { once: true });\n if (signal.aborted) stop();\n pending.then(resolve, reject).finally(() => signal.removeEventListener(\"abort\", stop));\n });\n}\n","import { pollConnectAttempt } from \"./poll\";\nimport type { ConnectAttempt, ConnectTransport } from \"./types\";\n\n/** Inject navigation so hosts own routing and this package needs no DOM globals. */\nexport type ConnectNavigation = {\n openPopup(url: string): { close(): void; readonly closed?: boolean | undefined } | null;\n redirect(url: string): void;\n};\n\nexport class ConnectPopupClosedError extends Error {\n constructor() {\n super(\"Sign-in window closed. You can try connecting again.\");\n this.name = \"ConnectPopupClosedError\";\n }\n}\n\n/** Invoke directly from a user gesture for popup mode. Persist the opaque\n * attempt ID in host-owned state before redirect mode, then recover/poll on\n * return. Neither URL parameters nor popup messages prove completion. */\nexport function authorizeConnectAttempt(\n transport: Pick<ConnectTransport, \"get\">,\n attempt: ConnectAttempt,\n navigation: ConnectNavigation,\n options: { mode: \"popup\" | \"redirect\"; signal?: AbortSignal; timeoutMs?: number },\n): Promise<ConnectAttempt | null> {\n options.signal?.throwIfAborted();\n if (attempt.nextAction.type !== \"authorize\") {\n throw new Error(\"Connect attempt does not require authorization\");\n }\n const destination = new URL(attempt.nextAction.url);\n if (destination.protocol !== \"https:\" || destination.username || destination.password) {\n throw new Error(\"Connect authorization requires an HTTPS destination without credentials\");\n }\n if (\n !attempt.id ||\n !attempt.workspaceId ||\n !Number.isSafeInteger(attempt.revision) ||\n attempt.revision < 1\n )\n throw new Error(\"Connect authorization requires a scope\");\n if (options.mode === \"redirect\") {\n navigation.redirect(attempt.nextAction.url);\n return Promise.resolve(null);\n }\n const popup = navigation.openPopup(attempt.nextAction.url);\n if (!popup) throw new Error(\"Connect popup was blocked; retry with redirect mode\");\n const observation = new AbortController();\n const closed = new ConnectPopupClosedError();\n const abort = () => observation.abort(options.signal?.reason);\n options.signal?.addEventListener(\"abort\", abort, { once: true });\n if (options.signal?.aborted) abort();\n const watch = setInterval(() => {\n try {\n if (popup.closed === true) observation.abort(closed);\n } catch {\n // Some hosts cannot observe their popup after cross-origin navigation.\n }\n }, 250);\n return pollConnectAttempt(transport, attempt.workspaceId, attempt.id, {\n ...options,\n signal: observation.signal,\n minimumRevision: attempt.revision,\n })\n .catch(async (failure: unknown) => {\n if (failure !== closed) throw failure;\n // The callback may have committed just as the provider window closed.\n // Recheck the backend briefly; the window itself is never success evidence.\n const recovery = new AbortController();\n const abortRecovery = () => recovery.abort(options.signal?.reason);\n options.signal?.addEventListener(\"abort\", abortRecovery, { once: true });\n if (options.signal?.aborted) abortRecovery();\n const deadline = setTimeout(() => recovery.abort(closed), 1_500);\n try {\n return await pollConnectAttempt(transport, attempt.workspaceId, attempt.id, {\n signal: recovery.signal,\n minimumRevision: attempt.revision,\n timeoutMs: 2_000,\n });\n } catch (recoveryFailure) {\n if (recoveryFailure === closed) throw closed;\n throw recoveryFailure;\n } finally {\n clearTimeout(deadline);\n options.signal?.removeEventListener(\"abort\", abortRecovery);\n }\n })\n .finally(() => {\n clearInterval(watch);\n options.signal?.removeEventListener(\"abort\", abort);\n // Window cleanup must never replace the authoritative result or failure.\n try {\n popup.close();\n } catch {\n /* Host navigation may already have disposed it. */\n }\n });\n}\n","import type { ConnectNavigation } from \"./authorization\";\n\n/** Structural browser surface so importing Connect never reads DOM globals. */\nexport type ConnectBrowserWindow = {\n open(\n url: string,\n target: string,\n features: string,\n ): {\n opener: unknown;\n readonly closed?: boolean;\n location: { replace(url: string): void };\n close(): void;\n } | null;\n location: { assign(url: string): void };\n};\n\nfunction validateDestination(url: string): void {\n const parsed = new URL(url);\n if (parsed.protocol !== \"https:\" || parsed.username || parsed.password)\n throw new Error(\"Connect authorization requires an HTTPS destination without credentials\");\n}\n\nfunction closeIsolatedPopup(popup: NonNullable<ReturnType<ConnectBrowserWindow[\"open\"]>>): void {\n try {\n if (popup.closed) return;\n // After opener isolation, browsers cannot close a foreign-origin window.\n // Check access first to avoid a futile close and its browser warning.\n Reflect.get(popup.location, \"href\");\n popup.close();\n } catch {\n /* The human closes foreign-origin or detached provider windows. */\n }\n}\n\n/** Reserve the isolated window during the human's click, before asynchronous\n * discovery. The caller must close it if setup fails before navigation. */\nexport function reserveBrowserConnectNavigation(browser: ConnectBrowserWindow): {\n navigation: ConnectNavigation;\n close(): void;\n} {\n const popup = browser.open(\"about:blank\", \"_blank\", \"popup,width=520,height=720\");\n if (!popup) throw new Error(\"Allow popups to connect your account, then try again.\");\n try {\n popup.opener = null;\n if (popup.opener !== null) throw new Error(\"Connect popup isolation failed\");\n } catch {\n closeIsolatedPopup(popup);\n throw new Error(\"Connect popup could not open safely. Please try again.\");\n }\n const close = () => closeIsolatedPopup(popup);\n return {\n close,\n navigation: {\n openPopup(url) {\n validateDestination(url);\n popup.location.replace(url);\n return {\n close,\n get closed() {\n return popup.closed;\n },\n };\n },\n redirect(url) {\n validateDestination(url);\n close();\n browser.location.assign(url);\n },\n },\n };\n}\n\n/** Pass window from the host's browser entry point. Opens a fresh blank window\n * synchronously and severs its opener BEFORE any provider content can load.\n * Never uses a reusable named target or relies on provider window messages.\n * The caller retains only best-effort close capability for polling cleanup;\n * the human closes provider windows that remain on a foreign origin. */\nexport function createBrowserConnectNavigation(browser: ConnectBrowserWindow): ConnectNavigation {\n return {\n openPopup(url) {\n validateDestination(url);\n const popup = browser.open(\"about:blank\", \"_blank\", \"popup,width=520,height=720\");\n if (!popup) return null;\n try {\n popup.opener = null;\n if (popup.opener !== null) throw new Error(\"Connect popup isolation failed\");\n popup.location.replace(url);\n } catch {\n closeIsolatedPopup(popup);\n throw new Error(\"Connect popup could not navigate safely; retry with redirect mode\");\n }\n return {\n close: () => closeIsolatedPopup(popup),\n get closed() {\n return popup.closed;\n },\n };\n },\n redirect(url) {\n validateDestination(url);\n browser.location.assign(url);\n },\n };\n}\n","export * from \"./types\";\nexport { pollDeviceAuthorization } from \"./device\";\nexport { findConnectRecoveryAccount } from \"./recovery\";\nexport { pollConnectAttempt } from \"./poll\";\nexport {\n authorizeConnectAttempt,\n ConnectPopupClosedError,\n type ConnectNavigation,\n} from \"./authorization\";\nexport {\n createBrowserConnectNavigation,\n reserveBrowserConnectNavigation,\n type ConnectBrowserWindow,\n} from \"./browser-navigation\";\nimport type { ConnectAdvance, ConnectAttempt, ConnectOwnership, ConnectTransport } from \"./types\";\nimport { pollConnectAttempt } from \"./poll\";\n\nexport type ConnectSnapshot = {\n attempt: ConnectAttempt | null;\n busy: boolean;\n error: Error | null;\n};\n\n/** A transport-injected, framework-neutral view of one durable setup attempt.\n * OAuth redirects are hints to navigate; completion is read from the backend.\n * Secret form values are never stored in a snapshot or browser persistence. */\nexport class ConnectController {\n private snapshot: ConnectSnapshot = Object.freeze({ attempt: null, busy: false, error: null });\n private readonly listeners = new Set<() => void>();\n private generation = 0;\n private request: AbortController | null = null;\n private disposed = false;\n\n constructor(\n readonly transport: ConnectTransport,\n readonly workspaceId: string,\n ) {\n if (!workspaceId) throw new Error(\"Connect requires an explicit workspace\");\n }\n\n getSnapshot = (): ConnectSnapshot => this.snapshot;\n subscribe = (listener: () => void): (() => void) => {\n this.assertActive();\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n };\n\n begin(input: {\n providerId: string;\n ownership: ConnectOwnership;\n returnUrl: string;\n idempotencyKey: string;\n reconnectAccountId?: string;\n installationTarget?: import(\"./types\").ConnectInstallationTarget;\n }): Promise<ConnectAttempt> {\n // Validation must not serialize or decorate the host's exact return string.\n const url = new URL(input.returnUrl);\n if (![\"https:\", \"http:\"].includes(url.protocol) || url.username || url.password) {\n throw new Error(\"Connect return URL must be an HTTP(S) destination without credentials\");\n }\n return this.run((signal) => this.transport.begin(this.workspaceId, input, { signal }), true);\n }\n\n recover(attemptId: string): Promise<ConnectAttempt> {\n if (!attemptId) throw new Error(\"Connect recovery requires an attempt ID\");\n return this.run(\n (signal) => this.transport.get(this.workspaceId, attemptId, { signal }),\n true,\n attemptId,\n );\n }\n\n refresh(): Promise<ConnectAttempt> {\n const attempt = this.requireAttempt();\n if (this.snapshot.busy) throw new Error(\"A Connect operation is already in progress\");\n return this.run(\n (signal) => this.transport.get(this.workspaceId, attempt.id, { signal }),\n false,\n attempt.id,\n );\n }\n\n advance(action: ConnectAdvance, idempotencyKey: string): Promise<ConnectAttempt> {\n const attempt = this.requireAttempt();\n if (this.snapshot.busy) throw new Error(\"A Connect operation is already in progress\");\n return this.run(\n (signal) =>\n this.transport.advance(\n this.workspaceId,\n attempt.id,\n {\n expectedRevision: attempt.revision,\n idempotencyKey,\n action,\n },\n { signal },\n ),\n false,\n attempt.id,\n );\n }\n\n /** Observe backend progress without replaying a setup mutation. Disposal or\n * selecting another attempt aborts the read loop and fences its late result. */\n waitForAction(options: { timeoutMs?: number } = {}): Promise<ConnectAttempt> {\n const attempt = this.requireAttempt();\n if (this.snapshot.busy) throw new Error(\"A Connect operation is already in progress\");\n return this.run(\n (signal) =>\n pollConnectAttempt(this.transport, this.workspaceId, attempt.id, {\n ...options,\n signal,\n minimumRevision: attempt.revision,\n }),\n false,\n attempt.id,\n );\n }\n\n cancel(idempotencyKey: string): Promise<ConnectAttempt> {\n const attempt = this.requireAttempt();\n if (this.snapshot.busy) throw new Error(\"A Connect operation is already in progress\");\n return this.run(\n (signal) =>\n this.transport.cancel(\n this.workspaceId,\n attempt.id,\n {\n expectedRevision: attempt.revision,\n idempotencyKey,\n },\n { signal },\n ),\n false,\n attempt.id,\n );\n }\n\n dispose(): void {\n if (this.disposed) return;\n this.disposed = true;\n this.generation++;\n this.request?.abort();\n this.request = null;\n this.listeners.clear();\n }\n\n private assertActive(): void {\n if (this.disposed) throw new Error(\"Connect controller is disposed\");\n }\n private requireAttempt(): ConnectAttempt {\n this.assertActive();\n if (!this.snapshot.attempt) throw new Error(\"No Connect attempt is selected\");\n return this.snapshot.attempt;\n }\n private publish(snapshot: ConnectSnapshot): void {\n this.snapshot = Object.freeze(snapshot);\n for (const listener of this.listeners) listener();\n }\n private async run(\n operation: (signal: AbortSignal) => Promise<ConnectAttempt>,\n replace: boolean,\n expectedId?: string,\n ): Promise<ConnectAttempt> {\n this.assertActive();\n const generation = ++this.generation;\n this.request?.abort();\n const request = new AbortController();\n this.request = request;\n this.publish({ attempt: replace ? null : this.snapshot.attempt, busy: true, error: null });\n try {\n const result = await operation(request.signal);\n if (generation !== this.generation || this.disposed)\n throw new Error(\"Connect operation was superseded\");\n if (result.workspaceId !== this.workspaceId || (expectedId && result.id !== expectedId)) {\n throw new Error(\"Connect response scope mismatch\");\n }\n if (\n !Number.isSafeInteger(result.revision) ||\n result.revision < 1 ||\n (this.snapshot.attempt?.id === result.id &&\n result.revision < this.snapshot.attempt.revision)\n ) {\n throw new Error(\"Connect response revision is stale\");\n }\n const attempt = freezeTree(structuredClone(result));\n this.publish({ attempt, busy: false, error: null });\n return structuredClone(attempt);\n } catch (cause) {\n const error = cause instanceof Error ? cause : new Error(\"Connect operation failed\");\n if (generation === this.generation && !this.disposed) {\n // Transport errors can retain request bodies, headers, nested causes or\n // echoed credentials. Keep only a fixed, credential-free UI error in\n // the long-lived snapshot; direct callers still receive the rejection.\n this.publish({\n attempt: this.snapshot.attempt,\n busy: false,\n error: Object.freeze(\n new Error(\"Connect operation failed; refresh its status before retrying\"),\n ),\n });\n }\n throw error;\n } finally {\n if (generation === this.generation) this.request = null;\n }\n }\n}\n\nfunction freezeTree<T>(value: T): T {\n if (value !== null && typeof value === \"object\") {\n for (const child of Object.values(value)) freezeTree(child);\n Object.freeze(value);\n }\n return value;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/device.ts","../src/recovery.ts","../src/poll.ts","../src/authorization.ts","../src/browser-navigation.ts","../src/index.ts"],"sourcesContent":["/** Shared device-code behavior for model-account domains. These accounts keep\n * their existing APIs and ownership semantics; they are not generic credentials.\n * Keep opaque provider state on the host backend when reload recovery is needed. */\nexport async function pollDeviceAuthorization<\n T extends { status: string; intervalSeconds?: number },\n>(options: {\n poll: () => Promise<T>;\n expired: T;\n initialIntervalSeconds: number;\n expiresAtMs: number;\n signal: AbortSignal;\n retryable?: (error: unknown) => boolean;\n now?: () => number;\n wait?: (delayMs: number, signal: AbortSignal) => Promise<boolean>;\n maxRetryDelaySeconds?: number;\n}): Promise<T | null> {\n const now = options.now ?? Date.now;\n if (\n !Number.isFinite(options.expiresAtMs) ||\n !Number.isFinite(options.initialIntervalSeconds) ||\n options.initialIntervalSeconds <= 0 ||\n (options.maxRetryDelaySeconds !== undefined &&\n (!Number.isFinite(options.maxRetryDelaySeconds) || options.maxRetryDelaySeconds <= 0))\n )\n throw new Error(\"Device authorization requires a finite expiry and polling interval\");\n const wait = options.wait ?? waitForDeviceDelay;\n const initial = Math.max(1, options.initialIntervalSeconds);\n const maximum = Math.max(initial, options.maxRetryDelaySeconds ?? 30);\n let delay = initial;\n while (!options.signal.aborted) {\n const remaining = options.expiresAtMs - now();\n if (remaining <= 0) return options.expired;\n if (!(await wait(Math.min(delay * 1000, remaining), options.signal)) || options.signal.aborted)\n return null;\n if (now() >= options.expiresAtMs) return options.expired;\n let result: T;\n try {\n const observed = await observeDevicePoll(\n options.poll,\n options.expiresAtMs - now(),\n options.signal,\n );\n if (observed.kind === \"aborted\") return null;\n if (observed.kind === \"expired\") return options.expired;\n result = observed.result;\n } catch (error) {\n if (!options.retryable?.(error)) throw error;\n delay = Math.min(maximum, Math.max(initial, delay * 2));\n continue;\n }\n if (options.signal.aborted) return null;\n if (result.status !== \"pending\" && result.status !== \"slow_down\") return result;\n if (\n result.intervalSeconds !== undefined &&\n (!Number.isFinite(result.intervalSeconds) || result.intervalSeconds <= 0)\n )\n throw new Error(\"Provider returned an invalid device polling interval\");\n delay = Math.max(\n 1,\n result.intervalSeconds ?? (result.status === \"slow_down\" ? delay + 5 : delay),\n );\n }\n return null;\n}\n\n/** A transport may ignore cancellation. Bound observation without retrying an\n * in-flight request or treating the loss of observation as provider success. */\nasync function observeDevicePoll<T>(\n poll: () => Promise<T>,\n remainingMs: number,\n signal: AbortSignal,\n): Promise<{ kind: \"result\"; result: T } | { kind: \"aborted\" } | { kind: \"expired\" }> {\n if (signal.aborted) return { kind: \"aborted\" };\n if (remainingMs <= 0) return { kind: \"expired\" };\n let timer: ReturnType<typeof setTimeout> | undefined;\n let abort: (() => void) | undefined;\n try {\n const stopped = new Promise<{ kind: \"aborted\" } | { kind: \"expired\" }>((resolve) => {\n abort = () => resolve({ kind: \"aborted\" });\n signal.addEventListener(\"abort\", abort, { once: true });\n timer = setTimeout(() => resolve({ kind: \"expired\" }), remainingMs);\n });\n return await Promise.race([\n Promise.resolve()\n .then(poll)\n .then((result) => ({ kind: \"result\" as const, result })),\n stopped,\n ]);\n } finally {\n if (timer) clearTimeout(timer);\n if (abort) signal.removeEventListener(\"abort\", abort);\n }\n}\n\nasync function waitForDeviceDelay(delayMs: number, signal: AbortSignal): Promise<boolean> {\n if (signal.aborted) return false;\n return new Promise((resolve) => {\n const abort = () => {\n clearTimeout(timer);\n resolve(false);\n };\n const timer = setTimeout(() => {\n signal.removeEventListener(\"abort\", abort);\n resolve(true);\n }, delayMs);\n signal.addEventListener(\"abort\", abort, { once: true });\n if (signal.aborted) abort();\n });\n}\n","import type { ConnectAccount } from \"./types\";\n\n/** A provider/domain match is not account identity. Never silently substitute\n * another account when the original connection has disappeared. */\nexport function findConnectRecoveryAccount(\n accounts: readonly ConnectAccount[],\n connectionId: string | null | undefined,\n): ConnectAccount | null {\n if (!connectionId) return null;\n const matches = accounts.filter(\n (account) => account.id === connectionId || account.id === `social:${connectionId}`,\n );\n if (matches.length > 1)\n throw new Error(\"Connection recovery is ambiguous; choose the exact account.\");\n return matches[0] ?? null;\n}\n","import type { ConnectAttempt, ConnectTransport } from \"./types\";\n\n/** Read-only continuation. The backend remains authoritative for expiry and\n * completion; redirects and popup messages are never completion evidence. */\nexport async function pollConnectAttempt(\n transport: Pick<ConnectTransport, \"get\">,\n workspaceId: string,\n attemptId: string,\n options: { signal?: AbortSignal; timeoutMs?: number; minimumRevision?: number } = {},\n): Promise<ConnectAttempt> {\n const timeoutMs = options.timeoutMs ?? 120_000;\n if (\n !workspaceId ||\n !attemptId ||\n !Number.isFinite(timeoutMs) ||\n timeoutMs < 1 ||\n timeoutMs > 600_000 ||\n !Number.isSafeInteger(options.minimumRevision ?? 1) ||\n (options.minimumRevision ?? 1) < 1\n ) {\n throw new Error(\"Connect polling requires a scope and a bounded timeout\");\n }\n const abort = new AbortController();\n const cancel = () => abort.abort(options.signal?.reason);\n options.signal?.addEventListener(\"abort\", cancel, { once: true });\n if (options.signal?.aborted) cancel();\n const timer = setTimeout(() => abort.abort(new Error(\"Connect polling timed out\")), timeoutMs);\n let revision = options.minimumRevision ?? 1;\n try {\n while (true) {\n abort.signal.throwIfAborted();\n const result = await abortable(\n transport.get(workspaceId, attemptId, { signal: abort.signal }),\n abort.signal,\n );\n if (\n result.workspaceId !== workspaceId ||\n result.id !== attemptId ||\n !Number.isSafeInteger(result.revision) ||\n result.revision < Math.max(1, revision)\n ) {\n throw new Error(\"Connect polling response scope or revision mismatch\");\n }\n revision = result.revision;\n if (\n [\"complete\", \"cancelled\", \"expired\", \"failed\", \"uncertain\"].includes(result.state) ||\n ![\"authorize\", \"wait\"].includes(result.nextAction.type)\n )\n return result;\n const requested = result.nextAction.type === \"wait\" ? result.nextAction.pollAfterMs : 1000;\n const delay = Number.isFinite(requested) ? Math.min(60_000, Math.max(250, requested)) : 1000;\n await new Promise<void>((resolve, reject) => {\n const stop = () => {\n clearTimeout(wait);\n reject(abort.signal.reason);\n };\n const wait = setTimeout(() => {\n abort.signal.removeEventListener(\"abort\", stop);\n resolve();\n }, delay);\n abort.signal.addEventListener(\"abort\", stop, { once: true });\n if (abort.signal.aborted) stop();\n });\n }\n } finally {\n clearTimeout(timer);\n options.signal?.removeEventListener(\"abort\", cancel);\n }\n}\n\nfunction abortable<T>(pending: Promise<T>, signal: AbortSignal): Promise<T> {\n return new Promise((resolve, reject) => {\n const stop = () => reject(signal.reason);\n signal.addEventListener(\"abort\", stop, { once: true });\n if (signal.aborted) stop();\n pending.then(resolve, reject).finally(() => signal.removeEventListener(\"abort\", stop));\n });\n}\n","import { pollConnectAttempt } from \"./poll\";\nimport type { ConnectAttempt, ConnectTransport } from \"./types\";\n\n/** Inject navigation so hosts own routing and this package needs no DOM globals. */\nexport type ConnectNavigation = {\n openPopup(url: string): { close(): void; readonly closed?: boolean | undefined } | null;\n redirect(url: string): void;\n};\n\nexport class ConnectPopupClosedError extends Error {\n constructor() {\n super(\"Sign-in window closed. You can try connecting again.\");\n this.name = \"ConnectPopupClosedError\";\n }\n}\n\n/** Invoke directly from a user gesture for popup mode. Persist the opaque\n * attempt ID in host-owned state before redirect mode, then recover/poll on\n * return. Neither URL parameters nor popup messages prove completion. */\nexport function authorizeConnectAttempt(\n transport: Pick<ConnectTransport, \"get\">,\n attempt: ConnectAttempt,\n navigation: ConnectNavigation,\n options: { mode: \"popup\" | \"redirect\"; signal?: AbortSignal; timeoutMs?: number },\n): Promise<ConnectAttempt | null> {\n options.signal?.throwIfAborted();\n if (attempt.nextAction.type !== \"authorize\") {\n throw new Error(\"Connect attempt does not require authorization\");\n }\n const destination = new URL(attempt.nextAction.url);\n if (destination.protocol !== \"https:\" || destination.username || destination.password) {\n throw new Error(\"Connect authorization requires an HTTPS destination without credentials\");\n }\n if (\n !attempt.id ||\n !attempt.workspaceId ||\n !Number.isSafeInteger(attempt.revision) ||\n attempt.revision < 1\n )\n throw new Error(\"Connect authorization requires a scope\");\n if (options.mode === \"redirect\") {\n navigation.redirect(attempt.nextAction.url);\n return Promise.resolve(null);\n }\n const popup = navigation.openPopup(attempt.nextAction.url);\n if (!popup) throw new Error(\"Connect popup was blocked; retry with redirect mode\");\n const observation = new AbortController();\n const closed = new ConnectPopupClosedError();\n const abort = () => observation.abort(options.signal?.reason);\n options.signal?.addEventListener(\"abort\", abort, { once: true });\n if (options.signal?.aborted) abort();\n const watch = setInterval(() => {\n try {\n if (popup.closed === true) observation.abort(closed);\n } catch {\n // Some hosts cannot observe their popup after cross-origin navigation.\n }\n }, 250);\n return pollConnectAttempt(transport, attempt.workspaceId, attempt.id, {\n ...options,\n signal: observation.signal,\n minimumRevision: attempt.revision,\n })\n .catch(async (failure: unknown) => {\n if (failure !== closed) throw failure;\n // The callback may have committed just as the provider window closed.\n // Recheck the backend briefly; the window itself is never success evidence.\n const recovery = new AbortController();\n const abortRecovery = () => recovery.abort(options.signal?.reason);\n options.signal?.addEventListener(\"abort\", abortRecovery, { once: true });\n if (options.signal?.aborted) abortRecovery();\n const deadline = setTimeout(() => recovery.abort(closed), 1_500);\n try {\n return await pollConnectAttempt(transport, attempt.workspaceId, attempt.id, {\n signal: recovery.signal,\n minimumRevision: attempt.revision,\n timeoutMs: 2_000,\n });\n } catch (recoveryFailure) {\n if (recoveryFailure === closed) throw closed;\n throw recoveryFailure;\n } finally {\n clearTimeout(deadline);\n options.signal?.removeEventListener(\"abort\", abortRecovery);\n }\n })\n .finally(() => {\n clearInterval(watch);\n options.signal?.removeEventListener(\"abort\", abort);\n // Window cleanup must never replace the authoritative result or failure.\n try {\n popup.close();\n } catch {\n /* Host navigation may already have disposed it. */\n }\n });\n}\n","import type { ConnectNavigation } from \"./authorization\";\n\n/** Structural browser surface so importing Connect never reads DOM globals. */\nexport type ConnectBrowserWindow = {\n open(\n url: string,\n target: string,\n features: string,\n ): {\n opener: unknown;\n readonly closed?: boolean;\n location: { replace(url: string): void };\n close(): void;\n } | null;\n location: { assign(url: string): void };\n};\n\nfunction validateDestination(url: string): void {\n const parsed = new URL(url);\n if (parsed.protocol !== \"https:\" || parsed.username || parsed.password)\n throw new Error(\"Connect authorization requires an HTTPS destination without credentials\");\n}\n\nfunction closeIsolatedPopup(popup: NonNullable<ReturnType<ConnectBrowserWindow[\"open\"]>>): void {\n try {\n if (popup.closed) return;\n // After opener isolation, browsers cannot close a foreign-origin window.\n // Check access first to avoid a futile close and its browser warning.\n Reflect.get(popup.location, \"href\");\n popup.close();\n } catch {\n /* The human closes foreign-origin or detached provider windows. */\n }\n}\n\n/** Reserve the isolated window during the human's click, before asynchronous\n * discovery. The caller must close it if setup fails before navigation. */\nexport function reserveBrowserConnectNavigation(browser: ConnectBrowserWindow): {\n navigation: ConnectNavigation;\n close(): void;\n} {\n const popup = browser.open(\"about:blank\", \"_blank\", \"popup,width=520,height=720\");\n if (!popup) throw new Error(\"Allow popups to connect your account, then try again.\");\n try {\n popup.opener = null;\n if (popup.opener !== null) throw new Error(\"Connect popup isolation failed\");\n } catch {\n closeIsolatedPopup(popup);\n throw new Error(\"Connect popup could not open safely. Please try again.\");\n }\n const close = () => closeIsolatedPopup(popup);\n return {\n close,\n navigation: {\n openPopup(url) {\n validateDestination(url);\n popup.location.replace(url);\n return {\n close,\n // Browser COOP can sever this WindowProxy and report closed while\n // the provider window is still open. Keep polling durable completion;\n // the host's Stop control and bounded timeout end observation.\n };\n },\n redirect(url) {\n validateDestination(url);\n close();\n browser.location.assign(url);\n },\n },\n };\n}\n\n/** Pass window from the host's browser entry point. Opens a fresh blank window\n * synchronously and severs its opener BEFORE any provider content can load.\n * Never uses a reusable named target or relies on provider window messages.\n * The caller retains only best-effort close capability for polling cleanup;\n * the human closes provider windows that remain on a foreign origin. */\nexport function createBrowserConnectNavigation(browser: ConnectBrowserWindow): ConnectNavigation {\n return {\n openPopup(url) {\n validateDestination(url);\n const popup = browser.open(\"about:blank\", \"_blank\", \"popup,width=520,height=720\");\n if (!popup) return null;\n try {\n popup.opener = null;\n if (popup.opener !== null) throw new Error(\"Connect popup isolation failed\");\n popup.location.replace(url);\n } catch {\n closeIsolatedPopup(popup);\n throw new Error(\"Connect popup could not navigate safely; retry with redirect mode\");\n }\n return {\n close: () => closeIsolatedPopup(popup),\n // WindowProxy.closed is not a reliable user-cancellation signal after\n // a provider moves the popup into a different browsing context group.\n };\n },\n redirect(url) {\n validateDestination(url);\n browser.location.assign(url);\n },\n };\n}\n","export * from \"./types\";\nexport { pollDeviceAuthorization } from \"./device\";\nexport { findConnectRecoveryAccount } from \"./recovery\";\nexport { pollConnectAttempt } from \"./poll\";\nexport {\n authorizeConnectAttempt,\n ConnectPopupClosedError,\n type ConnectNavigation,\n} from \"./authorization\";\nexport {\n createBrowserConnectNavigation,\n reserveBrowserConnectNavigation,\n type ConnectBrowserWindow,\n} from \"./browser-navigation\";\nimport type { ConnectAdvance, ConnectAttempt, ConnectOwnership, ConnectTransport } from \"./types\";\nimport { pollConnectAttempt } from \"./poll\";\n\nexport type ConnectSnapshot = {\n attempt: ConnectAttempt | null;\n busy: boolean;\n error: Error | null;\n};\n\n/** A transport-injected, framework-neutral view of one durable setup attempt.\n * OAuth redirects are hints to navigate; completion is read from the backend.\n * Secret form values are never stored in a snapshot or browser persistence. */\nexport class ConnectController {\n private snapshot: ConnectSnapshot = Object.freeze({ attempt: null, busy: false, error: null });\n private readonly listeners = new Set<() => void>();\n private generation = 0;\n private request: AbortController | null = null;\n private disposed = false;\n\n constructor(\n readonly transport: ConnectTransport,\n readonly workspaceId: string,\n ) {\n if (!workspaceId) throw new Error(\"Connect requires an explicit workspace\");\n }\n\n getSnapshot = (): ConnectSnapshot => this.snapshot;\n subscribe = (listener: () => void): (() => void) => {\n this.assertActive();\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n };\n\n begin(input: {\n providerId: string;\n ownership: ConnectOwnership;\n returnUrl: string;\n idempotencyKey: string;\n reconnectAccountId?: string;\n installationTarget?: import(\"./types\").ConnectInstallationTarget;\n }): Promise<ConnectAttempt> {\n // Validation must not serialize or decorate the host's exact return string.\n const url = new URL(input.returnUrl);\n if (![\"https:\", \"http:\"].includes(url.protocol) || url.username || url.password) {\n throw new Error(\"Connect return URL must be an HTTP(S) destination without credentials\");\n }\n return this.run((signal) => this.transport.begin(this.workspaceId, input, { signal }), true);\n }\n\n recover(attemptId: string): Promise<ConnectAttempt> {\n if (!attemptId) throw new Error(\"Connect recovery requires an attempt ID\");\n return this.run(\n (signal) => this.transport.get(this.workspaceId, attemptId, { signal }),\n true,\n attemptId,\n );\n }\n\n refresh(): Promise<ConnectAttempt> {\n const attempt = this.requireAttempt();\n if (this.snapshot.busy) throw new Error(\"A Connect operation is already in progress\");\n return this.run(\n (signal) => this.transport.get(this.workspaceId, attempt.id, { signal }),\n false,\n attempt.id,\n );\n }\n\n advance(action: ConnectAdvance, idempotencyKey: string): Promise<ConnectAttempt> {\n const attempt = this.requireAttempt();\n if (this.snapshot.busy) throw new Error(\"A Connect operation is already in progress\");\n return this.run(\n (signal) =>\n this.transport.advance(\n this.workspaceId,\n attempt.id,\n {\n expectedRevision: attempt.revision,\n idempotencyKey,\n action,\n },\n { signal },\n ),\n false,\n attempt.id,\n );\n }\n\n /** Observe backend progress without replaying a setup mutation. Disposal or\n * selecting another attempt aborts the read loop and fences its late result. */\n waitForAction(options: { timeoutMs?: number } = {}): Promise<ConnectAttempt> {\n const attempt = this.requireAttempt();\n if (this.snapshot.busy) throw new Error(\"A Connect operation is already in progress\");\n return this.run(\n (signal) =>\n pollConnectAttempt(this.transport, this.workspaceId, attempt.id, {\n ...options,\n signal,\n minimumRevision: attempt.revision,\n }),\n false,\n attempt.id,\n );\n }\n\n cancel(idempotencyKey: string): Promise<ConnectAttempt> {\n const attempt = this.requireAttempt();\n if (this.snapshot.busy) throw new Error(\"A Connect operation is already in progress\");\n return this.run(\n (signal) =>\n this.transport.cancel(\n this.workspaceId,\n attempt.id,\n {\n expectedRevision: attempt.revision,\n idempotencyKey,\n },\n { signal },\n ),\n false,\n attempt.id,\n );\n }\n\n dispose(): void {\n if (this.disposed) return;\n this.disposed = true;\n this.generation++;\n this.request?.abort();\n this.request = null;\n this.listeners.clear();\n }\n\n private assertActive(): void {\n if (this.disposed) throw new Error(\"Connect controller is disposed\");\n }\n private requireAttempt(): ConnectAttempt {\n this.assertActive();\n if (!this.snapshot.attempt) throw new Error(\"No Connect attempt is selected\");\n return this.snapshot.attempt;\n }\n private publish(snapshot: ConnectSnapshot): void {\n this.snapshot = Object.freeze(snapshot);\n for (const listener of this.listeners) listener();\n }\n private async run(\n operation: (signal: AbortSignal) => Promise<ConnectAttempt>,\n replace: boolean,\n expectedId?: string,\n ): Promise<ConnectAttempt> {\n this.assertActive();\n const generation = ++this.generation;\n this.request?.abort();\n const request = new AbortController();\n this.request = request;\n this.publish({ attempt: replace ? null : this.snapshot.attempt, busy: true, error: null });\n try {\n const result = await operation(request.signal);\n if (generation !== this.generation || this.disposed)\n throw new Error(\"Connect operation was superseded\");\n if (result.workspaceId !== this.workspaceId || (expectedId && result.id !== expectedId)) {\n throw new Error(\"Connect response scope mismatch\");\n }\n if (\n !Number.isSafeInteger(result.revision) ||\n result.revision < 1 ||\n (this.snapshot.attempt?.id === result.id &&\n result.revision < this.snapshot.attempt.revision)\n ) {\n throw new Error(\"Connect response revision is stale\");\n }\n const attempt = freezeTree(structuredClone(result));\n this.publish({ attempt, busy: false, error: null });\n return structuredClone(attempt);\n } catch (cause) {\n const error = cause instanceof Error ? cause : new Error(\"Connect operation failed\");\n if (generation === this.generation && !this.disposed) {\n // Transport errors can retain request bodies, headers, nested causes or\n // echoed credentials. Keep only a fixed, credential-free UI error in\n // the long-lived snapshot; direct callers still receive the rejection.\n this.publish({\n attempt: this.snapshot.attempt,\n busy: false,\n error: Object.freeze(\n new Error(\"Connect operation failed; refresh its status before retrying\"),\n ),\n });\n }\n throw error;\n } finally {\n if (generation === this.generation) this.request = null;\n }\n }\n}\n\nfunction freezeTree<T>(value: T): T {\n if (value !== null && typeof value === \"object\") {\n for (const child of Object.values(value)) freezeTree(child);\n Object.freeze(value);\n }\n return value;\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengeni/connect",
3
- "version": "0.3.1",
3
+ "version": "0.3.2-canary.37090756480001",
4
4
  "description": "Framework-neutral OpenGeni connection setup and recovery controller.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -57,9 +57,9 @@ export function reserveBrowserConnectNavigation(browser: ConnectBrowserWindow):
57
57
  popup.location.replace(url);
58
58
  return {
59
59
  close,
60
- get closed() {
61
- return popup.closed;
62
- },
60
+ // Browser COOP can sever this WindowProxy and report closed while
61
+ // the provider window is still open. Keep polling durable completion;
62
+ // the host's Stop control and bounded timeout end observation.
63
63
  };
64
64
  },
65
65
  redirect(url) {
@@ -92,9 +92,8 @@ export function createBrowserConnectNavigation(browser: ConnectBrowserWindow): C
92
92
  }
93
93
  return {
94
94
  close: () => closeIsolatedPopup(popup),
95
- get closed() {
96
- return popup.closed;
97
- },
95
+ // WindowProxy.closed is not a reliable user-cancellation signal after
96
+ // a provider moves the popup into a different browsing context group.
98
97
  };
99
98
  },
100
99
  redirect(url) {