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.
- package/README.md +8 -9
- package/dist/cli/commands/admin.d.ts +8 -0
- package/dist/cli/commands/admin.d.ts.map +1 -0
- package/dist/cli/commands/admin.js +231 -0
- package/dist/cli/commands/admin.js.map +1 -0
- package/dist/cli/commands/cron.d.ts +6 -0
- package/dist/cli/commands/cron.d.ts.map +1 -0
- package/dist/cli/commands/cron.js +201 -0
- package/dist/cli/commands/cron.js.map +1 -0
- package/dist/cli/commands/dev-worker.d.ts +12 -0
- package/dist/cli/commands/dev-worker.d.ts.map +1 -0
- package/dist/cli/commands/dev-worker.js +66 -0
- package/dist/cli/commands/dev-worker.js.map +1 -0
- package/dist/cli/commands/dev.d.ts +8 -1
- package/dist/cli/commands/dev.d.ts.map +1 -1
- package/dist/cli/commands/dev.js +137 -82
- package/dist/cli/commands/dev.js.map +1 -1
- package/dist/cli/commands/push.d.ts.map +1 -1
- package/dist/cli/commands/push.js +57 -37
- package/dist/cli/commands/push.js.map +1 -1
- package/dist/cli/deploy/assets.d.ts +8 -8
- package/dist/cli/deploy/assets.d.ts.map +1 -1
- package/dist/cli/deploy/assets.js +15 -15
- package/dist/cli/deploy/assets.js.map +1 -1
- package/dist/cli/deploy/bundler.d.ts +20 -3
- package/dist/cli/deploy/bundler.d.ts.map +1 -1
- package/dist/cli/deploy/bundler.js +89 -4
- package/dist/cli/deploy/bundler.js.map +1 -1
- package/dist/cli/index.js +4 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/utils/retry.d.ts +25 -0
- package/dist/cli/utils/retry.d.ts.map +1 -0
- package/dist/cli/utils/retry.js +34 -0
- package/dist/cli/utils/retry.js.map +1 -0
- package/dist/runtime/migrate.d.ts.map +1 -1
- package/dist/runtime/migrate.js +3 -2
- package/dist/runtime/migrate.js.map +1 -1
- package/dist/worker-runtime/index.d.ts +32 -3
- package/dist/worker-runtime/index.d.ts.map +1 -1
- package/dist/worker-runtime/index.js +31 -4
- package/dist/worker-runtime/index.js.map +1 -1
- package/package.json +1 -1
- package/templates/default/CLAUDE.md +37 -3
- 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
|
-
##
|
|
17
|
+
## Quick Start
|
|
18
18
|
|
|
19
19
|
```bash
|
|
20
|
-
|
|
20
|
+
npx flingit
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
|
|
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
|
-
|
|
27
|
+
### Global Install (Optional)
|
|
28
28
|
|
|
29
|
-
|
|
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
|
-
|
|
36
|
-
|
|
37
|
-
### Subsequent Uses
|
|
36
|
+
### Returning to Your Project
|
|
38
37
|
|
|
39
38
|
```bash
|
|
40
|
-
|
|
39
|
+
npx flingit
|
|
41
40
|
```
|
|
42
41
|
|
|
43
42
|
Opens Claude Code in your existing project. Continue where you left off.
|
|
@@ -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 @@
|
|
|
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
|
|
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"}
|