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

chadtmiller.com/pds.js

An atproto PDS in JavaScript, for Cloudflare Workers and Node

0
0
main
54 lines · 1.9 KB Raw History
import { fileURLToPath } from 'node:url';
import tailwindcss from '@tailwindcss/vite';
import react from '@vitejs/plugin-react';
import { defineConfig } from 'vite';
import { viteSingleFile } from 'vite-plugin-singlefile';

// The PDS this dev server proxies to for API, auth, and (pre-login) the
// account pages themselves. See `just dev-live`.
const PDS_TARGET = process.env.PDS_DEV_TARGET || 'http://localhost:2471';
const toPds = { target: PDS_TARGET, ws: true };

// One file out, by design. The PDS serves this from a JS module rather than a
// directory: Workers has no filesystem, and a single document means the
// account pages keep arriving in one request the way the server-rendered
// ones did.
export default defineConfig({
  plugins: [react(), tailwindcss(), viteSingleFile()],
  // Dev-only (ignored by `vite build`): serve this app with HMR while the real
  // PDS answers everything dynamic. The Host header is forwarded as-is, so the
  // PDS's same-origin POST check still passes.
  server: {
    proxy: {
      // API, form posts, and xrpc always hit the PDS.
      '^/(account/(api|sign-in|sign-out)|xrpc)(/|$)': toPds,
      // Account pages: serve the local SPA (with HMR) once signed in; before
      // that, proxy to the PDS so its sign-in / onboarding / consent screens
      // render and can set the session cookie on this origin.
      '^/account($|/)': {
        ...toPds,
        bypass(req) {
          const signedIn = (req.headers.cookie || '').includes(
            'pdsjs_account=',
          );
          if (req.method === 'GET' && signedIn) return '/index.html';
        },
      },
    },
  },
  resolve: {
    alias: [
      {
        find: /^#\/(.*)/,
        replacement: `${fileURLToPath(new URL('./src', import.meta.url))}/$1`,
      },
    ],
  },
  build: {
    target: 'es2022',
    assetsInlineLimit: 100000000,
    chunkSizeWarningLimit: 4096,
    cssCodeSplit: false,
    reportCompressedSize: false,
  },
});