Experiment to rebuild Diffuse using web applets.
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: perform input-configurator actions directly on its worker

+233 -163
+1 -1
package-lock.json
··· 2230 2230 "node_modules/@web-applets/sdk": { 2231 2231 "version": "0.2.6", 2232 2232 "resolved": "https://gitpkg.vercel.app/unternet-co/web-applets/sdk?tokono.ma/experiment&scripts.postinstall=npm%20i%20%40types%2Fnode%20%26%26%20npx%20tsc", 2233 - "integrity": "sha512-6fDpl977RqV7zMfKDPrGEaJs2nX2cpLERFv6mC4pdpw2PwdBb1rqADitBRlEIquLUakga0pCfqJFSHqfRRJMOw==", 2233 + "integrity": "sha512-cIJ5viAtAKbbeB0izJ9VTXVDr9xsxAiGWMlhDZd1F9iHdGMk7j0cO8Q03wKxidVx5d/1kijHP07CDA7fygccEA==", 2234 2234 "hasInstallScript": true, 2235 2235 "license": "MIT" 2236 2236 },
+15 -107
src/pages/configurator/input/_applet.astro
··· 33 33 34 34 <script> 35 35 import type { Applet } from "@web-applets/sdk"; 36 - import * as URI from "uri-js"; 37 36 38 - import type { Consult, GroupConsult, Track } from "@applets/core/types.d.ts"; 39 - import type { Actions } from "@scripts/configurator/input/worker"; 37 + import type { Tasks } from "@scripts/configurator/input/worker"; 40 38 import type { Scheme } from "@scripts/configurator/input/types"; 41 39 import { CONNECTIONS } from "@scripts/configurator/input/constants"; 42 40 import { applet, register } from "@scripts/applet/common"; 43 - import { endpoint, groupTracksPerScheme, transfer } from "@scripts/common"; 41 + import { endpoint, transfer } from "@scripts/common"; 44 42 import manifest from "./_manifest.json"; 45 43 46 44 //////////////////////////////////////////// 47 45 // SETUP 48 46 //////////////////////////////////////////// 49 - const worker = endpoint<Actions>( 47 + const worker = endpoint<Tasks>( 50 48 new SharedWorker(new URL("../../../scripts/configurator/input/worker", import.meta.url), { 51 49 type: "module", 52 50 name: manifest.name, 53 51 }).port, 54 52 ); 55 53 56 - // Register applet 57 - const context = register(); 54 + // Register applet + worker 55 + const context = register({ worker }); 58 56 59 57 //////////////////////////////////////////// 60 58 // CONNECTIONS 61 - ////////////////////////////////////////////// Applet connections 62 - const connections: Record<Scheme, Promise<Applet> | undefined> = { 63 - "file+local": undefined, 64 - opensubsonic: undefined, 65 - s3: undefined, 66 - }; 67 - 68 - async function connection(scheme: Scheme) { 69 - connections[scheme] = connections[scheme] ?? applet(CONNECTIONS[scheme]); 70 - return connections[scheme]; 71 - } 72 - 73 - function isSupportedScheme(scheme: string): scheme is Scheme { 74 - return !!CONNECTIONS[scheme as Scheme]; 75 - } 76 - 77 59 //////////////////////////////////////////// 78 - // ACTIONS 79 - //////////////////////////////////////////// 80 - const consult = async (fileUriOrScheme: string): Promise<Consult> => { 81 - const scheme = fileUriOrScheme.includes(":") 82 - ? URI.parse(fileUriOrScheme).scheme || fileUriOrScheme 83 - : fileUriOrScheme; 84 - 85 - if (!isSupportedScheme(scheme)) { 86 - return { supported: false, reason: "Unsupported scheme" }; 87 - } 88 - 89 - const conn = await connection(scheme); 90 - return await conn.sendAction<Consult>("consult", fileUriOrScheme, { 91 - timeoutDuration: 60000 * 5, 92 - }); 93 - }; 94 - 95 - const contextualize = async (tracks: Track[]) => { 96 - const groups = await worker.groupTracks(transfer(tracks)); 97 - const promises = Object.entries(groups).map( 98 - async ([scheme, tracksGroup]: [string, Track[]]) => { 99 - if (!isSupportedScheme(scheme) || tracksGroup.length === 0) return; 100 - const conn = await connection(scheme); 101 - await conn.sendAction("contextualize", tracksGroup, { timeoutDuration: 60000 * 5 }); 102 - }, 103 - ); 104 - 105 - await Promise.all(promises); 106 - }; 107 - 108 - const groupConsult = async (tracks: Track[]) => { 109 - const groups = groupTracksPerScheme(tracks); 110 - const consultations = await Promise.all( 111 - Object.keys(groups).map(async (scheme) => { 112 - if (!isSupportedScheme(scheme)) { 113 - return { available: false, reason: "Unsupported scheme" }; 114 - } 115 - 116 - const conn = await connection(scheme); 117 - return await conn.sendAction("groupConsult", groups[scheme] || [], { 118 - timeoutDuration: 60000 * 5, 119 - }); 120 - }), 121 - ); 122 - 123 - return consultations.reduce((acc: GroupConsult, c: GroupConsult) => { 124 - return { ...acc, ...c }; 125 - }, {}); 60 + const connections: Record<Scheme, Promise<Applet>> = { 61 + "file+local": applet(CONNECTIONS["file+local"], { context: self }), 62 + opensubsonic: applet(CONNECTIONS.opensubsonic, { context: self }), 63 + s3: applet(CONNECTIONS.s3, { context: self }), 126 64 }; 127 65 128 - const list = async (cachedTracks: Track[] = []) => { 129 - const groups = await worker.groupTracks(transfer(cachedTracks)); 130 - 131 - const promises = Object.entries(groups).map( 132 - async ([scheme, cachedTracksGroup]: [string, Track[]]) => { 133 - if (!isSupportedScheme(scheme)) return cachedTracksGroup; 134 - const conn = await connection(scheme); 135 - return await conn.sendAction("list", cachedTracksGroup, { 136 - timeoutDuration: 60000 * 60 * 24, 137 - }); 138 - }, 139 - ); 140 - 141 - const nested = await Promise.all(promises); 142 - const tracks = nested.flat(1); 143 - 144 - return tracks; 145 - }; 146 - 147 - const resolve = async (args: { method: string; uri: string }) => { 148 - const scheme = args.uri.split(":", 1)[0]; 149 - if (!isSupportedScheme(scheme)) return undefined; 150 - 151 - try { 152 - const conn = await connection(scheme); 153 - return await conn.sendAction("resolve", args, { timeoutDuration: 60000 * 5 }); 154 - } catch (err) { 155 - console.error(`[configuration/input] Resolve error for scheme '${scheme}'.`, err); 156 - } 157 - }; 158 - 159 - context.setActionHandler("consult", consult); 160 - context.setActionHandler("contextualize", contextualize); 161 - context.setActionHandler("groupConsult", groupConsult); 162 - context.setActionHandler("list", list); 163 - context.setActionHandler("resolve", resolve); 66 + // Pass worker message ports to configurator worker 67 + Object.entries(connections).forEach(([scheme, promise]) => { 68 + promise.then((conn) => { 69 + return worker.manageInputWorker(scheme as Scheme, transfer(conn.ports.worker)); 70 + }); 71 + }); 164 72 </script>
+8
src/pages/core/types.d.ts
··· 16 16 17 17 export type GroupConsult = Record<string, ConsultGrouping>; 18 18 19 + export interface InputWorkerTasks { 20 + consult(fileUriOrScheme: string): Promise<Consult>; 21 + contextualize(tracks: Track[]): Promise<void>; 22 + groupConsult(tracks: Track[]): Promise<GroupConsult>; 23 + list(cachedTracks: Track[] = []): Promise<Track[]>; 24 + resolve({ method, uri }: { method: string; uri: string }): Promise<ResolvedUri>; 25 + } 26 + 19 27 /* OUTPUT */ 20 28 21 29 export interface Output<S = TrackStats, T = TrackTags> {
+3 -3
src/pages/input/native-fs/_applet.astro
··· 16 16 </main> 17 17 18 18 <script> 19 - import type { Actions } from "@scripts/input/native-fs/worker"; 19 + import type { Tasks } from "@scripts/input/native-fs/worker"; 20 20 import type { Track } from "@applets/core/types.d.ts"; 21 21 import { register } from "@scripts/applet/common"; 22 22 import { endpoint, inIframe, SharedWorker, transfer } from "@scripts/common"; ··· 26 26 //////////////////////////////////////////// 27 27 // SETUP 28 28 //////////////////////////////////////////// 29 - const worker = endpoint<Actions>( 29 + const worker = endpoint<Tasks>( 30 30 new SharedWorker(new URL("../../../scripts/input/native-fs/worker", import.meta.url), { 31 31 type: "module", 32 32 name: manifest.name, ··· 34 34 ); 35 35 36 36 // Register applet 37 - const context = register(); 37 + const context = register({ worker }); 38 38 39 39 //////////////////////////////////////////// 40 40 // ACTIONS
+3 -3
src/pages/input/opensubsonic/_applet.astro
··· 18 18 </main> 19 19 20 20 <script> 21 - import type { Actions } from "@scripts/input/opensubsonic/worker"; 21 + import type { Tasks } from "@scripts/input/opensubsonic/worker"; 22 22 import type { Track } from "@applets/core/types.d.ts"; 23 23 import { register } from "@scripts/applet/common"; 24 24 import { endpoint, inIframe, SharedWorker, transfer } from "@scripts/common"; ··· 27 27 //////////////////////////////////////////// 28 28 // SETUP 29 29 //////////////////////////////////////////// 30 - const worker = endpoint<Actions>( 30 + const worker = endpoint<Tasks>( 31 31 new SharedWorker(new URL("../../../scripts/input/opensubsonic/worker", import.meta.url), { 32 32 type: "module", 33 33 name: manifest.name, ··· 35 35 ); 36 36 37 37 // Register applet 38 - const context = register(); 38 + const context = register({ worker }); 39 39 40 40 //////////////////////////////////////////// 41 41 // ACTIONS
+3 -4
src/pages/input/s3/_applet.astro
··· 37 37 </style> 38 38 39 39 <script> 40 - import type { Actions } from "@scripts/input/s3/worker"; 41 - 40 + import type { Tasks } from "@scripts/input/s3/worker"; 42 41 import type { Track } from "@applets/core/types.d.ts"; 43 42 import { register } from "@scripts/applet/common"; 44 43 import { endpoint, inIframe, SharedWorker, transfer } from "@scripts/common"; ··· 47 46 //////////////////////////////////////////// 48 47 // SETUP 49 48 //////////////////////////////////////////// 50 - const worker = endpoint<Actions>( 49 + const worker = endpoint<Tasks>( 51 50 new SharedWorker(new URL("../../../scripts/input/s3/worker", import.meta.url), { 52 51 type: "module", 53 52 name: manifest.name, ··· 55 54 ); 56 55 57 56 // Register applet 58 - const context = register(); 57 + const context = register({ worker }); 59 58 60 59 //////////////////////////////////////////// 61 60 // ACTIONS
+9 -5
src/pages/orchestrator/input-cache/_applet.astro
··· 24 24 }; 25 25 26 26 // Start processing once settled and tracks are loaded 27 - // context 28 - // .settled() 29 - // .then(() => configurator.output) 30 - // .then((output) => wait(output, (d) => d?.tracks.state === "loaded")) 31 - // .then(() => (context.isMainInstance() ? process() : undefined)); 27 + context 28 + .settled() 29 + .then(() => configurator.output) 30 + .then((output) => wait(output, (d) => d?.tracks.state === "loaded")) 31 + .then(() => (context.isMainInstance() ? process() : undefined)); 32 32 33 33 //////////////////////////////////////////// 34 34 // ACTIONS ··· 47 47 48 48 await input.sendAction("contextualize", cachedTracks, { 49 49 timeoutDuration: 60000 * 5, 50 + worker: true, 50 51 }); 51 52 52 53 console.log("CONTEXTUALIZED"); 53 54 54 55 const tracks = await input.sendAction<Track[]>("list", cachedTracks, { 55 56 timeoutDuration: 60000 * 60 * 24, 57 + worker: true, 56 58 }); 57 59 58 60 console.log("LISTED", tracks); ··· 69 71 { method: "GET", uri: track.uri }, 70 72 { 71 73 timeoutDuration: 60000 * 5, 74 + worker: true, 72 75 }, 73 76 ); 74 77 ··· 77 80 { method: "HEAD", uri: track.uri }, 78 81 { 79 82 timeoutDuration: 60000 * 5, 83 + worker: true, 80 84 }, 81 85 ); 82 86
+1 -1
src/pages/orchestrator/queue-tracks/_applet.astro
··· 37 37 const groups = await configurator.input.sendAction<GroupConsult>( 38 38 "groupConsult", 39 39 configurator.output.data.tracks.collection, 40 - { timeoutDuration: 60000 * 5 }, 40 + { timeoutDuration: 60000 * 5, worker: true }, 41 41 ); 42 42 43 43 // Available tracks
+6 -4
src/scripts/applet/common.ts
··· 7 7 import QS from "query-string"; 8 8 9 9 import type { ResolvedUri } from "@applets/core/types"; 10 - import { transfer, type WorkerActions } from "@scripts/common"; 10 + import { transfer, type WorkerTasks } from "@scripts/common"; 11 11 12 12 //////////////////////////////////////////// 13 13 // 🪟 Applet connecting ··· 17 17 opts: { 18 18 addSlashSuffix?: boolean; 19 19 container?: HTMLElement | Element; 20 + context?: Window; 20 21 frameId?: string; 21 22 groupId?: string; 22 23 setHeight?: boolean; ··· 40 41 src = QS.stringifyUrl({ url: src, query }); 41 42 } 42 43 43 - const context = self.top || self.parent; 44 + const context = opts.context || self.top || self.parent; 44 45 const existingFrame: HTMLIFrameElement | null = context.document.querySelector(`[src="${src}"]`); 45 46 46 47 let frame; ··· 109 110 }; 110 111 111 112 export function register<DataType = any>( 112 - options: { worker?: Comlink.Remote<WorkerActions> } = {}, 113 + options: { worker?: Comlink.Remote<WorkerTasks> } = {}, 113 114 ): BroadcastedApplet<DataType> { 114 115 const url = new URL(location.href); 115 116 const scope = applets.register<DataType>(); ··· 288 289 if (options.worker !== undefined) 289 290 context.scope.onworkerport = (event) => { 290 291 if (!event.port) return; 291 - options.worker?.perform(transfer(event.port)); 292 + options.worker?.listenForActions(transfer(event.port)); 292 293 }; 293 294 294 295 return context; ··· 335 336 }, 336 337 { 337 338 timeoutDuration: 60000 * 5, 339 + worker: true, 338 340 }, 339 341 ); 340 342 }
+16 -10
src/scripts/common.ts
··· 12 12 // 🌳 13 13 //////////////////////////////////////////// 14 14 15 - export type WorkerActions = { 16 - perform: ReturnType<typeof handleWorkerActions>; 15 + export type WorkerTasks = { 16 + listenForActions: ReturnType<typeof handleWorkerActions>; 17 17 }; 18 18 19 19 //////////////////////////////////////////// ··· 59 59 return xxh32(JSON.stringify(value)); 60 60 } 61 61 62 - export function endpoint<T extends Record<string, any> = WorkerActions>(ini: Comlink.Endpoint) { 62 + export function endpoint<T extends Record<string, any> = WorkerTasks>(ini: Comlink.Endpoint) { 63 63 const e = Comlink.wrap<T>(ini); 64 64 if ("start" in ini && typeof ini.start === "function") ini.start(); 65 65 return e; 66 66 } 67 67 68 - export function expose<A extends Record<string, any>>(actions: A): A { 68 + export function expose<A extends Record<string, any>>(tasks: A): A { 69 69 if (globalThis.SharedWorkerGlobalScope && self instanceof SharedWorkerGlobalScope) { 70 70 self.onconnect = (event: MessageEvent) => { 71 71 const port = event.ports[0]; 72 - Comlink.expose(actions, port); 72 + Comlink.expose(tasks, port); 73 73 port.start(); 74 74 }; 75 75 76 76 (self as any).connected = true; 77 77 } else { 78 - Comlink.expose(actions, self); 78 + Comlink.expose(tasks, self); 79 79 } 80 80 81 - return actions; 81 + return tasks; 82 82 } 83 83 84 84 export function groupTracksPerScheme( ··· 107 107 return new TextEncoder().encode(JSON.stringify(a)); 108 108 } 109 109 110 - export function provide<A extends Record<string, any>>(actions: A) { 111 - return expose({ 112 - perform: handleWorkerActions(actions), 110 + export function provide<A extends Record<string, any>, B extends Record<string, any>>( 111 + actions: A, 112 + tasks: B = {} as B, 113 + ) { 114 + return expose<WorkerTasks & B>({ 115 + listenForActions: handleWorkerActions(actions), 116 + ...tasks, 113 117 }); 114 118 } 115 119 ··· 154 158 } 155 159 156 160 return (port: MessagePort) => { 161 + Comlink.expose(actions, port); 162 + 157 163 port.onmessage = async (message) => { 158 164 switch (message.data?.type) { 159 165 case "action":
+6
src/scripts/configurator/input/common.ts
··· 1 + import { CONNECTIONS } from "./constants"; 2 + import type { Scheme } from "./types"; 3 + 4 + export function isSupportedScheme(scheme: string): scheme is Scheme { 5 + return !!CONNECTIONS[scheme as Scheme]; 6 + }
+133 -8
src/scripts/configurator/input/worker.ts
··· 1 - import { expose, groupTracksPerScheme, transfer } from "@scripts/common"; 1 + import * as URI from "uri-js"; 2 + 3 + import type { 4 + Consult, 5 + ConsultGrouping, 6 + GroupConsult, 7 + InputWorkerTasks, 8 + Track, 9 + } from "@applets/core/types"; 10 + import type { Scheme } from "./types"; 2 11 import { CONNECTIONS } from "./constants"; 3 - import type { Track } from "@applets/core/types"; 12 + import { endpoint, groupTracksPerScheme, provide, transfer } from "@scripts/common"; 13 + import { isSupportedScheme } from "./common"; 14 + import type { Remote } from "comlink"; 15 + 16 + //////////////////////////////////////////// 17 + // TASKS 18 + //////////////////////////////////////////// 19 + const tasks = provide( 20 + { 21 + consult, 22 + contextualize, 23 + groupConsult, 24 + list, 25 + resolve, 26 + }, 27 + { 28 + manageInputWorker, 29 + }, 30 + ); 31 + 32 + export type Tasks = typeof tasks; 33 + 34 + //////////////////////////////////////////// 35 + // CONNECTIONS 36 + //////////////////////////////////////////// 37 + const connections: Record< 38 + Scheme, 39 + { 40 + promise: Promise<Remote<InputWorkerTasks>>; 41 + resolve: (value: Remote<InputWorkerTasks>) => void; 42 + reject: () => void; 43 + } 44 + > = { 45 + "file+local": Promise.withResolvers(), 46 + opensubsonic: Promise.withResolvers(), 47 + s3: Promise.withResolvers(), 48 + }; 49 + 50 + function manageInputWorker(scheme: Scheme, port: MessagePort) { 51 + // TODO: Not sure what happens here when it's already resolved. 52 + // I guess ideally the connections record should always 53 + // provide the latest incoming value from here. 54 + connections[scheme].resolve(endpoint<InputWorkerTasks>(port)); 55 + } 4 56 5 57 //////////////////////////////////////////// 6 58 // ACTIONS 7 59 //////////////////////////////////////////// 8 - const actions = expose({ 9 - groupTracks, 10 - }); 60 + 61 + async function consult(fileUriOrScheme: string): Promise<Consult> { 62 + const scheme = fileUriOrScheme.includes(":") 63 + ? URI.parse(fileUriOrScheme).scheme || fileUriOrScheme 64 + : fileUriOrScheme; 65 + 66 + if (!isSupportedScheme(scheme)) { 67 + return { supported: false, reason: "Unsupported scheme" }; 68 + } 69 + 70 + const conn = await connections[scheme].promise; 71 + return conn.consult(fileUriOrScheme); 72 + } 73 + 74 + async function contextualize(tracks: Track[]) { 75 + const groups = groupTracks(tracks); 76 + const promises = Object.entries(groups).map(async ([scheme, tracksGroup]: [string, Track[]]) => { 77 + if (!isSupportedScheme(scheme) || tracksGroup.length === 0) return; 78 + const conn = await connections[scheme].promise; 79 + await conn.contextualize(tracksGroup); 80 + }); 81 + 82 + await Promise.all(promises); 83 + } 84 + 85 + async function groupConsult(tracks: Track[]) { 86 + const groups = groupTracksPerScheme(tracks); 87 + 88 + const consultations: GroupConsult[] = await Promise.all( 89 + Object.keys(groups).map(async (scheme) => { 90 + if (!isSupportedScheme(scheme)) { 91 + return { 92 + [scheme]: { available: false, reason: "Unsupported scheme" }, 93 + }; 94 + } 95 + 96 + const conn = await connections[scheme].promise; 97 + const result = await conn.groupConsult(groups[scheme] || []); 11 98 12 - export type Actions = typeof actions; 99 + return result; 100 + }), 101 + ); 13 102 14 - // Actions 103 + return consultations.reduce((acc: GroupConsult, c: GroupConsult) => { 104 + return { ...acc, ...c }; 105 + }, {}); 106 + } 107 + 108 + async function list(cachedTracks: Track[] = []) { 109 + const groups = groupTracks(cachedTracks); 110 + 111 + const promises = Object.entries(groups).map( 112 + async ([scheme, cachedTracksGroup]: [string, Track[]]) => { 113 + if (!isSupportedScheme(scheme)) return cachedTracksGroup; 114 + const conn = await connections[scheme].promise; 115 + return conn.list(cachedTracksGroup); 116 + }, 117 + ); 118 + 119 + const nested = await Promise.all(promises); 120 + const tracks = nested.flat(1); 121 + 122 + return tracks; 123 + } 124 + 125 + async function resolve(args: { method: string; uri: string }) { 126 + const scheme = args.uri.split(":", 1)[0]; 127 + if (!isSupportedScheme(scheme)) return undefined; 128 + 129 + try { 130 + const conn = await connections[scheme].promise; 131 + return await conn.resolve(args); 132 + } catch (err) { 133 + console.error(`[configuration/input] Resolve error for scheme '${scheme}'.`, err); 134 + } 135 + } 136 + 137 + //////////////////////////////////////////// 138 + // 🛠️ 139 + //////////////////////////////////////////// 15 140 16 141 function groupTracks(tracks: Track[]) { 17 142 const grouped = groupTracksPerScheme( ··· 23 148 ), 24 149 ); 25 150 26 - return transfer(grouped); 151 + return grouped; 27 152 }
+8 -5
src/scripts/input/native-fs/worker.ts
··· 9 9 recursiveList, 10 10 trackHandleId, 11 11 } from "./common"; 12 - import { expose, transfer } from "@scripts/common"; 12 + import { expose, provide, transfer } from "@scripts/common"; 13 13 14 14 //////////////////////////////////////////// 15 - // ACTIONS 15 + // TASKS 16 16 //////////////////////////////////////////// 17 - const actions = expose({ 17 + const actions = { 18 18 consult, 19 19 contextualize, 20 20 groupConsult, 21 21 list, 22 22 resolve, 23 - }); 23 + }; 24 + 25 + const tasks = provide(actions, actions); 24 26 25 27 export type Actions = typeof actions; 28 + export type Tasks = typeof tasks; 26 29 27 - // Actions 30 + // Tasks 28 31 29 32 export async function consult(fileUriOrScheme: string): Promise<Consult> { 30 33 if (!self.FileSystemDirectoryHandle) {
+5 -2
src/scripts/input/opensubsonic/common.ts
··· 138 138 query: `tls=${server.tls ? "t" : "f"}`, 139 139 }; 140 140 141 - if (server.apiKey) return URI.serialize({ ...parts, userinfo: server.apiKey }); 142 - return URI.serialize({ ...parts, userinfo: `${server.username}:${server.password}` }); 141 + const uri = server.apiKey 142 + ? URI.serialize({ ...parts, userinfo: server.apiKey }) 143 + : URI.serialize({ ...parts, userinfo: `${server.username}:${server.password}` }); 144 + 145 + return btoa(uri); 143 146 }
+8 -5
src/scripts/input/opensubsonic/worker.ts
··· 14 14 serverId, 15 15 serversFromTracks, 16 16 } from "./common.ts"; 17 - import { expose, transfer } from "@scripts/common.ts"; 17 + import { expose, provide, transfer } from "@scripts/common.ts"; 18 18 19 19 //////////////////////////////////////////// 20 - // ACTIONS 20 + // TASKS 21 21 //////////////////////////////////////////// 22 - const actions = expose({ 22 + const actions = { 23 23 consult, 24 24 contextualize, 25 25 groupConsult, 26 26 list, 27 27 resolve, 28 - }); 28 + }; 29 + 30 + const tasks = provide(actions, actions); 29 31 30 32 export type Actions = typeof actions; 33 + export type Tasks = typeof tasks; 31 34 32 - // Actions 35 + // Tasks 33 36 34 37 async function consult(fileUriOrScheme: string): Promise<Consult> { 35 38 if (!fileUriOrScheme.includes(":")) return { supported: true, consult: "undetermined" };
+8 -5
src/scripts/input/s3/worker.ts
··· 10 10 loadBuckets, 11 11 parseURI, 12 12 } from "./common"; 13 - import { expose, transfer } from "@scripts/common"; 13 + import { expose, provide, transfer } from "@scripts/common"; 14 14 import { SCHEME } from "./constants"; 15 15 16 16 //////////////////////////////////////////// 17 - // ACTIONS 17 + // TASKS 18 18 //////////////////////////////////////////// 19 - const actions = expose({ 19 + const actions = { 20 20 consult, 21 21 contextualize, 22 22 groupConsult, 23 23 list, 24 24 resolve, 25 - }); 25 + }; 26 + 27 + const tasks = provide(actions, actions); 26 28 27 29 export type Actions = typeof actions; 30 + export type Tasks = typeof tasks; 28 31 29 - // Actions 32 + // Tasks 30 33 31 34 async function consult(fileUriOrScheme: string): Promise<Consult> { 32 35 if (!fileUriOrScheme.includes(":")) return { supported: true, consult: "undetermined" };