chadtmiller.com/hatk
AT Protocol app framework
1
0
Switch from config.yaml to hatk.config.ts
Goal
Replace config.yaml with hatk.config.ts for type safety, autocompletion, and single-language consistency. No YAML fallback.
Design
User-facing config file
// hatk.config.ts
import { defineConfig } from 'hatk'
export default defineConfig({
relay: 'ws://localhost:2583',
port: 3000,
database: 'data/hatk.db',
collections: ['app.bsky.feed.post'],
backfill: {
parallelism: 10,
fullNetwork: false,
},
})
defineConfig helper
Identity function exported from the hatk package. Exists solely for type inference:
export function defineConfig(config: Partial<HatkConfig>): Partial<HatkConfig> {
return config
}
Takes Partial<HatkConfig> so users only specify what they need; defaults fill the rest.
Loader (config.ts)
loadConfig becomes async (dynamic import replaces readFileSync + YAML parse):
export async function loadConfig(configPath?: string): Promise<HatkConfig> {
const resolved = resolve(configPath || 'hatk.config.ts')
const configDir = dirname(resolved)
const mod = await import(resolved)
const raw: Partial<HatkConfig> = mod.default
return applyDefaultsAndEnvOverrides(raw, configDir)
}
- Relative paths still resolved against the config file's directory.
- Environment variable overrides preserved (essential for container deployments).
- Defaults unchanged from current behavior.
Environment variable overrides
Same as today. Env vars take precedence over the TS config values:
| Env var | Config field |
|---|---|
DATABASE | database |
RELAY | relay |
DID_PLC_URL | plc |
PORT | port |
BACKFILL_REPOS | backfill.repos |
BACKFILL_FULL_NETWORK | backfill.fullNetwork |
BACKFILL_PARALLELISM | backfill.parallelism |
BACKFILL_FETCH_TIMEOUT | backfill.fetchTimeout |
BACKFILL_MAX_RETRIES | backfill.maxRetries |
FTS_REBUILD_INTERVAL | ftsRebuildInterval |
OAUTH_ISSUER | oauth.issuer |
ADMINS | admins |
Changes required
config.ts
- Remove
yamlimport andreadFileSync loadConfigbecomesasync, usesawait import()instead of YAML parse- Add
defineConfigexport - Input type becomes
Partial<HatkConfig>(users specify only what they need)
Callers of loadConfig (4 files)
main.ts— already async context; changeloadConfig(configPath)toawait loadConfig(configPath), update default from'config.yaml'to'hatk.config.ts'cli.ts— changeloadConfig(resolve('config.yaml'))toawait loadConfig(resolve('hatk.config.ts'))(2 call sites)test.ts— change toawait loadConfig(...), update fallback pathvite-plugin.ts— update spawned server argument from'config.yaml'to'hatk.config.ts'
Package exports
- Export
defineConfigandHatkConfigfrom the package entry point so users can import them
Dependencies
- Remove
yamlfrompackage.jsondependencies
Documentation
- Update
docs/site/src/content/docs/getting-started/configuration.mdxto show TypeScript config instead of YAML
Migration
- No automatic migration. Clean break from YAML.
- If
hatk.config.tsis not found at startup, print a clear error message explaining the change.