Experiment to rebuild Diffuse using web applets.
at main 2.6 kB view raw
1import * as Orama from "@orama/orama"; 2// import { pluginQPS } from "@orama/plugin-qps"; 3 4import type { Track } from "@applets/core/types"; 5import { expose, provide, 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 57const actions = { 58 search, 59 supply, 60}; 61 62const { tasks } = provide({ 63 actions, 64 tasks: actions, 65}); 66 67export type Actions = typeof actions; 68export type Tasks = typeof tasks; 69 70//////////////////////////////////////////// 71// ACTIONS 72//////////////////////////////////////////// 73 74async function search(term: string): Promise<Track[]> { 75 const results = await Orama.search(db, { 76 // mode: "hybrid", 77 term, 78 }); 79 80 const tracks = results.hits.map((hit) => hit.document as unknown as Track); 81 return transfer(tracks); 82} 83 84async function supply(tracks: Track[]) { 85 // TODO: Generate a hash based on the track itself, 86 // so we can detect changes to tags or other data. 87 88 const ids = []; 89 const tracksMap: Record<string, Track> = {}; 90 91 tracks.forEach((track) => { 92 ids.push(track.id); 93 tracksMap[track.id] = track; 94 }); 95 96 const currentSet = state.inserted; 97 const newSet = new Set(tracks.map((t) => t.id)); 98 99 const removedIds = currentSet.difference(newSet); 100 const newIds = newSet.difference(currentSet); 101 const newTracks = Array.from(newIds).map((id) => tracksMap[id]); 102 103 await Orama.removeMultiple(db, Array.from(removedIds)); 104 await Orama.insertMultiple(db, newTracks); 105 106 state.inserted = newSet; 107}