create-nextly-app 0.0.2-alpha.73 → 0.0.2-alpha.75
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/dist/cli.cjs +1 -1
- package/dist/cli.mjs +1 -1
- package/dist/{create-nextly-Q62KZJib.cjs → create-nextly-DdIL2e9E.cjs} +170 -77
- package/dist/{create-nextly-Q62KZJib.cjs.map → create-nextly-DdIL2e9E.cjs.map} +1 -1
- package/dist/{create-nextly-CuWn_ITx.mjs → create-nextly-N_COehCu.mjs} +170 -77
- package/dist/{create-nextly-CuWn_ITx.mjs.map → create-nextly-N_COehCu.mjs.map} +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +5 -5
- package/skills/nextly-authentication/SKILL.md +1 -1
- package/skills/nextly-collections/SKILL.md +1 -1
- package/skills/nextly-deploy/SKILL.md +1 -1
- package/skills/nextly-install/SKILL.md +1 -1
- package/templates/base/src/app/admin/[[...params]]/layout.tsx +60 -8
- package/templates/base/src/app/layout.tsx +5 -0
- package/templates/base/src/nextly/cached-read.ts +52 -0
- package/templates/base/src/types/generated/plugin-admin-imports.generated.ts +2 -0
- package/templates/blank/src/app/layout.tsx +5 -0
- package/templates/blank/src/instrumentation.ts +4 -1
- package/templates/plugin/AGENTS.md.template +2 -2
- package/templates/plugin/dev/src/app/layout.tsx +6 -0
- package/templates/plugin/dev/src/instrumentation.ts +4 -1
- package/templates/plugin/dev/src/nextly/cached-read.ts +52 -0
- package/templates/plugin/dev/src/types/generated/plugin-admin-imports.generated.ts +2 -2
- package/templates/plugin/src/admin/index.ts +4 -14
- package/templates/plugin/dev/src/app/admin/[[...params]]/layout.tsx +0 -24
package/dist/index.cjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_create_nextly = require("./create-nextly-
|
|
2
|
+
const require_create_nextly = require("./create-nextly-DdIL2e9E.cjs");
|
|
3
3
|
exports.createNextly = require_create_nextly.createNextly;
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { t as createNextly } from "./create-nextly-
|
|
1
|
+
export { t as createNextly } from "./create-nextly-N_COehCu.mjs";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-nextly-app",
|
|
3
|
-
"version": "0.0.2-alpha.
|
|
3
|
+
"version": "0.0.2-alpha.75",
|
|
4
4
|
"description": "CLI to scaffold Nextly in your Next.js project",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -37,10 +37,10 @@
|
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@babel/types": "^7.29.7",
|
|
40
|
-
"@nextlyhq/eslint-plugin": "0.0.2-alpha.
|
|
41
|
-
"@nextlyhq/module-specifiers": "0.0.2-alpha.
|
|
42
|
-
"@nextlyhq/telemetry": "0.0.2-alpha.
|
|
43
|
-
"@nextlyhq/tsconfig": "0.0.2-alpha.
|
|
40
|
+
"@nextlyhq/eslint-plugin": "0.0.2-alpha.75",
|
|
41
|
+
"@nextlyhq/module-specifiers": "0.0.2-alpha.75",
|
|
42
|
+
"@nextlyhq/telemetry": "0.0.2-alpha.75",
|
|
43
|
+
"@nextlyhq/tsconfig": "0.0.2-alpha.75",
|
|
44
44
|
"@testing-library/react": "^16.3.0",
|
|
45
45
|
"@types/fs-extra": "^11.0.4",
|
|
46
46
|
"@types/node": "^22.20.5",
|
|
@@ -7,7 +7,7 @@ description: >-
|
|
|
7
7
|
code, and extra fields on users. Also use when asked to add login or
|
|
8
8
|
sign-up to a Nextly site, so the answer matches what Nextly provides.
|
|
9
9
|
metadata:
|
|
10
|
-
nextly-version: 0.0.2-alpha.
|
|
10
|
+
nextly-version: 0.0.2-alpha.75
|
|
11
11
|
---
|
|
12
12
|
|
|
13
13
|
# Authentication and access in Nextly
|
|
@@ -8,7 +8,7 @@ description: >-
|
|
|
8
8
|
Nextly install shows no collections, fails to load nextly.config.ts, or its
|
|
9
9
|
admin panel misbehaves after setup.
|
|
10
10
|
metadata:
|
|
11
|
-
nextly-version: 0.0.2-alpha.
|
|
11
|
+
nextly-version: 0.0.2-alpha.75
|
|
12
12
|
---
|
|
13
13
|
|
|
14
14
|
# Install Nextly into an existing Next.js app
|
|
@@ -1,11 +1,43 @@
|
|
|
1
1
|
import { connection } from "next/server";
|
|
2
2
|
import { Suspense } from "react";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
ADMIN_BRANDING_ELEMENT_ID,
|
|
5
|
+
adminBrandingJson,
|
|
6
|
+
adminMetadataFor,
|
|
7
|
+
getBrandingCss,
|
|
8
|
+
} from "nextly/config";
|
|
4
9
|
|
|
5
10
|
import config from "../../../../nextly.config";
|
|
11
|
+
import { registeredComponentPaths } from "../../../types/generated/plugin-admin-components.generated";
|
|
6
12
|
|
|
7
13
|
const brandingCss = getBrandingCss(config.admin?.branding);
|
|
14
|
+
// The configured logo, name and favicon, read by the admin before any request
|
|
15
|
+
// answers, so they are right from the first paint.
|
|
16
|
+
const brandingJson = adminBrandingJson(config.admin?.branding);
|
|
8
17
|
|
|
18
|
+
/**
|
|
19
|
+
* The admin is never a page for search results: `noindex, nofollow` in the
|
|
20
|
+
* head of the first HTML the server sends, whatever plugins the site runs,
|
|
21
|
+
* and the configured favicon's link beside it.
|
|
22
|
+
*/
|
|
23
|
+
export const metadata = adminMetadataFor(config.admin?.branding);
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* `/admin` itself is built ahead, so it is served from the build's files. The
|
|
27
|
+
* admin's other paths are drawn by the same page in the browser, and are
|
|
28
|
+
* served the same prebuilt shell.
|
|
29
|
+
*/
|
|
30
|
+
export function generateStaticParams(): { params: string[] }[] {
|
|
31
|
+
return [{ params: [] }];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Prebuilt in production: the same page for every visitor, built once, with
|
|
36
|
+
* no request-time work and nothing read from the database. Everything about
|
|
37
|
+
* the person comes from the admin's own requests once it loads, so a CDN or
|
|
38
|
+
* the browser may keep the page, and it is served while the server is still
|
|
39
|
+
* starting.
|
|
40
|
+
*/
|
|
9
41
|
export default function AdminLayout({
|
|
10
42
|
children,
|
|
11
43
|
}: {
|
|
@@ -16,19 +48,39 @@ export default function AdminLayout({
|
|
|
16
48
|
{brandingCss && (
|
|
17
49
|
<style dangerouslySetInnerHTML={{ __html: brandingCss }} />
|
|
18
50
|
)}
|
|
19
|
-
|
|
20
|
-
<
|
|
21
|
-
|
|
51
|
+
{brandingJson && (
|
|
52
|
+
<script
|
|
53
|
+
type="application/json"
|
|
54
|
+
id={ADMIN_BRANDING_ELEMENT_ID}
|
|
55
|
+
dangerouslySetInnerHTML={{ __html: brandingJson }}
|
|
56
|
+
/>
|
|
57
|
+
)}
|
|
58
|
+
{process.env.NODE_ENV === "development" ? (
|
|
59
|
+
<Suspense fallback={null}>
|
|
60
|
+
<ComponentMapKeptCurrent>{children}</ComponentMapKeptCurrent>
|
|
61
|
+
</Suspense>
|
|
62
|
+
) : (
|
|
63
|
+
children
|
|
64
|
+
)}
|
|
22
65
|
</>
|
|
23
66
|
);
|
|
24
67
|
}
|
|
25
68
|
|
|
26
69
|
/**
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
70
|
+
* Development only: before any admin page, the generated component map is
|
|
71
|
+
* written again when it falls behind the config. A production build serves
|
|
72
|
+
* the map it was built with, so it drops this, and the page with it is
|
|
73
|
+
* prebuilt. Beneath a Suspense boundary, as request work outside one fails a
|
|
74
|
+
* Cache Components build, in development too. The check is loaded here, so a
|
|
75
|
+
* production page never loads the runtime it lives in.
|
|
30
76
|
*/
|
|
31
|
-
async function
|
|
77
|
+
async function ComponentMapKeptCurrent({
|
|
78
|
+
children,
|
|
79
|
+
}: {
|
|
80
|
+
children: React.ReactNode;
|
|
81
|
+
}) {
|
|
32
82
|
await connection();
|
|
83
|
+
const { checkAdminComponents } = await import("nextly/runtime");
|
|
84
|
+
await checkAdminComponents({ config, registeredComponentPaths });
|
|
33
85
|
return children;
|
|
34
86
|
}
|
|
@@ -3,6 +3,11 @@ import "@fontsource-variable/geist";
|
|
|
3
3
|
import "@fontsource-variable/geist-mono";
|
|
4
4
|
import "./globals.css";
|
|
5
5
|
import { SITE_URL } from "@/lib/site-url";
|
|
6
|
+
// Registers the app's "use cache" read function, and how Nextly starts when a
|
|
7
|
+
// read finds it not started, for every route before any of them reads,
|
|
8
|
+
// during `next build` too: under Cache Components Nextly's cached reads go
|
|
9
|
+
// through that function, and `<SiteCode>` refuses to read without it.
|
|
10
|
+
import "@/nextly/cached-read";
|
|
6
11
|
|
|
7
12
|
/**
|
|
8
13
|
* The faces are imported as STYLESHEETS from packages in `node_modules`, rather
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Nextly's cached reads under Cache Components.
|
|
3
|
+
*
|
|
4
|
+
* Next.js caches non-fetch reads with `"use cache"` and `cacheTag` once Cache
|
|
5
|
+
* Components is on, and the directive works only in code Next.js compiles, so
|
|
6
|
+
* Nextly reads through this function of the app's own. It receives the read's
|
|
7
|
+
* key, its tags and its lifetime, and runs the reader Nextly registered for
|
|
8
|
+
* that key. The root layout imports this file, so it is registered on every
|
|
9
|
+
* route before anything is read: `<SiteCode>` refuses to read without it.
|
|
10
|
+
*
|
|
11
|
+
* The same import also tells Nextly how to start with the app's config when a
|
|
12
|
+
* read finds it not started, so the root layout's import both registers the
|
|
13
|
+
* cached read and covers a read made before any page starts Nextly, during
|
|
14
|
+
* `next build` too.
|
|
15
|
+
*
|
|
16
|
+
* It works with `cacheComponents: true` and Nextly's cache handlers in
|
|
17
|
+
* `next.config.ts`, as this app ships:
|
|
18
|
+
* https://nextlyhq.com/docs/guides/isr-caching#cache-components
|
|
19
|
+
*/
|
|
20
|
+
import { cacheLife, cacheTag } from "next/cache";
|
|
21
|
+
import { getNextly, registerNextlyStart } from "nextly";
|
|
22
|
+
import { registerCachedRead, runRegisteredRead } from "nextly/runtime";
|
|
23
|
+
|
|
24
|
+
import config from "@nextly-config";
|
|
25
|
+
|
|
26
|
+
export async function cachedRead(
|
|
27
|
+
key: string,
|
|
28
|
+
tags: string[],
|
|
29
|
+
revalidate: number | false
|
|
30
|
+
): Promise<unknown> {
|
|
31
|
+
"use cache";
|
|
32
|
+
cacheTag(...tags);
|
|
33
|
+
// `revalidate: false` is tag-only, as everywhere in Nextly: only a write
|
|
34
|
+
// expires the entry, never time. Next.js's "max" profile revalidates monthly.
|
|
35
|
+
if (revalidate === false) {
|
|
36
|
+
cacheLife({ revalidate: Infinity, expire: Infinity });
|
|
37
|
+
} else {
|
|
38
|
+
// Expired at twice the revalidate, and never within 5 minutes: Next.js
|
|
39
|
+
// leaves an entry that expires sooner out of a static prerender.
|
|
40
|
+
cacheLife({ revalidate, expire: Math.max(revalidate * 2, 300) });
|
|
41
|
+
}
|
|
42
|
+
return runRegisteredRead(key);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
registerCachedRead(cachedRead, process.env.__NEXT_CACHE_COMPONENTS);
|
|
46
|
+
|
|
47
|
+
// Tells Nextly how this app starts it, for a read that finds it not started,
|
|
48
|
+
// such as the root layout's `<SiteCode>` on `/_not-found` while `next build`
|
|
49
|
+
// prerenders, where nothing else starts it. Nothing starts here: a page that
|
|
50
|
+
// calls `getNextly` first is the start that counts. An app that passes
|
|
51
|
+
// `getNextly` more than its config passes the same options here.
|
|
52
|
+
registerNextlyStart(() => getNextly({ config }));
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* string (pages, settings, views, slots, field-type editors) so they load
|
|
4
4
|
* without manual host imports. */
|
|
5
5
|
|
|
6
|
+
import { registerComponentMap } from "@nextlyhq/admin";
|
|
6
7
|
import { registeredComponentPaths as listed } from "./plugin-admin-components.generated";
|
|
7
8
|
|
|
8
9
|
const registered = {};
|
|
@@ -29,4 +30,5 @@ if (
|
|
|
29
30
|
);
|
|
30
31
|
}
|
|
31
32
|
|
|
33
|
+
registerComponentMap(registered);
|
|
32
34
|
export const registeredComponentPaths = listed;
|
|
@@ -4,6 +4,11 @@ import "@fontsource-variable/jetbrains-mono";
|
|
|
4
4
|
|
|
5
5
|
import "./globals.css";
|
|
6
6
|
import { SITE_URL } from "@/lib/site-url";
|
|
7
|
+
// Registers the app's "use cache" read function, and how Nextly starts when a
|
|
8
|
+
// read finds it not started, for every route before any of them reads,
|
|
9
|
+
// during `next build` too: under Cache Components Nextly's cached reads go
|
|
10
|
+
// through that function, and `<SiteCode>` refuses to read without it.
|
|
11
|
+
import "@/nextly/cached-read";
|
|
7
12
|
|
|
8
13
|
/**
|
|
9
14
|
* The faces are imported as STYLESHEETS from packages in `node_modules`, rather
|
|
@@ -26,8 +26,11 @@ export async function register(): Promise<void> {
|
|
|
26
26
|
// Next.js writes its Cache Components setting into this file as it builds
|
|
27
27
|
// it. Nextly, loaded from node_modules, cannot read that for itself. With
|
|
28
28
|
// it off, Nextly warns at start; with it on, a cached read that finds no
|
|
29
|
-
// "use cache" read function says so.
|
|
29
|
+
// "use cache" read function says so. The same holds for the build's newest
|
|
30
|
+
// migration, which withNextly sets: a production start compares it with
|
|
31
|
+
// the database's schema version and warns when the database is behind.
|
|
30
32
|
await createRegister(config, {
|
|
31
33
|
cacheComponents: process.env.__NEXT_CACHE_COMPONENTS,
|
|
34
|
+
buildSchemaVersion: process.env.NEXTLY_BUILD_SCHEMA_VERSION,
|
|
32
35
|
})();
|
|
33
36
|
}
|
|
@@ -41,8 +41,8 @@ working on an app.
|
|
|
41
41
|
- **Plugin APIs come from `@nextlyhq/plugin-sdk`; schema APIs come from
|
|
42
42
|
`nextly/config`.** The SDK is the stability boundary for everything a plugin
|
|
43
43
|
does AS a plugin: `definePlugin`, field factories, `pluginField` and
|
|
44
|
-
`NextlyError` from `@nextlyhq/plugin-sdk`; `registerComponents`
|
|
45
|
-
|
|
44
|
+
`NextlyError` from `@nextlyhq/plugin-sdk`; `registerComponents` from
|
|
45
|
+
`@nextlyhq/plugin-sdk/admin`; `createTestNextly`
|
|
46
46
|
from `@nextlyhq/plugin-sdk/testing`. Collections and singles are defined the same way an app defines
|
|
47
47
|
them, with `defineCollection` from `nextly/config` — which is what
|
|
48
48
|
`src/collections/example.ts` does.
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import type { ReactNode } from "react";
|
|
2
2
|
|
|
3
|
+
// Registers the dev app's "use cache" read function, and how Nextly starts
|
|
4
|
+
// when a read finds it not started, for every route before any of them
|
|
5
|
+
// reads, during `next build` too: under Cache Components Nextly's cached
|
|
6
|
+
// reads go through that function, and `<SiteCode>` refuses to read without it.
|
|
7
|
+
import "../nextly/cached-read";
|
|
8
|
+
|
|
3
9
|
export const metadata = {
|
|
4
10
|
title: "{{pluginName}} — dev playground",
|
|
5
11
|
};
|
|
@@ -10,9 +10,12 @@ export async function register(): Promise<void> {
|
|
|
10
10
|
// Next.js writes its Cache Components setting into this file as it builds
|
|
11
11
|
// it. Nextly, loaded from node_modules, cannot read that for itself. With
|
|
12
12
|
// it off, Nextly warns at start; with it on, a cached read that finds no
|
|
13
|
-
// "use cache" read function says so.
|
|
13
|
+
// "use cache" read function says so. The same holds for the build's newest
|
|
14
|
+
// migration, which withNextly sets: a production start compares it with
|
|
15
|
+
// the database's schema version and warns when the database is behind.
|
|
14
16
|
await createRegister(config, {
|
|
15
17
|
cacheComponents: process.env.__NEXT_CACHE_COMPONENTS,
|
|
18
|
+
buildSchemaVersion: process.env.NEXTLY_BUILD_SCHEMA_VERSION,
|
|
16
19
|
})();
|
|
17
20
|
|
|
18
21
|
// Create the user admin.devAutoLogin signs in as (see seed-dev-user.ts).
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Nextly's cached reads under Cache Components, for the plugin's dev app.
|
|
3
|
+
*
|
|
4
|
+
* Next.js caches non-fetch reads with `"use cache"` and `cacheTag` once Cache
|
|
5
|
+
* Components is on, and the directive works only in code Next.js compiles, so
|
|
6
|
+
* Nextly reads through this function of the app's own. It receives the read's
|
|
7
|
+
* key, its tags and its lifetime, and runs the reader Nextly registered for
|
|
8
|
+
* that key. The root layout imports this file, so it is registered on every
|
|
9
|
+
* route before anything is read, as in an app `create-nextly-app` makes.
|
|
10
|
+
*
|
|
11
|
+
* The same import also tells Nextly how to start with the app's config when a
|
|
12
|
+
* read finds it not started, so the root layout's import both registers the
|
|
13
|
+
* cached read and covers a read made before any page starts Nextly, during
|
|
14
|
+
* `next build` too.
|
|
15
|
+
*
|
|
16
|
+
* It works with `cacheComponents: true` and Nextly's cache handlers in
|
|
17
|
+
* `next.config.ts`, as this dev app ships:
|
|
18
|
+
* https://nextlyhq.com/docs/guides/isr-caching#cache-components
|
|
19
|
+
*/
|
|
20
|
+
import { cacheLife, cacheTag } from "next/cache";
|
|
21
|
+
import { getNextly, registerNextlyStart } from "nextly";
|
|
22
|
+
import { registerCachedRead, runRegisteredRead } from "nextly/runtime";
|
|
23
|
+
|
|
24
|
+
import config from "../../nextly.config";
|
|
25
|
+
|
|
26
|
+
export async function cachedRead(
|
|
27
|
+
key: string,
|
|
28
|
+
tags: string[],
|
|
29
|
+
revalidate: number | false
|
|
30
|
+
): Promise<unknown> {
|
|
31
|
+
"use cache";
|
|
32
|
+
cacheTag(...tags);
|
|
33
|
+
// `revalidate: false` is tag-only, as everywhere in Nextly: only a write
|
|
34
|
+
// expires the entry, never time. Next.js's "max" profile revalidates monthly.
|
|
35
|
+
if (revalidate === false) {
|
|
36
|
+
cacheLife({ revalidate: Infinity, expire: Infinity });
|
|
37
|
+
} else {
|
|
38
|
+
// Expired at twice the revalidate, and never within 5 minutes: Next.js
|
|
39
|
+
// leaves an entry that expires sooner out of a static prerender.
|
|
40
|
+
cacheLife({ revalidate, expire: Math.max(revalidate * 2, 300) });
|
|
41
|
+
}
|
|
42
|
+
return runRegisteredRead(key);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
registerCachedRead(cachedRead, process.env.__NEXT_CACHE_COMPONENTS);
|
|
46
|
+
|
|
47
|
+
// Tells Nextly how this app starts it, for a read that finds it not started,
|
|
48
|
+
// such as the root layout's `<SiteCode>` on `/_not-found` while `next build`
|
|
49
|
+
// prerenders, where nothing else starts it. Nothing starts here: a page that
|
|
50
|
+
// calls `getNextly` first is the start that counts. An app that passes
|
|
51
|
+
// `getNextly` more than its config passes the same options here.
|
|
52
|
+
registerNextlyStart(() => getNextly({ config }));
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* string (pages, settings, views, slots, field-type editors) so they load
|
|
4
4
|
* without manual host imports. */
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import { registerComponentMap } from "@nextlyhq/admin";
|
|
7
7
|
import * as _p0 from "{{pluginName}}/admin";
|
|
8
8
|
import { registeredComponentPaths as listed } from "./plugin-admin-components.generated";
|
|
9
9
|
|
|
@@ -33,5 +33,5 @@ if (
|
|
|
33
33
|
);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
registerComponentMap(registered);
|
|
37
37
|
export const registeredComponentPaths = listed;
|
|
@@ -1,24 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Admin component registration
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* the eager + lazy registration below is the fallback.
|
|
2
|
+
* Admin component registration. Importing this module registers the React
|
|
3
|
+
* components referenced by `contributes.admin` string paths so the host admin
|
|
4
|
+
* can resolve them. The host's generated component map imports it for you.
|
|
6
5
|
*/
|
|
7
|
-
import {
|
|
8
|
-
registerComponents,
|
|
9
|
-
registerKnownPlugin,
|
|
10
|
-
} from "@nextlyhq/plugin-sdk/admin";
|
|
6
|
+
import { registerComponents } from "@nextlyhq/plugin-sdk/admin";
|
|
11
7
|
|
|
12
8
|
import { SettingsPage } from "./SettingsPage";
|
|
13
9
|
|
|
14
10
|
const SETTINGS_PATH = "{{pluginName}}/admin#SettingsPage";
|
|
15
11
|
|
|
16
|
-
// Eager: register on module load.
|
|
17
12
|
registerComponents({ [SETTINGS_PATH]: SettingsPage });
|
|
18
13
|
|
|
19
|
-
// Lazy fallback: the host can trigger registration on demand by package prefix.
|
|
20
|
-
registerKnownPlugin("{{pluginName}}", async () => {
|
|
21
|
-
registerComponents({ [SETTINGS_PATH]: SettingsPage });
|
|
22
|
-
});
|
|
23
|
-
|
|
24
14
|
export { SettingsPage };
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { connection } from "next/server";
|
|
2
|
-
import { Suspense } from "react";
|
|
3
|
-
|
|
4
|
-
export default function AdminLayout({
|
|
5
|
-
children,
|
|
6
|
-
}: {
|
|
7
|
-
children: React.ReactNode;
|
|
8
|
-
}) {
|
|
9
|
-
return (
|
|
10
|
-
<Suspense fallback={null}>
|
|
11
|
-
<ForThisRequest>{children}</ForThisRequest>
|
|
12
|
-
</Suspense>
|
|
13
|
-
);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* The admin renders for each request, never from a cache another user's
|
|
18
|
-
* request filled. Beneath the layout's Suspense boundary, so under Cache
|
|
19
|
-
* Components the rest of the page still prerenders.
|
|
20
|
-
*/
|
|
21
|
-
async function ForThisRequest({ children }: { children: React.ReactNode }) {
|
|
22
|
-
await connection();
|
|
23
|
-
return children;
|
|
24
|
-
}
|