~ knotless Search/
↑↓ move↵ open⇧↵ all results

chadtmiller.com/pds.js

An atproto PDS in JavaScript, for Cloudflare Workers and Node

0
0
main
94 lines · 3.1 KB Raw History
// The git gate in createServer: the full extension mounts whenever the git
// package is installed, `git.external` swaps it for the guard alone, and the
// /git/ smart HTTP prefix follows the http option.

import { mkdtempSync, rmSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { afterEach, describe, expect, it } from 'vitest';
import { createServer } from '../src/index.js';

/** @type {Array<{close: () => Promise<void>}>} */
const servers = [];
/** @type {string[]} */
const dirs = [];

/**
 * @param {{experimental?: {git?: {http?: boolean, external?: boolean, guardOnly?: boolean}}}} [opts]
 */
async function makeServer(opts = {}) {
  const dir = mkdtempSync(join(tmpdir(), 'pdsjs-git-wiring-'));
  dirs.push(dir);
  const server = await createServer({
    dbPath: join(dir, 'pds.db'),
    blobsDir: join(dir, 'blobs'),
    jwtSecret: 'wiring-test-secret',
    hostname: 'pds.example.com',
    ...opts,
  });
  servers.push(server);
  return server;
}

afterEach(async () => {
  for (const server of servers.splice(0)) {
    // close() rejects when listen() was never called; these tests only
    // construct the server.
    await server.close().catch(() => {});
  }
  for (const dir of dirs.splice(0))
    rmSync(dir, { recursive: true, force: true });
});

describe('node git wiring', () => {
  it('mounts the full extension by default', async () => {
    const { pds } = await makeServer();
    expect(pds.extensionFeatures.git).toBe(true);
    expect(pds.extensionFeatures.gitBrowse).toBe(true);

    // The XRPC methods are served; listRepos answers an empty listing.
    const response = await pds.fetch(
      new Request('https://pds.example.com/xrpc/dev.pdsjs.git.listRepos'),
    );
    expect(response.status).toBe(200);
  });

  it('serves smart HTTP only with the http option', async () => {
    const { pds } = await makeServer({
      experimental: { git: { http: true } },
    });
    // Without the option the /git path is nobody's route; the PDS answers
    // its generic bad request, not a git advertisement.
    const response = await pds.fetch(
      new Request('https://pds.example.com/git/x/y/info/refs'),
    );
    expect(response.status).toBe(400);
    expect(response.headers.get('content-type')).not.toContain(
      'git-upload-pack-advertisement',
    );

    const on = await makeServer({
      experimental: { git: { http: true } },
    });
    const advertisement = await on.pds.fetch(
      new Request(
        'https://pds.example.com/git/did:plc:unknown/repo/info/refs?service=git-upload-pack',
      ),
    );
    expect(advertisement.status).toBe(404);
  });

  it('drops the routes and keeps the guard in external mode', async () => {
    const { pds } = await makeServer({
      experimental: { git: { external: true } },
    });
    expect(pds.extensionFeatures.git).toBe(true);
    expect(pds.extensionFeatures.gitBrowse).toBe(false);

    // An unknown XRPC method is a 501, the unimplemented answer.
    const response = await pds.fetch(
      new Request('https://pds.example.com/xrpc/dev.pdsjs.git.listRepos'),
    );
    expect(response.status).toBe(501);
  });
});