flingit 0.0.14 → 0.0.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,317 +1,5 @@
1
1
  # Fling Project
2
2
 
3
- This is a Fling project - a personal software platform for building and deploying personal tools with a React frontend and Hono API backend.
3
+ This is a Fling project - a personal software platform for building and deploying personal tools with a React frontend, API backend, SQL database, storage, and more.
4
4
 
5
- ## IMPORTANT: Do NOT ask about deployment, hosting, or technology choices!
6
-
7
- Fling handles all of this automatically. When the user asks you to build something:
8
- 1. Write backend code in `src/worker/index.ts` using the Fling API
9
- 2. Write frontend code in `src/react-app/` using React
10
- 3. Run `npm start` to test it locally (you have bash access - run commands yourself!)
11
- 4. When it works, run `npm exec fling push` to deploy
12
-
13
- **IMPORTANT: Run CLI commands yourself.** You have bash access. Do NOT ask the user to run commands like `fling push`, `fling dev`, or `npm start`. Execute them directly and report the results.
14
-
15
- ## Project Structure
16
-
17
- ```
18
- src/
19
- worker/
20
- index.ts # Backend API entry point (routes, migrations)
21
- react-app/
22
- main.tsx # React entry point
23
- App.tsx # Main React component
24
- App.css # Component styles
25
- index.css # Global styles
26
- public/ # Static assets (served by Vite)
27
- index.html # Vite entry HTML
28
- vite.config.ts # Vite configuration
29
- .fling/secrets # Local secrets (gitignored)
30
- .fling/data/ # SQLite database (gitignored)
31
- ```
32
-
33
- ## Development
34
-
35
- Run `npm start` (or `fling dev`) to start development:
36
- - **Frontend**: http://localhost:5173 (Vite with React HMR)
37
- - **API**: http://localhost:3210 (Hono backend)
38
- - Vite proxies `/api/*` requests to the API server
39
-
40
- ### Hot Module Replacement (HMR)
41
-
42
- The dev server provides hot reloading for both frontend AND backend - no restart needed:
43
- - **Frontend (React)**: Changes to `src/react-app/` are instantly reflected via Vite HMR
44
- - **Backend (Worker)**: Changes to `src/worker/` are automatically reloaded via tsx watch
45
-
46
- Just edit and save - changes appear immediately.
47
-
48
- ## Fling API (Backend)
49
-
50
- All primitives are imported from `"flingit"` in the backend:
51
-
52
- ```typescript
53
- import { app, db, migrate, secrets, cron, storage } from "flingit";
54
- ```
55
-
56
- ### HTTP Routes (Hono)
57
-
58
- ```typescript
59
- // API routes should use /api prefix for Vite proxy
60
- app.get("/api/hello", (c) => c.json({ message: "Hello!" }));
61
- app.post("/api/data", async (c) => {
62
- const body = await c.req.json();
63
- return c.json({ received: body });
64
- });
65
- ```
66
-
67
- **Note:** Paths starting with `/__` are reserved for internal platform use. Do not create routes with these prefixes.
68
-
69
- ### Migrations
70
-
71
- **IMPORTANT: Migrations MUST be idempotent** (safe to run multiple times).
72
-
73
- ```typescript
74
- migrate("001_create_users", async () => {
75
- await db.prepare(`
76
- CREATE TABLE IF NOT EXISTS users (
77
- id INTEGER PRIMARY KEY AUTOINCREMENT,
78
- name TEXT NOT NULL,
79
- created_at TEXT DEFAULT (datetime('now'))
80
- )
81
- `).run();
82
- });
83
- ```
84
-
85
- ### Database (SQLite, D1-compatible)
86
-
87
- ```typescript
88
- // Query
89
- const item = await db.prepare("SELECT * FROM items WHERE id = ?").bind(id).first();
90
- const all = await db.prepare("SELECT * FROM items").all();
91
-
92
- // Insert/Update/Delete
93
- await db.prepare("INSERT INTO items (name) VALUES (?)").bind(name).run();
94
- ```
95
-
96
- ### Secrets
97
-
98
- ```typescript
99
- const apiKey = secrets.get("API_KEY"); // Throws if not set
100
- ```
101
-
102
- ### Cron Jobs
103
-
104
- Schedule tasks to run automatically on a schedule using standard cron syntax:
105
-
106
- ```typescript
107
- cron("daily-cleanup", "0 3 * * *", async () => {
108
- // Runs at 3 AM daily
109
- await db.prepare("DELETE FROM old_logs WHERE created_at < ?")
110
- .bind(Date.now() - 86400000).run();
111
- });
112
-
113
- cron("hourly-report", "0 * * * *", async () => {
114
- // Runs every hour - can return a result that's stored in history
115
- const count = await processRecords();
116
- return { processed: count };
117
- });
118
- ```
119
-
120
- Cron expressions: `minute hour day-of-month month day-of-week`
121
- - `"0 9 * * *"` - 9 AM daily
122
- - `"*/15 * * * *"` - Every 15 minutes
123
- - `"0 0 * * 1"` - Midnight on Mondays
124
-
125
- Manage cron jobs with CLI:
126
- ```bash
127
- npm exec fling cron list # List all cron jobs
128
- npm exec fling cron history <name> # View invocation history
129
- npm exec fling cron trigger <name> # Manually trigger a job
130
- ```
131
-
132
- ### Storage (R2)
133
-
134
- Store and retrieve files. Uses local filesystem in development, Cloudflare R2 in production.
135
-
136
- ```typescript
137
- import { storage } from "flingit";
138
-
139
- // Store objects
140
- await storage.put("images/logo.png", imageBuffer, { contentType: "image/png" });
141
- await storage.put("data/config.json", JSON.stringify(config));
142
-
143
- // Retrieve objects
144
- const file = await storage.get("images/logo.png");
145
- if (file) {
146
- const buffer = await file.arrayBuffer();
147
- const text = await file.text();
148
- const json = await file.json<ConfigType>();
149
- // Or stream: file.body (ReadableStream)
150
- }
151
-
152
- // Check existence without downloading
153
- const meta = await storage.head("images/logo.png");
154
-
155
- // Delete objects
156
- await storage.delete("old-file.txt");
157
- await storage.delete(["file1.txt", "file2.txt"]); // Batch delete
158
-
159
- // List objects
160
- const result = await storage.list({ prefix: "images/", limit: 100 });
161
- for (const obj of result.objects) {
162
- console.log(`${obj.key}: ${obj.size} bytes`);
163
- }
164
- ```
165
-
166
- Manage storage with CLI:
167
- ```bash
168
- npm exec fling storage list # List local storage objects
169
- npm exec fling storage put key file.txt # Upload file to storage
170
- npm exec fling storage get key output # Download object to file
171
- npm exec fling storage delete key --yes # Delete object
172
- npm exec fling storage info # Show storage stats
173
- ```
174
-
175
- ## React Frontend
176
-
177
- The frontend is a standard React + Vite setup. Call the backend API:
178
-
179
- ```typescript
180
- // In React components
181
- useEffect(() => {
182
- fetch("/api/hello")
183
- .then(res => res.json())
184
- .then(data => setMessage(data.message));
185
- }, []);
186
- ```
187
-
188
- ## CLI Commands
189
-
190
- Always use `npm exec` to run the project's Fling:
191
-
192
- ```bash
193
- npm exec fling dev # Start local dev server (API + Vite)
194
- npm exec fling dev -- --port 8080 # Custom API port
195
- npm exec fling db sql "SELECT * FROM users" # Query local SQLite
196
- npm exec fling db reset # Wipe local database
197
- npm exec fling db sql "SELECT * FROM users" # Query local SQLite
198
- npm exec fling secret set K=V # Set local secret
199
- npm exec fling secret list # List local secrets
200
- npm exec fling logs # View local logs
201
- npm exec fling storage list # List storage objects
202
- npm exec fling storage put K F # Upload file F as key K
203
- npm exec fling storage get K O # Download key K to file O
204
- npm exec fling push # Build and deploy to production
205
- npm exec fling tunnel 3000 # Expose localhost:3000 via public URL
206
- ```
207
-
208
- ### Local vs Production (`--prod`)
209
-
210
- Most CLI commands operate on the **local** environment by default. Add `--prod` for production:
211
-
212
- ```bash
213
- # Local (default)
214
- npm exec fling secret list # Local secrets
215
- npm exec fling logs # Local logs
216
- npm exec fling db sql "SELECT 1" # Local SQLite
217
- npm exec fling storage list # Local storage
218
-
219
- # Production (requires login)
220
- npm exec fling -- --prod logs # Deployed logs
221
- npm exec fling -- --prod db sql "SELECT 1" # Deployed D1
222
- npm exec fling -- --prod storage list # R2 storage
223
- ```
224
-
225
- **Note:** Production logs have a delay of ~10 seconds or more before they appear.
226
-
227
- **Secrets:** Always stored locally in `.fling/secrets`. Use `fling push` to deploy secrets to production along with your code.
228
-
229
- ## Deployment
230
-
231
- `fling push` handles everything automatically:
232
-
233
- 1. Builds React frontend with Vite → `dist/client/`
234
- 2. Uploads static assets (HTML, JS, CSS, images, fonts)
235
- 3. Bundles backend code with esbuild
236
- 4. Deploys to Cloudflare Workers
237
-
238
- **Limits:** 25MB per file, 100MB total assets.
239
-
240
- **Routing in production:**
241
- - `/api/*` → Backend worker code
242
- - Everything else → Static assets from `dist/client/`
243
- - SPA fallback: Unknown paths serve `index.html`
244
-
245
- ## Platform Limitations
246
-
247
- Be aware of these constraints when building:
248
-
249
- ### Feature Scope
250
- - **Supported:** Frontend (React), backend (Hono API), database (SQLite/D1), cron jobs, file storage (R2), Discord integration
251
- - **Not yet supported:** Websockets
252
- - If the user needs unsupported features, encourage them to send feedback via `npm exec fling feedback`
253
-
254
- ### Backend Memory (128MB limit)
255
- - The backend runs in a Cloudflare Worker with ~128MB memory
256
- - Cannot process large datasets in memory all at once
257
- - For large data: use streaming, pagination, or chunked processing
258
- - Example: process files line-by-line instead of loading entirely into memory
259
-
260
- ### Cloudflare Workers Runtime
261
- - Workers do NOT have the full Node.js API
262
- - Some npm packages won't work (those requiring `fs`, `path`, `child_process`, native modules)
263
- - Must use Workers-compatible packages (check package docs for "Cloudflare Workers" or "edge runtime" support)
264
- - Web standard APIs work fine (fetch, crypto.subtle, TextEncoder, etc.)
265
-
266
- ### Backend Assets (Images, Fonts, etc.)
267
-
268
- If the backend needs to return or process an asset (image, icon, font), keep it small and store the base64 data in a separate file to keep your main code clean:
269
-
270
- ```typescript
271
- // src/worker/assets/favicon.ts - separate file for the asset
272
- export const FAVICON_BASE64 = "iVBORw0KGgo..."; // base64-encoded PNG
273
- ```
274
-
275
- ```typescript
276
- // src/worker/index.ts - import and use the asset
277
- import { FAVICON_BASE64 } from "./assets/favicon";
278
-
279
- app.get("/favicon.ico", (c) => {
280
- const buffer = Uint8Array.from(atob(FAVICON_BASE64), c => c.charCodeAt(0));
281
- return new Response(buffer, {
282
- headers: { "Content-Type": "image/x-icon" }
283
- });
284
- });
285
- ```
286
-
287
- This approach:
288
- - Keeps the main code readable (no long base64 strings inline)
289
- - Makes assets easy to find and update
290
- - Base64 keeps assets bundled with the code (required for Workers)
291
-
292
- **For large assets:** Serve them from the frontend (`public/` folder) instead.
293
-
294
- **If the user's request might hit these limitations, warn them early and suggest alternatives.**
295
-
296
- ## Key Points
297
-
298
- - **Don't ask about hosting** - Fling handles deployment
299
- - **Don't ask about databases** - Use `db` from fling
300
- - **Don't suggest external services** - Fling provides what you need
301
- - **Use /api prefix** - For Vite proxy to work in development
302
- - **Run commands yourself** - You have bash access, don't ask the user to run CLI commands
303
-
304
- ## After First Deployment
305
-
306
- After your first `fling push`, consider asking the user if they want a custom URL.
307
- Their project was auto-assigned a slug like `proj-abc123`.
308
-
309
- To change it: `npm exec fling project slug:set my-custom-slug`
310
-
311
- Slugs must be:
312
- - More than 4 characters
313
- - Lowercase alphanumeric with optional hyphens
314
- - Globally unique across all Fling projects
315
-
316
- See `.claude/skills/fling/` for detailed API documentation.
317
- See `.claude/skills/discord/` for Discord chatops integration (slash commands, messages, interactions).
5
+ Read the `fling` skill in detail!
@@ -1 +1 @@
1
- effee60df04f3781c257b08a6cf0c6bb
1
+ 221778dddff2fffb4811276555d0f095
@@ -333,6 +333,36 @@ Secret names must be uppercase with underscores:
333
333
  - `apiKey` ✗
334
334
  - `github-token` ✗
335
335
 
336
+ ## Cron Jobs
337
+
338
+ Schedule tasks to run automatically on a schedule using standard cron syntax:
339
+
340
+ ```typescript
341
+ cron("daily-cleanup", "0 3 * * *", async () => {
342
+ // Runs at 3 AM daily
343
+ await db.prepare("DELETE FROM old_logs WHERE created_at < ?")
344
+ .bind(Date.now() - 86400000).run();
345
+ });
346
+
347
+ cron("hourly-report", "0 * * * *", async () => {
348
+ // Runs every hour - can return a result that's stored in history
349
+ const count = await processRecords();
350
+ return { processed: count };
351
+ });
352
+ ```
353
+
354
+ Cron expressions: `minute hour day-of-month month day-of-week`
355
+ - `"0 9 * * *"` - 9 AM daily
356
+ - `"*/15 * * * *"` - Every 15 minutes
357
+ - `"0 0 * * 1"` - Midnight on Mondays
358
+
359
+ Manage cron jobs with CLI:
360
+ ```bash
361
+ npm exec fling cron list # List all cron jobs
362
+ npm exec fling cron history <name> # View invocation history
363
+ npm exec fling cron trigger <name> # Manually trigger a job
364
+ ```
365
+
336
366
  ## Storage (R2)
337
367
 
338
368
  Object storage for files and binary data. Uses local filesystem in development, Cloudflare R2 in production.
@@ -618,4 +648,3 @@ app.get("/api/compute", async (c) => {
618
648
  - **Cloudflare blocks dynamic WASM compilation** - You cannot use `WebAssembly.instantiate(bytes)` with raw bytes fetched at runtime. WASM must be imported statically so Cloudflare can pre-compile it at deploy time.
619
649
  - **Initialize once** - WASM initialization is expensive. Cache the instance and reuse it across requests.
620
650
  - **Bundle size** - WASM modules count toward the 10MB bundle limit. Large WASM files may require optimization.
621
-
@@ -7,6 +7,25 @@ description: Building and deploying this app easily to the internet
7
7
 
8
8
  You are working on a Fling project - a personal software platform for building and deploying personal tools with a React frontend and Hono API backend.
9
9
 
10
+ ## IMPORTANT: Do NOT ask about deployment, hosting, or technology choices!
11
+
12
+ Fling handles all of this automatically. When the user asks you to build something:
13
+ 1. Write backend code in `src/worker/index.ts` using the Fling API
14
+ 2. Write frontend code in `src/react-app/` using React
15
+ 3. Run `npm start` to test it locally (you have bash access - run commands yourself!)
16
+ 4. When it works, run `npm exec fling push` to deploy
17
+
18
+ ## When to Send Feedback
19
+
20
+ Fling can send feedback to its authors. Read FEEDBACK.md for details.
21
+
22
+ Proactively offer to send feedback in these situations:
23
+
24
+ 1. **User frustration** - When the user expresses frustration with Fling
25
+ 2. **Product limitations** - When Fling can't do something the user needs
26
+ 3. **After difficulties** - When you've helped resolve a confusing issue
27
+ 4. **Feature requests** - When the user wishes Fling could do something differently
28
+
10
29
  ## Core Concepts
11
30
 
12
31
  Fling provides seven primitives that work identically in local development and production:
@@ -181,11 +200,33 @@ Run `npm start` (or `fling dev`) to start development:
181
200
  - **API**: http://localhost:3210 (Hono backend)
182
201
  - Vite proxies `/api/*` requests to the API server
183
202
 
203
+ ### Hot Module Replacement (HMR)
204
+
205
+ The dev server provides hot reloading for both frontend AND backend - no restart needed:
206
+ - **Frontend (React)**: Changes to `src/react-app/` are instantly reflected via Vite HMR
207
+ - **Backend (Worker)**: Changes to `src/worker/` are automatically reloaded via tsx watch
208
+
209
+ Just edit and save - changes appear immediately.
210
+
184
211
  ## Deployment
185
212
 
186
- When the user's request is complete and working locally, deploy it:
213
+ When the user's request is complete and working locally, offer to deploy it. But if their app has a backend and no secure authorization method, you must make it clear to them that the deployed app will be visible on the internet, and that they should not expose anything that should not be publicly visible!
214
+
215
+ To deploy:
187
216
  **Run `npm exec fling push` directly** - you have bash access, don't ask the user to run commands.
188
217
 
218
+ ### After First Deployment
219
+
220
+ After your first `fling push`, consider asking the user if they want a custom URL.
221
+ Their project was auto-assigned a slug like `proj-abc123`.
222
+
223
+ To change it: `npm exec fling project slug:set my-custom-slug`
224
+
225
+ Slugs must be:
226
+ - More than 4 characters
227
+ - Lowercase alphanumeric with optional hyphens
228
+ - Globally unique across all Fling projects
229
+
189
230
  ### What `fling push` does:
190
231
 
191
232
  1. **Builds frontend** - Runs `vite build`, outputs to `dist/client/`
@@ -193,6 +234,8 @@ When the user's request is complete and working locally, deploy it:
193
234
  3. **Bundles backend** - Compiles `src/worker/index.ts` with esbuild
194
235
  4. **Deploys to Cloudflare** - Both frontend and backend go live
195
236
 
237
+ **Secrets:** Always stored locally in `.fling/secrets`. Use `fling push` to deploy secrets to production along with your code.
238
+
196
239
  ### Static Asset Limits
197
240
 
198
241
  - **25MB** per file maximum
@@ -245,4 +288,52 @@ This gives collaborators:
245
288
 
246
289
  **If the user's request might hit platform limitations, warn them early and suggest alternatives.**
247
290
 
291
+ ## Migrations
292
+
293
+ **IMPORTANT: Migrations MUST be idempotent** (safe to run multiple times).
294
+
295
+ Use the `migrate` helper for schema changes:
296
+
297
+ ```typescript
298
+ import { migrate, db } from "flingit";
299
+
300
+ migrate("001_create_users", async () => {
301
+ await db.prepare(`
302
+ CREATE TABLE IF NOT EXISTS users (
303
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
304
+ name TEXT NOT NULL,
305
+ created_at TEXT DEFAULT (datetime('now'))
306
+ )
307
+ `).run();
308
+ });
309
+ ```
310
+
311
+ ## Backend Assets (Images, Fonts, etc.)
312
+
313
+ If the backend needs to return or process an asset (image, icon, font), keep it small and store the base64 data in a separate file to keep your main code clean:
314
+
315
+ ```typescript
316
+ // src/worker/assets/favicon.ts - separate file for the asset
317
+ export const FAVICON_BASE64 = "iVBORw0KGgo..."; // base64-encoded PNG
318
+ ```
319
+
320
+ ```typescript
321
+ // src/worker/index.ts - import and use the asset
322
+ import { FAVICON_BASE64 } from "./assets/favicon";
323
+
324
+ app.get("/favicon.ico", (c) => {
325
+ const buffer = Uint8Array.from(atob(FAVICON_BASE64), c => c.charCodeAt(0));
326
+ return new Response(buffer, {
327
+ headers: { "Content-Type": "image/x-icon" }
328
+ });
329
+ });
330
+ ```
331
+
332
+ This approach:
333
+ - Keeps the main code readable (no long base64 strings inline)
334
+ - Makes assets easy to find and update
335
+ - Base64 keeps assets bundled with the code (required for Workers)
336
+
337
+ **For large assets:** Serve them from the frontend (`public/` folder) instead.
338
+
248
339
  See API.md for detailed API reference, EXAMPLES.md for common patterns, and FEEDBACK.md for collecting user feedback.