@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.
Files changed (72) hide show
  1. package/dist/components/devtools/MarkdownViewer.d.ts.map +1 -1
  2. package/dist/components/devtools/MarkdownViewer.js +5 -0
  3. package/dist/components/devtools/api-explorer/ApiDocsModal.d.ts.map +1 -1
  4. package/dist/components/devtools/api-explorer/ApiDocsModal.js +0 -0
  5. package/dist/components/devtools/api-explorer/ApiEndpointsSidebar.d.ts.map +1 -1
  6. package/dist/components/devtools/api-explorer/ApiEndpointsSidebar.js +16 -5
  7. package/dist/components/devtools/api-explorer/ApiExplorer.d.ts.map +1 -1
  8. package/dist/components/devtools/api-explorer/ApiExplorer.js +63 -21
  9. package/dist/components/devtools/api-explorer/ApiRequestPanel.d.ts +3 -1
  10. package/dist/components/devtools/api-explorer/ApiRequestPanel.d.ts.map +1 -1
  11. package/dist/components/devtools/api-explorer/ApiRequestPanel.js +5 -1
  12. package/dist/components/devtools/api-explorer/explorer-storage.d.ts +12 -0
  13. package/dist/components/devtools/api-explorer/explorer-storage.d.ts.map +1 -0
  14. package/dist/components/devtools/api-explorer/explorer-storage.js +25 -0
  15. package/dist/components/devtools/api-tester/AuthSelector.d.ts +4 -1
  16. package/dist/components/devtools/api-tester/AuthSelector.d.ts.map +1 -1
  17. package/dist/components/devtools/api-tester/AuthSelector.js +24 -2
  18. package/dist/components/docs/docs-content.d.ts.map +1 -1
  19. package/dist/components/docs/docs-content.js +17 -0
  20. package/dist/components/docs/mermaid-diagram.d.ts +11 -0
  21. package/dist/components/docs/mermaid-diagram.d.ts.map +1 -0
  22. package/dist/components/docs/mermaid-diagram.js +20 -0
  23. package/dist/components/permissions/PermissionsMatrix.d.ts.map +1 -1
  24. package/dist/components/permissions/PermissionsMatrix.js +5 -4
  25. package/dist/components/teams/InviteMemberDialog.js +1 -1
  26. package/dist/components/teams/TeamMembersList.js +1 -1
  27. package/dist/hooks/useApiExplorerNavigation.d.ts.map +1 -1
  28. package/dist/hooks/useApiExplorerNavigation.js +5 -1
  29. package/dist/lib/actions/team.actions.d.ts.map +1 -1
  30. package/dist/lib/actions/team.actions.js +7 -5
  31. package/dist/lib/api/auth/dual-auth.d.ts +14 -0
  32. package/dist/lib/api/auth/dual-auth.d.ts.map +1 -1
  33. package/dist/lib/api/auth/dual-auth.js +43 -2
  34. package/dist/lib/auth.d.ts.map +1 -1
  35. package/dist/lib/auth.js +3 -3
  36. package/dist/lib/config/app.config.js +60 -60
  37. package/dist/lib/config/config-sync.d.ts.map +1 -1
  38. package/dist/lib/config/config-sync.js +14 -9
  39. package/dist/lib/config/roles-merge.d.ts +0 -77
  40. package/dist/lib/config/roles-merge.d.ts.map +1 -1
  41. package/dist/lib/config/roles-merge.js +1 -98
  42. package/dist/lib/config/types.d.ts +6 -2
  43. package/dist/lib/config/types.d.ts.map +1 -1
  44. package/dist/lib/docs/mermaid.d.ts +15 -0
  45. package/dist/lib/docs/mermaid.d.ts.map +1 -0
  46. package/dist/lib/docs/mermaid.js +42 -0
  47. package/dist/lib/docs/parser.d.ts.map +1 -1
  48. package/dist/lib/docs/parser.js +2 -1
  49. package/dist/lib/docs/remark-mermaid.d.ts +15 -0
  50. package/dist/lib/docs/remark-mermaid.d.ts.map +1 -0
  51. package/dist/lib/docs/remark-mermaid.js +26 -0
  52. package/dist/lib/services/membership.service.js +2 -2
  53. package/dist/lib/services/team-member.service.d.ts +2 -2
  54. package/dist/lib/services/team-member.service.d.ts.map +1 -1
  55. package/dist/lib/services/team-member.service.js +4 -3
  56. package/dist/lib/teams/types.d.ts +2 -1
  57. package/dist/lib/teams/types.d.ts.map +1 -1
  58. package/dist/lib/teams/types.js +4 -4
  59. package/dist/styles/classes.json +3 -2
  60. package/dist/styles/ui.css +1 -1
  61. package/dist/templates/app/(auth)/login/page.tsx +2 -0
  62. package/dist/templates/app/(auth)/signup/page.tsx +4 -0
  63. package/dist/templates/app/superadmin/team-roles/page.tsx +2 -2
  64. package/package.json +3 -2
  65. package/scripts/build/registry/__tests__/team-roles.test.mjs +192 -0
  66. package/scripts/build/registry/discovery/permissions.mjs +163 -1
  67. package/scripts/build/registry/generators/permissions-registry.mjs +95 -35
  68. package/styles/docs.css +15 -0
  69. package/templates/app/(auth)/login/page.tsx +2 -0
  70. package/templates/app/(auth)/signup/page.tsx +4 -0
  71. package/templates/app/superadmin/team-roles/page.tsx +2 -2
  72. 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":"AAQA,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,2CA2CzE"}
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":"AAeA,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"}
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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ApiEndpointsSidebar.d.ts","sourceRoot":"","sources":["../../../../src/components/devtools/api-explorer/ApiEndpointsSidebar.tsx"],"names":[],"mappings":"AAWA,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,2CAoP1B"}
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
- /* @__PURE__ */ new Set(["core", "entity", "theme", "plugin"])
48
- );
49
- const [expandedPrefixes, setExpandedPrefixes] = useState(/* @__PURE__ */ new Set());
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;AAY5F,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,2CAwXxE"}
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
- setPathParams(extractPathParams(path));
70
- setQueryParams(createEmptyRows());
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
- setPathParams(extractPathParams(urlPath));
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
- setPathParams(extractPathParams(urlPath));
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
- setPathParams(extractPathParams(initialEndpoint.path));
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
- setPathParams(extractPathParams(firstRoute.path));
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,2CA8NtB"}
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;CAC9C;AAED,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,MAAM,EACN,UAAU,EACV,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,YAAY,GACb,EAAE,iBAAiB,2CAmEnB"}
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":"AAEA,UAAU,gBAAgB;IACxB,IAAI,EAAE,MAAM,CAAA;CACb;AAED,wBAAgB,WAAW,CAAC,EAAE,IAAI,EAAE,EAAE,gBAAgB,2CAQrD"}
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,2CA8GxB"}
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 ? ["admin", "member", "viewer"] : ["owner", "admin", "member", "viewer"];
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.teamRoles.hierarchy;
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.teamRoles.availableTeamRoles.filter(
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,CAwDhC"}
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
- router.push(newUrl);
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;AAMzE;;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,QAAmB,GACxB,OAAO,CAAC,kBAAkB,CAAC,kBAAkB,CAAC,CAAC,CAqEjD;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,CAsEzC"}
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"}