flingit 0.0.3 → 0.0.5

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.
Files changed (44) hide show
  1. package/README.md +8 -9
  2. package/dist/cli/commands/admin.d.ts +8 -0
  3. package/dist/cli/commands/admin.d.ts.map +1 -0
  4. package/dist/cli/commands/admin.js +231 -0
  5. package/dist/cli/commands/admin.js.map +1 -0
  6. package/dist/cli/commands/cron.d.ts +6 -0
  7. package/dist/cli/commands/cron.d.ts.map +1 -0
  8. package/dist/cli/commands/cron.js +201 -0
  9. package/dist/cli/commands/cron.js.map +1 -0
  10. package/dist/cli/commands/dev-worker.d.ts +12 -0
  11. package/dist/cli/commands/dev-worker.d.ts.map +1 -0
  12. package/dist/cli/commands/dev-worker.js +66 -0
  13. package/dist/cli/commands/dev-worker.js.map +1 -0
  14. package/dist/cli/commands/dev.d.ts +8 -1
  15. package/dist/cli/commands/dev.d.ts.map +1 -1
  16. package/dist/cli/commands/dev.js +137 -82
  17. package/dist/cli/commands/dev.js.map +1 -1
  18. package/dist/cli/commands/push.d.ts.map +1 -1
  19. package/dist/cli/commands/push.js +57 -37
  20. package/dist/cli/commands/push.js.map +1 -1
  21. package/dist/cli/deploy/assets.d.ts +8 -8
  22. package/dist/cli/deploy/assets.d.ts.map +1 -1
  23. package/dist/cli/deploy/assets.js +15 -15
  24. package/dist/cli/deploy/assets.js.map +1 -1
  25. package/dist/cli/deploy/bundler.d.ts +20 -3
  26. package/dist/cli/deploy/bundler.d.ts.map +1 -1
  27. package/dist/cli/deploy/bundler.js +89 -4
  28. package/dist/cli/deploy/bundler.js.map +1 -1
  29. package/dist/cli/index.js +4 -0
  30. package/dist/cli/index.js.map +1 -1
  31. package/dist/cli/utils/retry.d.ts +25 -0
  32. package/dist/cli/utils/retry.d.ts.map +1 -0
  33. package/dist/cli/utils/retry.js +34 -0
  34. package/dist/cli/utils/retry.js.map +1 -0
  35. package/dist/runtime/migrate.d.ts.map +1 -1
  36. package/dist/runtime/migrate.js +3 -2
  37. package/dist/runtime/migrate.js.map +1 -1
  38. package/dist/worker-runtime/index.d.ts +32 -3
  39. package/dist/worker-runtime/index.d.ts.map +1 -1
  40. package/dist/worker-runtime/index.js +31 -4
  41. package/dist/worker-runtime/index.js.map +1 -1
  42. package/package.json +1 -1
  43. package/templates/default/CLAUDE.md +37 -3
  44. package/templates/default/skills/fling/SKILL.md +24 -2
package/README.md CHANGED
@@ -14,30 +14,29 @@ Claude writes the code, runs it locally, tests it, and iterates until it works.
14
14
 
15
15
  **The target user is anyone who can describe what they want.** Technical users get the benefit of standard, portable code. Non-technical users get things built without knowing that code exists.
16
16
 
17
- ## Installation
17
+ ## Quick Start
18
18
 
19
19
  ```bash
20
- npm install -g flingit
20
+ npx flingit
21
21
  ```
22
22
 
23
- The npm package is `flingit` and it installs the `fling` CLI.
23
+ That's it. This creates a project at `~/fling`, sets up the environment, and opens Claude Code. You're immediately in a conversation — just describe what you want to build.
24
24
 
25
25
  Requires Node.js 22 or later.
26
26
 
27
- ## Quick Start
27
+ ### Global Install (Optional)
28
28
 
29
- ### First Time
29
+ If you prefer a global command:
30
30
 
31
31
  ```bash
32
+ npm install -g flingit
32
33
  fling
33
34
  ```
34
35
 
35
- This creates a project at `~/fling`, sets up the environment, and opens Claude Code. You're immediately in a conversation — just describe what you want to build.
36
-
37
- ### Subsequent Uses
36
+ ### Returning to Your Project
38
37
 
39
38
  ```bash
40
- fling
39
+ npx flingit
41
40
  ```
42
41
 
43
42
  Opens Claude Code in your existing project. Continue where you left off.
@@ -0,0 +1,8 @@
1
+ /**
2
+ * fling admin - Admin commands for platform management
3
+ *
4
+ * Requires ADMIN_KEY environment variable to be set.
5
+ */
6
+ import { Command } from "commander";
7
+ export declare const adminCommand: Command;
8
+ //# sourceMappingURL=admin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/admin.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqJpC,eAAO,MAAM,YAAY,SAWtB,CAAC"}
@@ -0,0 +1,231 @@
1
+ /**
2
+ * fling admin - Admin commands for platform management
3
+ *
4
+ * Requires ADMIN_KEY environment variable to be set.
5
+ */
6
+ import { Command } from "commander";
7
+ import { getApiUrl } from "../utils/config.js";
8
+ // Billable rates per Cloudflare pricing
9
+ const RATES = {
10
+ requestsPerMillion: 0.3, // $0.30 per million requests
11
+ cpuMsPerMillion: 0.02, // $0.02 per million CPU ms
12
+ rowsReadPerMillion: 0.001, // $0.001 per million rows read
13
+ rowsWrittenPerMillion: 1.0, // $1.00 per million rows written
14
+ storagePerGBMonth: 0.75, // $0.75 per GB-month
15
+ };
16
+ /**
17
+ * Make an authenticated admin request to the platform API.
18
+ */
19
+ async function adminFetch(path) {
20
+ const adminKey = process.env["ADMIN_KEY"];
21
+ if (!adminKey) {
22
+ throw new Error("ADMIN_KEY environment variable is required for admin commands");
23
+ }
24
+ const url = `${getApiUrl()}${path}`;
25
+ return fetch(url, {
26
+ headers: {
27
+ Authorization: `Bearer ${adminKey}`,
28
+ },
29
+ });
30
+ }
31
+ /**
32
+ * Format a number with commas for readability.
33
+ */
34
+ function formatNumber(n) {
35
+ return n.toLocaleString();
36
+ }
37
+ /**
38
+ * Format bytes as human-readable size.
39
+ */
40
+ function formatBytes(bytes) {
41
+ if (bytes === 0)
42
+ return "0 B";
43
+ const units = ["B", "KB", "MB", "GB", "TB"];
44
+ const i = Math.floor(Math.log(bytes) / Math.log(1024));
45
+ const value = bytes / Math.pow(1024, i);
46
+ return `${value.toFixed(1)}${units[i]}`;
47
+ }
48
+ /**
49
+ * Format cost as currency.
50
+ */
51
+ function formatCost(cost) {
52
+ if (cost < 0.01 && cost > 0) {
53
+ return "<$0.01";
54
+ }
55
+ return `$${cost.toFixed(2)}`;
56
+ }
57
+ /**
58
+ * Calculate cost from usage.
59
+ */
60
+ function calculateCost(usage) {
61
+ const requestsCost = (usage.worker.requests / 1_000_000) * RATES.requestsPerMillion;
62
+ const cpuCost = (usage.worker.cpu_time_ms / 1_000_000) * RATES.cpuMsPerMillion;
63
+ const rowsReadCost = ((usage.d1?.rows_read ?? 0) / 1_000_000) * RATES.rowsReadPerMillion;
64
+ const rowsWrittenCost = ((usage.d1?.rows_written ?? 0) / 1_000_000) * RATES.rowsWrittenPerMillion;
65
+ const storageCost = ((usage.d1?.storage_bytes ?? 0) / (1024 * 1024 * 1024)) * RATES.storagePerGBMonth;
66
+ return requestsCost + cpuCost + rowsReadCost + rowsWrittenCost + storageCost;
67
+ }
68
+ function aggregateUsage(usages) {
69
+ return usages.reduce((acc, u) => ({
70
+ requests: acc.requests + u.worker.requests,
71
+ errors: acc.errors + u.worker.errors,
72
+ cpuTimeMs: acc.cpuTimeMs + u.worker.cpu_time_ms,
73
+ rowsRead: acc.rowsRead + (u.d1?.rows_read ?? 0),
74
+ rowsWritten: acc.rowsWritten + (u.d1?.rows_written ?? 0),
75
+ storageBytes: Math.max(acc.storageBytes, u.d1?.storage_bytes ?? 0), // Take max for storage
76
+ }), { requests: 0, errors: 0, cpuTimeMs: 0, rowsRead: 0, rowsWritten: 0, storageBytes: 0 });
77
+ }
78
+ /**
79
+ * Pad a string to a fixed width.
80
+ */
81
+ function pad(s, width, align = "left") {
82
+ if (s.length >= width)
83
+ return s;
84
+ const padding = " ".repeat(width - s.length);
85
+ return align === "left" ? s + padding : padding + s;
86
+ }
87
+ export const adminCommand = new Command("admin")
88
+ .description("Admin commands for platform management")
89
+ .addHelpText("after", `
90
+ Requires ADMIN_KEY environment variable.
91
+
92
+ Example:
93
+ ADMIN_KEY=your_key fling admin usage
94
+ ADMIN_KEY=your_key fling admin usage --days=7
95
+ `);
96
+ adminCommand
97
+ .command("usage")
98
+ .description("List all users with their resource usage and computed costs")
99
+ .option("--days <number>", "Number of days to look back (1-31)", "31")
100
+ .action(async (options) => {
101
+ const days = parseInt(options.days, 10);
102
+ if (isNaN(days) || days < 1 || days > 31) {
103
+ console.error("Error: days must be between 1 and 31");
104
+ process.exit(1);
105
+ }
106
+ try {
107
+ // Get all users
108
+ const usersResponse = await adminFetch("/admin/users");
109
+ if (!usersResponse.ok) {
110
+ const data = (await usersResponse.json());
111
+ console.error(`Error fetching users: ${data.error ?? "Unknown error"}`);
112
+ process.exit(1);
113
+ }
114
+ const { users } = (await usersResponse.json());
115
+ if (users.length === 0) {
116
+ console.log("No users found.");
117
+ return;
118
+ }
119
+ // Fetch usage for each user's projects with concurrency limit
120
+ const CONCURRENCY = 5;
121
+ const userUsages = new Map();
122
+ // Build list of all project fetch tasks
123
+ const tasks = [];
124
+ for (const user of users) {
125
+ if (user.project) {
126
+ tasks.push({ user, projectId: user.project.id });
127
+ }
128
+ else {
129
+ // User with no project - still track them
130
+ userUsages.set(user.id, { user, usages: [] });
131
+ }
132
+ }
133
+ // Process tasks with concurrency limit
134
+ let completed = 0;
135
+ const total = tasks.length;
136
+ for (let i = 0; i < tasks.length; i += CONCURRENCY) {
137
+ const batch = tasks.slice(i, i + CONCURRENCY);
138
+ const results = await Promise.allSettled(batch.map(async ({ user, projectId }) => {
139
+ const response = await adminFetch(`/admin/users/${user.id}/projects/${projectId}/usage?days=${days}`);
140
+ if (!response.ok) {
141
+ console.error(`Warning: Failed to fetch usage for ${user.email}`);
142
+ return null;
143
+ }
144
+ return { user, usage: (await response.json()) };
145
+ }));
146
+ for (const result of results) {
147
+ completed++;
148
+ if (result.status === "fulfilled" && result.value) {
149
+ const { user, usage } = result.value;
150
+ const existing = userUsages.get(user.id);
151
+ if (existing) {
152
+ existing.usages.push(usage);
153
+ }
154
+ else {
155
+ userUsages.set(user.id, { user, usages: [usage] });
156
+ }
157
+ }
158
+ }
159
+ // Progress indicator
160
+ process.stderr.write(`\rFetching usage... ${completed}/${total}`);
161
+ }
162
+ process.stderr.write("\r" + " ".repeat(40) + "\r"); // Clear progress line
163
+ const rows = [];
164
+ let totalRequests = 0;
165
+ let totalCpuTimeMs = 0;
166
+ let totalRowsRead = 0;
167
+ let totalRowsWritten = 0;
168
+ let totalStorageBytes = 0;
169
+ let totalCost = 0;
170
+ for (const { user, usages } of userUsages.values()) {
171
+ if (usages.length === 0)
172
+ continue;
173
+ const agg = aggregateUsage(usages);
174
+ const cost = usages.reduce((sum, u) => sum + calculateCost(u), 0);
175
+ rows.push({
176
+ email: user.email,
177
+ requests: agg.requests,
178
+ cpuTimeMs: agg.cpuTimeMs,
179
+ rowsRead: agg.rowsRead,
180
+ rowsWritten: agg.rowsWritten,
181
+ storageBytes: agg.storageBytes,
182
+ cost,
183
+ });
184
+ totalRequests += agg.requests;
185
+ totalCpuTimeMs += agg.cpuTimeMs;
186
+ totalRowsRead += agg.rowsRead;
187
+ totalRowsWritten += agg.rowsWritten;
188
+ totalStorageBytes = Math.max(totalStorageBytes, agg.storageBytes);
189
+ totalCost += cost;
190
+ }
191
+ // Sort by cost descending
192
+ rows.sort((a, b) => b.cost - a.cost);
193
+ // Calculate column widths
194
+ const hUser = "User";
195
+ const hRequests = "Requests";
196
+ const hCpu = "CPU (ms)";
197
+ const hRowsRead = "Rows Read";
198
+ const hRowsWritten = "Rows Written";
199
+ const hStorage = "Storage";
200
+ const hCost = "Cost";
201
+ const wUser = Math.max(hUser.length, ...rows.map((r) => r.email.length));
202
+ const wRequests = Math.max(hRequests.length, ...rows.map((r) => formatNumber(r.requests).length));
203
+ const wCpu = Math.max(hCpu.length, ...rows.map((r) => formatNumber(r.cpuTimeMs).length));
204
+ const wRowsRead = Math.max(hRowsRead.length, ...rows.map((r) => formatNumber(r.rowsRead).length));
205
+ const wRowsWritten = Math.max(hRowsWritten.length, ...rows.map((r) => formatNumber(r.rowsWritten).length));
206
+ const wStorage = Math.max(hStorage.length, ...rows.map((r) => formatBytes(r.storageBytes).length));
207
+ const wCost = Math.max(hCost.length, ...rows.map((r) => formatCost(r.cost).length));
208
+ // Print header
209
+ console.log(`${pad(hUser, wUser)} ${pad(hRequests, wRequests, "right")} ${pad(hCpu, wCpu, "right")} ${pad(hRowsRead, wRowsRead, "right")} ${pad(hRowsWritten, wRowsWritten, "right")} ${pad(hStorage, wStorage, "right")} ${pad(hCost, wCost, "right")}`);
210
+ // Print separator
211
+ const separator = [wUser, wRequests, wCpu, wRowsRead, wRowsWritten, wStorage, wCost]
212
+ .map((w) => "-".repeat(w))
213
+ .join(" ");
214
+ console.log(separator);
215
+ // Print rows
216
+ for (const row of rows) {
217
+ console.log(`${pad(row.email, wUser)} ${pad(formatNumber(row.requests), wRequests, "right")} ${pad(formatNumber(row.cpuTimeMs), wCpu, "right")} ${pad(formatNumber(row.rowsRead), wRowsRead, "right")} ${pad(formatNumber(row.rowsWritten), wRowsWritten, "right")} ${pad(formatBytes(row.storageBytes), wStorage, "right")} ${pad(formatCost(row.cost), wCost, "right")}`);
218
+ }
219
+ // Print total
220
+ console.log(separator);
221
+ console.log(`${pad("Total", wUser)} ${pad(formatNumber(totalRequests), wRequests, "right")} ${pad(formatNumber(totalCpuTimeMs), wCpu, "right")} ${pad(formatNumber(totalRowsRead), wRowsRead, "right")} ${pad(formatNumber(totalRowsWritten), wRowsWritten, "right")} ${pad(formatBytes(totalStorageBytes), wStorage, "right")} ${pad(formatCost(totalCost), wCost, "right")}`);
222
+ // Print period info
223
+ console.log();
224
+ console.log(`Period: last ${days} days`);
225
+ }
226
+ catch (error) {
227
+ console.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
228
+ process.exit(1);
229
+ }
230
+ });
231
+ //# sourceMappingURL=admin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin.js","sourceRoot":"","sources":["../../../src/cli/commands/admin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * fling cron - Manage cron jobs
3
+ */
4
+ import { Command } from "commander";
5
+ export declare const cronCommand: Command;
6
+ //# sourceMappingURL=cron.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cron.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/cron.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA4LpC,eAAO,MAAM,WAAW,SAoCpB,CAAC"}
@@ -0,0 +1,201 @@
1
+ /**
2
+ * fling cron - Manage cron jobs
3
+ */
4
+ import { Command } from "commander";
5
+ import { isLoggedIn, platformFetch } from "../utils/config.js";
6
+ /**
7
+ * Format a timestamp as a human-readable date string.
8
+ */
9
+ function formatDate(timestamp) {
10
+ return new Date(timestamp).toISOString().replace("T", " ").slice(0, 19);
11
+ }
12
+ /**
13
+ * Truncate a string with ellipsis if it exceeds max length.
14
+ */
15
+ function truncate(str, max) {
16
+ if (str.length <= max)
17
+ return str;
18
+ return str.slice(0, max - 3) + "...";
19
+ }
20
+ /**
21
+ * List cron jobs with status.
22
+ */
23
+ async function listCronJobs() {
24
+ const response = await platformFetch("/project/default/crons");
25
+ if (!response.ok) {
26
+ const data = (await response.json());
27
+ throw new Error(data.error ?? `API error: ${response.status}`);
28
+ }
29
+ const data = (await response.json());
30
+ if (data.crons.length === 0) {
31
+ console.log("No cron jobs registered.\n");
32
+ console.log("To add a cron job, use the cron() function in your code:");
33
+ console.log("");
34
+ console.log(' cron("daily-task", "0 9 * * *", async () => {');
35
+ console.log(" // Your scheduled task here");
36
+ console.log(" });");
37
+ console.log("");
38
+ console.log("Then run 'fling push' to deploy.");
39
+ return;
40
+ }
41
+ // Print table header
42
+ console.log("");
43
+ console.log("Name".padEnd(25) +
44
+ "Schedule".padEnd(15) +
45
+ "Scheduled For".padEnd(22) +
46
+ "Started At".padEnd(22) +
47
+ "Status");
48
+ console.log("-".repeat(95));
49
+ for (const job of data.crons) {
50
+ const name = truncate(job.name, 23).padEnd(25);
51
+ const schedule = truncate(job.schedule, 13).padEnd(15);
52
+ const scheduledFor = job.lastRun
53
+ ? formatDate(job.lastRun.scheduledFor).padEnd(22)
54
+ : "never".padEnd(22);
55
+ const startedAt = job.lastRun
56
+ ? formatDate(job.lastRun.startedAt).padEnd(22)
57
+ : "-".padEnd(22);
58
+ const status = job.lastRun?.status ?? "-";
59
+ console.log(name + schedule + scheduledFor + startedAt + status);
60
+ }
61
+ console.log("");
62
+ }
63
+ /**
64
+ * Show invocation history for a cron job.
65
+ */
66
+ async function showCronHistory(name, limit) {
67
+ const response = await platformFetch(`/project/default/crons/${encodeURIComponent(name)}/invocations?limit=${limit}`);
68
+ if (!response.ok) {
69
+ const data = (await response.json());
70
+ throw new Error(data.error ?? `API error: ${response.status}`);
71
+ }
72
+ const data = (await response.json());
73
+ if (data.invocations.length === 0) {
74
+ console.log(`No invocations found for cron job "${name}".`);
75
+ return;
76
+ }
77
+ // Print table header
78
+ console.log("");
79
+ console.log(`Invocation history for "${name}":`);
80
+ console.log("");
81
+ console.log("Scheduled For".padEnd(22) +
82
+ "Started At".padEnd(22) +
83
+ "Finished At".padEnd(22) +
84
+ "Status".padEnd(10) +
85
+ "Result / Error");
86
+ console.log("-".repeat(110));
87
+ for (const inv of data.invocations) {
88
+ const scheduledFor = formatDate(inv.scheduledFor).padEnd(22);
89
+ const startedAt = formatDate(inv.startedAt).padEnd(22);
90
+ const finishedAt = inv.finishedAt
91
+ ? formatDate(inv.finishedAt).padEnd(22)
92
+ : "running...".padEnd(22);
93
+ const status = inv.status.padEnd(10);
94
+ const result = inv.status === "error"
95
+ ? truncate(inv.error ?? "Unknown error", 30)
96
+ : inv.result
97
+ ? truncate(JSON.stringify(inv.result), 30)
98
+ : "-";
99
+ console.log(scheduledFor + startedAt + finishedAt + status + result);
100
+ }
101
+ console.log("");
102
+ }
103
+ /**
104
+ * Manually trigger a cron job.
105
+ */
106
+ async function triggerCronJob(name) {
107
+ console.log(`Triggering cron job "${name}"...`);
108
+ const response = await platformFetch(`/project/default/crons/${encodeURIComponent(name)}/trigger`, { method: "POST" });
109
+ if (!response.ok) {
110
+ const data = (await response.json());
111
+ throw new Error(data.error ?? `API error: ${response.status}`);
112
+ }
113
+ const data = (await response.json());
114
+ if (data.status === "error" && data.error) {
115
+ console.log(`Triggered "${name}" - invocation: ${data.invocationId}, status: ${data.status}`);
116
+ console.log(`Error: ${data.error}`);
117
+ }
118
+ else {
119
+ console.log(`Triggered "${name}" - invocation: ${data.invocationId}, status: ${data.status}`);
120
+ }
121
+ }
122
+ export const cronCommand = new Command("cron")
123
+ .description("Manage cron jobs")
124
+ .addHelpText("after", `
125
+ Cron jobs run on a schedule defined in your code. Use the cron() function:
126
+
127
+ import { cron } from "flingit";
128
+
129
+ cron("daily-cleanup", "0 3 * * *", async () => {
130
+ // Runs at 3 AM daily
131
+ await db.prepare("DELETE FROM old_logs WHERE ...").run();
132
+ });
133
+
134
+ Schedule format (standard cron syntax):
135
+ * * * * *
136
+ | | | | |
137
+ | | | | +-- Day of week (0-7, 0 and 7 are Sunday)
138
+ | | | +---- Month (1-12)
139
+ | | +------ Day of month (1-31)
140
+ | +-------- Hour (0-23)
141
+ +---------- Minute (0-59)
142
+
143
+ Examples:
144
+ "0 9 * * *" - 9 AM daily
145
+ "0 * * * *" - Every hour
146
+ "*/15 * * * *" - Every 15 minutes
147
+ "0 0 * * 1" - Midnight on Mondays
148
+ "0 9-17 * * *" - Every hour 9 AM - 5 PM
149
+ `)
150
+ .hook("preAction", () => {
151
+ if (!isLoggedIn()) {
152
+ console.error("Error: Not logged in. Run 'fling login' first.");
153
+ process.exit(1);
154
+ }
155
+ });
156
+ // fling cron list
157
+ cronCommand
158
+ .command("list")
159
+ .description("List all registered cron jobs")
160
+ .action(async () => {
161
+ try {
162
+ await listCronJobs();
163
+ }
164
+ catch (error) {
165
+ console.error("Error:", error.message);
166
+ process.exit(1);
167
+ }
168
+ });
169
+ // fling cron history <name>
170
+ cronCommand
171
+ .command("history <name>")
172
+ .description("Show invocation history for a cron job")
173
+ .option("--limit <n>", "Number of invocations to show", "20")
174
+ .action(async (name, options) => {
175
+ try {
176
+ const limit = parseInt(options.limit, 10);
177
+ if (isNaN(limit) || limit < 1 || limit > 100) {
178
+ console.error("Error: --limit must be between 1 and 100");
179
+ process.exit(1);
180
+ }
181
+ await showCronHistory(name, limit);
182
+ }
183
+ catch (error) {
184
+ console.error("Error:", error.message);
185
+ process.exit(1);
186
+ }
187
+ });
188
+ // fling cron trigger <name>
189
+ cronCommand
190
+ .command("trigger <name>")
191
+ .description("Manually trigger a cron job")
192
+ .action(async (name) => {
193
+ try {
194
+ await triggerCronJob(name);
195
+ }
196
+ catch (error) {
197
+ console.error("Error:", error.message);
198
+ process.exit(1);
199
+ }
200
+ });
201
+ //# sourceMappingURL=cron.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cron.js","sourceRoot":"","sources":["../../../src/cli/commands/cron.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * fling dev worker - The actual development server process
3
+ *
4
+ * This script is spawned by `fling dev` using `tsx watch`.
5
+ * tsx watch monitors all imported files and restarts this process on changes.
6
+ *
7
+ * Environment variables:
8
+ * PORT - Port to run the HTTP server on (default: 3210)
9
+ * PROJECT_DIR - Project directory (default: cwd)
10
+ */
11
+ export {};
12
+ //# sourceMappingURL=dev-worker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev-worker.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/dev-worker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * fling dev worker - The actual development server process
3
+ *
4
+ * This script is spawned by `fling dev` using `tsx watch`.
5
+ * tsx watch monitors all imported files and restarts this process on changes.
6
+ *
7
+ * Environment variables:
8
+ * PORT - Port to run the HTTP server on (default: 3210)
9
+ * PROJECT_DIR - Project directory (default: cwd)
10
+ */
11
+ import { serve } from "@hono/node-server";
12
+ import { pathToFileURL } from "node:url";
13
+ import { getWorkerEntryPath } from "../utils/project.js";
14
+ const port = parseInt(process.env["PORT"] ?? "3210", 10);
15
+ const projectDir = process.env["PROJECT_DIR"] ?? process.cwd();
16
+ const workerEntry = getWorkerEntryPath(projectDir);
17
+ console.log(`[worker] Starting backend server (pid ${process.pid})...`);
18
+ let server = null;
19
+ async function main() {
20
+ try {
21
+ // Import the user's app - this registers routes, cron jobs, and migrations
22
+ // tsx handles TypeScript imports automatically
23
+ const appUrl = pathToFileURL(workerEntry).href;
24
+ await import(appUrl);
25
+ // Import runtime modules
26
+ const { app } = await import("../../runtime/http.js");
27
+ const { runMigrations } = await import("../../runtime/migrate.js");
28
+ const { startCronJobs, getCronJobs, stopCronJobs } = await import("../../runtime/cron.js");
29
+ const { closeLogDatabase } = await import("../../runtime/log.js");
30
+ // Run migrations (before starting crons or HTTP server)
31
+ await runMigrations();
32
+ // Start cron jobs
33
+ startCronJobs();
34
+ const cronJobs = getCronJobs();
35
+ if (cronJobs.size > 0) {
36
+ console.log(`[worker] Cron jobs: ${cronJobs.size} registered`);
37
+ }
38
+ // Graceful shutdown handler
39
+ const shutdown = () => {
40
+ console.log("[worker] Shutting down...");
41
+ stopCronJobs();
42
+ closeLogDatabase();
43
+ if (server) {
44
+ server.close();
45
+ }
46
+ process.exit(0);
47
+ };
48
+ process.on("SIGINT", shutdown);
49
+ process.on("SIGTERM", shutdown);
50
+ // Start HTTP server
51
+ console.log(`[worker] API server: http://localhost:${port}`);
52
+ server = serve({
53
+ fetch: app.fetch,
54
+ port,
55
+ });
56
+ }
57
+ catch (error) {
58
+ console.error("[worker] Failed to start:", error);
59
+ process.exit(1);
60
+ }
61
+ }
62
+ main().catch((error) => {
63
+ console.error("[worker] Unhandled error:", error);
64
+ process.exit(1);
65
+ });
66
+ //# sourceMappingURL=dev-worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev-worker.js","sourceRoot":"","sources":["../../../src/cli/commands/dev-worker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,KAAK,EAAc,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAEzD,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,MAAM,EAAE,EAAE,CAAC,CAAC;AACzD,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;AAE/D,MAAM,WAAW,GAAG,kBAAkB,CAAC,UAAU,CAAC,CAAC;AAEnD,OAAO,CAAC,GAAG,CAAC,yCAAyC,OAAO,CAAC,GAAG,MAAM,CAAC,CAAC;AAExE,IAAI,MAAM,GAAsB,IAAI,CAAC;AAErC,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC;QACH,2EAA2E;QAC3E,+CAA+C;QAC/C,MAAM,MAAM,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC;QAC/C,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC;QAErB,yBAAyB;QACzB,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,MAAM,CAAC,uBAAuB,CAAC,CAAC;QACtD,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,0BAA0B,CAAC,CAAC;QACnE,MAAM,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAC/D,uBAAuB,CACxB,CAAC;QACF,MAAM,EAAE,gBAAgB,EAAE,GAAG,MAAM,MAAM,CAAC,sBAAsB,CAAC,CAAC;QAElE,wDAAwD;QACxD,MAAM,aAAa,EAAE,CAAC;QAEtB,kBAAkB;QAClB,aAAa,EAAE,CAAC;QAChB,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;QAC/B,IAAI,QAAQ,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;YACtB,OAAO,CAAC,GAAG,CAAC,uBAAuB,QAAQ,CAAC,IAAI,aAAa,CAAC,CAAC;QACjE,CAAC;QAED,4BAA4B;QAC5B,MAAM,QAAQ,GAAG,GAAG,EAAE;YACpB,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;YACzC,YAAY,EAAE,CAAC;YACf,gBAAgB,EAAE,CAAC;YACnB,IAAI,MAAM,EAAE,CAAC;gBACX,MAAM,CAAC,KAAK,EAAE,CAAC;YACjB,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC,CAAC;QAEF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC/B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QAEhC,oBAAoB;QACpB,OAAO,CAAC,GAAG,CAAC,yCAAyC,IAAI,EAAE,CAAC,CAAC;QAE7D,MAAM,GAAG,KAAK,CAAC;YACb,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,IAAI;SACL,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE,KAAK,CAAC,CAAC;QAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;IAC9B,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE,KAAK,CAAC,CAAC;IAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -1,5 +1,12 @@
1
1
  /**
2
- * fling dev - Run the local development server
2
+ * fling dev - Run the local development server with HMR
3
+ *
4
+ * This is a thin supervisor that spawns:
5
+ * 1. tsx watch dev-worker.ts - Backend server with automatic restart on changes
6
+ * 2. Vite dev server - Frontend with HMR
7
+ *
8
+ * tsx watch automatically monitors all imported files (follows the import graph)
9
+ * and restarts the worker process when any dependency changes.
3
10
  */
4
11
  import { Command } from "commander";
5
12
  export declare const devCommand: Command;
@@ -1 +1 @@
1
- {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/dev.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAYpC,eAAO,MAAM,UAAU,SAyKnB,CAAC"}
1
+ {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/dev.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmBpC,eAAO,MAAM,UAAU,SAyNnB,CAAC"}