11
12// Utility exports
13export * from "./utils/apiKey.ts";
14export * from "./utils/auth.ts";
15export * from "./utils/validation.ts";
18export * from "./email/notifications.ts";
19
20// API endpoints
21export { default as createApp } from "./api/createApp.http.ts";
22export { default as getApps } from "./api/getApps.http.ts";
23export { default as deleteApp } from "./api/deleteApp.http.ts";
24export { default as submitFeedback } from "./api/submitFeedback.http.ts";
25export { default as getFeedback } from "./api/getFeedback.http.ts";
26export { default as exportFeedback } from "./api/exportFeedback.http.ts";
27
28// Dashboard endpoints
10 id?: number;
11 name: string;
12 api_key: string;
13 description?: string;
14 created_at?: string;
40export async function createApp(app: Omit<App, 'id' | 'created_at'>): Promise<App> {
41 const result = await sqlite.execute(
42 `INSERT INTO apps (name, api_key, description)
43 VALUES (?, ?, ?)
44 RETURNING *`,
45 [app.name, app.api_key, app.description || null]
46 );
47
50
51/**
52 * Get an app by its API key
53 */
54export async function getAppByApiKey(apiKey: string): Promise<App | null> {
55 const result = await sqlite.execute(
56 `SELECT * FROM apps WHERE api_key = ?`,
57 [apiKey]
58 );
59
70 const apps = result.rows.map(row => {
71 // If row is already an object with named properties, return it
72 if (typeof row === 'object' && row !== null && 'id' in row && 'name' in row && 'api_key' in row) {
73 return row as App;
74 }
79 id: row[0],
80 name: row[1],
81 api_key: row[2],
82 description: row[3],
83 created_at: row[4]
90 id: typeof safeRow.id !== 'undefined' ? Number(safeRow.id) : undefined,
91 name: String(safeRow.name || ''),
92 api_key: String(safeRow.api_key || ''),
93 description: safeRow.description ? String(safeRow.description) : undefined,
94 created_at: safeRow.created_at ? String(safeRow.created_at) : undefined
117 id: appId,
118 name: app[1] || "Unnamed App",
119 api_key: app[2] || "unknown",
120 description: app[3] || null,
121 created_at: app[4] || new Date().toISOString()
126 sql: `UPDATE apps SET
127 name = :name,
128 api_key = :api_key,
129 description = :description,
130 created_at = :created_at
9
10import { sqlite } from "https://esm.town/v/std/sqlite";
11import { generateApiKey } from "../utils/apiKey.ts";
12
13// Test configuration
76}
77
78// Create a test app and return its ID and API key
79async function createTestApp(): Promise<{ id: number; api_key: string }> {
80 const apiKey = await generateApiKey();
81 const appName = `${TEST_APP_PREFIX} ${TEST_APP_NAME}`;
82
83 // Using named parameters and matching the schema (id is auto-increment)
84 const result = await sqlite.execute({
85 sql: `INSERT INTO apps (name, api_key, description)
86 VALUES (:name, :api_key, :description)`,
87 args: {
88 name: appName,
89 api_key: apiKey,
90 description: "Test app created for dashboard testing"
91 }
98 return {
99 id: appId,
100 api_key: apiKey
101 };
102}
190 */
191export async function setup(): Promise<{
192 app: { id: number; name: string; api_key: string };
193 feedbackCount: number;
194 dashboardUrl: string;
198
199 console.log(`Created test app with ID: ${app.id}`);
200 console.log(`API Key: ${app.api_key}`);
201
202 console.log(`Generating ${FEEDBACK_COUNT} feedback entries...`);
226 id: app.id,
227 name: appName,
228 api_key: app.api_key
229 },
230 feedbackCount: addedCount,
267 id: row[0],
268 name: row[1],
269 api_key: row[2],
270 description: row[3],
271 created_at: row[4]
279 apps.forEach(app => {
280 console.log(`- ${app.name} (ID: ${app.id})`);
281 console.log(` API Key: ${app.api_key}`);
282 console.log(` Created: ${app.created_at}`);
283 });
21console.log(`Test app: ${testData.app.name}`);
22console.log(`App ID: ${testData.app.id}`);
23console.log(`API Key: ${testData.app.api_key}`);
24console.log(`Added ${testData.feedbackCount} feedback entries`);
25
6import { initializeDatabase } from "../db/init.ts";
7import { createApp } from "../db/queries.ts";
8import { generateApiKey } from "../utils/apiKey.ts";
9
10async function main() {
21 // Create a test app
22 try {
23 const apiKey = await generateApiKey();
24 const app = await createApp({
25 name: "Test App",
26 api_key: apiKey,
27 description: "Test app for local development"
28 });
32 id: app.id,
33 name: app.name,
34 api_key: apiKey, // Show the full API key for testing
35 description: app.description,
36 created_at: app.created_at
28 const apps = await getAllApps();
29
30 // Mask api_key for security in response
31 const maskedApps = apps.map(app => ({
32 ...app,
33 api_key: app.api_key.slice(0, 8) + "..." + app.api_key.slice(-4)
34 }));
35
1/**
2 * Create App HTTP Endpoint
3 * Creates a new application with a generated API key
4 */
5
6import { createApp } from "../db/queries.ts";
7import { generateApiKey } from "../utils/apiKey.ts";
8import { validateAppInput, createValidationErrorResponse } from "../utils/validation.ts";
9import { authenticateDashboardRequest, createUnauthorizedResponse } from "../utils/auth.ts";
36 }
37
38 // Generate a unique API key
39 const apiKey = generateApiKey();
40
41 // Create the app in the database
42 const app = await createApp({
43 name: validation.data.name!,
44 api_key: apiKey,
45 description: validation.data.description
46 });
10 * - Technical context: deviceInfo, networkType, memoryUsage
11 *
12 * @see /api/README.md for full API documentation
13 */
14
15import { createFeedback } from "../db/queries.ts";
16import { authenticateApiRequest, createUnauthorizedResponse } from "../utils/auth.ts";
17import { validateFeedbackInput, createValidationErrorResponse } from "../utils/validation.ts";
18import { sendNotification } from "../email/notifications.ts";
33 }
34
35 // Authenticate the request using API key
36 const app = await authenticateApiRequest(req);
37 if (!app) {
38 return createUnauthorizedResponse("Invalid API key");
39 }
40
1# ProductPanel API Documentation
2
3## Feedback API
4
5### Submit Feedback
7**Endpoint:** `POST /submitFeedback`
8
9**Authentication:** Requires API key in the `Authorization` header as a Bearer token.
10
11```
12Authorization: Bearer YOUR_API_KEY
13```
14
86**Error Responses:**
87
88- **401 Unauthorized:** Invalid or missing API key
89- **400 Bad Request:** Invalid input (with details in the response)
90- **500 Internal Server Error:** Server-side error
129 ]
130
131 // Send the API request
132 // ...
133}