Enhets- og e2e-testene kjører mot Hono-fetch i prosess. Dette skriptet går mot en faktisk lyttende tjeneste — container eller deployet instans — og er det som fanget at Dockerfilen pekte på src/standalone.ts i en publisert pakke som bare shipper dist/. SCAFFOLDD_SOCKET=... RELAY=https://vault.zyon.no bun live-e2e.ts Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
75 lines
2.5 KiB
TypeScript
75 lines
2.5 KiB
TypeScript
/**
|
|
* Full backup mot en KJØRENDE vault — ikke Hono-fetch, men ekte HTTP.
|
|
*
|
|
* Kjøres manuelt mot en container eller en deployet tjeneste:
|
|
* SCAFFOLDD_SOCKET=... RELAY=https://vault.zyon.no bun live-e2e.ts
|
|
*/
|
|
import { connect } from 'node:net';
|
|
import { readFile } from 'node:fs/promises';
|
|
import { SubtleCryptoProvider } from '@shade/crypto-web';
|
|
import { HttpVaultTransport, VaultClient, deriveVaultKeys } from './src/index.js';
|
|
|
|
const SOCKET = process.env.SCAFFOLDD_SOCKET!;
|
|
const RELAY = process.env.RELAY!;
|
|
|
|
function ask(req: object): Promise<any> {
|
|
return new Promise((res, rej) => {
|
|
const s = connect(SOCKET);
|
|
let buf = '';
|
|
s.on('connect', () => s.write(`${JSON.stringify(req)}\n`));
|
|
s.on('data', (c) => {
|
|
buf += c.toString();
|
|
const nl = buf.indexOf('\n');
|
|
if (nl === -1) return;
|
|
s.destroy();
|
|
const r = JSON.parse(buf.slice(0, nl));
|
|
r.ok ? res(r.result) : rej(new Error(r.error));
|
|
});
|
|
s.on('error', rej);
|
|
});
|
|
}
|
|
|
|
const set = await ask({ op: 'backupSet' });
|
|
const files: { path: string; bytes: Uint8Array }[] = [];
|
|
for (const f of set.files) {
|
|
try {
|
|
files.push({ path: f.path, bytes: new Uint8Array(await readFile(f.source)) });
|
|
} catch {
|
|
/* uleselig fil hoppes over, som i broen */
|
|
}
|
|
}
|
|
|
|
const crypto = new SubtleCryptoProvider();
|
|
const keys = await deriveVaultKeys(new Uint8Array(32).fill(77), 'scaffold-live');
|
|
const client = new VaultClient(crypto, keys, new HttpVaultTransport(RELAY));
|
|
|
|
console.log(`push: ${files.length} filer …`);
|
|
let t = Date.now();
|
|
const r1 = await client.push(files, Date.now(), 'live e2e');
|
|
console.log(
|
|
` versjon ${r1.seq}: ${r1.uploaded} opplastet, ` +
|
|
`${(r1.bytesUploaded / 1024 / 1024).toFixed(1)} MB, ${((Date.now() - t) / 1000).toFixed(1)}s`,
|
|
);
|
|
|
|
const edited = files.map((f, i) =>
|
|
i === 0 ? { path: f.path, bytes: new TextEncoder().encode('endret') } : f,
|
|
);
|
|
t = Date.now();
|
|
const r2 = await client.push(edited, Date.now(), 'én endring');
|
|
console.log(
|
|
` versjon ${r2.seq}: ${r2.uploaded} opplastet, ${r2.reused} gjenbrukt, ` +
|
|
`${(r2.bytesUploaded / 1024).toFixed(0)} KB, ${((Date.now() - t) / 1000).toFixed(1)}s`,
|
|
);
|
|
|
|
const back = await client.pull(1);
|
|
let identical = 0;
|
|
let differ = 0;
|
|
for (const f of files) {
|
|
const got = back.files.get(f.path);
|
|
if (got && Buffer.from(got).equals(Buffer.from(f.bytes))) identical++;
|
|
else differ++;
|
|
}
|
|
console.log(`pull versjon 1: ${identical} bit-identiske, ${differ} avvik`);
|
|
const log = await client.history();
|
|
console.log(`historikk: ${log.entries.map((e) => e.seq).join(', ')} (head ${log.head})`);
|