aboutsummaryrefslogtreecommitdiff
path: root/src/index.ts
diff options
context:
space:
mode:
authorElizabeth Hunt <me@liz.coffee>2025-12-14 20:36:24 -0800
committerElizabeth Hunt <me@liz.coffee>2025-12-14 20:36:24 -0800
commit6bf57766feb8321f860baf300140563cd9539053 (patch)
treed80ff78c2a7f4dbea79f9ee850542aee1b735ef4 /src/index.ts
downloadposthook-6bf57766feb8321f860baf300140563cd9539053.tar.gz
posthook-6bf57766feb8321f860baf300140563cd9539053.zip
Init
Diffstat (limited to 'src/index.ts')
-rw-r--r--src/index.ts64
1 files changed, 64 insertions, 0 deletions
diff --git a/src/index.ts b/src/index.ts
new file mode 100644
index 0000000..cbc946a
--- /dev/null
+++ b/src/index.ts
@@ -0,0 +1,64 @@
+#!/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<IEither<Error, void>> => {
+ 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);
+ }),
+ );
+}