@ampless/admin 0.2.0-alpha.2 → 0.2.0-alpha.21

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 (49) hide show
  1. package/README.ja.md +73 -0
  2. package/README.md +3 -0
  3. package/dist/api/index.d.ts +1 -1
  4. package/dist/chunk-2ITWLRYF.js +38 -0
  5. package/dist/chunk-5JKOPRCO.js +41 -0
  6. package/dist/chunk-5Q6KVRZ2.js +250 -0
  7. package/dist/chunk-7IR4F7GA.js +6 -0
  8. package/dist/chunk-A3SWBQA6.js +71 -0
  9. package/dist/chunk-BC4B6DLO.js +21 -0
  10. package/dist/chunk-BWFCQNPU.js +1264 -0
  11. package/dist/chunk-CQY55RDG.js +48 -0
  12. package/dist/chunk-CVJCMTYB.js +1197 -0
  13. package/dist/chunk-JOASK4AM.js +360 -0
  14. package/dist/{chunk-TJR3ALRJ.js → chunk-OSUTPPAU.js} +171 -68
  15. package/dist/chunk-QXJIIBUQ.js +21 -0
  16. package/dist/chunk-S66L5CDS.js +335 -0
  17. package/dist/chunk-SRNH2IVA.js +149 -0
  18. package/dist/chunk-TZWSXAHD.js +32 -0
  19. package/dist/chunk-VXEVLHGL.js +10 -0
  20. package/dist/chunk-W6BXESPW.js +198 -0
  21. package/dist/chunk-XY4JWSMS.js +33 -0
  22. package/dist/components/admin-dashboard.d.ts +10 -0
  23. package/dist/components/admin-dashboard.js +9 -0
  24. package/dist/components/edit-post-view.d.ts +9 -0
  25. package/dist/components/edit-post-view.js +14 -0
  26. package/dist/components/index.d.ts +40 -21
  27. package/dist/components/index.js +32 -15
  28. package/dist/components/login-view.d.ts +5 -0
  29. package/dist/components/login-view.js +9 -0
  30. package/dist/components/mcp-tokens-view.d.ts +22 -0
  31. package/dist/components/mcp-tokens-view.js +9 -0
  32. package/dist/components/media-view.d.ts +5 -0
  33. package/dist/components/media-view.js +12 -0
  34. package/dist/components/new-post-view.d.ts +5 -0
  35. package/dist/components/new-post-view.js +14 -0
  36. package/dist/components/posts-list-view.d.ts +5 -0
  37. package/dist/components/posts-list-view.js +11 -0
  38. package/dist/components/users-list-view.d.ts +7 -0
  39. package/dist/components/users-list-view.js +9 -0
  40. package/dist/{i18n-ByHM_Bho.d.ts → i18n-MWvAMHzn.d.ts} +253 -2
  41. package/dist/index.d.ts +14 -9
  42. package/dist/index.js +18 -10
  43. package/dist/lib/theme-actions.d.ts +17 -0
  44. package/dist/lib/theme-actions.js +7 -0
  45. package/dist/metafile-esm.json +1 -1
  46. package/dist/pages/index.d.ts +67 -15
  47. package/dist/pages/index.js +147 -659
  48. package/package.json +12 -9
  49. package/dist/chunk-T2RSMFOI.js +0 -2074
@@ -1,297 +1,57 @@
1
- 'use client';
2
1
  import {
3
- I18nProvider,
4
- MediaUploader,
5
- PostForm,
2
+ NewPostPage
3
+ } from "../chunk-BC4B6DLO.js";
4
+ import {
5
+ PostsList
6
+ } from "../chunk-A3SWBQA6.js";
7
+ import {
8
+ UsersListView
9
+ } from "../chunk-SRNH2IVA.js";
10
+ import {
11
+ AdminDashboard
12
+ } from "../chunk-CQY55RDG.js";
13
+ import {
14
+ EditPostPage
15
+ } from "../chunk-5JKOPRCO.js";
16
+ import {
17
+ AdminProviders,
6
18
  Sidebar,
7
19
  SiteSelector,
8
20
  SiteSettingsForm,
9
- ThemeSettingsForm,
10
- setAdminCmsConfigClient,
11
- useT
12
- } from "../chunk-T2RSMFOI.js";
21
+ ThemeSettingsForm
22
+ } from "../chunk-BWFCQNPU.js";
23
+ import "../chunk-VXEVLHGL.js";
24
+ import "../chunk-CVJCMTYB.js";
25
+ import "../chunk-TZWSXAHD.js";
26
+ import "../chunk-7IR4F7GA.js";
27
+ import {
28
+ LoginPage
29
+ } from "../chunk-W6BXESPW.js";
30
+ import {
31
+ McpTokensView
32
+ } from "../chunk-JOASK4AM.js";
33
+ import {
34
+ MediaPage
35
+ } from "../chunk-QXJIIBUQ.js";
36
+ import "../chunk-5Q6KVRZ2.js";
37
+ import "../chunk-S66L5CDS.js";
38
+ import "../chunk-2ITWLRYF.js";
13
39
  import {
14
- readAdminSiteIdFromCookie,
15
- setAdminCmsConfig,
16
- setAdminMediaContext
17
- } from "../chunk-TJR3ALRJ.js";
40
+ I18nProvider
41
+ } from "../chunk-XY4JWSMS.js";
42
+ import "../chunk-OSUTPPAU.js";
18
43
 
19
44
  // src/pages/admin-layout.tsx
20
45
  import { redirect } from "next/navigation";
21
-
22
- // src/pages/admin-providers.tsx
23
- import { useEffect } from "react";
24
-
25
- // src/lib/amplify-client.ts
26
- import { Amplify } from "aws-amplify";
27
- var configured = false;
28
- function configureAmplify(outputs) {
29
- if (configured) return;
30
- Amplify.configure(outputs, { ssr: true });
31
- configured = true;
32
- }
33
-
34
- // src/lib/posts-provider.ts
35
- import { generateClient } from "aws-amplify/api";
36
- import {
37
- setPostsProvider,
38
- composeSiteIdStatus,
39
- composeSiteIdSlug
40
- } from "ampless";
41
- function encodeBody(value) {
42
- if (typeof value === "string") return value;
43
- return JSON.stringify(value ?? null);
44
- }
45
- function decodeBody(value) {
46
- if (typeof value !== "string") return value;
47
- try {
48
- return JSON.parse(value);
49
- } catch {
50
- return value;
51
- }
52
- }
53
- function toCorePost(p) {
46
+ import { jsx, jsxs } from "react/jsx-runtime";
47
+ function sanitizeCmsConfigForClient(config) {
54
48
  return {
55
- postId: p.postId,
56
- siteId: p.siteId,
57
- slug: p.slug,
58
- title: p.title,
59
- excerpt: p.excerpt ?? void 0,
60
- format: p.format ?? "markdown",
61
- body: decodeBody(p.body),
62
- status: p.status ?? "draft",
63
- publishedAt: p.publishedAt ?? void 0,
64
- tags: (p.tags ?? []).filter((t) => typeof t === "string")
65
- };
66
- }
67
- function postTagEntries(post) {
68
- if (post.status !== "published" || !post.publishedAt || !post.tags?.length) return [];
69
- return post.tags.map((tag) => ({
70
- siteIdTag: `${post.siteId}#${tag}`,
71
- publishedAtPostId: `${post.publishedAt}#${post.postId}`
72
- }));
73
- }
74
- function entryKey(e) {
75
- return `${e.siteIdTag}|${e.publishedAtPostId}`;
76
- }
77
- var installed = false;
78
- function installAdminPostsProvider() {
79
- if (installed) return;
80
- installed = true;
81
- const client = generateClient();
82
- async function syncPostTags(post, oldPost) {
83
- const oldEntries = oldPost ? postTagEntries(oldPost) : [];
84
- const newEntries = postTagEntries(post);
85
- const oldKeys = new Set(oldEntries.map(entryKey));
86
- const newKeys = new Set(newEntries.map(entryKey));
87
- await Promise.all(
88
- oldEntries.filter((e) => !newKeys.has(entryKey(e))).map((e) => client.models.PostTag.delete(e))
89
- );
90
- await Promise.all(
91
- newEntries.filter((e) => !oldKeys.has(entryKey(e))).map(
92
- (e) => client.models.PostTag.create({
93
- siteIdTag: e.siteIdTag,
94
- publishedAtPostId: e.publishedAtPostId,
95
- siteId: post.siteId,
96
- tag: e.siteIdTag.slice(post.siteId.length + 1),
97
- postId: post.postId,
98
- publishedAt: post.publishedAt,
99
- slug: post.slug,
100
- title: post.title,
101
- excerpt: post.excerpt,
102
- tags: post.tags ?? []
103
- })
104
- )
105
- );
106
- await Promise.all(
107
- newEntries.filter((e) => oldKeys.has(entryKey(e))).map(
108
- (e) => client.models.PostTag.update({
109
- siteIdTag: e.siteIdTag,
110
- publishedAtPostId: e.publishedAtPostId,
111
- slug: post.slug,
112
- title: post.title,
113
- excerpt: post.excerpt,
114
- tags: post.tags ?? []
115
- })
116
- )
117
- );
118
- }
119
- const provider = {
120
- async list(opts = {}) {
121
- const siteId = opts.siteId ?? "default";
122
- const status = opts.status ?? "published";
123
- const filter = { siteId: { eq: siteId } };
124
- if (status !== "all") filter.status = { eq: status };
125
- const { data } = await client.models.Post.list({ filter, limit: opts.limit ?? 100 });
126
- return data.map(toCorePost);
127
- },
128
- async get(slug, opts = {}) {
129
- const siteId = opts.siteId ?? "default";
130
- const { data } = await client.models.Post.list({
131
- filter: { siteId: { eq: siteId }, slug: { eq: slug } },
132
- limit: 1
133
- });
134
- return data[0] ? toCorePost(data[0]) : null;
135
- },
136
- async getById(postId, opts = {}) {
137
- const siteId = opts.siteId ?? "default";
138
- const { data } = await client.models.Post.get({ siteId, postId });
139
- return data ? toCorePost(data) : null;
140
- },
141
- async create(input) {
142
- const postId = input.postId ?? `post-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
143
- const { data, errors } = await client.models.Post.create({
144
- siteId: input.siteId,
145
- postId,
146
- slug: input.slug,
147
- title: input.title,
148
- excerpt: input.excerpt,
149
- format: input.format,
150
- body: encodeBody(input.body),
151
- status: input.status,
152
- publishedAt: input.publishedAt,
153
- tags: input.tags,
154
- // Denormalized GSI keys. Must match every change to slug /
155
- // status — see the update() branch below.
156
- siteIdStatus: composeSiteIdStatus(input.siteId, input.status),
157
- siteIdSlug: composeSiteIdSlug(input.siteId, input.slug)
158
- });
159
- if (errors || !data) throw new Error(errors?.[0]?.message ?? "Failed to create post");
160
- const created = toCorePost(data);
161
- await syncPostTags(created, null);
162
- return created;
163
- },
164
- async update(postId, patch, opts = {}) {
165
- const siteId = opts.siteId ?? "default";
166
- const oldPost = await this.getById(postId, { siteId });
167
- const nextStatus = patch.status ?? oldPost?.status;
168
- const nextSlug = patch.slug ?? oldPost?.slug;
169
- const { data, errors } = await client.models.Post.update({
170
- siteId,
171
- postId,
172
- ...patch.slug !== void 0 && { slug: patch.slug },
173
- ...patch.title !== void 0 && { title: patch.title },
174
- ...patch.excerpt !== void 0 && { excerpt: patch.excerpt },
175
- ...patch.format !== void 0 && { format: patch.format },
176
- ...patch.body !== void 0 && { body: encodeBody(patch.body) },
177
- ...patch.status !== void 0 && { status: patch.status },
178
- ...patch.publishedAt !== void 0 && { publishedAt: patch.publishedAt },
179
- ...patch.tags !== void 0 && { tags: patch.tags },
180
- ...patch.status !== void 0 && nextStatus && { siteIdStatus: composeSiteIdStatus(siteId, nextStatus) },
181
- ...patch.slug !== void 0 && nextSlug && { siteIdSlug: composeSiteIdSlug(siteId, nextSlug) }
182
- });
183
- if (errors || !data) throw new Error(errors?.[0]?.message ?? "Failed to update post");
184
- const updated = toCorePost(data);
185
- await syncPostTags(updated, oldPost);
186
- return updated;
187
- },
188
- async remove(postId, opts = {}) {
189
- const siteId = opts.siteId ?? "default";
190
- const oldPost = await this.getById(postId, { siteId });
191
- if (oldPost) {
192
- await syncPostTags({ ...oldPost, status: "draft" }, oldPost);
193
- }
194
- const { errors } = await client.models.Post.delete({ siteId, postId });
195
- if (errors) throw new Error(errors[0]?.message ?? "Failed to delete post");
196
- }
197
- };
198
- setPostsProvider(provider);
199
- }
200
-
201
- // src/lib/kv-provider.ts
202
- import { generateClient as generateClient2 } from "aws-amplify/api";
203
- import { setKvStore } from "ampless";
204
- var installed2 = false;
205
- function installAdminKvProvider() {
206
- if (installed2) return;
207
- installed2 = true;
208
- const client = generateClient2();
209
- function requireModel() {
210
- const m = client.models.KvStore;
211
- if (!m) {
212
- throw new Error(
213
- "KvStore model is not available on the AppSync client. Did you redeploy the sandbox? Run `npx ampx sandbox` and wait for it to finish, then reload this page."
214
- );
215
- }
216
- return m;
217
- }
218
- function encodeValue(value) {
219
- return JSON.stringify(value ?? null);
220
- }
221
- function decodeValue(raw) {
222
- if (typeof raw !== "string") return raw;
223
- try {
224
- return JSON.parse(raw);
225
- } catch {
226
- return raw;
227
- }
228
- }
229
- const store = {
230
- async get(pk, sk) {
231
- const model = requireModel();
232
- const { data } = await model.get({ pk, sk });
233
- return data ? decodeValue(data.value) : null;
234
- },
235
- async query(pk) {
236
- const model = requireModel();
237
- const { data } = await model.list({
238
- filter: { pk: { eq: pk } },
239
- limit: 1e3
240
- });
241
- return (data ?? []).map((row) => ({
242
- pk: row.pk,
243
- sk: row.sk,
244
- value: decodeValue(row.value),
245
- ttl: row.ttl ?? void 0
246
- }));
247
- },
248
- async put(pk, sk, value, opts) {
249
- const model = requireModel();
250
- const ttl = opts?.ttlSeconds ? Math.floor(Date.now() / 1e3) + opts.ttlSeconds : void 0;
251
- const existing = await model.get({ pk, sk });
252
- if (existing.data) {
253
- const { errors } = await model.update({
254
- pk,
255
- sk,
256
- value: encodeValue(value),
257
- ttl: ttl ?? null
258
- });
259
- if (errors) throw new Error(errors[0]?.message ?? "KvStore.update failed");
260
- } else {
261
- const { errors } = await model.create({
262
- pk,
263
- sk,
264
- value: encodeValue(value),
265
- ttl
266
- });
267
- if (errors) throw new Error(errors[0]?.message ?? "KvStore.create failed");
268
- }
269
- },
270
- async remove(pk, sk) {
271
- const model = requireModel();
272
- const { errors } = await model.delete({ pk, sk });
273
- if (errors) throw new Error(errors[0]?.message ?? "KvStore.delete failed");
274
- }
49
+ ...config,
50
+ plugins: (config.plugins ?? []).map(
51
+ (p) => typeof p === "string" ? p : { name: p.name, apiVersion: p.apiVersion, trust_level: p.trust_level }
52
+ )
275
53
  };
276
- setKvStore(store);
277
- }
278
-
279
- // src/pages/admin-providers.tsx
280
- import { Fragment, jsx } from "react/jsx-runtime";
281
- function AdminProviders({ outputs, cmsConfig, children }) {
282
- configureAmplify(outputs);
283
- setAdminCmsConfig(cmsConfig);
284
- setAdminCmsConfigClient(cmsConfig);
285
- setAdminMediaContext(outputs, cmsConfig);
286
- useEffect(() => {
287
- installAdminPostsProvider();
288
- installAdminKvProvider();
289
- }, []);
290
- return /* @__PURE__ */ jsx(Fragment, { children });
291
54
  }
292
-
293
- // src/pages/admin-layout.tsx
294
- import { jsx as jsx2, jsxs } from "react/jsx-runtime";
295
55
  function createAdminLayout(admin) {
296
56
  async function AdminLayout({ children }) {
297
57
  const session = await admin.getServerSession();
@@ -300,216 +60,87 @@ function createAdminLayout(admin) {
300
60
  }
301
61
  const sites = admin.adminSiteOptions();
302
62
  const currentSiteId = await admin.currentAdminSiteId();
303
- const selector = sites.length > 0 ? /* @__PURE__ */ jsx2(SiteSelector, { current: currentSiteId, sites }) : null;
304
- return /* @__PURE__ */ jsx2(AdminProviders, { outputs: admin.outputs, cmsConfig: admin.cmsConfig, children: /* @__PURE__ */ jsx2(I18nProvider, { locale: admin.locale, dict: admin.dict, children: /* @__PURE__ */ jsxs("div", { className: "flex min-h-screen", children: [
305
- /* @__PURE__ */ jsx2(Sidebar, { email: session.email, siteSelector: selector }),
306
- /* @__PURE__ */ jsx2("main", { className: "flex-1 overflow-auto", children })
63
+ const selector = sites.length > 0 ? /* @__PURE__ */ jsx(SiteSelector, { current: currentSiteId, sites }) : null;
64
+ return /* @__PURE__ */ jsx(AdminProviders, { outputs: admin.outputs, cmsConfig: sanitizeCmsConfigForClient(admin.cmsConfig), children: /* @__PURE__ */ jsx(I18nProvider, { locale: admin.locale, dict: admin.dict, children: /* @__PURE__ */ jsxs("div", { className: "flex min-h-screen flex-col md:flex-row", children: [
65
+ /* @__PURE__ */ jsx(
66
+ Sidebar,
67
+ {
68
+ email: session.email,
69
+ siteSelector: selector,
70
+ isAdmin: admin.isAdmin(session)
71
+ }
72
+ ),
73
+ /* @__PURE__ */ jsx("main", { className: "min-w-0 flex-1", children })
307
74
  ] }) }) });
308
75
  }
309
76
  return AdminLayout;
310
77
  }
311
78
 
312
79
  // src/pages/dashboard.tsx
313
- import { useEffect as useEffect2, useState } from "react";
314
- import Link from "next/link";
315
- import { listPosts } from "ampless";
316
- import { Button, Card, CardContent, CardHeader, CardTitle } from "@ampless/runtime/ui";
317
- import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
318
- function AdminDashboard() {
319
- const t = useT();
320
- const [posts, setPosts] = useState([]);
321
- const [loading, setLoading] = useState(true);
322
- useEffect2(() => {
323
- listPosts({ status: "all" }).then(setPosts).finally(() => setLoading(false));
324
- }, []);
325
- const published = posts.filter((p) => p.status === "published").length;
326
- const drafts = posts.filter((p) => p.status === "draft").length;
327
- return /* @__PURE__ */ jsxs2("div", { className: "p-8", children: [
328
- /* @__PURE__ */ jsxs2("div", { className: "mb-8 flex items-center justify-between", children: [
329
- /* @__PURE__ */ jsx3("h1", { className: "text-3xl font-bold", children: t("dashboard.title") }),
330
- /* @__PURE__ */ jsx3(Button, { asChild: true, children: /* @__PURE__ */ jsx3(Link, { href: "/admin/posts/new", children: t("dashboard.newPost") }) })
331
- ] }),
332
- /* @__PURE__ */ jsxs2("div", { className: "grid grid-cols-1 gap-4 md:grid-cols-3", children: [
333
- /* @__PURE__ */ jsxs2(Card, { children: [
334
- /* @__PURE__ */ jsx3(CardHeader, { children: /* @__PURE__ */ jsx3(CardTitle, { children: t("dashboard.totalPosts") }) }),
335
- /* @__PURE__ */ jsxs2(CardContent, { children: [
336
- /* @__PURE__ */ jsx3("p", { className: "text-3xl font-bold", children: loading ? "\u2014" : posts.length }),
337
- /* @__PURE__ */ jsx3("p", { className: "text-sm text-muted-foreground", children: t("dashboard.totalLabel") })
338
- ] })
339
- ] }),
340
- /* @__PURE__ */ jsxs2(Card, { children: [
341
- /* @__PURE__ */ jsx3(CardHeader, { children: /* @__PURE__ */ jsx3(CardTitle, { children: t("dashboard.published") }) }),
342
- /* @__PURE__ */ jsx3(CardContent, { children: /* @__PURE__ */ jsx3("p", { className: "text-3xl font-bold", children: loading ? "\u2014" : published }) })
343
- ] }),
344
- /* @__PURE__ */ jsxs2(Card, { children: [
345
- /* @__PURE__ */ jsx3(CardHeader, { children: /* @__PURE__ */ jsx3(CardTitle, { children: t("dashboard.drafts") }) }),
346
- /* @__PURE__ */ jsx3(CardContent, { children: /* @__PURE__ */ jsx3("p", { className: "text-3xl font-bold", children: loading ? "\u2014" : drafts }) })
347
- ] })
348
- ] })
349
- ] });
350
- }
351
80
  function createAdminDashboardPage(_admin) {
352
81
  return AdminDashboard;
353
82
  }
354
83
 
355
84
  // src/pages/posts-list.tsx
356
- import { useEffect as useEffect3, useState as useState2 } from "react";
357
- import Link2 from "next/link";
358
- import { listPosts as listPosts2 } from "ampless";
359
- import {
360
- Button as Button2,
361
- Table,
362
- TableBody,
363
- TableCell,
364
- TableHead,
365
- TableHeader,
366
- TableRow
367
- } from "@ampless/runtime/ui";
368
- import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
369
- function PostsList() {
370
- const t = useT();
371
- const [posts, setPosts] = useState2([]);
372
- const [loading, setLoading] = useState2(true);
373
- useEffect3(() => {
374
- const siteId = readAdminSiteIdFromCookie();
375
- listPosts2({ status: "all", siteId }).then(setPosts).finally(() => setLoading(false));
376
- }, []);
377
- return /* @__PURE__ */ jsxs3("div", { className: "p-8", children: [
378
- /* @__PURE__ */ jsxs3("div", { className: "mb-8 flex items-center justify-between", children: [
379
- /* @__PURE__ */ jsx4("h1", { className: "text-3xl font-bold", children: t("posts.list.title") }),
380
- /* @__PURE__ */ jsx4(Button2, { asChild: true, children: /* @__PURE__ */ jsx4(Link2, { href: "/admin/posts/new", children: t("posts.list.newButton") }) })
381
- ] }),
382
- loading ? /* @__PURE__ */ jsx4("p", { className: "text-muted-foreground", children: t("common.loading") }) : posts.length === 0 ? /* @__PURE__ */ jsxs3("div", { className: "rounded-md border p-12 text-center", children: [
383
- /* @__PURE__ */ jsx4("p", { className: "text-muted-foreground", children: t("posts.list.empty") }),
384
- /* @__PURE__ */ jsx4(Button2, { asChild: true, className: "mt-4", children: /* @__PURE__ */ jsx4(Link2, { href: "/admin/posts/new", children: t("posts.list.createFirst") }) })
385
- ] }) : /* @__PURE__ */ jsx4("div", { className: "rounded-md border", children: /* @__PURE__ */ jsxs3(Table, { children: [
386
- /* @__PURE__ */ jsx4(TableHeader, { children: /* @__PURE__ */ jsxs3(TableRow, { children: [
387
- /* @__PURE__ */ jsx4(TableHead, { children: t("posts.list.columnTitle") }),
388
- /* @__PURE__ */ jsx4(TableHead, { children: t("posts.list.columnStatus") }),
389
- /* @__PURE__ */ jsx4(TableHead, { children: t("posts.list.columnSlug") }),
390
- /* @__PURE__ */ jsx4(TableHead, { children: t("posts.list.columnUpdated") })
391
- ] }) }),
392
- /* @__PURE__ */ jsx4(TableBody, { children: posts.map((post) => /* @__PURE__ */ jsxs3(TableRow, { children: [
393
- /* @__PURE__ */ jsx4(TableCell, { children: /* @__PURE__ */ jsx4(
394
- Link2,
395
- {
396
- href: `/admin/posts/${post.postId}`,
397
- className: "font-medium hover:underline",
398
- children: post.title
399
- }
400
- ) }),
401
- /* @__PURE__ */ jsx4(TableCell, { children: /* @__PURE__ */ jsx4(
402
- "span",
403
- {
404
- className: post.status === "published" ? "inline-block rounded-full bg-green-100 px-2 py-0.5 text-xs text-green-700" : "inline-block rounded-full bg-gray-100 px-2 py-0.5 text-xs text-gray-700",
405
- children: t(`common.${post.status}`)
406
- }
407
- ) }),
408
- /* @__PURE__ */ jsx4(TableCell, { className: "font-mono text-xs text-muted-foreground", children: post.slug }),
409
- /* @__PURE__ */ jsx4(TableCell, { className: "text-sm text-muted-foreground", children: post.publishedAt ? new Date(post.publishedAt).toLocaleDateString() : "\u2014" })
410
- ] }, post.postId)) })
411
- ] }) })
412
- ] });
413
- }
414
85
  function createPostsListPage(_admin) {
415
86
  return PostsList;
416
87
  }
417
88
 
418
89
  // src/pages/post-new.tsx
419
- import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
420
- function NewPostPage() {
421
- const t = useT();
422
- return /* @__PURE__ */ jsxs4("div", { className: "p-8", children: [
423
- /* @__PURE__ */ jsx5("h1", { className: "mb-8 text-3xl font-bold", children: t("posts.form.newTitle") }),
424
- /* @__PURE__ */ jsx5(PostForm, {})
425
- ] });
426
- }
427
90
  function createNewPostPage(_admin) {
428
91
  return NewPostPage;
429
92
  }
430
93
 
431
94
  // src/pages/post-edit.tsx
432
- import { useEffect as useEffect4, useState as useState3, use } from "react";
433
- import { notFound } from "next/navigation";
434
- import { getPostById } from "ampless";
435
- import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
436
- function EditPostPage({ params }) {
437
- const t = useT();
438
- const { postId } = use(params);
439
- const [post, setPost] = useState3(null);
440
- const [loading, setLoading] = useState3(true);
441
- const [missing, setMissing] = useState3(false);
442
- useEffect4(() => {
443
- const siteId = readAdminSiteIdFromCookie();
444
- getPostById(postId, { siteId }).then((p) => {
445
- if (!p) setMissing(true);
446
- else setPost(p);
447
- }).finally(() => setLoading(false));
448
- }, [postId]);
449
- if (loading) return /* @__PURE__ */ jsx6("div", { className: "p-8", children: t("common.loading") });
450
- if (missing) notFound();
451
- return /* @__PURE__ */ jsxs5("div", { className: "p-8", children: [
452
- /* @__PURE__ */ jsx6("h1", { className: "mb-8 text-3xl font-bold", children: t("posts.form.editTitle") }),
453
- post && /* @__PURE__ */ jsx6(PostForm, { post })
454
- ] });
455
- }
456
95
  function createEditPostPage(_admin) {
457
96
  return EditPostPage;
458
97
  }
459
98
 
460
99
  // src/pages/media.tsx
461
- import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
462
- function MediaPage() {
463
- const t = useT();
464
- return /* @__PURE__ */ jsxs6("div", { className: "p-8", children: [
465
- /* @__PURE__ */ jsx7("h1", { className: "mb-8 text-3xl font-bold", children: t("media.title") }),
466
- /* @__PURE__ */ jsx7(MediaUploader, {})
467
- ] });
468
- }
469
100
  function createMediaPage(_admin) {
470
101
  return MediaPage;
471
102
  }
472
103
 
473
104
  // src/pages/sites-list.tsx
474
- import Link3 from "next/link";
105
+ import Link from "next/link";
475
106
  import { DEFAULT_SITE_ID, isMultiSite, siteFor } from "ampless";
476
107
  import {
477
- Button as Button3,
478
- Table as Table2,
479
- TableBody as TableBody2,
480
- TableCell as TableCell2,
481
- TableHead as TableHead2,
482
- TableHeader as TableHeader2,
483
- TableRow as TableRow2
108
+ Button,
109
+ Table,
110
+ TableBody,
111
+ TableCell,
112
+ TableHead,
113
+ TableHeader,
114
+ TableRow
484
115
  } from "@ampless/runtime/ui";
485
- import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
116
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
486
117
  function createSitesListPage(admin) {
487
118
  const { cmsConfig, t } = admin;
488
119
  async function SitesPage() {
489
120
  const multi = isMultiSite(cmsConfig);
490
121
  const ids = multi ? Object.keys(cmsConfig.sites ?? {}) : [DEFAULT_SITE_ID];
491
- return /* @__PURE__ */ jsxs7("div", { className: "p-8", children: [
492
- /* @__PURE__ */ jsx8("div", { className: "mb-8 flex items-center justify-between", children: /* @__PURE__ */ jsxs7("div", { children: [
493
- /* @__PURE__ */ jsx8("h1", { className: "text-3xl font-bold", children: t("sites.list.title") }),
494
- /* @__PURE__ */ jsx8("p", { className: "mt-1 text-sm text-muted-foreground", children: t("sites.list.description") })
122
+ return /* @__PURE__ */ jsxs2("div", { className: "mx-auto max-w-7xl p-4 md:p-8", children: [
123
+ /* @__PURE__ */ jsx2("div", { className: "mb-6 flex flex-wrap items-center justify-between gap-3 md:mb-8", children: /* @__PURE__ */ jsxs2("div", { children: [
124
+ /* @__PURE__ */ jsx2("h1", { className: "text-2xl font-bold md:text-3xl", children: t("sites.list.title") }),
125
+ /* @__PURE__ */ jsx2("p", { className: "mt-1 text-sm text-muted-foreground", children: t("sites.list.description") })
495
126
  ] }) }),
496
- /* @__PURE__ */ jsx8("div", { className: "rounded-md border", children: /* @__PURE__ */ jsxs7(Table2, { children: [
497
- /* @__PURE__ */ jsx8(TableHeader2, { children: /* @__PURE__ */ jsxs7(TableRow2, { children: [
498
- /* @__PURE__ */ jsx8(TableHead2, { children: t("sites.list.columnSiteId") }),
499
- /* @__PURE__ */ jsx8(TableHead2, { children: t("sites.list.columnName") }),
500
- /* @__PURE__ */ jsx8(TableHead2, { children: t("sites.list.columnUrl") }),
501
- /* @__PURE__ */ jsx8(TableHead2, { children: t("sites.list.columnDomains") }),
502
- /* @__PURE__ */ jsx8(TableHead2, {})
127
+ /* @__PURE__ */ jsx2("div", { className: "overflow-x-auto rounded-md border", children: /* @__PURE__ */ jsxs2(Table, { children: [
128
+ /* @__PURE__ */ jsx2(TableHeader, { children: /* @__PURE__ */ jsxs2(TableRow, { children: [
129
+ /* @__PURE__ */ jsx2(TableHead, { children: t("sites.list.columnSiteId") }),
130
+ /* @__PURE__ */ jsx2(TableHead, { children: t("sites.list.columnName") }),
131
+ /* @__PURE__ */ jsx2(TableHead, { children: t("sites.list.columnUrl") }),
132
+ /* @__PURE__ */ jsx2(TableHead, { children: t("sites.list.columnDomains") }),
133
+ /* @__PURE__ */ jsx2(TableHead, {})
503
134
  ] }) }),
504
- /* @__PURE__ */ jsx8(TableBody2, { children: ids.map((id) => {
135
+ /* @__PURE__ */ jsx2(TableBody, { children: ids.map((id) => {
505
136
  const site = siteFor(id, cmsConfig);
506
137
  const domains = cmsConfig.sites?.[id]?.domains ?? [];
507
- return /* @__PURE__ */ jsxs7(TableRow2, { children: [
508
- /* @__PURE__ */ jsx8(TableCell2, { className: "font-mono text-xs", children: id }),
509
- /* @__PURE__ */ jsx8(TableCell2, { className: "font-medium", children: site.name }),
510
- /* @__PURE__ */ jsx8(TableCell2, { className: "text-sm text-muted-foreground", children: site.url }),
511
- /* @__PURE__ */ jsx8(TableCell2, { className: "text-sm text-muted-foreground", children: domains.length > 0 ? domains.join(", ") : "\u2014" }),
512
- /* @__PURE__ */ jsx8(TableCell2, { children: /* @__PURE__ */ jsx8(Button3, { asChild: true, variant: "outline", size: "sm", children: /* @__PURE__ */ jsx8(Link3, { href: `/admin/sites/${id}`, children: t("sites.list.edit") }) }) })
138
+ return /* @__PURE__ */ jsxs2(TableRow, { children: [
139
+ /* @__PURE__ */ jsx2(TableCell, { className: "font-mono text-xs", children: id }),
140
+ /* @__PURE__ */ jsx2(TableCell, { className: "font-medium", children: site.name }),
141
+ /* @__PURE__ */ jsx2(TableCell, { className: "text-sm text-muted-foreground", children: site.url }),
142
+ /* @__PURE__ */ jsx2(TableCell, { className: "text-sm text-muted-foreground", children: domains.length > 0 ? domains.join(", ") : "\u2014" }),
143
+ /* @__PURE__ */ jsx2(TableCell, { children: /* @__PURE__ */ jsx2(Button, { asChild: true, variant: "outline", size: "sm", children: /* @__PURE__ */ jsx2(Link, { href: `/admin/sites/${id}`, children: t("sites.list.edit") }) }) })
513
144
  ] }, id);
514
145
  }) })
515
146
  ] }) })
@@ -519,9 +150,9 @@ function createSitesListPage(admin) {
519
150
  }
520
151
 
521
152
  // src/pages/site-edit.tsx
522
- import Link4 from "next/link";
153
+ import Link2 from "next/link";
523
154
  import { siteFor as siteFor2 } from "ampless";
524
- import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
155
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
525
156
  function createSiteEditPage(admin) {
526
157
  const { cmsConfig, t, loadSiteSettings } = admin;
527
158
  async function EditSitePage({ params }) {
@@ -546,10 +177,10 @@ function createSiteEditPage(admin) {
546
177
  dateFormat: settings.dateFormat,
547
178
  timezone: settings.timezone
548
179
  };
549
- return /* @__PURE__ */ jsxs8("div", { className: "p-8", children: [
550
- /* @__PURE__ */ jsxs8("div", { className: "mb-8", children: [
551
- /* @__PURE__ */ jsxs8(
552
- Link4,
180
+ return /* @__PURE__ */ jsxs3("div", { className: "mx-auto max-w-7xl p-4 md:p-8", children: [
181
+ /* @__PURE__ */ jsxs3("div", { className: "mb-6 md:mb-8", children: [
182
+ /* @__PURE__ */ jsxs3(
183
+ Link2,
553
184
  {
554
185
  href: "/admin/sites",
555
186
  className: "text-sm text-muted-foreground hover:underline",
@@ -559,14 +190,14 @@ function createSiteEditPage(admin) {
559
190
  ]
560
191
  }
561
192
  ),
562
- /* @__PURE__ */ jsx9("h1", { className: "mt-2 text-3xl font-bold", children: settings.site.name }),
563
- /* @__PURE__ */ jsxs8("p", { className: "text-sm text-muted-foreground", children: [
193
+ /* @__PURE__ */ jsx3("h1", { className: "mt-2 text-2xl font-bold md:text-3xl", children: settings.site.name }),
194
+ /* @__PURE__ */ jsxs3("p", { className: "text-sm text-muted-foreground", children: [
564
195
  t("common.siteId"),
565
196
  ": ",
566
- /* @__PURE__ */ jsx9("code", { className: "font-mono", children: siteId })
197
+ /* @__PURE__ */ jsx3("code", { className: "font-mono", children: siteId })
567
198
  ] }),
568
- /* @__PURE__ */ jsx9("div", { className: "mt-4", children: /* @__PURE__ */ jsx9(
569
- Link4,
199
+ /* @__PURE__ */ jsx3("div", { className: "mt-4", children: /* @__PURE__ */ jsx3(
200
+ Link2,
570
201
  {
571
202
  href: `/admin/sites/${siteId}/theme`,
572
203
  className: "text-sm font-medium underline",
@@ -574,16 +205,16 @@ function createSiteEditPage(admin) {
574
205
  }
575
206
  ) })
576
207
  ] }),
577
- /* @__PURE__ */ jsx9(SiteSettingsForm, { siteId, initial, fallback })
208
+ /* @__PURE__ */ jsx3(SiteSettingsForm, { siteId, initial, fallback })
578
209
  ] });
579
210
  }
580
211
  return EditSitePage;
581
212
  }
582
213
 
583
214
  // src/pages/site-theme.tsx
584
- import Link5 from "next/link";
215
+ import Link3 from "next/link";
585
216
  import { siteFor as siteFor3, resolveLocalized } from "ampless";
586
- import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
217
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
587
218
  function createSiteThemePage(admin, themeList) {
588
219
  const { cmsConfig, t, locale, loadThemeConfig } = admin;
589
220
  async function ThemePage({ params }) {
@@ -595,10 +226,10 @@ function createSiteThemePage(admin, themeList) {
595
226
  label: m.manifest.label,
596
227
  description: m.manifest.description
597
228
  }));
598
- return /* @__PURE__ */ jsxs9("div", { className: "p-8", children: [
599
- /* @__PURE__ */ jsxs9("div", { className: "mb-8", children: [
600
- /* @__PURE__ */ jsxs9(
601
- Link5,
229
+ return /* @__PURE__ */ jsxs4("div", { className: "mx-auto max-w-7xl p-4 md:p-8", children: [
230
+ /* @__PURE__ */ jsxs4("div", { className: "mb-6 md:mb-8", children: [
231
+ /* @__PURE__ */ jsxs4(
232
+ Link3,
602
233
  {
603
234
  href: `/admin/sites/${siteId}`,
604
235
  className: "text-sm text-muted-foreground hover:underline",
@@ -608,25 +239,26 @@ function createSiteThemePage(admin, themeList) {
608
239
  ]
609
240
  }
610
241
  ),
611
- /* @__PURE__ */ jsx10("h1", { className: "mt-2 text-3xl font-bold", children: t("theme.title") }),
612
- /* @__PURE__ */ jsxs9("p", { className: "text-sm text-muted-foreground", children: [
242
+ /* @__PURE__ */ jsx4("h1", { className: "mt-2 text-2xl font-bold md:text-3xl", children: t("theme.title") }),
243
+ /* @__PURE__ */ jsxs4("p", { className: "text-sm text-muted-foreground", children: [
613
244
  t("common.active"),
614
245
  ":",
615
246
  " ",
616
- /* @__PURE__ */ jsx10("strong", { children: resolveLocalized(theme.manifest.label, locale) }),
247
+ /* @__PURE__ */ jsx4("strong", { children: resolveLocalized(theme.manifest.label, locale) }),
617
248
  " (",
618
249
  theme.activeTheme,
619
250
  ")"
620
251
  ] })
621
252
  ] }),
622
- /* @__PURE__ */ jsx10(
253
+ /* @__PURE__ */ jsx4(
623
254
  ThemeSettingsForm,
624
255
  {
625
256
  siteId,
626
257
  manifest: theme.manifest,
627
258
  activeTheme: theme.activeTheme,
628
259
  themeOptions,
629
- initial: theme.values
260
+ initial: theme.values,
261
+ initialColorScheme: theme.colorScheme
630
262
  }
631
263
  )
632
264
  ] });
@@ -634,195 +266,49 @@ function createSiteThemePage(admin, themeList) {
634
266
  return ThemePage;
635
267
  }
636
268
 
637
- // src/pages/login.tsx
638
- import { useState as useState4 } from "react";
639
- import { useRouter } from "next/navigation";
640
- import {
641
- signIn,
642
- signUp,
643
- confirmSignUp,
644
- resetPassword,
645
- confirmResetPassword
646
- } from "aws-amplify/auth";
647
- import {
648
- Button as Button4,
649
- Input,
650
- Label,
651
- Card as Card2,
652
- CardContent as CardContent2,
653
- CardHeader as CardHeader2,
654
- CardTitle as CardTitle2,
655
- CardDescription
656
- } from "@ampless/runtime/ui";
657
- import { Fragment as Fragment2, jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
658
- function LoginPage() {
659
- const router = useRouter();
660
- const t = useT();
661
- const [mode, setMode] = useState4("signIn");
662
- const [email, setEmail] = useState4("");
663
- const [password, setPassword] = useState4("");
664
- const [code, setCode] = useState4("");
665
- const [error, setError] = useState4(null);
666
- const [info, setInfo] = useState4(null);
667
- const [loading, setLoading] = useState4(false);
668
- function go(next) {
669
- setMode(next);
670
- setError(null);
671
- setInfo(null);
672
- setCode("");
673
- if (next === "signIn" || next === "signUp" || next === "forgot") setPassword("");
269
+ // src/pages/users-list.tsx
270
+ import { redirect as redirect2 } from "next/navigation";
271
+ import { jsx as jsx5 } from "react/jsx-runtime";
272
+ function createUsersListPage(admin) {
273
+ async function UsersPage() {
274
+ const session = await admin.getServerSession();
275
+ if (!admin.isAdmin(session)) {
276
+ redirect2("/admin");
277
+ }
278
+ return /* @__PURE__ */ jsx5(UsersListView, { currentUserId: session.userId });
674
279
  }
675
- async function handleSubmit(e) {
676
- e.preventDefault();
677
- setError(null);
678
- setInfo(null);
679
- setLoading(true);
680
- try {
681
- if (mode === "signIn") {
682
- const result = await signIn({ username: email, password });
683
- if (result.isSignedIn) {
684
- router.push("/admin");
685
- router.refresh();
686
- } else {
687
- setError(t("auth.additionalStep", { step: result.nextStep.signInStep }));
688
- }
689
- } else if (mode === "signUp") {
690
- await signUp({
691
- username: email,
692
- password,
693
- options: { userAttributes: { email } }
694
- });
695
- go("confirm");
696
- } else if (mode === "confirm") {
697
- await confirmSignUp({ username: email, confirmationCode: code });
698
- const result = await signIn({ username: email, password });
699
- if (result.isSignedIn) {
700
- router.push("/admin");
701
- router.refresh();
702
- }
703
- } else if (mode === "forgot") {
704
- await resetPassword({ username: email });
705
- setMode("reset");
706
- setInfo(t("auth.forgot.codeSent"));
707
- } else if (mode === "reset") {
708
- await confirmResetPassword({
709
- username: email,
710
- confirmationCode: code,
711
- newPassword: password
712
- });
713
- const result = await signIn({ username: email, password });
714
- if (result.isSignedIn) {
715
- router.push("/admin");
716
- router.refresh();
717
- } else {
718
- setMode("signIn");
719
- setInfo(t("auth.reset.passwordUpdated"));
720
- }
721
- }
722
- } catch (err) {
723
- setError(err instanceof Error ? err.message : String(err));
724
- } finally {
725
- setLoading(false);
280
+ return UsersPage;
281
+ }
282
+
283
+ // src/pages/mcp-tokens.tsx
284
+ import { redirect as redirect3 } from "next/navigation";
285
+ import { jsx as jsx6 } from "react/jsx-runtime";
286
+ function createMcpTokensPage(admin) {
287
+ async function McpTokensPage() {
288
+ const session = await admin.getServerSession();
289
+ if (!admin.isAdmin(session)) {
290
+ redirect3("/admin");
726
291
  }
292
+ const sites = admin.adminSiteOptions();
293
+ const mcpEndpoint = extractMcpEndpoint(admin.outputs);
294
+ return /* @__PURE__ */ jsx6(
295
+ McpTokensView,
296
+ {
297
+ currentUserId: session.userId,
298
+ currentUserEmail: session.email,
299
+ sites,
300
+ mcpEndpoint
301
+ }
302
+ );
727
303
  }
728
- const showEmail = mode !== "confirm" && mode !== "reset";
729
- const showPassword = mode === "signIn" || mode === "signUp" || mode === "reset";
730
- const showCode = mode === "confirm" || mode === "reset";
731
- return /* @__PURE__ */ jsx11("main", { className: "flex min-h-screen items-center justify-center bg-muted/30 p-4", children: /* @__PURE__ */ jsxs10(Card2, { className: "w-full max-w-md", children: [
732
- /* @__PURE__ */ jsxs10(CardHeader2, { children: [
733
- /* @__PURE__ */ jsx11(CardTitle2, { children: t(`auth.${mode}.title`) }),
734
- /* @__PURE__ */ jsx11(CardDescription, { children: t(`auth.${mode}.description`) })
735
- ] }),
736
- /* @__PURE__ */ jsx11(CardContent2, { children: /* @__PURE__ */ jsxs10("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
737
- showEmail && /* @__PURE__ */ jsxs10("div", { className: "space-y-2", children: [
738
- /* @__PURE__ */ jsx11(Label, { htmlFor: "email", children: t("auth.common.email") }),
739
- /* @__PURE__ */ jsx11(
740
- Input,
741
- {
742
- id: "email",
743
- type: "email",
744
- required: true,
745
- value: email,
746
- onChange: (e) => setEmail(e.target.value),
747
- autoComplete: "email"
748
- }
749
- )
750
- ] }),
751
- showCode && /* @__PURE__ */ jsxs10("div", { className: "space-y-2", children: [
752
- /* @__PURE__ */ jsx11(Label, { htmlFor: "code", children: t("auth.common.code") }),
753
- /* @__PURE__ */ jsx11(
754
- Input,
755
- {
756
- id: "code",
757
- required: true,
758
- value: code,
759
- onChange: (e) => setCode(e.target.value),
760
- autoComplete: "one-time-code"
761
- }
762
- )
763
- ] }),
764
- showPassword && /* @__PURE__ */ jsxs10("div", { className: "space-y-2", children: [
765
- /* @__PURE__ */ jsx11(Label, { htmlFor: "password", children: mode === "reset" ? t("auth.common.newPassword") : t("auth.common.password") }),
766
- /* @__PURE__ */ jsx11(
767
- Input,
768
- {
769
- id: "password",
770
- type: "password",
771
- required: true,
772
- minLength: 8,
773
- value: password,
774
- onChange: (e) => setPassword(e.target.value),
775
- autoComplete: mode === "signIn" ? "current-password" : "new-password"
776
- }
777
- ),
778
- (mode === "signUp" || mode === "reset") && /* @__PURE__ */ jsx11("p", { className: "text-xs text-muted-foreground", children: t("auth.common.passwordHint") })
779
- ] }),
780
- info && /* @__PURE__ */ jsx11("p", { className: "text-sm text-muted-foreground", children: info }),
781
- error && /* @__PURE__ */ jsx11("p", { className: "text-sm text-destructive", children: error }),
782
- /* @__PURE__ */ jsx11(Button4, { type: "submit", className: "w-full", disabled: loading, children: loading ? t("auth.common.working") : t(`auth.${mode}.submit`) }),
783
- /* @__PURE__ */ jsxs10("div", { className: "space-y-1 text-center text-sm", children: [
784
- mode === "signIn" && /* @__PURE__ */ jsxs10(Fragment2, { children: [
785
- /* @__PURE__ */ jsx11("p", { children: /* @__PURE__ */ jsx11(
786
- "button",
787
- {
788
- type: "button",
789
- className: "text-primary hover:underline",
790
- onClick: () => go("forgot"),
791
- children: t("auth.signIn.forgotPassword")
792
- }
793
- ) }),
794
- /* @__PURE__ */ jsx11("p", { children: /* @__PURE__ */ jsx11(
795
- "button",
796
- {
797
- type: "button",
798
- className: "text-primary hover:underline",
799
- onClick: () => go("signUp"),
800
- children: t("auth.signIn.createAccount")
801
- }
802
- ) })
803
- ] }),
804
- (mode === "signUp" || mode === "forgot" || mode === "reset") && /* @__PURE__ */ jsx11("p", { children: /* @__PURE__ */ jsx11(
805
- "button",
806
- {
807
- type: "button",
808
- className: "text-primary hover:underline",
809
- onClick: () => go("signIn"),
810
- children: t("auth.signUp.backToSignIn")
811
- }
812
- ) }),
813
- mode === "reset" && /* @__PURE__ */ jsx11("p", { children: /* @__PURE__ */ jsx11(
814
- "button",
815
- {
816
- type: "button",
817
- className: "text-primary hover:underline",
818
- onClick: () => go("forgot"),
819
- children: t("auth.reset.resendCode")
820
- }
821
- ) })
822
- ] })
823
- ] }) })
824
- ] }) });
304
+ return McpTokensPage;
825
305
  }
306
+ function extractMcpEndpoint(outputs) {
307
+ const custom = outputs.custom;
308
+ return custom?.mcp?.endpoint ?? null;
309
+ }
310
+
311
+ // src/pages/login.tsx
826
312
  function createLoginPage(_admin) {
827
313
  return LoginPage;
828
314
  }
@@ -831,10 +317,12 @@ export {
831
317
  createAdminLayout,
832
318
  createEditPostPage,
833
319
  createLoginPage,
320
+ createMcpTokensPage,
834
321
  createMediaPage,
835
322
  createNewPostPage,
836
323
  createPostsListPage,
837
324
  createSiteEditPage,
838
325
  createSiteThemePage,
839
- createSitesListPage
326
+ createSitesListPage,
327
+ createUsersListPage
840
328
  };