Experiment to rebuild Diffuse using web applets.
1import * as Orama from "@orama/orama";
2// import { pluginQPS } from "@orama/plugin-qps";
3
4import type { Track } from "@applets/core/types";
5import { expose, transfer } from "@scripts/common";
6import { SCHEMA } from "./constants";
7import type { State } from "./types";
8
9////////////////////////////////////////////
10// SETUP
11////////////////////////////////////////////
12
13let state: State = {
14 inserted: new Set<string>(),
15};
16
17// TODO: Generate embeddings plugin
18//
19// I tried this and getting some bundler/vite errors about a default import.
20//
21// const plugin = await pluginEmbeddings({
22// embeddings: {
23// defaultProperty: "embeddings",
24// onInsert: {
25// generate: true,
26// // Properties to use for generating embeddings at insert time.
27// // These properties will be concatenated and used to generate embeddings.
28// properties: ["album", "artist", "title", "year", "kind", "genre"],
29// // verbose: true,
30// },
31// },
32// });
33//
34// TODO:
35//
36// Does not work either.
37// `TypeError: a is undefined`
38//
39// pluginQPS()
40
41const PLUGINS: Orama.OramaPlugin[] = [];
42
43// Search through tracks
44const db = Orama.create({
45 schema: SCHEMA,
46 plugins: PLUGINS,
47
48 // components: {
49 // TODO:
50 // https://docs.orama.com/open-source/usage/insert#remote-document-storing
51 // documentStore: { ... }
52 // },
53});
54
55////////////////////////////////////////////
56// ACTIONS
57////////////////////////////////////////////
58const actions = expose({
59 search,
60 supply,
61});
62
63export type Actions = typeof actions;
64
65// Actions
66
67async function search(term: string): Promise<Track[]> {
68 const results = await Orama.search(db, {
69 // mode: "hybrid",
70 term,
71 });
72
73 const tracks = results.hits.map((hit) => hit.document as unknown as Track);
74 return transfer(tracks);
75}
76
77async function supply(tracks: Track[]) {
78 // TODO: Generate a hash based on the track itself,
79 // so we can detect changes to tags or other data.
80
81 const ids = [];
82 const tracksMap: Record<string, Track> = {};
83
84 tracks.forEach((track) => {
85 ids.push(track.id);
86 tracksMap[track.id] = track;
87 });
88
89 const currentSet = state.inserted;
90 const newSet = new Set(tracks.map((t) => t.id));
91
92 const removedIds = currentSet.difference(newSet);
93 const newIds = newSet.difference(currentSet);
94 const newTracks = Array.from(newIds).map((id) => tracksMap[id]);
95
96 await Orama.removeMultiple(db, Array.from(removedIds));
97 await Orama.insertMultiple(db, newTracks);
98
99 state.inserted = newSet;
100}