claudeship 0.2.12 → 0.2.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/README.md +18 -0
  2. package/apps/server/dist/app.module.js +10 -0
  3. package/apps/server/dist/app.module.js.map +1 -1
  4. package/apps/server/dist/chat/prompts/fullstack-express-prompt.d.ts +1 -1
  5. package/apps/server/dist/chat/prompts/fullstack-express-prompt.js +109 -1
  6. package/apps/server/dist/chat/prompts/fullstack-express-prompt.js.map +1 -1
  7. package/apps/server/dist/chat/prompts/fullstack-fastapi-prompt.d.ts +1 -1
  8. package/apps/server/dist/chat/prompts/fullstack-fastapi-prompt.js +109 -1
  9. package/apps/server/dist/chat/prompts/fullstack-fastapi-prompt.js.map +1 -1
  10. package/apps/server/dist/chat/prompts/web-system-prompt.d.ts +1 -1
  11. package/apps/server/dist/chat/prompts/web-system-prompt.js +156 -0
  12. package/apps/server/dist/chat/prompts/web-system-prompt.js.map +1 -1
  13. package/apps/server/dist/checkpoint/checkpoint.controller.d.ts +19 -0
  14. package/apps/server/dist/checkpoint/checkpoint.controller.js +93 -0
  15. package/apps/server/dist/checkpoint/checkpoint.controller.js.map +1 -0
  16. package/apps/server/dist/checkpoint/checkpoint.module.d.ts +2 -0
  17. package/apps/server/dist/checkpoint/checkpoint.module.js +25 -0
  18. package/apps/server/dist/checkpoint/checkpoint.module.js.map +1 -0
  19. package/apps/server/dist/checkpoint/checkpoint.service.d.ts +41 -0
  20. package/apps/server/dist/checkpoint/checkpoint.service.js +261 -0
  21. package/apps/server/dist/checkpoint/checkpoint.service.js.map +1 -0
  22. package/apps/server/dist/database/database.controller.d.ts +23 -0
  23. package/apps/server/dist/database/database.controller.js +109 -0
  24. package/apps/server/dist/database/database.controller.js.map +1 -0
  25. package/apps/server/dist/database/database.module.d.ts +2 -0
  26. package/apps/server/dist/database/database.module.js +25 -0
  27. package/apps/server/dist/database/database.module.js.map +1 -0
  28. package/apps/server/dist/database/database.service.d.ts +32 -0
  29. package/apps/server/dist/database/database.service.js +238 -0
  30. package/apps/server/dist/database/database.service.js.map +1 -0
  31. package/apps/server/dist/env/env.controller.d.ts +14 -0
  32. package/apps/server/dist/env/env.controller.js +84 -0
  33. package/apps/server/dist/env/env.controller.js.map +1 -0
  34. package/apps/server/dist/env/env.module.d.ts +2 -0
  35. package/apps/server/dist/env/env.module.js +25 -0
  36. package/apps/server/dist/env/env.module.js.map +1 -0
  37. package/apps/server/dist/env/env.service.d.ts +21 -0
  38. package/apps/server/dist/env/env.service.js +194 -0
  39. package/apps/server/dist/env/env.service.js.map +1 -0
  40. package/apps/server/dist/preview/preview.controller.d.ts +5 -0
  41. package/apps/server/dist/preview/preview.controller.js +41 -0
  42. package/apps/server/dist/preview/preview.controller.js.map +1 -1
  43. package/apps/server/dist/preview/preview.service.d.ts +20 -0
  44. package/apps/server/dist/preview/preview.service.js +51 -2
  45. package/apps/server/dist/preview/preview.service.js.map +1 -1
  46. package/apps/server/dist/project/project.controller.d.ts +10 -1
  47. package/apps/server/dist/project/project.controller.js +57 -0
  48. package/apps/server/dist/project/project.controller.js.map +1 -1
  49. package/apps/server/dist/project/project.service.d.ts +15 -0
  50. package/apps/server/dist/project/project.service.js +111 -0
  51. package/apps/server/dist/project/project.service.js.map +1 -1
  52. package/apps/server/dist/project-context/project-context.controller.d.ts +42 -0
  53. package/apps/server/dist/project-context/project-context.controller.js +127 -0
  54. package/apps/server/dist/project-context/project-context.controller.js.map +1 -0
  55. package/apps/server/dist/project-context/project-context.module.d.ts +2 -0
  56. package/apps/server/dist/project-context/project-context.module.js +25 -0
  57. package/apps/server/dist/project-context/project-context.module.js.map +1 -0
  58. package/apps/server/dist/project-context/project-context.service.d.ts +36 -0
  59. package/apps/server/dist/project-context/project-context.service.js +260 -0
  60. package/apps/server/dist/project-context/project-context.service.js.map +1 -0
  61. package/apps/server/dist/testing/testing.controller.d.ts +24 -0
  62. package/apps/server/dist/testing/testing.controller.js +126 -0
  63. package/apps/server/dist/testing/testing.controller.js.map +1 -0
  64. package/apps/server/dist/testing/testing.module.d.ts +2 -0
  65. package/apps/server/dist/testing/testing.module.js +26 -0
  66. package/apps/server/dist/testing/testing.module.js.map +1 -0
  67. package/apps/server/dist/testing/testing.service.d.ts +62 -0
  68. package/apps/server/dist/testing/testing.service.js +269 -0
  69. package/apps/server/dist/testing/testing.service.js.map +1 -0
  70. package/apps/server/dist/tsconfig.tsbuildinfo +1 -1
  71. package/apps/server/package.json +1 -1
  72. package/apps/web/.next/BUILD_ID +1 -1
  73. package/apps/web/.next/app-build-manifest.json +5 -5
  74. package/apps/web/.next/build-manifest.json +2 -2
  75. package/apps/web/.next/cache/.previewinfo +1 -1
  76. package/apps/web/.next/cache/.rscinfo +1 -1
  77. package/apps/web/.next/cache/.tsbuildinfo +1 -1
  78. package/apps/web/.next/cache/config.json +3 -3
  79. package/apps/web/.next/cache/eslint/.cache_j3uhuz +1 -1
  80. package/apps/web/.next/cache/webpack/client-production/0.pack +0 -0
  81. package/apps/web/.next/cache/webpack/client-production/index.pack +0 -0
  82. package/apps/web/.next/cache/webpack/edge-server-production/index.pack +0 -0
  83. package/apps/web/.next/cache/webpack/server-production/0.pack +0 -0
  84. package/apps/web/.next/cache/webpack/server-production/index.pack +0 -0
  85. package/apps/web/.next/prerender-manifest.json +10 -10
  86. package/apps/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  87. package/apps/web/.next/server/app/_not-found.html +1 -1
  88. package/apps/web/.next/server/app/_not-found.rsc +2 -2
  89. package/apps/web/.next/server/app/index.html +1 -1
  90. package/apps/web/.next/server/app/index.rsc +3 -3
  91. package/apps/web/.next/server/app/page.js +2 -2
  92. package/apps/web/.next/server/app/page_client-reference-manifest.js +1 -1
  93. package/apps/web/.next/server/app/project/[id]/page.js +2 -2
  94. package/apps/web/.next/server/app/project/[id]/page_client-reference-manifest.js +1 -1
  95. package/apps/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  96. package/apps/web/.next/server/app/settings.html +1 -1
  97. package/apps/web/.next/server/app/settings.rsc +3 -3
  98. package/apps/web/.next/server/chunks/392.js +1 -1
  99. package/apps/web/.next/server/pages/404.html +1 -1
  100. package/apps/web/.next/server/pages/500.html +1 -1
  101. package/apps/web/.next/server/server-reference-manifest.json +1 -1
  102. package/apps/web/.next/static/chunks/574-1fe2bcd6cfb41646.js +1 -0
  103. package/apps/web/.next/static/chunks/app/page-f19cfa58541ca83d.js +1 -0
  104. package/apps/web/.next/static/chunks/app/project/[id]/page-dffaa1d02f012216.js +1 -0
  105. package/apps/web/.next/static/chunks/app/settings/page-d1318c2fd58729a5.js +1 -0
  106. package/apps/web/.next/static/css/0a24552d9794f8c8.css +3 -0
  107. package/apps/web/.next/trace +18 -17
  108. package/apps/web/node_modules/.bin/eslint +2 -2
  109. package/apps/web/package.json +2 -1
  110. package/apps/web/src/components/checkpoint/CheckpointPanel.tsx +384 -0
  111. package/apps/web/src/components/database/DatabasePanel.tsx +405 -0
  112. package/apps/web/src/components/env/EnvPanel.tsx +356 -0
  113. package/apps/web/src/components/preview/ConsoleViewer.tsx +270 -0
  114. package/apps/web/src/components/preview/ErrorOverlay.tsx +189 -0
  115. package/apps/web/src/components/preview/PreviewPanel.tsx +148 -6
  116. package/apps/web/src/components/testing/TestRunner.tsx +481 -0
  117. package/apps/web/src/components/ui/tabs.tsx +55 -0
  118. package/apps/web/src/components/visual-editor/VisualEditor.tsx +382 -0
  119. package/apps/web/src/components/workspace/WorkspaceLayout.tsx +66 -4
  120. package/apps/web/src/lib/api.ts +5 -2
  121. package/package.json +1 -1
  122. package/apps/web/.next/static/chunks/298-6f3d6b321c288cd3.js +0 -1
  123. package/apps/web/.next/static/chunks/app/page-3d093f7f480a8599.js +0 -1
  124. package/apps/web/.next/static/chunks/app/project/[id]/page-e5cda6f9050b0a52.js +0 -1
  125. package/apps/web/.next/static/chunks/app/settings/page-92d28565c3d8c755.js +0 -1
  126. package/apps/web/.next/static/css/8f946046a2047594.css +0 -3
  127. /package/apps/web/.next/static/{aXT20mSdxaem1-z8VH2F1 → mkY_TTl_ho_ehDKiX10AN}/_buildManifest.js +0 -0
  128. /package/apps/web/.next/static/{aXT20mSdxaem1-z8VH2F1 → mkY_TTl_ho_ehDKiX10AN}/_ssgManifest.js +0 -0
@@ -0,0 +1,405 @@
1
+ "use client";
2
+
3
+ import { useEffect, useState, useCallback } from "react";
4
+ import {
5
+ Database,
6
+ Table,
7
+ RefreshCw,
8
+ ChevronLeft,
9
+ ChevronRight,
10
+ Plus,
11
+ Trash2,
12
+ AlertCircle,
13
+ Play,
14
+ } from "lucide-react";
15
+ import { Button } from "@/components/ui/button";
16
+ import { Input } from "@/components/ui/input";
17
+ import { api } from "@/lib/api";
18
+
19
+ interface TableInfo {
20
+ name: string;
21
+ rowCount: number;
22
+ }
23
+
24
+ interface ColumnInfo {
25
+ name: string;
26
+ type: string;
27
+ nullable: boolean;
28
+ primaryKey: boolean;
29
+ }
30
+
31
+ interface TableData {
32
+ columns: ColumnInfo[];
33
+ rows: Record<string, unknown>[];
34
+ total: number;
35
+ page: number;
36
+ pageSize: number;
37
+ }
38
+
39
+ interface DatabasePanelProps {
40
+ projectId: string;
41
+ }
42
+
43
+ export function DatabasePanel({ projectId }: DatabasePanelProps) {
44
+ const [tables, setTables] = useState<TableInfo[]>([]);
45
+ const [selectedTable, setSelectedTable] = useState<string | null>(null);
46
+ const [tableData, setTableData] = useState<TableData | null>(null);
47
+ const [isLoading, setIsLoading] = useState(false);
48
+ const [error, setError] = useState<string | null>(null);
49
+ const [page, setPage] = useState(1);
50
+ const [queryMode, setQueryMode] = useState(false);
51
+ const [query, setQuery] = useState("");
52
+ const [queryResult, setQueryResult] = useState<Record<string, unknown>[] | null>(null);
53
+
54
+ const pageSize = 50;
55
+
56
+ // Fetch tables
57
+ const fetchTables = useCallback(async () => {
58
+ setIsLoading(true);
59
+ setError(null);
60
+ try {
61
+ const result = await api.get<TableInfo[]>(`/projects/${projectId}/database/tables`);
62
+ setTables(result);
63
+ if (result.length > 0 && !selectedTable) {
64
+ setSelectedTable(result[0].name);
65
+ }
66
+ } catch (e) {
67
+ setError(e instanceof Error ? e.message : "Failed to load tables");
68
+ } finally {
69
+ setIsLoading(false);
70
+ }
71
+ }, [projectId, selectedTable]);
72
+
73
+ // Fetch table data
74
+ const fetchTableData = useCallback(async () => {
75
+ if (!selectedTable) return;
76
+
77
+ setIsLoading(true);
78
+ setError(null);
79
+ try {
80
+ const result = await api.get<TableData>(
81
+ `/projects/${projectId}/database/tables/${selectedTable}/data?page=${page}&pageSize=${pageSize}`
82
+ );
83
+ setTableData(result);
84
+ } catch (e) {
85
+ setError(e instanceof Error ? e.message : "Failed to load table data");
86
+ } finally {
87
+ setIsLoading(false);
88
+ }
89
+ }, [projectId, selectedTable, page]);
90
+
91
+ useEffect(() => {
92
+ fetchTables();
93
+ }, [fetchTables]);
94
+
95
+ useEffect(() => {
96
+ if (selectedTable) {
97
+ setPage(1);
98
+ fetchTableData();
99
+ }
100
+ }, [selectedTable]);
101
+
102
+ useEffect(() => {
103
+ if (selectedTable) {
104
+ fetchTableData();
105
+ }
106
+ }, [page, fetchTableData]);
107
+
108
+ const handleSelectTable = (tableName: string) => {
109
+ setSelectedTable(tableName);
110
+ setQueryMode(false);
111
+ setQueryResult(null);
112
+ };
113
+
114
+ const handleDeleteRow = async (row: Record<string, unknown>) => {
115
+ if (!selectedTable || !tableData) return;
116
+
117
+ const primaryKeyCol = tableData.columns.find((c) => c.primaryKey);
118
+ if (!primaryKeyCol) {
119
+ setError("No primary key found for this table");
120
+ return;
121
+ }
122
+
123
+ if (!confirm("Are you sure you want to delete this row?")) {
124
+ return;
125
+ }
126
+
127
+ try {
128
+ await api.delete(`/projects/${projectId}/database/tables/${selectedTable}/rows`, {
129
+ primaryKey: primaryKeyCol.name,
130
+ primaryKeyValue: row[primaryKeyCol.name],
131
+ });
132
+ await fetchTableData();
133
+ } catch (e) {
134
+ setError(e instanceof Error ? e.message : "Failed to delete row");
135
+ }
136
+ };
137
+
138
+ const handleExecuteQuery = async () => {
139
+ if (!query.trim()) return;
140
+
141
+ setIsLoading(true);
142
+ setError(null);
143
+ try {
144
+ const result = await api.post<Record<string, unknown>[]>(
145
+ `/projects/${projectId}/database/query`,
146
+ { query }
147
+ );
148
+ setQueryResult(result);
149
+ } catch (e) {
150
+ setError(e instanceof Error ? e.message : "Query execution failed");
151
+ } finally {
152
+ setIsLoading(false);
153
+ }
154
+ };
155
+
156
+ const totalPages = tableData ? Math.ceil(tableData.total / pageSize) : 0;
157
+
158
+ if (isLoading && tables.length === 0) {
159
+ return (
160
+ <div className="flex h-full items-center justify-center text-muted-foreground">
161
+ <RefreshCw className="h-5 w-5 animate-spin mr-2" />
162
+ Loading database...
163
+ </div>
164
+ );
165
+ }
166
+
167
+ if (error && tables.length === 0) {
168
+ return (
169
+ <div className="flex h-full items-center justify-center text-muted-foreground">
170
+ <div className="text-center">
171
+ <Database className="h-8 w-8 mx-auto mb-2 opacity-50" />
172
+ <p className="text-sm">{error}</p>
173
+ <Button variant="outline" size="sm" onClick={fetchTables} className="mt-2">
174
+ Retry
175
+ </Button>
176
+ </div>
177
+ </div>
178
+ );
179
+ }
180
+
181
+ return (
182
+ <div className="flex h-full flex-col">
183
+ {/* Header */}
184
+ <div className="flex items-center justify-between border-b px-4 py-3">
185
+ <h3 className="font-medium flex items-center gap-2">
186
+ <Database className="h-4 w-4" />
187
+ Database
188
+ </h3>
189
+ <div className="flex items-center gap-2">
190
+ <Button
191
+ variant={queryMode ? "secondary" : "outline"}
192
+ size="sm"
193
+ onClick={() => setQueryMode(!queryMode)}
194
+ className="h-8"
195
+ >
196
+ SQL
197
+ </Button>
198
+ <Button
199
+ variant="ghost"
200
+ size="sm"
201
+ onClick={fetchTables}
202
+ disabled={isLoading}
203
+ className="h-8 w-8 p-0"
204
+ >
205
+ <RefreshCw className={`h-4 w-4 ${isLoading ? "animate-spin" : ""}`} />
206
+ </Button>
207
+ </div>
208
+ </div>
209
+
210
+ {/* Error */}
211
+ {error && (
212
+ <div className="flex items-center gap-2 px-4 py-2 bg-destructive/10 text-destructive text-sm">
213
+ <AlertCircle className="h-4 w-4" />
214
+ {error}
215
+ </div>
216
+ )}
217
+
218
+ {/* Query Mode */}
219
+ {queryMode && (
220
+ <div className="border-b p-4 space-y-2">
221
+ <div className="flex gap-2">
222
+ <Input
223
+ value={query}
224
+ onChange={(e) => setQuery(e.target.value)}
225
+ placeholder="SELECT * FROM users LIMIT 10"
226
+ className="font-mono text-sm"
227
+ onKeyDown={(e) => {
228
+ if (e.key === "Enter" && e.metaKey) {
229
+ handleExecuteQuery();
230
+ }
231
+ }}
232
+ />
233
+ <Button onClick={handleExecuteQuery} disabled={isLoading} size="sm">
234
+ <Play className="h-4 w-4 mr-1" />
235
+ Run
236
+ </Button>
237
+ </div>
238
+ <p className="text-xs text-muted-foreground">
239
+ Press Cmd+Enter to execute
240
+ </p>
241
+ </div>
242
+ )}
243
+
244
+ <div className="flex flex-1 overflow-hidden">
245
+ {/* Table List Sidebar */}
246
+ <div className="w-48 border-r overflow-auto">
247
+ <div className="p-2 space-y-1">
248
+ {tables.map((table) => (
249
+ <button
250
+ key={table.name}
251
+ onClick={() => handleSelectTable(table.name)}
252
+ className={`w-full flex items-center justify-between px-3 py-2 text-sm rounded-md transition-colors ${
253
+ selectedTable === table.name
254
+ ? "bg-primary/10 text-primary"
255
+ : "hover:bg-muted"
256
+ }`}
257
+ >
258
+ <span className="flex items-center gap-2 truncate">
259
+ <Table className="h-4 w-4 shrink-0" />
260
+ <span className="truncate">{table.name}</span>
261
+ </span>
262
+ <span className="text-xs text-muted-foreground">{table.rowCount}</span>
263
+ </button>
264
+ ))}
265
+ {tables.length === 0 && (
266
+ <p className="text-sm text-muted-foreground px-3 py-2">
267
+ No tables found
268
+ </p>
269
+ )}
270
+ </div>
271
+ </div>
272
+
273
+ {/* Data Grid */}
274
+ <div className="flex-1 flex flex-col overflow-hidden">
275
+ {queryMode && queryResult ? (
276
+ // Query Results
277
+ <div className="flex-1 overflow-auto">
278
+ {queryResult.length > 0 ? (
279
+ <table className="w-full text-sm">
280
+ <thead className="bg-muted/50 sticky top-0">
281
+ <tr>
282
+ {Object.keys(queryResult[0]).map((key) => (
283
+ <th
284
+ key={key}
285
+ className="px-3 py-2 text-left font-medium text-muted-foreground border-b"
286
+ >
287
+ {key}
288
+ </th>
289
+ ))}
290
+ </tr>
291
+ </thead>
292
+ <tbody>
293
+ {queryResult.map((row, i) => (
294
+ <tr key={i} className="border-b hover:bg-muted/30">
295
+ {Object.values(row).map((value, j) => (
296
+ <td key={j} className="px-3 py-2 font-mono">
297
+ {value === null ? (
298
+ <span className="text-muted-foreground">NULL</span>
299
+ ) : (
300
+ String(value)
301
+ )}
302
+ </td>
303
+ ))}
304
+ </tr>
305
+ ))}
306
+ </tbody>
307
+ </table>
308
+ ) : (
309
+ <div className="flex h-full items-center justify-center text-muted-foreground">
310
+ Query returned no results
311
+ </div>
312
+ )}
313
+ </div>
314
+ ) : tableData ? (
315
+ // Table Data
316
+ <>
317
+ <div className="flex-1 overflow-auto">
318
+ <table className="w-full text-sm">
319
+ <thead className="bg-muted/50 sticky top-0">
320
+ <tr>
321
+ {tableData.columns.map((col) => (
322
+ <th
323
+ key={col.name}
324
+ className="px-3 py-2 text-left font-medium text-muted-foreground border-b"
325
+ >
326
+ <div className="flex items-center gap-1">
327
+ {col.name}
328
+ {col.primaryKey && (
329
+ <span className="text-xs text-primary">PK</span>
330
+ )}
331
+ </div>
332
+ <span className="text-xs font-normal">{col.type}</span>
333
+ </th>
334
+ ))}
335
+ <th className="w-10 border-b"></th>
336
+ </tr>
337
+ </thead>
338
+ <tbody>
339
+ {tableData.rows.map((row, i) => (
340
+ <tr key={i} className="border-b hover:bg-muted/30">
341
+ {tableData.columns.map((col) => (
342
+ <td key={col.name} className="px-3 py-2 font-mono">
343
+ {row[col.name] === null ? (
344
+ <span className="text-muted-foreground">NULL</span>
345
+ ) : (
346
+ String(row[col.name])
347
+ )}
348
+ </td>
349
+ ))}
350
+ <td className="px-2">
351
+ <Button
352
+ variant="ghost"
353
+ size="sm"
354
+ onClick={() => handleDeleteRow(row)}
355
+ className="h-6 w-6 p-0 text-muted-foreground hover:text-destructive"
356
+ >
357
+ <Trash2 className="h-3 w-3" />
358
+ </Button>
359
+ </td>
360
+ </tr>
361
+ ))}
362
+ </tbody>
363
+ </table>
364
+ </div>
365
+
366
+ {/* Pagination */}
367
+ <div className="flex items-center justify-between border-t px-4 py-2">
368
+ <span className="text-sm text-muted-foreground">
369
+ {tableData.total} rows total
370
+ </span>
371
+ <div className="flex items-center gap-2">
372
+ <Button
373
+ variant="outline"
374
+ size="sm"
375
+ onClick={() => setPage((p) => Math.max(1, p - 1))}
376
+ disabled={page === 1}
377
+ className="h-8 w-8 p-0"
378
+ >
379
+ <ChevronLeft className="h-4 w-4" />
380
+ </Button>
381
+ <span className="text-sm">
382
+ {page} / {totalPages || 1}
383
+ </span>
384
+ <Button
385
+ variant="outline"
386
+ size="sm"
387
+ onClick={() => setPage((p) => Math.min(totalPages, p + 1))}
388
+ disabled={page >= totalPages}
389
+ className="h-8 w-8 p-0"
390
+ >
391
+ <ChevronRight className="h-4 w-4" />
392
+ </Button>
393
+ </div>
394
+ </div>
395
+ </>
396
+ ) : (
397
+ <div className="flex h-full items-center justify-center text-muted-foreground">
398
+ Select a table to view data
399
+ </div>
400
+ )}
401
+ </div>
402
+ </div>
403
+ </div>
404
+ );
405
+ }