@botlr/next 0.1.0 → 0.2.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/CHANGELOG.md +16 -0
- package/README.md +72 -20
- package/dist/index.cjs +570 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +326 -3
- package/dist/index.d.ts +326 -3
- package/dist/index.js +551 -3
- package/dist/index.js.map +1 -1
- package/package.json +5 -3
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server.ts","../src/env.ts","../src/locale.ts","../src/index.ts"],"sourcesContent":["import { headers } from \"next/headers\";\nimport { cache } from \"react\";\nimport { createBotlrClient, type BotlrClient } from \"@botlr/sdk\";\nimport { configFromEnv } from \"./env\";\nimport { localeFromAcceptLanguage } from \"./locale\";\n\nexport type GetBotlrParams = {\n /** The app instance ID. Falls back to `BOTLR_APP_ID`. */\n appId?: string;\n /** Locale override; defaults to the request's `Accept-Language`, then `en`. */\n locale?: string;\n preview?: boolean;\n /** Site token; falls back to `BOTLR_API_KEY`. Omit in dev mode. */\n apiKey?: string;\n /** Preview JWT, forwarded to `/api/resolve` in preview mode. */\n previewToken?: string;\n /** API origin; falls back to `BOTLR_API_URL`. */\n baseUrl?: string;\n fetch?: typeof fetch;\n};\n\n/**\n * A Botlr client for the current request, for Server Components, route\n * handlers and server actions. Reads the locale from `Accept-Language`\n * unless given.\n *\n * ```ts\n * const botlr = await getBotlrForRoute({ appId: scope.appInstanceId, locale: scope.locale, preview });\n * const pages = await botlr.getPageList({ tags: [\"news\"] });\n * ```\n */\nexport async function getBotlrForRoute(params: GetBotlrParams = {}): Promise<BotlrClient> {\n const h = await headers();\n const locale = params.locale || localeFromAcceptLanguage(h.get(\"accept-language\"));\n return createBotlrClient(\n configFromEnv({\n appId: params.appId,\n apiKey: params.apiKey,\n baseUrl: params.baseUrl,\n previewToken: params.previewToken,\n locale,\n preview: params.preview,\n fetch: params.fetch,\n }),\n );\n}\n\n/**\n * `getBotlrForRoute` memoised per request with React `cache`, so several\n * components in one render share a client.\n */\nexport const getCachedBotlr: (params?: GetBotlrParams) => Promise<BotlrClient> = cache(getBotlrForRoute);\n\n/**\n * A client from the environment alone, with no request context. For scripts,\n * `generateStaticParams`, instrumentation and anywhere `headers()` is not\n * available.\n */\nexport function createBotlrFromEnv(overrides: Partial<GetBotlrParams> = {}): BotlrClient {\n return createBotlrClient(configFromEnv(overrides));\n}\n","import type { BotlrClientConfig } from \"@botlr/sdk\";\n\n/** Environment variables the helpers read. All server-side: the API URL is never exposed to the browser. */\nexport const BOTLR_ENV = {\n apiUrl: \"BOTLR_API_URL\",\n apiKey: \"BOTLR_API_KEY\",\n appId: \"BOTLR_APP_ID\",\n pat: \"BOTLR_PAT\",\n} as const;\n\nexport const DEFAULT_API_URL = \"http://localhost:8888\";\n\nfunction env(name: string): string | undefined {\n const value = typeof process !== \"undefined\" ? process.env?.[name] : undefined;\n return value === \"\" ? undefined : value;\n}\n\n/**\n * Client config from the environment, with `overrides` winning. Throws when\n * no app id is known, since every Botlr request needs one.\n */\nexport function configFromEnv(overrides: Partial<BotlrClientConfig> = {}): BotlrClientConfig {\n const appId = overrides.appId ?? env(BOTLR_ENV.appId);\n if (!appId) {\n throw new Error(`@botlr/next: pass appId or set ${BOTLR_ENV.appId}`);\n }\n return {\n ...overrides,\n baseUrl: overrides.baseUrl ?? env(BOTLR_ENV.apiUrl) ?? DEFAULT_API_URL,\n appId,\n apiKey: overrides.apiKey ?? env(BOTLR_ENV.apiKey),\n personalToken: overrides.personalToken ?? env(BOTLR_ENV.pat),\n };\n}\n","/** The first language of an `Accept-Language` value, or `fallback`. */\nexport function localeFromAcceptLanguage(header: string | null | undefined, fallback = \"en\"): string {\n if (!header) return fallback;\n const first = header.split(\",\")[0]?.split(\";\")[0]?.trim();\n return first || fallback;\n}\n","export { getBotlrForRoute, getCachedBotlr, createBotlrFromEnv, type GetBotlrParams } from \"./server\";\nexport { configFromEnv, BOTLR_ENV, DEFAULT_API_URL } from \"./env\";\nexport { localeFromAcceptLanguage } from \"./locale\";\n\nexport * from \"@botlr/react\";\nexport type * from \"@botlr/sdk\";\nexport { BotlrError, BotlrConflictError, createBotlrClient } from \"@botlr/sdk\";\n"],"mappings":";AAAA,SAAS,eAAe;AACxB,SAAS,aAAa;AACtB,SAAS,yBAA2C;;;ACC7C,IAAM,YAAY;AAAA,EACvB,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,KAAK;AACP;AAEO,IAAM,kBAAkB;AAE/B,SAAS,IAAI,MAAkC;AAC7C,QAAM,QAAQ,OAAO,YAAY,cAAc,QAAQ,MAAM,IAAI,IAAI;AACrE,SAAO,UAAU,KAAK,SAAY;AACpC;AAMO,SAAS,cAAc,YAAwC,CAAC,GAAsB;AAC3F,QAAM,QAAQ,UAAU,SAAS,IAAI,UAAU,KAAK;AACpD,MAAI,CAAC,OAAO;AACV,UAAM,IAAI,MAAM,kCAAkC,UAAU,KAAK,EAAE;AAAA,EACrE;AACA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,SAAS,UAAU,WAAW,IAAI,UAAU,MAAM,KAAK;AAAA,IACvD;AAAA,IACA,QAAQ,UAAU,UAAU,IAAI,UAAU,MAAM;AAAA,IAChD,eAAe,UAAU,iBAAiB,IAAI,UAAU,GAAG;AAAA,EAC7D;AACF;;;AChCO,SAAS,yBAAyB,QAAmC,WAAW,MAAc;AACnG,MAAI,CAAC,OAAQ,QAAO;AACpB,QAAM,QAAQ,OAAO,MAAM,GAAG,EAAE,CAAC,GAAG,MAAM,GAAG,EAAE,CAAC,GAAG,KAAK;AACxD,SAAO,SAAS;AAClB;;;AF0BA,eAAsB,iBAAiB,SAAyB,CAAC,GAAyB;AACxF,QAAM,IAAI,MAAM,QAAQ;AACxB,QAAM,SAAS,OAAO,UAAU,yBAAyB,EAAE,IAAI,iBAAiB,CAAC;AACjF,SAAO;AAAA,IACL,cAAc;AAAA,MACZ,OAAO,OAAO;AAAA,MACd,QAAQ,OAAO;AAAA,MACf,SAAS,OAAO;AAAA,MAChB,cAAc,OAAO;AAAA,MACrB;AAAA,MACA,SAAS,OAAO;AAAA,MAChB,OAAO,OAAO;AAAA,IAChB,CAAC;AAAA,EACH;AACF;AAMO,IAAM,iBAAoE,MAAM,gBAAgB;AAOhG,SAAS,mBAAmB,YAAqC,CAAC,GAAgB;AACvF,SAAO,kBAAkB,cAAc,SAAS,CAAC;AACnD;;;AGxDA,cAAc;AAEd,SAAS,YAAY,oBAAoB,qBAAAA,0BAAyB;","names":["createBotlrClient"]}
|
|
1
|
+
{"version":3,"sources":["../src/server.ts","../src/env.ts","../src/locale.ts","../src/resolve-page.ts","../src/page-metadata.ts","../src/render-cms-page.tsx","../src/theme-css.ts","../src/static-text-file.ts","../src/locale-page.tsx","../src/rate-limit.ts","../src/index.ts"],"sourcesContent":["import { headers } from \"next/headers\";\nimport { cache } from \"react\";\nimport { createBotlrClient, type BotlrClient } from \"@botlr/sdk\";\nimport { configFromEnv } from \"./env\";\nimport { localeFromAcceptLanguage } from \"./locale\";\n\nexport type GetBotlrParams = {\n /** The app instance ID. Falls back to `BOTLR_APP_ID`. */\n appId?: string;\n /** Locale override; defaults to the request's `Accept-Language`, then `en`. */\n locale?: string;\n preview?: boolean;\n /** Site token; falls back to `BOTLR_API_KEY`. Omit in dev mode. */\n apiKey?: string;\n /** Preview JWT, forwarded to `/api/resolve` in preview mode. */\n previewToken?: string;\n /** API origin; falls back to `BOTLR_API_URL`. */\n baseUrl?: string;\n fetch?: typeof fetch;\n};\n\n/**\n * A Botlr client for the current request, for Server Components, route\n * handlers and server actions. Reads the locale from `Accept-Language`\n * unless given.\n *\n * ```ts\n * const botlr = await getBotlrForRoute({ appId: scope.appInstanceId, locale: scope.locale, preview });\n * const pages = await botlr.getPageList({ tags: [\"news\"] });\n * ```\n */\nexport async function getBotlrForRoute(params: GetBotlrParams = {}): Promise<BotlrClient> {\n const h = await headers();\n const locale = params.locale || localeFromAcceptLanguage(h.get(\"accept-language\"));\n return createBotlrClient(\n configFromEnv({\n appId: params.appId,\n apiKey: params.apiKey,\n baseUrl: params.baseUrl,\n previewToken: params.previewToken,\n locale,\n preview: params.preview,\n fetch: params.fetch,\n }),\n );\n}\n\n/**\n * `getBotlrForRoute` memoised per request with React `cache`, so several\n * components in one render share a client.\n */\nexport const getCachedBotlr: (params?: GetBotlrParams) => Promise<BotlrClient> = cache(getBotlrForRoute);\n\n/**\n * A client from the environment alone, with no request context. For scripts,\n * `generateStaticParams`, instrumentation and anywhere `headers()` is not\n * available.\n */\nexport function createBotlrFromEnv(overrides: Partial<GetBotlrParams> = {}): BotlrClient {\n return createBotlrClient(configFromEnv(overrides));\n}\n","import type { BotlrClientConfig, PublisherScope } from \"@botlr/sdk\";\n\n/** Environment variables the helpers read. All server-side: the API URL is never exposed to the browser. */\nexport const BOTLR_ENV = {\n apiUrl: \"BOTLR_API_URL\",\n apiKey: \"BOTLR_API_KEY\",\n appId: \"BOTLR_APP_ID\",\n pat: \"BOTLR_PAT\",\n orgSlug: \"BOTLR_ORG_SLUG\",\n projectSlug: \"BOTLR_PROJECT_SLUG\",\n appInstanceSlug: \"BOTLR_APP_INSTANCE_SLUG\",\n environment: \"BOTLR_ENVIRONMENT\",\n} as const;\n\nexport const DEFAULT_API_URL = \"http://localhost:8888\";\n\nfunction env(name: string): string | undefined {\n const value = typeof process !== \"undefined\" ? process.env?.[name] : undefined;\n return value === \"\" ? undefined : value;\n}\n\n/**\n * Client config from the environment, with `overrides` winning. Throws when\n * no app id is known, since every Botlr request needs one.\n */\nexport function configFromEnv(overrides: Partial<BotlrClientConfig> = {}): BotlrClientConfig {\n const appId = overrides.appId ?? env(BOTLR_ENV.appId);\n if (!appId) {\n throw new Error(`@botlr/next: pass appId or set ${BOTLR_ENV.appId}`);\n }\n return {\n ...overrides,\n baseUrl: overrides.baseUrl ?? env(BOTLR_ENV.apiUrl) ?? DEFAULT_API_URL,\n appId,\n apiKey: overrides.apiKey ?? env(BOTLR_ENV.apiKey),\n personalToken: overrides.personalToken ?? env(BOTLR_ENV.pat),\n };\n}\n\n/**\n * The deployment environment used by visibility rules: `BOTLR_ENVIRONMENT`,\n * then `ENVIRONMENT`, then `NODE_ENV`, then `fallback`.\n */\nexport function environmentFromEnv(fallback = \"production\"): string {\n return env(BOTLR_ENV.environment) ?? env(\"ENVIRONMENT\") ?? env(\"NODE_ENV\") ?? fallback;\n}\n\n/**\n * The `PublisherScope` for a locale from `BOTLR_ORG_SLUG`, `BOTLR_PROJECT_SLUG`,\n * `BOTLR_APP_INSTANCE_SLUG` and `BOTLR_APP_ID`, with `overrides` winning.\n * Missing slugs become empty strings rather than errors, since only asset\n * URLs need them.\n */\nexport function scopeFromEnv(overrides: Partial<PublisherScope> & Pick<PublisherScope, \"locale\">): PublisherScope {\n return {\n orgSlug: env(BOTLR_ENV.orgSlug) ?? \"\",\n projectSlug: env(BOTLR_ENV.projectSlug) ?? \"\",\n appInstanceSlug: env(BOTLR_ENV.appInstanceSlug) ?? \"\",\n appInstanceId: env(BOTLR_ENV.appId) ?? \"\",\n ...overrides,\n };\n}\n","/** The first language of an `Accept-Language` value, or `fallback`. */\nexport function localeFromAcceptLanguage(header: string | null | undefined, fallback = \"en\"): string {\n if (!header) return fallback;\n const first = header.split(\",\")[0]?.split(\";\")[0]?.trim();\n return first || fallback;\n}\n","import { cache } from \"react\";\nimport type { BotlrClient, InlineSectionInstance, PageResponse } from \"@botlr/sdk\";\n\nexport type ResolvedPage =\n | { kind: \"page\"; pageData: PageResponse }\n | { kind: \"redirect\"; destination: string }\n | { kind: \"404\" }\n | { kind: \"error\"; message: string };\n\nexport interface ResolvePageOptions {\n /**\n * Non-page content types rendered through a section: the resolved content\n * is prepended to the `main` region as an inline section of the mapped\n * type. Defaults to `{ article: \"article\" }`.\n */\n contentSections?: Record<string, string>;\n}\n\nconst DEFAULT_CONTENT_SECTIONS: Record<string, string> = { article: \"article\" };\n\n/**\n * Resolves a slug to a page through `/api/resolve`, folding redirects, 404s\n * and errors into one result and injecting article content into the layout.\n * Not cached; see `createPageResolver`.\n */\nexport async function resolvePage(\n client: BotlrClient,\n slug: string,\n locale?: string,\n options: ResolvePageOptions = {},\n): Promise<ResolvedPage> {\n try {\n const result = await client.resolveUrl(slug, locale);\n\n if (result.kind === \"404\") return { kind: \"404\" };\n if (result.kind === \"redirect\" && result.redirect) {\n return { kind: \"redirect\", destination: result.redirect.destination };\n }\n if (!result.data) return { kind: \"404\" };\n\n const data = result.data;\n const layout = data.layout ?? {};\n\n const content = data.content ?? {};\n const contentType: string | null = content[\"type\"] ?? data.type ?? null;\n if (contentType && contentType !== \"page\") {\n const sectionType = (options.contentSections ?? DEFAULT_CONTENT_SECTIONS)[contentType];\n if (sectionType) {\n const section: InlineSectionInstance = {\n _key: `${sectionType}-${content[\"id\"] ?? data.id}`,\n mode: \"inline\",\n sectionType,\n props: content,\n status: \"published\",\n };\n layout[\"main\"] = [section, ...(layout[\"main\"] ?? [])];\n } else {\n console.warn(\"Unknown content type:\", contentType);\n }\n }\n\n return {\n kind: \"page\",\n pageData: {\n id: data.id,\n name: data.name,\n slug: data.slug || \"\",\n full_slug: data.full_slug || \"\",\n layout,\n status: data.status,\n theme: data.theme,\n page_template: data.page_template,\n seo_meta: data.seo_meta,\n alternate_translations: result.alternate_translations ?? [],\n breadcrumbs: result.breadcrumbs ?? [],\n },\n };\n } catch (error) {\n return {\n kind: \"error\",\n message: error instanceof Error ? error.message : \"Unknown error\",\n };\n }\n}\n\n/**\n * `resolvePage` bound to a client and memoised per request with React\n * `cache`, so `generateMetadata` and the page share one fetch.\n *\n * ```ts\n * const resolvePage = createPageResolver(botlr);\n * const resolved = await resolvePage(\"about/team\", \"en\");\n * ```\n */\nexport function createPageResolver(\n client: BotlrClient,\n options: ResolvePageOptions = {},\n): (slug: string, locale?: string) => Promise<ResolvedPage> {\n return cache((slug: string, locale?: string) => resolvePage(client, slug, locale, options));\n}\n","import type { Metadata } from \"next\";\nimport type { PageResponse } from \"@botlr/sdk\";\n\nexport interface PageMetadataOptions {\n /**\n * The site origin, for example `https://www.example.com`. Needed for the\n * canonical URL and hreflang alternates; without it only an explicit\n * `seo_meta.canonical` is emitted.\n */\n siteUrl?: string;\n /** URL prefix of the page's locale, for example `/en`. Empty for the root locale. */\n folder?: string;\n}\n\n/**\n * Next.js `Metadata` from a page's `seo_meta`: title, description, keywords,\n * Open Graph, Twitter, robots, canonical and hreflang alternates.\n */\nexport function buildPageMetadata(pageData: PageResponse, options: PageMetadataOptions = {}): Metadata {\n const seo = pageData.seo_meta || {};\n const title = seo.title || pageData.name;\n const alternates = pageData.alternate_translations || [];\n const siteUrl = options.siteUrl?.replace(/\\/+$/, \"\");\n const folder = options.folder ? `/${options.folder.replace(/^\\/+|\\/+$/g, \"\")}` : \"\";\n\n const metadata: Metadata = { title };\n\n if (seo.description) metadata.description = seo.description;\n if (seo.keywords) metadata.keywords = seo.keywords;\n\n const ogImage = seo.ogImage?.url || seo.ogImage?.filename;\n const description = seo.ogDescription || seo.description;\n metadata.openGraph = {\n title: seo.ogTitle || title,\n ...(description ? { description } : {}),\n ...(seo.ogType ? { type: seo.ogType } : {}),\n ...(ogImage ? { images: [ogImage] } : {}),\n };\n\n if (seo.twitterCard) {\n metadata.twitter = {\n card: seo.twitterCard,\n title: seo.ogTitle || title,\n ...(description ? { description } : {}),\n ...(ogImage ? { images: [ogImage] } : {}),\n };\n }\n\n if (seo.noindex !== undefined || seo.nofollow !== undefined || seo.robots) {\n metadata.robots = seo.robots ?? { index: !seo.noindex, follow: !seo.nofollow };\n }\n\n if (seo.canonical) {\n metadata.alternates = { canonical: seo.canonical };\n } else if (siteUrl) {\n const canonical = pageData.full_slug\n ? `${siteUrl}${folder}/${pageData.full_slug}`\n : `${siteUrl}${folder}`;\n metadata.alternates = { canonical };\n }\n\n if (siteUrl && alternates.length > 0) {\n const languages: Record<string, string> = {};\n for (const alt of alternates) {\n languages[alt.locale] = `${siteUrl}${alt.full_slug}`;\n }\n metadata.alternates = { ...metadata.alternates, languages };\n }\n\n return metadata;\n}\n","import type { JSX, ReactNode } from \"react\";\nimport parse, { type HTMLReactParserOptions } from \"html-react-parser\";\nimport {\n SectionRenderer,\n filterVisibleNodesRecursive,\n type ComponentRegistry,\n type VisibilityContext,\n} from \"@botlr/react\";\nimport type { BotlrClient, LayoutNode, PageResponse, PageScope, PublisherScope } from \"@botlr/sdk\";\nimport { environmentFromEnv } from \"./env\";\nimport { themeSettingsToCss } from \"./theme-css\";\n\ntype Layout = Record<string, LayoutNode[]>;\n\nexport interface RenderCmsPageOptions {\n pageData: PageResponse;\n scope: PublisherScope;\n /** Section type to component map used for every region. */\n componentRegistry: ComponentRegistry;\n /** Defaults to `\"published\"`; `\"draft\"` also renders draft sections. */\n mode?: \"draft\" | \"published\";\n /** Defaults to `scope.locale`. */\n locale?: string;\n /** Environment for visibility rules; defaults to `environmentFromEnv()`. */\n environment?: string;\n /** Used to fetch shared sections unless `fetchSharedSection` is given. */\n client?: BotlrClient;\n /** Fetch a shared section's page by id. Defaults to `client.getPageBySlug(id, locale)`. */\n fetchSharedSection?: (id: string) => Promise<{ layout?: Partial<Layout> } | null>;\n /** Show a fixed \"draft/published preview\" badge; for preview routes only. */\n showModeBadge?: boolean;\n /** Rendered when the template cannot be parsed. */\n renderError?: (error: unknown) => ReactNode;\n}\n\nconst DEFAULT_TEMPLATE = `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>__PAGE_TITLE__</title>\n <style>\n * { margin: 0; padding: 0; box-sizing: border-box; }\n body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; }\n </style>\n __THEME_CSS__\n</head>\n<body>\n <main>\n __REGION_MAIN__\n </main>\n</body>\n</html>`;\n\nfunction extractBodyContent(html: string): string {\n const bodyMatch = html.match(/<body[^>]*>([\\s\\S]*)<\\/body>/i);\n return bodyMatch?.[1] ? bodyMatch[1].trim() : html;\n}\n\n/** Ids of every shared section in the layout, grid columns included. */\nexport function collectSharedSectionIds(nodes: LayoutNode[]): string[] {\n const ids: string[] = [];\n for (const node of nodes) {\n if (\"mode\" in node && node.mode === \"shared\" && node.sharedSectionId) {\n ids.push(node.sharedSectionId);\n }\n if (\"type\" in node && node.type === \"grid-container\" && Array.isArray(node.columns)) {\n for (const column of node.columns) {\n if (Array.isArray(column.sections)) ids.push(...collectSharedSectionIds(column.sections));\n }\n }\n }\n return ids;\n}\n\n/**\n * The template's `{{...}}` placeholders resolved: title, lang, theme css,\n * `{{{REGION}}}` markers turned into text markers for the parser, and the\n * body extracted.\n */\nexport function prepareTemplate(templateHtml: string, pageData: PageResponse, templateCss: string, locale: string): string {\n let prepared = templateHtml\n .replace(/\\{\\{page_title\\}\\}/g, pageData.name)\n .replace(/\\{\\{page_lang\\}\\}/g, locale)\n .replace(/\\{\\{page_description\\}\\}/g, \"\");\n\n prepared = prepared.replace(/\\{\\{\\{theme_css\\}\\}\\}/g, templateCss ? `<style>${templateCss}</style>` : \"\");\n prepared = prepared.replace(/\\{\\{\\{([A-Z_]+)\\}\\}\\}/g, \"__REGION_$1__\");\n prepared = prepared.replace(/\\{\\{#if\\s+([A-Z_]+)\\}\\}/g, \"\");\n prepared = prepared.replace(/\\{\\{\\/if\\}\\}/g, \"\");\n\n return extractBodyContent(prepared);\n}\n\n/** Template sections first, then the page's own, per region. */\nexport function mergeTemplateLayout(pageData: PageResponse): Layout {\n const merged: Layout = {};\n const regions = new Set([...Object.keys(pageData.layout), ...Object.keys(pageData.page_template?.layout ?? {})]);\n for (const region of regions) {\n merged[region] = [...(pageData.page_template?.layout?.[region] ?? []), ...(pageData.layout[region] ?? [])];\n }\n return merged;\n}\n\nconst errorBox = (heading: string, message: string): JSX.Element => (\n <div style={{ display: \"flex\", alignItems: \"center\", justifyContent: \"center\", minHeight: \"100vh\" }}>\n <div style={{ textAlign: \"center\" }}>\n <h1 style={{ fontSize: \"1.5rem\", fontWeight: 700, marginBottom: \"0.5rem\" }}>{heading}</h1>\n <p style={{ opacity: 0.7 }}>{message}</p>\n </div>\n </div>\n);\n\n/**\n * Renders a resolved page: picks the page template (page, then theme, then a\n * built-in default), merges template and page layouts, applies visibility\n * rules, fetches shared sections and mounts a `SectionRenderer` at every\n * `{{{REGION}}}` marker.\n */\nexport async function renderCmsPage({\n pageData,\n scope,\n componentRegistry,\n mode = \"published\",\n locale = scope.locale,\n environment = environmentFromEnv(),\n client,\n fetchSharedSection,\n showModeBadge = false,\n renderError,\n}: RenderCmsPageOptions): Promise<JSX.Element> {\n let templateHtml: string;\n let templateCss = \"\";\n\n if (pageData.page_template?.template_html) {\n templateHtml = pageData.page_template.template_html;\n templateCss = pageData.page_template.template_css || \"\";\n } else if (pageData.theme?.default_template_html) {\n templateHtml = pageData.theme.default_template_html;\n templateCss = pageData.theme.default_template_css || \"\";\n } else {\n templateHtml = DEFAULT_TEMPLATE;\n }\n\n const preparedTemplate = prepareTemplate(templateHtml, pageData, templateCss, locale);\n\n const pageScope: PageScope = {\n id: pageData.id,\n kind: \"page\",\n name: pageData.name,\n slug: pageData.slug || \"\",\n breadcrumbs: pageData.breadcrumbs || [],\n };\n\n const visibilityContext: VisibilityContext = {\n pageId: pageData.id,\n currentPath: \"/\" + (pageData.slug || \"\"),\n locale,\n environment,\n };\n const filteredLayout: Layout = {};\n for (const [region, sections] of Object.entries(mergeTemplateLayout(pageData))) {\n filteredLayout[region] = filterVisibleNodesRecursive(sections, visibilityContext);\n }\n\n const fetchShared =\n fetchSharedSection ??\n (client ? (id: string) => client.getPageBySlug(id, locale) : undefined);\n const sharedSectionIds = Object.values(filteredLayout).flatMap(collectSharedSectionIds);\n const sharedSectionsMap = new Map<string, LayoutNode[]>();\n\n if (sharedSectionIds.length > 0) {\n if (!fetchShared) {\n throw new Error(\"@botlr/next: renderCmsPage needs `client` or `fetchSharedSection` to render shared sections\");\n }\n const results = await Promise.all(\n [...new Set(sharedSectionIds)].map(async (id) => {\n try {\n const data = await fetchShared(id);\n const main = data?.layout?.[\"main\"];\n if (Array.isArray(main) && main.length > 0) return { id, sections: main };\n } catch (err) {\n console.error(`Error fetching shared section ${id}:`, err);\n }\n return null;\n }),\n );\n for (const result of results) {\n if (result) sharedSectionsMap.set(result.id, result.sections);\n }\n }\n\n const parseOptions: HTMLReactParserOptions = {\n replace: (domNode) => {\n if (!(\"data\" in domNode) || typeof domNode.data !== \"string\") return;\n const regionMatch = domNode.data.match(/__REGION_([A-Z_]+)__/);\n if (!regionMatch?.[1]) return;\n\n const regionKey = regionMatch[1].toLowerCase();\n const regionSections = filteredLayout[regionKey] ?? [];\n if (regionSections.length === 0) return <></>;\n\n const templateSectionKeys = new Set(\n (pageData.page_template?.layout?.[regionKey] ?? []).map((section) => section._key),\n );\n\n return (\n <>\n {regionSections.map((section) => (\n <SectionRenderer\n key={section._key}\n section={section}\n componentRegistry={componentRegistry}\n mode={mode}\n sharedSectionsData={sharedSectionsMap}\n scope={scope}\n pageScope={pageScope}\n fromTemplate={templateSectionKeys.has(section._key)}\n />\n ))}\n </>\n );\n },\n };\n\n const themeSettingsCss = themeSettingsToCss(pageData.theme?.settings);\n\n try {\n const renderedContent = parse(preparedTemplate, parseOptions);\n\n return (\n <>\n {themeSettingsCss && <style dangerouslySetInnerHTML={{ __html: themeSettingsCss }} />}\n {templateCss && <style dangerouslySetInnerHTML={{ __html: templateCss }} />}\n {renderedContent}\n {showModeBadge && (\n <div\n style={{\n position: \"fixed\",\n bottom: \"1rem\",\n right: \"1rem\",\n padding: \"0.5rem 1rem\",\n borderRadius: \"0.5rem\",\n background: \"#111\",\n color: \"#fff\",\n fontSize: \"0.875rem\",\n fontWeight: 500,\n boxShadow: \"0 4px 12px rgba(0,0,0,0.2)\",\n zIndex: 50,\n }}\n >\n {mode === \"draft\" ? \"Draft preview\" : \"Published preview\"}\n </div>\n )}\n </>\n );\n } catch (error) {\n console.error(\"Error rendering template:\", error);\n if (renderError) return <>{renderError(error)}</>;\n return errorBox(\"Template Error\", error instanceof Error ? error.message : \"Failed to render template\");\n }\n}\n\nexport { errorBox as renderErrorBox };\n","export interface ThemeColorSet {\n primary?: string;\n primaryForeground?: string;\n secondary?: string;\n secondaryForeground?: string;\n accent?: string;\n accentForeground?: string;\n background?: string;\n foreground?: string;\n muted?: string;\n mutedForeground?: string;\n border?: string;\n input?: string;\n ring?: string;\n destructive?: string;\n destructiveForeground?: string;\n success?: string;\n successForeground?: string;\n warning?: string;\n warningForeground?: string;\n info?: string;\n infoForeground?: string;\n}\n\nexport interface ThemeSettings {\n colors?: { light?: ThemeColorSet; dark?: ThemeColorSet };\n typography?: {\n fontFamily?: {\n heading?: string;\n body?: string;\n ui?: string;\n code?: string;\n sans?: string;\n serif?: string;\n mono?: string;\n };\n fontSize?: {\n h1?: string; h2?: string; h3?: string; h4?: string; h5?: string; h6?: string;\n xs?: string; sm?: string; base?: string; lg?: string; xl?: string;\n \"2xl\"?: string; \"3xl\"?: string; \"4xl\"?: string;\n };\n fontWeight?: { normal?: string; medium?: string; semibold?: string; bold?: string };\n lineHeight?: { tight?: string; normal?: string; relaxed?: string };\n };\n spacing?: { xs?: string; sm?: string; md?: string; lg?: string; xl?: string; \"2xl\"?: string };\n borderRadius?: { none?: string; sm?: string; md?: string; lg?: string; xl?: string; full?: string };\n shadows?: { sm?: string; md?: string; lg?: string; xl?: string };\n layout?: {\n containerMaxWidth?: string;\n sidebarWidth?: string;\n headerHeight?: string;\n footerHeight?: string;\n };\n}\n\nconst COLOR_KEYS: (keyof ThemeColorSet)[] = [\n \"primary\", \"primaryForeground\", \"secondary\", \"secondaryForeground\", \"accent\", \"accentForeground\",\n \"background\", \"foreground\", \"muted\", \"mutedForeground\", \"border\", \"input\", \"ring\",\n \"destructive\", \"destructiveForeground\", \"success\", \"successForeground\",\n \"warning\", \"warningForeground\", \"info\", \"infoForeground\",\n];\n\n/** Groups of common variables, in output order: [settings path, css prefix, keys]. */\nconst COMMON_GROUPS: [string[], string, string[]][] = [\n [[\"typography\", \"fontFamily\"], \"--font\", [\"heading\", \"body\", \"ui\", \"code\", \"sans\", \"serif\", \"mono\"]],\n [[\"typography\", \"fontSize\"], \"--font-size\", [\"h1\", \"h2\", \"h3\", \"h4\", \"h5\", \"h6\", \"xs\", \"sm\", \"base\", \"lg\", \"xl\", \"2xl\", \"3xl\", \"4xl\"]],\n [[\"typography\", \"fontWeight\"], \"--font-weight\", [\"normal\", \"medium\", \"semibold\", \"bold\"]],\n [[\"typography\", \"lineHeight\"], \"--line-height\", [\"tight\", \"normal\", \"relaxed\"]],\n [[\"spacing\"], \"--spacing\", [\"xs\", \"sm\", \"md\", \"lg\", \"xl\", \"2xl\"]],\n [[\"borderRadius\"], \"--radius\", [\"none\", \"sm\", \"md\", \"lg\", \"xl\", \"full\"]],\n [[\"shadows\"], \"--shadow\", [\"sm\", \"md\", \"lg\", \"xl\"]],\n [[\"layout\"], \"-\", [\"containerMaxWidth\", \"sidebarWidth\", \"headerHeight\", \"footerHeight\"]],\n];\n\nconst kebab = (key: string): string => key.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`);\n\nfunction colorVars(colors: ThemeColorSet | undefined): string[] {\n if (!colors) return [];\n const vars: string[] = [];\n for (const key of COLOR_KEYS) {\n const value = colors[key];\n if (value) vars.push(`--color-${kebab(key)}: ${value};`);\n }\n return vars;\n}\n\nfunction pick(settings: Record<string, any>, path: string[]): Record<string, string> | undefined {\n let current: any = settings;\n for (const segment of path) {\n current = current?.[segment];\n if (!current) return undefined;\n }\n return current;\n}\n\n/**\n * Theme settings as CSS custom properties: common variables and light colors\n * on `:root`, dark colors under `prefers-color-scheme: dark` and `.dark`.\n */\nexport function themeSettingsToCss(settings?: ThemeSettings | Record<string, any>): string {\n if (!settings) return \"\";\n\n const s = settings as ThemeSettings;\n const lightVars = colorVars(s.colors?.light);\n const darkVars = colorVars(s.colors?.dark);\n const commonVars: string[] = [];\n\n for (const [path, prefix, keys] of COMMON_GROUPS) {\n const group = pick(settings, path);\n if (!group) continue;\n for (const key of keys) {\n const value = group[key];\n if (value) commonVars.push(`${prefix}-${kebab(key)}: ${value};`);\n }\n }\n\n const cssBlocks: string[] = [];\n\n if (commonVars.length > 0) {\n cssBlocks.push(`:root {\\n ${commonVars.join(\"\\n \")}\\n}`);\n }\n\n if (lightVars.length > 0) {\n cssBlocks.push(`:root {\\n ${lightVars.join(\"\\n \")}\\n}`);\n }\n\n if (darkVars.length > 0) {\n cssBlocks.push(`@media (prefers-color-scheme: dark) {\\n :root {\\n ${darkVars.join(\"\\n \")}\\n }\\n}`);\n cssBlocks.push(`.dark {\\n ${darkVars.join(\"\\n \")}\\n}`);\n }\n\n return cssBlocks.join(\"\\n\\n\");\n}\n","import { filterVisibleNodesRecursive, type VisibilityContext } from \"@botlr/react\";\nimport type { BotlrClient, LayoutNode } from \"@botlr/sdk\";\nimport { environmentFromEnv } from \"./env\";\n\nexport interface StaticTextFileOptions {\n /** Defaults to the client's locale, then `en`. */\n locale?: string;\n /** Environment for visibility rules; defaults to `environmentFromEnv()`. */\n environment?: string;\n /** The section type whose content is served; defaults to `text`. */\n sectionType?: string;\n /** Section props tried in order for the text; defaults to `content`, `body`, `text`. */\n propKeys?: string[];\n}\n\nfunction collectSections(nodes: LayoutNode[], sectionType: string): LayoutNode[] {\n const result: LayoutNode[] = [];\n for (const node of nodes) {\n if (\"mode\" in node && node.mode === \"inline\" && node.sectionType === sectionType) {\n result.push(node);\n } else if (\"type\" in node && node.type === \"grid-container\" && Array.isArray(node.columns)) {\n for (const column of node.columns) {\n result.push(...collectSections(column.sections ?? [], sectionType));\n }\n }\n }\n return result;\n}\n\nconst TEXT_PLAIN = { \"Content-Type\": \"text/plain; charset=utf-8\" };\n\n/**\n * A CMS-managed plain-text file such as `robots.txt`, `humans.txt` or\n * `llms.txt`: the page at `slug`, its visible text sections concatenated.\n * Serves `defaultContent` when the page has none or cannot be fetched.\n *\n * ```ts\n * // app/robots.txt/route.ts\n * export const GET = () => serveStaticTextFile(botlr, \"robots.txt\", defaultRobotsContent());\n * ```\n */\nexport async function serveStaticTextFile(\n client: BotlrClient,\n slug: string,\n defaultContent: string,\n options: StaticTextFileOptions = {},\n): Promise<Response> {\n const locale = options.locale ?? client.config.locale ?? \"en\";\n const environment = options.environment ?? environmentFromEnv();\n const sectionType = options.sectionType ?? \"text\";\n const propKeys = options.propKeys ?? [\"content\", \"body\", \"text\"];\n\n try {\n const page = await client.getPageBySlug(slug, locale);\n if (page?.layout) {\n const visibilityContext: VisibilityContext = { locale, environment };\n const sections: LayoutNode[] = [];\n for (const region of Object.values(page.layout)) {\n if (Array.isArray(region)) {\n sections.push(...collectSections(filterVisibleNodesRecursive(region, visibilityContext), sectionType));\n }\n }\n\n const content = sections\n .map((section) => {\n const props: Record<string, unknown> = \"props\" in section ? (section.props ?? {}) : {};\n const value = propKeys.map((key) => props[key]).find((v) => typeof v === \"string\" && v);\n return typeof value === \"string\" ? value : \"\";\n })\n .filter(Boolean)\n .join(\"\\n\\n\");\n\n if (content) return new Response(content, { headers: TEXT_PLAIN });\n }\n } catch {\n // Fall through to the default\n }\n\n return new Response(defaultContent, { headers: TEXT_PLAIN });\n}\n\n/** Allow everything in production, disallow everything elsewhere. */\nexport function defaultRobotsContent(environment = environmentFromEnv()): string {\n return environment === \"production\" ? \"User-agent: *\\nAllow: /\\n\" : \"User-agent: *\\nDisallow: /\\n\";\n}\n","import type { Metadata } from \"next\";\nimport { notFound, permanentRedirect, redirect } from \"next/navigation\";\nimport type { ReactNode } from \"react\";\nimport type { ComponentRegistry } from \"@botlr/react\";\nimport type { BotlrClient, PublisherScope } from \"@botlr/sdk\";\nimport { environmentFromEnv, scopeFromEnv } from \"./env\";\nimport { buildPageMetadata } from \"./page-metadata\";\nimport { renderCmsPage, renderErrorBox } from \"./render-cms-page\";\nimport { createPageResolver, type ResolvePageOptions, type ResolvedPage } from \"./resolve-page\";\n\nexport interface LocalePageConfig {\n /** CMS locale code, for example `da` or `en`. */\n locale: string;\n /** URL prefix for this locale, for example `/en`. Empty for the root locale. */\n folder?: string;\n /** The client the pages are fetched with; usually one built with `createBotlrFromEnv`. */\n client: BotlrClient;\n componentRegistry: ComponentRegistry;\n /** Overrides on the scope built from the environment. */\n scope?: Partial<PublisherScope>;\n /** The site origin, for canonical and hreflang metadata. */\n siteUrl?: string;\n /** Environment for visibility rules; defaults to `environmentFromEnv()`. */\n environment?: string;\n resolveOptions?: ResolvePageOptions;\n /** Redirect kind for CMS redirects; defaults to `permanent` (308). */\n redirect?: \"permanent\" | \"temporary\";\n /** Page slugs fetched for `generateStaticParams`; defaults to 1000. */\n staticParamsLimit?: number;\n /** Rendered when resolving fails. */\n renderError?: (message: string) => ReactNode;\n}\n\nexport interface LocalePageProps {\n params: Promise<{ slug?: string[] }>;\n searchParams?: Promise<Record<string, string | string[] | undefined>>;\n}\n\n/** The page slug for a catch-all route: the segments joined, or `index`. */\nexport async function pageSlugFromParams(params: LocalePageProps[\"params\"]): Promise<string> {\n const slug = (await params).slug ?? [];\n return slug.length > 0 ? slug.join(\"/\") : \"index\";\n}\n\n/**\n * Everything a static per-locale `[[...slug]]` route needs. The route file\n * keeps only its segment config, which Next must read statically:\n *\n * ```ts\n * // app/(root)/[[...slug]]/page.tsx\n * export const revalidate = false;\n * export const dynamicParams = false;\n * const page = createLocalePage({ locale: \"da\", folder: \"\", client: botlr, componentRegistry });\n * export const generateStaticParams = page.generateStaticParams;\n * export const generateMetadata = page.generateMetadata;\n * export default page.Page;\n * ```\n */\nexport function createLocalePage(config: LocalePageConfig) {\n const { locale, client, componentRegistry } = config;\n const folder = config.folder ? `/${config.folder.replace(/^\\/+|\\/+$/g, \"\")}` : \"\";\n const scope: PublisherScope = scopeFromEnv({ locale, localePrefix: folder.replace(/^\\//, \"\"), ...config.scope });\n const resolvePage = createPageResolver(client, config.resolveOptions);\n const sendRedirect: (url: string) => never = config.redirect === \"temporary\" ? redirect : permanentRedirect;\n\n async function generateStaticParams(): Promise<{ slug?: string[] }[]> {\n const response = await client.getPageSlugList({ locale, limit: config.staticParamsLimit ?? 1000 });\n return (response.data ?? []).map((path) => ({ slug: path ? path.split(\"/\") : [] }));\n }\n\n async function generateMetadata({ params }: LocalePageProps): Promise<Metadata> {\n const resolved = await resolvePage(await pageSlugFromParams(params), locale);\n if (resolved.kind !== \"page\") return {};\n return buildPageMetadata(resolved.pageData, { siteUrl: config.siteUrl, folder });\n }\n\n async function Page({ params }: LocalePageProps) {\n const resolved: ResolvedPage = await resolvePage(await pageSlugFromParams(params), locale);\n\n if (resolved.kind === \"error\") {\n if (config.renderError) return <>{config.renderError(resolved.message)}</>;\n return renderErrorBox(\"Error Loading Page\", resolved.message);\n }\n if (resolved.kind === \"404\") notFound();\n if (resolved.kind === \"redirect\") sendRedirect(`${folder}${resolved.destination}`);\n\n const { pageData } = resolved;\n if (pageData.status !== \"published\") notFound();\n\n return renderCmsPage({\n pageData,\n scope,\n componentRegistry,\n mode: \"published\",\n locale,\n environment: config.environment ?? environmentFromEnv(),\n client,\n });\n }\n\n return { generateStaticParams, generateMetadata, Page, resolvePage, scope };\n}\n\n/**\n * A locale folder that only aliases another, for example `/se/*` to `/sv/*`.\n * Permanently redirects, keeping the rest of the path.\n */\nexport function createLocaleAliasPage(targetFolder: string) {\n return async function AliasPage({ params }: LocalePageProps): Promise<never> {\n const slug = (await params).slug ?? [];\n permanentRedirect(`${targetFolder}/${slug.join(\"/\")}`);\n };\n}\n","type Entry = { count: number; resetAt: number };\n\nconst store = new Map<string, Entry>();\n\nexport interface RateLimitConfig {\n /** Max requests allowed in the window */\n limit: number;\n /** Window size in seconds */\n window: number;\n}\n\nexport interface RateLimitResult {\n allowed: boolean;\n remaining: number;\n /** Epoch ms when the window resets */\n resetAt: number;\n}\n\n/**\n * A fixed-window in-memory rate limit, per server instance. Enough to slow\n * down form and forum spam; not shared across instances or restarts.\n *\n * ```ts\n * const rl = rateLimit(`form:${getClientIp(request)}`, { limit: 5, window: 60 });\n * if (!rl.allowed) return new Response(\"Too many requests\", { status: 429 });\n * ```\n */\nexport function rateLimit(key: string, config: RateLimitConfig): RateLimitResult {\n const now = Date.now();\n const windowMs = config.window * 1000;\n\n let entry = store.get(key);\n\n if (!entry || now >= entry.resetAt) {\n entry = { count: 1, resetAt: now + windowMs };\n store.set(key, entry);\n return { allowed: true, remaining: config.limit - 1, resetAt: entry.resetAt };\n }\n\n entry.count++;\n const allowed = entry.count <= config.limit;\n\n return {\n allowed,\n remaining: Math.max(0, config.limit - entry.count),\n resetAt: entry.resetAt,\n };\n}\n\n/** The client IP from `x-forwarded-for` or `x-real-ip`, or `\"unknown\"`. */\nexport function getClientIp(request: Request): string {\n return (\n request.headers.get(\"x-forwarded-for\")?.split(\",\")[0]?.trim() ||\n request.headers.get(\"x-real-ip\") ||\n \"unknown\"\n );\n}\n","export { getBotlrForRoute, getCachedBotlr, createBotlrFromEnv, type GetBotlrParams } from \"./server\";\nexport { configFromEnv, scopeFromEnv, environmentFromEnv, BOTLR_ENV, DEFAULT_API_URL } from \"./env\";\nexport { localeFromAcceptLanguage } from \"./locale\";\nexport { resolvePage, createPageResolver, type ResolvedPage, type ResolvePageOptions } from \"./resolve-page\";\nexport { buildPageMetadata, type PageMetadataOptions } from \"./page-metadata\";\nexport {\n renderCmsPage,\n prepareTemplate,\n mergeTemplateLayout,\n collectSharedSectionIds,\n type RenderCmsPageOptions,\n} from \"./render-cms-page\";\nexport { themeSettingsToCss, type ThemeSettings, type ThemeColorSet } from \"./theme-css\";\nexport { serveStaticTextFile, defaultRobotsContent, type StaticTextFileOptions } from \"./static-text-file\";\nexport {\n createLocalePage,\n createLocaleAliasPage,\n pageSlugFromParams,\n type LocalePageConfig,\n type LocalePageProps,\n} from \"./locale-page\";\nexport { rateLimit, getClientIp, type RateLimitConfig, type RateLimitResult } from \"./rate-limit\";\n\nexport * from \"@botlr/react\";\nexport type * from \"@botlr/sdk\";\nexport {\n BotlrError,\n BotlrConflictError,\n createBotlrClient,\n getAssetUrl,\n createAssetUrl,\n getAssetId,\n getAssetFilename,\n isAssetData,\n} from \"@botlr/sdk\";\n"],"mappings":"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","names":["cache","filterVisibleNodesRecursive","filterVisibleNodesRecursive","Fragment","jsx","resolvePage","createBotlrClient"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@botlr/next",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Next.js helpers for Botlr: per-request clients from headers and env, on top of @botlr/sdk and @botlr/react.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -40,8 +40,9 @@
|
|
|
40
40
|
"node": ">=20"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"
|
|
44
|
-
"@botlr/
|
|
43
|
+
"html-react-parser": "^6.1.3",
|
|
44
|
+
"@botlr/react": "^0.1.1",
|
|
45
|
+
"@botlr/sdk": "^0.2.0"
|
|
45
46
|
},
|
|
46
47
|
"peerDependencies": {
|
|
47
48
|
"next": ">=14",
|
|
@@ -49,6 +50,7 @@
|
|
|
49
50
|
},
|
|
50
51
|
"devDependencies": {
|
|
51
52
|
"@types/react": "^19.1.0",
|
|
53
|
+
"@types/react-dom": "^19.1.0",
|
|
52
54
|
"next": "16.2.9",
|
|
53
55
|
"react": "^19.1.0",
|
|
54
56
|
"react-dom": "^19.1.0",
|