Jason Tudisco b5528b0ecf Add Nostr dual-sync variant (folder + relay)
Fifth library variant that keeps folder sync for offline/local use
AND adds Nostr relay sync for cross-device reach via WebSocket.
Both transports run simultaneously - writes go to folder AND Nostr,
sync imports from both and bridges events between them.

Works from file:// since Nostr uses WebSocket (not fetch/WebRTC).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 22:44:39 -06:00

100 lines
2.9 KiB
TypeScript

/**
* Build script for paste app variants.
*
* Usage:
* bun run build.ts
*
* Produces self-contained HTML files in dist/:
* dist/paste-indexeddb.html
* dist/paste-sqlite.html
* dist/paste-nedb.html
*
* Each file is a single self-contained HTML with all JS and CSS inlined.
*
* If bun >= 1.3.10, you can also use:
* bun build --compile --target=browser ./indexeddb/index.html
*
* Docs: https://bun.com/docs/bundler/html-static
*/
import { readFileSync } from 'fs';
import { join, basename } from 'path';
const variants = ['indexeddb', 'sqlite', 'nedb', 'sql-js', 'nostr'] as const;
for (const variant of variants) {
console.log(`Building paste-${variant}...`);
const outdir = `./dist/${variant}`;
const result = await Bun.build({
entrypoints: [`./${variant}/index.html`],
outdir,
target: 'browser',
minify: true,
});
if (!result.success) {
console.error(` FAILED: paste-${variant}`);
for (const log of result.logs) {
console.error(' ', log);
}
process.exit(1);
}
// Read the generated HTML and inline all referenced chunks
const htmlPath = join(outdir, 'index.html');
let html = readFileSync(htmlPath, 'utf-8');
// Inline JS chunks: <script type="module" src="./chunk-xxx.js">
html = html.replace(
/<script[^>]+src="\.\/([^"]+\.js)"[^>]*><\/script>/g,
(_match, jsFile) => {
const jsPath = join(outdir, jsFile);
try {
const js = readFileSync(jsPath, 'utf-8');
return `<script type="module">${js}</script>`;
} catch {
console.warn(` Warning: could not inline ${jsFile}`);
return _match;
}
},
);
// Inline CSS chunks: <link rel="stylesheet" href="./chunk-xxx.css">
html = html.replace(
/<link[^>]+href="\.\/([^"]+\.css)"[^>]*\/?>/g,
(_match, cssFile) => {
const cssPath = join(outdir, cssFile);
try {
const css = readFileSync(cssPath, 'utf-8');
return `<style>${css}</style>`;
} catch {
console.warn(` Warning: could not inline ${cssFile}`);
return _match;
}
},
);
// Write the single self-contained HTML
const outFile = `./dist/paste-${variant}.html`;
await Bun.write(outFile, html);
console.log(` OK: ${outFile}`);
}
// Copy sqlite3.wasm to dist/ (needed for SQLite variant over HTTP)
const wasmSrc = '../sqlite/node_modules/@sqlite.org/sqlite-wasm/dist/sqlite3.wasm';
const wasmDst = './dist/sqlite3.wasm';
try {
const wasmFile = Bun.file(wasmSrc);
if (await wasmFile.exists()) {
await Bun.write(wasmDst, wasmFile);
console.log(`\nCopied sqlite3.wasm (${Math.round(wasmFile.size! / 1024)}KB) to dist/`);
}
} catch {
console.warn('\nWarning: could not copy sqlite3.wasm — run `npm install` in sqlite/ first');
}
console.log('\nAll builds complete. Single-file HTMLs in paste/dist/');
console.log('Note: paste-sqlite.html requires HTTP — run `bun run serve.ts`');