aboutsummaryrefslogtreecommitdiff
path: root/source/library/state/session.svelte.ts
diff options
context:
space:
mode:
Diffstat (limited to 'source/library/state/session.svelte.ts')
-rw-r--r--source/library/state/session.svelte.ts53
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) {