37 lines
1.3 KiB
TypeScript
37 lines
1.3 KiB
TypeScript
|
|
/**
|
||
|
|
* Bob — receiver. Boots a Shade runtime and mounts the transfer route on
|
||
|
|
* port 9992. Incoming uploads are decrypted, integrity-checked, and saved
|
||
|
|
* to ./received/<filename>.
|
||
|
|
*/
|
||
|
|
import { mkdirSync } from 'node:fs';
|
||
|
|
import { join } from 'node:path';
|
||
|
|
import { createShade } from '@shade/sdk';
|
||
|
|
|
||
|
|
const PREKEY_URL = 'http://localhost:9991';
|
||
|
|
const PORT = 9992;
|
||
|
|
const OUT_DIR = join(import.meta.dir, 'received');
|
||
|
|
mkdirSync(OUT_DIR, { recursive: true });
|
||
|
|
|
||
|
|
const bob = await createShade({ prekeyServer: PREKEY_URL, address: 'bob' });
|
||
|
|
|
||
|
|
bob.configureTransfers({
|
||
|
|
resolveBaseUrl: async () => {
|
||
|
|
throw new Error('bob is receive-only');
|
||
|
|
},
|
||
|
|
});
|
||
|
|
|
||
|
|
bob.onIncomingTransfer(async (incoming) => {
|
||
|
|
const name = incoming.metadata.name ?? incoming.streamId;
|
||
|
|
const path = join(OUT_DIR, name.replace(/[^a-zA-Z0-9._-]/g, '_'));
|
||
|
|
console.log(`[bob] incoming "${name}" from ${incoming.from} → ${path}`);
|
||
|
|
const handle = await incoming.accept({ output: { kind: 'file', path } });
|
||
|
|
void handle.done().then((result) => {
|
||
|
|
console.log(`[bob] done "${name}" — ${result.bytesSent} B, sha256=${result.sha256}`);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
const app = await bob.transferRoute();
|
||
|
|
Bun.serve({ port: PORT, fetch: app.fetch });
|
||
|
|
console.log(`Bob's transfer endpoint listening on http://localhost:${PORT}`);
|
||
|
|
console.log(`Saving incoming files to ${OUT_DIR}`);
|