2import React from "https://esm.sh/react@18.2.0?dev";
3
4interface ApiKeyWarningProps {
5 show: boolean;
6}
7
8export function ApiKeyWarning({ show }: ApiKeyWarningProps) {
9 if (!show) return null;
10
11 return (
12 <div className="bg-yellow-100 border-l-4 border-yellow-500 text-yellow-700 p-4 mb-4 rounded">
13 <p className="font-bold">Anthropic API Key Missing</p>
14 <p>Please log out and add your Anthropic API key to use this app.</p>
15 </div>
16 );
84
85async function sendFarcasterNotification(payload: any) {
86 return await fetch("https://api.warpcast.com/v1/frame-notifications", {
87 method: "POST",
88 headers: { "Content-Type": "application/json" },
43
44Custom middleware can be added in an array as the third argument.
45Middleware can add data to the `req.data` object or return a response for things like API endpoints.
46
47```tsx
69```tsx
70// example middleware
71async function api (req: Request, res: Response, next): Promise<Response> {
72 if (req.pathname !== "/api") return next();
73 if (req.method === "POST") {
74 return Repsonse.json({ message: "Hello POST request" });
77}
78
79export default render(App, import.meta.url, [ api ]);
80```
81
1import { betterFetch, BetterFetchError } from "https://esm.sh/@better-fetch/fetch";
2import { HNAPIResponse } from "https://esm.town/v/nbbaier/hn_notifier/shared/types.ts";
3
4export const HN_BASE_URL = "https://news.ycombinator.com/item";
5export const HN_API_URL = "https://hn.algolia.com/api/v1/items";
6
7export function countAllChildren(item: HNAPIResponse): number {
8 const stack: HNAPIResponse[] = [item];
9 let count = 0;
10
22
23export async function getHNItem(id: number) {
24 return await betterFetch<HNAPIResponse>(
25 `${HN_API_URL}/${id}`,
26 );
27}
47}
48
49export async function createDBItem(id: number, data: HNAPIResponse): Promise<DBItem> {
50 const comments = countAllChildren(data);
51
6};
7
8export type HNAPIResponse = {
9 author: string;
10 children: HNAPIResponse[];
11 created_at: string;
12 created_at_i: number;
1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2import React, { createContext, type ReactNode, useContext, useEffect, useState } from "https://esm.sh/react@18.2.0";
3import { $api } from "https://esm.town/v/nbbaier/hn_notifier/backend/fetchClient.ts";
4import type { DBItem } from "https://esm.town/v/nbbaier/hn_notifier/shared/types.ts";
5
38 setIsLoading(true);
39 try {
40 const { data, error } = await $api<DBItem[]>("/list");
41 if (data) {
42 setItems(data);
59 setIsLoading(true);
60 try {
61 const { data, error } = await $api<{ hnId: number }>("/follow", {
62 method: "POST",
63 headers: {
80 setIsLoading(true);
81 try {
82 const { data, error } = await $api(`/unfollow/${id}`);
83 await fetchUrls(); // Refresh the list after unfollowing
84 } catch (error) {
1import api from "https://esm.town/v/nbbaier/hn_notifier/backend/api.ts";
2import { createTables } from "https://esm.town/v/nbbaier/hn_notifier/backend/database/migrations.ts";
3import { parseProject, readFile, serveFile } from "https://esm.town/v/std/utils/index.ts";
24app.get("/shared/**/*", c => serveFile(c.req.path, import.meta.url));
25
26// api routes
27app.route("/api", api);
28
29app.onError((err, c) => {
1import { createFetch } from "https://esm.sh/@better-fetch/fetch";
2
3export const $api = createFetch({
4 baseURL: "/api",
5});
1import { HTTPException } from "https://esm.sh/hono/http-exception";
2import * as db from "https://esm.town/v/nbbaier/hn_notifier/backend/database/queries.ts";
3import { DBItem, HNAPIResponse } from "https://esm.town/v/nbbaier/hn_notifier/shared/types.ts";
4import {
5 createDBItem,
19});
20
21const api = new Hono();
22
23api.get("/follow/:id", zValidator("param", idSchema), async c => {
24 const { id } = c.req.valid("param");
25 return c.text(`GET /follow/${id}`);
26});
27
28api.post("/follow", zValidator("json", z.object({ id: z.number() })), async (c) => {
29 const { id } = c.req.valid("json");
30 const { data, error } = await getHNItem(id);
48});
49
50api.get("/unfollow/:id", zValidator("param", idSchema), async c => {
51 const { id } = c.req.valid("param");
52 await db.unfollow(id);
54});
55
56api.get("/get/:id", zValidator("param", idSchema), async c => {
57 const { id } = c.req.valid("param");
58 const data = await db.getItem(id);
60});
61
62api.get("/list", async c => {
63 const urls = await db.getAllItems();
64 return c.json(urls);
65});
66
67api.get("/check", async c => {
68 return c.text("GET /check");
69});
70
71export default api;
12app.get("/frontend/**/*", c => serveFile(c.req.path, import.meta.url));
13
14// Add your API routes here
15// app.get("/api/data", c => c.json({ hello: "world" }));
16
17// Unwrap and rethrow Hono errors as the original error