20 };
21
22 return fetchJSON(`https://api.val.town/v1/vals/${valId}`, {
23 headers: {
24 Authorization: `Bearer ${token}`,
40 useEffect(() => {
41 if (typeof navigator === "undefined" || !navigator.mediaDevices) {
42 setError("MediaDevices API not available in this environment");
43 return;
44 }
480 // Re-initialize camera on settings change or visibility change
481 useEffect(() => {
482 // Debounce or throttle might be useful here if performance becomes an issue with rapid changes
483 updateCamera();
484 }, [size, zoom, corner, margin, showSource, mirrored, ringColor, mode, cameraVisible]);
2import { socialDataSearch, Tweet } from "https://esm.town/v/stevekrouse/socialDataSearch";
3var axios = require("axios");
4const FMP_API_KEY = Deno.env.get("FMP_API_KEY");
5
6// Customize your keywords
16export async function financialNewsAlert({ lastRunAt }: Interval) {
17 const FMP_ARTICLES_ENDPOINT =
18 `https://financialmodelingprep.com/stable/fmp-articles?page=0&limit=20&apikey=${FMP_API_KEY}`;
19 const response = await axios.get(FMP_ARTICLES_ENDPOINT);
20 const newsData = response.data;
31Refer to [Twitter's search operators](https://socialdata.gitbook.io/docs/twitter-tweets/retrieve-search-results-by-keyword#endpoint-parameters) to fine-tune your query.
32
33### 4. Test API call
34Set `isProd = false` in the code if you are testing, to ensure there are enough tweets to display. <br>
35Toggle it back to `true` when you're ready to run this cron job in production and actuall send notifications.
60
61### NOTE: Usage Limits
62This val uses the SocialData API for Twitter data:
63
64- **Proxies via Val Town's [SocialDataProxy](https://www.val.town/v/stevekrouse/socialDataProxy)**: Limited to 10 cents per day for [**Val Town Pro users**](https://www.val.town/pricing). This API is *only* for Pro users.
65- **Need more calls?** Sign up for your own [SocialData API token](https://socialdata.tools) and configure the [`socialDataSearch`](https://www.val.town/v/stevekrouse/socialDataSearch) function.
5
6export async function getCalendars(accountId: string) {
7 const calendarAPI = await pipeDreamGoogle("calendar", accountId);
8 const calendars = await calendarAPI.calendarList.list();
9 return calendars.data.items;
10}
8const app = new Hono();
9
10// API routes
11app.get("/api/attachments", async (c) => {
12 const attachments = await getAllAttachments();
13 return c.json(attachments);
14});
15
16app.get("/api/attachments/:id", async (c) => {
17 const id = c.req.param("id");
18 const downloadParam = c.req.query("download");
41 const fetchAttachments = async () => {
42 try {
43 const response = await fetch("/api/attachments");
44 if (!response.ok) {
45 throw new Error("Failed to fetch attachments");
166 <div className="flex space-x-2">
167 <a
168 href={`/api/attachments/${selectedAttachment}?download=true`}
169 download
170 className="px-3 py-1 bg-blue-500 text-white rounded hover:bg-blue-600 flex items-center"
198 </div>
199 <iframe
200 src={`/api/attachments/${selectedAttachment}`}
201 className={`w-full ${isFullscreen ? 'h-[calc(100vh-60px)]' : 'h-[75vh]'} border-0`}
202 title="Document Viewer"
1import { createRoute } from "https://esm.sh/@hono/zod-openapi@0.18.4";
2import { ErrorSchema, UpdateUserSchema, UserIdPathParamSchema, UserSchema } from "../schema.ts";
3
1import { z } from "https://esm.sh/@hono/zod-openapi@0.18.4";
2
3// Schema that defines presence of an ID in the path
6 .coerce
7 .number()
8 .openapi({ example: 1 }),
9});
10
12export const NewUserSchema = z
13 .object({
14 name: z.string().min(2).max(50).openapi({ example: "Mark Scout" }),
15 email: z.string().email().openapi({ example: "mark@lumen.co" }),
16 age: z.number().int().min(18).max(120).openapi({ example: 35 }),
17 }).openapi("NewUser");
18
19// Schema that defines the response of a request to get a user
21 .object({
22 id: z.number().int(),
23 name: z.string().openapi({ example: "Mark Scout" }),
24 email: z.string().email().openapi({ example: "mark@lumen.co" }),
25 age: z.number().int().openapi({ example: 35 }),
26 }).openapi("User");
27
28export const UpdateUserSchema = z
29 .object({
30 name: z.string().optional().openapi({
31 example: "Marcus Scoutius",
32 }),
33 age: z.number().int().optional().openapi({
34 example: 53,
35 }),
36 })
37 .openapi("UpdateUser");
38
39// Error schema
1**Example Hono-Zod-OpenAPI app with a Fiberplane API explorer.**
2
3> For an example with regular-old Hono, see: https://www.val.town/v/fiberplane/fiberplaneHonoStarter
8 ```
9
102. Expose your OpenAPI spec
11 ```ts
12 app.doc("/doc", {
13 openapi: "3.0.0",
14 info: {
15 title: "User Management API",
16 version: "v1.0.0",
17 },
19 ```
20
213. Mount the api explorer
22
23 This will mount it at the root `/*`, but you can mount it to another route, like `/fp/*` if you
24 are using `/` for your main app. We recommend `/` if your Hono app is an API without a frontend.
25
26 ```ts
28 "/*",
29 createFiberplane({
30 openapi: { url: "/doc" },
31 }),
32 );
33 ```
34
354. Visit your Val's root route to play with the API explorer!
36
37## How it Works
38
39`createFiberplane` mounts Fiberpalne at the root route (`/`), which can be used to explore the api's routes and make requests.
40Think of it like an embedded, lightweight postman.