@nextsparkjs/core 0.1.0-beta.176 → 0.1.0-beta.178
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/dist/components/devtools/MarkdownViewer.d.ts.map +1 -1
- package/dist/components/devtools/MarkdownViewer.js +5 -0
- package/dist/components/devtools/api-explorer/ApiDocsModal.d.ts.map +1 -1
- package/dist/components/devtools/api-explorer/ApiDocsModal.js +0 -0
- package/dist/components/devtools/api-explorer/ApiEndpointsSidebar.d.ts.map +1 -1
- package/dist/components/devtools/api-explorer/ApiEndpointsSidebar.js +16 -5
- package/dist/components/devtools/api-explorer/ApiExplorer.d.ts.map +1 -1
- package/dist/components/devtools/api-explorer/ApiExplorer.js +63 -21
- package/dist/components/devtools/api-explorer/ApiRequestPanel.d.ts +3 -1
- package/dist/components/devtools/api-explorer/ApiRequestPanel.d.ts.map +1 -1
- package/dist/components/devtools/api-explorer/ApiRequestPanel.js +5 -1
- package/dist/components/devtools/api-explorer/explorer-storage.d.ts +12 -0
- package/dist/components/devtools/api-explorer/explorer-storage.d.ts.map +1 -0
- package/dist/components/devtools/api-explorer/explorer-storage.js +25 -0
- package/dist/components/devtools/api-tester/AuthSelector.d.ts +4 -1
- package/dist/components/devtools/api-tester/AuthSelector.d.ts.map +1 -1
- package/dist/components/devtools/api-tester/AuthSelector.js +24 -2
- package/dist/components/docs/docs-content.d.ts.map +1 -1
- package/dist/components/docs/docs-content.js +17 -0
- package/dist/components/docs/mermaid-diagram.d.ts +11 -0
- package/dist/components/docs/mermaid-diagram.d.ts.map +1 -0
- package/dist/components/docs/mermaid-diagram.js +20 -0
- package/dist/components/permissions/PermissionsMatrix.d.ts.map +1 -1
- package/dist/components/permissions/PermissionsMatrix.js +5 -4
- package/dist/components/teams/InviteMemberDialog.js +1 -1
- package/dist/components/teams/TeamMembersList.js +1 -1
- package/dist/hooks/useApiExplorerNavigation.d.ts.map +1 -1
- package/dist/hooks/useApiExplorerNavigation.js +5 -1
- package/dist/lib/actions/team.actions.d.ts.map +1 -1
- package/dist/lib/actions/team.actions.js +7 -5
- package/dist/lib/api/auth/dual-auth.d.ts +14 -0
- package/dist/lib/api/auth/dual-auth.d.ts.map +1 -1
- package/dist/lib/api/auth/dual-auth.js +43 -2
- package/dist/lib/auth.d.ts.map +1 -1
- package/dist/lib/auth.js +3 -3
- package/dist/lib/config/app.config.js +60 -60
- package/dist/lib/config/config-sync.d.ts.map +1 -1
- package/dist/lib/config/config-sync.js +14 -9
- package/dist/lib/config/roles-merge.d.ts +0 -77
- package/dist/lib/config/roles-merge.d.ts.map +1 -1
- package/dist/lib/config/roles-merge.js +1 -98
- package/dist/lib/config/types.d.ts +6 -2
- package/dist/lib/config/types.d.ts.map +1 -1
- package/dist/lib/docs/mermaid.d.ts +15 -0
- package/dist/lib/docs/mermaid.d.ts.map +1 -0
- package/dist/lib/docs/mermaid.js +42 -0
- package/dist/lib/docs/parser.d.ts.map +1 -1
- package/dist/lib/docs/parser.js +2 -1
- package/dist/lib/docs/remark-mermaid.d.ts +15 -0
- package/dist/lib/docs/remark-mermaid.d.ts.map +1 -0
- package/dist/lib/docs/remark-mermaid.js +26 -0
- package/dist/lib/services/membership.service.js +2 -2
- package/dist/lib/services/team-member.service.d.ts +2 -2
- package/dist/lib/services/team-member.service.d.ts.map +1 -1
- package/dist/lib/services/team-member.service.js +4 -3
- package/dist/lib/teams/types.d.ts +2 -1
- package/dist/lib/teams/types.d.ts.map +1 -1
- package/dist/lib/teams/types.js +4 -4
- package/dist/styles/classes.json +3 -2
- package/dist/styles/ui.css +1 -1
- package/dist/templates/app/(auth)/login/page.tsx +2 -0
- package/dist/templates/app/(auth)/signup/page.tsx +4 -0
- package/dist/templates/app/superadmin/team-roles/page.tsx +2 -2
- package/package.json +3 -2
- package/scripts/build/registry/__tests__/team-roles.test.mjs +192 -0
- package/scripts/build/registry/discovery/permissions.mjs +163 -1
- package/scripts/build/registry/generators/permissions-registry.mjs +95 -35
- package/styles/docs.css +15 -0
- package/templates/app/(auth)/login/page.tsx +2 -0
- package/templates/app/(auth)/signup/page.tsx +4 -0
- package/templates/app/superadmin/team-roles/page.tsx +2 -2
- package/tests/jest/__mocks__/@nextsparkjs/registries/permissions-registry.ts +1 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MarkdownViewer.d.ts","sourceRoot":"","sources":["../../../src/components/devtools/MarkdownViewer.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"MarkdownViewer.d.ts","sourceRoot":"","sources":["../../../src/components/devtools/MarkdownViewer.tsx"],"names":[],"mappings":"AASA,UAAU,mBAAmB;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAsED;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,mBAAmB,2CAgDzE"}
|
|
@@ -5,6 +5,7 @@ import remarkGfm from "remark-gfm";
|
|
|
5
5
|
import { useEffect, useState, memo } from "react";
|
|
6
6
|
import { codeToHtml } from "shiki";
|
|
7
7
|
import { cn } from "../../lib/utils/index.js";
|
|
8
|
+
import { MermaidDiagram } from "../docs/mermaid-diagram.js";
|
|
8
9
|
const ShikiCodeBlock = memo(function ShikiCodeBlock2({
|
|
9
10
|
code,
|
|
10
11
|
language
|
|
@@ -72,6 +73,10 @@ function MarkdownViewer({ content, className }) {
|
|
|
72
73
|
const match = /language-(\w+)/.exec(className2 || "");
|
|
73
74
|
const language = match ? match[1] : "";
|
|
74
75
|
const isInline = !match;
|
|
76
|
+
if (!isInline && language === "mermaid") {
|
|
77
|
+
const chart = String(children).replace(/\n$/, "");
|
|
78
|
+
return /* @__PURE__ */ jsx(MermaidDiagram, { chart });
|
|
79
|
+
}
|
|
75
80
|
if (!isInline && language) {
|
|
76
81
|
const code = String(children).replace(/\n$/, "");
|
|
77
82
|
return /* @__PURE__ */ jsx(ShikiCodeBlock, { code, language });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ApiDocsModal.d.ts","sourceRoot":"","sources":["../../../../src/components/devtools/api-explorer/ApiDocsModal.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ApiDocsModal.d.ts","sourceRoot":"","sources":["../../../../src/components/devtools/api-explorer/ApiDocsModal.tsx"],"names":[],"mappings":"AAgBA,UAAU,iBAAiB;IACzB,8CAA8C;IAC9C,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,wCAAwC;IACxC,KAAK,EAAE,MAAM,CAAA;CACd;AAED,wBAAgB,YAAY,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,iBAAiB,2CAwEjE"}
|
|
Binary file
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ApiEndpointsSidebar.d.ts","sourceRoot":"","sources":["../../../../src/components/devtools/api-explorer/ApiEndpointsSidebar.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ApiEndpointsSidebar.d.ts","sourceRoot":"","sources":["../../../../src/components/devtools/api-explorer/ApiEndpointsSidebar.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,0CAA0C,CAAA;AAC5F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AA4CrD,UAAU,gBAAgB;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,UAAU,CAAA;CACnB;AAED,UAAU,wBAAwB;IAChC,MAAM,EAAE,MAAM,CAAC,aAAa,EAAE,aAAa,EAAE,CAAC,CAAA;IAC9C,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAAA;IACzC,gBAAgB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,aAAa,KAAK,IAAI,CAAA;IAClF,WAAW,EAAE,OAAO,CAAA;IACpB,gBAAgB,EAAE,MAAM,IAAI,CAAA;CAC7B;AAED,wBAAgB,mBAAmB,CAAC,EAClC,MAAM,EACN,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,EACX,gBAAgB,GACjB,EAAE,wBAAwB,2CAkQ1B"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { useState, useMemo } from "react";
|
|
3
|
+
import { useState, useMemo, useEffect } from "react";
|
|
4
4
|
import { Search, ChevronRight, ChevronDown, Code, Database, Layers, Puzzle, PanelLeftClose, PanelLeft, Folder, FolderOpen } from "lucide-react";
|
|
5
|
+
import { loadState, saveState } from "./explorer-storage.js";
|
|
5
6
|
import { Input } from "../../ui/input.js";
|
|
6
7
|
import { Badge } from "../../ui/badge.js";
|
|
7
8
|
import { Button } from "../../ui/button.js";
|
|
@@ -43,10 +44,20 @@ function ApiEndpointsSidebar({
|
|
|
43
44
|
onToggleCollapse
|
|
44
45
|
}) {
|
|
45
46
|
const [searchQuery, setSearchQuery] = useState("");
|
|
46
|
-
const [expandedCategories, setExpandedCategories] = useState(
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
const [expandedCategories, setExpandedCategories] = useState(() => {
|
|
48
|
+
const saved = loadState("sidebar:expandedCategories");
|
|
49
|
+
return new Set(saved ?? ["core", "entity", "theme", "plugin"]);
|
|
50
|
+
});
|
|
51
|
+
const [expandedPrefixes, setExpandedPrefixes] = useState(() => {
|
|
52
|
+
const saved = loadState("sidebar:expandedPrefixes");
|
|
53
|
+
return new Set(saved ?? []);
|
|
54
|
+
});
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
saveState("sidebar:expandedCategories", Array.from(expandedCategories));
|
|
57
|
+
}, [expandedCategories]);
|
|
58
|
+
useEffect(() => {
|
|
59
|
+
saveState("sidebar:expandedPrefixes", Array.from(expandedPrefixes));
|
|
60
|
+
}, [expandedPrefixes]);
|
|
50
61
|
const filteredRoutes = useMemo(() => {
|
|
51
62
|
if (!searchQuery.trim()) return routes;
|
|
52
63
|
const query = searchQuery.toLowerCase();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ApiExplorer.d.ts","sourceRoot":"","sources":["../../../../src/components/devtools/api-explorer/ApiExplorer.tsx"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,0CAA0C,CAAA;
|
|
1
|
+
{"version":3,"file":"ApiExplorer.d.ts","sourceRoot":"","sources":["../../../../src/components/devtools/api-explorer/ApiExplorer.tsx"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,0CAA0C,CAAA;AAqB5F,UAAU,gBAAgB;IACxB,MAAM,EAAE,MAAM,CAAC,aAAa,EAAE,aAAa,EAAE,CAAC,CAAA;IAC9C,eAAe,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;CAC1D;AAwBD,wBAAgB,WAAW,CAAC,EAAE,MAAM,EAAE,eAAe,EAAE,EAAE,gBAAgB,2CAibxE"}
|
|
@@ -13,6 +13,7 @@ import { useApiExplorerNavigation } from "../../../hooks/useApiExplorerNavigatio
|
|
|
13
13
|
import { extractPathParams, buildUrl } from "../api-tester/utils/url-builder.js";
|
|
14
14
|
import { ApiPresetsService } from "../../../lib/services/api-presets.service.js";
|
|
15
15
|
import { ApiDocsService } from "../../../lib/services/api-docs.service.js";
|
|
16
|
+
import { loadState, saveState, draftKey } from "./explorer-storage.js";
|
|
16
17
|
function findRouteByPath(routes, path) {
|
|
17
18
|
for (const category of Object.keys(routes)) {
|
|
18
19
|
const found = routes[category].find((r) => r.path === path);
|
|
@@ -29,23 +30,26 @@ function createEmptyRows(count = 2) {
|
|
|
29
30
|
}));
|
|
30
31
|
}
|
|
31
32
|
function ApiExplorer({ routes, initialEndpoint }) {
|
|
32
|
-
const [isCollapsed, setIsCollapsed] = useState(false);
|
|
33
|
+
const [isCollapsed, setIsCollapsed] = useState(() => loadState("sidebarCollapsed") ?? false);
|
|
33
34
|
const [mobileOpen, setMobileOpen] = useState(false);
|
|
34
35
|
const [selectedEndpoint, setSelectedEndpoint] = useState(null);
|
|
35
36
|
const [method, setMethod] = useState("GET");
|
|
36
37
|
const [pathParams, setPathParams] = useState([]);
|
|
37
38
|
const [queryParams, setQueryParams] = useState(() => createEmptyRows());
|
|
38
39
|
const [headers, setHeaders] = useState(() => createEmptyRows());
|
|
39
|
-
const [authType, setAuthType] = useState("session");
|
|
40
|
-
const [apiKey, setApiKey] = useState("");
|
|
41
|
-
const [bypassMode, setBypassMode] = useState(false);
|
|
40
|
+
const [authType, setAuthType] = useState(() => loadState("authType") ?? "session");
|
|
41
|
+
const [apiKey, setApiKey] = useState(() => loadState("apiKey") ?? "");
|
|
42
|
+
const [bypassMode, setBypassMode] = useState(() => loadState("bypassMode") ?? false);
|
|
42
43
|
const [selectedTeamId, setSelectedTeamId] = useState(() => {
|
|
44
|
+
const saved = loadState("selectedTeamId");
|
|
45
|
+
if (saved) return saved;
|
|
43
46
|
if (typeof window !== "undefined") {
|
|
44
47
|
return localStorage.getItem("activeTeamId");
|
|
45
48
|
}
|
|
46
49
|
return null;
|
|
47
50
|
});
|
|
48
51
|
const [body, setBody] = useState("");
|
|
52
|
+
const [actAsUserId, setActAsUserId] = useState(() => loadState("actAsUserId") ?? "");
|
|
49
53
|
const [tabsModifiedByPreset, setTabsModifiedByPreset] = useState(
|
|
50
54
|
() => /* @__PURE__ */ new Set()
|
|
51
55
|
);
|
|
@@ -60,20 +64,35 @@ function ApiExplorer({ routes, initialEndpoint }) {
|
|
|
60
64
|
const hasInitialized = useRef(false);
|
|
61
65
|
const { status, response, error, execute, cancel, reset } = useApiRequest();
|
|
62
66
|
const { selectedMethod: urlMethod, selectedPath: urlPath, navigateToEndpoint } = useApiExplorerNavigation({ basePath: "/devtools/api" });
|
|
67
|
+
const applyEndpointState = useCallback((endpointMethod, path) => {
|
|
68
|
+
const draft = loadState(draftKey(endpointMethod, path));
|
|
69
|
+
setPathParams((draft == null ? void 0 : draft.pathParams) ?? extractPathParams(path));
|
|
70
|
+
setQueryParams((draft == null ? void 0 : draft.queryParams) ?? createEmptyRows());
|
|
71
|
+
setHeaders((draft == null ? void 0 : draft.headers) ?? createEmptyRows());
|
|
72
|
+
setBody((draft == null ? void 0 : draft.body) ?? "");
|
|
73
|
+
setTabsModifiedByPreset(/* @__PURE__ */ new Set());
|
|
74
|
+
}, []);
|
|
75
|
+
useEffect(() => {
|
|
76
|
+
saveState("authType", authType);
|
|
77
|
+
saveState("apiKey", apiKey);
|
|
78
|
+
saveState("bypassMode", bypassMode);
|
|
79
|
+
saveState("selectedTeamId", selectedTeamId);
|
|
80
|
+
saveState("actAsUserId", actAsUserId);
|
|
81
|
+
}, [authType, apiKey, bypassMode, selectedTeamId, actAsUserId]);
|
|
82
|
+
useEffect(() => {
|
|
83
|
+
saveState("sidebarCollapsed", isCollapsed);
|
|
84
|
+
}, [isCollapsed]);
|
|
63
85
|
const handleSelectEndpoint = useCallback(
|
|
64
86
|
(path, selectedMethod, route) => {
|
|
65
87
|
reset();
|
|
66
88
|
navigateToEndpoint(selectedMethod, path);
|
|
67
89
|
setSelectedEndpoint({ path, method: selectedMethod, route });
|
|
68
90
|
setMethod(selectedMethod);
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
setHeaders(createEmptyRows());
|
|
72
|
-
setBody("");
|
|
73
|
-
setTabsModifiedByPreset(/* @__PURE__ */ new Set());
|
|
91
|
+
applyEndpointState(selectedMethod, path);
|
|
92
|
+
saveState("lastEndpoint", { method: selectedMethod, path });
|
|
74
93
|
setMobileOpen(false);
|
|
75
94
|
},
|
|
76
|
-
[reset, navigateToEndpoint]
|
|
95
|
+
[reset, navigateToEndpoint, applyEndpointState]
|
|
77
96
|
);
|
|
78
97
|
const handleSend = useCallback(async () => {
|
|
79
98
|
if (!selectedEndpoint) return;
|
|
@@ -90,6 +109,9 @@ function ApiExplorer({ routes, initialEndpoint }) {
|
|
|
90
109
|
customHeaders["x-team-id"] = selectedTeamId;
|
|
91
110
|
}
|
|
92
111
|
}
|
|
112
|
+
if (actAsUserId.trim()) {
|
|
113
|
+
customHeaders["x-act-as-user"] = actAsUserId.trim();
|
|
114
|
+
}
|
|
93
115
|
for (const h of headers) {
|
|
94
116
|
if (h.enabled && h.key) {
|
|
95
117
|
customHeaders[h.key] = h.value;
|
|
@@ -103,7 +125,7 @@ function ApiExplorer({ routes, initialEndpoint }) {
|
|
|
103
125
|
authType,
|
|
104
126
|
apiKey: authType === "apiKey" ? apiKey : void 0
|
|
105
127
|
});
|
|
106
|
-
}, [selectedEndpoint, pathParams, queryParams, headers, method, body, authType, apiKey, bypassMode, selectedTeamId, execute]);
|
|
128
|
+
}, [selectedEndpoint, pathParams, queryParams, headers, method, body, authType, apiKey, bypassMode, selectedTeamId, actAsUserId, execute]);
|
|
107
129
|
const handleApplyPreset = useCallback((preset) => {
|
|
108
130
|
const modifiedTabs = /* @__PURE__ */ new Set();
|
|
109
131
|
if (preset.method) {
|
|
@@ -168,14 +190,19 @@ function ApiExplorer({ routes, initialEndpoint }) {
|
|
|
168
190
|
if (route && ((selectedEndpoint == null ? void 0 : selectedEndpoint.path) !== urlPath || (selectedEndpoint == null ? void 0 : selectedEndpoint.method) !== urlMethod)) {
|
|
169
191
|
setSelectedEndpoint({ path: urlPath, method: urlMethod, route });
|
|
170
192
|
setMethod(urlMethod);
|
|
171
|
-
|
|
172
|
-
setQueryParams(createEmptyRows());
|
|
173
|
-
setHeaders(createEmptyRows());
|
|
174
|
-
setBody("");
|
|
175
|
-
setTabsModifiedByPreset(/* @__PURE__ */ new Set());
|
|
193
|
+
applyEndpointState(urlMethod, urlPath);
|
|
176
194
|
}
|
|
177
195
|
}
|
|
178
|
-
}, [urlPath, urlMethod, routes, selectedEndpoint]);
|
|
196
|
+
}, [urlPath, urlMethod, routes, selectedEndpoint, applyEndpointState]);
|
|
197
|
+
useEffect(() => {
|
|
198
|
+
if (!selectedEndpoint) return;
|
|
199
|
+
saveState(draftKey(selectedEndpoint.method, selectedEndpoint.path), {
|
|
200
|
+
pathParams,
|
|
201
|
+
queryParams,
|
|
202
|
+
headers,
|
|
203
|
+
body
|
|
204
|
+
});
|
|
205
|
+
}, [selectedEndpoint, pathParams, queryParams, headers, body]);
|
|
179
206
|
useEffect(() => {
|
|
180
207
|
if (hasInitialized.current) return;
|
|
181
208
|
if (urlPath && urlMethod) {
|
|
@@ -184,7 +211,7 @@ function ApiExplorer({ routes, initialEndpoint }) {
|
|
|
184
211
|
hasInitialized.current = true;
|
|
185
212
|
setSelectedEndpoint({ path: urlPath, method: urlMethod, route });
|
|
186
213
|
setMethod(urlMethod);
|
|
187
|
-
|
|
214
|
+
applyEndpointState(urlMethod, urlPath);
|
|
188
215
|
return;
|
|
189
216
|
}
|
|
190
217
|
}
|
|
@@ -195,13 +222,26 @@ function ApiExplorer({ routes, initialEndpoint }) {
|
|
|
195
222
|
const endpointMethod = initialEndpoint.method;
|
|
196
223
|
setSelectedEndpoint({ path: initialEndpoint.path, method: endpointMethod, route });
|
|
197
224
|
setMethod(endpointMethod);
|
|
198
|
-
|
|
225
|
+
applyEndpointState(endpointMethod, initialEndpoint.path);
|
|
199
226
|
if (!urlPath) {
|
|
200
227
|
navigateToEndpoint(endpointMethod, initialEndpoint.path);
|
|
201
228
|
}
|
|
202
229
|
return;
|
|
203
230
|
}
|
|
204
231
|
}
|
|
232
|
+
const last = loadState("lastEndpoint");
|
|
233
|
+
if (last) {
|
|
234
|
+
const route = findRouteByPath(routes, last.path);
|
|
235
|
+
if (route) {
|
|
236
|
+
hasInitialized.current = true;
|
|
237
|
+
const lastMethod = last.method;
|
|
238
|
+
setSelectedEndpoint({ path: last.path, method: lastMethod, route });
|
|
239
|
+
setMethod(lastMethod);
|
|
240
|
+
applyEndpointState(lastMethod, last.path);
|
|
241
|
+
navigateToEndpoint(lastMethod, last.path);
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
205
245
|
const categories = ["core", "entity", "theme", "plugin"];
|
|
206
246
|
for (const category of categories) {
|
|
207
247
|
const categoryRoutes = routes[category];
|
|
@@ -211,12 +251,12 @@ function ApiExplorer({ routes, initialEndpoint }) {
|
|
|
211
251
|
const firstMethod = firstRoute.methods[0] || "GET";
|
|
212
252
|
setSelectedEndpoint({ path: firstRoute.path, method: firstMethod, route: firstRoute });
|
|
213
253
|
setMethod(firstMethod);
|
|
214
|
-
|
|
254
|
+
applyEndpointState(firstMethod, firstRoute.path);
|
|
215
255
|
navigateToEndpoint(firstMethod, firstRoute.path);
|
|
216
256
|
break;
|
|
217
257
|
}
|
|
218
258
|
}
|
|
219
|
-
}, [routes, initialEndpoint, urlPath, urlMethod, navigateToEndpoint]);
|
|
259
|
+
}, [routes, initialEndpoint, urlPath, urlMethod, navigateToEndpoint, applyEndpointState]);
|
|
220
260
|
const totalRoutes = Object.values(routes).reduce((sum, arr) => sum + arr.length, 0);
|
|
221
261
|
return /* @__PURE__ */ jsxs("div", { className: "flex h-[calc(100vh-4rem)] w-full overflow-hidden", "data-cy": sel("devtools.apiExplorer.container"), children: [
|
|
222
262
|
/* @__PURE__ */ jsxs("div", { className: "lg:hidden fixed top-0 left-0 right-0 z-50 h-14 bg-background border-b flex items-center px-4 gap-3", children: [
|
|
@@ -281,6 +321,7 @@ function ApiExplorer({ routes, initialEndpoint }) {
|
|
|
281
321
|
apiKey,
|
|
282
322
|
bypassMode,
|
|
283
323
|
selectedTeamId,
|
|
324
|
+
actAsUserId,
|
|
284
325
|
body,
|
|
285
326
|
status,
|
|
286
327
|
onMethodChange: setMethod,
|
|
@@ -291,6 +332,7 @@ function ApiExplorer({ routes, initialEndpoint }) {
|
|
|
291
332
|
onApiKeyChange: setApiKey,
|
|
292
333
|
onBypassModeChange: setBypassMode,
|
|
293
334
|
onTeamChange: setSelectedTeamId,
|
|
335
|
+
onActAsUserChange: setActAsUserId,
|
|
294
336
|
onBodyChange: setBody,
|
|
295
337
|
onSend: handleSend,
|
|
296
338
|
onCancel: cancel,
|
|
@@ -12,6 +12,7 @@ interface ApiRequestPanelProps {
|
|
|
12
12
|
apiKey: string;
|
|
13
13
|
bypassMode: boolean;
|
|
14
14
|
selectedTeamId: string | null;
|
|
15
|
+
actAsUserId: string;
|
|
15
16
|
body: string;
|
|
16
17
|
status: RequestStatus;
|
|
17
18
|
onMethodChange: (method: HttpMethod) => void;
|
|
@@ -22,6 +23,7 @@ interface ApiRequestPanelProps {
|
|
|
22
23
|
onApiKeyChange: (key: string) => void;
|
|
23
24
|
onBypassModeChange: (enabled: boolean) => void;
|
|
24
25
|
onTeamChange: (teamId: string | null) => void;
|
|
26
|
+
onActAsUserChange: (userId: string) => void;
|
|
25
27
|
onBodyChange: (body: string) => void;
|
|
26
28
|
onSend: () => void;
|
|
27
29
|
onCancel: () => void;
|
|
@@ -34,6 +36,6 @@ interface ApiRequestPanelProps {
|
|
|
34
36
|
tabsModifiedByPreset?: Set<'params' | 'headers' | 'body'>;
|
|
35
37
|
onClearPresetIndicator?: (tab: 'params' | 'headers' | 'body') => void;
|
|
36
38
|
}
|
|
37
|
-
export declare function ApiRequestPanel({ route, basePath, method, pathParams, queryParams, headers, authType, apiKey, bypassMode, selectedTeamId, body, status, onMethodChange, onPathParamsChange, onQueryParamsChange, onHeadersChange, onAuthTypeChange, onApiKeyChange, onBypassModeChange, onTeamChange, onBodyChange, onSend, onCancel, endpointPresets, endpointDoc, onApplyPreset, tabsModifiedByPreset, onClearPresetIndicator, }: ApiRequestPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
39
|
+
export declare function ApiRequestPanel({ route, basePath, method, pathParams, queryParams, headers, authType, apiKey, bypassMode, selectedTeamId, actAsUserId, body, status, onMethodChange, onPathParamsChange, onQueryParamsChange, onHeadersChange, onAuthTypeChange, onApiKeyChange, onBypassModeChange, onTeamChange, onActAsUserChange, onBodyChange, onSend, onCancel, endpointPresets, endpointDoc, onApplyPreset, tabsModifiedByPreset, onClearPresetIndicator, }: ApiRequestPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
38
40
|
export {};
|
|
39
41
|
//# sourceMappingURL=ApiRequestPanel.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ApiRequestPanel.d.ts","sourceRoot":"","sources":["../../../../src/components/devtools/api-explorer/ApiRequestPanel.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACvG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0CAA0C,CAAA;AAC7E,OAAO,KAAK,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAA;AAa/E,UAAU,oBAAoB;IAC5B,KAAK,EAAE,aAAa,CAAA;IACpB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,UAAU,CAAA;IAClB,UAAU,EAAE,SAAS,EAAE,CAAA;IACvB,WAAW,EAAE,YAAY,EAAE,CAAA;IAC3B,OAAO,EAAE,YAAY,EAAE,CAAA;IACvB,QAAQ,EAAE,QAAQ,CAAA;IAClB,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,OAAO,CAAA;IACnB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,aAAa,CAAA;IACrB,cAAc,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAA;IAC5C,kBAAkB,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,IAAI,CAAA;IACjD,mBAAmB,EAAE,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,IAAI,CAAA;IACrD,eAAe,EAAE,CAAC,OAAO,EAAE,YAAY,EAAE,KAAK,IAAI,CAAA;IAClD,gBAAgB,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAA;IAC1C,cAAc,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;IACrC,kBAAkB,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;IAC9C,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAA;IAC7C,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACpC,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,QAAQ,EAAE,MAAM,IAAI,CAAA;IAEpB,eAAe,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAAA;IAC3C,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;IACpD,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,SAAS,KAAK,IAAI,CAAA;IAE3C,oBAAoB,CAAC,EAAE,GAAG,CAAC,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC,CAAA;IACzD,sBAAsB,CAAC,EAAE,CAAC,GAAG,EAAE,QAAQ,GAAG,SAAS,GAAG,MAAM,KAAK,IAAI,CAAA;CACtE;AAED,wBAAgB,eAAe,CAAC,EAC9B,KAAK,EACL,QAAQ,EACR,MAAM,EACN,UAAU,EACV,WAAW,EACX,OAAO,EACP,QAAQ,EACR,MAAM,EACN,UAAU,EACV,cAAc,EACd,IAAI,EACJ,MAAM,EACN,cAAc,EACd,kBAAkB,EAClB,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,YAAY,EACZ,YAAY,EACZ,MAAM,EACN,QAAQ,EACR,eAAe,EACf,WAAW,EACX,aAAa,EACb,oBAAoB,EACpB,sBAAsB,GACvB,EAAE,oBAAoB,
|
|
1
|
+
{"version":3,"file":"ApiRequestPanel.d.ts","sourceRoot":"","sources":["../../../../src/components/devtools/api-explorer/ApiRequestPanel.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACvG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0CAA0C,CAAA;AAC7E,OAAO,KAAK,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAA;AAa/E,UAAU,oBAAoB;IAC5B,KAAK,EAAE,aAAa,CAAA;IACpB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,UAAU,CAAA;IAClB,UAAU,EAAE,SAAS,EAAE,CAAA;IACvB,WAAW,EAAE,YAAY,EAAE,CAAA;IAC3B,OAAO,EAAE,YAAY,EAAE,CAAA;IACvB,QAAQ,EAAE,QAAQ,CAAA;IAClB,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,OAAO,CAAA;IACnB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,aAAa,CAAA;IACrB,cAAc,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAA;IAC5C,kBAAkB,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,IAAI,CAAA;IACjD,mBAAmB,EAAE,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,IAAI,CAAA;IACrD,eAAe,EAAE,CAAC,OAAO,EAAE,YAAY,EAAE,KAAK,IAAI,CAAA;IAClD,gBAAgB,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAA;IAC1C,cAAc,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;IACrC,kBAAkB,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;IAC9C,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAA;IAC7C,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;IAC3C,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACpC,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,QAAQ,EAAE,MAAM,IAAI,CAAA;IAEpB,eAAe,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAAA;IAC3C,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;IACpD,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,SAAS,KAAK,IAAI,CAAA;IAE3C,oBAAoB,CAAC,EAAE,GAAG,CAAC,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC,CAAA;IACzD,sBAAsB,CAAC,EAAE,CAAC,GAAG,EAAE,QAAQ,GAAG,SAAS,GAAG,MAAM,KAAK,IAAI,CAAA;CACtE;AAED,wBAAgB,eAAe,CAAC,EAC9B,KAAK,EACL,QAAQ,EACR,MAAM,EACN,UAAU,EACV,WAAW,EACX,OAAO,EACP,QAAQ,EACR,MAAM,EACN,UAAU,EACV,cAAc,EACd,WAAW,EACX,IAAI,EACJ,MAAM,EACN,cAAc,EACd,kBAAkB,EAClB,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,YAAY,EACZ,iBAAiB,EACjB,YAAY,EACZ,MAAM,EACN,QAAQ,EACR,eAAe,EACf,WAAW,EACX,aAAa,EACb,oBAAoB,EACpB,sBAAsB,GACvB,EAAE,oBAAoB,2CAgOtB"}
|
|
@@ -36,6 +36,7 @@ function ApiRequestPanel({
|
|
|
36
36
|
apiKey,
|
|
37
37
|
bypassMode,
|
|
38
38
|
selectedTeamId,
|
|
39
|
+
actAsUserId,
|
|
39
40
|
body,
|
|
40
41
|
status,
|
|
41
42
|
onMethodChange,
|
|
@@ -46,6 +47,7 @@ function ApiRequestPanel({
|
|
|
46
47
|
onApiKeyChange,
|
|
47
48
|
onBypassModeChange,
|
|
48
49
|
onTeamChange,
|
|
50
|
+
onActAsUserChange,
|
|
49
51
|
onBodyChange,
|
|
50
52
|
onSend,
|
|
51
53
|
onCancel,
|
|
@@ -132,10 +134,12 @@ function ApiRequestPanel({
|
|
|
132
134
|
apiKey,
|
|
133
135
|
bypassMode,
|
|
134
136
|
selectedTeamId,
|
|
137
|
+
actAsUserId,
|
|
135
138
|
onAuthTypeChange,
|
|
136
139
|
onApiKeyChange,
|
|
137
140
|
onBypassModeChange,
|
|
138
|
-
onTeamChange
|
|
141
|
+
onTeamChange,
|
|
142
|
+
onActAsUserChange
|
|
139
143
|
}
|
|
140
144
|
)
|
|
141
145
|
] }),
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Small localStorage helper for the API Explorer.
|
|
3
|
+
*
|
|
4
|
+
* Persists the Explorer's working state — session/auth config and per-endpoint
|
|
5
|
+
* request drafts — across reloads and endpoint switches. All access is SSR-safe
|
|
6
|
+
* and swallows quota/parse errors.
|
|
7
|
+
*/
|
|
8
|
+
export declare function loadState<T>(key: string): T | null;
|
|
9
|
+
export declare function saveState(key: string, value: unknown): void;
|
|
10
|
+
/** localStorage key for a specific endpoint's saved request draft. */
|
|
11
|
+
export declare function draftKey(method: string, path: string): string;
|
|
12
|
+
//# sourceMappingURL=explorer-storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"explorer-storage.d.ts","sourceRoot":"","sources":["../../../../src/components/devtools/api-explorer/explorer-storage.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,wBAAgB,SAAS,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI,CAQlD;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAO3D;AAED,sEAAsE;AACtE,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE7D"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const PREFIX = "nextspark:apiExplorer:";
|
|
2
|
+
function loadState(key) {
|
|
3
|
+
if (typeof window === "undefined") return null;
|
|
4
|
+
try {
|
|
5
|
+
const raw = window.localStorage.getItem(PREFIX + key);
|
|
6
|
+
return raw ? JSON.parse(raw) : null;
|
|
7
|
+
} catch {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
function saveState(key, value) {
|
|
12
|
+
if (typeof window === "undefined") return;
|
|
13
|
+
try {
|
|
14
|
+
window.localStorage.setItem(PREFIX + key, JSON.stringify(value));
|
|
15
|
+
} catch {
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function draftKey(method, path) {
|
|
19
|
+
return `draft:${method}:${path}`;
|
|
20
|
+
}
|
|
21
|
+
export {
|
|
22
|
+
draftKey,
|
|
23
|
+
loadState,
|
|
24
|
+
saveState
|
|
25
|
+
};
|
|
@@ -4,11 +4,14 @@ interface AuthSelectorProps {
|
|
|
4
4
|
apiKey: string;
|
|
5
5
|
bypassMode: boolean;
|
|
6
6
|
selectedTeamId: string | null;
|
|
7
|
+
/** Optional. The act-as input renders only when onActAsUserChange is provided. */
|
|
8
|
+
actAsUserId?: string;
|
|
7
9
|
onAuthTypeChange: (type: AuthType) => void;
|
|
8
10
|
onApiKeyChange: (key: string) => void;
|
|
9
11
|
onBypassModeChange: (enabled: boolean) => void;
|
|
10
12
|
onTeamChange: (teamId: string | null) => void;
|
|
13
|
+
onActAsUserChange?: (userId: string) => void;
|
|
11
14
|
}
|
|
12
|
-
export declare function AuthSelector({ authType, apiKey, bypassMode, selectedTeamId, onAuthTypeChange, onApiKeyChange, onBypassModeChange, onTeamChange, }: AuthSelectorProps): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
export declare function AuthSelector({ authType, apiKey, bypassMode, selectedTeamId, actAsUserId, onAuthTypeChange, onApiKeyChange, onBypassModeChange, onTeamChange, onActAsUserChange, }: AuthSelectorProps): import("react/jsx-runtime").JSX.Element;
|
|
13
16
|
export {};
|
|
14
17
|
//# sourceMappingURL=AuthSelector.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthSelector.d.ts","sourceRoot":"","sources":["../../../../src/components/devtools/api-tester/AuthSelector.tsx"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAGvC,UAAU,iBAAiB;IACzB,QAAQ,EAAE,QAAQ,CAAA;IAClB,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,OAAO,CAAA;IACnB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,gBAAgB,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAA;IAC1C,cAAc,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;IACrC,kBAAkB,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;IAC9C,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"AuthSelector.d.ts","sourceRoot":"","sources":["../../../../src/components/devtools/api-tester/AuthSelector.tsx"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAGvC,UAAU,iBAAiB;IACzB,QAAQ,EAAE,QAAQ,CAAA;IAClB,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,OAAO,CAAA;IACnB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,kFAAkF;IAClF,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,gBAAgB,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAA;IAC1C,cAAc,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;IACrC,kBAAkB,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;IAC9C,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAA;IAC7C,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;CAC7C;AAED,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,MAAM,EACN,UAAU,EACV,cAAc,EACd,WAAW,EACX,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,YAAY,EACZ,iBAAiB,GAClB,EAAE,iBAAiB,2CAoGnB"}
|
|
@@ -19,10 +19,12 @@ function AuthSelector({
|
|
|
19
19
|
apiKey,
|
|
20
20
|
bypassMode,
|
|
21
21
|
selectedTeamId,
|
|
22
|
+
actAsUserId,
|
|
22
23
|
onAuthTypeChange,
|
|
23
24
|
onApiKeyChange,
|
|
24
25
|
onBypassModeChange,
|
|
25
|
-
onTeamChange
|
|
26
|
+
onTeamChange,
|
|
27
|
+
onActAsUserChange
|
|
26
28
|
}) {
|
|
27
29
|
const t = useTranslations("devtools.apiTester.auth");
|
|
28
30
|
return /* @__PURE__ */ jsxs("div", { className: "space-y-3", "data-cy": sel("devtools.apiExplorer.auth.container"), children: [
|
|
@@ -79,7 +81,27 @@ function AuthSelector({
|
|
|
79
81
|
onTeamChange,
|
|
80
82
|
bypassMode
|
|
81
83
|
}
|
|
82
|
-
)
|
|
84
|
+
),
|
|
85
|
+
onActAsUserChange && /* @__PURE__ */ jsxs("div", { className: "space-y-1.5 pt-2 border-t", children: [
|
|
86
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
87
|
+
/* @__PURE__ */ jsx(Label, { htmlFor: "act-as-user", className: "text-sm cursor-pointer", children: "Act as user" }),
|
|
88
|
+
/* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
89
|
+
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(Info, { className: "h-4 w-4 text-muted-foreground cursor-help" }) }),
|
|
90
|
+
/* @__PURE__ */ jsx(TooltipContent, { className: "max-w-xs", children: "Developer-only. Resolves session-scoped endpoints (e.g. /me/*) as the given user without switching your session. Requires the developer role, a non-production environment, and ALLOW_ACT_AS_USER=true. Leave empty to use your own session." })
|
|
91
|
+
] }) })
|
|
92
|
+
] }),
|
|
93
|
+
/* @__PURE__ */ jsx(
|
|
94
|
+
Input,
|
|
95
|
+
{
|
|
96
|
+
id: "act-as-user",
|
|
97
|
+
placeholder: "user id (empty = your own session)",
|
|
98
|
+
value: actAsUserId ?? "",
|
|
99
|
+
onChange: (e) => onActAsUserChange(e.target.value),
|
|
100
|
+
className: "font-mono text-sm",
|
|
101
|
+
"data-cy": "devtools-api-auth-act-as-user"
|
|
102
|
+
}
|
|
103
|
+
)
|
|
104
|
+
] })
|
|
83
105
|
] });
|
|
84
106
|
}
|
|
85
107
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"docs-content.d.ts","sourceRoot":"","sources":["../../../src/components/docs/docs-content.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"docs-content.d.ts","sourceRoot":"","sources":["../../../src/components/docs/docs-content.tsx"],"names":[],"mappings":"AAKA,UAAU,gBAAgB;IACxB,IAAI,EAAE,MAAM,CAAA;CACb;AAED,wBAAgB,WAAW,CAAC,EAAE,IAAI,EAAE,EAAE,gBAAgB,2CA4BrD"}
|
|
@@ -1,9 +1,26 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useRef } from "react";
|
|
4
|
+
import { renderMermaid } from "../../lib/docs/mermaid.js";
|
|
3
5
|
function DocsContent({ html }) {
|
|
6
|
+
const containerRef = useRef(null);
|
|
7
|
+
useEffect(() => {
|
|
8
|
+
const container = containerRef.current;
|
|
9
|
+
if (!container) return;
|
|
10
|
+
const nodes = Array.from(
|
|
11
|
+
container.querySelectorAll(
|
|
12
|
+
'pre.mermaid:not([data-processed="true"])'
|
|
13
|
+
)
|
|
14
|
+
);
|
|
15
|
+
if (nodes.length === 0) return;
|
|
16
|
+
renderMermaid(nodes).catch((error) => {
|
|
17
|
+
console.error("[DocsContent] Failed to render mermaid diagrams:", error);
|
|
18
|
+
});
|
|
19
|
+
}, [html]);
|
|
4
20
|
return /* @__PURE__ */ jsx(
|
|
5
21
|
"div",
|
|
6
22
|
{
|
|
23
|
+
ref: containerRef,
|
|
7
24
|
className: "docs-content",
|
|
8
25
|
dangerouslySetInnerHTML: { __html: html },
|
|
9
26
|
"data-cy": "docs-content"
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
interface MermaidDiagramProps {
|
|
2
|
+
chart: string;
|
|
3
|
+
}
|
|
4
|
+
/**
|
|
5
|
+
* Renders a single mermaid diagram from its source. Used by React-based
|
|
6
|
+
* markdown renderers (e.g. MarkdownViewer) where a ```mermaid fence maps to a
|
|
7
|
+
* React element rather than to an HTML marker string.
|
|
8
|
+
*/
|
|
9
|
+
export declare function MermaidDiagram({ chart }: MermaidDiagramProps): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=mermaid-diagram.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mermaid-diagram.d.ts","sourceRoot":"","sources":["../../../src/components/docs/mermaid-diagram.tsx"],"names":[],"mappings":"AAKA,UAAU,mBAAmB;IAC3B,KAAK,EAAE,MAAM,CAAA;CACd;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,EAAE,KAAK,EAAE,EAAE,mBAAmB,2CAgB5D"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useRef } from "react";
|
|
4
|
+
import { renderMermaid } from "../../lib/docs/mermaid.js";
|
|
5
|
+
function MermaidDiagram({ chart }) {
|
|
6
|
+
const ref = useRef(null);
|
|
7
|
+
useEffect(() => {
|
|
8
|
+
const node = ref.current;
|
|
9
|
+
if (!node) return;
|
|
10
|
+
node.removeAttribute("data-processed");
|
|
11
|
+
node.textContent = chart;
|
|
12
|
+
renderMermaid([node]).catch((error) => {
|
|
13
|
+
console.error("[MermaidDiagram] Failed to render diagram:", error);
|
|
14
|
+
});
|
|
15
|
+
}, [chart]);
|
|
16
|
+
return /* @__PURE__ */ jsx("pre", { ref, className: "mermaid" });
|
|
17
|
+
}
|
|
18
|
+
export {
|
|
19
|
+
MermaidDiagram
|
|
20
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PermissionsMatrix.d.ts","sourceRoot":"","sources":["../../../src/components/permissions/PermissionsMatrix.tsx"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,QAAQ,EAAsB,MAAM,6BAA6B,CAAA;AAS/E,UAAU,sBAAsB;IAC9B,kCAAkC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAEjB,qEAAqE;IACrE,OAAO,CAAC,EAAE,OAAO,CAAA;IAEjB,yEAAyE;IACzE,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAA;CAC3D;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,QAAQ,EACR,OAAe,EACf,WAAW,GACZ,EAAE,sBAAsB,
|
|
1
|
+
{"version":3,"file":"PermissionsMatrix.d.ts","sourceRoot":"","sources":["../../../src/components/permissions/PermissionsMatrix.tsx"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,QAAQ,EAAsB,MAAM,6BAA6B,CAAA;AAS/E,UAAU,sBAAsB;IAC9B,kCAAkC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAEjB,qEAAqE;IACrE,OAAO,CAAC,EAAE,OAAO,CAAA;IAEjB,yEAAyE;IACzE,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAA;CAC3D;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,QAAQ,EACR,OAAe,EACf,WAAW,GACZ,EAAE,sBAAsB,2CAgHxB"}
|
|
@@ -31,17 +31,18 @@ function PermissionsMatrix({
|
|
|
31
31
|
onCellClick
|
|
32
32
|
}) {
|
|
33
33
|
const t = useTranslations("permissions");
|
|
34
|
-
const { permissions, matrix } = useMemo(() => {
|
|
34
|
+
const { permissions, matrix, roles: allRoles } = useMemo(() => {
|
|
35
35
|
const data = PermissionService.getMatrix();
|
|
36
36
|
if (category) {
|
|
37
37
|
return {
|
|
38
38
|
permissions: data.permissions.filter((p) => p.category === category),
|
|
39
|
-
matrix: data.matrix
|
|
39
|
+
matrix: data.matrix,
|
|
40
|
+
roles: data.roles
|
|
40
41
|
};
|
|
41
42
|
}
|
|
42
43
|
return data;
|
|
43
44
|
}, [category]);
|
|
44
|
-
const roles = compact ?
|
|
45
|
+
const roles = compact ? allRoles.filter((role) => role !== "owner") : allRoles;
|
|
45
46
|
const groupedPermissions = useMemo(() => {
|
|
46
47
|
const groups = {};
|
|
47
48
|
for (const perm of permissions) {
|
|
@@ -55,7 +56,7 @@ function PermissionsMatrix({
|
|
|
55
56
|
return /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsx("div", { className: "rounded-md border", "data-cy": "permissions-matrix", children: /* @__PURE__ */ jsxs(Table, { children: [
|
|
56
57
|
/* @__PURE__ */ jsx(TableHeader, { children: /* @__PURE__ */ jsxs(TableRow, { children: [
|
|
57
58
|
/* @__PURE__ */ jsx(TableHead, { className: "w-[300px]", children: t("permission") }),
|
|
58
|
-
roles.map((role) => /* @__PURE__ */ jsx(TableHead, { className: "text-center w-[100px]", children: /* @__PURE__ */ jsx(Badge, { variant: "outline", className: ROLE_COLORS[role], children: t(`roles.${role}.title`) }) }, role))
|
|
59
|
+
roles.map((role) => /* @__PURE__ */ jsx(TableHead, { className: "text-center w-[100px]", children: /* @__PURE__ */ jsx(Badge, { variant: "outline", className: ROLE_COLORS[role] ?? "text-muted-foreground bg-muted dark:bg-muted", children: t.has(`roles.${role}.title`) ? t(`roles.${role}.title`) : role.charAt(0).toUpperCase() + role.slice(1) }) }, role))
|
|
59
60
|
] }) }),
|
|
60
61
|
/* @__PURE__ */ jsx(TableBody, { children: Object.entries(groupedPermissions).map(([cat, perms]) => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
61
62
|
/* @__PURE__ */ jsx(TableRow, { className: "bg-muted/50", children: /* @__PURE__ */ jsx(TableCell, { colSpan: roles.length + 1, className: "font-semibold", children: cat }) }, `cat-${cat}`),
|
|
@@ -25,7 +25,7 @@ import { toast } from "sonner";
|
|
|
25
25
|
import { APP_CONFIG_MERGED } from "../../lib/config/config-sync.js";
|
|
26
26
|
import { getInvitableRoles } from "../../lib/teams/permissions.js";
|
|
27
27
|
function getAvailableRolesForInvite(userRole) {
|
|
28
|
-
const hierarchy = APP_CONFIG_MERGED.
|
|
28
|
+
const hierarchy = APP_CONFIG_MERGED.teams.roles.hierarchy;
|
|
29
29
|
const userLevel = hierarchy[userRole] ?? 0;
|
|
30
30
|
const invitableRoles = getInvitableRoles();
|
|
31
31
|
return invitableRoles.filter((role) => {
|
|
@@ -107,7 +107,7 @@ function TeamMembersList({ teamId: propTeamId, readOnly = false } = {}) {
|
|
|
107
107
|
canManageMembers && /* @__PURE__ */ jsx(TableCell, { children: !isOwner && !isCurrentUser && /* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
108
108
|
/* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon", "data-cy": `member-actions-${member.id}`, children: /* @__PURE__ */ jsx(MoreHorizontal, { className: "h-4 w-4" }) }) }),
|
|
109
109
|
/* @__PURE__ */ jsxs(DropdownMenuContent, { align: "end", children: [
|
|
110
|
-
APP_CONFIG_MERGED.
|
|
110
|
+
APP_CONFIG_MERGED.teams.roles.availableTeamRoles.filter(
|
|
111
111
|
(role) => role !== "owner" && // Cannot assign owner role
|
|
112
112
|
role !== memberRole && // Don't show current role
|
|
113
113
|
canManageRole(currentUserRole, role)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useApiExplorerNavigation.d.ts","sourceRoot":"","sources":["../../src/hooks/useApiExplorerNavigation.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yCAAyC,CAAA;AAEzE,MAAM,WAAW,+BAA+B;IAC9C,2EAA2E;IAC3E,QAAQ,EAAE,MAAM,CAAA;IAChB,8CAA8C;IAC9C,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAA;CAC5E;AAED,MAAM,WAAW,8BAA8B;IAC7C,qCAAqC;IACrC,cAAc,EAAE,UAAU,GAAG,IAAI,CAAA;IACjC,8DAA8D;IAC9D,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,8BAA8B;IAC9B,kBAAkB,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAC9D,yCAAyC;IACzC,cAAc,EAAE,MAAM,IAAI,CAAA;CAC3B;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,+BAA+B,GACvC,8BAA8B,
|
|
1
|
+
{"version":3,"file":"useApiExplorerNavigation.d.ts","sourceRoot":"","sources":["../../src/hooks/useApiExplorerNavigation.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yCAAyC,CAAA;AAEzE,MAAM,WAAW,+BAA+B;IAC9C,2EAA2E;IAC3E,QAAQ,EAAE,MAAM,CAAA;IAChB,8CAA8C;IAC9C,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAA;CAC5E;AAED,MAAM,WAAW,8BAA8B;IAC7C,qCAAqC;IACrC,cAAc,EAAE,UAAU,GAAG,IAAI,CAAA;IACjC,8DAA8D;IAC9D,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,8BAA8B;IAC9B,kBAAkB,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAC9D,yCAAyC;IACzC,cAAc,EAAE,MAAM,IAAI,CAAA;CAC3B;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,+BAA+B,GACvC,8BAA8B,CAiEhC"}
|
|
@@ -29,7 +29,11 @@ function useApiExplorerNavigation(options) {
|
|
|
29
29
|
(method, path) => {
|
|
30
30
|
const pathSegments = path.replace(/^\//, "");
|
|
31
31
|
const newUrl = `${basePath}/${method}/${pathSegments}`;
|
|
32
|
-
|
|
32
|
+
if (typeof window !== "undefined") {
|
|
33
|
+
window.history.pushState(null, "", newUrl);
|
|
34
|
+
} else {
|
|
35
|
+
router.push(newUrl);
|
|
36
|
+
}
|
|
33
37
|
},
|
|
34
38
|
[basePath, router]
|
|
35
39
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"team.actions.d.ts","sourceRoot":"","sources":["../../../src/lib/actions/team.actions.ts"],"names":[],"mappings":"AA4CA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAChE,OAAO,KAAK,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"team.actions.d.ts","sourceRoot":"","sources":["../../../src/lib/actions/team.actions.ts"],"names":[],"mappings":"AA4CA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAChE,OAAO,KAAK,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAA;AAQzE;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACnC;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,QAAQ,CAAA;CACf;AAgDD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CA4DnC;AAMD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,IAAI,GAAE,QAAoE,GACzE,OAAO,CAAC,kBAAkB,CAAC,kBAAkB,CAAC,CAAC,CAsEjD;AAMD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,sBAAsB,CAAC,CAgEjC;AAMD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,QAAQ,GACb,OAAO,CAAC,kBAAkB,CAAC,UAAU,CAAC,CAAC,CAuEzC"}
|