zudoku 0.3.0-dev.67 → 0.3.0-dev.69
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app/main.js +1 -0
- package/dist/app/main.js.map +1 -1
- package/dist/config/validators/validate.d.ts +3 -0
- package/dist/config/validators/validate.js +1 -0
- package/dist/config/validators/validate.js.map +1 -1
- package/dist/lib/components/DevPortal.d.ts +1 -0
- package/dist/lib/components/DevPortal.js +3 -1
- package/dist/lib/components/DevPortal.js.map +1 -1
- package/dist/lib/components/Layout.js +2 -1
- package/dist/lib/components/Layout.js.map +1 -1
- package/dist/lib/components/SlotletProvider.d.ts +9 -0
- package/dist/lib/components/SlotletProvider.js +11 -0
- package/dist/lib/components/SlotletProvider.js.map +1 -0
- package/dist/lib/components/navigation/SideNavigation.js +3 -2
- package/dist/lib/components/navigation/SideNavigation.js.map +1 -1
- package/dist/lib/core/DevPortalContext.d.ts +2 -0
- package/dist/lib/core/DevPortalContext.js.map +1 -1
- package/dist/lib/plugins/api-keys/SettingsApiKeys.js +2 -1
- package/dist/lib/plugins/api-keys/SettingsApiKeys.js.map +1 -1
- package/dist/lib/plugins/api-keys/index.js +1 -1
- package/dist/lib/plugins/api-keys/index.js.map +1 -1
- package/dist/lib/plugins/openapi/StaggeredRender.js +2 -2
- package/dist/lib/plugins/openapi/StaggeredRender.js.map +1 -1
- package/dist/lib/plugins/openapi/playground/Playground.js +1 -1
- package/dist/lib/plugins/openapi/playground/Playground.js.map +1 -1
- package/dist/lib/plugins/openapi/playground/QueryParams.js +1 -1
- package/dist/lib/plugins/openapi/playground/QueryParams.js.map +1 -1
- package/dist/lib/util/invariant.d.ts +6 -0
- package/dist/lib/util/invariant.js +21 -0
- package/dist/lib/util/invariant.js.map +1 -0
- package/dist/lib/util/requestIdleCallbackPolyfill.d.ts +1 -0
- package/dist/lib/util/requestIdleCallbackPolyfill.js +7 -0
- package/dist/lib/util/requestIdleCallbackPolyfill.js.map +1 -0
- package/lib/{OperationList-C1YlOjB7.js → OperationList-i6FGZUu4.js} +6 -5
- package/lib/{OperationList-C1YlOjB7.js.map → OperationList-i6FGZUu4.js.map} +1 -1
- package/lib/{hook-Cz5jddRs.js → SlotletProvider-CpNYmq6S.js} +42 -33
- package/lib/SlotletProvider-CpNYmq6S.js.map +1 -0
- package/lib/{Spinner-DyDcSKPz.js → Spinner-BBPlEab_.js} +21 -21
- package/lib/Spinner-BBPlEab_.js.map +1 -0
- package/lib/{index-3RQC9Hni.js → index-DT-cf5tv.js} +2 -2
- package/lib/{index-3RQC9Hni.js.map → index-DT-cf5tv.js.map} +1 -1
- package/lib/zudoku.components.js +549 -539
- package/lib/zudoku.components.js.map +1 -1
- package/lib/zudoku.plugin-api-keys.js +49 -46
- package/lib/zudoku.plugin-api-keys.js.map +1 -1
- package/lib/zudoku.plugin-openapi.js +1 -1
- package/package.json +1 -2
- package/src/app/main.tsx +1 -0
- package/src/lib/components/DevPortal.tsx +5 -1
- package/src/lib/components/Layout.tsx +3 -0
- package/src/lib/components/SlotletProvider.tsx +25 -0
- package/src/lib/components/navigation/SideNavigation.tsx +3 -0
- package/src/lib/core/DevPortalContext.ts +2 -0
- package/src/lib/plugins/api-keys/SettingsApiKeys.tsx +3 -0
- package/src/lib/plugins/api-keys/index.tsx +1 -1
- package/src/lib/plugins/openapi/StaggeredRender.tsx +2 -2
- package/src/lib/plugins/openapi/playground/Playground.tsx +2 -1
- package/src/lib/plugins/openapi/playground/QueryParams.tsx +1 -3
- package/src/lib/util/invariant.ts +26 -0
- package/src/lib/util/requestIdleCallbackPolyfill.ts +6 -0
- package/lib/Spinner-DyDcSKPz.js.map +0 -1
- package/lib/hook-Cz5jddRs.js.map +0 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { b as
|
|
2
|
-
import { u as g, R as v } from "./
|
|
3
|
-
import { u as w, a as
|
|
4
|
-
import { c as l, L as
|
|
5
|
-
import { u as
|
|
6
|
-
import { B as
|
|
1
|
+
import { b as y, j as e, O as f } from "./jsx-runtime-BIr0WBt_.js";
|
|
2
|
+
import { u as j, a as g, R as v } from "./SlotletProvider-CpNYmq6S.js";
|
|
3
|
+
import { u as w, a as h, I as k, S as b, b as K, c as N, d as A, e as E, f as x } from "./Input-DdAxw3vC.js";
|
|
4
|
+
import { c as l, L as u, a as S } from "./Markdown-DsCvZnhw.js";
|
|
5
|
+
import { u as p, x as I, y as P } from "./DevPortalProvider-BBhQ8kgI.js";
|
|
6
|
+
import { B as o, p as C } from "./Combination-Cq0UkOXq.js";
|
|
7
7
|
import { useState as D } from "react";
|
|
8
8
|
/**
|
|
9
9
|
* @license lucide-react v0.378.0 - ISC
|
|
@@ -57,27 +57,29 @@ const z = l("Trash", [
|
|
|
57
57
|
["path", { d: "M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6", key: "4alrt4" }],
|
|
58
58
|
["path", { d: "M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2", key: "v07s0e" }]
|
|
59
59
|
]);
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
60
|
+
function d(t, n) {
|
|
61
|
+
if (t)
|
|
62
|
+
return;
|
|
63
|
+
const r = typeof n == "function" ? n() : n;
|
|
64
|
+
throw new M(r ?? "Invariant failed");
|
|
65
|
+
}
|
|
66
|
+
class M extends Error {
|
|
67
|
+
constructor(n) {
|
|
68
|
+
super(n), this.name = "ZudokuError";
|
|
67
69
|
}
|
|
68
70
|
}
|
|
69
71
|
const L = ({ service: t }) => {
|
|
70
|
-
const n =
|
|
72
|
+
const n = p(), r = y(), a = w({
|
|
71
73
|
defaultValues: {
|
|
72
74
|
expiresOn: "30"
|
|
73
75
|
}
|
|
74
|
-
}), i =
|
|
75
|
-
mutationFn: ({ description: s, expiresOn:
|
|
76
|
+
}), i = h({
|
|
77
|
+
mutationFn: ({ description: s, expiresOn: c }) => {
|
|
76
78
|
if (!t.createKey)
|
|
77
79
|
throw new Error("deleteKey not implemented");
|
|
78
|
-
const
|
|
80
|
+
const m = c !== "never" ? T(Number(c)) : void 0;
|
|
79
81
|
return t.createKey(
|
|
80
|
-
{ description: s, expiresOn:
|
|
82
|
+
{ description: s, expiresOn: m },
|
|
81
83
|
n
|
|
82
84
|
);
|
|
83
85
|
},
|
|
@@ -91,28 +93,28 @@ const L = ({ service: t }) => {
|
|
|
91
93
|
onSubmit: a.handleSubmit((s) => i.mutate(s)),
|
|
92
94
|
children: /* @__PURE__ */ e.jsxs("div", { className: "flex gap-2 flex-col", children: [
|
|
93
95
|
"Note",
|
|
94
|
-
/* @__PURE__ */ e.jsx(
|
|
96
|
+
/* @__PURE__ */ e.jsx(k, { ...a.register("description") }),
|
|
95
97
|
"Expiration",
|
|
96
98
|
/* @__PURE__ */ e.jsxs(
|
|
97
|
-
|
|
99
|
+
b,
|
|
98
100
|
{
|
|
99
101
|
onValueChange: (s) => a.setValue("expiresOn", s),
|
|
100
102
|
defaultValue: a.getValues("expiresOn"),
|
|
101
103
|
children: [
|
|
102
104
|
/* @__PURE__ */ e.jsx(K, { children: /* @__PURE__ */ e.jsx(N, {}) }),
|
|
103
|
-
/* @__PURE__ */ e.jsx(
|
|
104
|
-
[7, 30, 60, 90].map((s) => /* @__PURE__ */ e.jsxs(
|
|
105
|
+
/* @__PURE__ */ e.jsx(A, { children: /* @__PURE__ */ e.jsxs(E, { children: [
|
|
106
|
+
[7, 30, 60, 90].map((s) => /* @__PURE__ */ e.jsxs(x, { value: String(s), children: [
|
|
105
107
|
s,
|
|
106
108
|
" days"
|
|
107
109
|
] }, s)),
|
|
108
|
-
/* @__PURE__ */ e.jsx(
|
|
110
|
+
/* @__PURE__ */ e.jsx(x, { value: "never", children: "Never" })
|
|
109
111
|
] }) })
|
|
110
112
|
]
|
|
111
113
|
}
|
|
112
114
|
),
|
|
113
115
|
/* @__PURE__ */ e.jsxs("div", { className: "flex gap-2", children: [
|
|
114
|
-
/* @__PURE__ */ e.jsx(
|
|
115
|
-
/* @__PURE__ */ e.jsx(
|
|
116
|
+
/* @__PURE__ */ e.jsx(o, { children: "Generate Key" }),
|
|
117
|
+
/* @__PURE__ */ e.jsx(o, { variant: "outline", asChild: !0, children: /* @__PURE__ */ e.jsx(u, { to: "/settings/api-keys/", children: "Cancel" }) })
|
|
116
118
|
] })
|
|
117
119
|
] })
|
|
118
120
|
}
|
|
@@ -121,22 +123,22 @@ const L = ({ service: t }) => {
|
|
|
121
123
|
}, T = (t) => {
|
|
122
124
|
const n = /* @__PURE__ */ new Date();
|
|
123
125
|
return n.setDate(n.getDate() + t), n.toISOString();
|
|
124
|
-
},
|
|
125
|
-
const t =
|
|
126
|
-
return t.isAuthEnabled && t.isPending ? null : t.isAuthenticated ? /* @__PURE__ */ e.jsx(
|
|
126
|
+
}, F = () => {
|
|
127
|
+
const t = j();
|
|
128
|
+
return t.isAuthEnabled && t.isPending ? null : t.isAuthenticated ? /* @__PURE__ */ e.jsx(f, {}) : t.isAuthEnabled ? /* @__PURE__ */ e.jsxs("div", { className: "flex flex-col justify-center gap-2 items-center h-1/2", children: [
|
|
127
129
|
"Please login first to view this page",
|
|
128
|
-
/* @__PURE__ */ e.jsx(
|
|
130
|
+
/* @__PURE__ */ e.jsx(o, { onClick: () => t.login(), children: "Login" })
|
|
129
131
|
] }) : /* @__PURE__ */ e.jsx("div", { className: "flex flex-col justify-center gap-2 items-center h-1/2", children: /* @__PURE__ */ e.jsxs(C, { className: "max-w-[600px]", children: [
|
|
130
132
|
"Authentication needs to be enabled for API keys to work. Enable it in your Zudoku configuration under ",
|
|
131
133
|
/* @__PURE__ */ e.jsx("code", { children: "authentication" }),
|
|
132
134
|
"."
|
|
133
135
|
] }) });
|
|
134
|
-
},
|
|
135
|
-
const n =
|
|
136
|
+
}, V = ({ service: t }) => {
|
|
137
|
+
const n = p(), r = I(), { data: a } = P({
|
|
136
138
|
queryFn: () => t.getKeys(n),
|
|
137
139
|
queryKey: ["api-keys"],
|
|
138
140
|
retry: !1
|
|
139
|
-
}), i =
|
|
141
|
+
}), i = h({
|
|
140
142
|
mutationFn: (s) => {
|
|
141
143
|
if (!t.deleteKey)
|
|
142
144
|
throw new Error("deleteKey not implemented");
|
|
@@ -149,19 +151,20 @@ const L = ({ service: t }) => {
|
|
|
149
151
|
return /* @__PURE__ */ e.jsxs("div", { className: "max-w-screen-lg h-full pt-[--padding-content-top] pb-[--padding-content-bottom]", children: [
|
|
150
152
|
/* @__PURE__ */ e.jsxs("div", { className: "flex justify-between mb-4 border-b pb-3", children: [
|
|
151
153
|
/* @__PURE__ */ e.jsx("h1", { className: "font-medium text-2xl", children: "API Keys" }),
|
|
152
|
-
t.createKey && /* @__PURE__ */ e.jsx(
|
|
154
|
+
t.createKey && /* @__PURE__ */ e.jsx(o, { asChild: !0, children: /* @__PURE__ */ e.jsx(u, { to: "/settings/api-keys/new", children: "Create API Key" }) })
|
|
153
155
|
] }),
|
|
156
|
+
/* @__PURE__ */ e.jsx(g, { name: "api-keys-list-page-before-keys" }),
|
|
154
157
|
a.length === 0 ? /* @__PURE__ */ e.jsxs("div", { className: "flex flex-col justify-center gap-4 items-center h-1/2 my-8", children: [
|
|
155
158
|
/* @__PURE__ */ e.jsxs("div", { className: "text-center", children: [
|
|
156
159
|
"No API keys created yet.",
|
|
157
160
|
/* @__PURE__ */ e.jsx("br", {}),
|
|
158
161
|
"Get started and create the first one now"
|
|
159
162
|
] }),
|
|
160
|
-
t.createKey && /* @__PURE__ */ e.jsx(
|
|
163
|
+
t.createKey && /* @__PURE__ */ e.jsx(o, { asChild: !0, children: /* @__PURE__ */ e.jsx(u, { to: "/settings/api-keys/new", children: "Create API Key" }) })
|
|
161
164
|
] }) : /* @__PURE__ */ e.jsx(
|
|
162
165
|
"ul",
|
|
163
166
|
{
|
|
164
|
-
className:
|
|
167
|
+
className: S(
|
|
165
168
|
"grid grid-cols-1 rounded border",
|
|
166
169
|
"lg:grid-cols-[minmax(250px,min-content)_1fr_min-content]"
|
|
167
170
|
),
|
|
@@ -185,9 +188,9 @@ const L = ({ service: t }) => {
|
|
|
185
188
|
] }),
|
|
186
189
|
/* @__PURE__ */ e.jsx("div", { className: "items-center flex lg:justify-center", children: /* @__PURE__ */ e.jsx(_, { apiKey: s.key }) }),
|
|
187
190
|
/* @__PURE__ */ e.jsxs("div", { className: "flex gap-2", children: [
|
|
188
|
-
t.rollKey && /* @__PURE__ */ e.jsx(
|
|
191
|
+
t.rollKey && /* @__PURE__ */ e.jsx(o, { size: "icon", children: /* @__PURE__ */ e.jsx(q, { size: 16 }) }),
|
|
189
192
|
t.deleteKey && /* @__PURE__ */ e.jsx(
|
|
190
|
-
|
|
193
|
+
o,
|
|
191
194
|
{
|
|
192
195
|
variant: "ghost",
|
|
193
196
|
size: "icon",
|
|
@@ -217,7 +220,7 @@ const L = ({ service: t }) => {
|
|
|
217
220
|
}
|
|
218
221
|
),
|
|
219
222
|
/* @__PURE__ */ e.jsx(
|
|
220
|
-
|
|
223
|
+
o,
|
|
221
224
|
{
|
|
222
225
|
variant: "outline",
|
|
223
226
|
onClick: () => r((a) => !a),
|
|
@@ -226,14 +229,14 @@ const L = ({ service: t }) => {
|
|
|
226
229
|
}
|
|
227
230
|
)
|
|
228
231
|
] });
|
|
229
|
-
},
|
|
232
|
+
}, Z = "https://zudoku-rewiringamerica-main-ef9c9c0.d2.zuplo.dev", B = (t) => ({
|
|
230
233
|
deleteKey: async (n, r) => {
|
|
231
234
|
const a = new Request(t + `/v1/developer/api-keys/${n}`, {
|
|
232
235
|
method: "DELETE"
|
|
233
236
|
});
|
|
234
237
|
await r.signRequest(a);
|
|
235
238
|
const i = await fetch(a);
|
|
236
|
-
|
|
239
|
+
d(i.ok, "Failed to delete API key");
|
|
237
240
|
},
|
|
238
241
|
createKey: async (n, r) => {
|
|
239
242
|
const a = new Request(t + "/v1/developer/api-keys", {
|
|
@@ -245,16 +248,16 @@ const L = ({ service: t }) => {
|
|
|
245
248
|
});
|
|
246
249
|
await r.signRequest(a);
|
|
247
250
|
const i = await fetch(a);
|
|
248
|
-
|
|
251
|
+
d(i.ok, "Failed to create API key");
|
|
249
252
|
},
|
|
250
253
|
getKeys: async (n) => {
|
|
251
254
|
const r = new Request(t + "/v1/developer/api-keys");
|
|
252
255
|
await n.signRequest(r);
|
|
253
256
|
const a = await fetch(r);
|
|
254
|
-
return
|
|
257
|
+
return d(a.ok, "Failed to fetch API keys"), await a.json();
|
|
255
258
|
}
|
|
256
259
|
}), W = (t) => {
|
|
257
|
-
const n = "endpoint" in t ? t.endpoint :
|
|
260
|
+
const n = "endpoint" in t ? t.endpoint : Z, r = "getKeys" in t ? t : B(n);
|
|
258
261
|
return {
|
|
259
262
|
getProfileMenuItems: () => [
|
|
260
263
|
{
|
|
@@ -265,7 +268,7 @@ const L = ({ service: t }) => {
|
|
|
265
268
|
getIdentities: async (a) => {
|
|
266
269
|
try {
|
|
267
270
|
return (await r.getKeys(a)).map((s) => ({
|
|
268
|
-
authorizeRequest: (
|
|
271
|
+
authorizeRequest: (c) => (c.headers.set("Authorization", `Bearer ${s.key}`), c),
|
|
269
272
|
id: s.id,
|
|
270
273
|
label: s.description ?? s.id
|
|
271
274
|
}));
|
|
@@ -275,12 +278,12 @@ const L = ({ service: t }) => {
|
|
|
275
278
|
},
|
|
276
279
|
getRoutes: () => [
|
|
277
280
|
{
|
|
278
|
-
element: /* @__PURE__ */ e.jsx(
|
|
281
|
+
element: /* @__PURE__ */ e.jsx(F, {}),
|
|
279
282
|
errorElement: /* @__PURE__ */ e.jsx(v, {}),
|
|
280
283
|
children: [
|
|
281
284
|
{
|
|
282
285
|
path: "/settings/api-keys",
|
|
283
|
-
element: /* @__PURE__ */ e.jsx(
|
|
286
|
+
element: /* @__PURE__ */ e.jsx(V, { service: r })
|
|
284
287
|
},
|
|
285
288
|
{
|
|
286
289
|
path: "/settings/api-keys/new",
|
|
@@ -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","../../../node_modules/.pnpm/tiny-invariant@1.3.3/node_modules/tiny-invariant/dist/esm/tiny-invariant.js","../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","var isProduction = process.env.NODE_ENV === 'production';\nvar prefix = 'Invariant failed';\nfunction invariant(condition, message) {\n if (condition) {\n return;\n }\n if (isProduction) {\n throw new Error(prefix);\n }\n var provided = typeof message === 'function' ? message() : message;\n var value = provided ? \"\".concat(prefix, \": \").concat(provided) : prefix;\n throw new Error(value);\n}\n\nexport { invariant as default };\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 { 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 return (\n <div className=\"max-w-screen-lg h-full pt-[--padding-content-top] pb-[--padding-content-bottom]\">\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 {data.length === 0 ? (\n <div className=\"flex flex-col justify-center gap-4 items-center h-1/2 my-8\">\n <div className=\"text-center\">\n No API keys created yet.\n <br />\n Get started and create the first one now\n </div>\n {service.createKey && (\n <Button asChild>\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 size=\"icon\">\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 <input\n className=\"border rounded bg-gray-100 dark:bg-gray-950 p-1 font-mono max-w-min\"\n value={revealed ? apiKey : \"•\".repeat(apiKey.length)}\n />\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 invariant from \"tiny-invariant\";\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 { 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 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","isProduction","prefix","invariant","condition","message","provided","value","CreateApiKey","service","context","useDevPortal","navigate","useNavigate","form","useForm","createKeyMutation","useMutation","description","expiresOn","expiresOnDate","addDaysToDate","jsxs","jsx","data","Input","Select","SelectTrigger","SelectValue","SelectContent","SelectGroup","option","SelectItem","Button","Link","days","date","ProtectedRoute","auth","useAuth","Outlet","DeveloperHint","SettingsApiKeys","queryClient","useQueryClient","useSuspenseQuery","deleteKeyMutation","id","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,4]}
|
|
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 return (\n <div className=\"max-w-screen-lg h-full pt-[--padding-content-top] pb-[--padding-content-bottom]\">\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 h-1/2 my-8\">\n <div className=\"text-center\">\n No API keys created yet.\n <br />\n Get started and create the first one now\n </div>\n {service.createKey && (\n <Button asChild>\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 size=\"icon\">\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 <input\n className=\"border rounded bg-gray-100 dark:bg-gray-950 p-1 font-mono max-w-min\"\n value={revealed ? apiKey : \"•\".repeat(apiKey.length)}\n />\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 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","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]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zudoku",
|
|
3
|
-
"version": "0.3.0-dev.
|
|
3
|
+
"version": "0.3.0-dev.69",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -135,7 +135,6 @@
|
|
|
135
135
|
"strip-ansi": "7.1.0",
|
|
136
136
|
"tailwind-merge": "2.3.0",
|
|
137
137
|
"tailwindcss": "3.4.4",
|
|
138
|
-
"tiny-invariant": "1.3.3",
|
|
139
138
|
"ulidx": "^2.3.0",
|
|
140
139
|
"unist-util-visit": "5.0.0",
|
|
141
140
|
"urql": "4.1.0",
|
package/src/app/main.tsx
CHANGED
|
@@ -21,6 +21,7 @@ import { hasHead } from "../core/plugins.js";
|
|
|
21
21
|
import { TopLevelError } from "../errors/TopLevelError.js";
|
|
22
22
|
import { StaggeredRenderContext } from "../plugins/openapi/StaggeredRender.js";
|
|
23
23
|
import { MdxComponents } from "../util/MdxComponents.js";
|
|
24
|
+
import "../util/requestIdleCallbackPolyfill.js";
|
|
24
25
|
import {
|
|
25
26
|
ComponentsProvider,
|
|
26
27
|
DEFAULT_COMPONENTS,
|
|
@@ -28,6 +29,7 @@ import {
|
|
|
28
29
|
import { DevPortalProvider } from "./context/DevPortalProvider.js";
|
|
29
30
|
import { ThemeProvider } from "./context/ThemeContext.js";
|
|
30
31
|
import { ViewportAnchorProvider } from "./context/ViewportAnchorContext.js";
|
|
32
|
+
import { SlotletProvider } from "./SlotletProvider.js";
|
|
31
33
|
|
|
32
34
|
export const DevPortalSystemPaths = {
|
|
33
35
|
Settings: "/settings",
|
|
@@ -84,7 +86,9 @@ const DevPortalInner = ({
|
|
|
84
86
|
<MDXProvider components={mdxComponents}>
|
|
85
87
|
<ThemeProvider>
|
|
86
88
|
<ComponentsProvider value={components}>
|
|
87
|
-
<
|
|
89
|
+
<SlotletProvider slotlets={props.slotlets}>
|
|
90
|
+
<ViewportAnchorProvider>{children}</ViewportAnchorProvider>
|
|
91
|
+
</SlotletProvider>
|
|
88
92
|
</ComponentsProvider>
|
|
89
93
|
</ThemeProvider>
|
|
90
94
|
</MDXProvider>
|
|
@@ -8,6 +8,7 @@ import { useDevPortal } from "./context/DevPortalProvider.js";
|
|
|
8
8
|
import { useViewportAnchor } from "./context/ViewportAnchorContext.js";
|
|
9
9
|
import { Header } from "./Header.js";
|
|
10
10
|
import { SideNavigation } from "./navigation/SideNavigation.js";
|
|
11
|
+
import { Slotlet } from "./SlotletProvider.js";
|
|
11
12
|
import { Spinner } from "./Spinner.js";
|
|
12
13
|
|
|
13
14
|
export const Layout = ({ children }: { children?: ReactNode }) => {
|
|
@@ -55,7 +56,9 @@ export const Layout = ({ children }: { children?: ReactNode }) => {
|
|
|
55
56
|
"lg:peer-data-[navigation=true]:translate-x-[--side-nav-width] lg:peer-data-[navigation=true]:pl-12",
|
|
56
57
|
)}
|
|
57
58
|
>
|
|
59
|
+
<Slotlet name="zudoku-before-content" />
|
|
58
60
|
{children ?? <Outlet />}
|
|
61
|
+
<Slotlet name="zudoku-after-content" />
|
|
59
62
|
</main>
|
|
60
63
|
</Suspense>
|
|
61
64
|
</div>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React, { ReactNode, useContext } from "react";
|
|
2
|
+
|
|
3
|
+
export type Slotlets = Record<string, ReactNode>;
|
|
4
|
+
|
|
5
|
+
const SlotletContext = React.createContext<Slotlets | undefined>({});
|
|
6
|
+
|
|
7
|
+
export const SlotletProvider = ({
|
|
8
|
+
slotlets,
|
|
9
|
+
children,
|
|
10
|
+
}: {
|
|
11
|
+
children: ReactNode;
|
|
12
|
+
slotlets?: Slotlets;
|
|
13
|
+
}) => {
|
|
14
|
+
return (
|
|
15
|
+
<SlotletContext.Provider value={slotlets}>
|
|
16
|
+
{children}
|
|
17
|
+
</SlotletContext.Provider>
|
|
18
|
+
);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const Slotlet = ({ name }: { name: string }) => {
|
|
22
|
+
const x = useContext(SlotletContext);
|
|
23
|
+
|
|
24
|
+
return x?.[name];
|
|
25
|
+
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useRef } from "react";
|
|
2
2
|
|
|
3
3
|
import { useNavigation } from "../context/DevPortalProvider.js";
|
|
4
|
+
import { Slotlet } from "../SlotletProvider.js";
|
|
4
5
|
import { SideNavigationCategory } from "./SideNavigationCategory.js";
|
|
5
6
|
import { SideNavigationWrapper } from "./SideNavigationWrapper.js";
|
|
6
7
|
|
|
@@ -13,9 +14,11 @@ export const SideNavigation = () => {
|
|
|
13
14
|
ref={navRef}
|
|
14
15
|
pushMainContent={navigation.data.items.length > 0}
|
|
15
16
|
>
|
|
17
|
+
<Slotlet name="zudoku-before-navigation" />
|
|
16
18
|
{navigation.data.items.map((category) => (
|
|
17
19
|
<SideNavigationCategory key={category.label} category={category} />
|
|
18
20
|
))}
|
|
21
|
+
<Slotlet name="zudoku-after-navigation" />
|
|
19
22
|
</SideNavigationWrapper>
|
|
20
23
|
);
|
|
21
24
|
};
|
|
@@ -3,6 +3,7 @@ import { type ReactNode } from "react";
|
|
|
3
3
|
import { type AuthenticationProvider } from "../authentication/authentication.js";
|
|
4
4
|
import type { ComponentsContextType } from "../components/context/ComponentsContext.js";
|
|
5
5
|
import { type DevPortalPath } from "../components/DevPortal.js";
|
|
6
|
+
import { Slotlets } from "../components/SlotletProvider.js";
|
|
6
7
|
import type { MdxComponentsType } from "../util/MdxComponents.js";
|
|
7
8
|
import {
|
|
8
9
|
type DevPortalPlugin,
|
|
@@ -90,6 +91,7 @@ export type ZudokuContextOptions = {
|
|
|
90
91
|
authentication?: AuthenticationProvider;
|
|
91
92
|
navigation: NavigationItem[];
|
|
92
93
|
plugins?: DevPortalPlugin[];
|
|
94
|
+
slotlets?: Slotlets;
|
|
93
95
|
mdx?: {
|
|
94
96
|
components?: MdxComponentsType;
|
|
95
97
|
};
|
|
@@ -7,6 +7,7 @@ import { EyeIcon, EyeOffIcon, RotateCwIcon, TrashIcon } from "lucide-react";
|
|
|
7
7
|
import { useState } from "react";
|
|
8
8
|
import { Link } from "react-router-dom";
|
|
9
9
|
import { useDevPortal } from "../../components/context/DevPortalProvider.js";
|
|
10
|
+
import { Slotlet } from "../../components/SlotletProvider.js";
|
|
10
11
|
import { Button } from "../../ui/Button.js";
|
|
11
12
|
import { cn } from "../../util/cn.js";
|
|
12
13
|
import { ApiKeyService } from "./index.js";
|
|
@@ -44,6 +45,8 @@ export const SettingsApiKeys = ({ service }: { service: ApiKeyService }) => {
|
|
|
44
45
|
)}
|
|
45
46
|
</div>
|
|
46
47
|
|
|
48
|
+
<Slotlet name="api-keys-list-page-before-keys" />
|
|
49
|
+
|
|
47
50
|
{data.length === 0 ? (
|
|
48
51
|
<div className="flex flex-col justify-center gap-4 items-center h-1/2 my-8">
|
|
49
52
|
<div className="text-center">
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { type RouteObject } from "react-router-dom";
|
|
2
|
-
import invariant from "tiny-invariant";
|
|
3
2
|
import { DevPortalContext } from "../../core/DevPortalContext.js";
|
|
4
3
|
import {
|
|
5
4
|
type ApiIdentityPlugin,
|
|
@@ -7,6 +6,7 @@ import {
|
|
|
7
6
|
ProfileMenuPlugin,
|
|
8
7
|
} from "../../core/plugins.js";
|
|
9
8
|
import { RouterError } from "../../errors/RouterError.js";
|
|
9
|
+
import invariant from "../../util/invariant.js";
|
|
10
10
|
import { CreateApiKey } from "./CreateApiKey.js";
|
|
11
11
|
import { ProtectedRoute } from "./ProtectedRoute.js";
|
|
12
12
|
import { SettingsApiKeys } from "./SettingsApiKeys.js";
|
|
@@ -18,11 +18,11 @@ const StaggeredRender = ({ children }: { children: ReactNode[] }) => {
|
|
|
18
18
|
return;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
const
|
|
21
|
+
const idle = requestIdleCallback(() => {
|
|
22
22
|
setRenderAll(true);
|
|
23
23
|
});
|
|
24
24
|
|
|
25
|
-
return () =>
|
|
25
|
+
return () => cancelIdleCallback(idle);
|
|
26
26
|
}, [renderAll]);
|
|
27
27
|
|
|
28
28
|
return !renderAll ? Children.toArray(children).slice(0, 3) : children;
|
|
@@ -188,9 +188,10 @@ export const Playground = ({
|
|
|
188
188
|
|
|
189
189
|
const urlQueryParams = formState.queryParams
|
|
190
190
|
.filter((p) => p.active)
|
|
191
|
-
.map((p) => (
|
|
191
|
+
.map((p, i, arr) => (
|
|
192
192
|
<Fragment key={p.name}>
|
|
193
193
|
{p.name}={encodeURIComponent(p.value).replaceAll("%20", "+")}
|
|
194
|
+
{i < arr.length - 1 && "&"}
|
|
194
195
|
<wbr />
|
|
195
196
|
</Fragment>
|
|
196
197
|
));
|
|
@@ -57,9 +57,7 @@ export const QueryParams = ({
|
|
|
57
57
|
title={requiredFields[i] ? "Required field" : undefined}
|
|
58
58
|
>
|
|
59
59
|
{field.value}
|
|
60
|
-
{requiredFields[i] &&
|
|
61
|
-
<sup className="text-destructive">*</sup>
|
|
62
|
-
)}
|
|
60
|
+
{requiredFields[i] && <sup> *</sup>}
|
|
63
61
|
</label>
|
|
64
62
|
</InlineInput>
|
|
65
63
|
)}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export default function invariant(
|
|
2
|
+
condition: any,
|
|
3
|
+
// Not providing an inline default argument for message as the result is smaller
|
|
4
|
+
/**
|
|
5
|
+
* Can provide a string, or a function that returns a string for cases where
|
|
6
|
+
* the message takes a fair amount of effort to compute
|
|
7
|
+
*/
|
|
8
|
+
message?: string | (() => string),
|
|
9
|
+
): asserts condition {
|
|
10
|
+
if (condition) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
// Condition not passed
|
|
14
|
+
|
|
15
|
+
const provided: string | undefined =
|
|
16
|
+
typeof message === "function" ? message() : message;
|
|
17
|
+
|
|
18
|
+
throw new ZudokuError(provided ?? "Invariant failed");
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
class ZudokuError extends Error {
|
|
22
|
+
constructor(message: string) {
|
|
23
|
+
super(message);
|
|
24
|
+
this.name = "ZudokuError";
|
|
25
|
+
}
|
|
26
|
+
}
|