#!/usr/bin/env node import { argv, Either, getEnv, type IEither, HonoProxy } from '@emprespresso/pengueno'; import { PosthookServer } from './server/index.js'; import { Storage } from './storage/index.js'; import { TokenSigner } from './token/index.js'; const main = async (_argv = process.argv.slice(2)): Promise> => { const argsResult = argv( ['--port', '--host', '--data-dir', '--token-secret'], { '--port': { absent: 9000, present: (port) => parseInt(port) }, '--host': { absent: '0.0.0.0', present: (host) => host }, '--data-dir': { absent: './data', present: (dir) => dir }, '--token-secret': { absent: undefined, present: (secret) => secret }, }, _argv, ); return argsResult .mapRight((args) => ({ port: args['--port'], host: args['--host'], dataDir: args['--data-dir'], tokenSecret: args['--token-secret'], })) .flatMapAsync(async (config) => { // Initialize storage const storage = new Storage(config.dataDir); const initResult = await storage.init(); if (initResult.left().present()) { return Either.left(initResult.left().get()); } // Initialize token signer (use env var or command line arg or generate random) const envSecret = getEnv('POSTHOOK_TOKEN_SECRET'); const secret = config.tokenSecret ?? (envSecret.present() ? envSecret.get() : undefined); const signer = new TokenSigner(secret); if (config.tokenSecret === undefined && !envSecret.present()) { console.log('No token secret provided; generated a random one (will not persist across restarts).'); console.log('Set POSTHOOK_TOKEN_SECRET or pass --token-secret to use a persistent secret.'); } console.log(`Storage initialized at: ${config.dataDir}`); console.log(`Starting server on ${config.host}:${config.port}`); // Create and start server const server = new PosthookServer(storage, signer); const hono = new HonoProxy(server); return hono.serve(config.port, config.host); }); }; if (process.argv[1] === import.meta.filename) { await main().then((eitherDone) => eitherDone.mapLeft((err) => { console.error('error:', err); process.exit(1); }), ); }