@hustle-together/api-dev-tools 3.12.3 → 4.5.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.
- package/.claude/adr-requests/.gitkeep +10 -0
- package/.claude/agents/adr-researcher.md +109 -0
- package/.claude/agents/visual-analyzer.md +183 -0
- package/.claude/api-dev-state.json +7 -463
- package/.claude/documentation-audit.json +114 -0
- package/.claude/registry.json +289 -0
- package/.claude/settings.json +45 -1
- package/.claude/workflow-logs/None.json +49 -0
- package/.claude/workflow-logs/session-20251230-143727.json +106 -0
- package/.skills/adr-deep-research/SKILL.md +351 -0
- package/.skills/api-create/SKILL.md +116 -17
- package/.skills/api-research/SKILL.md +130 -0
- package/.skills/docs-sync/SKILL.md +260 -0
- package/.skills/docs-update/SKILL.md +205 -0
- package/.skills/hustle-brand/SKILL.md +368 -0
- package/.skills/hustle-build/SKILL.md +786 -0
- package/.skills/hustle-build-review/SKILL.md +518 -0
- package/.skills/parallel-spawn/SKILL.md +212 -0
- package/.skills/ralph-continue/SKILL.md +151 -0
- package/.skills/ralph-loop/SKILL.md +341 -0
- package/.skills/ralph-status/SKILL.md +87 -0
- package/.skills/refactor/SKILL.md +59 -0
- package/.skills/shadcn/SKILL.md +522 -0
- package/.skills/test-all/SKILL.md +210 -0
- package/.skills/test-builds/SKILL.md +208 -0
- package/.skills/test-debug/SKILL.md +212 -0
- package/.skills/test-e2e/SKILL.md +168 -0
- package/.skills/test-review/SKILL.md +707 -0
- package/.skills/test-unit/SKILL.md +143 -0
- package/.skills/test-visual/SKILL.md +301 -0
- package/.skills/token-report/SKILL.md +132 -0
- package/CHANGELOG.md +575 -0
- package/README.md +426 -56
- package/bin/cli.js +1538 -88
- package/commands/hustle-api-create.md +22 -0
- package/commands/hustle-build.md +259 -0
- package/commands/hustle-combine.md +81 -2
- package/commands/hustle-ui-create-page.md +84 -2
- package/commands/hustle-ui-create.md +82 -2
- package/hooks/__pycache__/api-workflow-check.cpython-314.pyc +0 -0
- package/hooks/__pycache__/auto-answer.cpython-314.pyc +0 -0
- package/hooks/__pycache__/cache-research.cpython-314.pyc +0 -0
- package/hooks/__pycache__/check-api-routes.cpython-314.pyc +0 -0
- package/hooks/__pycache__/check-playwright-setup.cpython-314.pyc +0 -0
- package/hooks/__pycache__/check-storybook-setup.cpython-314.pyc +0 -0
- package/hooks/__pycache__/check-update.cpython-314.pyc +0 -0
- package/hooks/__pycache__/completion-promise-detector.cpython-314.pyc +0 -0
- package/hooks/__pycache__/context-capacity-warning.cpython-314.pyc +0 -0
- package/hooks/__pycache__/detect-interruption.cpython-314.pyc +0 -0
- package/hooks/__pycache__/docs-update-check.cpython-314.pyc +0 -0
- package/hooks/__pycache__/enforce-a11y-audit.cpython-314.pyc +0 -0
- package/hooks/__pycache__/enforce-brand-guide.cpython-314.pyc +0 -0
- package/hooks/__pycache__/enforce-component-type-confirm.cpython-314.pyc +0 -0
- package/hooks/__pycache__/enforce-deep-research.cpython-314.pyc +0 -0
- package/hooks/__pycache__/enforce-disambiguation.cpython-314.pyc +0 -0
- package/hooks/__pycache__/enforce-documentation.cpython-314.pyc +0 -0
- package/hooks/__pycache__/enforce-dry-run.cpython-314.pyc +0 -0
- package/hooks/__pycache__/enforce-environment.cpython-314.pyc +0 -0
- package/hooks/__pycache__/enforce-external-research.cpython-314.pyc +0 -0
- package/hooks/__pycache__/enforce-freshness.cpython-314.pyc +0 -0
- package/hooks/__pycache__/enforce-interview.cpython-314.pyc +0 -0
- package/hooks/__pycache__/enforce-page-components.cpython-314.pyc +0 -0
- package/hooks/__pycache__/enforce-page-data-schema.cpython-314.pyc +0 -0
- package/hooks/__pycache__/enforce-questions-sourced.cpython-314.pyc +0 -0
- package/hooks/__pycache__/enforce-refactor.cpython-314.pyc +0 -0
- package/hooks/__pycache__/enforce-research.cpython-314.pyc +0 -0
- package/hooks/__pycache__/enforce-schema-from-interview.cpython-314.pyc +0 -0
- package/hooks/__pycache__/enforce-schema.cpython-314.pyc +0 -0
- package/hooks/__pycache__/enforce-scope.cpython-314.pyc +0 -0
- package/hooks/__pycache__/enforce-tdd-red.cpython-314.pyc +0 -0
- package/hooks/__pycache__/enforce-ui-disambiguation.cpython-314.pyc +0 -0
- package/hooks/__pycache__/enforce-ui-interview.cpython-314.pyc +0 -0
- package/hooks/__pycache__/enforce-verify.cpython-314.pyc +0 -0
- package/hooks/__pycache__/generate-adr-options.cpython-314.pyc +0 -0
- package/hooks/__pycache__/generate-manifest-entry.cpython-314.pyc +0 -0
- package/hooks/__pycache__/hook_utils.cpython-314.pyc +0 -0
- package/hooks/__pycache__/notify-input-needed.cpython-314.pyc +0 -0
- package/hooks/__pycache__/notify-phase-complete.cpython-314.pyc +0 -0
- package/hooks/__pycache__/ntfy-on-question.cpython-314.pyc +0 -0
- package/hooks/__pycache__/orchestrator-completion.cpython-314.pyc +0 -0
- package/hooks/__pycache__/orchestrator-handoff.cpython-314.pyc +0 -0
- package/hooks/__pycache__/orchestrator-session-startup.cpython-314.pyc +0 -0
- package/hooks/__pycache__/parallel-orchestrator.cpython-314.pyc +0 -0
- package/hooks/__pycache__/periodic-reground.cpython-314.pyc +0 -0
- package/hooks/__pycache__/project-document-prompt.cpython-314.pyc +0 -0
- package/hooks/__pycache__/remote-question-proxy.cpython-314.pyc +0 -0
- package/hooks/__pycache__/remote-question-server.cpython-314.pyc +0 -0
- package/hooks/__pycache__/run-code-review.cpython-314.pyc +0 -0
- package/hooks/__pycache__/run-visual-qa.cpython-314.pyc +0 -0
- package/hooks/__pycache__/session-logger.cpython-314.pyc +0 -0
- package/hooks/__pycache__/session-startup.cpython-314.pyc +0 -0
- package/hooks/__pycache__/track-scope-coverage.cpython-314.pyc +0 -0
- package/hooks/__pycache__/track-token-usage.cpython-314.pyc +0 -0
- package/hooks/__pycache__/track-tool-use.cpython-314.pyc +0 -0
- package/hooks/__pycache__/update-adr-decision.cpython-314.pyc +0 -0
- package/hooks/__pycache__/update-api-showcase.cpython-314.pyc +0 -0
- package/hooks/__pycache__/update-registry.cpython-314.pyc +0 -0
- package/hooks/__pycache__/update-ui-showcase.cpython-314.pyc +0 -0
- package/hooks/__pycache__/verify-after-green.cpython-314.pyc +0 -0
- package/hooks/__pycache__/verify-implementation.cpython-314.pyc +0 -0
- package/hooks/api-workflow-check.py +34 -0
- package/hooks/auto-answer.py +305 -0
- package/hooks/check-update.py +132 -0
- package/hooks/completion-promise-detector.py +293 -0
- package/hooks/context-capacity-warning.py +171 -0
- package/hooks/docs-update-check.py +120 -0
- package/hooks/enforce-dry-run.py +134 -0
- package/hooks/enforce-external-research.py +25 -0
- package/hooks/enforce-interview.py +20 -0
- package/hooks/generate-adr-options.py +282 -0
- package/hooks/hook_utils.py +609 -0
- package/hooks/lib/__pycache__/__init__.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/greptile.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/ntfy.cpython-314.pyc +0 -0
- package/hooks/ntfy-on-question.py +240 -0
- package/hooks/orchestrator-completion.py +313 -0
- package/hooks/orchestrator-handoff.py +267 -0
- package/hooks/orchestrator-session-startup.py +146 -0
- package/hooks/parallel-orchestrator.py +451 -0
- package/hooks/periodic-reground.py +270 -67
- package/hooks/project-document-prompt.py +302 -0
- package/hooks/remote-question-proxy.py +284 -0
- package/hooks/remote-question-server.py +1224 -0
- package/hooks/run-code-review.py +176 -29
- package/hooks/run-visual-qa.py +338 -0
- package/hooks/session-logger.py +27 -1
- package/hooks/session-startup.py +113 -0
- package/hooks/update-adr-decision.py +236 -0
- package/hooks/update-api-showcase.py +13 -1
- package/hooks/update-testing-checklist.py +195 -0
- package/hooks/update-ui-showcase.py +13 -1
- package/package.json +7 -3
- package/scripts/extract-schema-docs.cjs +322 -0
- package/templates/.skills/hustle-interview/SKILL.md +174 -0
- package/templates/CLAUDE-SECTION.md +89 -64
- package/templates/adr-viewer/_components/ADRViewer.tsx +326 -0
- package/templates/api-dev-state.json +33 -1
- package/templates/api-showcase/_components/APIModal.tsx +100 -8
- package/templates/api-showcase/_components/APIShowcase.tsx +36 -4
- package/templates/api-showcase/_components/APITester.tsx +367 -58
- package/templates/brand-page/page.tsx +645 -0
- package/templates/component/Component.visual.spec.ts +30 -24
- package/templates/docs/page.tsx +230 -0
- package/templates/eslint-plugin-zod-schema/index.js +446 -0
- package/templates/eslint-plugin-zod-schema/package.json +26 -0
- package/templates/github-workflows/security.yml +274 -0
- package/templates/hustle-build-defaults.json +136 -0
- package/templates/hustle-dev-dashboard/page.tsx +365 -0
- package/templates/page/page.e2e.test.ts +30 -26
- package/templates/performance-budgets.json +63 -5
- package/templates/playwright-report/page.tsx +258 -0
- package/templates/registry.json +279 -3
- package/templates/review-dashboard/page.tsx +510 -0
- package/templates/settings.json +155 -7
- package/templates/test-results/page.tsx +237 -0
- package/templates/typedoc.json +19 -0
- package/templates/ui-showcase/_components/UIShowcase.tsx +48 -1
- package/templates/ui-showcase/_components/VisualTestingDashboard.tsx +579 -0
- package/templates/ui-showcase/page.tsx +1 -1
package/templates/settings.json
CHANGED
|
@@ -1,18 +1,87 @@
|
|
|
1
1
|
{
|
|
2
2
|
"permissions": {
|
|
3
3
|
"allow": [
|
|
4
|
+
"Read(*)",
|
|
5
|
+
"Write(*)",
|
|
6
|
+
"Edit(*)",
|
|
7
|
+
"Glob(*)",
|
|
8
|
+
"Grep(*)",
|
|
9
|
+
"LSP(*)",
|
|
10
|
+
"NotebookEdit(*)",
|
|
4
11
|
"WebSearch",
|
|
5
12
|
"WebFetch",
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"
|
|
13
|
+
"Task",
|
|
14
|
+
"TodoWrite",
|
|
15
|
+
"AskUserQuestion",
|
|
16
|
+
"Skill",
|
|
17
|
+
"mcp__context7__*",
|
|
18
|
+
"mcp__github__*",
|
|
19
|
+
"mcp__linear__*",
|
|
20
|
+
"mcp__supabase__*",
|
|
21
|
+
"mcp__playwright__*",
|
|
10
22
|
"Bash(claude mcp:*)",
|
|
11
|
-
"Bash(pnpm
|
|
12
|
-
"Bash(npm
|
|
23
|
+
"Bash(pnpm *)",
|
|
24
|
+
"Bash(npm *)",
|
|
25
|
+
"Bash(npx *)",
|
|
13
26
|
"Bash(git status:*)",
|
|
14
27
|
"Bash(git diff:*)",
|
|
15
|
-
"Bash(git log:*)"
|
|
28
|
+
"Bash(git log:*)",
|
|
29
|
+
"Bash(git add:*)",
|
|
30
|
+
"Bash(git commit:*)",
|
|
31
|
+
"Bash(git branch:*)",
|
|
32
|
+
"Bash(git checkout:*)",
|
|
33
|
+
"Bash(curl:*)",
|
|
34
|
+
"Bash(tree:*)",
|
|
35
|
+
"Bash(ls:*)",
|
|
36
|
+
"Bash(cat:*)",
|
|
37
|
+
"Bash(echo:*)",
|
|
38
|
+
"Bash(mkdir:*)",
|
|
39
|
+
"Bash(touch:*)",
|
|
40
|
+
"Bash(cp:*)",
|
|
41
|
+
"Bash(mv:*)",
|
|
42
|
+
"Bash(chmod:*)"
|
|
43
|
+
],
|
|
44
|
+
"deny": [
|
|
45
|
+
"Read(.env*)",
|
|
46
|
+
"Read(**/.env*)",
|
|
47
|
+
"Read(**/secrets/**)",
|
|
48
|
+
"Read(**/credentials*)",
|
|
49
|
+
"Read(**/*.pem)",
|
|
50
|
+
"Read(**/*.key)",
|
|
51
|
+
"Read(**/.ssh/**)",
|
|
52
|
+
"Read(**/.aws/**)",
|
|
53
|
+
"Read(**/.gcloud/**)",
|
|
54
|
+
"Write(.env*)",
|
|
55
|
+
"Write(**/.env*)",
|
|
56
|
+
"Write(**/secrets/**)",
|
|
57
|
+
"Edit(.env*)",
|
|
58
|
+
"Edit(**/.env*)",
|
|
59
|
+
"Edit(**/secrets/**)",
|
|
60
|
+
"Bash(rm -rf:*)",
|
|
61
|
+
"Bash(sudo:*)",
|
|
62
|
+
"Bash(chmod 777:*)",
|
|
63
|
+
"Bash(chown -R:*)",
|
|
64
|
+
"Bash(git push --force:*)",
|
|
65
|
+
"Bash(git push -f:*)",
|
|
66
|
+
"Bash(git reset --hard:*)",
|
|
67
|
+
"Bash(git clean -fd:*)",
|
|
68
|
+
"Bash(git stash drop:*)",
|
|
69
|
+
"Bash(git branch -D main)",
|
|
70
|
+
"Bash(git branch -D master)",
|
|
71
|
+
"Bash(eval:*)",
|
|
72
|
+
"Write(/etc/**)",
|
|
73
|
+
"Write(/var/**)",
|
|
74
|
+
"Write(/usr/**)",
|
|
75
|
+
"Write(/bin/**)",
|
|
76
|
+
"Write(/sbin/**)",
|
|
77
|
+
"Read(/etc/passwd)",
|
|
78
|
+
"Read(/etc/shadow)",
|
|
79
|
+
"Bash(nmap:*)",
|
|
80
|
+
"Bash(nikto:*)",
|
|
81
|
+
"Bash(sqlmap:*)",
|
|
82
|
+
"Bash(hydra:*)",
|
|
83
|
+
"Bash(metasploit:*)",
|
|
84
|
+
"Bash(msfconsole:*)"
|
|
16
85
|
]
|
|
17
86
|
},
|
|
18
87
|
"hooks": {
|
|
@@ -26,6 +95,18 @@
|
|
|
26
95
|
{
|
|
27
96
|
"type": "command",
|
|
28
97
|
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/detect-interruption.py"
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"type": "command",
|
|
101
|
+
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/check-update.py"
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"type": "command",
|
|
105
|
+
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/orchestrator-session-startup.py"
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"type": "command",
|
|
109
|
+
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/parallel-orchestrator.py"
|
|
29
110
|
}
|
|
30
111
|
]
|
|
31
112
|
}
|
|
@@ -36,6 +117,14 @@
|
|
|
36
117
|
{
|
|
37
118
|
"type": "command",
|
|
38
119
|
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/enforce-external-research.py"
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
"type": "command",
|
|
123
|
+
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/parallel-orchestrator.py"
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
"type": "command",
|
|
127
|
+
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/completion-promise-detector.py"
|
|
39
128
|
}
|
|
40
129
|
]
|
|
41
130
|
}
|
|
@@ -44,6 +133,10 @@
|
|
|
44
133
|
{
|
|
45
134
|
"matcher": "Write|Edit",
|
|
46
135
|
"hooks": [
|
|
136
|
+
{
|
|
137
|
+
"type": "command",
|
|
138
|
+
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/enforce-dry-run.py"
|
|
139
|
+
},
|
|
47
140
|
{
|
|
48
141
|
"type": "command",
|
|
49
142
|
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/enforce-disambiguation.py"
|
|
@@ -140,6 +233,19 @@
|
|
|
140
233
|
{
|
|
141
234
|
"type": "command",
|
|
142
235
|
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/enforce-questions-sourced.py"
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
"type": "command",
|
|
239
|
+
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/auto-answer.py"
|
|
240
|
+
}
|
|
241
|
+
]
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
"matcher": "Skill",
|
|
245
|
+
"hooks": [
|
|
246
|
+
{
|
|
247
|
+
"type": "command",
|
|
248
|
+
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/orchestrator-handoff.py"
|
|
143
249
|
}
|
|
144
250
|
]
|
|
145
251
|
}
|
|
@@ -159,6 +265,27 @@
|
|
|
159
265
|
{
|
|
160
266
|
"type": "command",
|
|
161
267
|
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/track-scope-coverage.py"
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
"type": "command",
|
|
271
|
+
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/context-capacity-warning.py"
|
|
272
|
+
},
|
|
273
|
+
{
|
|
274
|
+
"type": "command",
|
|
275
|
+
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/generate-adr-options.py"
|
|
276
|
+
}
|
|
277
|
+
]
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
"matcher": "AskUserQuestion",
|
|
281
|
+
"hooks": [
|
|
282
|
+
{
|
|
283
|
+
"type": "command",
|
|
284
|
+
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/ntfy-on-question.py"
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
"type": "command",
|
|
288
|
+
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/update-adr-decision.py"
|
|
162
289
|
}
|
|
163
290
|
]
|
|
164
291
|
},
|
|
@@ -168,6 +295,14 @@
|
|
|
168
295
|
{
|
|
169
296
|
"type": "command",
|
|
170
297
|
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/verify-after-green.py"
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
"type": "command",
|
|
301
|
+
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/completion-promise-detector.py"
|
|
302
|
+
},
|
|
303
|
+
{
|
|
304
|
+
"type": "command",
|
|
305
|
+
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/update-testing-checklist.py"
|
|
171
306
|
}
|
|
172
307
|
]
|
|
173
308
|
},
|
|
@@ -197,6 +332,19 @@
|
|
|
197
332
|
{
|
|
198
333
|
"type": "command",
|
|
199
334
|
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/enforce-a11y-audit.py"
|
|
335
|
+
},
|
|
336
|
+
{
|
|
337
|
+
"type": "command",
|
|
338
|
+
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/completion-promise-detector.py"
|
|
339
|
+
}
|
|
340
|
+
]
|
|
341
|
+
},
|
|
342
|
+
{
|
|
343
|
+
"matcher": "Skill",
|
|
344
|
+
"hooks": [
|
|
345
|
+
{
|
|
346
|
+
"type": "command",
|
|
347
|
+
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/orchestrator-completion.py"
|
|
200
348
|
}
|
|
201
349
|
]
|
|
202
350
|
}
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import Link from "next/link";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Test Results Page
|
|
7
|
+
*
|
|
8
|
+
* Shows Vitest unit test results or instructions to run tests.
|
|
9
|
+
* Designed to work with vitest --reporter=json output.
|
|
10
|
+
*
|
|
11
|
+
* Created with Hustle API Dev Tools (v3.12.12)
|
|
12
|
+
*/
|
|
13
|
+
export default function TestResultsPage() {
|
|
14
|
+
// In a real implementation, this would fetch test results from a JSON file
|
|
15
|
+
// For now, we show the empty state with instructions
|
|
16
|
+
const hasResults = false;
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<div className="min-h-screen bg-white dark:bg-gray-950">
|
|
20
|
+
{/* Header */}
|
|
21
|
+
<header className="border-b-4 border-black bg-[#BA0C2F] px-6 py-8 dark:border-gray-600">
|
|
22
|
+
<div className="mx-auto max-w-4xl">
|
|
23
|
+
<div className="flex items-center gap-2">
|
|
24
|
+
<Link
|
|
25
|
+
href="/hustle-dev-dashboard"
|
|
26
|
+
className="text-white/80 hover:text-white"
|
|
27
|
+
>
|
|
28
|
+
Dashboard
|
|
29
|
+
</Link>
|
|
30
|
+
<span className="text-white/60">/</span>
|
|
31
|
+
<span className="text-white">Test Results</span>
|
|
32
|
+
</div>
|
|
33
|
+
<h1 className="mt-2 text-3xl font-black text-white">TEST RESULTS</h1>
|
|
34
|
+
<p className="mt-2 text-white/80">Vitest unit test results</p>
|
|
35
|
+
</div>
|
|
36
|
+
</header>
|
|
37
|
+
|
|
38
|
+
{/* Main Content */}
|
|
39
|
+
<main className="mx-auto max-w-4xl px-6 py-8">
|
|
40
|
+
{hasResults ? <TestResults /> : <EmptyState />}
|
|
41
|
+
</main>
|
|
42
|
+
|
|
43
|
+
{/* Footer */}
|
|
44
|
+
<footer className="border-t-2 border-black px-6 py-4 dark:border-gray-600">
|
|
45
|
+
<div className="mx-auto max-w-4xl text-center text-sm text-gray-600 dark:text-gray-400">
|
|
46
|
+
Built with{" "}
|
|
47
|
+
<a
|
|
48
|
+
href="https://github.com/hustle-together/api-dev-tools"
|
|
49
|
+
className="font-bold text-[#BA0C2F] hover:underline"
|
|
50
|
+
>
|
|
51
|
+
Hustle API Dev Tools
|
|
52
|
+
</a>
|
|
53
|
+
</div>
|
|
54
|
+
</footer>
|
|
55
|
+
</div>
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function TestResults() {
|
|
60
|
+
// Placeholder for actual test results display
|
|
61
|
+
return (
|
|
62
|
+
<div className="space-y-6">
|
|
63
|
+
<div className="grid gap-4 sm:grid-cols-3">
|
|
64
|
+
<StatCard label="Passed" value={0} color="green" />
|
|
65
|
+
<StatCard label="Failed" value={0} color="red" />
|
|
66
|
+
<StatCard label="Skipped" value={0} color="yellow" />
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function EmptyState() {
|
|
73
|
+
return (
|
|
74
|
+
<div className="space-y-6">
|
|
75
|
+
{/* Status Card */}
|
|
76
|
+
<div className="border-2 border-black p-6 dark:border-gray-600">
|
|
77
|
+
<div className="flex items-center gap-3">
|
|
78
|
+
<div className="flex h-12 w-12 items-center justify-center rounded-full bg-gray-100 text-2xl dark:bg-gray-800">
|
|
79
|
+
0
|
|
80
|
+
</div>
|
|
81
|
+
<div>
|
|
82
|
+
<h2 className="text-xl font-bold text-black dark:text-white">
|
|
83
|
+
No Test Results
|
|
84
|
+
</h2>
|
|
85
|
+
<p className="text-gray-600 dark:text-gray-400">
|
|
86
|
+
Run your tests to see results here
|
|
87
|
+
</p>
|
|
88
|
+
</div>
|
|
89
|
+
</div>
|
|
90
|
+
</div>
|
|
91
|
+
|
|
92
|
+
{/* Instructions */}
|
|
93
|
+
<div className="border-2 border-black bg-gray-50 p-6 dark:border-gray-600 dark:bg-gray-900">
|
|
94
|
+
<h3 className="mb-4 font-bold text-black dark:text-white">Run Tests</h3>
|
|
95
|
+
<div className="space-y-4">
|
|
96
|
+
<Step
|
|
97
|
+
number={1}
|
|
98
|
+
title="Run Unit Tests"
|
|
99
|
+
command="pnpm test"
|
|
100
|
+
description="Runs Vitest in watch mode for development"
|
|
101
|
+
/>
|
|
102
|
+
<Step
|
|
103
|
+
number={2}
|
|
104
|
+
title="Run Tests Once"
|
|
105
|
+
command="pnpm test:run"
|
|
106
|
+
description="Runs all tests once and exits"
|
|
107
|
+
/>
|
|
108
|
+
<Step
|
|
109
|
+
number={3}
|
|
110
|
+
title="Run with Coverage"
|
|
111
|
+
command="pnpm test:coverage"
|
|
112
|
+
description="Generates code coverage report"
|
|
113
|
+
/>
|
|
114
|
+
</div>
|
|
115
|
+
</div>
|
|
116
|
+
|
|
117
|
+
{/* Test Commands Reference */}
|
|
118
|
+
<div className="border-2 border-black p-6 dark:border-gray-600">
|
|
119
|
+
<h3 className="mb-4 font-bold text-black dark:text-white">
|
|
120
|
+
Available Commands
|
|
121
|
+
</h3>
|
|
122
|
+
<div className="space-y-3">
|
|
123
|
+
<CommandItem
|
|
124
|
+
command="pnpm test"
|
|
125
|
+
description="Watch mode - reruns on file changes"
|
|
126
|
+
/>
|
|
127
|
+
<CommandItem
|
|
128
|
+
command="pnpm test:run"
|
|
129
|
+
description="Single run - CI/CD friendly"
|
|
130
|
+
/>
|
|
131
|
+
<CommandItem
|
|
132
|
+
command="pnpm test:coverage"
|
|
133
|
+
description="With coverage report"
|
|
134
|
+
/>
|
|
135
|
+
<CommandItem
|
|
136
|
+
command="pnpm test [file]"
|
|
137
|
+
description="Run specific test file"
|
|
138
|
+
/>
|
|
139
|
+
</div>
|
|
140
|
+
</div>
|
|
141
|
+
|
|
142
|
+
{/* Test File Conventions */}
|
|
143
|
+
<div className="border-2 border-black bg-gray-50 p-6 dark:border-gray-600 dark:bg-gray-900">
|
|
144
|
+
<h3 className="mb-4 font-bold text-black dark:text-white">
|
|
145
|
+
Test File Conventions
|
|
146
|
+
</h3>
|
|
147
|
+
<ul className="space-y-2 text-sm text-gray-600 dark:text-gray-400">
|
|
148
|
+
<li className="flex items-center gap-2">
|
|
149
|
+
<code className="rounded bg-white px-2 py-0.5 text-[#BA0C2F] dark:bg-gray-800">
|
|
150
|
+
*.test.ts
|
|
151
|
+
</code>
|
|
152
|
+
Unit tests
|
|
153
|
+
</li>
|
|
154
|
+
<li className="flex items-center gap-2">
|
|
155
|
+
<code className="rounded bg-white px-2 py-0.5 text-[#BA0C2F] dark:bg-gray-800">
|
|
156
|
+
*.api.test.ts
|
|
157
|
+
</code>
|
|
158
|
+
API route tests
|
|
159
|
+
</li>
|
|
160
|
+
<li className="flex items-center gap-2">
|
|
161
|
+
<code className="rounded bg-white px-2 py-0.5 text-[#BA0C2F] dark:bg-gray-800">
|
|
162
|
+
__tests__/
|
|
163
|
+
</code>
|
|
164
|
+
Test directory convention
|
|
165
|
+
</li>
|
|
166
|
+
</ul>
|
|
167
|
+
</div>
|
|
168
|
+
</div>
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function StatCard({
|
|
173
|
+
label,
|
|
174
|
+
value,
|
|
175
|
+
color,
|
|
176
|
+
}: {
|
|
177
|
+
label: string;
|
|
178
|
+
value: number;
|
|
179
|
+
color: "green" | "red" | "yellow";
|
|
180
|
+
}) {
|
|
181
|
+
const colorClasses = {
|
|
182
|
+
green: "text-green-600",
|
|
183
|
+
red: "text-red-600",
|
|
184
|
+
yellow: "text-yellow-600",
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
return (
|
|
188
|
+
<div className="border-2 border-black bg-white p-4 dark:border-gray-600 dark:bg-gray-900">
|
|
189
|
+
<p className={`text-3xl font-black ${colorClasses[color]}`}>{value}</p>
|
|
190
|
+
<p className="text-sm text-gray-600 dark:text-gray-400">{label}</p>
|
|
191
|
+
</div>
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function Step({
|
|
196
|
+
number,
|
|
197
|
+
title,
|
|
198
|
+
command,
|
|
199
|
+
description,
|
|
200
|
+
}: {
|
|
201
|
+
number: number;
|
|
202
|
+
title: string;
|
|
203
|
+
command: string;
|
|
204
|
+
description: string;
|
|
205
|
+
}) {
|
|
206
|
+
return (
|
|
207
|
+
<div className="flex gap-4">
|
|
208
|
+
<div className="flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full bg-[#BA0C2F] text-sm font-bold text-white">
|
|
209
|
+
{number}
|
|
210
|
+
</div>
|
|
211
|
+
<div>
|
|
212
|
+
<p className="font-medium text-black dark:text-white">{title}</p>
|
|
213
|
+
<code className="mt-1 block rounded bg-white px-3 py-1 font-mono text-sm text-[#BA0C2F] dark:bg-gray-800">
|
|
214
|
+
{command}
|
|
215
|
+
</code>
|
|
216
|
+
<p className="mt-1 text-sm text-gray-600 dark:text-gray-400">
|
|
217
|
+
{description}
|
|
218
|
+
</p>
|
|
219
|
+
</div>
|
|
220
|
+
</div>
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function CommandItem({
|
|
225
|
+
command,
|
|
226
|
+
description,
|
|
227
|
+
}: {
|
|
228
|
+
command: string;
|
|
229
|
+
description: string;
|
|
230
|
+
}) {
|
|
231
|
+
return (
|
|
232
|
+
<div className="flex items-center justify-between rounded bg-white px-4 py-2 dark:bg-gray-800">
|
|
233
|
+
<code className="font-mono text-[#BA0C2F]">{command}</code>
|
|
234
|
+
<span className="text-sm text-gray-500">{description}</span>
|
|
235
|
+
</div>
|
|
236
|
+
);
|
|
237
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://typedoc.org/schema.json",
|
|
3
|
+
"entryPoints": ["src/lib/schemas/*.ts", "src/app/api/**/*.ts"],
|
|
4
|
+
"out": "docs/api",
|
|
5
|
+
"plugin": ["typedoc-plugin-markdown"],
|
|
6
|
+
"exclude": ["**/*.test.ts", "**/__tests__/**", "**/node_modules/**"],
|
|
7
|
+
"excludePrivate": true,
|
|
8
|
+
"excludeInternal": true,
|
|
9
|
+
"readme": "none",
|
|
10
|
+
"name": "API Documentation",
|
|
11
|
+
"includeVersion": true,
|
|
12
|
+
"categorizeByGroup": true,
|
|
13
|
+
"sort": ["alphabetical"],
|
|
14
|
+
"validation": {
|
|
15
|
+
"notExported": false,
|
|
16
|
+
"invalidLink": false,
|
|
17
|
+
"notDocumented": false
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import { useState, useMemo } from "react";
|
|
4
|
-
import { HeroHeader } from "
|
|
4
|
+
import { HeroHeader } from "../../shared/HeroHeader";
|
|
5
5
|
import { PreviewCard } from "./PreviewCard";
|
|
6
6
|
import { PreviewModal } from "./PreviewModal";
|
|
7
|
+
import { VisualTestingDashboard } from "./VisualTestingDashboard";
|
|
7
8
|
|
|
8
9
|
// Import registry - this will be updated by the CLI when components are created
|
|
9
10
|
// Note: In production, this could be fetched from an API route
|
|
10
11
|
import registry from "@/../.claude/registry.json";
|
|
11
12
|
|
|
13
|
+
type ViewType = "gallery" | "visual-testing";
|
|
12
14
|
type FilterType = "all" | "components" | "pages";
|
|
13
15
|
|
|
14
16
|
interface RegistryItem {
|
|
@@ -48,6 +50,7 @@ interface Registry {
|
|
|
48
50
|
* Created with Hustle API Dev Tools (v3.9.2)
|
|
49
51
|
*/
|
|
50
52
|
export function UIShowcase() {
|
|
53
|
+
const [view, setView] = useState<ViewType>("gallery");
|
|
51
54
|
const [filter, setFilter] = useState<FilterType>("all");
|
|
52
55
|
const [searchQuery, setSearchQuery] = useState("");
|
|
53
56
|
const [selectedItem, setSelectedItem] = useState<{
|
|
@@ -106,8 +109,52 @@ export function UIShowcase() {
|
|
|
106
109
|
const componentCount = Object.keys(typedRegistry.components || {}).length;
|
|
107
110
|
const pageCount = Object.keys(typedRegistry.pages || {}).length;
|
|
108
111
|
|
|
112
|
+
// If viewing visual testing dashboard, render that instead
|
|
113
|
+
if (view === "visual-testing") {
|
|
114
|
+
return (
|
|
115
|
+
<div className="min-h-screen bg-white dark:bg-[#050505]">
|
|
116
|
+
{/* View Switcher */}
|
|
117
|
+
<div className="border-b-2 border-black bg-gray-100 dark:border-gray-600 dark:bg-gray-900">
|
|
118
|
+
<div className="container mx-auto flex gap-0 px-4">
|
|
119
|
+
<button
|
|
120
|
+
onClick={() => setView("gallery")}
|
|
121
|
+
className="border-b-4 border-transparent px-6 py-3 font-bold text-gray-600 hover:text-black dark:text-gray-400 dark:hover:text-white"
|
|
122
|
+
>
|
|
123
|
+
Gallery View
|
|
124
|
+
</button>
|
|
125
|
+
<button
|
|
126
|
+
onClick={() => setView("visual-testing")}
|
|
127
|
+
className="border-b-4 border-[#BA0C2F] px-6 py-3 font-bold text-[#BA0C2F]"
|
|
128
|
+
>
|
|
129
|
+
Visual Testing
|
|
130
|
+
</button>
|
|
131
|
+
</div>
|
|
132
|
+
</div>
|
|
133
|
+
<VisualTestingDashboard />
|
|
134
|
+
</div>
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
109
138
|
return (
|
|
110
139
|
<div className="min-h-screen bg-white dark:bg-[#050505]">
|
|
140
|
+
{/* View Switcher */}
|
|
141
|
+
<div className="border-b-2 border-black bg-gray-100 dark:border-gray-600 dark:bg-gray-900">
|
|
142
|
+
<div className="container mx-auto flex gap-0 px-4">
|
|
143
|
+
<button
|
|
144
|
+
onClick={() => setView("gallery")}
|
|
145
|
+
className="border-b-4 border-[#BA0C2F] px-6 py-3 font-bold text-[#BA0C2F]"
|
|
146
|
+
>
|
|
147
|
+
Gallery View
|
|
148
|
+
</button>
|
|
149
|
+
<button
|
|
150
|
+
onClick={() => setView("visual-testing")}
|
|
151
|
+
className="border-b-4 border-transparent px-6 py-3 font-bold text-gray-600 hover:text-black dark:text-gray-400 dark:hover:text-white"
|
|
152
|
+
>
|
|
153
|
+
Visual Testing
|
|
154
|
+
</button>
|
|
155
|
+
</div>
|
|
156
|
+
</div>
|
|
157
|
+
|
|
111
158
|
{/* Hero Header */}
|
|
112
159
|
<HeroHeader
|
|
113
160
|
title="UI Showcase"
|