zudoku 0.3.0-dev.86 → 0.3.0-dev.88

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 (117) hide show
  1. package/dist/config/validators/InputSidebarSchema.d.ts +176 -0
  2. package/dist/config/validators/InputSidebarSchema.js +71 -0
  3. package/dist/config/validators/InputSidebarSchema.js.map +1 -0
  4. package/dist/config/validators/SidebarSchema.d.ts +13 -173
  5. package/dist/config/validators/SidebarSchema.js +75 -70
  6. package/dist/config/validators/SidebarSchema.js.map +1 -1
  7. package/dist/config/validators/validate.d.ts +5 -5
  8. package/dist/config/validators/validate.js +4 -3
  9. package/dist/config/validators/validate.js.map +1 -1
  10. package/dist/index.d.ts +1 -1
  11. package/dist/lib/authentication/components/SignIn.js +2 -2
  12. package/dist/lib/authentication/components/SignIn.js.map +1 -1
  13. package/dist/lib/authentication/components/SignOut.js +2 -2
  14. package/dist/lib/authentication/components/SignOut.js.map +1 -1
  15. package/dist/lib/authentication/components/SignUp.js +2 -2
  16. package/dist/lib/authentication/components/SignUp.js.map +1 -1
  17. package/dist/lib/authentication/hook.js +2 -2
  18. package/dist/lib/authentication/hook.js.map +1 -1
  19. package/dist/lib/components/DevPortal.d.ts +0 -4
  20. package/dist/lib/components/DevPortal.js +4 -23
  21. package/dist/lib/components/DevPortal.js.map +1 -1
  22. package/dist/lib/components/Header.js +2 -2
  23. package/dist/lib/components/Header.js.map +1 -1
  24. package/dist/lib/components/Layout.js +2 -2
  25. package/dist/lib/components/Layout.js.map +1 -1
  26. package/dist/lib/components/TopNavigation.js +2 -2
  27. package/dist/lib/components/TopNavigation.js.map +1 -1
  28. package/dist/lib/components/context/{DevPortalProvider.d.ts → ZudokuContext.d.ts} +3 -3
  29. package/dist/lib/components/context/{DevPortalProvider.js → ZudokuContext.js} +8 -9
  30. package/dist/lib/components/context/ZudokuContext.js.map +1 -0
  31. package/dist/lib/components/context/ZudokuProvider.d.ts +5 -0
  32. package/dist/lib/components/context/ZudokuProvider.js +16 -0
  33. package/dist/lib/components/context/ZudokuProvider.js.map +1 -0
  34. package/dist/lib/components/navigation/Sidebar.js +1 -1
  35. package/dist/lib/components/navigation/Sidebar.js.map +1 -1
  36. package/dist/lib/components/navigation/SidebarCategory.d.ts +2 -2
  37. package/dist/lib/components/navigation/SidebarCategory.js +1 -1
  38. package/dist/lib/components/navigation/SidebarCategory.js.map +1 -1
  39. package/dist/lib/components/navigation/SidebarItem.d.ts +2 -2
  40. package/dist/lib/components/navigation/SidebarItem.js +2 -2
  41. package/dist/lib/components/navigation/SidebarItem.js.map +1 -1
  42. package/dist/lib/components/navigation/utils.d.ts +6 -6
  43. package/dist/lib/components/navigation/utils.js +3 -3
  44. package/dist/lib/components/navigation/utils.js.map +1 -1
  45. package/dist/lib/core/DevPortalContext.d.ts +3 -3
  46. package/dist/lib/core/DevPortalContext.js +2 -2
  47. package/dist/lib/core/DevPortalContext.js.map +1 -1
  48. package/dist/lib/core/plugins.d.ts +2 -2
  49. package/dist/lib/plugins/api-keys/CreateApiKey.js +2 -2
  50. package/dist/lib/plugins/api-keys/CreateApiKey.js.map +1 -1
  51. package/dist/lib/plugins/api-keys/SettingsApiKeys.js +2 -2
  52. package/dist/lib/plugins/api-keys/SettingsApiKeys.js.map +1 -1
  53. package/dist/lib/plugins/openapi/index.js +1 -1
  54. package/dist/lib/plugins/openapi/index.js.map +1 -1
  55. package/dist/lib/plugins/openapi/playground/Playground.js +1 -1
  56. package/dist/lib/plugins/openapi/playground/Playground.js.map +1 -1
  57. package/dist/vite/plugin-sidebar.js +1 -1
  58. package/dist/vite/plugin-sidebar.js.map +1 -1
  59. package/lib/{AuthenticationPlugin-DgwV0hVu.js → AuthenticationPlugin-C3dzfGaA.js} +2 -2
  60. package/lib/AuthenticationPlugin-C3dzfGaA.js.map +1 -0
  61. package/lib/{Combination-DkycFHkm.js → Combination-Djh-LWhb.js} +93 -93
  62. package/lib/Combination-Djh-LWhb.js.map +1 -0
  63. package/lib/{Input-BclXSY0g.js → Input-SCGD-EvD.js} +3 -3
  64. package/lib/{Input-BclXSY0g.js.map → Input-SCGD-EvD.js.map} +1 -1
  65. package/lib/{MdxPage-Crlr0GmN.js → MdxPage-d02krMBw.js} +2 -2
  66. package/lib/{MdxPage-Crlr0GmN.js.map → MdxPage-d02krMBw.js.map} +1 -1
  67. package/lib/{OperationList-CMH3DPpj.js → OperationList-BQweX28o.js} +4 -4
  68. package/lib/{OperationList-CMH3DPpj.js.map → OperationList-BQweX28o.js.map} +1 -1
  69. package/lib/{Route-CwXfyIUw.js → Route-BPGW1TS_.js} +2 -2
  70. package/lib/{Route-CwXfyIUw.js.map → Route-BPGW1TS_.js.map} +1 -1
  71. package/lib/{Spinner-fF-Xv-gw.js → Spinner-DEgs-1Gu.js} +2 -2
  72. package/lib/{Spinner-fF-Xv-gw.js.map → Spinner-DEgs-1Gu.js.map} +1 -1
  73. package/lib/{DevPortalProvider-CTxoCHIT.js → ZudokuContext-C3JtXViU.js} +99 -99
  74. package/lib/ZudokuContext-C3JtXViU.js.map +1 -0
  75. package/lib/{index-DkuZvRNP.js → index-B8BCBPkc.js} +3 -3
  76. package/lib/{index-DkuZvRNP.js.map → index-B8BCBPkc.js.map} +1 -1
  77. package/lib/{index-DUrF63A6.js → index-DoIWqOG1.js} +8 -8
  78. package/lib/index-DoIWqOG1.js.map +1 -0
  79. package/lib/{utils-CzT_9Tsn.js → utils-D3fcGEot.js} +9 -9
  80. package/lib/{utils-CzT_9Tsn.js.map → utils-D3fcGEot.js.map} +1 -1
  81. package/lib/zudoku.auth-clerk.js +1 -1
  82. package/lib/zudoku.auth-openid.js +1 -1
  83. package/lib/zudoku.components.js +569 -566
  84. package/lib/zudoku.components.js.map +1 -1
  85. package/lib/zudoku.plugin-api-keys.js +16 -16
  86. package/lib/zudoku.plugin-api-keys.js.map +1 -1
  87. package/lib/zudoku.plugin-markdown.js +1 -1
  88. package/lib/zudoku.plugin-openapi.js +3 -3
  89. package/package.json +1 -1
  90. package/src/lib/authentication/components/SignIn.tsx +2 -2
  91. package/src/lib/authentication/components/SignOut.tsx +2 -2
  92. package/src/lib/authentication/components/SignUp.tsx +2 -2
  93. package/src/lib/authentication/hook.ts +2 -2
  94. package/src/lib/components/DevPortal.tsx +4 -30
  95. package/src/lib/components/Header.tsx +2 -2
  96. package/src/lib/components/Layout.tsx +2 -2
  97. package/src/lib/components/TopNavigation.tsx +2 -2
  98. package/src/lib/components/context/{DevPortalProvider.ts → ZudokuContext.ts} +7 -9
  99. package/src/lib/components/context/ZudokuProvider.tsx +26 -0
  100. package/src/lib/components/navigation/Sidebar.tsx +1 -1
  101. package/src/lib/components/navigation/SidebarCategory.tsx +3 -3
  102. package/src/lib/components/navigation/SidebarItem.tsx +8 -4
  103. package/src/lib/components/navigation/utils.ts +12 -15
  104. package/src/lib/core/DevPortalContext.ts +4 -4
  105. package/src/lib/core/plugins.ts +2 -2
  106. package/src/lib/plugins/api-keys/CreateApiKey.tsx +2 -2
  107. package/src/lib/plugins/api-keys/SettingsApiKeys.tsx +2 -2
  108. package/src/lib/plugins/openapi/index.tsx +3 -3
  109. package/src/lib/plugins/openapi/playground/Playground.tsx +1 -1
  110. package/dist/config/validators/ResolvedSidebarSchema.d.ts +0 -18
  111. package/dist/config/validators/ResolvedSidebarSchema.js +0 -76
  112. package/dist/config/validators/ResolvedSidebarSchema.js.map +0 -1
  113. package/dist/lib/components/context/DevPortalProvider.js.map +0 -1
  114. package/lib/AuthenticationPlugin-DgwV0hVu.js.map +0 -1
  115. package/lib/Combination-DkycFHkm.js.map +0 -1
  116. package/lib/DevPortalProvider-CTxoCHIT.js.map +0 -1
  117. package/lib/index-DUrF63A6.js.map +0 -1
@@ -1,19 +1,19 @@
1
1
  import { j as e } from "./jsx-runtime-B6kdoens.js";
2
2
  import { a as p, R as f } from "./SlotletProvider-CzMAO73_.js";
3
- import { u as g, a as u, I as j, S as v, b as k, c as w, d as b, e as K, f as y } from "./Input-BclXSY0g.js";
3
+ import { u as g, a as u, I as j, S as k, b as v, c as w, d as b, e as K, f as y } from "./Input-SCGD-EvD.js";
4
4
  import { b as N, L as x, O as E } from "./index-7kcHaXD6.js";
5
- import { u as h, q as A, t as S } from "./DevPortalProvider-CTxoCHIT.js";
6
- import { B as l, p as I } from "./Combination-DkycFHkm.js";
5
+ import { u as h, t as A, j as S } from "./ZudokuContext-C3JtXViU.js";
6
+ import { B as l, p as I } from "./Combination-Djh-LWhb.js";
7
7
  import { D as P } from "./DeveloperHint-BQSFXH01.js";
8
- import { useState as D } from "react";
9
- import { c as d, a as q } from "./Markdown-B_Gax7at.js";
8
+ import { useState as C } from "react";
9
+ import { c as d, a as D } from "./Markdown-B_Gax7at.js";
10
10
  /**
11
11
  * @license lucide-react v0.378.0 - ISC
12
12
  *
13
13
  * This source code is licensed under the ISC license.
14
14
  * See the LICENSE file in the root directory of this source tree.
15
15
  */
16
- const C = d("EyeOff", [
16
+ const R = d("EyeOff", [
17
17
  ["path", { d: "M9.88 9.88a3 3 0 1 0 4.24 4.24", key: "1jxqfv" }],
18
18
  [
19
19
  "path",
@@ -34,7 +34,7 @@ const C = d("EyeOff", [
34
34
  * This source code is licensed under the ISC license.
35
35
  * See the LICENSE file in the root directory of this source tree.
36
36
  */
37
- const R = d("Eye", [
37
+ const q = d("Eye", [
38
38
  ["path", { d: "M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z", key: "rwhkz3" }],
39
39
  ["circle", { cx: "12", cy: "12", r: "3", key: "1v7zrd" }]
40
40
  ]);
@@ -98,12 +98,12 @@ const F = ({ service: t }) => {
98
98
  /* @__PURE__ */ e.jsx(j, { ...n.register("description") }),
99
99
  "Expiration",
100
100
  /* @__PURE__ */ e.jsxs(
101
- v,
101
+ k,
102
102
  {
103
103
  onValueChange: (i) => n.setValue("expiresOn", i),
104
104
  defaultValue: n.getValues("expiresOn"),
105
105
  children: [
106
- /* @__PURE__ */ e.jsx(k, { children: /* @__PURE__ */ e.jsx(w, {}) }),
106
+ /* @__PURE__ */ e.jsx(v, { children: /* @__PURE__ */ e.jsx(w, {}) }),
107
107
  /* @__PURE__ */ e.jsx(b, { children: /* @__PURE__ */ e.jsxs(K, { children: [
108
108
  [7, 30, 60, 90].map((i) => /* @__PURE__ */ e.jsxs(y, { value: String(i), children: [
109
109
  i,
@@ -174,7 +174,7 @@ const F = ({ service: t }) => {
174
174
  ] }) : /* @__PURE__ */ e.jsx(
175
175
  "ul",
176
176
  {
177
- className: q(
177
+ className: D(
178
178
  "grid grid-cols-1 rounded border",
179
179
  "lg:grid-cols-[minmax(250px,min-content)_1fr_min-content]"
180
180
  ),
@@ -196,7 +196,7 @@ const F = ({ service: t }) => {
196
196
  ] })
197
197
  ] })
198
198
  ] }),
199
- /* @__PURE__ */ e.jsx("div", { className: "items-center flex lg:justify-center", children: /* @__PURE__ */ e.jsx(_, { apiKey: a.key }) }),
199
+ /* @__PURE__ */ e.jsx("div", { className: "items-center flex lg:justify-center", children: /* @__PURE__ */ e.jsx(Z, { apiKey: a.key }) }),
200
200
  /* @__PURE__ */ e.jsxs("div", { className: "flex gap-2", children: [
201
201
  t.rollKey && /* @__PURE__ */ e.jsx(
202
202
  l,
@@ -230,8 +230,8 @@ const F = ({ service: t }) => {
230
230
  }
231
231
  )
232
232
  ] });
233
- }, _ = ({ apiKey: t }) => {
234
- const [s, r] = D(!1);
233
+ }, Z = ({ apiKey: t }) => {
234
+ const [s, r] = C(!1);
235
235
  return /* @__PURE__ */ e.jsxs("div", { className: "flex gap-2 items-center text-sm w-full", children: [
236
236
  /* @__PURE__ */ e.jsx("div", { className: "border rounded bg-gray-100 dark:bg-gray-950 p-1 font-mono w-fit overflow-x-scroll h-9 items-center flex px-2", children: s ? t : "•".repeat(t.length) }),
237
237
  /* @__PURE__ */ e.jsx(
@@ -240,11 +240,11 @@ const F = ({ service: t }) => {
240
240
  variant: "outline",
241
241
  onClick: () => r((n) => !n),
242
242
  size: "icon",
243
- children: s ? /* @__PURE__ */ e.jsx(C, { size: 16 }) : /* @__PURE__ */ e.jsx(R, { size: 16 })
243
+ children: s ? /* @__PURE__ */ e.jsx(R, { size: 16 }) : /* @__PURE__ */ e.jsx(q, { size: 16 })
244
244
  }
245
245
  )
246
246
  ] });
247
- }, Q = "https://zudoku-rewiringamerica-main-ef9c9c0.d2.zuplo.dev", Z = (t) => ({
247
+ }, _ = "https://zudoku-rewiringamerica-main-ef9c9c0.d2.zuplo.dev", Q = (t) => ({
248
248
  deleteKey: async (s, r) => {
249
249
  const n = new Request(t + `/v1/developer/api-keys/${s}`, {
250
250
  method: "DELETE"
@@ -282,7 +282,7 @@ const F = ({ service: t }) => {
282
282
  return c(n.ok, "Failed to fetch API keys"), await n.json();
283
283
  }
284
284
  }), ee = (t) => {
285
- const s = "endpoint" in t ? t.endpoint : Q, r = "getKeys" in t ? t : Z(s);
285
+ const s = "endpoint" in t ? t.endpoint : _, r = "getKeys" in t ? t : Q(s);
286
286
  return {
287
287
  getProfileMenuItems: () => [
288
288
  {
@@ -1 +1 @@
1
- {"version":3,"file":"zudoku.plugin-api-keys.js","sources":["../../../node_modules/.pnpm/lucide-react@0.378.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/eye-off.js","../../../node_modules/.pnpm/lucide-react@0.378.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/eye.js","../../../node_modules/.pnpm/lucide-react@0.378.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/rotate-cw.js","../../../node_modules/.pnpm/lucide-react@0.378.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/trash.js","../src/lib/util/invariant.ts","../src/lib/plugins/api-keys/CreateApiKey.tsx","../src/lib/plugins/api-keys/ProtectedRoute.tsx","../src/lib/plugins/api-keys/SettingsApiKeys.tsx","../src/lib/plugins/api-keys/index.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.378.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst EyeOff = createLucideIcon(\"EyeOff\", [\n [\"path\", { d: \"M9.88 9.88a3 3 0 1 0 4.24 4.24\", key: \"1jxqfv\" }],\n [\n \"path\",\n {\n d: \"M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68\",\n key: \"9wicm4\"\n }\n ],\n [\n \"path\",\n { d: \"M6.61 6.61A13.526 13.526 0 0 0 2 12s3 7 10 7a9.74 9.74 0 0 0 5.39-1.61\", key: \"1jreej\" }\n ],\n [\"line\", { x1: \"2\", x2: \"22\", y1: \"2\", y2: \"22\", key: \"a6p6uj\" }]\n]);\n\nexport { EyeOff as default };\n//# sourceMappingURL=eye-off.js.map\n","/**\n * @license lucide-react v0.378.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Eye = createLucideIcon(\"Eye\", [\n [\"path\", { d: \"M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z\", key: \"rwhkz3\" }],\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"3\", key: \"1v7zrd\" }]\n]);\n\nexport { Eye as default };\n//# sourceMappingURL=eye.js.map\n","/**\n * @license lucide-react v0.378.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst RotateCw = createLucideIcon(\"RotateCw\", [\n [\"path\", { d: \"M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8\", key: \"1p45f6\" }],\n [\"path\", { d: \"M21 3v5h-5\", key: \"1q7to0\" }]\n]);\n\nexport { RotateCw as default };\n//# sourceMappingURL=rotate-cw.js.map\n","/**\n * @license lucide-react v0.378.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Trash = createLucideIcon(\"Trash\", [\n [\"path\", { d: \"M3 6h18\", key: \"d0wm0j\" }],\n [\"path\", { d: \"M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6\", key: \"4alrt4\" }],\n [\"path\", { d: \"M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2\", key: \"v07s0e\" }]\n]);\n\nexport { Trash as default };\n//# sourceMappingURL=trash.js.map\n","export default function invariant(\n condition: any,\n // Not providing an inline default argument for message as the result is smaller\n /**\n * Can provide a string, or a function that returns a string for cases where\n * the message takes a fair amount of effort to compute\n */\n message?: string | (() => string),\n): asserts condition {\n if (condition) {\n return;\n }\n // Condition not passed\n\n const provided: string | undefined =\n typeof message === \"function\" ? message() : message;\n\n throw new ZudokuError(provided ?? \"Invariant failed\");\n}\n\nclass ZudokuError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ZudokuError\";\n }\n}\n","import { useMutation } from \"@tanstack/react-query\";\nimport { useForm } from \"react-hook-form\";\nimport { Link, useNavigate } from \"react-router-dom\";\nimport { useDevPortal } from \"../../components/context/DevPortalProvider.js\";\nimport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"../../components/Select.js\";\nimport { Button } from \"../../ui/Button.js\";\nimport { Input } from \"../../ui/Input.js\";\nimport { ApiKeyService } from \"./index.js\";\n\ntype CreateApiKey = { description: string; expiresOn?: string };\n\nexport const CreateApiKey = ({ service }: { service: ApiKeyService }) => {\n const context = useDevPortal();\n const navigate = useNavigate();\n const form = useForm<CreateApiKey>({\n defaultValues: {\n expiresOn: \"30\",\n },\n });\n const createKeyMutation = useMutation({\n mutationFn: ({ description, expiresOn }: CreateApiKey) => {\n if (!service.createKey) {\n throw new Error(\"deleteKey not implemented\");\n }\n\n const expiresOnDate =\n expiresOn !== \"never\" ? addDaysToDate(Number(expiresOn)) : undefined;\n\n return service.createKey(\n { description: description, expiresOn: expiresOnDate },\n context,\n );\n },\n onSuccess: () => navigate(\"/settings/api-keys/\"),\n });\n\n if (!service.createKey) {\n return null;\n }\n\n return (\n <div className=\"max-w-screen-lg pt-[--padding-content-top] pb-[--padding-content-bottom]\">\n <div className=\"flex justify-between mb-4 border-b pb-1\">\n <h1 className=\"font-medium text-2xl\">New API Key</h1>\n </div>\n <form\n onSubmit={form.handleSubmit((data) => createKeyMutation.mutate(data))}\n >\n <div className=\"flex gap-2 flex-col\">\n Note\n <Input {...form.register(\"description\")} />\n Expiration\n <Select\n onValueChange={(value) => form.setValue(\"expiresOn\", value)}\n defaultValue={form.getValues(\"expiresOn\")}\n >\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectGroup>\n {[7, 30, 60, 90].map((option) => (\n <SelectItem value={String(option)} key={option}>\n {option} days\n </SelectItem>\n ))}\n <SelectItem value=\"never\">Never</SelectItem>\n </SelectGroup>\n </SelectContent>\n </Select>\n <div className=\"flex gap-2\">\n <Button>Generate Key</Button>\n <Button variant=\"outline\" asChild>\n <Link to=\"/settings/api-keys/\">Cancel</Link>\n </Button>\n </div>\n </div>\n </form>\n </div>\n );\n};\n\nconst addDaysToDate = (days: number): string => {\n const date = new Date();\n date.setDate(date.getDate() + days);\n return date.toISOString();\n};\n","import { Outlet } from \"react-router-dom\";\nimport { useAuth } from \"../../authentication/hook.js\";\nimport { DeveloperHint } from \"../../components/DeveloperHint.js\";\nimport { Button } from \"../../ui/Button.js\";\n\nexport const ProtectedRoute = () => {\n const auth = useAuth();\n\n // TODO: should we suspend here somehow?\n if (auth.isAuthEnabled && auth.isPending) {\n return null;\n }\n\n return auth.isAuthenticated ? (\n <Outlet />\n ) : !auth.isAuthEnabled ? (\n <div className=\"flex flex-col justify-center gap-2 items-center h-1/2\">\n <DeveloperHint className=\"max-w-[600px]\">\n Authentication needs to be enabled for API keys to work. Enable it in\n your Zudoku configuration under <code>authentication</code>.\n </DeveloperHint>\n </div>\n ) : (\n <div className=\"flex flex-col justify-center gap-2 items-center h-1/2\">\n Please login first to view this page\n <Button onClick={() => auth.login()}>Login</Button>\n </div>\n );\n};\n","import {\n useMutation,\n useQueryClient,\n useSuspenseQuery,\n} from \"@tanstack/react-query\";\nimport { EyeIcon, EyeOffIcon, RotateCwIcon, TrashIcon } from \"lucide-react\";\nimport { useState } from \"react\";\nimport { Link } from \"react-router-dom\";\nimport { useDevPortal } from \"../../components/context/DevPortalProvider.js\";\nimport { Slotlet } from \"../../components/SlotletProvider.js\";\nimport { Button } from \"../../ui/Button.js\";\nimport { cn } from \"../../util/cn.js\";\nimport { ApiKeyService } from \"./index.js\";\n\nexport const SettingsApiKeys = ({ service }: { service: ApiKeyService }) => {\n const context = useDevPortal();\n const queryClient = useQueryClient();\n const { data } = useSuspenseQuery({\n queryFn: () => service.getKeys(context),\n queryKey: [\"api-keys\"],\n retry: false,\n });\n\n const deleteKeyMutation = useMutation({\n mutationFn: (id: string) => {\n if (!service.deleteKey) {\n throw new Error(\"deleteKey not implemented\");\n }\n\n return service.deleteKey(id, context);\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: [\"api-keys\"] });\n },\n });\n\n const rollKeyMutation = useMutation({\n mutationFn: (id: string) => {\n if (!service.rollKey) {\n throw new Error(\"rollKey not implemented\");\n }\n\n return service.rollKey(id, context);\n },\n onSuccess: () => queryClient.invalidateQueries({ queryKey: [\"api-keys\"] }),\n });\n\n return (\n <div className=\"max-w-screen-lg h-full pt-[--padding-content-top] pb-[--padding-content-bottom]\">\n <Slotlet name=\"api-keys-list-page\" />\n\n <div className=\"flex justify-between mb-4 border-b pb-3\">\n <h1 className=\"font-medium text-2xl\">API Keys</h1>\n {service.createKey && (\n <Button asChild>\n <Link to=\"/settings/api-keys/new\">Create API Key</Link>\n </Button>\n )}\n </div>\n\n <Slotlet name=\"api-keys-list-page-before-keys\" />\n\n {data.length === 0 ? (\n <div className=\"flex flex-col justify-center gap-4 items-center p-8 border rounded bg-muted/30 text-muted-foreground\">\n <p className=\"text-center\">\n No API keys created yet.\n <br />\n Get started and create your first key.\n </p>\n {service.createKey && (\n <Button asChild variant=\"outline\">\n <Link to=\"/settings/api-keys/new\">Create API Key</Link>\n </Button>\n )}\n </div>\n ) : (\n <ul\n className={cn(\n \"grid grid-cols-1 rounded border\",\n \"lg:grid-cols-[minmax(250px,min-content)_1fr_min-content]\",\n )}\n >\n {data.map((key) => (\n <li\n className=\"border-b p-5 grid grid-cols-subgrid col-span-full gap-2 items-center\"\n key={key.id}\n >\n <div className=\"flex flex-col gap-1 text-sm\">\n {key.description ?? key.id}\n <div className=\"text-muted-foreground text-xs\">\n {key.createdOn && (\n <div>\n Created on {new Date(key.createdOn).toLocaleDateString()}\n </div>\n )}\n {key.expiresOn && (\n <div>\n Expires on {new Date(key.expiresOn).toLocaleDateString()}\n </div>\n )}\n </div>\n </div>\n <div className=\"items-center flex lg:justify-center\">\n <RevealApiKey apiKey={key.key} />\n </div>\n <div className=\"flex gap-2\">\n {service.rollKey && (\n <Button\n size=\"icon\"\n title=\"Roll this key\"\n variant=\"ghost\"\n onClick={() => {\n if (!confirm(\"Do you want to roll this key?\")) {\n return;\n }\n\n rollKeyMutation.mutate(key.id);\n }}\n >\n <RotateCwIcon size={16} />\n </Button>\n )}\n {service.deleteKey && (\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => {\n if (!confirm(\"Do you want to delete this key?\")) {\n return;\n }\n\n deleteKeyMutation.mutate(key.id);\n }}\n disabled={deleteKeyMutation.isPending}\n >\n <TrashIcon size={16} />\n </Button>\n )}\n </div>\n </li>\n ))}\n </ul>\n )}\n </div>\n );\n};\n\nconst RevealApiKey = ({ apiKey }: { apiKey: string }) => {\n const [revealed, setRevealed] = useState(false);\n\n return (\n <div className=\"flex gap-2 items-center text-sm w-full\">\n <div className=\"border rounded bg-gray-100 dark:bg-gray-950 p-1 font-mono w-fit overflow-x-scroll h-9 items-center flex px-2\">\n {revealed ? apiKey : \"•\".repeat(apiKey.length)}\n </div>\n <Button\n variant=\"outline\"\n onClick={() => setRevealed((prev) => !prev)}\n size=\"icon\"\n >\n {revealed ? <EyeOffIcon size={16} /> : <EyeIcon size={16} />}\n </Button>\n </div>\n );\n};\n","import { type RouteObject } from \"react-router-dom\";\nimport { DevPortalContext } from \"../../core/DevPortalContext.js\";\nimport {\n type ApiIdentityPlugin,\n type DevPortalPlugin,\n ProfileMenuPlugin,\n} from \"../../core/plugins.js\";\nimport { RouterError } from \"../../errors/RouterError.js\";\nimport invariant from \"../../util/invariant.js\";\nimport { CreateApiKey } from \"./CreateApiKey.js\";\nimport { ProtectedRoute } from \"./ProtectedRoute.js\";\nimport { SettingsApiKeys } from \"./SettingsApiKeys.js\";\n\nconst DEFAULT_API_KEY_ENDPOINT =\n \"https://zudoku-rewiringamerica-main-ef9c9c0.d2.zuplo.dev\";\n\nexport type ApiKeyService = {\n getKeys: (context: DevPortalContext) => Promise<ApiKey[]>;\n rollKey?: (id: string, context: DevPortalContext) => Promise<void>;\n deleteKey?: (id: string, context: DevPortalContext) => Promise<void>;\n updateKeyDescription?: (\n apiKey: { id: string; description: string },\n context: DevPortalContext,\n ) => Promise<void>;\n getUsage?: (apiKeys: string[], context: DevPortalContext) => Promise<void>;\n createKey?: (\n apiKey: { description: string; expiresOn?: string },\n context: DevPortalContext,\n ) => Promise<void>;\n};\n\nexport type GetApiKeysOptions = ApiKeyService | { endpoint: string } | object;\n\nexport type ApiKeyPluginOptions = object & GetApiKeysOptions;\n\nexport interface ApiKey {\n id: string;\n description?: string;\n createdOn?: string;\n updatedOn?: string;\n expiresOn?: string;\n key: string;\n}\n\nconst createDefaultHandler = (endpoint: string): ApiKeyService => {\n return {\n deleteKey: async (id, context) => {\n const request = new Request(endpoint + `/v1/developer/api-keys/${id}`, {\n method: \"DELETE\",\n });\n\n await context.signRequest(request);\n\n const response = await fetch(request);\n invariant(response.ok, \"Failed to delete API key\");\n },\n rollKey: async (id, context) => {\n const response = await fetch(\n await context.signRequest(\n new Request(endpoint + `/v1/developer/api-keys/${id}/key`, {\n method: \"DELETE\",\n }),\n ),\n );\n invariant(response.ok, \"Failed to delete API key\");\n },\n createKey: async (apiKey, context) => {\n const request = new Request(endpoint + `/v1/developer/api-keys`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(apiKey),\n });\n\n await context.signRequest(request);\n\n const response = await fetch(request);\n invariant(response.ok, \"Failed to create API key\");\n },\n getKeys: async (context) => {\n const request = new Request(endpoint + `/v1/developer/api-keys`);\n\n await context.signRequest(request);\n\n const keys = await fetch(request);\n invariant(keys.ok, \"Failed to fetch API keys\");\n\n return await keys.json();\n },\n };\n};\n\nexport const apiKeyPlugin = (\n options: ApiKeyPluginOptions,\n): DevPortalPlugin & ApiIdentityPlugin & ProfileMenuPlugin => {\n const endpoint =\n \"endpoint\" in options ? options.endpoint : DEFAULT_API_KEY_ENDPOINT;\n\n const service =\n \"getKeys\" in options ? options : createDefaultHandler(endpoint);\n\n return {\n getProfileMenuItems: () => [\n {\n label: \"API Keys\",\n path: \"/settings/api-keys\",\n },\n ],\n getIdentities: async (context) => {\n try {\n const keys = await service.getKeys(context);\n\n return keys.map((key) => ({\n authorizeRequest: (request) => {\n request.headers.set(\"Authorization\", `Bearer ${key.key}`);\n return request;\n },\n id: key.id,\n label: key.description ?? key.id,\n }));\n } catch {\n return [];\n }\n },\n getRoutes: (): RouteObject[] => {\n // TODO: Make lazy\n return [\n {\n element: <ProtectedRoute />,\n errorElement: <RouterError />,\n children: [\n {\n path: \"/settings/api-keys\",\n element: <SettingsApiKeys service={service} />,\n },\n {\n path: \"/settings/api-keys/new\",\n element: <CreateApiKey service={service} />,\n },\n ],\n },\n ];\n },\n };\n};\n"],"names":["EyeOff","createLucideIcon","Eye","RotateCw","Trash","invariant","condition","message","provided","ZudokuError","CreateApiKey","service","context","useDevPortal","navigate","useNavigate","form","useForm","createKeyMutation","useMutation","description","expiresOn","expiresOnDate","addDaysToDate","jsxs","jsx","data","Input","Select","value","SelectTrigger","SelectValue","SelectContent","SelectGroup","option","SelectItem","Button","Link","days","date","ProtectedRoute","auth","useAuth","Outlet","DeveloperHint","SettingsApiKeys","queryClient","useQueryClient","useSuspenseQuery","deleteKeyMutation","id","rollKeyMutation","Slotlet","cn","key","RevealApiKey","RotateCwIcon","TrashIcon","apiKey","revealed","setRevealed","useState","prev","EyeOffIcon","EyeIcon","DEFAULT_API_KEY_ENDPOINT","createDefaultHandler","endpoint","request","response","keys","apiKeyPlugin","options","RouterError"],"mappings":"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","x_google_ignoreList":[0,1,2,3]}
1
+ {"version":3,"file":"zudoku.plugin-api-keys.js","sources":["../../../node_modules/.pnpm/lucide-react@0.378.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/eye-off.js","../../../node_modules/.pnpm/lucide-react@0.378.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/eye.js","../../../node_modules/.pnpm/lucide-react@0.378.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/rotate-cw.js","../../../node_modules/.pnpm/lucide-react@0.378.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/trash.js","../src/lib/util/invariant.ts","../src/lib/plugins/api-keys/CreateApiKey.tsx","../src/lib/plugins/api-keys/ProtectedRoute.tsx","../src/lib/plugins/api-keys/SettingsApiKeys.tsx","../src/lib/plugins/api-keys/index.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.378.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst EyeOff = createLucideIcon(\"EyeOff\", [\n [\"path\", { d: \"M9.88 9.88a3 3 0 1 0 4.24 4.24\", key: \"1jxqfv\" }],\n [\n \"path\",\n {\n d: \"M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68\",\n key: \"9wicm4\"\n }\n ],\n [\n \"path\",\n { d: \"M6.61 6.61A13.526 13.526 0 0 0 2 12s3 7 10 7a9.74 9.74 0 0 0 5.39-1.61\", key: \"1jreej\" }\n ],\n [\"line\", { x1: \"2\", x2: \"22\", y1: \"2\", y2: \"22\", key: \"a6p6uj\" }]\n]);\n\nexport { EyeOff as default };\n//# sourceMappingURL=eye-off.js.map\n","/**\n * @license lucide-react v0.378.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Eye = createLucideIcon(\"Eye\", [\n [\"path\", { d: \"M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z\", key: \"rwhkz3\" }],\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"3\", key: \"1v7zrd\" }]\n]);\n\nexport { Eye as default };\n//# sourceMappingURL=eye.js.map\n","/**\n * @license lucide-react v0.378.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst RotateCw = createLucideIcon(\"RotateCw\", [\n [\"path\", { d: \"M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8\", key: \"1p45f6\" }],\n [\"path\", { d: \"M21 3v5h-5\", key: \"1q7to0\" }]\n]);\n\nexport { RotateCw as default };\n//# sourceMappingURL=rotate-cw.js.map\n","/**\n * @license lucide-react v0.378.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Trash = createLucideIcon(\"Trash\", [\n [\"path\", { d: \"M3 6h18\", key: \"d0wm0j\" }],\n [\"path\", { d: \"M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6\", key: \"4alrt4\" }],\n [\"path\", { d: \"M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2\", key: \"v07s0e\" }]\n]);\n\nexport { Trash as default };\n//# sourceMappingURL=trash.js.map\n","export default function invariant(\n condition: any,\n // Not providing an inline default argument for message as the result is smaller\n /**\n * Can provide a string, or a function that returns a string for cases where\n * the message takes a fair amount of effort to compute\n */\n message?: string | (() => string),\n): asserts condition {\n if (condition) {\n return;\n }\n // Condition not passed\n\n const provided: string | undefined =\n typeof message === \"function\" ? message() : message;\n\n throw new ZudokuError(provided ?? \"Invariant failed\");\n}\n\nclass ZudokuError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ZudokuError\";\n }\n}\n","import { useMutation } from \"@tanstack/react-query\";\nimport { useForm } from \"react-hook-form\";\nimport { Link, useNavigate } from \"react-router-dom\";\nimport { useZudoku } from \"../../components/context/ZudokuContext.js\";\nimport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"../../components/Select.js\";\nimport { Button } from \"../../ui/Button.js\";\nimport { Input } from \"../../ui/Input.js\";\nimport { ApiKeyService } from \"./index.js\";\n\ntype CreateApiKey = { description: string; expiresOn?: string };\n\nexport const CreateApiKey = ({ service }: { service: ApiKeyService }) => {\n const context = useZudoku();\n const navigate = useNavigate();\n const form = useForm<CreateApiKey>({\n defaultValues: {\n expiresOn: \"30\",\n },\n });\n const createKeyMutation = useMutation({\n mutationFn: ({ description, expiresOn }: CreateApiKey) => {\n if (!service.createKey) {\n throw new Error(\"deleteKey not implemented\");\n }\n\n const expiresOnDate =\n expiresOn !== \"never\" ? addDaysToDate(Number(expiresOn)) : undefined;\n\n return service.createKey(\n { description: description, expiresOn: expiresOnDate },\n context,\n );\n },\n onSuccess: () => navigate(\"/settings/api-keys/\"),\n });\n\n if (!service.createKey) {\n return null;\n }\n\n return (\n <div className=\"max-w-screen-lg pt-[--padding-content-top] pb-[--padding-content-bottom]\">\n <div className=\"flex justify-between mb-4 border-b pb-1\">\n <h1 className=\"font-medium text-2xl\">New API Key</h1>\n </div>\n <form\n onSubmit={form.handleSubmit((data) => createKeyMutation.mutate(data))}\n >\n <div className=\"flex gap-2 flex-col\">\n Note\n <Input {...form.register(\"description\")} />\n Expiration\n <Select\n onValueChange={(value) => form.setValue(\"expiresOn\", value)}\n defaultValue={form.getValues(\"expiresOn\")}\n >\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectGroup>\n {[7, 30, 60, 90].map((option) => (\n <SelectItem value={String(option)} key={option}>\n {option} days\n </SelectItem>\n ))}\n <SelectItem value=\"never\">Never</SelectItem>\n </SelectGroup>\n </SelectContent>\n </Select>\n <div className=\"flex gap-2\">\n <Button>Generate Key</Button>\n <Button variant=\"outline\" asChild>\n <Link to=\"/settings/api-keys/\">Cancel</Link>\n </Button>\n </div>\n </div>\n </form>\n </div>\n );\n};\n\nconst addDaysToDate = (days: number): string => {\n const date = new Date();\n date.setDate(date.getDate() + days);\n return date.toISOString();\n};\n","import { Outlet } from \"react-router-dom\";\nimport { useAuth } from \"../../authentication/hook.js\";\nimport { DeveloperHint } from \"../../components/DeveloperHint.js\";\nimport { Button } from \"../../ui/Button.js\";\n\nexport const ProtectedRoute = () => {\n const auth = useAuth();\n\n // TODO: should we suspend here somehow?\n if (auth.isAuthEnabled && auth.isPending) {\n return null;\n }\n\n return auth.isAuthenticated ? (\n <Outlet />\n ) : !auth.isAuthEnabled ? (\n <div className=\"flex flex-col justify-center gap-2 items-center h-1/2\">\n <DeveloperHint className=\"max-w-[600px]\">\n Authentication needs to be enabled for API keys to work. Enable it in\n your Zudoku configuration under <code>authentication</code>.\n </DeveloperHint>\n </div>\n ) : (\n <div className=\"flex flex-col justify-center gap-2 items-center h-1/2\">\n Please login first to view this page\n <Button onClick={() => auth.login()}>Login</Button>\n </div>\n );\n};\n","import {\n useMutation,\n useQueryClient,\n useSuspenseQuery,\n} from \"@tanstack/react-query\";\nimport { EyeIcon, EyeOffIcon, RotateCwIcon, TrashIcon } from \"lucide-react\";\nimport { useState } from \"react\";\nimport { Link } from \"react-router-dom\";\nimport { useZudoku } from \"../../components/context/ZudokuContext.js\";\nimport { Slotlet } from \"../../components/SlotletProvider.js\";\nimport { Button } from \"../../ui/Button.js\";\nimport { cn } from \"../../util/cn.js\";\nimport { ApiKeyService } from \"./index.js\";\n\nexport const SettingsApiKeys = ({ service }: { service: ApiKeyService }) => {\n const context = useZudoku();\n const queryClient = useQueryClient();\n const { data } = useSuspenseQuery({\n queryFn: () => service.getKeys(context),\n queryKey: [\"api-keys\"],\n retry: false,\n });\n\n const deleteKeyMutation = useMutation({\n mutationFn: (id: string) => {\n if (!service.deleteKey) {\n throw new Error(\"deleteKey not implemented\");\n }\n\n return service.deleteKey(id, context);\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: [\"api-keys\"] });\n },\n });\n\n const rollKeyMutation = useMutation({\n mutationFn: (id: string) => {\n if (!service.rollKey) {\n throw new Error(\"rollKey not implemented\");\n }\n\n return service.rollKey(id, context);\n },\n onSuccess: () => queryClient.invalidateQueries({ queryKey: [\"api-keys\"] }),\n });\n\n return (\n <div className=\"max-w-screen-lg h-full pt-[--padding-content-top] pb-[--padding-content-bottom]\">\n <Slotlet name=\"api-keys-list-page\" />\n\n <div className=\"flex justify-between mb-4 border-b pb-3\">\n <h1 className=\"font-medium text-2xl\">API Keys</h1>\n {service.createKey && (\n <Button asChild>\n <Link to=\"/settings/api-keys/new\">Create API Key</Link>\n </Button>\n )}\n </div>\n\n <Slotlet name=\"api-keys-list-page-before-keys\" />\n\n {data.length === 0 ? (\n <div className=\"flex flex-col justify-center gap-4 items-center p-8 border rounded bg-muted/30 text-muted-foreground\">\n <p className=\"text-center\">\n No API keys created yet.\n <br />\n Get started and create your first key.\n </p>\n {service.createKey && (\n <Button asChild variant=\"outline\">\n <Link to=\"/settings/api-keys/new\">Create API Key</Link>\n </Button>\n )}\n </div>\n ) : (\n <ul\n className={cn(\n \"grid grid-cols-1 rounded border\",\n \"lg:grid-cols-[minmax(250px,min-content)_1fr_min-content]\",\n )}\n >\n {data.map((key) => (\n <li\n className=\"border-b p-5 grid grid-cols-subgrid col-span-full gap-2 items-center\"\n key={key.id}\n >\n <div className=\"flex flex-col gap-1 text-sm\">\n {key.description ?? key.id}\n <div className=\"text-muted-foreground text-xs\">\n {key.createdOn && (\n <div>\n Created on {new Date(key.createdOn).toLocaleDateString()}\n </div>\n )}\n {key.expiresOn && (\n <div>\n Expires on {new Date(key.expiresOn).toLocaleDateString()}\n </div>\n )}\n </div>\n </div>\n <div className=\"items-center flex lg:justify-center\">\n <RevealApiKey apiKey={key.key} />\n </div>\n <div className=\"flex gap-2\">\n {service.rollKey && (\n <Button\n size=\"icon\"\n title=\"Roll this key\"\n variant=\"ghost\"\n onClick={() => {\n if (!confirm(\"Do you want to roll this key?\")) {\n return;\n }\n\n rollKeyMutation.mutate(key.id);\n }}\n >\n <RotateCwIcon size={16} />\n </Button>\n )}\n {service.deleteKey && (\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => {\n if (!confirm(\"Do you want to delete this key?\")) {\n return;\n }\n\n deleteKeyMutation.mutate(key.id);\n }}\n disabled={deleteKeyMutation.isPending}\n >\n <TrashIcon size={16} />\n </Button>\n )}\n </div>\n </li>\n ))}\n </ul>\n )}\n </div>\n );\n};\n\nconst RevealApiKey = ({ apiKey }: { apiKey: string }) => {\n const [revealed, setRevealed] = useState(false);\n\n return (\n <div className=\"flex gap-2 items-center text-sm w-full\">\n <div className=\"border rounded bg-gray-100 dark:bg-gray-950 p-1 font-mono w-fit overflow-x-scroll h-9 items-center flex px-2\">\n {revealed ? apiKey : \"•\".repeat(apiKey.length)}\n </div>\n <Button\n variant=\"outline\"\n onClick={() => setRevealed((prev) => !prev)}\n size=\"icon\"\n >\n {revealed ? <EyeOffIcon size={16} /> : <EyeIcon size={16} />}\n </Button>\n </div>\n );\n};\n","import { type RouteObject } from \"react-router-dom\";\nimport { DevPortalContext } from \"../../core/DevPortalContext.js\";\nimport {\n type ApiIdentityPlugin,\n type DevPortalPlugin,\n ProfileMenuPlugin,\n} from \"../../core/plugins.js\";\nimport { RouterError } from \"../../errors/RouterError.js\";\nimport invariant from \"../../util/invariant.js\";\nimport { CreateApiKey } from \"./CreateApiKey.js\";\nimport { ProtectedRoute } from \"./ProtectedRoute.js\";\nimport { SettingsApiKeys } from \"./SettingsApiKeys.js\";\n\nconst DEFAULT_API_KEY_ENDPOINT =\n \"https://zudoku-rewiringamerica-main-ef9c9c0.d2.zuplo.dev\";\n\nexport type ApiKeyService = {\n getKeys: (context: DevPortalContext) => Promise<ApiKey[]>;\n rollKey?: (id: string, context: DevPortalContext) => Promise<void>;\n deleteKey?: (id: string, context: DevPortalContext) => Promise<void>;\n updateKeyDescription?: (\n apiKey: { id: string; description: string },\n context: DevPortalContext,\n ) => Promise<void>;\n getUsage?: (apiKeys: string[], context: DevPortalContext) => Promise<void>;\n createKey?: (\n apiKey: { description: string; expiresOn?: string },\n context: DevPortalContext,\n ) => Promise<void>;\n};\n\nexport type GetApiKeysOptions = ApiKeyService | { endpoint: string } | object;\n\nexport type ApiKeyPluginOptions = object & GetApiKeysOptions;\n\nexport interface ApiKey {\n id: string;\n description?: string;\n createdOn?: string;\n updatedOn?: string;\n expiresOn?: string;\n key: string;\n}\n\nconst createDefaultHandler = (endpoint: string): ApiKeyService => {\n return {\n deleteKey: async (id, context) => {\n const request = new Request(endpoint + `/v1/developer/api-keys/${id}`, {\n method: \"DELETE\",\n });\n\n await context.signRequest(request);\n\n const response = await fetch(request);\n invariant(response.ok, \"Failed to delete API key\");\n },\n rollKey: async (id, context) => {\n const response = await fetch(\n await context.signRequest(\n new Request(endpoint + `/v1/developer/api-keys/${id}/key`, {\n method: \"DELETE\",\n }),\n ),\n );\n invariant(response.ok, \"Failed to delete API key\");\n },\n createKey: async (apiKey, context) => {\n const request = new Request(endpoint + `/v1/developer/api-keys`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(apiKey),\n });\n\n await context.signRequest(request);\n\n const response = await fetch(request);\n invariant(response.ok, \"Failed to create API key\");\n },\n getKeys: async (context) => {\n const request = new Request(endpoint + `/v1/developer/api-keys`);\n\n await context.signRequest(request);\n\n const keys = await fetch(request);\n invariant(keys.ok, \"Failed to fetch API keys\");\n\n return await keys.json();\n },\n };\n};\n\nexport const apiKeyPlugin = (\n options: ApiKeyPluginOptions,\n): DevPortalPlugin & ApiIdentityPlugin & ProfileMenuPlugin => {\n const endpoint =\n \"endpoint\" in options ? options.endpoint : DEFAULT_API_KEY_ENDPOINT;\n\n const service =\n \"getKeys\" in options ? options : createDefaultHandler(endpoint);\n\n return {\n getProfileMenuItems: () => [\n {\n label: \"API Keys\",\n path: \"/settings/api-keys\",\n },\n ],\n getIdentities: async (context) => {\n try {\n const keys = await service.getKeys(context);\n\n return keys.map((key) => ({\n authorizeRequest: (request) => {\n request.headers.set(\"Authorization\", `Bearer ${key.key}`);\n return request;\n },\n id: key.id,\n label: key.description ?? key.id,\n }));\n } catch {\n return [];\n }\n },\n getRoutes: (): RouteObject[] => {\n // TODO: Make lazy\n return [\n {\n element: <ProtectedRoute />,\n errorElement: <RouterError />,\n children: [\n {\n path: \"/settings/api-keys\",\n element: <SettingsApiKeys service={service} />,\n },\n {\n path: \"/settings/api-keys/new\",\n element: <CreateApiKey service={service} />,\n },\n ],\n },\n ];\n },\n };\n};\n"],"names":["EyeOff","createLucideIcon","Eye","RotateCw","Trash","invariant","condition","message","provided","ZudokuError","CreateApiKey","service","context","useZudoku","navigate","useNavigate","form","useForm","createKeyMutation","useMutation","description","expiresOn","expiresOnDate","addDaysToDate","jsxs","jsx","data","Input","Select","value","SelectTrigger","SelectValue","SelectContent","SelectGroup","option","SelectItem","Button","Link","days","date","ProtectedRoute","auth","useAuth","Outlet","DeveloperHint","SettingsApiKeys","queryClient","useQueryClient","useSuspenseQuery","deleteKeyMutation","id","rollKeyMutation","Slotlet","cn","key","RevealApiKey","RotateCwIcon","TrashIcon","apiKey","revealed","setRevealed","useState","prev","EyeOffIcon","EyeIcon","DEFAULT_API_KEY_ENDPOINT","createDefaultHandler","endpoint","request","response","keys","apiKeyPlugin","options","RouterError"],"mappings":"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","x_google_ignoreList":[0,1,2,3]}
@@ -6,7 +6,7 @@ const u = (t, e) => Object.entries(t).flatMap(([a, r]) => {
6
6
  return {
7
7
  path: s.at(-1) === "index" ? s.slice(0, -1).join("/") : o,
8
8
  lazy: async () => {
9
- const { MdxPage: i } = await import("./MdxPage-Crlr0GmN.js"), { default: p, ...c } = await r();
9
+ const { MdxPage: i } = await import("./MdxPage-d02krMBw.js"), { default: p, ...c } = await r();
10
10
  return {
11
11
  element: /* @__PURE__ */ m.jsx(
12
12
  i,
@@ -1,9 +1,9 @@
1
1
  import "./jsx-runtime-B6kdoens.js";
2
- import { o as l } from "./index-DUrF63A6.js";
2
+ import { o as l } from "./index-DoIWqOG1.js";
3
3
  import "./urql-DrBfkb92.js";
4
- import "./DevPortalProvider-CTxoCHIT.js";
4
+ import "./ZudokuContext-C3JtXViU.js";
5
5
  import "zudoku/openapi-worker";
6
- import "./Combination-DkycFHkm.js";
6
+ import "./Combination-Djh-LWhb.js";
7
7
  import "./Markdown-B_Gax7at.js";
8
8
  import "./joinPath-VeNuJa7y.js";
9
9
  import "./router-BiRCp01d.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zudoku",
3
- "version": "0.3.0-dev.86",
3
+ "version": "0.3.0-dev.88",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist",
@@ -1,9 +1,9 @@
1
1
  import { useEffect } from "react";
2
2
  import { useSearchParams } from "react-router-dom";
3
- import { useDevPortal } from "../../components/context/DevPortalProvider.js";
3
+ import { useZudoku } from "../../components/context/ZudokuContext.js";
4
4
 
5
5
  export const SignIn = () => {
6
- const context = useDevPortal();
6
+ const context = useZudoku();
7
7
  const [search] = useSearchParams();
8
8
  useEffect(() => {
9
9
  void context.authentication?.signIn({
@@ -1,9 +1,9 @@
1
1
  import { useEffect } from "react";
2
2
  import { useNavigate } from "react-router-dom";
3
- import { useDevPortal } from "../../components/context/DevPortalProvider.js";
3
+ import { useZudoku } from "../../components/context/ZudokuContext.js";
4
4
 
5
5
  export const SignOut = () => {
6
- const context = useDevPortal();
6
+ const context = useZudoku();
7
7
  const navigate = useNavigate();
8
8
  useEffect(() => {
9
9
  void context.authentication?.signOut().then(() => navigate("/"));
@@ -1,8 +1,8 @@
1
1
  import { useEffect } from "react";
2
- import { useDevPortal } from "../../components/context/DevPortalProvider.js";
2
+ import { useZudoku } from "../../components/context/ZudokuContext.js";
3
3
 
4
4
  export const SignUp = () => {
5
- const context = useDevPortal();
5
+ const context = useZudoku();
6
6
  useEffect(() => {
7
7
  void (context.authentication?.signUp() ?? context.authentication?.signIn());
8
8
  }, [context.authentication]);
@@ -1,8 +1,8 @@
1
- import { useDevPortal } from "../components/context/DevPortalProvider.js";
1
+ import { useZudoku } from "../components/context/ZudokuContext.js";
2
2
  import { useAuthState } from "./state.js";
3
3
 
4
4
  export const useAuth = () => {
5
- const { authentication } = useDevPortal();
5
+ const { authentication } = useZudoku();
6
6
  const authState = useAuthState();
7
7
  const isAuthEnabled = typeof authentication !== "undefined";
8
8
 
@@ -8,11 +8,10 @@ import {
8
8
  useContext,
9
9
  useEffect,
10
10
  useMemo,
11
- useRef,
12
11
  useState,
13
12
  } from "react";
14
13
  import { ErrorBoundary } from "react-error-boundary";
15
- import { Outlet, useNavigate, useNavigation } from "react-router-dom";
14
+ import { Outlet, useNavigation } from "react-router-dom";
16
15
  import {
17
16
  DevPortalContext,
18
17
  queryClient,
@@ -27,19 +26,11 @@ import {
27
26
  ComponentsProvider,
28
27
  DEFAULT_COMPONENTS,
29
28
  } from "./context/ComponentsContext.js";
30
- import { DevPortalProvider } from "./context/DevPortalProvider.js";
31
29
  import { ThemeProvider } from "./context/ThemeProvider.js";
32
30
  import { ViewportAnchorProvider } from "./context/ViewportAnchorContext.js";
31
+ import { ZudokuProvider } from "./context/ZudokuProvider.js";
33
32
  import { SlotletProvider } from "./SlotletProvider.js";
34
33
 
35
- export const DevPortalSystemPaths = {
36
- Settings: "/settings",
37
- } as const;
38
-
39
- export type DevPortalPath =
40
- | string
41
- | (typeof DevPortalSystemPaths)[keyof typeof DevPortalSystemPaths];
42
-
43
34
  const DevPortalInner = ({
44
35
  children,
45
36
  ...props
@@ -62,11 +53,8 @@ const DevPortalInner = ({
62
53
  ...props.mdx?.components,
63
54
  };
64
55
  }, [props.mdx?.components, props.plugins]);
65
- const [isInitialized, setIsInitialized] = useState(false);
66
56
  const { stagger } = useContext(StaggeredRenderContext);
67
57
  const [didNavigate, setDidNavigate] = useState(false);
68
- const navigate = useNavigate();
69
- const initRef = useRef<"idle" | "pending" | "done">("idle");
70
58
  const staggeredValue = useMemo(
71
59
  () => (didNavigate ? { stagger: true } : { stagger }),
72
60
  [stagger, didNavigate],
@@ -82,30 +70,16 @@ const DevPortalInner = ({
82
70
 
83
71
  const [devPortalContext] = useState(() => new DevPortalContext(props));
84
72
 
85
- // TODO could be handled more elegantly
86
- useEffect(() => {
87
- if (initRef.current === "pending") return;
88
- initRef.current = "pending";
89
- void devPortalContext.initialize({ navigate }).then(() => {
90
- initRef.current = "done";
91
- setIsInitialized(true);
92
- });
93
- }, [devPortalContext, navigate]);
94
-
95
73
  const heads = props.plugins
96
74
  ?.filter(hasHead)
97
75
  // eslint-disable-next-line react/no-array-index-key
98
76
  .map((plugin, i) => <Fragment key={i}>{plugin.getHead?.()}</Fragment>);
99
77
 
100
- if (!isInitialized) {
101
- return null;
102
- }
103
-
104
78
  return (
105
79
  <QueryClientProvider client={queryClient}>
106
80
  <Helmet>{heads}</Helmet>
107
81
  <StaggeredRenderContext.Provider value={staggeredValue}>
108
- <DevPortalProvider value={devPortalContext}>
82
+ <ZudokuProvider context={devPortalContext}>
109
83
  <MDXProvider components={mdxComponents}>
110
84
  <ThemeProvider>
111
85
  <ComponentsProvider value={components}>
@@ -117,7 +91,7 @@ const DevPortalInner = ({
117
91
  </ComponentsProvider>
118
92
  </ThemeProvider>
119
93
  </MDXProvider>
120
- </DevPortalProvider>
94
+ </ZudokuProvider>
121
95
  </StaggeredRenderContext.Provider>
122
96
  </QueryClientProvider>
123
97
  );
@@ -19,8 +19,8 @@ import {
19
19
  } from "../ui/DropdownMenu.js";
20
20
  import { cn } from "../util/cn.js";
21
21
  import { TopNavigation } from "./TopNavigation.js";
22
- import { useDevPortal } from "./context/DevPortalProvider.js";
23
22
  import { useTheme } from "./context/ThemeContext.js";
23
+ import { useZudoku } from "./context/ZudokuContext.js";
24
24
 
25
25
  const RecursiveMenu = ({ item }: { item: ProfileNavigationItem }) => {
26
26
  return item.children ? (
@@ -46,7 +46,7 @@ export const Header = memo(function HeaderInner() {
46
46
  const [isDark, toggleTheme] = useTheme();
47
47
  const { isAuthenticated, profile, isAuthEnabled } = useAuth();
48
48
  const { pathname } = useLocation();
49
- const context = useDevPortal();
49
+ const context = useZudoku();
50
50
  const { page, plugins } = context;
51
51
 
52
52
  const accountItems = plugins
@@ -4,8 +4,8 @@ import { Outlet, useLocation } from "react-router-dom";
4
4
  import { cn } from "../util/cn.js";
5
5
  import { useScrollToAnchor } from "../util/useScrollToAnchor.js";
6
6
  import { useScrollToTop } from "../util/useScrollToTop.js";
7
- import { useDevPortal } from "./context/DevPortalProvider.js";
8
7
  import { useViewportAnchor } from "./context/ViewportAnchorContext.js";
8
+ import { useZudoku } from "./context/ZudokuContext.js";
9
9
  import { Header } from "./Header.js";
10
10
  import { Sidebar } from "./navigation/Sidebar.js";
11
11
  import { Slotlet } from "./SlotletProvider.js";
@@ -14,7 +14,7 @@ import { Spinner } from "./Spinner.js";
14
14
  export const Layout = ({ children }: { children?: ReactNode }) => {
15
15
  const location = useLocation();
16
16
  const { setActiveAnchor } = useViewportAnchor();
17
- const { meta } = useDevPortal();
17
+ const { meta } = useZudoku();
18
18
 
19
19
  useScrollToAnchor();
20
20
  useScrollToTop();
@@ -1,10 +1,10 @@
1
1
  import { cx } from "class-variance-authority";
2
2
  import { NavLink } from "react-router-dom";
3
3
 
4
- import { useDevPortal } from "./context/DevPortalProvider.js";
4
+ import { useZudoku } from "./context/ZudokuContext.js";
5
5
 
6
6
  export const TopNavigation = () => {
7
- const { topNavigation } = useDevPortal();
7
+ const { topNavigation } = useZudoku();
8
8
 
9
9
  // Hide top nav if there is only one item
10
10
  if (topNavigation.length <= 1) {
@@ -3,14 +3,12 @@ import { createContext, useContext } from "react";
3
3
  import { useLocation } from "react-router-dom";
4
4
  import { DevPortalContext } from "../../core/DevPortalContext.js";
5
5
 
6
- const DevPortalReactContext = createContext<DevPortalContext | undefined>(
6
+ export const ZudokuReactContext = createContext<DevPortalContext | undefined>(
7
7
  undefined,
8
8
  );
9
9
 
10
- export const DevPortalProvider = DevPortalReactContext.Provider;
11
-
12
- export const useDevPortal = () => {
13
- const context = useContext(DevPortalReactContext);
10
+ export const useZudoku = () => {
11
+ const context = useContext(ZudokuReactContext);
14
12
 
15
13
  if (!context) {
16
14
  throw new Error("useDevPortal must be used within a DevPortalProvider.");
@@ -20,7 +18,7 @@ export const useDevPortal = () => {
20
18
  };
21
19
 
22
20
  export const useApiIdentities = () => {
23
- const { getApiIdentities } = useDevPortal();
21
+ const { getApiIdentities } = useZudoku();
24
22
  return useQuery({
25
23
  queryFn: getApiIdentities,
26
24
  queryKey: ["api-identities"],
@@ -28,7 +26,7 @@ export const useApiIdentities = () => {
28
26
  };
29
27
 
30
28
  export const useTopNavigationItem = () => {
31
- const { topNavigation } = useDevPortal();
29
+ const { topNavigation } = useZudoku();
32
30
  const location = useLocation();
33
31
 
34
32
  const firstPart = location.pathname.split("/").at(1);
@@ -38,14 +36,14 @@ export const useTopNavigationItem = () => {
38
36
  };
39
37
 
40
38
  export const useNavigation = () => {
41
- const { getPluginNavigation, sidebars } = useDevPortal();
39
+ const { getPluginSidebar, sidebars } = useZudoku();
42
40
  const navItem = useTopNavigationItem();
43
41
  const path = navItem?.id;
44
42
  const currentSidebar = path ? sidebars[path] ?? [] : [];
45
43
 
46
44
  return useSuspenseQuery({
47
45
  queryFn: async () => {
48
- const pluginSidebar = path ? await getPluginNavigation(path) : [];
46
+ const pluginSidebar = path ? await getPluginSidebar(path) : [];
49
47
 
50
48
  return {
51
49
  items: [...currentSidebar, ...pluginSidebar],
@@ -0,0 +1,26 @@
1
+ import { useSuspenseQuery } from "@tanstack/react-query";
2
+ import type { PropsWithChildren } from "react";
3
+ import { useNavigate } from "react-router-dom";
4
+ import { DevPortalContext } from "../../core/DevPortalContext.js";
5
+ import { ZudokuReactContext } from "./ZudokuContext.js";
6
+
7
+ export const ZudokuProvider = ({
8
+ children,
9
+ context,
10
+ }: PropsWithChildren<{ context: DevPortalContext }>) => {
11
+ const navigate = useNavigate();
12
+
13
+ useSuspenseQuery({
14
+ queryFn: async () => {
15
+ await context.initialize({ navigate });
16
+ return true;
17
+ },
18
+ queryKey: ["zudoku-initialize"],
19
+ });
20
+
21
+ return (
22
+ <ZudokuReactContext.Provider value={context}>
23
+ {children}
24
+ </ZudokuReactContext.Provider>
25
+ );
26
+ };
@@ -1,6 +1,6 @@
1
1
  import { useRef } from "react";
2
2
 
3
- import { useNavigation } from "../context/DevPortalProvider.js";
3
+ import { useNavigation } from "../context/ZudokuContext.js";
4
4
  import { Slotlet } from "../SlotletProvider.js";
5
5
  import { SidebarItem } from "./SidebarItem.js";
6
6
  import { SidebarWrapper } from "./SidebarWrapper.js";
@@ -2,10 +2,10 @@ import * as Collapsible from "@radix-ui/react-collapsible";
2
2
  import { ChevronRightIcon } from "lucide-react";
3
3
  import { useEffect, useState } from "react";
4
4
  import { NavLink } from "react-router-dom";
5
- import type { ResolvedSidebarItemCategory } from "../../../config/validators/ResolvedSidebarSchema.js";
5
+ import type { SidebarItemCategory } from "../../../config/validators/SidebarSchema.js";
6
6
  import { cn } from "../../util/cn.js";
7
7
  import { joinPath } from "../../util/joinPath.js";
8
- import { useTopNavigationItem } from "../context/DevPortalProvider.js";
8
+ import { useTopNavigationItem } from "../context/ZudokuContext.js";
9
9
  import { navigationListItem, SidebarItem } from "./SidebarItem.js";
10
10
  import { useIsCategoryOpen } from "./utils.js";
11
11
 
@@ -13,7 +13,7 @@ export const SidebarCategory = ({
13
13
  category,
14
14
  level,
15
15
  }: {
16
- category: ResolvedSidebarItemCategory;
16
+ category: SidebarItemCategory;
17
17
  level: number;
18
18
  }) => {
19
19
  const topNavItem = useTopNavigationItem();
@@ -2,12 +2,12 @@ import { cva } from "class-variance-authority";
2
2
  import { ExternalLinkIcon } from "lucide-react";
3
3
  import { NavLink } from "react-router-dom";
4
4
 
5
- import type { ResolvedSidebarItem } from "../../../config/validators/ResolvedSidebarSchema.js";
5
+ import type { SidebarItem as SidebarItemType } from "../../../config/validators/SidebarSchema.js";
6
6
  import { cn } from "../../util/cn.js";
7
7
  import { joinPath } from "../../util/joinPath.js";
8
8
  import { AnchorLink } from "../AnchorLink.js";
9
- import { useTopNavigationItem } from "../context/DevPortalProvider.js";
10
9
  import { useViewportAnchor } from "../context/ViewportAnchorContext.js";
10
+ import { useTopNavigationItem } from "../context/ZudokuContext.js";
11
11
  import { SidebarBadge } from "./SidebarBadge.js";
12
12
  import { SidebarCategory } from "./SidebarCategory.js";
13
13
 
@@ -36,7 +36,7 @@ export const SidebarItem = ({
36
36
  item,
37
37
  level = 0,
38
38
  }: {
39
- item: ResolvedSidebarItem;
39
+ item: SidebarItemType;
40
40
  basePath?: string;
41
41
  level?: number;
42
42
  }) => {
@@ -74,7 +74,7 @@ export const SidebarItem = ({
74
74
  {item.label}
75
75
  {item.badge && <SidebarBadge {...item.badge} />}
76
76
  </AnchorLink>
77
- ) : (
77
+ ) : item.href.startsWith("http") ? (
78
78
  <a
79
79
  className={cn(
80
80
  navigationListItem({ isTopLevel: level === 0 }),
@@ -91,6 +91,10 @@ export const SidebarItem = ({
91
91
  <ExternalLinkIcon className="inline ml-1" size={12} />
92
92
  </span>
93
93
  </a>
94
+ ) : (
95
+ <NavLink className={cn(navigationListItem({}), "block")} to={item.href}>
96
+ {item.label}
97
+ </NavLink>
94
98
  );
95
99
  }
96
100
  };