chadtmiller.com/pds.js
An atproto PDS in JavaScript, for Cloudflare Workers and Node
0
0
// test/helpers/deno-server.js
import { spawn } from 'node:child_process';
import { mkdirSync, rmSync } from 'node:fs';
import { TEST_PORT } from './test-port.js';
const TEST_DATA_DIR = './test-data';
const USE_LOCAL_INFRA = process.env.USE_LOCAL_INFRA !== 'false';
/** @type {import('node:child_process').ChildProcess | null} */
let denoProcess = null;
/**
* Start Deno PDS server for e2e tests
* Spawns Deno process running examples/deno/main.ts
* @returns {Promise<{close: () => Promise<void>}>} Server instance with close() method
*/
export async function startDenoServer() {
// Fresh data each run
rmSync(TEST_DATA_DIR, { recursive: true, force: true });
mkdirSync(TEST_DATA_DIR, { recursive: true });
const hostname = USE_LOCAL_INFRA
? 'host.docker.internal:3443'
: `localhost:${TEST_PORT}`;
const env = {
...process.env,
PDS_DB_PATH: `${TEST_DATA_DIR}/pds.db`,
PDS_BLOBS_DIR: `${TEST_DATA_DIR}/blobs`,
JWT_SECRET: 'test-secret-for-e2e',
HOSTNAME: hostname,
PORT: String(TEST_PORT),
PDS_PASSWORD: 'test-password',
RELAY_URL: USE_LOCAL_INFRA ? 'http://localhost:2470' : '',
APPVIEW_URL: 'https://api.bsky.app',
APPVIEW_DID: 'did:web:api.bsky.app',
};
denoProcess = spawn(
'deno',
[
'run',
'--allow-net',
'--allow-read',
'--allow-write',
'--allow-env',
'--unstable-ffi',
'examples/deno/main.ts',
],
{
env,
stdio: ['ignore', 'pipe', 'pipe'],
cwd: process.cwd(),
},
);
// Log output for debugging
denoProcess.stdout?.on('data', (data) => {
const msg = data.toString().trim();
if (msg) console.log(`[deno] ${msg}`);
});
denoProcess.stderr?.on('data', (data) => {
const msg = data.toString().trim();
if (msg) console.error(`[deno] ${msg}`);
});
// Wait for server to be ready
await waitForReady();
return {
async close() {
if (denoProcess) {
denoProcess.kill('SIGTERM');
// Wait for process to exit
await new Promise((resolve) => {
denoProcess?.on('exit', resolve);
// Timeout after 5s
setTimeout(resolve, 5000);
});
denoProcess = null;
}
},
};
}
/**
* Wait for Deno server to be ready
*/
async function waitForReady(maxAttempts = 30) {
for (let i = 0; i < maxAttempts; i++) {
try {
const res = await fetch(`http://localhost:${TEST_PORT}/`);
if (res.ok) return;
} catch {
// Server not ready yet
}
await new Promise((r) => setTimeout(r, 500));
}
throw new Error('Deno server failed to start');
}
/**
* Stop Deno PDS server
* @param {{close: () => Promise<void>}} server - Server instance from startDenoServer
*/
export async function stopDenoServer(server) {
await server.close();
}
export { TEST_PORT, USE_LOCAL_INFRA };