Experiment to rebuild Diffuse using web applets.
0
fork

Configure Feed

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

feat: make use of transferables in the connection between applets and their workers

+75 -62
+3 -3
src/pages/configurator/input/_applet.astro
··· 40 40 import type { Scheme } from "@scripts/configurator/input/types"; 41 41 import { CONNECTIONS } from "@scripts/configurator/input/constants"; 42 42 import { applet, register } from "@scripts/applet/common"; 43 - import { endpoint, groupTracksPerScheme } from "@scripts/common"; 43 + import { endpoint, groupTracksPerScheme, transfer } from "@scripts/common"; 44 44 45 45 //////////////////////////////////////////// 46 46 // SETUP ··· 91 91 }; 92 92 93 93 const contextualize = async (tracks: Track[]) => { 94 - const groups = await worker.groupTracks(tracks); 94 + const groups = await worker.groupTracks(transfer(tracks)); 95 95 const promises = Object.entries(groups).map( 96 96 async ([scheme, tracksGroup]: [string, Track[]]) => { 97 97 if (!isSupportedScheme(scheme) || tracksGroup.length === 0) return; ··· 124 124 }; 125 125 126 126 const list = async (cachedTracks: Track[] = []) => { 127 - const groups = await worker.groupTracks(cachedTracks); 127 + const groups = await worker.groupTracks(transfer(cachedTracks)); 128 128 129 129 const promises = Object.entries(groups).map( 130 130 async ([scheme, cachedTracksGroup]: [string, Track[]]) => {
+5 -5
src/pages/engine/queue/_applet.astro
··· 4 4 import type { State } from "./types.d.ts"; 5 5 6 6 import { register } from "@scripts/applet/common"; 7 - import { endpoint, SharedWorker } from "@scripts/common"; 7 + import { endpoint, SharedWorker, transfer } from "@scripts/common"; 8 8 9 9 //////////////////////////////////////////// 10 10 // SETUP ··· 34 34 context.setActionHandler("unshift", unshift); 35 35 36 36 async function add(items: Track[]) { 37 - context.data = await worker.add(context.data, items); 37 + context.data = await worker.add(transfer(context.data), transfer(items)); 38 38 } 39 39 40 40 async function pool(items: Track[]) { 41 - context.data = await worker.pool(context.data, items); 41 + context.data = await worker.pool(transfer(context.data), transfer(items)); 42 42 } 43 43 44 44 async function shift() { 45 - context.data = await worker.shift(context.data); 45 + context.data = await worker.shift(transfer(context.data)); 46 46 } 47 47 48 48 async function unshift() { 49 - context.data = await worker.unshift(context.data); 49 + context.data = await worker.unshift(transfer(context.data)); 50 50 } 51 51 </script>
+4 -4
src/pages/input/native-fs/_applet.astro
··· 19 19 import type { Actions } 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 - import { endpoint, inIframe, SharedWorker } from "@scripts/common"; 22 + import { endpoint, inIframe, SharedWorker, transfer } from "@scripts/common"; 23 23 import * as Mounting from "@scripts/input/native-fs/mounting"; 24 24 25 25 //////////////////////////////////////////// ··· 42 42 }; 43 43 44 44 const contextualize = async (cachedTracks: Track[]) => { 45 - return await worker.contextualize(cachedTracks); 45 + return await worker.contextualize(transfer(cachedTracks)); 46 46 }; 47 47 48 48 const groupConsult = async (tracks: Track[]) => { 49 - return await worker.groupConsult(tracks); 49 + return await worker.groupConsult(transfer(tracks)); 50 50 }; 51 51 52 52 const list = async (cachedTracks: Track[] = []) => { 53 - return await worker.list(cachedTracks); 53 + return await worker.list(transfer(cachedTracks)); 54 54 }; 55 55 56 56 const resolve = async (args: { uri: string }) => {
+4 -4
src/pages/input/opensubsonic/_applet.astro
··· 21 21 import type { Actions } 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 - import { endpoint, inIframe, SharedWorker } from "@scripts/common"; 24 + import { endpoint, inIframe, SharedWorker, transfer } from "@scripts/common"; 25 25 26 26 //////////////////////////////////////////// 27 27 // SETUP ··· 43 43 }; 44 44 45 45 const contextualize = async (tracks: Track[]) => { 46 - const s = await worker.contextualize(tracks); 46 + const s = await worker.contextualize(transfer(tracks)); 47 47 ui?.setServers({ ...ui?.servers(), ...s }); 48 48 }; 49 49 50 50 const groupConsult = async (tracks: Track[]) => { 51 - return await worker.groupConsult(tracks); 51 + return await worker.groupConsult(transfer(tracks)); 52 52 }; 53 53 54 54 const list = async (cachedTracks: Track[] = []) => { 55 - return await worker.list(cachedTracks); 55 + return await worker.list(transfer(cachedTracks)); 56 56 }; 57 57 58 58 const resolve = async (args: { method: string; uri: string }) => {
+4 -4
src/pages/input/s3/_applet.astro
··· 41 41 42 42 import type { Track } from "@applets/core/types.d.ts"; 43 43 import { register } from "@scripts/applet/common"; 44 - import { endpoint, inIframe, SharedWorker } from "@scripts/common"; 44 + import { endpoint, inIframe, SharedWorker, transfer } from "@scripts/common"; 45 45 46 46 //////////////////////////////////////////// 47 47 // SETUP ··· 63 63 }; 64 64 65 65 const contextualize = async (tracks: Track[]) => { 66 - const s = await worker.contextualize(tracks); 66 + const s = await worker.contextualize(transfer(tracks)); 67 67 ui?.setBuckets({ ...ui?.buckets(), ...s }); 68 68 }; 69 69 70 70 const groupConsult = async (tracks: Track[]) => { 71 - return await worker.groupConsult(tracks); 71 + return await worker.groupConsult(transfer(tracks)); 72 72 }; 73 73 74 74 const list = async (cachedTracks: Track[] = []) => { 75 - return await worker.list(cachedTracks); 75 + return await worker.list(transfer(cachedTracks)); 76 76 }; 77 77 78 78 const resolve = async (args: { method: string; uri: string }) => {
+2 -2
src/pages/output/indexed-db/_applet.astro
··· 2 2 import type { Actions } from "@scripts/output/indexed-db/worker"; 3 3 import type { ManagedOutput, Track } from "@applets/core/types.d.ts"; 4 4 import { register } from "@scripts/applet/common"; 5 - import { SharedWorker, endpoint } from "@scripts/common"; 5 + import { SharedWorker, endpoint, transfer } from "@scripts/common"; 6 6 import { INITIAL_MANAGED_OUTPUT, outputManager } from "@scripts/output/common"; 7 7 8 8 //////////////////////////////////////////// ··· 29 29 }, 30 30 31 31 async put(tracks: Track[]) { 32 - return worker.putTracks(tracks); 32 + return worker.putTracks(transfer(tracks)); 33 33 }, 34 34 }, 35 35 });
+2 -2
src/pages/output/native-fs/_applet.astro
··· 6 6 import type { ManagedOutput, Track } from "@applets/core/types"; 7 7 import { register } from "@scripts/applet/common"; 8 8 import { INITIAL_MANAGED_OUTPUT, outputManager } from "@scripts/output/common"; 9 - import { endpoint, SharedWorker } from "@scripts/common"; 9 + import { endpoint, SharedWorker, transfer } from "@scripts/common"; 10 10 import { IDB_DEVICE_KEY } from "@scripts/output/native-fs/constants"; 11 11 12 12 //////////////////////////////////////////// ··· 38 38 }, 39 39 40 40 async put(tracks: Track[]) { 41 - return worker.putTracks(tracks); 41 + return worker.putTracks(transfer(tracks)); 42 42 }, 43 43 }, 44 44 });
+3 -2
src/pages/processor/artwork/_applet.astro
··· 3 3 import type { ArtworkRequest } from "./types.d.ts"; 4 4 import { register } from "@scripts/applet/common"; 5 5 import { endpoint, SharedWorker } from "@scripts/common"; 6 + import { transfer } from "@scripts/common"; 6 7 7 8 //////////////////////////////////////////// 8 9 // SETUP ··· 20 21 // ACTIONS 21 22 //////////////////////////////////////////// 22 23 function artwork(request: ArtworkRequest) { 23 - return worker.artwork(request); 24 + return worker.artwork(transfer(request)); 24 25 } 25 26 26 27 function supply(items: ArtworkRequest[]) { 27 - return worker.supply(items); 28 + return worker.supply(transfer(items)); 28 29 } 29 30 30 31 context.setActionHandler("artwork", artwork);
+4 -3
src/pages/processor/metadata/_applet.astro
··· 1 1 <script> 2 2 import type { Actions } from "@scripts/processor/metadata/worker"; 3 3 import { register } from "@scripts/applet/common"; 4 - import { endpoint, SharedWorker } from "@scripts/common"; 4 + import { endpoint, SharedWorker, transfer } from "@scripts/common"; 5 5 6 6 //////////////////////////////////////////// 7 7 // SETUP ··· 18 18 //////////////////////////////////////////// 19 19 // ACTIONS 20 20 //////////////////////////////////////////// 21 - const supply: Actions["supply"] = (...args: Parameters<Actions["supply"]>) => { 22 - return worker.supply(...args); 21 + const supply: Actions["supply"] = (args: Parameters<Actions["supply"]>[0]) => { 22 + const transferredArgs = transfer(args); 23 + return worker.supply(transferredArgs); 23 24 }; 24 25 25 26 context.setActionHandler("supply", supply);
+2 -2
src/pages/processor/search/_applet.astro
··· 2 2 import type { Actions } from "@scripts/processor/search/worker"; 3 3 import type { Track } from "@applets/core/types"; 4 4 import { register } from "@scripts/applet/common"; 5 - import { endpoint } from "@scripts/common"; 5 + import { endpoint, transfer } from "@scripts/common"; 6 6 7 7 //////////////////////////////////////////// 8 8 // SETUP ··· 27 27 } 28 28 29 29 async function supply(tracks: Track[]) { 30 - return worker.supply(tracks); 30 + return worker.supply(transfer(tracks)); 31 31 } 32 32 </script>
+4 -2
src/scripts/configurator/input/worker.ts
··· 1 - import { expose, groupTracksPerScheme } from "@scripts/common"; 1 + import { expose, groupTracksPerScheme, transfer } from "@scripts/common"; 2 2 import { CONNECTIONS } from "./constants"; 3 3 import type { Track } from "@applets/core/types"; 4 4 ··· 14 14 // Actions 15 15 16 16 function groupTracks(tracks: Track[]) { 17 - return groupTracksPerScheme( 17 + const grouped = groupTracksPerScheme( 18 18 tracks, 19 19 Object.fromEntries( 20 20 Object.entries(CONNECTIONS).map(([k, _v]) => { ··· 22 22 }), 23 23 ), 24 24 ); 25 + 26 + return transfer(grouped); 25 27 }
+6 -5
src/scripts/engine/queue/worker.ts
··· 1 1 import type { Track } from "@applets/core/types.js"; 2 2 import type { State } from "./types"; 3 - import { expose } from "@scripts/common.ts"; 3 + import { expose, transfer } from "@scripts/common.ts"; 4 4 5 5 //////////////////////////////////////////// 6 6 // STATE ··· 27 27 // Actions 28 28 29 29 function add(state: State, items: Track[]): State { 30 - return { ...state, future: [...state.future, ...items] }; 30 + return transfer({ ...state, future: [...state.future, ...items] }); 31 31 } 32 32 33 33 function pool(state: State, tracks: Track[]): State { ··· 42 42 43 43 // Automatically insert track if there isn't any 44 44 if (!state.now) return shift(state); 45 - return state; 45 + return transfer(state); 46 46 } 47 47 48 48 function shift(state: State): State { 49 49 const now = state.future[0] || null; 50 50 const future = state.future.slice(1); 51 51 const past = state.now ? [...state.past, state.now] : state.past; 52 + const filled = fill({ past, now, future }); 52 53 53 - return fill({ past, now, future }); 54 + return transfer(filled); 54 55 } 55 56 56 57 function unshift(state: State): State { ··· 61 62 const now = last ?? null; 62 63 const future = state.now ? [state.now, ...state.future] : state.future; 63 64 64 - return { past, now, future }; 65 + return transfer({ past, now, future }); 65 66 } 66 67 67 68 // 🛠️
+5 -3
src/scripts/input/native-fs/worker.ts
··· 9 9 recursiveList, 10 10 trackHandleId, 11 11 } from "./common"; 12 - import { expose } from "@scripts/common"; 12 + import { expose, transfer } from "@scripts/common"; 13 13 14 14 //////////////////////////////////////////// 15 15 // ACTIONS ··· 61 61 }); 62 62 63 63 const entries = (await Promise.all(promises)).map((entry) => [entry.key, entry.grouping]); 64 - return Object.fromEntries(entries); 64 + const obj = Object.fromEntries(entries); 65 + 66 + return transfer(obj); 65 67 } 66 68 67 69 export async function list(cachedTracks: Track[] = []) { ··· 108 110 }); 109 111 110 112 // Fin 111 - return data; 113 + return transfer(data); 112 114 } 113 115 114 116 export async function resolve(args: { uri: string }) {
+6 -5
src/scripts/input/opensubsonic/worker.ts
··· 15 15 serverId, 16 16 serversFromTracks, 17 17 } from "./common.ts"; 18 - import { expose } from "../../../scripts/common.ts"; 18 + import { expose, transfer } from "@scripts/common.ts"; 19 19 20 20 //////////////////////////////////////////// 21 21 // ACTIONS ··· 62 62 }); 63 63 64 64 const entries = (await Promise.all(promises)).map((entry) => [entry.key, entry.grouping]); 65 - return Object.fromEntries(entries); 65 + const obj = Object.fromEntries(entries); 66 + 67 + return transfer(obj); 66 68 } 67 69 68 70 async function list(cachedTracks: Track[] = []) { ··· 76 78 return { ...acc, [bid]: acc[bid] ? { ...acc[bid], ...trk } : trk }; 77 79 }, {}); 78 80 79 - // TODO 80 - 81 81 async function search(client: SubsonicAPI, offset = 0): Promise<Child[]> { 82 82 const result = await client.search3({ 83 83 query: "", ··· 131 131 }); 132 132 }); 133 133 134 - return (await Promise.all(promises)).flat(1); 134 + const tracks = (await Promise.all(promises)).flat(1); 135 + return transfer(tracks); 135 136 } 136 137 137 138 async function resolve({ uri }: { method: string; uri: string }) {
+6 -5
src/scripts/input/s3/worker.ts
··· 1 - import * as URI from "uri-js"; 2 - 3 1 import type { Consult, ConsultGrouping, GroupConsult, Track } from "@applets/core/types.d.ts"; 4 2 import { isAudioFile } from "@scripts/input/common"; 5 3 import { ··· 12 10 loadBuckets, 13 11 parseURI, 14 12 } from "./common"; 15 - import { expose } from "@scripts/common"; 13 + import { expose, transfer } from "@scripts/common"; 16 14 import { SCHEME } from "./constants"; 17 15 18 16 //////////////////////////////////////////// ··· 60 58 }); 61 59 62 60 const entries = (await Promise.all(promises)).map((entry) => [entry.key, entry.grouping]); 63 - return Object.fromEntries(entries); 61 + const obj = Object.fromEntries(entries); 62 + 63 + return transfer(obj); 64 64 } 65 65 66 66 async function list(cachedTracks: Track[] = []) { ··· 105 105 }); 106 106 }); 107 107 108 - return (await Promise.all(promises)).flat(1); 108 + const tracks = (await Promise.all(promises)).flat(1); 109 + return transfer(tracks); 109 110 } 110 111 111 112 async function resolve({ method, uri }: { method: string; uri: string }) {
+3 -2
src/scripts/output/indexed-db/worker.ts
··· 1 1 import * as IDB from "idb-keyval"; 2 2 3 - import { expose, jsonDecode, jsonEncode } from "@scripts/common"; 3 + import { expose, jsonDecode, jsonEncode, transfer } from "@scripts/common"; 4 4 import type { Track } from "@applets/core/types"; 5 5 import { IDB_PREFIX } from "./constants"; 6 6 ··· 19 19 async function getTracks() { 20 20 const encoded = await get({ name: "tracks.json" }); 21 21 if (!encoded) return []; 22 - return jsonDecode<Track[]>(encoded); 22 + const tracks = jsonDecode<Track[]>(encoded); 23 + return transfer(tracks); 23 24 } 24 25 25 26 async function putTracks(tracks: Track[]) {
+3 -2
src/scripts/output/native-fs/worker.ts
··· 1 1 import * as IDB from "idb-keyval"; 2 2 3 - import { expose, jsonDecode, jsonEncode } from "@scripts/common"; 3 + import { expose, jsonDecode, jsonEncode, transfer } from "@scripts/common"; 4 4 import type { Track } from "@applets/core/types"; 5 5 import { IDB_DEVICE_KEY, IDB_PREFIX } from "./constants"; 6 6 ··· 19 19 async function getTracks() { 20 20 const encoded = await get({ name: "tracks.json" }); 21 21 if (!encoded) return []; 22 - return jsonDecode<Track[]>(encoded); 22 + const tracks = jsonDecode<Track[]>(encoded); 23 + return transfer(tracks); 23 24 } 24 25 25 26 async function putTracks(tracks: Track[]) {
+4 -3
src/scripts/processor/artwork/worker.ts
··· 2 2 import * as IDB from "idb-keyval"; 3 3 4 4 import type { Artwork, ArtworkRequest } from "./types"; 5 - import { expose } from "@scripts/common"; 5 + import { expose, transfer } from "@scripts/common"; 6 6 import { IDB_ARTWORK_PREFIX } from "./constants"; 7 7 import { musicMetadataTags } from "../metadata/common"; 8 8 ··· 21 21 22 22 // Actions 23 23 24 - function artwork(request: ArtworkRequest) { 24 + async function artwork(request: ArtworkRequest) { 25 25 console.log("INSERT REQ", request); 26 - return processRequest(request); 26 + const art = await processRequest(request); 27 + return transfer(art); 27 28 } 28 29 29 30 function supply(items: ArtworkRequest[]) {
+2 -2
src/scripts/processor/metadata/worker.ts
··· 1 1 import type { Extraction, Urls } from "./types.d.ts"; 2 - import { expose } from "@scripts/common"; 2 + import { expose, transfer } from "@scripts/common"; 3 3 import { musicMetadataTags } from "./common.ts"; 4 4 5 5 //////////////////////////////////////////// ··· 29 29 }); 30 30 31 31 // Fin 32 - return response; 32 + return transfer(response); 33 33 }
+3 -2
src/scripts/processor/search/worker.ts
··· 2 2 // import { pluginQPS } from "@orama/plugin-qps"; 3 3 4 4 import type { Track } from "@applets/core/types"; 5 - import { expose } from "@scripts/common"; 5 + import { expose, transfer } from "@scripts/common"; 6 6 import { SCHEMA } from "./constants"; 7 7 import type { State } from "./types"; 8 8 ··· 70 70 term, 71 71 }); 72 72 73 - return results.hits.map((hit) => hit.document as unknown as Track); 73 + const tracks = results.hits.map((hit) => hit.document as unknown as Track); 74 + return transfer(tracks); 74 75 } 75 76 76 77 async function supply(tracks: Track[]) {