57
58export async function exec(interval: Interval) {
59 const apiKey = Deno.env.get("LINEAR_API_KEY");
60 if (!apiKey) {
61 console.error("LINEAR_API_KEY not found in environment variables");
62 Deno.exit(1);
63 }
65 const { startDate, endDate } = getYesterdayDateRange();
66
67 const response = await fetch("https://api.linear.app/graphql", {
68 method: "POST",
69 headers: {
70 "Content-Type": "application/json",
71 Authorization: apiKey,
72 },
73 body: JSON.stringify({
80
81 if (data.errors) {
82 console.error("Error fetching data from Linear API:", data.errors);
83 Deno.exit(1);
84 }
94 }
95
96 const historyResponse = await fetch("https://api.linear.app/graphql", {
97 method: "POST",
98 headers: {
99 "Content-Type": "application/json",
100 Authorization: apiKey,
101 },
102 body: JSON.stringify({
190 }
191
192 const slackResponse = await fetch("https://slack.com/api/chat.postMessage", {
193 method: "POST",
194 headers: {
19};
20
21// API Functions
22const api = {
23 async getTodos(filter = 'all') {
24 const response = await fetch(`/api/todos?filter=${filter}`);
25 if (!response.ok) throw new Error('Failed to fetch todos');
26 return response.json();
28
29 async createTodo(text) {
30 const response = await fetch('/api/todos', {
31 method: 'POST',
32 headers: { 'Content-Type': 'application/json' },
38
39 async updateTodo(id, updates) {
40 const response = await fetch(`/api/todos/${id}`, {
41 method: 'PATCH',
42 headers: { 'Content-Type': 'application/json' },
48
49 async deleteTodo(id) {
50 const response = await fetch(`/api/todos/${id}`, {
51 method: 'DELETE'
52 });
63
64 // Fetch todos with the current filter
65 const todos = await api.getTodos(currentFilter);
66
67 // Clear the list
121
122 try {
123 await api.createTodo(text);
124 todoInput.value = '';
125 await renderTodos();
132const handleToggleTodo = async (id, completed) => {
133 try {
134 await api.updateTodo(id, { completed });
135 await renderTodos();
136 } catch (error) {
144
145 try {
146 await api.deleteTodo(id);
147 await renderTodos();
148 } catch (error) {
12## Project Structure
13
14- `/backend` - Server-side code with Hono API and SQLite database
15- `/frontend` - Client-side HTML, CSS, and JavaScript
16- `/shared` - Shared types and utilities
19
20- TypeScript
21- Hono (API framework)
22- SQLite (database)
23- TailwindCSS (styling)
8)`);
9
10// Types for GitHub API responses
11interface GitHubDiscussion {
12 id: string;
50 }
51
52 const url = `https://api.github.com/graphql`;
53 const query = `
54 query {
84
85 if (!response.ok) {
86 throw new Error(`GitHub API error: ${response.status} ${await response.text()}`);
87 }
88
26## How It Works
27
281. The script fetches the most recent discussions from the specified GitHub repository using the GitHub GraphQL API
292. It compares the fetched discussions with a list of previously processed discussions stored in Val Town's blob storage
303. For each new discussion, it sends an email notification with details about the discussion
302 const d = { m: err.message, n: err.name, s: err.stack, t: err.type, c: err.code }; // Abbreviated error details
303 log("ER", "oai", `Fail tid=${tid}`, { e: d }, mid, tid);
304 throw new Error(`API fail: ${err.message}` + (err.code ? ` (Code: ${err.code})` : ""));
305 }
306}
936// Original HTML generation function generateOrthogonalUI() and its embedded JS remains here.
937function generateOrthogonalUI(): string {
938 return `<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>AI Biz Asst</title><script src="https://cdn.tailwindcss.com"></script><link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet"><style>
939 body{font-family: 'Inter',sans-serif;overflow:hidden;background:#f3f4f6 radial-gradient(circle,rgba(0,0,0,.03) 1px,transparent 1px);background-size:10px 10px;background-attachment:fixed;transition:background-position .5s ease-out;color:#1f2937}
940 #grid{display:grid;grid-template-columns:repeat(3,1fr);gap:1rem;padding:1rem;max-width:900px;margin:auto;perspective:1000px;transition:opacity .5s ease-out}
1import axios from "axios";
2
3const baseURL = "https://khefue-backend.azurewebsites.net/khefue/api/v1";
4
5export const api = axios.create({
6 baseURL,
7 headers: {
10});
11
12api.interceptors.request.use((config) => {
13 const token = localStorage.getItem("authToken");
14 if (token) {
3
4import { useEffect, useState } from "react";
5import { api } from "../api";
6import ProductCard from "../components/ProductCard";
7
12 const fetchProducts = async () => {
13 try {
14 const response = await api.get("/customer/products");
15 setProducts(response.data.products);
16 setLoading(false);
4import { useState } from "react";
5import { useNavigate } from "react-router-dom";
6import { api } from "../api";
7import { useAuth } from "../context/AuthContext";
8
18 e.preventDefault();
19 try {
20 const response = await api.post("/partner", formData);
21 login(response.data.partner, response.data.token);
22 navigate("/partner/dashboard");
3
4import { useEffect, useState } from "react";
5import { api } from "../api";
6import ProductForm from "../components/ProductForm";
7import ProductList from "../components/ProductList";
13 const fetchProducts = async () => {
14 try {
15 const response = await api.get("/partners/all-product");
16 setProducts(response.data.products);
17 setLoading(false);
27 const handleCreateProduct = async (formData) => {
28 try {
29 await api.post("/partners/product", formData, {
30 headers: {
31 "Content-Type": "multipart/form-data",