clawfire 0.1.0

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 (87) hide show
  1. package/README.md +182 -0
  2. package/dist/admin.cjs +309 -0
  3. package/dist/admin.cjs.map +1 -0
  4. package/dist/admin.d.cts +93 -0
  5. package/dist/admin.d.ts +93 -0
  6. package/dist/admin.js +274 -0
  7. package/dist/admin.js.map +1 -0
  8. package/dist/auth-DQ3cifhb.d.cts +55 -0
  9. package/dist/auth-DtnUPbXT.d.ts +55 -0
  10. package/dist/chunk-37Y2XI7X.js +75 -0
  11. package/dist/chunk-YGIPORYL.js +339 -0
  12. package/dist/cli.js +241 -0
  13. package/dist/client.cjs +97 -0
  14. package/dist/client.cjs.map +1 -0
  15. package/dist/client.d.cts +4 -0
  16. package/dist/client.d.ts +4 -0
  17. package/dist/client.js +68 -0
  18. package/dist/client.js.map +1 -0
  19. package/dist/codegen.cjs +648 -0
  20. package/dist/codegen.cjs.map +1 -0
  21. package/dist/codegen.d.cts +25 -0
  22. package/dist/codegen.d.ts +25 -0
  23. package/dist/codegen.js +617 -0
  24. package/dist/codegen.js.map +1 -0
  25. package/dist/config-QMBJRn9G.d.cts +46 -0
  26. package/dist/config-QMBJRn9G.d.ts +46 -0
  27. package/dist/dev-server-QAVWINAT.js +973 -0
  28. package/dist/dev.cjs +1388 -0
  29. package/dist/dev.cjs.map +1 -0
  30. package/dist/dev.d.cts +111 -0
  31. package/dist/dev.d.ts +111 -0
  32. package/dist/dev.js +1349 -0
  33. package/dist/dev.js.map +1 -0
  34. package/dist/discover-BPMAZFBD.js +9 -0
  35. package/dist/discover-DYNqz_ym.d.cts +28 -0
  36. package/dist/discover-DYNqz_ym.d.ts +28 -0
  37. package/dist/errors-s_mP7rs9.d.cts +33 -0
  38. package/dist/errors-s_mP7rs9.d.ts +33 -0
  39. package/dist/functions.cjs +1156 -0
  40. package/dist/functions.cjs.map +1 -0
  41. package/dist/functions.d.cts +115 -0
  42. package/dist/functions.d.ts +115 -0
  43. package/dist/functions.js +1108 -0
  44. package/dist/functions.js.map +1 -0
  45. package/dist/hosting-7WVFHAYJ.js +85 -0
  46. package/dist/html-PCUCJGBH.js +7 -0
  47. package/dist/index.cjs +349 -0
  48. package/dist/index.cjs.map +1 -0
  49. package/dist/index.d.cts +22 -0
  50. package/dist/index.d.ts +22 -0
  51. package/dist/index.js +312 -0
  52. package/dist/index.js.map +1 -0
  53. package/dist/playground.cjs +364 -0
  54. package/dist/playground.cjs.map +1 -0
  55. package/dist/playground.d.cts +12 -0
  56. package/dist/playground.d.ts +12 -0
  57. package/dist/playground.js +337 -0
  58. package/dist/playground.js.map +1 -0
  59. package/dist/router-BVB_I-tu.d.ts +65 -0
  60. package/dist/router-Cikk8Heq.d.cts +65 -0
  61. package/dist/schema-BJsictSV.d.cts +172 -0
  62. package/dist/schema-BJsictSV.d.ts +172 -0
  63. package/package.json +150 -0
  64. package/templates/CLAUDE.md +71 -0
  65. package/templates/app/routes/auth/login.ts +35 -0
  66. package/templates/app/routes/health.ts +20 -0
  67. package/templates/app/schemas/user.ts +26 -0
  68. package/templates/clawfire.config.ts +25 -0
  69. package/templates/functions/index.ts +43 -0
  70. package/templates/starter/.claude/skills/clawfire-api/SKILL.md +131 -0
  71. package/templates/starter/.claude/skills/clawfire-auth/SKILL.md +111 -0
  72. package/templates/starter/.claude/skills/clawfire-deploy/SKILL.md +95 -0
  73. package/templates/starter/.claude/skills/clawfire-diagnose/SKILL.md +99 -0
  74. package/templates/starter/.claude/skills/clawfire-model/SKILL.md +128 -0
  75. package/templates/starter/CLAUDE.md +227 -0
  76. package/templates/starter/app/routes/health.ts +20 -0
  77. package/templates/starter/app/routes/todos/create.ts +25 -0
  78. package/templates/starter/app/routes/todos/delete.ts +20 -0
  79. package/templates/starter/app/routes/todos/list.ts +26 -0
  80. package/templates/starter/app/routes/todos/update.ts +32 -0
  81. package/templates/starter/app/schemas/todo.ts +16 -0
  82. package/templates/starter/app/store.ts +56 -0
  83. package/templates/starter/clawfire.config.ts +25 -0
  84. package/templates/starter/dev.ts +12 -0
  85. package/templates/starter/package.json +19 -0
  86. package/templates/starter/public/index.html +365 -0
  87. package/templates/starter/tsconfig.json +17 -0
@@ -0,0 +1,365 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Clawfire Todo App</title>
7
+ <style>
8
+ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
9
+
10
+ body {
11
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
12
+ background: #0f0f13;
13
+ color: #e4e4e7;
14
+ min-height: 100vh;
15
+ display: flex;
16
+ justify-content: center;
17
+ padding: 48px 16px;
18
+ }
19
+
20
+ .app {
21
+ width: 100%;
22
+ max-width: 560px;
23
+ }
24
+
25
+ /* Header */
26
+ .header {
27
+ text-align: center;
28
+ margin-bottom: 32px;
29
+ }
30
+ .header h1 {
31
+ font-size: 28px;
32
+ font-weight: 700;
33
+ background: linear-gradient(135deg, #f97316, #fb923c);
34
+ -webkit-background-clip: text;
35
+ -webkit-text-fill-color: transparent;
36
+ margin-bottom: 4px;
37
+ }
38
+ .header p {
39
+ color: #71717a;
40
+ font-size: 14px;
41
+ }
42
+
43
+ /* Input area */
44
+ .input-row {
45
+ display: flex;
46
+ gap: 8px;
47
+ margin-bottom: 24px;
48
+ }
49
+ .input-row input {
50
+ flex: 1;
51
+ padding: 12px 16px;
52
+ background: #1a1a23;
53
+ border: 1px solid #27272a;
54
+ border-radius: 10px;
55
+ color: #e4e4e7;
56
+ font-size: 15px;
57
+ outline: none;
58
+ transition: border-color 0.15s;
59
+ }
60
+ .input-row input:focus {
61
+ border-color: #f97316;
62
+ }
63
+ .input-row input::placeholder { color: #52525b; }
64
+ .input-row button {
65
+ padding: 12px 20px;
66
+ background: #f97316;
67
+ color: #fff;
68
+ border: none;
69
+ border-radius: 10px;
70
+ font-size: 15px;
71
+ font-weight: 600;
72
+ cursor: pointer;
73
+ white-space: nowrap;
74
+ transition: background 0.15s;
75
+ }
76
+ .input-row button:hover { background: #ea580c; }
77
+ .input-row button:disabled { opacity: 0.5; cursor: not-allowed; }
78
+
79
+ /* Stats bar */
80
+ .stats {
81
+ display: flex;
82
+ justify-content: space-between;
83
+ align-items: center;
84
+ padding: 8px 0;
85
+ margin-bottom: 12px;
86
+ font-size: 13px;
87
+ color: #71717a;
88
+ }
89
+ .stats .count { font-weight: 600; color: #a1a1aa; }
90
+
91
+ /* Todo list */
92
+ .todo-list {
93
+ display: flex;
94
+ flex-direction: column;
95
+ gap: 6px;
96
+ }
97
+
98
+ .todo-item {
99
+ display: flex;
100
+ align-items: center;
101
+ gap: 12px;
102
+ padding: 12px 16px;
103
+ background: #1a1a23;
104
+ border: 1px solid #27272a;
105
+ border-radius: 10px;
106
+ transition: border-color 0.15s, opacity 0.2s;
107
+ }
108
+ .todo-item:hover { border-color: #3f3f46; }
109
+ .todo-item.completed { opacity: 0.5; }
110
+
111
+ /* Checkbox */
112
+ .todo-check {
113
+ width: 22px;
114
+ height: 22px;
115
+ border: 2px solid #3f3f46;
116
+ border-radius: 6px;
117
+ cursor: pointer;
118
+ display: flex;
119
+ align-items: center;
120
+ justify-content: center;
121
+ flex-shrink: 0;
122
+ transition: all 0.15s;
123
+ }
124
+ .todo-check:hover { border-color: #f97316; }
125
+ .todo-item.completed .todo-check {
126
+ background: #f97316;
127
+ border-color: #f97316;
128
+ }
129
+ .todo-check svg { display: none; }
130
+ .todo-item.completed .todo-check svg { display: block; }
131
+
132
+ /* Title */
133
+ .todo-title {
134
+ flex: 1;
135
+ font-size: 15px;
136
+ line-height: 1.4;
137
+ word-break: break-word;
138
+ }
139
+ .todo-item.completed .todo-title {
140
+ text-decoration: line-through;
141
+ color: #71717a;
142
+ }
143
+
144
+ /* Delete button */
145
+ .todo-delete {
146
+ background: none;
147
+ border: none;
148
+ color: #52525b;
149
+ cursor: pointer;
150
+ padding: 4px;
151
+ border-radius: 6px;
152
+ display: flex;
153
+ align-items: center;
154
+ justify-content: center;
155
+ opacity: 0;
156
+ transition: all 0.15s;
157
+ }
158
+ .todo-item:hover .todo-delete { opacity: 1; }
159
+ .todo-delete:hover { color: #ef4444; background: rgba(239, 68, 68, 0.1); }
160
+
161
+ /* Empty state */
162
+ .empty {
163
+ text-align: center;
164
+ padding: 48px 0;
165
+ color: #52525b;
166
+ }
167
+ .empty svg { margin-bottom: 12px; }
168
+ .empty p { font-size: 14px; }
169
+
170
+ /* Loading */
171
+ .loading {
172
+ text-align: center;
173
+ padding: 48px 0;
174
+ color: #71717a;
175
+ font-size: 14px;
176
+ }
177
+
178
+ /* Error */
179
+ .error-toast {
180
+ position: fixed;
181
+ bottom: 24px;
182
+ left: 50%;
183
+ transform: translateX(-50%);
184
+ background: #7f1d1d;
185
+ color: #fca5a5;
186
+ padding: 10px 20px;
187
+ border-radius: 8px;
188
+ font-size: 13px;
189
+ display: none;
190
+ z-index: 100;
191
+ }
192
+ .error-toast.show { display: block; }
193
+ </style>
194
+ </head>
195
+ <body>
196
+ <div class="app">
197
+ <div class="header">
198
+ <h1>Clawfire Todos</h1>
199
+ <p>Your first Clawfire app — add, complete, and delete todos</p>
200
+ </div>
201
+
202
+ <div class="input-row">
203
+ <input type="text" id="todo-input" placeholder="What needs to be done?" maxlength="200" />
204
+ <button id="add-btn" onclick="addTodo()">Add</button>
205
+ </div>
206
+
207
+ <div class="stats" id="stats" style="display:none">
208
+ <span><span class="count" id="total-count">0</span> total</span>
209
+ <span><span class="count" id="done-count">0</span> completed</span>
210
+ </div>
211
+
212
+ <div id="todo-list" class="todo-list">
213
+ <div class="loading">Loading todos...</div>
214
+ </div>
215
+
216
+ <div class="error-toast" id="error-toast"></div>
217
+ </div>
218
+
219
+ <script>
220
+ const API = '/api/todos';
221
+ let todos = [];
222
+
223
+ // ─── API Calls ──────────────────────────────────
224
+ async function api(path, body = {}) {
225
+ const res = await fetch(`${API}/${path}`, {
226
+ method: 'POST',
227
+ headers: { 'Content-Type': 'application/json' },
228
+ body: JSON.stringify(body),
229
+ });
230
+ const json = await res.json();
231
+ if (!res.ok) throw new Error(json.error || 'Request failed');
232
+ return json.data;
233
+ }
234
+
235
+ async function loadTodos() {
236
+ try {
237
+ const data = await api('list');
238
+ todos = data.todos;
239
+ render();
240
+ } catch (e) {
241
+ showError('Failed to load todos: ' + e.message);
242
+ }
243
+ }
244
+
245
+ async function addTodo() {
246
+ const input = document.getElementById('todo-input');
247
+ const title = input.value.trim();
248
+ if (!title) return;
249
+
250
+ const btn = document.getElementById('add-btn');
251
+ btn.disabled = true;
252
+ try {
253
+ const data = await api('create', { title });
254
+ todos.unshift(data.todo);
255
+ input.value = '';
256
+ render();
257
+ } catch (e) {
258
+ showError('Failed to add todo: ' + e.message);
259
+ } finally {
260
+ btn.disabled = false;
261
+ input.focus();
262
+ }
263
+ }
264
+
265
+ async function toggleTodo(id) {
266
+ const todo = todos.find(t => t.id === id);
267
+ if (!todo) return;
268
+ try {
269
+ const data = await api('update', { id, completed: !todo.completed });
270
+ if (data.todo) {
271
+ const idx = todos.findIndex(t => t.id === id);
272
+ if (idx !== -1) todos[idx] = data.todo;
273
+ render();
274
+ }
275
+ } catch (e) {
276
+ showError('Failed to update todo: ' + e.message);
277
+ }
278
+ }
279
+
280
+ async function deleteTodo(id) {
281
+ try {
282
+ await api('delete', { id });
283
+ todos = todos.filter(t => t.id !== id);
284
+ render();
285
+ } catch (e) {
286
+ showError('Failed to delete todo: ' + e.message);
287
+ }
288
+ }
289
+
290
+ // ─── Render ─────────────────────────────────────
291
+ function render() {
292
+ const list = document.getElementById('todo-list');
293
+ const stats = document.getElementById('stats');
294
+
295
+ if (todos.length === 0) {
296
+ stats.style.display = 'none';
297
+ list.innerHTML = `
298
+ <div class="empty">
299
+ <svg width="48" height="48" fill="none" stroke="#3f3f46" stroke-width="1.5" viewBox="0 0 24 24">
300
+ <path d="M9 5H7a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-2M9 5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2M9 5h6"/>
301
+ </svg>
302
+ <p>No todos yet. Add one above!</p>
303
+ </div>`;
304
+ return;
305
+ }
306
+
307
+ const done = todos.filter(t => t.completed).length;
308
+ stats.style.display = 'flex';
309
+ document.getElementById('total-count').textContent = todos.length;
310
+ document.getElementById('done-count').textContent = done;
311
+
312
+ list.innerHTML = todos.map(todo => `
313
+ <div class="todo-item ${todo.completed ? 'completed' : ''}" data-id="${todo.id}">
314
+ <div class="todo-check" onclick="toggleTodo('${todo.id}')">
315
+ <svg width="14" height="14" fill="none" stroke="#fff" stroke-width="2.5" viewBox="0 0 24 24">
316
+ <path d="M5 13l4 4L19 7"/>
317
+ </svg>
318
+ </div>
319
+ <span class="todo-title">${escapeHtml(todo.title)}</span>
320
+ <button class="todo-delete" onclick="deleteTodo('${todo.id}')" title="Delete">
321
+ <svg width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
322
+ <path d="M18 6L6 18M6 6l12 12"/>
323
+ </svg>
324
+ </button>
325
+ </div>
326
+ `).join('');
327
+ }
328
+
329
+ function escapeHtml(text) {
330
+ const d = document.createElement('div');
331
+ d.textContent = text;
332
+ return d.innerHTML;
333
+ }
334
+
335
+ function showError(msg) {
336
+ const toast = document.getElementById('error-toast');
337
+ toast.textContent = msg;
338
+ toast.classList.add('show');
339
+ setTimeout(() => toast.classList.remove('show'), 3000);
340
+ }
341
+
342
+ // ─── Init ───────────────────────────────────────
343
+ document.getElementById('todo-input').addEventListener('keydown', (e) => {
344
+ if (e.key === 'Enter') addTodo();
345
+ });
346
+
347
+ loadTodos();
348
+
349
+ // ─── Live Reload (dev server) ───────────────────
350
+ if (location.hostname === 'localhost') {
351
+ try {
352
+ const es = new EventSource('/__dev/events');
353
+ es.onmessage = (e) => {
354
+ try {
355
+ const data = JSON.parse(e.data);
356
+ if (data.type !== 'connected') {
357
+ setTimeout(() => location.reload(), 300);
358
+ }
359
+ } catch {}
360
+ };
361
+ } catch {}
362
+ }
363
+ </script>
364
+ </body>
365
+ </html>
@@ -0,0 +1,17 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "esModuleInterop": true,
7
+ "strict": true,
8
+ "skipLibCheck": true,
9
+ "outDir": "dist",
10
+ "rootDir": ".",
11
+ "declaration": true,
12
+ "resolveJsonModule": true,
13
+ "isolatedModules": true
14
+ },
15
+ "include": ["app/**/*", "dev.ts", "clawfire.config.ts"],
16
+ "exclude": ["node_modules", "dist", "generated"]
17
+ }