Experiment to rebuild Diffuse using web applets.
1import * as URI from "uri-js";
2
3import type { Consult, GroupConsult, InputWorkerTasks, Track } from "@applets/core/types";
4import { groupTracksPerScheme, initialConnections, provide } from "@scripts/common";
5
6////////////////////////////////////////////
7// SETUP
8////////////////////////////////////////////
9const actions = {
10 consult,
11 contextualize,
12 groupConsult,
13 list,
14 resolve,
15};
16
17const { connections, tasks } = provide({
18 actions,
19 connections: initialConnections<InputWorkerTasks>(["file+local", "opensubsonic", "s3"]),
20 tasks: actions,
21});
22
23export type Actions = typeof actions;
24export type Tasks = typeof tasks;
25
26function isSupportedScheme(scheme: string) {
27 return !!connections[scheme];
28}
29
30////////////////////////////////////////////
31// ACTIONS
32////////////////////////////////////////////
33
34async function consult(fileUriOrScheme: string): Promise<Consult> {
35 const scheme = fileUriOrScheme.includes(":")
36 ? URI.parse(fileUriOrScheme).scheme || fileUriOrScheme
37 : fileUriOrScheme;
38
39 if (!isSupportedScheme(scheme)) {
40 return { supported: false, reason: "Unsupported scheme" };
41 }
42
43 const conn = await connections[scheme].promise;
44 return conn.consult(fileUriOrScheme);
45}
46
47async function contextualize(tracks: Track[]) {
48 const groups = groupTracks(tracks);
49 const promises = Object.entries(groups).map(async ([scheme, tracksGroup]: [string, Track[]]) => {
50 if (!isSupportedScheme(scheme) || tracksGroup.length === 0) return;
51 const conn = await connections[scheme].promise;
52 await conn.contextualize(tracksGroup);
53 });
54
55 await Promise.all(promises);
56}
57
58async function groupConsult(tracks: Track[]) {
59 const groups = groupTracksPerScheme(tracks);
60
61 const consultations: GroupConsult[] = await Promise.all(
62 Object.keys(groups).map(async (scheme) => {
63 if (!isSupportedScheme(scheme)) {
64 return {
65 [scheme]: { available: false, reason: "Unsupported scheme" },
66 };
67 }
68
69 const conn = await connections[scheme].promise;
70 const result = await conn.groupConsult(groups[scheme] || []);
71
72 return result;
73 }),
74 );
75
76 return consultations.reduce((acc: GroupConsult, c: GroupConsult) => {
77 return { ...acc, ...c };
78 }, {});
79}
80
81async function list(cachedTracks: Track[] = []) {
82 const groups = groupTracks(cachedTracks);
83
84 const promises = Object.entries(groups).map(
85 async ([scheme, cachedTracksGroup]: [string, Track[]]) => {
86 if (!isSupportedScheme(scheme)) return cachedTracksGroup;
87 const conn = await connections[scheme].promise;
88 return conn.list(cachedTracksGroup);
89 },
90 );
91
92 const nested = await Promise.all(promises);
93 const tracks = nested.flat(1);
94
95 return tracks;
96}
97
98async function resolve(args: { method: string; uri: string }) {
99 const scheme = args.uri.split(":", 1)[0];
100 if (!isSupportedScheme(scheme)) return undefined;
101
102 try {
103 const conn = await connections[scheme].promise;
104 return await conn.resolve(args);
105 } catch (err) {
106 console.error(`[configuration/input] Resolve error for scheme '${scheme}'.`, err);
107 }
108}
109
110////////////////////////////////////////////
111// 🛠️
112////////////////////////////////////////////
113
114function groupTracks(tracks: Track[]) {
115 const grouped = groupTracksPerScheme(
116 tracks,
117 Object.fromEntries(
118 Object.entries(connections).map(([k, _v]) => {
119 return [k, []];
120 }),
121 ),
122 );
123
124 return grouped;
125}