@botlr/next 0.1.0 → 0.3.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 +29 -0
- package/README.md +78 -20
- package/dist/index.cjs +580 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +336 -3
- package/dist/index.d.ts +336 -3
- package/dist/index.js +561 -4
- package/dist/index.js.map +1 -1
- package/package.json +5 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
# @botlr/next
|
|
2
2
|
|
|
3
|
+
## 0.3.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- e3ff8e7: `createLocalePage` now throws when a page cannot be resolved, so `next build` fails instead of saving an error page. In development the error box is still rendered. The new `resolveErrors` option (`"throw"` or `"render"`) overrides the default; `ResolvedPage`'s error result carries the original error as `cause`.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- e3ff8e7: Retry failed reads. GET requests that fail with a network error or a 408, 429 or 5xx status are retried twice with exponential backoff and `Retry-After` support before `BotlrError` is thrown. Configure or disable with the new `retry` client option, also accepted by `getBotlrForRoute` and `createBotlrFromEnv`. Writes are never retried.
|
|
12
|
+
- Updated dependencies [e3ff8e7]
|
|
13
|
+
- @botlr/sdk@0.3.0
|
|
14
|
+
- @botlr/react@0.1.2
|
|
15
|
+
|
|
16
|
+
## 0.2.0
|
|
17
|
+
|
|
18
|
+
### Minor Changes
|
|
19
|
+
|
|
20
|
+
- Page helpers extracted from the satellite apps.
|
|
21
|
+
|
|
22
|
+
`@botlr/sdk`: `PageResponse` gains optional `full_slug`, `breadcrumbs` and `alternate_translations` (new `AlternateTranslation` type, also used by `ResolveResponse`). New asset helpers `getAssetUrl`, `createAssetUrl`, `getAssetId`, `getAssetFilename` and `isAssetData` take the media server URL explicitly instead of reading `NEXT_PUBLIC_MEDIA_URL`.
|
|
23
|
+
|
|
24
|
+
`@botlr/next`: `resolvePage` and `createPageResolver`, `buildPageMetadata`, `renderCmsPage` with `themeSettingsToCss`, `serveStaticTextFile` and `defaultRobotsContent`, `createLocalePage` and `createLocaleAliasPage`, `rateLimit` and `getClientIp`, plus `scopeFromEnv` and `environmentFromEnv`. Every helper takes its client and component registry as arguments. `html-react-parser` is a new dependency.
|
|
25
|
+
|
|
26
|
+
### Patch Changes
|
|
27
|
+
|
|
28
|
+
- Updated dependencies
|
|
29
|
+
- @botlr/sdk@0.2.0
|
|
30
|
+
- @botlr/react@0.1.1
|
|
31
|
+
|
|
3
32
|
## 0.1.0
|
|
4
33
|
|
|
5
34
|
- First release. `getBotlrForRoute` moves here from the publisher's
|
package/README.md
CHANGED
|
@@ -1,22 +1,12 @@
|
|
|
1
1
|
# @botlr/next
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
Next.js helpers on top of `@botlr/sdk` and `@botlr/react`. Everything from
|
|
4
|
+
both packages is re-exported, so a server file can import from `@botlr/next`
|
|
5
|
+
alone. The package imports `next/headers` and `next/navigation`, so client
|
|
6
|
+
components should import runtime values from `@botlr/sdk` or `@botlr/react`
|
|
7
|
+
instead; type imports from `@botlr/next` are fine anywhere.
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
// app/[[...slug]]/page.tsx
|
|
9
|
-
import { getBotlrForRoute, SectionRenderer } from "@botlr/next";
|
|
10
|
-
|
|
11
|
-
export default async function Page({ params, searchParams }) {
|
|
12
|
-
const botlr = await getBotlrForRoute({
|
|
13
|
-
appId: process.env.BOTLR_APP_ID!,
|
|
14
|
-
preview: (await searchParams).preview === "true",
|
|
15
|
-
});
|
|
16
|
-
const resolved = await botlr.resolveUrl((await params).slug?.join("/") ?? "");
|
|
17
|
-
// ...render resolved.data.layout with SectionRenderer
|
|
18
|
-
}
|
|
19
|
-
```
|
|
9
|
+
## Clients
|
|
20
10
|
|
|
21
11
|
- `getBotlrForRoute(params)` builds a client for the current request. The
|
|
22
12
|
locale comes from `Accept-Language` unless given; `baseUrl`, `apiKey` and
|
|
@@ -25,8 +15,76 @@ export default async function Page({ params, searchParams }) {
|
|
|
25
15
|
browser through a `NEXT_PUBLIC_` name.
|
|
26
16
|
- `getCachedBotlr` is the same, memoised per request with React `cache`.
|
|
27
17
|
- `createBotlrFromEnv(overrides)` needs no request context (scripts,
|
|
28
|
-
`generateStaticParams
|
|
29
|
-
- `
|
|
30
|
-
|
|
18
|
+
`generateStaticParams`, the page helpers below).
|
|
19
|
+
- `configFromEnv`, `scopeFromEnv({ locale })` (from `BOTLR_ORG_SLUG`,
|
|
20
|
+
`BOTLR_PROJECT_SLUG`, `BOTLR_APP_INSTANCE_SLUG`, `BOTLR_APP_ID`),
|
|
21
|
+
`environmentFromEnv()` (`BOTLR_ENVIRONMENT`, `ENVIRONMENT`, `NODE_ENV`) and
|
|
22
|
+
`localeFromAcceptLanguage` are the building blocks.
|
|
23
|
+
|
|
24
|
+
## A static locale route in one call
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
// lib/botlr.ts
|
|
28
|
+
import { createBotlrFromEnv } from "@botlr/next";
|
|
29
|
+
export const botlr = createBotlrFromEnv();
|
|
30
|
+
|
|
31
|
+
// app/(root)/[[...slug]]/page.tsx
|
|
32
|
+
import { createLocalePage } from "@botlr/next";
|
|
33
|
+
import { botlr } from "@/lib/botlr";
|
|
34
|
+
import { publisherSectionRegistry } from "@/components/sections/publisher-section-registry";
|
|
35
|
+
|
|
36
|
+
// Segment config must stay as literals here so Next can read it statically.
|
|
37
|
+
export const revalidate = false;
|
|
38
|
+
export const dynamicParams = false;
|
|
39
|
+
|
|
40
|
+
const page = createLocalePage({
|
|
41
|
+
locale: "da",
|
|
42
|
+
folder: "",
|
|
43
|
+
client: botlr,
|
|
44
|
+
componentRegistry: publisherSectionRegistry,
|
|
45
|
+
siteUrl: process.env.NEXT_PUBLIC_APP_URL,
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
export const generateStaticParams = page.generateStaticParams;
|
|
49
|
+
export const generateMetadata = page.generateMetadata;
|
|
50
|
+
export default page.Page;
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
`createLocalePage` lists slugs with `getPageSlugList`, resolves each request
|
|
54
|
+
once for metadata and page through `createPageResolver`, calls `notFound()`
|
|
55
|
+
for missing and unpublished pages, follows CMS redirects with
|
|
56
|
+
`permanentRedirect` (or `redirect` with `redirect: "temporary"`) prefixed by
|
|
57
|
+
`folder`, and renders with `renderCmsPage`. `createLocaleAliasPage("/sv")`
|
|
58
|
+
makes a folder that only redirects to another one.
|
|
59
|
+
|
|
60
|
+
When resolving a page throws, even after the client's retries, the page
|
|
61
|
+
throws too: `next build` fails instead of saving an error page, and Vercel
|
|
62
|
+
keeps the previous deploy live. In development an error box is rendered in
|
|
63
|
+
its place. Pass `resolveErrors: "render"` to always show the box (with
|
|
64
|
+
`renderError` to customise it) or `resolveErrors: "throw"` to always throw.
|
|
65
|
+
|
|
66
|
+
## The pieces
|
|
67
|
+
|
|
68
|
+
- `resolvePage(client, slug, locale, options)` folds `/api/resolve` into
|
|
69
|
+
`{ kind: "page" | "redirect" | "404" | "error" }` and prepends non-page
|
|
70
|
+
content (articles by default; see `contentSections`) to the `main` region as
|
|
71
|
+
an inline section. `createPageResolver(client, options)` binds the client
|
|
72
|
+
and memoises per request.
|
|
73
|
+
- `buildPageMetadata(pageData, { siteUrl, folder })` turns `seo_meta` into
|
|
74
|
+
Next `Metadata`: title, description, keywords, Open Graph, Twitter, robots,
|
|
75
|
+
canonical and hreflang alternates. Without `siteUrl` only an explicit
|
|
76
|
+
`seo_meta.canonical` is emitted.
|
|
77
|
+
- `renderCmsPage({ pageData, scope, componentRegistry, client })` picks the
|
|
78
|
+
page template, then the theme's, then a built-in one; merges template and
|
|
79
|
+
page layouts; applies visibility rules for `environment`; fetches shared
|
|
80
|
+
sections through `client` or `fetchSharedSection`; and mounts a
|
|
81
|
+
`SectionRenderer` at every `{{{REGION}}}` marker. `themeSettingsToCss`
|
|
82
|
+
emits the theme's custom properties.
|
|
83
|
+
- `serveStaticTextFile(client, slug, defaultContent)` serves a CMS page's
|
|
84
|
+
text sections as `text/plain`, for `robots.txt`, `humans.txt` and
|
|
85
|
+
`llms.txt` routes. `defaultRobotsContent()` allows everything in production
|
|
86
|
+
and disallows elsewhere.
|
|
87
|
+
- `rateLimit(key, { limit, window })` and `getClientIp(request)` for form and
|
|
88
|
+
forum route handlers. In-memory, per server instance.
|
|
31
89
|
|
|
32
|
-
`next` and `react` are peer dependencies.
|
|
90
|
+
`next` and `react` are peer dependencies; `html-react-parser` is a dependency.
|