@pantheon-systems/create-p1-starter-kit 0.12.0 → 0.14.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/README.md +3 -3
- package/lib/cli.js +122 -53
- package/lib/cli.test.js +55 -0
- package/lib/copy-template.js +37 -0
- package/lib/copy-template.test.js +42 -1
- package/lib/messages.js +1 -1
- package/package.json +7 -4
- package/template/README.md +82 -0
- package/template/__tests__/auth-route.test.ts +1 -1
- package/template/__tests__/chatbot-flag-context.test.ts +55 -0
- package/template/__tests__/data-list-block-sub-components.test.tsx +246 -0
- package/template/__tests__/data-list-block-utils.test.ts +84 -0
- package/template/__tests__/data-list-block.test.ts +198 -0
- package/template/__tests__/published-page-routes.test.ts +86 -0
- package/template/__tests__/seo-metadata.test.ts +1 -1
- package/template/__tests__/styles-canvas-scope.test.ts +1 -1
- package/template/__tests__/widget-logout.test.ts +114 -0
- package/template/app/[...puckPath]/client.tsx +38 -10
- package/template/app/[...puckPath]/page.tsx +10 -117
- package/template/app/[...puckPath]/widget-logout.ts +36 -0
- package/template/app/p1/(editor)/[[...p1]]/editor-client.tsx +33 -140
- package/template/app/page.tsx +11 -69
- package/template/app/published-pages.tsx +23 -0
- package/template/app/styles.css +1 -1
- package/template/app/welcome-block.tsx +25 -0
- package/template/ci-examples/github-actions-sync-puck-registry.yml +15 -7
- package/template/components/ChatbotFlagProvider.tsx +3 -8
- package/template/components/p1-lockup.tsx +2 -1
- package/template/components/puck/image-block.tsx +5 -2
- package/template/components/puck/welcome-block-render.tsx +30 -37
- package/template/components/welcome-block.module.css +124 -0
- package/template/eslint.config.js +72 -1
- package/template/gitignore +43 -0
- package/template/lib/chatbot-flag/ai-generate.ts +1 -1
- package/template/lib/chatbot-flag/flag-context.ts +32 -0
- package/template/lib/page-seo.ts +1 -1
- package/template/package.json +5 -5
- package/template/scripts/__tests__/sync-puck-registry.test.ts +3 -3
- package/template/scripts/sync-puck-registry.ts +18 -18
- package/template/vitest.config.ts +17 -20
- package/template/CHANGELOG.md +0 -76
- package/template/__tests__/published-page-404.test.ts +0 -65
package/template/lib/page-seo.ts
CHANGED
|
@@ -37,7 +37,7 @@ const carriesTemplate = (value: unknown): value is string =>
|
|
|
37
37
|
typeof value === "string" && value.includes("{{");
|
|
38
38
|
|
|
39
39
|
/**
|
|
40
|
-
* Produces the per-page <head> Metadata for a route
|
|
40
|
+
* Produces the per-page <head> Metadata for a route. Title,
|
|
41
41
|
* description and the free-text metadata fields are template-allowed.
|
|
42
42
|
*/
|
|
43
43
|
export async function resolvePageMetadata({
|
package/template/package.json
CHANGED
|
@@ -15,12 +15,12 @@
|
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"@pantheon-systems/cpub-react-sdk": "^5.2.1",
|
|
18
|
-
"@pantheon-systems/css-client": "^0.
|
|
19
|
-
"@pantheon-systems/p1-ai-chat": "^0.
|
|
20
|
-
"@pantheon-systems/p1-media": "^0.4.
|
|
21
|
-
"@pantheon-systems/p1-next-sdk": "^0.
|
|
18
|
+
"@pantheon-systems/css-client": "^0.14.0",
|
|
19
|
+
"@pantheon-systems/p1-ai-chat": "^0.6.0",
|
|
20
|
+
"@pantheon-systems/p1-media": "^0.4.5",
|
|
21
|
+
"@pantheon-systems/p1-next-sdk": "^0.14.0",
|
|
22
22
|
"@pantheon-systems/pds-toolkit-react": "2.0.0-alpha.66",
|
|
23
|
-
"@pantheon-systems/puck-css": "^0.
|
|
23
|
+
"@pantheon-systems/puck-css": "^0.14.0",
|
|
24
24
|
"@puckeditor/core": "^0.21.1",
|
|
25
25
|
"@tailwindcss/postcss": "^4.2.2",
|
|
26
26
|
"@tailwindcss/typography": "^0.5.16",
|
|
@@ -56,7 +56,7 @@ describe("validateEnv", () => {
|
|
|
56
56
|
});
|
|
57
57
|
|
|
58
58
|
it("defaults defaultBranchName to 'main' when CSS_DEFAULT_BRANCH is not set", () => {
|
|
59
|
-
// Safe because the
|
|
59
|
+
// Safe because the site's main content branch is always literally named
|
|
60
60
|
// "main": a push override of "main" resolves to the same branch either
|
|
61
61
|
// by name match or by isMain, so the default only adds semantics.
|
|
62
62
|
const result = validateEnv(baseEnv());
|
|
@@ -145,8 +145,8 @@ describe("resolveBranchId", () => {
|
|
|
145
145
|
|
|
146
146
|
describe("resolveBranchId default-branch semantics", () => {
|
|
147
147
|
// In CI the override is always the pushed git ref's name, so a repo whose
|
|
148
|
-
// default branch is not literally named "main" would never match the
|
|
149
|
-
// main branch (whose name is always "main") — the sync silently skips on
|
|
148
|
+
// default branch is not literally named "main" would never match the
|
|
149
|
+
// site's main branch (whose name is always "main") — the sync silently skips on
|
|
150
150
|
// every default-branch push. When the caller also supplies the repo's
|
|
151
151
|
// default branch name, an override equal to it must resolve via isMain.
|
|
152
152
|
const branches = [
|
|
@@ -2,23 +2,23 @@
|
|
|
2
2
|
* Syncs this site's Puck component registry (_registry/components/* and the
|
|
3
3
|
* registry index) headlessly, without opening the editor in a browser.
|
|
4
4
|
* Intended to run from CI on push to main or a branch whose name matches a
|
|
5
|
-
*
|
|
5
|
+
* branch on the site, whenever puck.config.tsx or components/puck/** change.
|
|
6
6
|
*
|
|
7
7
|
* Usage: tsx scripts/sync-puck-registry.ts [--dry-run]
|
|
8
8
|
*
|
|
9
9
|
* Required env vars (see validateEnv below for the full fallback contract):
|
|
10
10
|
* CSS_BASE_URL, CSS_SITE_ID, CSS_REGISTRY_API_KEY
|
|
11
11
|
* Optional:
|
|
12
|
-
* CSS_BRANCH_ID —
|
|
12
|
+
* CSS_BRANCH_ID — branch to target (in CI: the pushed git ref's name)
|
|
13
13
|
* CSS_DEFAULT_BRANCH — the repo's default branch name (defaults to "main");
|
|
14
14
|
* when CSS_BRANCH_ID equals it, the site's isMain branch is targeted
|
|
15
15
|
* regardless of naming (see resolveBranchId for the resolution contract)
|
|
16
16
|
*
|
|
17
17
|
* CSS_REGISTRY_API_KEY must be a sat_ site token scoped to write:registry
|
|
18
18
|
* only — do not reuse a read-scoped token (P1_CSS_API_KEY). Because that
|
|
19
|
-
* token has no read access at all, every run
|
|
20
|
-
* descriptor + the registry index
|
|
21
|
-
* see syncComponentRegistryWriteOnly.
|
|
19
|
+
* token has no read access at all, every run posts every component
|
|
20
|
+
* descriptor + the registry index; the backend compares each against stored
|
|
21
|
+
* content and writes only what changed — see syncComponentRegistryWriteOnly.
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
24
|
import { register } from "node:module";
|
|
@@ -43,7 +43,7 @@ export function validateEnv(env: Record<string, string | undefined>): ValidatedE
|
|
|
43
43
|
const siteId = env.CSS_SITE_ID ?? env.NEXT_PUBLIC_CSS_SITE_ID;
|
|
44
44
|
const apiKey = env.CSS_REGISTRY_API_KEY;
|
|
45
45
|
const branchOverride = env.CSS_BRANCH_ID ?? env.NEXT_PUBLIC_CSS_BRANCH_ID;
|
|
46
|
-
// Defaults to "main": the
|
|
46
|
+
// Defaults to "main": the site's main content branch is always literally
|
|
47
47
|
// named "main", so for repos whose default git branch is also "main" this
|
|
48
48
|
// resolves to the same branch it would have matched by name. Repos with a
|
|
49
49
|
// differently-named default branch (master, trunk) must set it explicitly.
|
|
@@ -88,10 +88,10 @@ export function resolveConfigModule(mod: unknown): unknown {
|
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
/**
|
|
91
|
-
* Thrown by resolveBranchId when no
|
|
92
|
-
* other errors so callers (main(), a CI trigger firing on every git
|
|
93
|
-
* can treat "this branch has no
|
|
94
|
-
* than a real sync failure.
|
|
91
|
+
* Thrown by resolveBranchId when no matching branch is found. Distinguished
|
|
92
|
+
* from other errors so callers (main(), a CI trigger firing on every git
|
|
93
|
+
* branch) can treat "this branch has no counterpart on the site" as a benign
|
|
94
|
+
* no-op rather than a real sync failure.
|
|
95
95
|
*/
|
|
96
96
|
export class NoBranchMatchError extends Error {}
|
|
97
97
|
|
|
@@ -133,12 +133,12 @@ export function filterAssetStubbedDescriptors(descriptors: Descriptor[]): {
|
|
|
133
133
|
|
|
134
134
|
/**
|
|
135
135
|
* Resolution contract: an override (in CI, always the pushed git ref's name)
|
|
136
|
-
* matches a
|
|
137
|
-
* default branch name, which always resolves the site's isMain
|
|
138
|
-
* main is always literally named "main", so
|
|
139
|
-
* default branch is "master"/"trunk" would
|
|
140
|
-
* default branch means the main registry,
|
|
141
|
-
*
|
|
136
|
+
* matches a branch on the site by id or name — EXCEPT when it equals the
|
|
137
|
+
* repo's default branch name, which always resolves the site's isMain
|
|
138
|
+
* branch. The site's main branch is always literally named "main", so
|
|
139
|
+
* without that rule a repo whose default branch is "master"/"trunk" would
|
|
140
|
+
* silently skip on every push. The default branch means the main registry,
|
|
141
|
+
* even over a coincidentally-named branch on the site, e.g. "master".
|
|
142
142
|
*/
|
|
143
143
|
export function resolveBranchId(
|
|
144
144
|
branches: Branch[],
|
|
@@ -211,8 +211,8 @@ const isMainModule = import.meta.url === pathToFileURL(process.argv[1] ?? "").hr
|
|
|
211
211
|
if (isMainModule) {
|
|
212
212
|
main().catch((err: unknown) => {
|
|
213
213
|
// A CI trigger firing on every git branch push has no way to know ahead
|
|
214
|
-
// of time which branches have a matching
|
|
215
|
-
// discovered at runtime. Treat "no match" as a benign no-op, not a
|
|
214
|
+
// of time which branches have a matching branch on the site — that has
|
|
215
|
+
// to be discovered at runtime. Treat "no match" as a benign no-op, not a
|
|
216
216
|
// failure, so unrelated feature-branch pushes don't turn CI red.
|
|
217
217
|
if (err instanceof NoBranchMatchError) {
|
|
218
218
|
console.log(`[sync-puck-registry] Skipping: ${err.message}`);
|
|
@@ -1,30 +1,27 @@
|
|
|
1
|
-
import { resolve } from "path";
|
|
2
1
|
import { defineConfig } from "vitest/config";
|
|
3
2
|
import react from "@vitejs/plugin-react";
|
|
4
3
|
|
|
5
4
|
export default defineConfig({
|
|
6
5
|
plugins: [react()],
|
|
7
|
-
resolve: {
|
|
8
|
-
alias: {
|
|
9
|
-
"@pantheon-systems/puck-css/fields": resolve(
|
|
10
|
-
__dirname,
|
|
11
|
-
"../..",
|
|
12
|
-
"packages/puck-css/src/data/fields.tsx",
|
|
13
|
-
),
|
|
14
|
-
"@pantheon-systems/pds-toolkit-react": resolve(
|
|
15
|
-
__dirname,
|
|
16
|
-
"../..",
|
|
17
|
-
"packages/puck-css/src/__mocks__/@pantheon-systems/pds-toolkit-react.ts",
|
|
18
|
-
),
|
|
19
|
-
"@puckeditor/core": resolve(
|
|
20
|
-
__dirname,
|
|
21
|
-
"../..",
|
|
22
|
-
"packages/puck-css/src/__mocks__/@puckeditor/core.ts",
|
|
23
|
-
),
|
|
24
|
-
},
|
|
25
|
-
},
|
|
26
6
|
test: {
|
|
27
7
|
environment: "node",
|
|
8
|
+
// Inlining below means the first test to import puck-css pays for Vite
|
|
9
|
+
// transforming that whole graph — seconds on a cold machine, and the default
|
|
10
|
+
// 5s timeout fails it on slower CI runners while every later test in the file
|
|
11
|
+
// runs in milliseconds.
|
|
12
|
+
testTimeout: 30_000,
|
|
13
|
+
server: {
|
|
14
|
+
deps: {
|
|
15
|
+
// pds-toolkit-react's entry point imports its own dist/index.css, and
|
|
16
|
+
// puck-css imports pds-toolkit-react. Left external, vitest hands that
|
|
17
|
+
// chain to Node's ESM loader, which has no loader for .css; inlining
|
|
18
|
+
// routes it through Vite instead. Both must be listed — inlining only the
|
|
19
|
+
// leaf leaves puck-css external, and Node then loads the whole subtree
|
|
20
|
+
// without consulting this list. The patterns match a resolved path, so
|
|
21
|
+
// they allow pnpm's `@pantheon-systems+puck-css` directory form too.
|
|
22
|
+
inline: [/@pantheon-systems[/+]puck-css/, /@pantheon-systems[/+]pds-toolkit-react/],
|
|
23
|
+
},
|
|
24
|
+
},
|
|
28
25
|
typecheck: {
|
|
29
26
|
tsconfig: "./tsconfig.test.json",
|
|
30
27
|
},
|
package/template/CHANGELOG.md
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
# @pantheon-systems/p1-starter
|
|
2
|
-
|
|
3
|
-
## 1.0.7
|
|
4
|
-
|
|
5
|
-
### Patch Changes
|
|
6
|
-
|
|
7
|
-
- Updated dependencies
|
|
8
|
-
- Updated dependencies
|
|
9
|
-
- Updated dependencies
|
|
10
|
-
- Updated dependencies [3ed945e]
|
|
11
|
-
- Updated dependencies
|
|
12
|
-
- Updated dependencies
|
|
13
|
-
- Updated dependencies
|
|
14
|
-
- Updated dependencies
|
|
15
|
-
- Updated dependencies
|
|
16
|
-
- Updated dependencies
|
|
17
|
-
- Updated dependencies
|
|
18
|
-
- Updated dependencies
|
|
19
|
-
- @pantheon-systems/puck-css@0.8.0
|
|
20
|
-
- @pantheon-systems/p1-next-sdk@0.8.0
|
|
21
|
-
- @pantheon-systems/css-client@0.8.0
|
|
22
|
-
|
|
23
|
-
## 1.0.6
|
|
24
|
-
|
|
25
|
-
### Patch Changes
|
|
26
|
-
|
|
27
|
-
- Updated dependencies [b0254ff]
|
|
28
|
-
- Updated dependencies
|
|
29
|
-
- Updated dependencies [e937842]
|
|
30
|
-
- Updated dependencies [e937842]
|
|
31
|
-
- @pantheon-systems/puck-css@0.7.0
|
|
32
|
-
- @pantheon-systems/css-client@0.7.0
|
|
33
|
-
- @pantheon-systems/p1-next-sdk@0.7.0
|
|
34
|
-
|
|
35
|
-
## 1.0.5
|
|
36
|
-
|
|
37
|
-
### Patch Changes
|
|
38
|
-
|
|
39
|
-
- @pantheon-systems/puck-css@0.6.0
|
|
40
|
-
- @pantheon-systems/p1-next-sdk@0.6.0
|
|
41
|
-
|
|
42
|
-
## 1.0.4
|
|
43
|
-
|
|
44
|
-
### Patch Changes
|
|
45
|
-
|
|
46
|
-
- Updated dependencies [0bc7982]
|
|
47
|
-
- @pantheon-systems/puck-css@0.5.0
|
|
48
|
-
- @pantheon-systems/p1-next-sdk@0.5.0
|
|
49
|
-
|
|
50
|
-
## 1.0.3
|
|
51
|
-
|
|
52
|
-
### Patch Changes
|
|
53
|
-
|
|
54
|
-
- Updated dependencies
|
|
55
|
-
- @pantheon-systems/puck-css@0.4.4
|
|
56
|
-
- @pantheon-systems/p1-next-sdk@0.4.4
|
|
57
|
-
- @pantheon-systems/css-client@0.4.4
|
|
58
|
-
|
|
59
|
-
## 1.0.2
|
|
60
|
-
|
|
61
|
-
### Patch Changes
|
|
62
|
-
|
|
63
|
-
- Updated dependencies
|
|
64
|
-
- @pantheon-systems/puck-css@0.4.3
|
|
65
|
-
- @pantheon-systems/p1-next-sdk@0.4.3
|
|
66
|
-
- @pantheon-systems/css-client@0.4.3
|
|
67
|
-
|
|
68
|
-
## 1.0.1
|
|
69
|
-
|
|
70
|
-
### Patch Changes
|
|
71
|
-
|
|
72
|
-
- Updated dependencies [6650602]
|
|
73
|
-
- Updated dependencies [dc7cfd7]
|
|
74
|
-
- @pantheon-systems/puck-css@0.4.2
|
|
75
|
-
- @pantheon-systems/css-client@0.4.2
|
|
76
|
-
- @pantheon-systems/p1-next-sdk@0.4.2
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
-
|
|
3
|
-
const { loadPublishedPage, notFound } = vi.hoisted(() => ({
|
|
4
|
-
loadPublishedPage: vi.fn(),
|
|
5
|
-
notFound: vi.fn(() => {
|
|
6
|
-
throw new Error("NEXT_NOT_FOUND");
|
|
7
|
-
}),
|
|
8
|
-
}));
|
|
9
|
-
|
|
10
|
-
vi.mock("@pantheon-systems/p1-next-sdk/server", () => ({
|
|
11
|
-
loadPublishedPage,
|
|
12
|
-
loadRouteTemplateKeys: vi.fn().mockResolvedValue([]),
|
|
13
|
-
createCssQueryFetchers: vi.fn().mockReturnValue([]),
|
|
14
|
-
}));
|
|
15
|
-
|
|
16
|
-
vi.mock("next/navigation", () => ({ notFound }));
|
|
17
|
-
|
|
18
|
-
vi.mock("@pantheon-systems/puck-css/server", () => ({
|
|
19
|
-
pagePathFromCatchAllSegments: (segments: string[]) => `/${segments.join("/")}`,
|
|
20
|
-
loadRemoteDatasourceContext: vi.fn().mockResolvedValue({}),
|
|
21
|
-
extractReferencedDatasourceIds: vi.fn().mockReturnValue([]),
|
|
22
|
-
resolveDataTemplates: vi.fn(async (d: unknown) => d),
|
|
23
|
-
}));
|
|
24
|
-
|
|
25
|
-
vi.mock("../lib/remote-datasource-fetchers", () => ({
|
|
26
|
-
REMOTE_DATASOURCE_FETCHERS: [],
|
|
27
|
-
}));
|
|
28
|
-
|
|
29
|
-
vi.mock("../app/[...puckPath]/client", () => ({ Client: () => null }));
|
|
30
|
-
vi.mock("../components/content-unavailable", () => ({
|
|
31
|
-
ContentUnavailable: () => null,
|
|
32
|
-
}));
|
|
33
|
-
|
|
34
|
-
import Page from "../app/[...puckPath]/page";
|
|
35
|
-
|
|
36
|
-
const render = (...segments: string[]) =>
|
|
37
|
-
Page({ params: Promise.resolve({ puckPath: segments }) });
|
|
38
|
-
|
|
39
|
-
describe("catch-all route — missing vs unavailable", () => {
|
|
40
|
-
beforeEach(() => vi.clearAllMocks());
|
|
41
|
-
|
|
42
|
-
// The route is statically renderable, so a 200 here would write every junk URL
|
|
43
|
-
// a crawler probes into the response cache as a successful page.
|
|
44
|
-
it("404s a path with no published page", async () => {
|
|
45
|
-
loadPublishedPage.mockResolvedValue({ status: "missing" });
|
|
46
|
-
await expect(render("nope")).rejects.toThrow("NEXT_NOT_FOUND");
|
|
47
|
-
expect(notFound).toHaveBeenCalled();
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
// 404ing here would deindex a live page over a transient backend blip.
|
|
51
|
-
it("does not 404 when the backend is unreachable", async () => {
|
|
52
|
-
loadPublishedPage.mockResolvedValue({ status: "unavailable" });
|
|
53
|
-
await render("real-page");
|
|
54
|
-
expect(notFound).not.toHaveBeenCalled();
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
it("renders published content", async () => {
|
|
58
|
-
loadPublishedPage.mockResolvedValue({
|
|
59
|
-
status: "ok",
|
|
60
|
-
data: { root: { props: { title: "Hi" } }, content: [] },
|
|
61
|
-
});
|
|
62
|
-
await render("blog");
|
|
63
|
-
expect(notFound).not.toHaveBeenCalled();
|
|
64
|
-
});
|
|
65
|
-
});
|