@ampless/admin 0.2.0-alpha.0 → 0.2.0-alpha.10

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.
@@ -0,0 +1,42 @@
1
+ // src/lib/media.ts
2
+ var state = { outputs: null, cmsConfig: null };
3
+ function setAdminMediaContext(outputs, cmsConfig) {
4
+ state.outputs = outputs;
5
+ state.cmsConfig = cmsConfig;
6
+ }
7
+ function publicMediaUrl(input) {
8
+ if (/^https?:\/\//.test(input)) return input;
9
+ let path = input.replace(/^\/+/, "");
10
+ if (path.startsWith("public/")) path = path.slice("public/".length);
11
+ const { outputs, cmsConfig } = state;
12
+ const delivery = cmsConfig?.media?.delivery ?? "nextjs";
13
+ if (delivery !== "s3-direct") return `/api/media/${path}`;
14
+ const storage = outputs?.storage;
15
+ if (!storage) return `/api/media/${path}`;
16
+ return `https://${storage.bucket_name}.s3.${storage.aws_region}.amazonaws.com/public/${path}`;
17
+ }
18
+ function createMedia(outputs, cmsConfig) {
19
+ const storage = outputs.storage;
20
+ function s3DirectUrl(path) {
21
+ if (!storage) return `/api/media/${path}`;
22
+ return `https://${storage.bucket_name}.s3.${storage.aws_region}.amazonaws.com/public/${path}`;
23
+ }
24
+ function urlFor(input) {
25
+ if (/^https?:\/\//.test(input)) return input;
26
+ let path = input.replace(/^\/+/, "");
27
+ if (path.startsWith("public/")) path = path.slice("public/".length);
28
+ const delivery = cmsConfig.media?.delivery ?? "nextjs";
29
+ return delivery === "s3-direct" ? s3DirectUrl(path) : `/api/media/${path}`;
30
+ }
31
+ return { publicMediaUrl: urlFor };
32
+ }
33
+
34
+ // src/lib/admin-site-cookie.ts
35
+ var ADMIN_SITE_COOKIE = "admin-site-id";
36
+
37
+ export {
38
+ setAdminMediaContext,
39
+ publicMediaUrl,
40
+ createMedia,
41
+ ADMIN_SITE_COOKIE
42
+ };
@@ -0,0 +1,149 @@
1
+ 'use client';
2
+ import {
3
+ useT
4
+ } from "./chunk-OFHKZNZS.js";
5
+
6
+ // src/components/users-list-view.tsx
7
+ import { useEffect, useState } from "react";
8
+ import { generateClient } from "aws-amplify/api";
9
+ import {
10
+ Button,
11
+ Table,
12
+ TableBody,
13
+ TableCell,
14
+ TableHead,
15
+ TableHeader,
16
+ TableRow
17
+ } from "@ampless/runtime/ui";
18
+ import { jsx, jsxs } from "react/jsx-runtime";
19
+ function isAdminRole(value) {
20
+ return value === "admin" || value === "editor" || value === "none";
21
+ }
22
+ function UsersListView({ currentUserId }) {
23
+ const t = useT();
24
+ const [users, setUsers] = useState(null);
25
+ const [loading, setLoading] = useState(true);
26
+ const [loadError, setLoadError] = useState(null);
27
+ const [rows, setRows] = useState({});
28
+ useEffect(() => {
29
+ const client = generateClient();
30
+ client.queries.listAdminUsers().then(({ data, errors }) => {
31
+ if (errors && errors.length > 0) {
32
+ const msg = errors[0]?.message ?? "listAdminUsers failed";
33
+ console.error("[users-list-view] listAdminUsers errors:", errors);
34
+ setLoadError(msg);
35
+ return;
36
+ }
37
+ const list = data ?? [];
38
+ setUsers(list);
39
+ setRows(
40
+ Object.fromEntries(
41
+ list.map((u) => [u.userId, { selected: u.role, saving: false, error: null }])
42
+ )
43
+ );
44
+ }).catch((err) => {
45
+ console.error("[users-list-view] listAdminUsers threw:", err);
46
+ setLoadError(err instanceof Error ? err.message : String(err));
47
+ }).finally(() => setLoading(false));
48
+ }, []);
49
+ function updateRow(userId, patch) {
50
+ setRows((prev) => ({
51
+ ...prev,
52
+ [userId]: { ...prev[userId], ...patch }
53
+ }));
54
+ }
55
+ async function save(userId) {
56
+ const row = rows[userId];
57
+ if (!row) return;
58
+ updateRow(userId, { saving: true, error: null });
59
+ try {
60
+ const client = generateClient();
61
+ const { data, errors } = await client.mutations.setAdminUserRole({
62
+ userId,
63
+ role: row.selected
64
+ });
65
+ if (errors && errors.length > 0) {
66
+ const msg = errors[0]?.message ?? "setAdminUserRole failed";
67
+ console.error("[users-list-view] setAdminUserRole errors:", errors);
68
+ updateRow(userId, { saving: false, error: msg });
69
+ return;
70
+ }
71
+ if (data) {
72
+ setUsers(
73
+ (prev) => (prev ?? []).map((u) => u.userId === userId ? data : u)
74
+ );
75
+ updateRow(userId, { saving: false, selected: data.role, error: null });
76
+ } else {
77
+ updateRow(userId, { saving: false });
78
+ }
79
+ } catch (err) {
80
+ console.error("[users-list-view] setAdminUserRole threw:", err);
81
+ updateRow(userId, {
82
+ saving: false,
83
+ error: err instanceof Error ? err.message : String(err)
84
+ });
85
+ }
86
+ }
87
+ return /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-7xl p-4 md:p-8", children: [
88
+ /* @__PURE__ */ jsxs("div", { className: "mb-6 md:mb-8", children: [
89
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold md:text-3xl", children: t("users.list.title") }),
90
+ /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: t("users.list.description") })
91
+ ] }),
92
+ loading ? /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: t("users.list.loading") }) : loadError ? /* @__PURE__ */ jsxs("p", { className: "text-sm text-destructive", children: [
93
+ t("users.list.error"),
94
+ ": ",
95
+ loadError
96
+ ] }) : !users || users.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: t("users.list.empty") }) : /* @__PURE__ */ jsx("div", { className: "overflow-x-auto rounded-md border", children: /* @__PURE__ */ jsxs(Table, { children: [
97
+ /* @__PURE__ */ jsx(TableHeader, { children: /* @__PURE__ */ jsxs(TableRow, { children: [
98
+ /* @__PURE__ */ jsx(TableHead, { children: t("users.list.columnEmail") }),
99
+ /* @__PURE__ */ jsx(TableHead, { children: t("users.list.columnRole") }),
100
+ /* @__PURE__ */ jsx(TableHead, { className: "w-[1%] whitespace-nowrap", children: t("users.list.columnActions") })
101
+ ] }) }),
102
+ /* @__PURE__ */ jsx(TableBody, { children: users.map((u) => {
103
+ const row = rows[u.userId];
104
+ if (!row) return null;
105
+ const isSelf = u.userId === currentUserId;
106
+ const dirty = row.selected !== u.role;
107
+ return /* @__PURE__ */ jsxs(TableRow, { children: [
108
+ /* @__PURE__ */ jsx(TableCell, { className: "font-medium", children: u.email || u.userId }),
109
+ /* @__PURE__ */ jsxs(TableCell, { children: [
110
+ /* @__PURE__ */ jsxs(
111
+ "select",
112
+ {
113
+ className: "rounded-md border bg-background px-2 py-1.5 text-sm disabled:cursor-not-allowed disabled:opacity-60",
114
+ value: row.selected,
115
+ disabled: isSelf || row.saving,
116
+ onChange: (e) => {
117
+ const next = e.target.value;
118
+ if (isAdminRole(next)) {
119
+ updateRow(u.userId, { selected: next });
120
+ }
121
+ },
122
+ children: [
123
+ /* @__PURE__ */ jsx("option", { value: "admin", children: t("users.list.roleAdmin") }),
124
+ /* @__PURE__ */ jsx("option", { value: "editor", children: t("users.list.roleEditor") }),
125
+ /* @__PURE__ */ jsx("option", { value: "none", children: t("users.list.roleNone") })
126
+ ]
127
+ }
128
+ ),
129
+ isSelf && /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-muted-foreground", children: t("users.list.cannotEditSelf") }),
130
+ row.error && /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-destructive", children: row.error })
131
+ ] }),
132
+ /* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(
133
+ Button,
134
+ {
135
+ size: "sm",
136
+ disabled: isSelf || row.saving || !dirty,
137
+ onClick: () => save(u.userId),
138
+ children: row.saving ? t("users.list.saving") : t("users.list.save")
139
+ }
140
+ ) })
141
+ ] }, u.userId);
142
+ }) })
143
+ ] }) })
144
+ ] });
145
+ }
146
+
147
+ export {
148
+ UsersListView
149
+ };
@@ -0,0 +1,10 @@
1
+ 'use server';
2
+ // src/lib/theme-actions.ts
3
+ import { updateTag } from "next/cache";
4
+ async function invalidateSiteSettingsCache(siteId) {
5
+ updateTag(`site-settings:${siteId}`);
6
+ }
7
+
8
+ export {
9
+ invalidateSiteSettingsCache
10
+ };
@@ -1,8 +1,10 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { L as Locale, D as Dictionary } from '../i18n-ByHM_Bho.js';
2
+ import { L as Locale, D as Dictionary } from '../i18n-DzXXcIQQ.js';
3
3
  import { Config, Post, ThemeManifest, LocalizedString, MediaProcessingDefaults } from 'ampless';
4
4
  import { AmplessOutputs } from '@ampless/runtime';
5
+ export { A as AdminDashboard, E as EditPostPage, L as LoginPage, M as MediaPage, N as NewPostPage, P as PostsList } from '../login-view-BKrSZLJu.js';
5
6
  import { ProcessOptions } from 'ampless/media';
7
+ export { invalidateSiteSettingsCache } from '../lib/theme-actions.js';
6
8
 
7
9
  interface ProviderProps {
8
10
  locale: Locale;
@@ -23,7 +25,33 @@ declare function useT(): (key: string, vars?: Record<string, string | number>) =
23
25
  /** Read the active locale from context (e.g. for `<html lang>` parity). */
24
26
  declare function useLocale(): Locale;
25
27
 
28
+ interface Props$3 {
29
+ outputs: AmplessOutputs;
30
+ cmsConfig: Config;
31
+ children: React.ReactNode;
32
+ }
33
+ /**
34
+ * Client-side admin bootstrap. Runs on first render of any admin route
35
+ * — configures the Amplify SDK, registers the cms.config / outputs in
36
+ * the client-side state modules, and installs the admin's posts / kv
37
+ * providers so 'ampless'-imported functions hit the AppSync client.
38
+ *
39
+ * All bootstrap calls happen synchronously during render, NOT in
40
+ * `useEffect`. React runs child useEffects before parent useEffects,
41
+ * so if `installAdminPostsProvider` were inside an effect, a child
42
+ * page's first `listPosts()` call (also in a useEffect) would race
43
+ * the install and fall back to ampless's dummy data. Synchronous
44
+ * registration guarantees the provider is in place before any child
45
+ * component mounts.
46
+ *
47
+ * All side effects are idempotent (the install functions guard with an
48
+ * `installed` flag) — mounting this multiple times (e.g. during HMR or
49
+ * remount) is safe.
50
+ */
51
+ declare function AdminProviders({ outputs, cmsConfig, children }: Props$3): react_jsx_runtime.JSX.Element;
52
+
26
53
  declare const ADMIN_SITE_COOKIE = "admin-site-id";
54
+
27
55
  /**
28
56
  * Register the cms.config for client-side multi-site lookups. Called
29
57
  * once from the admin layout factory.
@@ -80,22 +108,12 @@ declare function uploadProcessedImage(file: File, options: ProcessOptions): Prom
80
108
  url: string;
81
109
  }>;
82
110
 
83
- /**
84
- * Force-invalidate the Next.js fetch cache for a site's settings JSON.
85
- * Used by the admin theme switcher: writes to KvStore propagate to S3
86
- * via the trusted processor (~5-10s), and without this call the
87
- * `revalidate: 60` on the public-side fetch would keep serving the old
88
- * cached response for up to a minute after the rebuild.
89
- *
90
- * The cache tag matches the one used in `theme-active.ts` and
91
- * `theme-config.ts` (in `@ampless/runtime`): `site-settings:{siteId}`.
92
- */
93
- declare function invalidateSiteSettingsCache(siteId: string): Promise<void>;
94
-
95
- declare function Sidebar({ email, siteSelector, }: {
111
+ declare function Sidebar({ email, siteSelector, isAdmin, }: {
96
112
  email: string;
97
113
  /** Rendered above the main nav in multi-site mode. */
98
114
  siteSelector?: React.ReactNode;
115
+ /** Gates `adminOnly` nav entries (user management). */
116
+ isAdmin: boolean;
99
117
  }): react_jsx_runtime.JSX.Element;
100
118
 
101
119
  interface SiteOption {
@@ -166,4 +184,4 @@ interface ImageUploadDialogProps {
166
184
  }
167
185
  declare function ImageUploadDialog({ file, remaining, busy, defaults, onConfirm, onSkip, onCancel, }: ImageUploadDialogProps): react_jsx_runtime.JSX.Element | null;
168
186
 
169
- export { ADMIN_SITE_COOKIE, I18nProvider, ImageUploadDialog, type ImageUploadDialogProps, MediaPicker, MediaUploader, PostForm, Sidebar, SiteSelector, SiteSettingsForm, type SiteSettingsFormValues, ThemeSettingsForm, invalidateSiteSettingsCache, publicMediaUrl, readAdminSiteIdFromCookie, sanitizeName, setAdminCmsConfig, setAdminMediaContext, uploadProcessedImage, useLocale, useT };
187
+ export { ADMIN_SITE_COOKIE, AdminProviders, I18nProvider, ImageUploadDialog, type ImageUploadDialogProps, MediaPicker, MediaUploader, PostForm, Sidebar, SiteSelector, SiteSettingsForm, type SiteSettingsFormValues, ThemeSettingsForm, publicMediaUrl, readAdminSiteIdFromCookie, sanitizeName, setAdminCmsConfig, setAdminMediaContext, uploadProcessedImage, useLocale, useT };
@@ -1,33 +1,53 @@
1
+ 'use client';
1
2
  import {
2
- I18nProvider,
3
+ AdminDashboard,
4
+ AdminProviders,
5
+ EditPostPage,
3
6
  ImageUploadDialog,
7
+ LoginPage,
8
+ MediaPage,
4
9
  MediaPicker,
5
10
  MediaUploader,
11
+ NewPostPage,
6
12
  PostForm,
13
+ PostsList,
7
14
  Sidebar,
8
15
  SiteSelector,
9
16
  SiteSettingsForm,
10
17
  ThemeSettingsForm,
11
- invalidateSiteSettingsCache,
18
+ readAdminSiteIdFromCookie,
12
19
  sanitizeName,
13
- uploadProcessedImage,
14
- useLocale,
15
- useT
16
- } from "../chunk-BN6BW7MP.js";
20
+ setAdminCmsConfig,
21
+ uploadProcessedImage
22
+ } from "../chunk-PAL62MXF.js";
17
23
  import {
18
24
  ADMIN_SITE_COOKIE,
19
25
  publicMediaUrl,
20
- readAdminSiteIdFromCookie,
21
- setAdminCmsConfig,
22
26
  setAdminMediaContext
23
- } from "../chunk-TJR3ALRJ.js";
27
+ } from "../chunk-QMVFRT62.js";
28
+ import {
29
+ I18nProvider,
30
+ useLocale,
31
+ useT
32
+ } from "../chunk-OFHKZNZS.js";
33
+ import "../chunk-OPQ3SAZJ.js";
34
+ import {
35
+ invalidateSiteSettingsCache
36
+ } from "../chunk-VXEVLHGL.js";
24
37
  export {
25
38
  ADMIN_SITE_COOKIE,
39
+ AdminDashboard,
40
+ AdminProviders,
41
+ EditPostPage,
26
42
  I18nProvider,
27
43
  ImageUploadDialog,
44
+ LoginPage,
45
+ MediaPage,
28
46
  MediaPicker,
29
47
  MediaUploader,
48
+ NewPostPage,
30
49
  PostForm,
50
+ PostsList,
31
51
  Sidebar,
32
52
  SiteSelector,
33
53
  SiteSettingsForm,
@@ -0,0 +1,7 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ declare function UsersListView({ currentUserId }: {
4
+ currentUserId: string;
5
+ }): react_jsx_runtime.JSX.Element;
6
+
7
+ export { UsersListView };
@@ -0,0 +1,9 @@
1
+ "use client";
2
+ import {
3
+ UsersListView
4
+ } from "../chunk-UOU7KQLR.js";
5
+ import "../chunk-OFHKZNZS.js";
6
+ import "../chunk-OPQ3SAZJ.js";
7
+ export {
8
+ UsersListView
9
+ };
@@ -32,9 +32,12 @@ var sidebar = {
32
32
  posts: "Posts",
33
33
  media: "Media",
34
34
  sites: "Sites",
35
+ users: "Users",
35
36
  viewSite: "View site",
36
37
  signOut: "Sign out",
37
- site: "Site"
38
+ site: "Site",
39
+ openMenu: "Open menu",
40
+ closeMenu: "Close menu"
38
41
  };
39
42
  var dashboard = {
40
43
  title: "Dashboard",
@@ -74,6 +77,20 @@ var posts = {
74
77
  tagsPlaceholder: "comma, separated, tags",
75
78
  tagsHint: "Used to group posts on tag pages (e.g. /tag/tech).",
76
79
  status: "Status",
80
+ noLayout: "No layout",
81
+ noLayoutHint: "Serve this post as bare HTML — no theme header, footer, or root layout. The body is returned as the entire response. Best paired with format: HTML when the body contains a full <!DOCTYPE html>…</html> document.",
82
+ formatStaticLabel: "Static (zip / file bundle)",
83
+ "static": {
84
+ pick: "Pick a .zip or one or more files",
85
+ pickHint: "Bundle assets must reference each other with relative paths only (no leading /). The zip's contents are extracted into a directory under your post slug and served verbatim — no theme chrome.",
86
+ currentBundle: "Current bundle: {count} files (entry: {entrypoint})",
87
+ pendingBundle: "Pending upload: {count} files, {size}",
88
+ issuesTitle: "{count} validation issue(s)",
89
+ issuesHint: "Fix the listed paths and re-upload. Absolute (/foo) and protocol-relative (//cdn.example/foo) references break under the bundle's URL prefix.",
90
+ emptyBundle: "No usable files found in the selection.",
91
+ noBundle: "Pick a bundle before saving.",
92
+ previewHint: "Static bundles render as the served HTML at /<slug>/. Preview by saving and visiting the public URL."
93
+ },
77
94
  saveChanges: "Save changes",
78
95
  createPost: "Create post",
79
96
  "delete": "Delete",
@@ -145,6 +162,25 @@ var sites = {
145
162
  label: "Site"
146
163
  }
147
164
  };
165
+ var users = {
166
+ list: {
167
+ title: "Users",
168
+ description: "Promote signed-up users to admin or editor. Sign-ups always start with no role and must be granted access here.",
169
+ columnEmail: "Email",
170
+ columnRole: "Role",
171
+ columnActions: "Actions",
172
+ save: "Save",
173
+ saving: "Saving...",
174
+ saved: "Saved.",
175
+ cannotEditSelf: "You cannot change your own role.",
176
+ empty: "No users yet.",
177
+ loading: "Loading users...",
178
+ error: "Failed to load users",
179
+ roleAdmin: "Admin",
180
+ roleEditor: "Editor",
181
+ roleNone: "None"
182
+ }
183
+ };
148
184
  var theme = {
149
185
  title: "Theme",
150
186
  activeLabel: "Active theme",
@@ -231,6 +267,7 @@ var en = {
231
267
  media: media,
232
268
  mediaPicker: mediaPicker,
233
269
  sites: sites,
270
+ users: users,
234
271
  theme: theme,
235
272
  editor: editor,
236
273
  auth: auth,
@@ -278,9 +315,12 @@ declare const dictionaries: {
278
315
  posts: string;
279
316
  media: string;
280
317
  sites: string;
318
+ users: string;
281
319
  viewSite: string;
282
320
  signOut: string;
283
321
  site: string;
322
+ openMenu: string;
323
+ closeMenu: string;
284
324
  };
285
325
  dashboard: {
286
326
  title: string;
@@ -320,6 +360,20 @@ declare const dictionaries: {
320
360
  tagsPlaceholder: string;
321
361
  tagsHint: string;
322
362
  status: string;
363
+ noLayout: string;
364
+ noLayoutHint: string;
365
+ formatStaticLabel: string;
366
+ static: {
367
+ pick: string;
368
+ pickHint: string;
369
+ currentBundle: string;
370
+ pendingBundle: string;
371
+ issuesTitle: string;
372
+ issuesHint: string;
373
+ emptyBundle: string;
374
+ noBundle: string;
375
+ previewHint: string;
376
+ };
323
377
  saveChanges: string;
324
378
  createPost: string;
325
379
  delete: string;
@@ -391,6 +445,25 @@ declare const dictionaries: {
391
445
  label: string;
392
446
  };
393
447
  };
448
+ users: {
449
+ list: {
450
+ title: string;
451
+ description: string;
452
+ columnEmail: string;
453
+ columnRole: string;
454
+ columnActions: string;
455
+ save: string;
456
+ saving: string;
457
+ saved: string;
458
+ cannotEditSelf: string;
459
+ empty: string;
460
+ loading: string;
461
+ error: string;
462
+ roleAdmin: string;
463
+ roleEditor: string;
464
+ roleNone: string;
465
+ };
466
+ };
394
467
  theme: {
395
468
  title: string;
396
469
  activeLabel: string;
@@ -511,9 +584,12 @@ declare const dictionaries: {
511
584
  posts: string;
512
585
  media: string;
513
586
  sites: string;
587
+ users: string;
514
588
  viewSite: string;
515
589
  signOut: string;
516
590
  site: string;
591
+ openMenu: string;
592
+ closeMenu: string;
517
593
  };
518
594
  dashboard: {
519
595
  title: string;
@@ -553,6 +629,20 @@ declare const dictionaries: {
553
629
  tagsPlaceholder: string;
554
630
  tagsHint: string;
555
631
  status: string;
632
+ noLayout: string;
633
+ noLayoutHint: string;
634
+ formatStaticLabel: string;
635
+ static: {
636
+ pick: string;
637
+ pickHint: string;
638
+ currentBundle: string;
639
+ pendingBundle: string;
640
+ issuesTitle: string;
641
+ issuesHint: string;
642
+ emptyBundle: string;
643
+ noBundle: string;
644
+ previewHint: string;
645
+ };
556
646
  saveChanges: string;
557
647
  createPost: string;
558
648
  delete: string;
@@ -624,6 +714,25 @@ declare const dictionaries: {
624
714
  label: string;
625
715
  };
626
716
  };
717
+ users: {
718
+ list: {
719
+ title: string;
720
+ description: string;
721
+ columnEmail: string;
722
+ columnRole: string;
723
+ columnActions: string;
724
+ save: string;
725
+ saving: string;
726
+ saved: string;
727
+ cannotEditSelf: string;
728
+ empty: string;
729
+ loading: string;
730
+ error: string;
731
+ roleAdmin: string;
732
+ roleEditor: string;
733
+ roleNone: string;
734
+ };
735
+ };
627
736
  theme: {
628
737
  title: string;
629
738
  activeLabel: string;
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Config } from 'ampless';
2
2
  import { AmplessOutputs, EffectiveSiteSettings, EffectiveThemeConfig, Ampless } from '@ampless/runtime';
3
- import { L as Locale, D as Dictionary } from './i18n-ByHM_Bho.js';
4
- export { A as AdminLocaleStrings, g as getDictionary, r as resolveLocale, t as translate } from './i18n-ByHM_Bho.js';
3
+ import { L as Locale, D as Dictionary } from './i18n-DzXXcIQQ.js';
4
+ export { A as AdminLocaleStrings, g as getDictionary, r as resolveLocale, t as translate } from './i18n-DzXXcIQQ.js';
5
5
  import * as _aws_amplify_adapter_nextjs from '@aws-amplify/adapter-nextjs';
6
6
 
7
7
  /**
package/dist/index.js CHANGED
@@ -1,10 +1,12 @@
1
1
  import {
2
2
  ADMIN_SITE_COOKIE,
3
- createMedia,
3
+ createMedia
4
+ } from "./chunk-QMVFRT62.js";
5
+ import {
4
6
  getDictionary,
5
7
  resolveLocale,
6
8
  translate
7
- } from "./chunk-TJR3ALRJ.js";
9
+ } from "./chunk-OPQ3SAZJ.js";
8
10
 
9
11
  // src/lib/admin-site.ts
10
12
  import { cookies } from "next/headers";
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Force-invalidate the Next.js fetch cache for a site's settings JSON.
3
+ * Used by the admin theme switcher: writes to KvStore propagate to S3
4
+ * via the trusted processor (~5-10s), and without this call the
5
+ * `revalidate: 60` on the public-side fetch would keep serving the old
6
+ * cached response for up to a minute after the rebuild.
7
+ *
8
+ * The cache tag matches the one used in `theme-active.ts` and
9
+ * `theme-config.ts` (in `@ampless/runtime`): `site-settings:{siteId}`.
10
+ *
11
+ * Uses `updateTag` (Next 16+) — the read-your-own-writes variant of
12
+ * the old `revalidateTag`, which is the right semantics inside a
13
+ * server action (this entire module is `'use server'`).
14
+ */
15
+ declare function invalidateSiteSettingsCache(siteId: string): Promise<void>;
16
+
17
+ export { invalidateSiteSettingsCache };
@@ -0,0 +1,7 @@
1
+ "use server";
2
+ import {
3
+ invalidateSiteSettingsCache
4
+ } from "../chunk-VXEVLHGL.js";
5
+ export {
6
+ invalidateSiteSettingsCache
7
+ };
@@ -0,0 +1,24 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ /**
4
+ * Admin home / dashboard. Lists post counts. Marked client-side because
5
+ * it reads from the AppSync client directly (no server-rendered query
6
+ * yet — listed posts come from Amplify SDK at mount time).
7
+ */
8
+ declare function AdminDashboard(): react_jsx_runtime.JSX.Element;
9
+
10
+ declare function PostsList(): react_jsx_runtime.JSX.Element;
11
+
12
+ declare function NewPostPage(): react_jsx_runtime.JSX.Element;
13
+
14
+ declare function EditPostPage({ params }: {
15
+ params: Promise<{
16
+ postId: string;
17
+ }>;
18
+ }): react_jsx_runtime.JSX.Element;
19
+
20
+ declare function MediaPage(): react_jsx_runtime.JSX.Element;
21
+
22
+ declare function LoginPage(): react_jsx_runtime.JSX.Element;
23
+
24
+ export { AdminDashboard as A, EditPostPage as E, LoginPage as L, MediaPage as M, NewPostPage as N, PostsList as P };