diff options
Diffstat (limited to 'source/library/state')
| -rw-r--r-- | source/library/state/session.svelte.ts | 53 |
1 files changed, 51 insertions, 2 deletions
diff --git a/source/library/state/session.svelte.ts b/source/library/state/session.svelte.ts index d9f52ff..9345d29 100644 --- a/source/library/state/session.svelte.ts +++ b/source/library/state/session.svelte.ts @@ -3,7 +3,7 @@ /*** UTILITY ------------------------------------------ ***/ -import type { Fetcher } from "../fetcher/types.ts"; +import type { Fetcher, FetcherResult } from "../fetcher/types.ts"; import { deriveTitle, parseOperations, @@ -13,6 +13,12 @@ import type { Storage } from "./storage.ts"; const STORAGE_KEY = "session"; +function isAsyncIterable<T>(value: unknown): value is AsyncIterable<T> { + return typeof value === "object" && + value !== null && + typeof (value as AsyncIterable<T>)[Symbol.asyncIterator] === "function"; +} + type Snapshot = { activeId: string; tabs: Tab[]; @@ -40,6 +46,13 @@ export type TabSeed = { variables?: string; }; +export type SubscriptionMode = "append" | "replace"; + +export type RunOptions = { + signal?: AbortSignal; + subscriptionMode?: SubscriptionMode; +}; + export class SessionStore { activeId = $state<string>(""); tabs = $state<Tab[]>([]); @@ -115,12 +128,15 @@ export class SessionStore { tab.titleDirty = true; } - async run(fetcher: Fetcher): Promise<boolean> { + async run(fetcher: Fetcher, options: RunOptions = {}): Promise<boolean> { const tab = this.active; if (!tab) return false; + const mode = options.subscriptionMode ?? "append"; + const signal = options.signal; + try { const variables = tab.variables.trim() ? JSON.parse(tab.variables) : {}; const headers = tab.headers.trim() ? JSON.parse(tab.headers) : {}; @@ -132,6 +148,39 @@ export class SessionStore { variables }); + if (isAsyncIterable<FetcherResult>(result)) { + tab.result = ""; + const iterator = result[Symbol.asyncIterator](); + + try { + while (true) { + if (signal?.aborted) { + await iterator.return?.(); + break; + } + + const step = await iterator.next(); + + if (step.done) + break; + + const payload = JSON.stringify(step.value, null, 2); + + if (mode === "append") { + const stamp = new Date().toISOString(); + const chunk = `// ${stamp}\n${payload}\n`; + tab.result = tab.result ? `${tab.result}\n${chunk}` : chunk; + } else { + tab.result = payload; + } + } + } finally { + await iterator.return?.(); + } + + return true; + } + tab.result = JSON.stringify(result, null, 2); return true; } catch(err) { |