~ 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 · 4.0 KB Raw History
// Example Node.js PDS server
import { createLogEmailer, createServer, createSmtpEmailer } from '@pdsjs/node';

/**
 * Pick a backup target from the environment. A directory is the simple case
 * (`PDS_BACKUP_DIR`, ideally a different disk than the database); an
 * S3-compatible bucket — Bunny, Backblaze B2, MinIO, R2, AWS — takes
 * `PDS_BACKUP_S3_ENDPOINT`, `PDS_BACKUP_S3_BUCKET`, `PDS_BACKUP_S3_ACCESS_KEY`
 * and `PDS_BACKUP_S3_SECRET_KEY` (plus `PDS_BACKUP_S3_REGION` where the
 * provider cares), no SDK required. Neither set, the backups page reports
 * backups as unavailable.
 */
async function backupTargetFromEnv() {
  if (!process.env.PDS_BACKUP_S3_BUCKET) return undefined;
  const { createS3FetchBackupTarget } = await import('@pdsjs/blobs-s3');
  return createS3FetchBackupTarget({
    endpoint: /** @type {string} */ (process.env.PDS_BACKUP_S3_ENDPOINT),
    bucket: process.env.PDS_BACKUP_S3_BUCKET,
    region: process.env.PDS_BACKUP_S3_REGION || 'us-east-1',
    accessKeyId: /** @type {string} */ (process.env.PDS_BACKUP_S3_ACCESS_KEY),
    secretAccessKey: /** @type {string} */ (
      process.env.PDS_BACKUP_S3_SECRET_KEY
    ),
  });
}

/**
 * Pick a mail sender from the environment. `smtp` delivers to a catch-all
 * inbox like Mailpit (see docker-compose) so sent mail is visible in a
 * browser; `log` prints codes to the terminal; anything else stores addresses
 * without being able to confirm them.
 */
function emailerFromEnv() {
  if (process.env.PDS_EMAIL_TRANSPORT === 'smtp')
    return createSmtpEmailer({
      host: process.env.PDS_SMTP_HOST,
      port: process.env.PDS_SMTP_PORT
        ? Number(process.env.PDS_SMTP_PORT)
        : undefined,
      from: process.env.PDS_EMAIL_FROM,
    });
  if (process.env.PDS_EMAIL_TRANSPORT === 'log') return createLogEmailer();
  return undefined;
}

const { listen } = await createServer({
  dbPath: process.env.PDS_DB_PATH || './pds.db',
  blobsDir: process.env.PDS_BLOBS_DIR || './blobs',
  jwtSecret: process.env.JWT_SECRET || 'development-secret',
  blobUploadLimit: process.env.PDS_BLOB_UPLOAD_LIMIT
    ? Number(process.env.PDS_BLOB_UPLOAD_LIMIT)
    : undefined,
  port: parseInt(process.env.PORT || '3000', 10),
  hostname: process.env.HOSTNAME,
  appviewUrl: process.env.APPVIEW_URL,
  appviewDid: process.env.APPVIEW_DID,
  relayUrl: process.env.RELAY_URL,
  plcUrl: process.env.PLC_URL,
  password: process.env.PDS_PASSWORD,
  // Development only. A deployment supplies a real sender here.
  emailer: emailerFromEnv(),
  // The React account application. Installed here, so on unless refused.
  accountUi: process.env.PDS_ACCOUNT_UI !== 'false',
  // Permissioned data (proposal 0016). Off unless explicitly enabled.
  spaces: process.env.PDS_ENABLE_SPACES === 'true',
  // Semver-exempt experiments; see the experimental option's documentation.
  experimental: {
    // Git hosting: smart HTTP off unless enabled, browsing on unless
    // refused. `external` hands the reads to a separate forge process and
    // keeps only the branch-protection write guard here.
    git: {
      http: process.env.PDS_EXPERIMENTAL_GIT_HTTP === 'true',
      browse: process.env.PDS_EXPERIMENTAL_GIT_BROWSE !== 'false',
      external: process.env.PDS_EXPERIMENTAL_GIT_EXTERNAL === 'true',
    },
    // Files stored in the repo, on unless refused.
    drive: process.env.PDS_EXPERIMENTAL_DRIVE !== 'false',
    // Registries for what this account publishes, both off unless enabled.
    // Each needs its own optional peer package installed.
    oci: process.env.PDS_EXPERIMENTAL_OCI === 'true',
    npm: process.env.PDS_EXPERIMENTAL_NPM === 'true',
    // Static sites from the repo (off without a domain) and queries.
    sites: {
      domain: process.env.PDS_EXPERIMENTAL_SITE_DOMAIN,
      apexName: process.env.PDS_EXPERIMENTAL_SITE_APEX_NAME,
      queries: process.env.PDS_EXPERIMENTAL_QUERIES === 'true',
    },
  },
  // Scheduled backups: a directory, or an S3-compatible bucket.
  backupDir: process.env.PDS_BACKUP_DIR,
  backupTarget: await backupTargetFromEnv(),
});

await listen();