1// Presets: the templates in relay-templates/, one click each. A template is2// a relay configuration with the rules sections only (policy, kinds and3// retention, and the Connect fold's shortcuts when it names them), so4// applying one sets writes, reads, the directory, the features, the kind5// rules, the keep-for rules and the app shortcuts together and leaves6// limits, identity, people and bans alone. Haven's four relays are the7// first four: names are cheap here, so one name per role is the way to get8// the same split.9import { TEMPLATES } from "./gen/templates.ts";10import { applyConfig, parseConfig, type Config } from "./config.ts";11import type { Connection, Policy, Settings } from "./settings.ts";1213export interface Preset {14 name: string;15 title: string;16 about: string;17 writes: Policy["writes"];18 reads: Policy["reads"];19 directoryPublic: boolean;20 allow: number[];21 block: number[];22 retention: { kind: number | null; days: number }[];23 // The Connect fold's shortcuts the template sets, when it has a24 // connections section; left out, the shortcuts stay as they are.25 connections?: Connection[];26 // A replica keeps itself in step with a source relay through a standing27 // pull of its kinds. "required" presets refuse to apply without one.28 source?: "required" | "optional";29 every?: number; // hours between pulls30 config: Config;31}3233export const PRESETS: Preset[] = TEMPLATES.map(({ name, document }) => {34 const config = parseConfig(document);35 if (typeof config === "string" || !config.template) throw new Error(`template ${name}: ${typeof config === "string" ? config : "no template block"}`);36 const p = config.policy;37 return { name, title: config.template.title, about: config.template.about, source: config.template.source, every: config.template.every, writes: p.writes ?? "open", reads: p.reads ?? "open", directoryPublic: p.directoryPublic ?? true, allow: config.kinds.allow, block: config.kinds.block, retention: config.retention, ...(config.sections.includes("connections") ? { connections: config.connections } : {}), config };38});3940export function findPreset(name: string): Preset | undefined {41 return PRESETS.find((p) => p.name === name);42}4344// applyPreset applies the template's sections: the policy fields it names,45// the kind rules and the keep-for rules. Returns "" or a reason.46export function applyPreset(s: Settings, name: string, now: number): string {47 const p = findPreset(name);48 if (!p) return "invalid: no preset named " + name;49 applyConfig(s, p.config, now);50 return "";51}