Simple API gateway for webhooks

initial commit

+157
+23
.tangled/workflows/deploy.yaml
··· 1 + when: 2 + - event: ["push", "pull_request"] 3 + branch: ["main"] 4 + 5 + dependencies: 6 + nixpkgs: 7 + - deno 8 + 9 + engine: "nixery" 10 + 11 + steps: 12 + - name: Lint code 13 + command: | 14 + deno lint 15 + 16 + - name: Install deployctl 17 + command: | 18 + deno install -gArf jsr:@deno/deployctl 19 + 20 + - name: Deploy to Deno Deploy 21 + command: | 22 + cd .output/public 23 + ~/.deno/bin/deployctl deploy --project finxol-hook --entrypoint src/main.ts --include=. --prod
+3
.zed/settings.json
··· 1 + { 2 + "language_servers": ["deno", "!biome"] 3 + }
+3
README.md
··· 1 + ``` 2 + deno task start 3 + ```
+4
config.ts
··· 1 + export const config = { 2 + title: "finxol's Webhook server", 3 + description: "Simple API endpoint for webhooks", 4 + }
+34
deno.json
··· 1 + { 2 + "imports": { 3 + "@hono/ua-blocker": "npm:@hono/ua-blocker@^0.1.9", 4 + "hono": "npm:hono@^4.9.6" 5 + }, 6 + "tasks": { 7 + "start": "deno run --allow-net src/main.ts" 8 + }, 9 + "unstable": [ 10 + "kv" 11 + ], 12 + "compilerOptions": { 13 + "jsx": "precompile", 14 + "jsxImportSource": "hono/jsx" 15 + }, 16 + "fmt": { 17 + "useTabs": false, 18 + "lineWidth": 90, 19 + "indentWidth": 4, 20 + "semiColons": false, 21 + "singleQuote": false, 22 + "proseWrap": "preserve" 23 + }, 24 + "deploy": { 25 + "project": "bd2e7894-6133-473d-8093-f84066914d26", 26 + "exclude": [ 27 + "**/node_modules" 28 + ], 29 + "include": [ 30 + "." 31 + ], 32 + "entrypoint": "src/main.ts" 33 + } 34 + }
+34
deno.lock
··· 1 + { 2 + "version": "5", 3 + "specifiers": { 4 + "npm:@hono/ua-blocker@~0.1.9": "0.1.9_hono@4.9.6", 5 + "npm:@types/node@*": "24.2.0", 6 + "npm:hono@^4.9.6": "4.9.6" 7 + }, 8 + "npm": { 9 + "@hono/ua-blocker@0.1.9_hono@4.9.6": { 10 + "integrity": "sha512-JETVhZEZGLa/kA0IZB72YhuhscacGLSeFNGxUX06stC1yagGtHAbWV98R4C/Xsta5xpfwiReMIPt+3hbsCiZoQ==", 11 + "dependencies": [ 12 + "hono" 13 + ] 14 + }, 15 + "@types/node@24.2.0": { 16 + "integrity": "sha512-3xyG3pMCq3oYCNg7/ZP+E1ooTaGB4cG8JWRsqqOYQdbWNY4zbaV0Ennrd7stjiJEFZCaybcIgpTjJWHRfBSIDw==", 17 + "dependencies": [ 18 + "undici-types" 19 + ] 20 + }, 21 + "hono@4.9.6": { 22 + "integrity": "sha512-doVjXhSFvYZ7y0dNokjwwSahcrAfdz+/BCLvAMa/vHLzjj8+CFyV5xteThGUsKdkaasgN+gF2mUxao+SGLpUeA==" 23 + }, 24 + "undici-types@7.10.0": { 25 + "integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==" 26 + } 27 + }, 28 + "workspace": { 29 + "dependencies": [ 30 + "npm:@hono/ua-blocker@~0.1.9", 31 + "npm:hono@^4.9.6" 32 + ] 33 + } 34 + }
+53
src/main.ts
··· 1 + import { Hono } from "hono" 2 + import { uaBlocker } from "@hono/ua-blocker" 3 + import { aiBots, useAiRobotsTxt } from "@hono/ua-blocker/ai-bots" 4 + import { config } from "../config.ts" 5 + 6 + const app = new Hono() 7 + .get("/robots.txt", useAiRobotsTxt()) 8 + .use( 9 + "*", 10 + uaBlocker({ 11 + blocklist: aiBots, 12 + }), 13 + ) 14 + .get("/", (ctx) => { 15 + return ctx.html(` 16 + <html> 17 + <head> 18 + <title>${config.title || "auth server"}</title> 19 + <style> 20 + body { 21 + font-family: Arial, sans-serif; 22 + margin: 0; 23 + padding: 0; 24 + background-color: #f5f5f5; 25 + display: flex; 26 + flex-direction: column; 27 + justify-content: center; 28 + align-items: center; 29 + height: 100svh; 30 + } 31 + h1 { 32 + font-size: 3rem; 33 + color: #333; 34 + text-align: center; 35 + } 36 + p { 37 + font-size: 1.2rem; 38 + color: #666; 39 + text-align: center; 40 + } 41 + </style> 42 + </head> 43 + <body> 44 + <h1>${config.title || "auth server"}</h1> 45 + <p> 46 + ${config.description || "This is a simple auth server"} 47 + </p> 48 + </body> 49 + </html> 50 + `) 51 + }) 52 + 53 + Deno.serve(app.fetch)
+3
src/sensors.ts
··· 1 + import { Hono } from "hono" 2 + 3 + export const app = new Hono().get("/", (c) => c.text("Hello World!"))