3import * as queries from "../database/queries.ts";
4
5const api = new Hono();
6
7// Task routes
8api.get('/tasks', async (c) => {
9 const list = c.req.query('list');
10 const context = c.req.query('context');
25});
26
27api.post('/tasks', async (c) => {
28 try {
29 const taskData: CreateTaskRequest = await c.req.json();
38});
39
40api.put('/tasks/:id', async (c) => {
41 const id = parseInt(c.req.param('id'));
42 const updates: UpdateTaskRequest = await c.req.json();
50});
51
52api.delete('/tasks/:id', async (c) => {
53 const id = parseInt(c.req.param('id'));
54 const deleted = await queries.deleteTask(id);
62
63// Project routes
64api.get('/projects', async (c) => {
65 const projects = await queries.getAllProjects();
66 return c.json(projects);
67});
68
69api.post('/projects', async (c) => {
70 const projectData: CreateProjectRequest = await c.req.json();
71 const project = await queries.createProject(projectData);
73});
74
75api.put('/projects/:id', async (c) => {
76 const id = parseInt(c.req.param('id'));
77 const updates: UpdateProjectRequest = await c.req.json();
85});
86
87api.delete('/projects/:id', async (c) => {
88 const id = parseInt(c.req.param('id'));
89 const deleted = await queries.deleteProject(id);
97
98// Context routes
99api.get('/contexts', async (c) => {
100 const contexts = await queries.getAllContexts();
101 return c.json(contexts);
102});
103
104export default api;
2import { readFile, serveFile } from "https://esm.town/v/std/utils/index.ts";
3import { initializeDatabase } from "./database/schema.ts";
4import api from "./routes/api.ts";
5
6const app = new Hono();
14await initializeDatabase();
15
16// API routes
17app.route('/api', api);
18
19// Serve static files
19 useEffect(() => {
20 Promise.all([
21 fetch('/api/tasks').then(r => r.json()),
22 fetch('/api/projects').then(r => r.json()),
23 fetch('/api/contexts').then(r => r.json())
24 ]).then(([tasksData, projectsData, contextsData]) => {
25 setTasks(tasksData);
31
32 const refreshTasks = async () => {
33 const response = await fetch('/api/tasks');
34 const tasksData = await response.json();
35 setTasks(tasksData);
37
38 const refreshProjects = async () => {
39 const response = await fetch('/api/projects');
40 const projectsData = await response.json();
41 setProjects(projectsData);
45 try {
46 if (editingTask) {
47 await fetch(`/api/tasks/${editingTask.id}`, {
48 method: 'PUT',
49 headers: { 'Content-Type': 'application/json' },
51 });
52 } else {
53 await fetch('/api/tasks', {
54 method: 'POST',
55 headers: { 'Content-Type': 'application/json' },
67 const handleProjectSubmit = async (projectData: any) => {
68 try {
69 await fetch('/api/projects', {
70 method: 'POST',
71 headers: { 'Content-Type': 'application/json' },
81 const handleTaskDelete = async (taskId: number) => {
82 try {
83 await fetch(`/api/tasks/${taskId}`, { method: 'DELETE' });
84 await refreshTasks();
85 } catch (error) {
95 const handleTaskComplete = async (taskId: number, completed: boolean) => {
96 try {
97 await fetch(`/api/tasks/${taskId}`, {
98 method: 'PUT',
99 headers: { 'Content-Type': 'application/json' },
21│ │ └── queries.ts # Database query functions
22│ └── routes/
23│ └── api.ts # API routes
24├── frontend/
25│ ├── index.html # Main HTML template
1export async function searchUser(email: string) {
2 const resp = await fetch(`https://kilocode.ai/admin/api/users?search=${email}`, {
3 method: "GET",
4 headers: {
5 "Content-Type": "application/json",
6 "Authorization": `Bearer ${Deno.env.get("KILOCODE_ADMIN_API_KEY")}`,
7 },
8 });
15export async function issueCredits(email: string) {
16 console.log(`[CREDITS] Issuing credits for ${email}`);
17 const resp = await fetch("https://kilocode.ai/admin/api/users/add-credit", {
18 method: "POST",
19 headers: {
20 "Content-Type": "application/json",
21 "Authorization": `Bearer ${Deno.env.get("KILOCODE_ADMIN_API_KEY")}`,
22 },
23 body: JSON.stringify({
30 }),
31 });
32 console.log(`[CREDITS] API response for ${email}:`, resp.status, resp.statusText);
33 return resp;
34}
2
3export async function getUserEmailFromCommits(username: string) {
4 const url = new URL("https://api.github.com/search/commits");
5 url.searchParams.set("q", `author:${username}`);
6 url.searchParams.set("sort", "author-date");
13export async function getUserEmail(username: string) {
14 // Try looking up their email directly but most people don't have this set up
15 const response = await fetch(`https://api.github.com/users/${username}`);
16 const data = await response.json();
17 if (data.email) return data.email;
22
23export async function getGithubUsernameFromCommits(email: string) {
24 const url = new URL("https://api.github.com/search/commits");
25 url.searchParams.set("q", `author-email:${email}`);
26 url.searchParams.set("sort", "author-date");
33export async function getPopularGithubRepo(username: string) {
34 const response = await fetch(
35 `https://api.github.com/users/${username}/repos?sort=updated&per_page=100`,
36 );
37 const repos = await response.json();
105// 自作コードからのfetch呼び出し (Requestオブジェクト)
106console.log(bold("\n--- My code fetch (Request object) ---"));
107const myRequest = new Request("https://api.github.com/users/denoland", {
108 method: "GET",
109 headers: {
14 }
15
16 const response = await fetch(`https://www.shovel.report/api/domains/${domain}`);
17
18 if (!response.ok) {
2
3export default async function proxy(req: Request) {
4 // Parse query params from the request to pass along to the API call
5 const searchParams = new URL(req.url).searchParams;
6 const limit = searchParams.get("limit") || 1;
7
8 // Pass along the other query params to the API
9 let apiUrl = `http://api.quotable.io/quotes/random?limit=${limit}`;
10 if (searchParams.size > 0) {
11 apiUrl += `&${searchParams.toString()}`;
12 }
13
14 const resp = await fetch(
15 apiUrl,
16 );
17 const json = await resp.json();
10
11 <!-- external CSS link -->
12 <link rel="preconnect" href="https://fonts.googleapis.com">
13 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
14 <link href="https://fonts.googleapis.com/css2?family=Cinzel:wght@400..900&family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" rel="stylesheet">
15 <link rel="preconnect" href="https://fonts.googleapis.com">
16 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
17 <link href="https://fonts.googleapis.com/css2?family=Dancing+Script:wght@400..700&display=swap" rel="stylesheet">
18 <script src="https://kit.fontawesome.com/2bd2ac3840.js" crossorigin="anonymous"></script>
19