Webhooks for the AT Protocol airglow.run
atproto atprotocol automation webhook
12
fork

Configure Feed

Select the types of activity you want to include in your feed.

refactor: use lucide instead of lucide-preact

Hugo 0b759f35 e03ae359

+89 -90
+65 -64
app/icons.ts
··· 1 - // Re-export lucide-preact icons with hono/jsx-compatible types. 1 + // Render lucide icon data as hono/jsx SVG elements. 2 2 // Deep imports avoid pulling in all 3000+ icon modules during dev. 3 - // At runtime the preact Vite alias makes them work; this file fixes the TS type mismatch. 3 + import { createElement } from "hono/jsx"; 4 4 import type { FC } from "hono/jsx"; 5 + import type { HtmlEscapedString } from "hono/utils/html"; 5 6 6 - // @ts-expect-error deep import 7 - import ActivityIcon from "lucide-preact/icons/activity.js"; 8 - // @ts-expect-error deep import 9 - import CopyIcon from "lucide-preact/icons/copy.js"; 10 - // @ts-expect-error deep import 11 - import ChevronDownIcon from "lucide-preact/icons/chevron-down.js"; 12 - // @ts-expect-error deep import 13 - import ChevronRightIcon from "lucide-preact/icons/chevron-right.js"; 14 - // @ts-expect-error deep import 15 - import CircleAlertIcon from "lucide-preact/icons/circle-alert.js"; 16 - // @ts-expect-error deep import 17 - import ArrowLeftIcon from "lucide-preact/icons/arrow-left.js"; 18 - // @ts-expect-error deep import 19 - import DatabaseIcon from "lucide-preact/icons/database.js"; 20 - // @ts-expect-error deep import 21 - import EyeIcon from "lucide-preact/icons/eye.js"; 22 - // @ts-expect-error deep import 23 - import FilePlus2Icon from "lucide-preact/icons/file-plus-corner.js"; 24 - // @ts-expect-error deep import 25 - import FilterIcon from "lucide-preact/icons/funnel.js"; 26 - // @ts-expect-error deep import 27 - import FlaskConicalIcon from "lucide-preact/icons/flask-conical.js"; 28 - // @ts-expect-error deep import 29 - import MoonIcon from "lucide-preact/icons/moon.js"; 30 - // @ts-expect-error deep import 31 - import PencilIcon from "lucide-preact/icons/pencil.js"; 32 - // @ts-expect-error deep import 33 - import PlusIcon from "lucide-preact/icons/plus.js"; 34 - // @ts-expect-error deep import 35 - import PowerIcon from "lucide-preact/icons/power.js"; 36 - // @ts-expect-error deep import 37 - import RefreshCwIcon from "lucide-preact/icons/refresh-cw.js"; 38 - // @ts-expect-error deep import 39 - import SunIcon from "lucide-preact/icons/sun.js"; 40 - // @ts-expect-error deep import 41 - import Trash2Icon from "lucide-preact/icons/trash-2.js"; 42 - // @ts-expect-error deep import 43 - import WebhookIcon from "lucide-preact/icons/webhook.js"; 44 - // @ts-expect-error deep import 45 - import ZapIcon from "lucide-preact/icons/zap.js"; 7 + type IconNode = [string, Record<string, string>][]; 8 + type IconProps = { size?: number; class?: string; color?: string; "stroke-width"?: number }; 9 + 10 + function icon(nodes: IconNode): FC<IconProps> { 11 + return ({ size = 24, class: cls, color = "currentColor", "stroke-width": sw = 2 }) => 12 + createElement( 13 + "svg", 14 + { 15 + xmlns: "http://www.w3.org/2000/svg", 16 + width: size, 17 + height: size, 18 + viewBox: "0 0 24 24", 19 + fill: "none", 20 + stroke: color, 21 + "stroke-width": sw, 22 + "stroke-linecap": "round", 23 + "stroke-linejoin": "round", 24 + class: cls, 25 + }, 26 + ...nodes.map(([tag, attrs]) => createElement(tag, attrs) as unknown as HtmlEscapedString), 27 + ) as unknown as HtmlEscapedString; 28 + } 46 29 47 - type IconProps = { size?: number; class?: string; color?: string; "stroke-width"?: number }; 48 - const cast = (icon: unknown) => icon as FC<IconProps>; 30 + import ActivityData from "lucide/icons/activity"; 31 + import CopyData from "lucide/icons/copy"; 32 + import ChevronDownData from "lucide/icons/chevron-down"; 33 + import ChevronRightData from "lucide/icons/chevron-right"; 34 + import CircleAlertData from "lucide/icons/circle-alert"; 35 + import ArrowLeftData from "lucide/icons/arrow-left"; 36 + import DatabaseData from "lucide/icons/database"; 37 + import EyeData from "lucide/icons/eye"; 38 + import FilePlus2Data from "lucide/icons/file-plus-corner"; 39 + import FilterData from "lucide/icons/funnel"; 40 + import FlaskConicalData from "lucide/icons/flask-conical"; 41 + import MoonData from "lucide/icons/moon"; 42 + import PencilData from "lucide/icons/pencil"; 43 + import PlusData from "lucide/icons/plus"; 44 + import PowerData from "lucide/icons/power"; 45 + import RefreshCwData from "lucide/icons/refresh-cw"; 46 + import SunData from "lucide/icons/sun"; 47 + import Trash2Data from "lucide/icons/trash-2"; 48 + import WebhookData from "lucide/icons/webhook"; 49 + import ZapData from "lucide/icons/zap"; 49 50 50 - export const Activity = cast(ActivityIcon); 51 - export const ArrowLeft = cast(ArrowLeftIcon); 52 - export const Copy = cast(CopyIcon); 53 - export const ChevronDown = cast(ChevronDownIcon); 54 - export const ChevronRight = cast(ChevronRightIcon); 55 - export const CircleAlert = cast(CircleAlertIcon); 56 - export const Database = cast(DatabaseIcon); 57 - export const Eye = cast(EyeIcon); 58 - export const FilePlus2 = cast(FilePlus2Icon); 59 - export const Filter = cast(FilterIcon); 60 - export const FlaskConical = cast(FlaskConicalIcon); 61 - export const Moon = cast(MoonIcon); 62 - export const Pencil = cast(PencilIcon); 63 - export const Plus = cast(PlusIcon); 64 - export const Power = cast(PowerIcon); 65 - export const RefreshCw = cast(RefreshCwIcon); 66 - export const Sun = cast(SunIcon); 67 - export const Trash2 = cast(Trash2Icon); 68 - export const Webhook = cast(WebhookIcon); 69 - export const Zap = cast(ZapIcon); 51 + export const Activity = icon(ActivityData); 52 + export const ArrowLeft = icon(ArrowLeftData); 53 + export const Copy = icon(CopyData); 54 + export const ChevronDown = icon(ChevronDownData); 55 + export const ChevronRight = icon(ChevronRightData); 56 + export const CircleAlert = icon(CircleAlertData); 57 + export const Database = icon(DatabaseData); 58 + export const Eye = icon(EyeData); 59 + export const FilePlus2 = icon(FilePlus2Data); 60 + export const Filter = icon(FilterData); 61 + export const FlaskConical = icon(FlaskConicalData); 62 + export const Moon = icon(MoonData); 63 + export const Pencil = icon(PencilData); 64 + export const Plus = icon(PlusData); 65 + export const Power = icon(PowerData); 66 + export const RefreshCw = icon(RefreshCwData); 67 + export const Sun = icon(SunData); 68 + export const Trash2 = icon(Trash2Data); 69 + export const Webhook = icon(WebhookData); 70 + export const Zap = icon(ZapData);
+5
app/lucide.d.ts
··· 1 + declare module "lucide/icons/*" { 2 + type IconNode = [tag: string, attrs: Record<string, string>][]; 3 + const icon: IconNode; 4 + export default icon; 5 + }
+6 -1
app/routes/api/lexicons/[nsid].ts
··· 11 11 return c.json({ error: "Invalid NSID format" }, 400); 12 12 } 13 13 14 - if (!isNsidAllowed(nsid, config.nsidAllowlist, config.nsidBlocklist)) { 14 + // Blocklist only applies to source lexicons (event triggers). 15 + // Target collections (schema=record) can always be written to. 16 + if ( 17 + c.req.query("schema") !== "record" && 18 + !isNsidAllowed(nsid, config.nsidAllowlist, config.nsidBlocklist) 19 + ) { 15 20 return c.json({ error: "This lexicon is not allowed on this instance" }, 403); 16 21 } 17 22
+3 -5
bun.lock
··· 12 12 "drizzle-orm": "^0.45.2", 13 13 "hono": "^4.12.12", 14 14 "honox": "^0.1.55", 15 - "lucide-preact": "^1.8.0", 15 + "lucide": "^1.8.0", 16 16 "nanoid": "^5.1.7", 17 17 "vite": "npm:@voidzero-dev/vite-plus-core@latest", 18 - "vitest": "^0.1.16", 18 + "vitest": "^4.1.4", 19 19 }, 20 20 "devDependencies": { 21 21 "@types/better-sqlite3": "^7.6.13", ··· 543 543 544 544 "lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], 545 545 546 - "lucide-preact": ["lucide-preact@1.8.0", "", { "peerDependencies": { "preact": "^10.27.2" } }, "sha512-va4a8kofUvE324fKPgBIewfpm9IiGm1TwMN8NoveK2wwywuZIQxsXX9IJVB0+rM1I79XBMnfWNuLjIF2LwAXiQ=="], 546 + "lucide": ["lucide@1.8.0", "", {}, "sha512-JjV/QnadgFLj1Pyu9IKl0lknrolFEzo04B64QcYLLeRzZl/iEHpdbSrRRKbyXcv45SZNv+WGjIUCT33e7xHO6Q=="], 547 547 548 548 "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], 549 549 ··· 610 610 "postcss": ["postcss@8.5.8", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg=="], 611 611 612 612 "postcss-values-parser": ["postcss-values-parser@6.0.2", "", { "dependencies": { "color-name": "^1.1.4", "is-url-superb": "^4.0.0", "quote-unquote": "^1.0.0" }, "peerDependencies": { "postcss": "^8.2.9" } }, "sha512-YLJpK0N1brcNJrs9WatuJFtHaV9q5aAOj+S4DI5S7jgHlRfm0PIbDCAFRYMQD5SHq7Fy6xsDhyutgS0QOAs0qw=="], 613 - 614 - "preact": ["preact@10.29.1", "", {}, "sha512-gQCLc/vWroE8lIpleXtdJhTFDogTdZG9AjMUpVkDf2iTCNwYNWA+u16dL41TqUDJO4gm2IgrcMv3uTpjd4Pwmg=="], 615 613 616 614 "prebuild-install": ["prebuild-install@7.1.3", "", { "dependencies": { "detect-libc": "^2.0.0", "expand-template": "^2.0.3", "github-from-package": "0.0.0", "minimist": "^1.2.3", "mkdirp-classic": "^0.5.3", "napi-build-utils": "^2.0.0", "node-abi": "^3.3.0", "pump": "^3.0.0", "rc": "^1.2.7", "simple-get": "^4.0.0", "tar-fs": "^2.0.0", "tunnel-agent": "^0.6.0" }, "bin": { "prebuild-install": "bin.js" } }, "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug=="], 617 615
-2
lib/shims/preact-hooks.ts
··· 1 - // Preact hooks shim — re-exports hono/jsx hooks for lucide-preact compatibility. 2 - export { useContext, useMemo } from "hono/jsx";
-9
lib/shims/preact.ts
··· 1 - // Preact compatibility shim — maps preact APIs to hono/jsx equivalents 2 - // so that lucide-preact works in this hono/jsx project. 3 - export { createElement as h, createContext, Fragment } from "hono/jsx"; 4 - 5 - export function toChildArray(children: unknown): unknown[] { 6 - if (children == null || children === false) return []; 7 - if (Array.isArray(children)) return children.flat(Infinity); 8 - return [children]; 9 - }
+2 -2
package.json
··· 17 17 "drizzle-orm": "^0.45.2", 18 18 "hono": "^4.12.12", 19 19 "honox": "^0.1.55", 20 - "lucide-preact": "^1.8.0", 20 + "lucide": "^1.8.0", 21 21 "nanoid": "^5.1.7", 22 22 "vite": "npm:@voidzero-dev/vite-plus-core@latest", 23 - "vitest": "^0.1.16" 23 + "vitest": "^4.1.4" 24 24 }, 25 25 "devDependencies": { 26 26 "@types/better-sqlite3": "^7.6.13",
+8 -7
vite.config.ts
··· 203 203 port: 5175, 204 204 host: true, 205 205 }, 206 - plugins: [devCss(), pdsProxy(), sqliteCompat(), honox(), vanillaExtractPlugin({ identifiers: "short" })], 206 + plugins: [ 207 + devCss(), 208 + pdsProxy(), 209 + sqliteCompat(), 210 + honox(), 211 + vanillaExtractPlugin({ identifiers: "short" }), 212 + ], 207 213 ssr: { 208 214 external: ["bun:sqlite"], 209 215 }, 210 216 resolve: { 211 217 alias: { 212 218 "@": "/lib", 213 - "lucide-preact/icons": resolve( 214 - import.meta.dirname, 215 - "node_modules/lucide-preact/dist/esm/icons", 216 - ), 217 - "preact/hooks": resolve(import.meta.dirname, "lib/shims/preact-hooks.ts"), 218 - preact: resolve(import.meta.dirname, "lib/shims/preact.ts"), 219 + "lucide/icons": resolve(import.meta.dirname, "node_modules/lucide/dist/esm/icons"), 219 220 }, 220 221 }, 221 222 });