soulseek, extracted into plugins/soulseek — the platform half
Seventh extraction, and the first of something that was already dead. Soulseek had been switched off since 2026-08-13: hono.ts carried the router import and its PROTECTED_MOUNTS entry commented out, so createSidecarProxy never ran and registerProxiedPrefix was never called; officer-slskd was not in the ecosystem at all. Because the permission entry had been reduced to api: [], the totality check was satisfied and the server booted clean — the UI rendered and every request 404'd. Worth naming: the boot check proves every MOUNTED prefix has a permission, and is silent about a feature that mounts nothing. Also closes a live data hazard: schema.ts had the soulseek export commented out, so the three tables were absent from the drizzle barrel and bun db:push would have dropped soulseek_favorites, soulseek_browse_snapshots and soulseek_browse_dirs on any server holding them. rebuild-soulseek-tree.ts documented the workaround rather than the problem; deleted with the rest. The connection stays in core service_connections under service 'slskd' while the mount is now /api/soulseek. Those differ on purpose. Test fixtures: slskd was canonical in three app-store tests, the third extraction running to break them. installer.test.ts now builds a literal fixture instead of reaching into the catalogue — it pins planSteps, which is installer logic, and no catalogue entry is both provisioned and members:'none' any more. catalogue.test.ts and members.test.ts re-anchored to vnc/notify/gitea. Unrelated but mine: check:theme caught 5 palette classes I introduced in CommandHQ earlier tonight against a baseline of 0. Converted to bg-success / bg-warning. check:theme is not part of bun test, which is why the green suite never showed it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,52 +0,0 @@
|
||||
// Re-derive the stored tree shape for every cached share snapshot, from the folder rows already in
|
||||
// Postgres — no peer contact, so it works with everyone offline and is deterministic.
|
||||
//
|
||||
// Written for the backfill when the tree columns were added, but kept because it's the answer to any
|
||||
// future change in tree shape: it runs the SAME buildTree + finishSoulseekBrowse the sidecar's ingest
|
||||
// runs, so there's no second implementation to drift.
|
||||
//
|
||||
// bun scripts/rebuild-soulseek-tree.ts
|
||||
|
||||
import type { BrowsedFile } from 'officerdb';
|
||||
import { eq, asc } from 'drizzle-orm';
|
||||
import { db, finishSoulseekBrowse } from 'officerdb';
|
||||
// soulseek is a plugin, so its tables are commented out of officerdb's schema aggregator —
|
||||
// import them from the feature directly.
|
||||
import { soulseekBrowseSnapshots, soulseekBrowseDirs } from 'officerdb/soulseek/schema';
|
||||
import { buildTree } from '../src/servers/sidecar/slskd/browse';
|
||||
|
||||
const snapshots = await db
|
||||
.select({
|
||||
id: soulseekBrowseSnapshots.id,
|
||||
userId: soulseekBrowseSnapshots.userId,
|
||||
username: soulseekBrowseSnapshots.username,
|
||||
status: soulseekBrowseSnapshots.status,
|
||||
})
|
||||
.from(soulseekBrowseSnapshots)
|
||||
.orderBy(asc(soulseekBrowseSnapshots.id));
|
||||
|
||||
console.log(`${snapshots.length} snapshot(s) to rebuild`);
|
||||
|
||||
for (const snap of snapshots) {
|
||||
const started = Date.now();
|
||||
const rows = await db
|
||||
.select({ name: soulseekBrowseDirs.name, files: soulseekBrowseDirs.files })
|
||||
.from(soulseekBrowseDirs)
|
||||
.where(eq(soulseekBrowseDirs.snapshotId, snap.id));
|
||||
|
||||
if (!rows.length) {
|
||||
console.log(` #${snap.id} ${snap.username}: no folder rows, skipped`);
|
||||
continue;
|
||||
}
|
||||
|
||||
const tree = buildTree(rows.map((r) => ({ name: r.name, files: r.files as BrowsedFile[] })));
|
||||
await finishSoulseekBrowse(snap.id, tree);
|
||||
const roots = tree.filter((t) => t.parentPath === null);
|
||||
console.log(
|
||||
` #${snap.id} ${snap.username}: ${rows.length} -> ${tree.length} rows ` +
|
||||
`(+${tree.length - rows.length} synthesized), ${roots.length} root(s), ` +
|
||||
`${roots.reduce((n, r) => n + r.subtreeFileCount, 0)} files, ${Date.now() - started}ms`,
|
||||
);
|
||||
}
|
||||
|
||||
process.exit(0);
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"src/apps/officer-web/Screens": 144,
|
||||
"src/apps/officer-web/Screens": 122,
|
||||
"src/workspaces/components": 47,
|
||||
"src/workspaces/officerdev/src/apps/AppStore": 6,
|
||||
"src/workspaces/officerdev/src/apps/Chat": 12,
|
||||
@@ -11,13 +11,9 @@
|
||||
"src/workspaces/officerdev/src/apps/FileViewer": 38,
|
||||
"src/workspaces/officerdev/src/apps/Invoices": 95,
|
||||
"src/workspaces/officerdev/src/apps/Jellyfin": 48,
|
||||
"src/workspaces/officerdev/src/apps/Photos": 47,
|
||||
"src/workspaces/officerdev/src/apps/Preview": 4,
|
||||
"src/workspaces/officerdev/src/apps/QrTransfer": 5,
|
||||
"src/workspaces/officerdev/src/apps/Soulseek": 313,
|
||||
"src/workspaces/officerdev/src/apps/SystemMonitor": 1,
|
||||
"src/workspaces/officerdev/src/apps/Terminal": 10,
|
||||
"src/workspaces/officerdev/src/apps/Transmission": 43,
|
||||
"src/workspaces/officerdev/src/apps/Wallet": 68,
|
||||
"src/workspaces/officerdev/src/components": 22
|
||||
"src/workspaces/officerdev/src/apps/Wallet": 68
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user