@ampless/admin 0.2.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +78 -0
- package/dist/api/index.d.ts +24 -0
- package/dist/api/index.js +41 -0
- package/dist/chunk-BN6BW7MP.js +2074 -0
- package/dist/chunk-TJR3ALRJ.js +575 -0
- package/dist/components/index.d.ts +169 -0
- package/dist/components/index.js +44 -0
- package/dist/i18n-ByHM_Bho.d.ts +738 -0
- package/dist/index.d.ts +75 -0
- package/dist/index.js +115 -0
- package/dist/pages/index.d.ts +90 -0
- package/dist/pages/index.js +839 -0
- package/package.json +83 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { Config } from 'ampless';
|
|
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';
|
|
5
|
+
import * as _aws_amplify_adapter_nextjs from '@aws-amplify/adapter-nextjs';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Build a Next.js Amplify server runner from outputs. Returns the
|
|
9
|
+
* `runWithAmplifyServerContext` helper used by API routes / server
|
|
10
|
+
* components that need cookie-aware Amplify calls (auth, signed-URL
|
|
11
|
+
* media proxy).
|
|
12
|
+
*/
|
|
13
|
+
declare function createAmplifyServer(outputs: AmplessOutputs): _aws_amplify_adapter_nextjs.NextServer.CreateServerRunnerOutput;
|
|
14
|
+
type AmplifyServer = ReturnType<typeof createAmplifyServer>;
|
|
15
|
+
|
|
16
|
+
interface ServerSession {
|
|
17
|
+
userId: string;
|
|
18
|
+
email: string;
|
|
19
|
+
groups: string[];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface CreateAdminOpts {
|
|
23
|
+
outputs: AmplessOutputs;
|
|
24
|
+
cmsConfig: Config;
|
|
25
|
+
/**
|
|
26
|
+
* Optional pre-built ampless runtime instance for cross-package
|
|
27
|
+
* sharing. When omitted, admin doesn't build one — server pages
|
|
28
|
+
* (sites list / site edit / theme edit) still need
|
|
29
|
+
* `loadSiteSettings` / `loadThemeConfig`, so passing an `ampless`
|
|
30
|
+
* here lets admin reuse the same runtime your public pages already
|
|
31
|
+
* use. If not provided, the admin's server pages won't be able to
|
|
32
|
+
* load site settings.
|
|
33
|
+
*/
|
|
34
|
+
ampless?: Ampless;
|
|
35
|
+
/**
|
|
36
|
+
* Locale for admin UI strings. Pass a string code ('en', 'ja') for a
|
|
37
|
+
* built-in dictionary, or an object literal to override specific
|
|
38
|
+
* strings. Defaults to English.
|
|
39
|
+
*/
|
|
40
|
+
locale?: string | Record<string, unknown>;
|
|
41
|
+
}
|
|
42
|
+
interface Admin {
|
|
43
|
+
t(key: string, vars?: Record<string, string | number>): string;
|
|
44
|
+
readonly locale: Locale;
|
|
45
|
+
readonly dict: Dictionary;
|
|
46
|
+
getServerSession(): Promise<ServerSession | null>;
|
|
47
|
+
isAdmin(session: ServerSession | null): boolean;
|
|
48
|
+
isEditor(session: ServerSession | null): boolean;
|
|
49
|
+
readonly amplifyServer: AmplifyServer;
|
|
50
|
+
currentAdminSiteId(): Promise<string>;
|
|
51
|
+
adminSiteOptions(): Array<{
|
|
52
|
+
id: string;
|
|
53
|
+
name: string;
|
|
54
|
+
}>;
|
|
55
|
+
loadSiteSettings(siteId?: string): Promise<EffectiveSiteSettings>;
|
|
56
|
+
loadThemeConfig(siteId?: string): Promise<EffectiveThemeConfig>;
|
|
57
|
+
publicMediaUrl(input: string): string;
|
|
58
|
+
readonly outputs: AmplessOutputs;
|
|
59
|
+
readonly cmsConfig: Config;
|
|
60
|
+
readonly ampless: Ampless | null;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Wire up the admin UI from user-supplied config blobs. Returns an
|
|
64
|
+
* `Admin` instance containing everything page / API factories need —
|
|
65
|
+
* the same instance is shared by `<AdminLayout>`, `<PostForm>`,
|
|
66
|
+
* `<SiteSelector>`, `/api/media`, etc.
|
|
67
|
+
*
|
|
68
|
+
* If `opts.ampless` is omitted, server-side pages that depend on
|
|
69
|
+
* `loadSiteSettings` / `loadThemeConfig` (the sites edit and theme
|
|
70
|
+
* pages) will throw. Pass the same runtime instance you already use on
|
|
71
|
+
* the public side for shared caching.
|
|
72
|
+
*/
|
|
73
|
+
declare function createAdmin(opts: CreateAdminOpts): Admin;
|
|
74
|
+
|
|
75
|
+
export { type Admin, type CreateAdminOpts, Dictionary, Locale, type ServerSession, createAdmin };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ADMIN_SITE_COOKIE,
|
|
3
|
+
createMedia,
|
|
4
|
+
getDictionary,
|
|
5
|
+
resolveLocale,
|
|
6
|
+
translate
|
|
7
|
+
} from "./chunk-TJR3ALRJ.js";
|
|
8
|
+
|
|
9
|
+
// src/lib/admin-site.ts
|
|
10
|
+
import { cookies } from "next/headers";
|
|
11
|
+
import { DEFAULT_SITE_ID, isMultiSite, siteFor } from "ampless";
|
|
12
|
+
function createAdminSite(cmsConfig) {
|
|
13
|
+
async function currentAdminSiteId() {
|
|
14
|
+
if (!isMultiSite(cmsConfig)) return DEFAULT_SITE_ID;
|
|
15
|
+
const sites = cmsConfig.sites ?? {};
|
|
16
|
+
const c = await cookies();
|
|
17
|
+
const v = c.get(ADMIN_SITE_COOKIE)?.value;
|
|
18
|
+
if (v && sites[v]) return v;
|
|
19
|
+
const first = Object.keys(sites)[0];
|
|
20
|
+
return first ?? DEFAULT_SITE_ID;
|
|
21
|
+
}
|
|
22
|
+
function adminSiteOptions() {
|
|
23
|
+
if (!isMultiSite(cmsConfig)) return [];
|
|
24
|
+
return Object.entries(cmsConfig.sites ?? {}).map(([id]) => ({
|
|
25
|
+
id,
|
|
26
|
+
name: siteFor(id, cmsConfig).name
|
|
27
|
+
}));
|
|
28
|
+
}
|
|
29
|
+
return { currentAdminSiteId, adminSiteOptions };
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// src/lib/amplify-server.ts
|
|
33
|
+
import { createServerRunner } from "@aws-amplify/adapter-nextjs";
|
|
34
|
+
function createAmplifyServer(outputs) {
|
|
35
|
+
return createServerRunner({
|
|
36
|
+
config: outputs
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// src/lib/auth-server.ts
|
|
41
|
+
import { cookies as cookies2 } from "next/headers";
|
|
42
|
+
import { fetchAuthSession, getCurrentUser } from "aws-amplify/auth/server";
|
|
43
|
+
function createAuthServer(server) {
|
|
44
|
+
const { runWithAmplifyServerContext } = server;
|
|
45
|
+
async function getServerSession() {
|
|
46
|
+
try {
|
|
47
|
+
const session = await runWithAmplifyServerContext({
|
|
48
|
+
nextServerContext: { cookies: cookies2 },
|
|
49
|
+
operation: async (ctx) => {
|
|
50
|
+
const authSession = await fetchAuthSession(ctx);
|
|
51
|
+
const user = await getCurrentUser(ctx);
|
|
52
|
+
const payload = authSession.tokens?.accessToken.payload;
|
|
53
|
+
const groups = payload?.["cognito:groups"] ?? [];
|
|
54
|
+
return {
|
|
55
|
+
userId: user.userId,
|
|
56
|
+
email: user.signInDetails?.loginId ?? "",
|
|
57
|
+
groups
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
return session;
|
|
62
|
+
} catch {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function isAdmin(session) {
|
|
67
|
+
return !!session && session.groups.includes("ampless-admin");
|
|
68
|
+
}
|
|
69
|
+
function isEditor(session) {
|
|
70
|
+
return !!session && (session.groups.includes("ampless-admin") || session.groups.includes("ampless-editor"));
|
|
71
|
+
}
|
|
72
|
+
return { getServerSession, isAdmin, isEditor };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// src/index.ts
|
|
76
|
+
function createAdmin(opts) {
|
|
77
|
+
const { outputs, cmsConfig, ampless: amplessIn, locale: localeOpt } = opts;
|
|
78
|
+
const { locale, dict } = resolveLocale(localeOpt);
|
|
79
|
+
const adminSite = createAdminSite(cmsConfig);
|
|
80
|
+
const amplifyServer = createAmplifyServer(outputs);
|
|
81
|
+
const auth = createAuthServer(amplifyServer);
|
|
82
|
+
const media = createMedia(outputs, cmsConfig);
|
|
83
|
+
const ampless = amplessIn ?? null;
|
|
84
|
+
function requireAmpless() {
|
|
85
|
+
if (!ampless) {
|
|
86
|
+
throw new Error(
|
|
87
|
+
"[@ampless/admin] createAdmin was called without an `ampless` runtime instance, but a method that needs one (loadSiteSettings / loadThemeConfig) was invoked. Pass `ampless` in the `createAdmin` options so admin can reuse your public-side runtime."
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
return ampless;
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
t: (key, vars) => translate(dict, key, vars),
|
|
94
|
+
locale,
|
|
95
|
+
dict,
|
|
96
|
+
getServerSession: auth.getServerSession,
|
|
97
|
+
isAdmin: auth.isAdmin,
|
|
98
|
+
isEditor: auth.isEditor,
|
|
99
|
+
amplifyServer,
|
|
100
|
+
currentAdminSiteId: adminSite.currentAdminSiteId,
|
|
101
|
+
adminSiteOptions: adminSite.adminSiteOptions,
|
|
102
|
+
loadSiteSettings: (siteId) => requireAmpless().loadSiteSettings(siteId),
|
|
103
|
+
loadThemeConfig: (siteId) => requireAmpless().loadThemeConfig(siteId),
|
|
104
|
+
publicMediaUrl: media.publicMediaUrl,
|
|
105
|
+
outputs,
|
|
106
|
+
cmsConfig,
|
|
107
|
+
ampless
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
export {
|
|
111
|
+
createAdmin,
|
|
112
|
+
getDictionary,
|
|
113
|
+
resolveLocale,
|
|
114
|
+
translate
|
|
115
|
+
};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { Admin } from '../index.js';
|
|
3
|
+
import { ThemeManifest } from 'ampless';
|
|
4
|
+
import '@ampless/runtime';
|
|
5
|
+
import '../i18n-ByHM_Bho.js';
|
|
6
|
+
import '@aws-amplify/adapter-nextjs';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Build the admin layout component. Wraps every admin route with:
|
|
10
|
+
*
|
|
11
|
+
* - An auth gate (`redirect('/login')` if the visitor isn't in the
|
|
12
|
+
* `ampless-admin` or `ampless-editor` Cognito group).
|
|
13
|
+
* - The admin sidebar (with optional multi-site selector).
|
|
14
|
+
* - An i18n provider hydrated from the resolved locale dict.
|
|
15
|
+
* - A client-side `AdminProviders` shell that configures the Amplify
|
|
16
|
+
* SDK and installs the admin's posts / kv providers once on mount.
|
|
17
|
+
*/
|
|
18
|
+
declare function createAdminLayout(admin: Admin): ({ children }: {
|
|
19
|
+
children: React.ReactNode;
|
|
20
|
+
}) => Promise<react_jsx_runtime.JSX.Element>;
|
|
21
|
+
|
|
22
|
+
declare function AdminDashboard(): react_jsx_runtime.JSX.Element;
|
|
23
|
+
/**
|
|
24
|
+
* Admin home / dashboard. Lists post counts. Marked client-side because
|
|
25
|
+
* it reads from the AppSync client directly (no server-rendered query
|
|
26
|
+
* yet — listed posts come from Amplify SDK at mount time).
|
|
27
|
+
*/
|
|
28
|
+
declare function createAdminDashboardPage(_admin: unknown): typeof AdminDashboard;
|
|
29
|
+
|
|
30
|
+
declare function PostsList(): react_jsx_runtime.JSX.Element;
|
|
31
|
+
declare function createPostsListPage(_admin: unknown): typeof PostsList;
|
|
32
|
+
|
|
33
|
+
declare function NewPostPage(): react_jsx_runtime.JSX.Element;
|
|
34
|
+
declare function createNewPostPage(_admin: unknown): typeof NewPostPage;
|
|
35
|
+
|
|
36
|
+
declare function EditPostPage({ params }: {
|
|
37
|
+
params: Promise<{
|
|
38
|
+
postId: string;
|
|
39
|
+
}>;
|
|
40
|
+
}): react_jsx_runtime.JSX.Element;
|
|
41
|
+
declare function createEditPostPage(_admin: unknown): typeof EditPostPage;
|
|
42
|
+
|
|
43
|
+
declare function MediaPage(): react_jsx_runtime.JSX.Element;
|
|
44
|
+
declare function createMediaPage(_admin: unknown): typeof MediaPage;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Sites overview. In single-site mode there's exactly one row
|
|
48
|
+
* (`default`); in multi-site mode each declared site shows up. Adding
|
|
49
|
+
* / removing sites is still done in cms.config.ts (the domains[] field
|
|
50
|
+
* is wired to DNS / SSL outside ampless's reach).
|
|
51
|
+
*/
|
|
52
|
+
declare function createSitesListPage(admin: Admin): () => Promise<react_jsx_runtime.JSX.Element>;
|
|
53
|
+
|
|
54
|
+
interface Props$1 {
|
|
55
|
+
params: Promise<{
|
|
56
|
+
siteId: string;
|
|
57
|
+
}>;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Server-rendered: pre-fills the form with the merged settings (so the
|
|
61
|
+
* editor sees what's currently effective). The form itself writes
|
|
62
|
+
* directly to KvStore via the AppSync client; no Server Action needed.
|
|
63
|
+
*/
|
|
64
|
+
declare function createSiteEditPage(admin: Admin): ({ params }: Props$1) => Promise<react_jsx_runtime.JSX.Element>;
|
|
65
|
+
|
|
66
|
+
interface Props {
|
|
67
|
+
params: Promise<{
|
|
68
|
+
siteId: string;
|
|
69
|
+
}>;
|
|
70
|
+
}
|
|
71
|
+
interface ThemeListEntry {
|
|
72
|
+
name: string;
|
|
73
|
+
manifest: ThemeManifest;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Theme admin: pick which installed theme is active for this site, plus
|
|
77
|
+
* edit the active theme's customizable manifest fields. Reads through
|
|
78
|
+
* the S3 site-settings cache (same path the public site uses) so the
|
|
79
|
+
* admin sees the same effective state visitors see.
|
|
80
|
+
*
|
|
81
|
+
* The full `themeList` (one entry per installed theme manifest) is
|
|
82
|
+
* passed in because the registry lives in the user's project — admin
|
|
83
|
+
* stays agnostic of which themes a project happens to install.
|
|
84
|
+
*/
|
|
85
|
+
declare function createSiteThemePage(admin: Admin, themeList: ReadonlyArray<ThemeListEntry>): ({ params }: Props) => Promise<react_jsx_runtime.JSX.Element>;
|
|
86
|
+
|
|
87
|
+
declare function LoginPage(): react_jsx_runtime.JSX.Element;
|
|
88
|
+
declare function createLoginPage(_admin: unknown): typeof LoginPage;
|
|
89
|
+
|
|
90
|
+
export { createAdminDashboardPage, createAdminLayout, createEditPostPage, createLoginPage, createMediaPage, createNewPostPage, createPostsListPage, createSiteEditPage, createSiteThemePage, createSitesListPage };
|