flingit 0.0.1

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 (161) hide show
  1. package/README.md +84 -0
  2. package/dist/cli/commands/db.d.ts +9 -0
  3. package/dist/cli/commands/db.d.ts.map +1 -0
  4. package/dist/cli/commands/db.js +215 -0
  5. package/dist/cli/commands/db.js.map +1 -0
  6. package/dist/cli/commands/dev.d.ts +6 -0
  7. package/dist/cli/commands/dev.d.ts.map +1 -0
  8. package/dist/cli/commands/dev.js +145 -0
  9. package/dist/cli/commands/dev.js.map +1 -0
  10. package/dist/cli/commands/feedback.d.ts +6 -0
  11. package/dist/cli/commands/feedback.d.ts.map +1 -0
  12. package/dist/cli/commands/feedback.js +116 -0
  13. package/dist/cli/commands/feedback.js.map +1 -0
  14. package/dist/cli/commands/init.d.ts +6 -0
  15. package/dist/cli/commands/init.d.ts.map +1 -0
  16. package/dist/cli/commands/init.js +161 -0
  17. package/dist/cli/commands/init.js.map +1 -0
  18. package/dist/cli/commands/launch.d.ts +12 -0
  19. package/dist/cli/commands/launch.d.ts.map +1 -0
  20. package/dist/cli/commands/launch.js +176 -0
  21. package/dist/cli/commands/launch.js.map +1 -0
  22. package/dist/cli/commands/login.d.ts +6 -0
  23. package/dist/cli/commands/login.d.ts.map +1 -0
  24. package/dist/cli/commands/login.js +90 -0
  25. package/dist/cli/commands/login.js.map +1 -0
  26. package/dist/cli/commands/logout.d.ts +6 -0
  27. package/dist/cli/commands/logout.d.ts.map +1 -0
  28. package/dist/cli/commands/logout.js +32 -0
  29. package/dist/cli/commands/logout.js.map +1 -0
  30. package/dist/cli/commands/logs.d.ts +12 -0
  31. package/dist/cli/commands/logs.d.ts.map +1 -0
  32. package/dist/cli/commands/logs.js +261 -0
  33. package/dist/cli/commands/logs.js.map +1 -0
  34. package/dist/cli/commands/onboard.d.ts +22 -0
  35. package/dist/cli/commands/onboard.d.ts.map +1 -0
  36. package/dist/cli/commands/onboard.js +244 -0
  37. package/dist/cli/commands/onboard.js.map +1 -0
  38. package/dist/cli/commands/project.d.ts +6 -0
  39. package/dist/cli/commands/project.d.ts.map +1 -0
  40. package/dist/cli/commands/project.js +142 -0
  41. package/dist/cli/commands/project.js.map +1 -0
  42. package/dist/cli/commands/push.d.ts +6 -0
  43. package/dist/cli/commands/push.d.ts.map +1 -0
  44. package/dist/cli/commands/push.js +351 -0
  45. package/dist/cli/commands/push.js.map +1 -0
  46. package/dist/cli/commands/register.d.ts +6 -0
  47. package/dist/cli/commands/register.d.ts.map +1 -0
  48. package/dist/cli/commands/register.js +115 -0
  49. package/dist/cli/commands/register.js.map +1 -0
  50. package/dist/cli/commands/secret.d.ts +11 -0
  51. package/dist/cli/commands/secret.d.ts.map +1 -0
  52. package/dist/cli/commands/secret.js +124 -0
  53. package/dist/cli/commands/secret.js.map +1 -0
  54. package/dist/cli/commands/whoami.d.ts +6 -0
  55. package/dist/cli/commands/whoami.d.ts.map +1 -0
  56. package/dist/cli/commands/whoami.js +54 -0
  57. package/dist/cli/commands/whoami.js.map +1 -0
  58. package/dist/cli/deploy/assets.d.ts +73 -0
  59. package/dist/cli/deploy/assets.d.ts.map +1 -0
  60. package/dist/cli/deploy/assets.js +167 -0
  61. package/dist/cli/deploy/assets.js.map +1 -0
  62. package/dist/cli/deploy/base64-stream.d.ts +16 -0
  63. package/dist/cli/deploy/base64-stream.d.ts.map +1 -0
  64. package/dist/cli/deploy/base64-stream.js +44 -0
  65. package/dist/cli/deploy/base64-stream.js.map +1 -0
  66. package/dist/cli/deploy/bucket-stream.d.ts +18 -0
  67. package/dist/cli/deploy/bucket-stream.d.ts.map +1 -0
  68. package/dist/cli/deploy/bucket-stream.js +63 -0
  69. package/dist/cli/deploy/bucket-stream.js.map +1 -0
  70. package/dist/cli/deploy/bundler.d.ts +22 -0
  71. package/dist/cli/deploy/bundler.d.ts.map +1 -0
  72. package/dist/cli/deploy/bundler.js +131 -0
  73. package/dist/cli/deploy/bundler.js.map +1 -0
  74. package/dist/cli/deploy/worker-entry.d.ts +14 -0
  75. package/dist/cli/deploy/worker-entry.d.ts.map +1 -0
  76. package/dist/cli/deploy/worker-entry.js +60 -0
  77. package/dist/cli/deploy/worker-entry.js.map +1 -0
  78. package/dist/cli/deploy/wrangler-config.d.ts +20 -0
  79. package/dist/cli/deploy/wrangler-config.d.ts.map +1 -0
  80. package/dist/cli/deploy/wrangler-config.js +54 -0
  81. package/dist/cli/deploy/wrangler-config.js.map +1 -0
  82. package/dist/cli/index.d.ts +10 -0
  83. package/dist/cli/index.d.ts.map +1 -0
  84. package/dist/cli/index.js +72 -0
  85. package/dist/cli/index.js.map +1 -0
  86. package/dist/cli/utils/config.d.ts +39 -0
  87. package/dist/cli/utils/config.d.ts.map +1 -0
  88. package/dist/cli/utils/config.js +105 -0
  89. package/dist/cli/utils/config.js.map +1 -0
  90. package/dist/cli/utils/duration.d.ts +21 -0
  91. package/dist/cli/utils/duration.d.ts.map +1 -0
  92. package/dist/cli/utils/duration.js +44 -0
  93. package/dist/cli/utils/duration.js.map +1 -0
  94. package/dist/cli/utils/environment.d.ts +17 -0
  95. package/dist/cli/utils/environment.d.ts.map +1 -0
  96. package/dist/cli/utils/environment.js +27 -0
  97. package/dist/cli/utils/environment.js.map +1 -0
  98. package/dist/cli/utils/project.d.ts +24 -0
  99. package/dist/cli/utils/project.d.ts.map +1 -0
  100. package/dist/cli/utils/project.js +47 -0
  101. package/dist/cli/utils/project.js.map +1 -0
  102. package/dist/cli/utils/registry.d.ts +34 -0
  103. package/dist/cli/utils/registry.d.ts.map +1 -0
  104. package/dist/cli/utils/registry.js +94 -0
  105. package/dist/cli/utils/registry.js.map +1 -0
  106. package/dist/cli/utils/token.d.ts +12 -0
  107. package/dist/cli/utils/token.d.ts.map +1 -0
  108. package/dist/cli/utils/token.js +27 -0
  109. package/dist/cli/utils/token.js.map +1 -0
  110. package/dist/index.d.ts +12 -0
  111. package/dist/index.d.ts.map +1 -0
  112. package/dist/index.js +12 -0
  113. package/dist/index.js.map +1 -0
  114. package/dist/runtime/cron.d.ts +50 -0
  115. package/dist/runtime/cron.d.ts.map +1 -0
  116. package/dist/runtime/cron.js +80 -0
  117. package/dist/runtime/cron.js.map +1 -0
  118. package/dist/runtime/db.d.ts +93 -0
  119. package/dist/runtime/db.d.ts.map +1 -0
  120. package/dist/runtime/db.js +137 -0
  121. package/dist/runtime/db.js.map +1 -0
  122. package/dist/runtime/http.d.ts +33 -0
  123. package/dist/runtime/http.d.ts.map +1 -0
  124. package/dist/runtime/http.js +36 -0
  125. package/dist/runtime/http.js.map +1 -0
  126. package/dist/runtime/log.d.ts +90 -0
  127. package/dist/runtime/log.d.ts.map +1 -0
  128. package/dist/runtime/log.js +211 -0
  129. package/dist/runtime/log.js.map +1 -0
  130. package/dist/runtime/migrate.d.ts +54 -0
  131. package/dist/runtime/migrate.d.ts.map +1 -0
  132. package/dist/runtime/migrate.js +130 -0
  133. package/dist/runtime/migrate.js.map +1 -0
  134. package/dist/runtime/secrets.d.ts +36 -0
  135. package/dist/runtime/secrets.d.ts.map +1 -0
  136. package/dist/runtime/secrets.js +75 -0
  137. package/dist/runtime/secrets.js.map +1 -0
  138. package/dist/worker-runtime/index.d.ts +79 -0
  139. package/dist/worker-runtime/index.d.ts.map +1 -0
  140. package/dist/worker-runtime/index.js +203 -0
  141. package/dist/worker-runtime/index.js.map +1 -0
  142. package/package.json +81 -0
  143. package/templates/default/.nvmrc +1 -0
  144. package/templates/default/CLAUDE.md +197 -0
  145. package/templates/default/index.html +13 -0
  146. package/templates/default/package.json +25 -0
  147. package/templates/default/public/vite.svg +1 -0
  148. package/templates/default/skills/fling/API.md +335 -0
  149. package/templates/default/skills/fling/EXAMPLES.md +204 -0
  150. package/templates/default/skills/fling/FEEDBACK.md +73 -0
  151. package/templates/default/skills/fling/SKILL.md +159 -0
  152. package/templates/default/src/react-app/App.css +34 -0
  153. package/templates/default/src/react-app/App.tsx +27 -0
  154. package/templates/default/src/react-app/index.css +15 -0
  155. package/templates/default/src/react-app/main.tsx +10 -0
  156. package/templates/default/src/react-app/vite-env.d.ts +1 -0
  157. package/templates/default/src/worker/index.ts +27 -0
  158. package/templates/default/tsconfig.app.json +22 -0
  159. package/templates/default/tsconfig.json +7 -0
  160. package/templates/default/tsconfig.worker.json +11 -0
  161. package/templates/default/vite.config.ts +21 -0
package/README.md ADDED
@@ -0,0 +1,84 @@
1
+ # Fling
2
+
3
+ **Personal Software Platform** — Build and deploy personal tools through conversation.
4
+
5
+ [Watch the demo](https://www.loom.com/share/5add6a6ff897441cadeb67e3ee477b14)
6
+
7
+ ## What is Fling?
8
+
9
+ Fling lets you build personal software tools by describing what you want. You open a terminal, type `fling`, and start talking to Claude. That's it.
10
+
11
+ > "I want a podcast feed that picks randomly between Hard Fork and The Daily each day, and gives me one episode per day."
12
+
13
+ Claude writes the code, runs it locally, tests it, and iterates until it works. You can watch the local server, see logs, check the database — but you don't have to.
14
+
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
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ npm install -g flingit
21
+ ```
22
+
23
+ Requires Node.js 24 or later.
24
+
25
+ ## Quick Start
26
+
27
+ ### First Time
28
+
29
+ ```bash
30
+ fling
31
+ ```
32
+
33
+ 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.
34
+
35
+ ### Subsequent Uses
36
+
37
+ ```bash
38
+ fling
39
+ ```
40
+
41
+ Opens Claude Code in your existing project. Continue where you left off.
42
+
43
+ ## How It Works
44
+
45
+ Fling provides four primitives that Claude uses to build your tools:
46
+
47
+ | Primitive | What it does |
48
+ |-----------|--------------|
49
+ | **HTTP** | Expose endpoints to the web (via [Hono](https://hono.dev)) |
50
+ | **Cron** | Run code on a schedule |
51
+ | **Database** | Store and query data (SQLite) |
52
+ | **Secrets** | Manage API keys and credentials |
53
+
54
+ Everything works locally during development. When you're ready, `fling push` deploys to production.
55
+
56
+ ## Design Philosophy
57
+
58
+ 1. **Claude-first, not CLI-first** — The user's interface is natural language. The CLI exists for Claude to operate.
59
+
60
+ 2. **Standard tools over custom abstractions** — Hono for HTTP, SQLite for data, standard cron syntax. Claude already knows these.
61
+
62
+ 3. **Local-first development** — Everything works locally. Deployment is an optimization.
63
+
64
+ 4. **Fail fast** — Missing secrets throw. Invalid syntax throws. Obvious errors help Claude debug.
65
+
66
+ ## Publishing
67
+
68
+ The package is published to npm as `flingit`. The `prepublishOnly` script runs lint, typecheck, build, and tests automatically.
69
+
70
+ ```bash
71
+ npm publish
72
+ ```
73
+
74
+ To do a dry run first:
75
+
76
+ ```bash
77
+ npm pack --dry-run
78
+ ```
79
+
80
+ ## Documentation
81
+
82
+ - [ARCHITECTURE.md](./ARCHITECTURE.md) — How Fling works internally (CLI commands, runtime API, platform)
83
+ - [API.md](./API.md) — Platform HTTP API reference
84
+ - [SPEC.md](./SPEC.md) — Original product specification
@@ -0,0 +1,9 @@
1
+ /**
2
+ * fling db - Database management commands
3
+ *
4
+ * Default: operates on local SQLite database
5
+ * With --prod: operates on deployed D1 database (requires login)
6
+ */
7
+ import { Command } from "commander";
8
+ export declare const dbCommand: Command;
9
+ //# sourceMappingURL=db.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/db.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA2BpC,eAAO,MAAM,SAAS,SAepB,CAAC"}
@@ -0,0 +1,215 @@
1
+ /**
2
+ * fling db - Database management commands
3
+ *
4
+ * Default: operates on local SQLite database
5
+ * With --prod: operates on deployed D1 database (requires login)
6
+ */
7
+ import { Command } from "commander";
8
+ import { existsSync, rmSync, mkdirSync } from "node:fs";
9
+ import { join, dirname } from "node:path";
10
+ import Database from "better-sqlite3";
11
+ import { platformFetch } from "../utils/config.js";
12
+ import { getTargetEnv, requireProdAuth } from "../utils/environment.js";
13
+ const DB_PATH = join(process.cwd(), ".fling", "data", "local.db");
14
+ export const dbCommand = new Command("db")
15
+ .description("Database management commands (local SQLite or production D1)")
16
+ .addHelpText("after", `
17
+ Environment:
18
+ By default, operates on local SQLite at .fling/data/local.db
19
+ Use --prod flag to operate on the deployed Cloudflare D1 database.
20
+
21
+ Subcommands:
22
+ reset Wipe the local database (local only)
23
+ sql Execute SQL queries
24
+
25
+ Examples:
26
+ fling db reset Wipe local database
27
+ fling db sql "SELECT * FROM users" Query local database
28
+ fling --prod db sql "SELECT count(*) FROM logs" Query production D1
29
+ `);
30
+ dbCommand
31
+ .command("reset")
32
+ .description("Delete the local database file (irreversible)")
33
+ .addHelpText("after", `
34
+ Deletes the local SQLite database and WAL files.
35
+ Migrations will re-run on next 'fling dev'.
36
+
37
+ Note: This command only works with the local database.
38
+ There is no reset for production D1 (use SQL to drop tables).
39
+ `)
40
+ .action(async () => {
41
+ if (!existsSync(DB_PATH)) {
42
+ console.log("Database does not exist. Nothing to reset.");
43
+ return;
44
+ }
45
+ // Remove database and WAL files
46
+ rmSync(DB_PATH, { force: true });
47
+ rmSync(`${DB_PATH}-wal`, { force: true });
48
+ rmSync(`${DB_PATH}-shm`, { force: true });
49
+ console.log("Local database has been reset.");
50
+ });
51
+ dbCommand
52
+ .command("sql")
53
+ .description("Execute a SQL query and display results")
54
+ .argument("<query>", "SQL query to execute (SELECT, INSERT, UPDATE, etc.)")
55
+ .option("-j, --json", "Output raw JSON instead of formatted table")
56
+ .addHelpText("after", `
57
+ Output formats:
58
+ Default: Formatted table with column headers
59
+ --json: Raw JSON with results array
60
+
61
+ Examples:
62
+ fling db sql "SELECT * FROM users"
63
+ fling db sql "SELECT * FROM users WHERE active = 1" --json
64
+ fling db sql "INSERT INTO users (name) VALUES ('Alice')"
65
+ fling --prod db sql "SELECT count(*) FROM logs"
66
+ fling --prod db sql "SELECT * FROM users LIMIT 10" --json
67
+ `)
68
+ .action(async (query, options, command) => {
69
+ const env = getTargetEnv(command);
70
+ if (env === "prod") {
71
+ requireProdAuth(env);
72
+ await executeD1Query(query, options);
73
+ }
74
+ else {
75
+ await executeLocalQuery(query, options);
76
+ }
77
+ });
78
+ /**
79
+ * Execute SQL query on the local SQLite database.
80
+ */
81
+ async function executeLocalQuery(query, options) {
82
+ if (!existsSync(DB_PATH)) {
83
+ // Ensure directory exists
84
+ const dir = dirname(DB_PATH);
85
+ if (!existsSync(dir)) {
86
+ mkdirSync(dir, { recursive: true });
87
+ }
88
+ console.log("Database not found. It will be created.");
89
+ }
90
+ try {
91
+ const db = new Database(DB_PATH);
92
+ const stmt = db.prepare(query);
93
+ // Check if this is a SELECT query (returns data)
94
+ // better-sqlite3 requires using .all() for SELECT and .run() for others
95
+ const isSelect = query.trim().toUpperCase().startsWith("SELECT");
96
+ if (isSelect) {
97
+ const rows = stmt.all();
98
+ if (options.json) {
99
+ console.log(JSON.stringify({ results: rows }, null, 2));
100
+ db.close();
101
+ return;
102
+ }
103
+ if (rows.length === 0) {
104
+ console.log("Query returned no rows");
105
+ db.close();
106
+ return;
107
+ }
108
+ printRows(rows);
109
+ console.log(`\n${rows.length} row(s) returned`);
110
+ }
111
+ else {
112
+ const result = stmt.run();
113
+ if (options.json) {
114
+ console.log(JSON.stringify({
115
+ changes: result.changes,
116
+ lastInsertRowid: result.lastInsertRowid,
117
+ }, null, 2));
118
+ db.close();
119
+ return;
120
+ }
121
+ console.log(`Query executed: ${result.changes} row(s) affected`);
122
+ }
123
+ db.close();
124
+ }
125
+ catch (error) {
126
+ console.error(`Error: ${error instanceof Error ? error.message : "Query failed"}`);
127
+ process.exit(1);
128
+ }
129
+ }
130
+ /**
131
+ * Execute SQL query on the deployed D1 database.
132
+ */
133
+ async function executeD1Query(query, options) {
134
+ try {
135
+ const response = await platformFetch("/project/default/sql", {
136
+ method: "POST",
137
+ headers: { "Content-Type": "application/json" },
138
+ body: JSON.stringify({
139
+ statements: [{ sql: query }],
140
+ }),
141
+ });
142
+ const data = (await response.json());
143
+ if (!response.ok) {
144
+ console.error(`Error: ${data.error ?? `API error (${response.status})`}`);
145
+ process.exit(1);
146
+ }
147
+ if (!data.results || data.results.length === 0) {
148
+ console.log("Query executed successfully (no results)");
149
+ return;
150
+ }
151
+ const [result] = data.results;
152
+ if (!result) {
153
+ console.log("Query executed successfully (no results)");
154
+ return;
155
+ }
156
+ if (options.json) {
157
+ // Raw JSON output
158
+ console.log(JSON.stringify(result, null, 2));
159
+ return;
160
+ }
161
+ // Formatted output
162
+ const rows = result.results;
163
+ if (rows.length === 0) {
164
+ console.log("Query returned no rows");
165
+ console.log(`\nMeta: ${result.meta.changes} changes, ${result.meta.duration.toFixed(2)}ms`);
166
+ return;
167
+ }
168
+ printRows(rows);
169
+ console.log(`\n${rows.length} row(s) returned`);
170
+ console.log(`Meta: ${result.meta.changes} changes, ${result.meta.duration.toFixed(2)}ms`);
171
+ }
172
+ catch (error) {
173
+ console.error(`Error: ${error instanceof Error ? error.message : "Query failed"}`);
174
+ process.exit(1);
175
+ }
176
+ }
177
+ /**
178
+ * Print rows in a formatted table.
179
+ */
180
+ function printRows(rows) {
181
+ const [firstRow] = rows;
182
+ if (!firstRow) {
183
+ console.log("Query returned no rows");
184
+ return;
185
+ }
186
+ const columns = Object.keys(firstRow);
187
+ // Helper to stringify values (handles objects, nulls, etc.)
188
+ const stringify = (value) => {
189
+ if (value === null || value === undefined)
190
+ return "NULL";
191
+ if (typeof value === "object")
192
+ return JSON.stringify(value);
193
+ // At this point, value is a primitive (string, number, boolean, etc.)
194
+ return String(value);
195
+ };
196
+ // Calculate column widths
197
+ const widths = columns.map((col) => {
198
+ const maxValueWidth = Math.max(...rows.map((row) => stringify(row[col]).length));
199
+ return Math.max(col.length, maxValueWidth);
200
+ });
201
+ // Print header
202
+ const header = columns
203
+ .map((col, i) => col.padEnd(widths[i] ?? 0))
204
+ .join(" | ");
205
+ console.log(header);
206
+ console.log(widths.map((w) => "-".repeat(w)).join("-+-"));
207
+ // Print rows
208
+ for (const row of rows) {
209
+ const line = columns
210
+ .map((col, i) => stringify(row[col]).padEnd(widths[i] ?? 0))
211
+ .join(" | ");
212
+ console.log(line);
213
+ }
214
+ }
215
+ //# sourceMappingURL=db.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.js","sourceRoot":"","sources":["../../../src/cli/commands/db.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * fling dev - Run the local development server
3
+ */
4
+ import { Command } from "commander";
5
+ export declare const devCommand: Command;
6
+ //# sourceMappingURL=dev.d.ts.map
@@ -0,0 +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,SAsKnB,CAAC"}
@@ -0,0 +1,145 @@
1
+ /**
2
+ * fling dev - Run the local development server
3
+ */
4
+ import { Command } from "commander";
5
+ import { serve } from "@hono/node-server";
6
+ import { existsSync } from "node:fs";
7
+ import { join } from "node:path";
8
+ import { pathToFileURL } from "node:url";
9
+ import { spawn } from "node:child_process";
10
+ import { getWorkerEntryPath, hasWorkerEntry } from "../utils/project.js";
11
+ export const devCommand = new Command("dev")
12
+ .description("Start the local development server")
13
+ .option("-p, --port <port>", "Port to run on", "3210")
14
+ .addHelpText("after", `
15
+ Prerequisites:
16
+ - Must have run 'fling init' first
17
+ - Must have run 'npm install' first
18
+ - Requires src/worker/index.ts
19
+
20
+ What it does:
21
+ - Runs database migrations
22
+ - Starts cron jobs (if any are registered)
23
+ - Starts API server at http://localhost:PORT
24
+ - Starts Vite dev server at http://localhost:5173
25
+ - Proxies /api/* requests from Vite to the API server
26
+ - React HMR enabled for frontend development
27
+
28
+ The servers run until you press Ctrl+C.
29
+
30
+ Examples:
31
+ fling dev Start on default port 3210
32
+ fling dev -p 8080 Start API on port 8080
33
+ `)
34
+ .action(async (options) => {
35
+ const cwd = process.cwd();
36
+ const port = parseInt(options.port, 10);
37
+ // Check if project is initialized
38
+ if (!existsSync(join(cwd, ".fling"))) {
39
+ console.error("Error: Not a Fling project. Run 'fling init' first.");
40
+ process.exit(1);
41
+ }
42
+ // Check for worker entry point
43
+ if (!hasWorkerEntry(cwd)) {
44
+ console.error("Error: src/worker/index.ts not found.\n");
45
+ console.error("This file is your backend API entry point.");
46
+ console.error("Run 'fling init' to create a new project with the correct structure.");
47
+ process.exit(1);
48
+ }
49
+ const workerEntry = getWorkerEntryPath(cwd);
50
+ let viteProcess = null;
51
+ console.log("Starting Fling development server...\n");
52
+ try {
53
+ // Dynamic import of tsx to run TypeScript
54
+ // Using pathToFileURL for proper ESM imports
55
+ const appUrl = pathToFileURL(workerEntry).href;
56
+ // Import the user's app - this registers routes, cron jobs, and migrations
57
+ await import(appUrl);
58
+ // Import runtime modules
59
+ const { app } = await import("../../runtime/http.js");
60
+ const { runMigrations } = await import("../../runtime/migrate.js");
61
+ const { startCronJobs, getCronJobs } = await import("../../runtime/cron.js");
62
+ // Run migrations (before starting crons or HTTP server)
63
+ await runMigrations();
64
+ // Start cron jobs
65
+ startCronJobs();
66
+ const cronJobs = getCronJobs();
67
+ if (cronJobs.size > 0) {
68
+ console.log(`Cron jobs: ${cronJobs.size} registered`);
69
+ }
70
+ // Import log database cleanup
71
+ const { closeLogDatabase } = await import("../../runtime/log.js");
72
+ const { stopCronJobs } = await import("../../runtime/cron.js");
73
+ // Function to spawn Vite dev server
74
+ function spawnViteDevServer(projectDir) {
75
+ // Use npm exec for reliability and clear error messages
76
+ const vite = spawn("npm", ["exec", "vite"], {
77
+ cwd: projectDir,
78
+ stdio: ["ignore", "pipe", "pipe"],
79
+ env: { ...process.env, FORCE_COLOR: "1" },
80
+ });
81
+ // Prefix Vite output for clarity
82
+ // stdout/stderr are always defined when using stdio: ["ignore", "pipe", "pipe"]
83
+ vite.stdout.on("data", (data) => {
84
+ const lines = data.toString().split("\n").filter(Boolean);
85
+ for (const line of lines) {
86
+ console.log(`[vite] ${line}`);
87
+ }
88
+ });
89
+ vite.stderr.on("data", (data) => {
90
+ const lines = data.toString().split("\n").filter(Boolean);
91
+ for (const line of lines) {
92
+ console.error(`[vite] ${line}`);
93
+ }
94
+ });
95
+ return vite;
96
+ }
97
+ // Graceful shutdown handler
98
+ const shutdown = () => {
99
+ console.log("\nShutting down...");
100
+ if (viteProcess && !viteProcess.killed) {
101
+ viteProcess.kill("SIGTERM");
102
+ }
103
+ stopCronJobs();
104
+ closeLogDatabase();
105
+ process.exit(0);
106
+ };
107
+ process.on("SIGINT", shutdown);
108
+ process.on("SIGTERM", shutdown);
109
+ // Start HTTP server
110
+ console.log(`\nAPI server: http://localhost:${port}`);
111
+ serve({
112
+ fetch: app.fetch,
113
+ port,
114
+ });
115
+ // Start Vite dev server
116
+ console.log("Starting Vite dev server...");
117
+ viteProcess = spawnViteDevServer(cwd);
118
+ viteProcess.on("error", (error) => {
119
+ if (error.code === "ENOENT") {
120
+ console.error("\nError: Could not start Vite dev server.\n");
121
+ console.error("npm is not found in PATH. Ensure Node.js is properly installed.");
122
+ }
123
+ else {
124
+ console.error("\nError starting Vite dev server:", error.message);
125
+ }
126
+ console.error(`\nThe API server is still running at http://localhost:${port}`);
127
+ console.error("To fix Vite, ensure dependencies are installed: npm install");
128
+ });
129
+ viteProcess.on("close", (code) => {
130
+ if (code !== 0 && code !== null) {
131
+ console.error(`\n[vite] Process exited with code ${code}`);
132
+ console.error("[vite] Check if vite is installed: npm install");
133
+ }
134
+ viteProcess = null;
135
+ });
136
+ console.log(`\nFrontend: http://localhost:5173`);
137
+ console.log(`API proxy: /api/* -> http://localhost:${port}`);
138
+ console.log("\nPress Ctrl+C to stop\n");
139
+ }
140
+ catch (error) {
141
+ console.error("Failed to start development server:", error);
142
+ process.exit(1);
143
+ }
144
+ });
145
+ //# sourceMappingURL=dev.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev.js","sourceRoot":"","sources":["../../../src/cli/commands/dev.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * fling feedback - Submit feedback to the Fling team
3
+ */
4
+ import { Command } from "commander";
5
+ export declare const feedbackCommand: Command;
6
+ //# sourceMappingURL=feedback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feedback.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/feedback.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmDpC,eAAO,MAAM,eAAe,SA+ExB,CAAC"}
@@ -0,0 +1,116 @@
1
+ /**
2
+ * fling feedback - Submit feedback to the Fling team
3
+ */
4
+ import { Command } from "commander";
5
+ import { createInterface } from "node:readline";
6
+ import { isLoggedIn, platformFetch } from "../utils/config.js";
7
+ const MIN_LENGTH = 10;
8
+ const MAX_LENGTH = 5000;
9
+ /**
10
+ * Prompt for single-line input.
11
+ */
12
+ async function prompt(question) {
13
+ const rl = createInterface({
14
+ input: process.stdin,
15
+ output: process.stdout,
16
+ });
17
+ return new Promise((resolve) => {
18
+ rl.question(question, (answer) => {
19
+ rl.close();
20
+ resolve(answer);
21
+ });
22
+ });
23
+ }
24
+ /**
25
+ * Prompt for multi-line input (interactive mode).
26
+ * User enters text and presses Ctrl+D (Unix) or Ctrl+Z (Windows) to finish.
27
+ */
28
+ async function promptMultiline() {
29
+ console.log("Enter your feedback (press Ctrl+D when done):");
30
+ console.log("---");
31
+ const rl = createInterface({
32
+ input: process.stdin,
33
+ output: process.stdout,
34
+ terminal: false,
35
+ });
36
+ const lines = [];
37
+ return new Promise((resolve) => {
38
+ rl.on("line", (line) => {
39
+ lines.push(line);
40
+ });
41
+ rl.on("close", () => {
42
+ console.log("---");
43
+ resolve(lines.join("\n"));
44
+ });
45
+ });
46
+ }
47
+ export const feedbackCommand = new Command("feedback")
48
+ .description("Submit feedback, bug reports, or feature requests to the Fling team")
49
+ .argument("[message]", "Feedback message, 10-5000 chars (will prompt if not provided)")
50
+ .option("-i, --interactive", "Multi-line input mode (end with Ctrl+D)")
51
+ .addHelpText("after", `
52
+ Where feedback goes:
53
+ Feedback is sent directly to the Fling development team for review.
54
+ Include details about bugs, feature requests, or general feedback.
55
+
56
+ Requires login (run 'fling login' first).
57
+
58
+ Examples:
59
+ fling feedback "Love the new logs command!"
60
+ fling feedback "Bug: push fails when bundle > 1MB"
61
+ fling feedback -i Multi-line mode for detailed feedback
62
+ `)
63
+ .action(async (messageArg, options) => {
64
+ // Check if logged in
65
+ if (!isLoggedIn()) {
66
+ console.error("Not logged in. Run 'fling login' first.");
67
+ process.exit(1);
68
+ }
69
+ // Get feedback message
70
+ let message;
71
+ if (messageArg) {
72
+ message = messageArg;
73
+ }
74
+ else if (options.interactive) {
75
+ message = await promptMultiline();
76
+ }
77
+ else {
78
+ message = await prompt("Feedback: ");
79
+ }
80
+ // Trim and validate
81
+ message = message.trim();
82
+ if (!message) {
83
+ console.error("Feedback message is required.");
84
+ process.exit(1);
85
+ }
86
+ if (message.length < MIN_LENGTH) {
87
+ console.error(`Feedback must be at least ${MIN_LENGTH} characters.`);
88
+ process.exit(1);
89
+ }
90
+ if (message.length > MAX_LENGTH) {
91
+ console.error(`Feedback must be less than ${MAX_LENGTH} characters.`);
92
+ process.exit(1);
93
+ }
94
+ // Submit feedback
95
+ console.log("Submitting feedback...");
96
+ try {
97
+ const response = await platformFetch("/feedback", {
98
+ method: "POST",
99
+ headers: {
100
+ "Content-Type": "application/json",
101
+ },
102
+ body: JSON.stringify({ content: message }),
103
+ });
104
+ const data = (await response.json());
105
+ if (!response.ok) {
106
+ console.error(`Failed to submit feedback: ${data.error ?? "Unknown error"}`);
107
+ process.exit(1);
108
+ }
109
+ console.log("Thank you! Your feedback has been submitted.");
110
+ }
111
+ catch (error) {
112
+ console.error(`Failed to submit feedback: ${error instanceof Error ? error.message : "Network error"}`);
113
+ process.exit(1);
114
+ }
115
+ });
116
+ //# sourceMappingURL=feedback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feedback.js","sourceRoot":"","sources":["../../../src/cli/commands/feedback.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * fling init - Scaffold a new project in the current directory
3
+ */
4
+ import { Command } from "commander";
5
+ export declare const initCommand: Command;
6
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkCpC,eAAO,MAAM,WAAW,SA2KpB,CAAC"}