untitled-1522api.ts16 matches
29} from "../database/queries.ts";
3031const api = new Hono();
32const openai = new OpenAI();
3334// Middleware to ensure user is authenticated
35api.use('*', async (c, next) => {
36const email = c.req.header('X-LastLogin-Email');
37if (!email) {
4748// Get user's conversations
49api.get('/conversations', async (c) => {
50const user = c.get('user');
51const conversations = await getUserConversationsWithParticipants(user.id);
5455// Debug endpoint to check user status in a conversation
56api.get('/conversations/:id/status', async (c) => {
57const user = c.get('user');
58const conversationId = parseInt(c.req.param('id'));
7879// Get specific conversation with messages
80api.get('/conversations/:id', async (c) => {
81const user = c.get('user');
82const conversationId = parseInt(c.req.param('id'));
99100// Create new conversation
101api.post('/conversations', async (c) => {
102const user = c.get('user');
103const { title } = await c.req.json();
112113// Delete conversation
114api.delete('/conversations/:id', async (c) => {
115const user = c.get('user');
116const conversationId = parseInt(c.req.param('id'));
130131// Get conversation participants
132api.get('/conversations/:id/participants', async (c) => {
133const user = c.get('user');
134const conversationId = parseInt(c.req.param('id'));
152153// Invite user to conversation
154api.post('/conversations/:id/invite', async (c) => {
155const user = c.get('user');
156const conversationId = parseInt(c.req.param('id'));
194195// Send invitation email
196const inviteUrl = `${c.req.url.split('/api')[0]}/invite/${invite.invite_token}`;
197
198try {
218219// Remove participant from conversation
220api.delete('/conversations/:id/participants/:userId', async (c) => {
221const user = c.get('user');
222const conversationId = parseInt(c.req.param('id'));
248249// Send chat message
250api.post('/chat', async (c) => {
251const user = c.get('user');
252const { message, conversationId }: ChatRequest = await c.req.json();
326327// Get invite details (public endpoint)
328api.get('/invites/:token', async (c) => {
329const token = c.req.param('token');
330
348349// Accept invitation
350api.post('/invites/:token/accept', async (c) => {
351const user = c.get('user');
352const token = c.req.param('token');
381382// Server-Sent Events for real-time updates
383api.get('/conversations/:id/stream', async (c) => {
384const user = c.get('user');
385const conversationId = parseInt(c.req.param('id'));
437});
438439export default api;
untitled-1522README.md16 matches
1# Backend
23Hono-based API server with LastLogin authentication, SQLite database, and group chat functionality.
45## Structure
7- `index.ts` - Main HTTP handler with LastLogin wrapper
8- `database/` - Database migrations and query functions
9- `routes/` - API route handlers
1011## API Endpoints
1213### Authentication
14- All API routes require authentication via LastLogin
15- User email is extracted from `X-LastLogin-Email` header
1617### Conversations
18- `GET /api/conversations` - Get user's conversations (with participant info)
19- `GET /api/conversations/:id` - Get specific conversation with messages
20- `POST /api/conversations` - Create new conversation
21- `DELETE /api/conversations/:id` - Delete conversation (admin only)
2223### Group Chat Features
24- `GET /api/conversations/:id/participants` - Get conversation participants
25- `POST /api/conversations/:id/invite` - Invite user by email (admin only)
26- `DELETE /api/conversations/:id/participants/:userId` - Remove participant (admin only)
2728### Invitations
29- `GET /api/invites/:token` - Get invitation details (public)
30- `POST /api/invites/:token/accept` - Accept invitation and join conversation
3132### Chat & Real-time
33- `POST /api/chat` - Send message and get ChatGPT response
34- `GET /api/conversations/:id/stream` - Server-Sent Events for real-time updates
3536## Database Schema
49- **Automatic user creation** on first login
50- **Conversation history storage** with full message history
51- **ChatGPT integration** via OpenAI API
52- **Group chat functionality** with role-based permissions
53- **Email invitations** with secure tokens
untitled-1522README.md1 match
31## Project Structure
3233- `backend/` - Hono API server with authentication and group chat
34- `frontend/` - React chat interface with group features
35- `shared/` - Shared TypeScript types
untitled-1522App.tsx5 matches
48setIsLoadingConversations(true);
49try {
50const response = await fetch('/api/conversations');
51if (response.ok) {
52const data = await response.json();
63setIsLoadingConversation(true);
64try {
65const response = await fetch(`/api/conversations/${id}`);
66if (response.ok) {
67const data = await response.json();
77const loadConversationParticipants = async (conversationId: number) => {
78try {
79const response = await fetch(`/api/conversations/${conversationId}/participants`);
80if (response.ok) {
81const participants = await response.json();
105106try {
107const response = await fetch(`/api/conversations/${id}`, {
108method: 'DELETE'
109});
131132try {
133const response = await fetch('/api/chat', {
134method: 'POST',
135headers: {
untitled-1522ParticipantsList.tsx2 matches
25const loadParticipants = async () => {
26try {
27const response = await fetch(`/api/conversations/${conversationId}/participants`);
28if (response.ok) {
29const data = await response.json();
4344try {
45const response = await fetch(`/api/conversations/${conversationId}/participants/${userId}`, {
46method: 'DELETE'
47});
untitled-1522InvitePage.tsx2 matches
23const loadInviteDetails = async () => {
24try {
25const response = await fetch(`/api/invites/${token}`);
26
27if (!response.ok) {
4546try {
47const response = await fetch(`/api/invites/${token}/accept`, {
48method: 'POST'
49});
untitled-1522InviteModal.tsx1 match
32const inviteRequest: InviteRequest = { email: email.trim() };
33
34const response = await fetch(`/api/conversations/${conversationId}/invite`, {
35method: 'POST',
36headers: {
untitled-1522index.ts3 matches
3import { readFile, serveFile } from "https://esm.town/v/std/utils@85-main/index.ts";
4import { runMigrations } from "./database/migrations.ts";
5import api from "./routes/api.ts";
67const app = new Hono();
13await runMigrations();
1415// Mount API routes
16app.route('/api', api);
1718// Serve static files
8- [theme](https://github.com/vadimdemedes/thememirror/tree/main/source/themes)
910## API
1112You can access the code using the `code` property:
krazyy-cam-configmain.ts7 matches
35JSON.stringify({
36iss: serviceAccount.client_email,
37scope: "https://www.googleapis.com/auth/datastore",
38aud: "https://oauth2.googleapis.com/token",
39exp: now + 3600,
40iat: now,
7172// ---- Exchange JWT for access token ----
73const tokenRes = await fetch("https://oauth2.googleapis.com/token", {
74method: "POST",
75headers: { "Content-Type": "application/x-www-form-urlencoded" },
90// ---- Query Firestore publicLenses ----
91const pubDocRes = await fetch(
92`https://firestore.googleapis.com/v1/projects/${projectId}/databases/(default)/documents/publicLenses/${id}`,
93{ headers: { Authorization: `Bearer ${access_token}` } },
94);
106// ---- Query Firestore private user doc ----
107const privDocRes = await fetch(
108`https://firestore.googleapis.com/v1/projects/${projectId}/databases/(default)/documents/users/${owner}/lenses/${id}`,
109{ headers: { Authorization: `Bearer ${access_token}` } },
110);
116}
117const privDoc = await privDocRes.json();
118const apiToken = privDoc.fields.apiToken.stringValue;
119120// ---- Success ----
121return new Response(JSON.stringify({ apiToken, groupId, lensId }), {
122headers: corsHeaders(),
123});