ink-framework-network 0.1.0-alpha.10 → 0.1.0-alpha.12

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.
Files changed (2) hide show
  1. package/package.json +3 -3
  2. package/src/downloads.ts +56 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ink-framework-network",
3
- "version": "0.1.0-alpha.10",
3
+ "version": "0.1.0-alpha.12",
4
4
  "exports": {
5
5
  ".": "./src/index.ts",
6
6
  "./connectivity": "./src/connectivity.ts",
@@ -12,8 +12,8 @@
12
12
  "@types/whatwg-url": "13.0.0"
13
13
  },
14
14
  "peerDependencies": {
15
- "ink": "npm:ink-framework@0.1.0-alpha.10",
16
- "@ink/files": "npm:ink-framework-files@0.1.0-alpha.10"
15
+ "ink": "npm:ink-framework@0.1.0-alpha.12",
16
+ "@ink/files": "npm:ink-framework-files@0.1.0-alpha.12"
17
17
  },
18
18
  "sideEffects": [
19
19
  "./src/index.ts"
package/src/downloads.ts CHANGED
@@ -96,6 +96,60 @@ function observe(id: string): SnapshotSource<DownloadState> {
96
96
  const command = async (operation: string, id: string): Promise<void> => {
97
97
  await callNative("downloads", operation, { id });
98
98
  };
99
+ const allDownloads: SnapshotSource<readonly DownloadState[]> = (() => {
100
+ let snapshot: Snapshot<readonly DownloadState[]> = { status: "loading" };
101
+ const items = new Map<string, DownloadState>();
102
+ const listeners = new Set<() => void>();
103
+ let attachment: ReturnType<typeof attachNativeController> | undefined;
104
+ const publish = (value: Snapshot<readonly DownloadState[]>) => {
105
+ snapshot = value;
106
+ for (const listener of listeners) listener();
107
+ };
108
+ return {
109
+ getSnapshot: () => snapshot,
110
+ subscribe(listener) {
111
+ listeners.add(listener);
112
+ if (!attachment) {
113
+ const current = attachNativeController("downloads", { all: true }, value => {
114
+ if (attachment !== current) return;
115
+ try {
116
+ if (typeof value !== "object" || value === null) throw new Error("Invalid download update");
117
+ if ("items" in value && Array.isArray(value.items)) {
118
+ const decoded = value.items.map(decode);
119
+ if ("reset" in value && value.reset === true) items.clear();
120
+ for (const item of decoded) items.set(item.id, item);
121
+ if (!("complete" in value) || value.complete !== true) return;
122
+ } else if ("id" in value && typeof value.id === "string" && "item" in value) {
123
+ if (value.item === null) items.delete(value.id);
124
+ else {
125
+ const item = decode(value.item);
126
+ if (item.id !== value.id) throw new Error("Download update ID does not match");
127
+ items.set(item.id, item);
128
+ }
129
+ } else throw new Error("Invalid download update");
130
+ publish({ status: "ready", data: Array.from(items.values()) });
131
+ } catch (error) {
132
+ publish({ status: "error", error: error instanceof Error ? error : new Error(String(error)) });
133
+ }
134
+ });
135
+ attachment = current;
136
+ void current.ready.catch(error => {
137
+ if (attachment === current) publish({ status: "error", error });
138
+ });
139
+ }
140
+ return () => {
141
+ listeners.delete(listener);
142
+ if (!listeners.size) {
143
+ const current = attachment;
144
+ attachment = undefined;
145
+ snapshot = { status: "loading" };
146
+ items.clear();
147
+ void current?.dispose().catch(error => console.error("Could not stop observing downloads", error));
148
+ }
149
+ };
150
+ },
151
+ };
152
+ })();
99
153
  export const downloads = {
100
154
  async enqueue(options: { key: string; url: string; name: string; network?: "connected" | "unmetered" }): Promise<DownloadState> {
101
155
  return decode(JSON.parse(await callNative("downloads", "enqueue", options)));
@@ -104,6 +158,8 @@ export const downloads = {
104
158
  return decode(JSON.parse(await callNative("downloads", "get", { id })));
105
159
  },
106
160
  observe,
161
+ /** Observe the download queue with one native subscription, including additions and removals. */
162
+ observeAll: () => allDownloads,
107
163
  pause: (id: string) => command("pause", id),
108
164
  resume: (id: string) => command("resume", id),
109
165
  cancel: (id: string) => command("cancel", id),