+9
-4
@@ -111,12 +111,14 @@ if [[ "$PLATFORM" == "darwin" ]]; then
|
||||
printf '%s\n' '<?xml version="1.0" encoding="UTF-8"?>' '<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">' '<plist version="1.0"><dict><key>com.apple.security.cs.disable-library-validation</key><true/></dict></plist>' > "$ENTITLEMENTS_PLIST"
|
||||
codesign --force --sign - --entitlements "$ENTITLEMENTS_PLIST" "$HOST_BIN" 2>/dev/null || true
|
||||
|
||||
# Optional helper launcher (manual runs). Native messaging uses the Mach-O
|
||||
# binary directly — set-tmpdir.mjs inside the binary pins TMPDIR for signed addons.
|
||||
LAUNCHER="${HOST_DIR}/run-bridge-swarm-host.sh"
|
||||
printf '%s\n' '#!/bin/bash' 'DIR="$(cd "$(dirname "$0")" && pwd)"' 'export TMPDIR="${DIR}/tmp"' 'export BRIDGE_SWARM_STORAGE="${BRIDGE_SWARM_STORAGE:-${DIR}/bridge-swarm-storage}"' 'exec "${DIR}/bridge-swarm-host" "$@"' > "$LAUNCHER"
|
||||
chmod +x "$LAUNCHER"
|
||||
|
||||
echo " Extracting native addons (--extract-addons)..."
|
||||
"$LAUNCHER" --extract-addons 2>/dev/null || true
|
||||
TMPDIR="$ADDON_TMPDIR" "$HOST_BIN" --extract-addons 2>/dev/null || true
|
||||
sleep 2
|
||||
|
||||
SIGNED=0
|
||||
@@ -127,16 +129,19 @@ if [[ "$PLATFORM" == "darwin" ]]; then
|
||||
done < <(find "$ADDON_TMPDIR" \( -name "*.bare" -o -name "*.dylib" \) -print0 2>/dev/null)
|
||||
fi
|
||||
echo " Signed ${SIGNED} native addons; main binary has library-validation disabled"
|
||||
HOST_BIN="$LAUNCHER"
|
||||
# Keep HOST_BIN as the Mach-O binary for Chrome native messaging
|
||||
else
|
||||
# Linux launcher sets storage path next to the binary
|
||||
# Linux: binary path is fine; set-tmpdir is macOS-only
|
||||
HOST_DIR="$(dirname "$HOST_BIN")"
|
||||
LAUNCHER="${HOST_DIR}/run-bridge-swarm-host.sh"
|
||||
printf '%s\n' '#!/bin/bash' 'DIR="$(cd "$(dirname "$0")" && pwd)"' 'export BRIDGE_SWARM_STORAGE="${BRIDGE_SWARM_STORAGE:-${DIR}/bridge-swarm-storage}"' 'exec "${DIR}/bridge-swarm-host" "$@"' > "$LAUNCHER"
|
||||
chmod +x "$LAUNCHER"
|
||||
HOST_BIN="$LAUNCHER"
|
||||
fi
|
||||
|
||||
# Default storage next to install when launched by the browser
|
||||
# (bare host also honors BRIDGE_SWARM_STORAGE if set by a wrapper)
|
||||
export BRIDGE_SWARM_STORAGE="${BRIDGE_SWARM_STORAGE:-${INSTALL_DIR}/bridge-swarm-storage}"
|
||||
|
||||
echo " Binary: $HOST_BIN"
|
||||
|
||||
# ── Extension downloads ────────────────────────────────────────────────────────
|
||||
|
||||
Executable
+122
@@ -0,0 +1,122 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Serve BridgeSwarm examples over http://localhost so they share one origin.
|
||||
* Modern Chrome/Firefox treat each file:// URL as a unique opaque origin, which
|
||||
* breaks local HTML demos (scripts, styles, extension injection).
|
||||
*
|
||||
* Usage: npm run examples
|
||||
* node scripts/serve-examples.js [port]
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
const http = require('http');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { exec } = require('child_process');
|
||||
|
||||
const ROOT = path.resolve(__dirname, '..', 'examples');
|
||||
const PORT = Number(process.argv[2]) || Number(process.env.PORT) || 4173;
|
||||
const HOST = process.env.HOST || '127.0.0.1';
|
||||
|
||||
const MIME = {
|
||||
'.html': 'text/html; charset=utf-8',
|
||||
'.js': 'text/javascript; charset=utf-8',
|
||||
'.mjs': 'text/javascript; charset=utf-8',
|
||||
'.css': 'text/css; charset=utf-8',
|
||||
'.json': 'application/json; charset=utf-8',
|
||||
'.svg': 'image/svg+xml',
|
||||
'.png': 'image/png',
|
||||
'.jpg': 'image/jpeg',
|
||||
'.jpeg': 'image/jpeg',
|
||||
'.gif': 'image/gif',
|
||||
'.webp': 'image/webp',
|
||||
'.ico': 'image/x-icon',
|
||||
'.woff': 'font/woff',
|
||||
'.woff2': 'font/woff2',
|
||||
'.map': 'application/json',
|
||||
'.txt': 'text/plain; charset=utf-8',
|
||||
'.md': 'text/markdown; charset=utf-8',
|
||||
};
|
||||
|
||||
function safeJoin(root, urlPath) {
|
||||
const decoded = decodeURIComponent((urlPath || '/').split('?')[0]);
|
||||
const cleaned = path.normalize(decoded).replace(/^(\.\.[/\\])+/, '');
|
||||
const full = path.join(root, cleaned);
|
||||
if (!full.startsWith(root)) return null;
|
||||
return full;
|
||||
}
|
||||
|
||||
function send(res, status, body, headers = {}) {
|
||||
res.writeHead(status, {
|
||||
'Cache-Control': 'no-store',
|
||||
...headers,
|
||||
});
|
||||
res.end(body);
|
||||
}
|
||||
|
||||
function contentType(filePath) {
|
||||
return MIME[path.extname(filePath).toLowerCase()] || 'application/octet-stream';
|
||||
}
|
||||
|
||||
const server = http.createServer((req, res) => {
|
||||
let urlPath = req.url || '/';
|
||||
if (urlPath === '/') urlPath = '/index.html';
|
||||
|
||||
const filePath = safeJoin(ROOT, urlPath);
|
||||
if (!filePath) {
|
||||
send(res, 403, 'Forbidden');
|
||||
return;
|
||||
}
|
||||
|
||||
fs.stat(filePath, (err, st) => {
|
||||
if (!err && st.isDirectory()) {
|
||||
const indexPath = path.join(filePath, 'index.html');
|
||||
fs.readFile(indexPath, (err2, data) => {
|
||||
if (err2) {
|
||||
send(res, 404, 'Not found');
|
||||
return;
|
||||
}
|
||||
send(res, 200, data, { 'Content-Type': 'text/html; charset=utf-8' });
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
fs.readFile(filePath, (err2, data) => {
|
||||
if (err2) {
|
||||
send(res, 404, 'Not found');
|
||||
return;
|
||||
}
|
||||
send(res, 200, data, { 'Content-Type': contentType(filePath) });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
server.listen(PORT, HOST, () => {
|
||||
const base = `http://${HOST}:${PORT}`;
|
||||
console.log('');
|
||||
console.log('BridgeSwarm examples');
|
||||
console.log('====================');
|
||||
console.log(`Serving ${ROOT}`);
|
||||
console.log(`Open: ${base}/`);
|
||||
console.log('');
|
||||
console.log('Demos:');
|
||||
console.log(` ${base}/chat/`);
|
||||
console.log(` ${base}/chat-advanced/`);
|
||||
console.log(` ${base}/sdk-demo/`);
|
||||
console.log(` ${base}/hrpc-demo/`);
|
||||
console.log(` ${base}/whiteboard/`);
|
||||
console.log(` ${base}/screenshare/`);
|
||||
console.log(` ${base}/data-demo/`);
|
||||
console.log('');
|
||||
console.log('Do not open examples via file:// — Chrome treats each file as a unique origin.');
|
||||
console.log('Press Ctrl+C to stop.');
|
||||
console.log('');
|
||||
|
||||
const openUrl = `${base}/`;
|
||||
if (process.env.BRIDGESWARM_NO_OPEN !== '1') {
|
||||
const platform = process.platform;
|
||||
const cmd =
|
||||
platform === 'darwin' ? `open "${openUrl}"` : platform === 'win32' ? `start "" "${openUrl}"` : `xdg-open "${openUrl}"`;
|
||||
exec(cmd, () => {});
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user