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

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.
@@ -1,297 +1,31 @@
1
- 'use client';
2
1
  import {
2
+ AdminDashboard,
3
+ AdminProviders,
4
+ EditPostPage,
3
5
  I18nProvider,
4
- MediaUploader,
5
- PostForm,
6
+ LoginPage,
7
+ MediaPage,
8
+ NewPostPage,
9
+ PostsList,
6
10
  Sidebar,
7
11
  SiteSelector,
8
12
  SiteSettingsForm,
9
- ThemeSettingsForm,
10
- setAdminCmsConfigClient,
11
- useT
12
- } from "../chunk-T2RSMFOI.js";
13
- import {
14
- readAdminSiteIdFromCookie,
15
- setAdminCmsConfig,
16
- setAdminMediaContext
17
- } from "../chunk-TJR3ALRJ.js";
13
+ ThemeSettingsForm
14
+ } from "../chunk-7WFZULH7.js";
15
+ import "../chunk-FI7CM4LH.js";
16
+ import "../chunk-VXEVLHGL.js";
18
17
 
19
18
  // src/pages/admin-layout.tsx
20
19
  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) {
20
+ import { jsx, jsxs } from "react/jsx-runtime";
21
+ function sanitizeCmsConfigForClient(config) {
54
22
  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
- }
23
+ ...config,
24
+ plugins: (config.plugins ?? []).map(
25
+ (p) => typeof p === "string" ? p : { name: p.name, apiVersion: p.apiVersion, trust_level: p.trust_level }
26
+ )
275
27
  };
276
- setKvStore(store);
277
28
  }
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
- }
292
-
293
- // src/pages/admin-layout.tsx
294
- import { jsx as jsx2, jsxs } from "react/jsx-runtime";
295
29
  function createAdminLayout(admin) {
296
30
  async function AdminLayout({ children }) {
297
31
  const session = await admin.getServerSession();
@@ -300,216 +34,80 @@ function createAdminLayout(admin) {
300
34
  }
301
35
  const sites = admin.adminSiteOptions();
302
36
  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 })
37
+ const selector = sites.length > 0 ? /* @__PURE__ */ jsx(SiteSelector, { current: currentSiteId, sites }) : null;
38
+ 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", children: [
39
+ /* @__PURE__ */ jsx(Sidebar, { email: session.email, siteSelector: selector }),
40
+ /* @__PURE__ */ jsx("main", { className: "flex-1 overflow-auto", children })
307
41
  ] }) }) });
308
42
  }
309
43
  return AdminLayout;
310
44
  }
311
45
 
312
46
  // 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
47
  function createAdminDashboardPage(_admin) {
352
48
  return AdminDashboard;
353
49
  }
354
50
 
355
51
  // 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
52
  function createPostsListPage(_admin) {
415
53
  return PostsList;
416
54
  }
417
55
 
418
56
  // 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
57
  function createNewPostPage(_admin) {
428
58
  return NewPostPage;
429
59
  }
430
60
 
431
61
  // 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
62
  function createEditPostPage(_admin) {
457
63
  return EditPostPage;
458
64
  }
459
65
 
460
66
  // 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
67
  function createMediaPage(_admin) {
470
68
  return MediaPage;
471
69
  }
472
70
 
473
71
  // src/pages/sites-list.tsx
474
- import Link3 from "next/link";
72
+ import Link from "next/link";
475
73
  import { DEFAULT_SITE_ID, isMultiSite, siteFor } from "ampless";
476
74
  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
75
+ Button,
76
+ Table,
77
+ TableBody,
78
+ TableCell,
79
+ TableHead,
80
+ TableHeader,
81
+ TableRow
484
82
  } from "@ampless/runtime/ui";
485
- import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
83
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
486
84
  function createSitesListPage(admin) {
487
85
  const { cmsConfig, t } = admin;
488
86
  async function SitesPage() {
489
87
  const multi = isMultiSite(cmsConfig);
490
88
  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") })
89
+ return /* @__PURE__ */ jsxs2("div", { className: "p-8", children: [
90
+ /* @__PURE__ */ jsx2("div", { className: "mb-8 flex items-center justify-between", children: /* @__PURE__ */ jsxs2("div", { children: [
91
+ /* @__PURE__ */ jsx2("h1", { className: "text-3xl font-bold", children: t("sites.list.title") }),
92
+ /* @__PURE__ */ jsx2("p", { className: "mt-1 text-sm text-muted-foreground", children: t("sites.list.description") })
495
93
  ] }) }),
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, {})
94
+ /* @__PURE__ */ jsx2("div", { className: "rounded-md border", children: /* @__PURE__ */ jsxs2(Table, { children: [
95
+ /* @__PURE__ */ jsx2(TableHeader, { children: /* @__PURE__ */ jsxs2(TableRow, { children: [
96
+ /* @__PURE__ */ jsx2(TableHead, { children: t("sites.list.columnSiteId") }),
97
+ /* @__PURE__ */ jsx2(TableHead, { children: t("sites.list.columnName") }),
98
+ /* @__PURE__ */ jsx2(TableHead, { children: t("sites.list.columnUrl") }),
99
+ /* @__PURE__ */ jsx2(TableHead, { children: t("sites.list.columnDomains") }),
100
+ /* @__PURE__ */ jsx2(TableHead, {})
503
101
  ] }) }),
504
- /* @__PURE__ */ jsx8(TableBody2, { children: ids.map((id) => {
102
+ /* @__PURE__ */ jsx2(TableBody, { children: ids.map((id) => {
505
103
  const site = siteFor(id, cmsConfig);
506
104
  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") }) }) })
105
+ return /* @__PURE__ */ jsxs2(TableRow, { children: [
106
+ /* @__PURE__ */ jsx2(TableCell, { className: "font-mono text-xs", children: id }),
107
+ /* @__PURE__ */ jsx2(TableCell, { className: "font-medium", children: site.name }),
108
+ /* @__PURE__ */ jsx2(TableCell, { className: "text-sm text-muted-foreground", children: site.url }),
109
+ /* @__PURE__ */ jsx2(TableCell, { className: "text-sm text-muted-foreground", children: domains.length > 0 ? domains.join(", ") : "\u2014" }),
110
+ /* @__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
111
  ] }, id);
514
112
  }) })
515
113
  ] }) })
@@ -519,9 +117,9 @@ function createSitesListPage(admin) {
519
117
  }
520
118
 
521
119
  // src/pages/site-edit.tsx
522
- import Link4 from "next/link";
120
+ import Link2 from "next/link";
523
121
  import { siteFor as siteFor2 } from "ampless";
524
- import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
122
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
525
123
  function createSiteEditPage(admin) {
526
124
  const { cmsConfig, t, loadSiteSettings } = admin;
527
125
  async function EditSitePage({ params }) {
@@ -546,10 +144,10 @@ function createSiteEditPage(admin) {
546
144
  dateFormat: settings.dateFormat,
547
145
  timezone: settings.timezone
548
146
  };
549
- return /* @__PURE__ */ jsxs8("div", { className: "p-8", children: [
550
- /* @__PURE__ */ jsxs8("div", { className: "mb-8", children: [
551
- /* @__PURE__ */ jsxs8(
552
- Link4,
147
+ return /* @__PURE__ */ jsxs3("div", { className: "p-8", children: [
148
+ /* @__PURE__ */ jsxs3("div", { className: "mb-8", children: [
149
+ /* @__PURE__ */ jsxs3(
150
+ Link2,
553
151
  {
554
152
  href: "/admin/sites",
555
153
  className: "text-sm text-muted-foreground hover:underline",
@@ -559,14 +157,14 @@ function createSiteEditPage(admin) {
559
157
  ]
560
158
  }
561
159
  ),
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: [
160
+ /* @__PURE__ */ jsx3("h1", { className: "mt-2 text-3xl font-bold", children: settings.site.name }),
161
+ /* @__PURE__ */ jsxs3("p", { className: "text-sm text-muted-foreground", children: [
564
162
  t("common.siteId"),
565
163
  ": ",
566
- /* @__PURE__ */ jsx9("code", { className: "font-mono", children: siteId })
164
+ /* @__PURE__ */ jsx3("code", { className: "font-mono", children: siteId })
567
165
  ] }),
568
- /* @__PURE__ */ jsx9("div", { className: "mt-4", children: /* @__PURE__ */ jsx9(
569
- Link4,
166
+ /* @__PURE__ */ jsx3("div", { className: "mt-4", children: /* @__PURE__ */ jsx3(
167
+ Link2,
570
168
  {
571
169
  href: `/admin/sites/${siteId}/theme`,
572
170
  className: "text-sm font-medium underline",
@@ -574,16 +172,16 @@ function createSiteEditPage(admin) {
574
172
  }
575
173
  ) })
576
174
  ] }),
577
- /* @__PURE__ */ jsx9(SiteSettingsForm, { siteId, initial, fallback })
175
+ /* @__PURE__ */ jsx3(SiteSettingsForm, { siteId, initial, fallback })
578
176
  ] });
579
177
  }
580
178
  return EditSitePage;
581
179
  }
582
180
 
583
181
  // src/pages/site-theme.tsx
584
- import Link5 from "next/link";
182
+ import Link3 from "next/link";
585
183
  import { siteFor as siteFor3, resolveLocalized } from "ampless";
586
- import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
184
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
587
185
  function createSiteThemePage(admin, themeList) {
588
186
  const { cmsConfig, t, locale, loadThemeConfig } = admin;
589
187
  async function ThemePage({ params }) {
@@ -595,10 +193,10 @@ function createSiteThemePage(admin, themeList) {
595
193
  label: m.manifest.label,
596
194
  description: m.manifest.description
597
195
  }));
598
- return /* @__PURE__ */ jsxs9("div", { className: "p-8", children: [
599
- /* @__PURE__ */ jsxs9("div", { className: "mb-8", children: [
600
- /* @__PURE__ */ jsxs9(
601
- Link5,
196
+ return /* @__PURE__ */ jsxs4("div", { className: "p-8", children: [
197
+ /* @__PURE__ */ jsxs4("div", { className: "mb-8", children: [
198
+ /* @__PURE__ */ jsxs4(
199
+ Link3,
602
200
  {
603
201
  href: `/admin/sites/${siteId}`,
604
202
  className: "text-sm text-muted-foreground hover:underline",
@@ -608,18 +206,18 @@ function createSiteThemePage(admin, themeList) {
608
206
  ]
609
207
  }
610
208
  ),
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: [
209
+ /* @__PURE__ */ jsx4("h1", { className: "mt-2 text-3xl font-bold", children: t("theme.title") }),
210
+ /* @__PURE__ */ jsxs4("p", { className: "text-sm text-muted-foreground", children: [
613
211
  t("common.active"),
614
212
  ":",
615
213
  " ",
616
- /* @__PURE__ */ jsx10("strong", { children: resolveLocalized(theme.manifest.label, locale) }),
214
+ /* @__PURE__ */ jsx4("strong", { children: resolveLocalized(theme.manifest.label, locale) }),
617
215
  " (",
618
216
  theme.activeTheme,
619
217
  ")"
620
218
  ] })
621
219
  ] }),
622
- /* @__PURE__ */ jsx10(
220
+ /* @__PURE__ */ jsx4(
623
221
  ThemeSettingsForm,
624
222
  {
625
223
  siteId,
@@ -635,194 +233,6 @@ function createSiteThemePage(admin, themeList) {
635
233
  }
636
234
 
637
235
  // 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("");
674
- }
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);
726
- }
727
- }
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
- ] }) });
825
- }
826
236
  function createLoginPage(_admin) {
827
237
  return LoginPage;
828
238
  }