@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
|
@@ -3,10 +3,29 @@
|
|
|
3
3
|
import { useEffect, useCallback, useState } from "react";
|
|
4
4
|
import { APITester } from "./APITester";
|
|
5
5
|
|
|
6
|
+
interface EndpointParam {
|
|
7
|
+
name: string;
|
|
8
|
+
type: string;
|
|
9
|
+
description?: string;
|
|
10
|
+
required?: boolean;
|
|
11
|
+
default?: string | number | boolean;
|
|
12
|
+
enum?: string[];
|
|
13
|
+
example?: string;
|
|
14
|
+
min?: number;
|
|
15
|
+
max?: number;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
interface EndpointExample {
|
|
19
|
+
description: string;
|
|
20
|
+
query: string;
|
|
21
|
+
curl: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
6
24
|
interface RegistryAPI {
|
|
7
25
|
name: string;
|
|
8
26
|
description?: string;
|
|
9
27
|
route: string;
|
|
28
|
+
routeFile?: string;
|
|
10
29
|
schemas?: string;
|
|
11
30
|
tests?: string;
|
|
12
31
|
methods?: string[];
|
|
@@ -17,8 +36,11 @@ interface RegistryAPI {
|
|
|
17
36
|
endpoints?: Record<
|
|
18
37
|
string,
|
|
19
38
|
{
|
|
20
|
-
methods
|
|
39
|
+
methods?: string[];
|
|
40
|
+
method?: string;
|
|
21
41
|
description?: string;
|
|
42
|
+
params?: EndpointParam[];
|
|
43
|
+
examples?: Record<string, EndpointExample>;
|
|
22
44
|
}
|
|
23
45
|
>;
|
|
24
46
|
}
|
|
@@ -41,13 +63,15 @@ interface APIModalProps {
|
|
|
41
63
|
* - Request/response display
|
|
42
64
|
* - Curl example generation
|
|
43
65
|
*
|
|
44
|
-
* Created with Hustle API Dev Tools (v3.
|
|
66
|
+
* Created with Hustle API Dev Tools (v3.12.10)
|
|
45
67
|
*/
|
|
46
68
|
export function APIModal({ id, type, data, onClose }: APIModalProps) {
|
|
47
69
|
const [activeTab, setActiveTab] = useState<"try-it" | "docs" | "curl">(
|
|
48
70
|
"try-it",
|
|
49
71
|
);
|
|
50
72
|
const [selectedEndpoint, setSelectedEndpoint] = useState<string | null>(null);
|
|
73
|
+
const [submitRequest, setSubmitRequest] = useState<(() => Promise<void>) | null>(null);
|
|
74
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
51
75
|
|
|
52
76
|
// Close on Escape key
|
|
53
77
|
const handleKeyDown = useCallback(
|
|
@@ -86,14 +110,26 @@ export function APIModal({ id, type, data, onClose }: APIModalProps) {
|
|
|
86
110
|
const currentEndpoint = selectedEndpoint
|
|
87
111
|
? endpoints[selectedEndpoint]
|
|
88
112
|
: endpoints[endpointKeys[0]];
|
|
89
|
-
|
|
113
|
+
// Handle both methods array and single method string
|
|
114
|
+
const methods = currentEndpoint?.methods ||
|
|
115
|
+
(currentEndpoint?.method ? [currentEndpoint.method] : null) ||
|
|
116
|
+
data.methods ||
|
|
117
|
+
["POST"];
|
|
90
118
|
const baseUrl =
|
|
91
119
|
typeof window !== "undefined"
|
|
92
120
|
? window.location.origin
|
|
93
121
|
: "http://localhost:3000";
|
|
94
122
|
|
|
95
|
-
// Build endpoint path
|
|
123
|
+
// Build endpoint path - always use base path for action-based APIs
|
|
124
|
+
// Actions are passed as query parameters, not sub-paths
|
|
96
125
|
const getEndpointPath = () => {
|
|
126
|
+
// Check if this API uses action-based routing (has params with action)
|
|
127
|
+
const hasActionParam = currentEndpoint?.params?.some(p => p.name === "action");
|
|
128
|
+
if (hasActionParam) {
|
|
129
|
+
// Action-based APIs use query params, not path segments
|
|
130
|
+
return `/api/v2/${id}`;
|
|
131
|
+
}
|
|
132
|
+
// For true sub-endpoint APIs, include the path
|
|
97
133
|
if (selectedEndpoint && selectedEndpoint !== "default") {
|
|
98
134
|
return `/api/v2/${id}/${selectedEndpoint}`;
|
|
99
135
|
}
|
|
@@ -102,10 +138,26 @@ export function APIModal({ id, type, data, onClose }: APIModalProps) {
|
|
|
102
138
|
|
|
103
139
|
const endpoint = getEndpointPath();
|
|
104
140
|
|
|
105
|
-
// Generate curl example
|
|
141
|
+
// Generate curl example with proper query params
|
|
106
142
|
const generateCurl = (method: string) => {
|
|
143
|
+
// Build example query string from params
|
|
144
|
+
const params = currentEndpoint?.params || [];
|
|
145
|
+
const queryParts: string[] = [];
|
|
146
|
+
|
|
147
|
+
for (const param of params) {
|
|
148
|
+
if (param.name === "action" && selectedEndpoint) {
|
|
149
|
+
queryParts.push(`action=${selectedEndpoint}`);
|
|
150
|
+
} else if (param.required && param.example) {
|
|
151
|
+
queryParts.push(`${param.name}=${encodeURIComponent(param.example)}`);
|
|
152
|
+
} else if (param.example) {
|
|
153
|
+
queryParts.push(`${param.name}=${encodeURIComponent(param.example)}`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const queryString = queryParts.length > 0 ? `?${queryParts.join("&")}` : "";
|
|
158
|
+
|
|
107
159
|
if (method === "GET") {
|
|
108
|
-
return `curl -X GET "${baseUrl}${endpoint}"`;
|
|
160
|
+
return `curl -X GET "${baseUrl}${endpoint}${queryString}"`;
|
|
109
161
|
}
|
|
110
162
|
return `curl -X ${method} "${baseUrl}${endpoint}" \\
|
|
111
163
|
-H "Content-Type: application/json" \\
|
|
@@ -129,7 +181,7 @@ export function APIModal({ id, type, data, onClose }: APIModalProps) {
|
|
|
129
181
|
/>
|
|
130
182
|
|
|
131
183
|
{/* Modal Content */}
|
|
132
|
-
<div className="relative z-10 flex max-h-[90vh] w-full max-w-
|
|
184
|
+
<div className="relative z-10 flex max-h-[90vh] w-full max-w-7xl flex-col overflow-hidden border-2 border-black bg-white shadow-xl dark:border-gray-600 dark:bg-gray-900">
|
|
133
185
|
{/* Header */}
|
|
134
186
|
<header className="flex items-center justify-between border-b-2 border-black px-6 py-4 dark:border-gray-600">
|
|
135
187
|
<div className="flex items-center gap-4">
|
|
@@ -271,6 +323,11 @@ export function APIModal({ id, type, data, onClose }: APIModalProps) {
|
|
|
271
323
|
methods={methods}
|
|
272
324
|
selectedEndpoint={selectedEndpoint}
|
|
273
325
|
schemaPath={data.schemas}
|
|
326
|
+
endpointParams={data.endpoints?.[selectedEndpoint || "default"]?.params || data.endpoints?.[Object.keys(data.endpoints || {})[0]]?.params}
|
|
327
|
+
apiRoute={data.routeFile || data.route}
|
|
328
|
+
examples={data.endpoints?.[selectedEndpoint || "default"]?.examples || data.endpoints?.[Object.keys(data.endpoints || {})[0]]?.examples}
|
|
329
|
+
onSubmitRef={(fn) => setSubmitRequest(() => fn)}
|
|
330
|
+
onLoadingChange={setIsLoading}
|
|
274
331
|
/>
|
|
275
332
|
)}
|
|
276
333
|
|
|
@@ -408,10 +465,45 @@ export function APIModal({ id, type, data, onClose }: APIModalProps) {
|
|
|
408
465
|
);
|
|
409
466
|
}
|
|
410
467
|
}}
|
|
411
|
-
className="border-2 border-black
|
|
468
|
+
className="border-2 border-black px-3 py-1.5 text-sm font-medium hover:bg-gray-100 dark:border-gray-600 dark:hover:bg-gray-800"
|
|
412
469
|
>
|
|
413
470
|
Copy Schema Import
|
|
414
471
|
</button>
|
|
472
|
+
{activeTab === "try-it" && submitRequest && (
|
|
473
|
+
<button
|
|
474
|
+
onClick={() => submitRequest()}
|
|
475
|
+
disabled={isLoading}
|
|
476
|
+
className="border-2 border-black bg-[#BA0C2F] px-4 py-1.5 text-sm font-bold text-white transition-colors hover:bg-[#8a0923] disabled:opacity-50"
|
|
477
|
+
>
|
|
478
|
+
{isLoading ? (
|
|
479
|
+
<span className="flex items-center gap-2">
|
|
480
|
+
<svg
|
|
481
|
+
className="h-4 w-4 animate-spin"
|
|
482
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
483
|
+
fill="none"
|
|
484
|
+
viewBox="0 0 24 24"
|
|
485
|
+
>
|
|
486
|
+
<circle
|
|
487
|
+
className="opacity-25"
|
|
488
|
+
cx="12"
|
|
489
|
+
cy="12"
|
|
490
|
+
r="10"
|
|
491
|
+
stroke="currentColor"
|
|
492
|
+
strokeWidth="4"
|
|
493
|
+
/>
|
|
494
|
+
<path
|
|
495
|
+
className="opacity-75"
|
|
496
|
+
fill="currentColor"
|
|
497
|
+
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"
|
|
498
|
+
/>
|
|
499
|
+
</svg>
|
|
500
|
+
Sending...
|
|
501
|
+
</span>
|
|
502
|
+
) : (
|
|
503
|
+
"Send Request"
|
|
504
|
+
)}
|
|
505
|
+
</button>
|
|
506
|
+
)}
|
|
415
507
|
</div>
|
|
416
508
|
</div>
|
|
417
509
|
</footer>
|
|
@@ -4,6 +4,33 @@ import { useState, useMemo } from "react";
|
|
|
4
4
|
import { APICard } from "./APICard";
|
|
5
5
|
import { APIModal } from "./APIModal";
|
|
6
6
|
|
|
7
|
+
// Import registry - this will be updated by the CLI when APIs are created
|
|
8
|
+
import registryData from "@/../.claude/registry.json";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Parameter documentation from registry.json
|
|
12
|
+
*/
|
|
13
|
+
interface EndpointParam {
|
|
14
|
+
name: string;
|
|
15
|
+
type: string;
|
|
16
|
+
description?: string;
|
|
17
|
+
required?: boolean;
|
|
18
|
+
default?: string | number | boolean;
|
|
19
|
+
enum?: string[];
|
|
20
|
+
example?: string;
|
|
21
|
+
min?: number;
|
|
22
|
+
max?: number;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Example request from registry.json
|
|
27
|
+
*/
|
|
28
|
+
interface EndpointExample {
|
|
29
|
+
description: string;
|
|
30
|
+
query: string;
|
|
31
|
+
curl: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
7
34
|
/**
|
|
8
35
|
* Registry structure from .claude/registry.json
|
|
9
36
|
*/
|
|
@@ -11,16 +38,21 @@ interface RegistryAPI {
|
|
|
11
38
|
name: string;
|
|
12
39
|
description?: string;
|
|
13
40
|
route: string;
|
|
41
|
+
routeFile?: string;
|
|
14
42
|
schemas?: string;
|
|
15
43
|
tests?: string;
|
|
16
44
|
methods?: string[];
|
|
17
45
|
created_at?: string;
|
|
18
46
|
status?: string;
|
|
47
|
+
actions?: string[];
|
|
19
48
|
endpoints?: Record<
|
|
20
49
|
string,
|
|
21
50
|
{
|
|
22
|
-
methods
|
|
51
|
+
methods?: string[];
|
|
52
|
+
method?: string;
|
|
23
53
|
description?: string;
|
|
54
|
+
params?: EndpointParam[];
|
|
55
|
+
examples?: Record<string, EndpointExample>;
|
|
24
56
|
}
|
|
25
57
|
>;
|
|
26
58
|
}
|
|
@@ -46,7 +78,7 @@ interface APIShowcaseProps {
|
|
|
46
78
|
*
|
|
47
79
|
* Data source: .claude/registry.json (apis + combined sections)
|
|
48
80
|
*
|
|
49
|
-
* Created with Hustle API Dev Tools (v3.
|
|
81
|
+
* Created with Hustle API Dev Tools (v3.12.10)
|
|
50
82
|
*/
|
|
51
83
|
export function APIShowcase({ registry: propRegistry }: APIShowcaseProps) {
|
|
52
84
|
const [selectedAPI, setSelectedAPI] = useState<{
|
|
@@ -57,8 +89,8 @@ export function APIShowcase({ registry: propRegistry }: APIShowcaseProps) {
|
|
|
57
89
|
const [filter, setFilter] = useState<"all" | "api" | "combined">("all");
|
|
58
90
|
const [search, setSearch] = useState("");
|
|
59
91
|
|
|
60
|
-
// Use prop registry or default empty structure
|
|
61
|
-
const registry: Registry = propRegistry || {
|
|
92
|
+
// Use prop registry, imported registry, or default empty structure
|
|
93
|
+
const registry: Registry = propRegistry || registryData || {
|
|
62
94
|
version: "1.0.0",
|
|
63
95
|
apis: {},
|
|
64
96
|
combined: {},
|