@valkyrianlabs/payload-markdown-docs 0.3.1 → 0.4.1
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 +79 -171
- package/dist/admin/DocsSetManager.js +5 -3
- package/dist/admin/DocsSetManager.js.map +1 -1
- package/dist/admin/docsSetManagerData.d.ts +6 -5
- package/dist/admin/docsSetManagerData.js +60 -33
- package/dist/admin/docsSetManagerData.js.map +1 -1
- package/dist/admin/docsSetManagerTypes.d.ts +12 -9
- package/dist/admin/docsSetManagerTypes.js.map +1 -1
- package/dist/cli/commands/manifest.js +1 -2
- package/dist/cli/commands/manifest.js.map +1 -1
- package/dist/cli/commands/plan.js +1 -2
- package/dist/cli/commands/plan.js.map +1 -1
- package/dist/cli/commands/push.js +19 -12
- package/dist/cli/commands/push.js.map +1 -1
- package/dist/cli/commands/validate.js +11 -6
- package/dist/cli/commands/validate.js.map +1 -1
- package/dist/cli/index.js +6 -15
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/parseArgs.js +0 -3
- package/dist/cli/parseArgs.js.map +1 -1
- package/dist/cli/types.d.ts +0 -3
- package/dist/cli/types.js.map +1 -1
- package/dist/collections/docs.js +0 -24
- package/dist/collections/docs.js.map +1 -1
- package/dist/collections/docsGroups.js +8 -9
- package/dist/collections/docsGroups.js.map +1 -1
- package/dist/collections/docsKeys.d.ts +5 -0
- package/dist/collections/docsKeys.js +44 -0
- package/dist/collections/docsKeys.js.map +1 -0
- package/dist/collections/docsSets.js +47 -202
- package/dist/collections/docsSets.js.map +1 -1
- package/dist/collections/docsTrusted.d.ts +5 -0
- package/dist/collections/docsTrusted.js +60 -0
- package/dist/collections/docsTrusted.js.map +1 -0
- package/dist/collections/index.d.ts +4 -0
- package/dist/collections/index.js +2 -0
- package/dist/collections/index.js.map +1 -1
- package/dist/constants.d.ts +3 -1
- package/dist/constants.js +3 -1
- package/dist/constants.js.map +1 -1
- package/dist/endpoints/sync.d.ts +6 -7
- package/dist/endpoints/sync.js +57 -124
- package/dist/endpoints/sync.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/next/PayloadMarkdownDocsPage.js +2 -6
- package/dist/next/PayloadMarkdownDocsPage.js.map +1 -1
- package/dist/next/index.d.ts +2 -0
- package/dist/next/index.js +1 -0
- package/dist/next/index.js.map +1 -1
- package/dist/next/links.d.ts +11 -0
- package/dist/next/links.js +79 -0
- package/dist/next/links.js.map +1 -0
- package/dist/next/markdown.js +91 -19
- package/dist/next/markdown.js.map +1 -1
- package/dist/next/metadata.js +6 -6
- package/dist/next/metadata.js.map +1 -1
- package/dist/next/records.js +13 -23
- package/dist/next/records.js.map +1 -1
- package/dist/next/route.js +141 -49
- package/dist/next/route.js.map +1 -1
- package/dist/next/types.d.ts +0 -14
- package/dist/next/types.js.map +1 -1
- package/dist/payload/docsKeys.d.ts +20 -0
- package/dist/payload/docsKeys.js +29 -0
- package/dist/payload/docsKeys.js.map +1 -0
- package/dist/payload/docsSets.d.ts +32 -6
- package/dist/payload/docsSets.js +146 -83
- package/dist/payload/docsSets.js.map +1 -1
- package/dist/payload/docsTrusted.d.ts +16 -0
- package/dist/payload/docsTrusted.js +49 -0
- package/dist/payload/docsTrusted.js.map +1 -0
- package/dist/payload/index.d.ts +5 -1
- package/dist/payload/index.js +3 -1
- package/dist/payload/index.js.map +1 -1
- package/dist/plugin.js +36 -9
- package/dist/plugin.js.map +1 -1
- package/dist/security/ed25519Keys.d.ts +9 -0
- package/dist/security/ed25519Keys.js +183 -0
- package/dist/security/ed25519Keys.js.map +1 -0
- package/dist/security/githubOidc.d.ts +18 -5
- package/dist/security/githubOidc.js +44 -16
- package/dist/security/githubOidc.js.map +1 -1
- package/dist/security/index.d.ts +2 -1
- package/dist/security/index.js +1 -0
- package/dist/security/index.js.map +1 -1
- package/dist/security/sign.js +3 -12
- package/dist/security/sign.js.map +1 -1
- package/dist/security/verify.js +3 -12
- package/dist/security/verify.js.map +1 -1
- package/dist/skills/codex/SKILL.md +3 -4
- package/dist/skills/codex/examples/github-actions.md +0 -2
- package/dist/skills/codex/reference/admin.md +0 -6
- package/dist/skills/codex/reference/routing.md +2 -1
- package/dist/skills/codex/reference/sync.md +7 -5
- package/dist/skills/codex/reference/troubleshooting.md +3 -4
- package/dist/skills/codex/reference/workflow.md +0 -1
- package/dist/sync/manifest.d.ts +1 -3
- package/dist/sync/manifest.js +2 -3
- package/dist/sync/manifest.js.map +1 -1
- package/dist/sync/validate.js +1 -2
- package/dist/sync/validate.js.map +1 -1
- package/dist/types.d.ts +7 -50
- package/dist/types.js.map +1 -1
- package/package.json +6 -4
package/README.md
CHANGED
|
@@ -3,42 +3,24 @@
|
|
|
3
3
|
Git-backed Markdown documentation sync for Payload CMS, powered by
|
|
4
4
|
`@valkyrianlabs/payload-markdown`.
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
The default workflow is intentionally small:
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
The sync endpoint is not the human docs route. If your Payload site is deployed
|
|
14
|
-
at `https://docs.valkyrianlabs.com`, the default sync endpoint is:
|
|
15
|
-
|
|
16
|
-
```text
|
|
17
|
-
https://docs.valkyrianlabs.com/api/payload-markdown-docs/sync
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
The human docs route is whatever docs set route base you configure, for example:
|
|
21
|
-
|
|
22
|
-
```text
|
|
23
|
-
https://docs.valkyrianlabs.com/plugins/payload-markdown-docs
|
|
24
|
-
```
|
|
8
|
+
1. Install the plugin in your Payload app.
|
|
9
|
+
2. Create a docs set with a title and slug.
|
|
10
|
+
3. Add a trusted GitHub owner once.
|
|
11
|
+
4. Push Markdown from GitHub Actions.
|
|
12
|
+
5. Render generated docs in your Next route.
|
|
25
13
|
|
|
26
14
|
## Install
|
|
27
15
|
|
|
28
|
-
Install this package in the Payload app that will receive and render docs:
|
|
29
|
-
|
|
30
16
|
```bash
|
|
31
17
|
pnpm add @valkyrianlabs/payload-markdown-docs @valkyrianlabs/payload-markdown
|
|
32
18
|
```
|
|
33
19
|
|
|
34
|
-
Install the same package in any
|
|
20
|
+
Install the same package in any repository that runs the
|
|
35
21
|
`payload-markdown-docs` CLI.
|
|
36
22
|
|
|
37
|
-
##
|
|
38
|
-
|
|
39
|
-
Add the plugin to `payload.config.ts`. Keep source authorization in Payload
|
|
40
|
-
Admin docs sets; the plugin config should define the endpoint, collections, and
|
|
41
|
-
sync lifecycle behavior.
|
|
23
|
+
## Configure Payload
|
|
42
24
|
|
|
43
25
|
```ts
|
|
44
26
|
import { payloadMarkdownDocs } from '@valkyrianlabs/payload-markdown-docs'
|
|
@@ -47,74 +29,49 @@ import { buildConfig } from 'payload'
|
|
|
47
29
|
export default buildConfig({
|
|
48
30
|
plugins: [
|
|
49
31
|
payloadMarkdownDocs({
|
|
50
|
-
enabled: true,
|
|
51
|
-
|
|
52
|
-
// Optional default OIDC audience. Repository/workflow/environment
|
|
53
|
-
// allowlists belong on the docs set in Payload Admin.
|
|
54
32
|
auth: {
|
|
55
|
-
githubOidc:
|
|
56
|
-
audience: 'payload-markdown-docs',
|
|
57
|
-
},
|
|
33
|
+
githubOidc: true,
|
|
58
34
|
},
|
|
59
|
-
|
|
60
35
|
target: {
|
|
61
|
-
type: 'docsCollection',
|
|
62
36
|
enableDrafts: true,
|
|
63
37
|
},
|
|
64
|
-
|
|
65
38
|
sync: {
|
|
66
39
|
allowWrites: true,
|
|
67
40
|
allowPublish: true,
|
|
68
|
-
allowHardDelete: false,
|
|
69
|
-
defaultPublishMode: 'draft',
|
|
70
|
-
deleteBehavior: 'archive',
|
|
71
41
|
},
|
|
72
42
|
}),
|
|
73
43
|
],
|
|
74
44
|
})
|
|
75
45
|
```
|
|
76
46
|
|
|
77
|
-
|
|
47
|
+
This adds `Docs Globals` admin collections:
|
|
48
|
+
|
|
49
|
+
- `Sets`: docs packages. The set `slug` is the sync source and OIDC audience.
|
|
50
|
+
- `Groups`: optional route nesting. Routes are derived from group slugs.
|
|
51
|
+
- `Keys`: global Ed25519 public keys for local or non-GitHub publishing.
|
|
52
|
+
- `Trusted`: global GitHub owners trusted for OIDC publishing.
|
|
78
53
|
|
|
79
|
-
|
|
80
|
-
- Registers the default Payload custom endpoint at
|
|
81
|
-
`/api/payload-markdown-docs/sync`.
|
|
82
|
-
- Accepts Ed25519 signed requests or GitHub OIDC bearer requests on the same
|
|
83
|
-
endpoint when the matched docs set has those auth policies.
|
|
84
|
-
- Uses docs sets in Payload Admin as the source allow-list. `sources` still
|
|
85
|
-
exists as a legacy fallback, but it is not the recommended path.
|
|
86
|
-
- Allows sync writes and publish requests, while archiving removed docs instead
|
|
87
|
-
of hard-deleting them.
|
|
54
|
+
The sync endpoint is `/api/payload-markdown-docs/sync`.
|
|
88
55
|
|
|
89
|
-
|
|
90
|
-
tag refs like `refs/tags/v0.1.0-canary.1`. The first pass uses exact string
|
|
91
|
-
matches, not glob patterns. For release publishing, constrain by repository and
|
|
92
|
-
workflow unless you want to list exact tag refs.
|
|
56
|
+
## Create Admin Records
|
|
93
57
|
|
|
94
|
-
|
|
58
|
+
Create a docs set:
|
|
95
59
|
|
|
96
|
-
|
|
97
|
-
|
|
60
|
+
- title: `Payload Markdown Docs`
|
|
61
|
+
- slug: `payload-markdown-docs`
|
|
62
|
+
- branch: `main`
|
|
63
|
+
- optional group: for example `plugins`, which makes the route
|
|
64
|
+
`/plugins/payload-markdown-docs`
|
|
98
65
|
|
|
99
|
-
|
|
100
|
-
- `sourceRoot`: `docs`
|
|
101
|
-
- `routeBase`: `/plugins/payload-markdown-docs`
|
|
102
|
-
- `title`: Payload Markdown Docs
|
|
103
|
-
- `auth.githubOidc.enabled`: checked
|
|
104
|
-
- `auth.githubOidc.allowedRepositories`: `valkyrianlabs/payload-markdown-docs`
|
|
105
|
-
- optionally restrict `auth.githubOidc.allowedWorkflows`,
|
|
106
|
-
`auth.githubOidc.allowedEnvironments`, or exact `auth.githubOidc.allowedRefs`
|
|
107
|
-
- optionally add `auth.ed25519.keys` with `keyId` and `publicKey` for local
|
|
108
|
-
machines or non-GitHub CI
|
|
66
|
+
Create a trusted GitHub owner:
|
|
109
67
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
add a new docs source by creating a new docs set in Payload Admin; you should
|
|
113
|
-
not need to redeploy the Payload app just to add another docs package.
|
|
68
|
+
- owner: `valkyrianlabs`
|
|
69
|
+
- `limitRepos`: off, unless you want to list specific repositories
|
|
114
70
|
|
|
115
|
-
|
|
71
|
+
When `limitRepos` is off, any repository owned by that GitHub owner can publish
|
|
72
|
+
to a matching docs set from the configured branch.
|
|
116
73
|
|
|
117
|
-
|
|
74
|
+
## Render In Next
|
|
118
75
|
|
|
119
76
|
```tsx
|
|
120
77
|
import config from '@payload-config'
|
|
@@ -142,141 +99,92 @@ export default async function Page({
|
|
|
142
99
|
}
|
|
143
100
|
```
|
|
144
101
|
|
|
145
|
-
|
|
146
|
-
`notFound()` immediately.
|
|
147
|
-
|
|
148
|
-
## 4. Add Docs Source Files
|
|
149
|
-
|
|
150
|
-
Keep docs in `docs/` and commit the AI Markdown Export manifest next to them.
|
|
151
|
-
The manifest controls the generated raw Markdown export; it is not a human docs
|
|
152
|
-
page and should not appear in human navigation.
|
|
153
|
-
|
|
154
|
-
```text
|
|
155
|
-
docs/
|
|
156
|
-
index.md
|
|
157
|
-
install.md
|
|
158
|
-
usage.md
|
|
159
|
-
index.ai.yml
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
Example `docs/index.ai.yml`:
|
|
163
|
-
|
|
164
|
-
```yaml
|
|
165
|
-
version: 1
|
|
166
|
-
|
|
167
|
-
title: Payload Markdown Docs
|
|
168
|
-
canonical: /plugins/payload-markdown-docs
|
|
169
|
-
output: /plugins/payload-markdown-docs.md
|
|
102
|
+
For header navigation, use the link helper:
|
|
170
103
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
preamble: |
|
|
175
|
-
This file is intended for AI agents, editor tooling, Codex, ChatGPT,
|
|
176
|
-
and offline reference.
|
|
177
|
-
|
|
178
|
-
order:
|
|
179
|
-
- ./index.md
|
|
180
|
-
- ./install.md
|
|
181
|
-
- ./usage.md
|
|
182
|
-
|
|
183
|
-
exclude:
|
|
184
|
-
- ./drafts/**
|
|
104
|
+
```ts
|
|
105
|
+
import { getPayloadMarkdownDocsLinks } from '@valkyrianlabs/payload-markdown-docs/next'
|
|
185
106
|
|
|
186
|
-
|
|
187
|
-
|
|
107
|
+
const docsLinks = await getPayloadMarkdownDocsLinks({ payload })
|
|
108
|
+
// [{ label: 'Payload Markdown Docs', url: '/plugins/payload-markdown-docs' }]
|
|
188
109
|
```
|
|
189
110
|
|
|
190
|
-
##
|
|
111
|
+
## Validate Locally
|
|
191
112
|
|
|
192
|
-
|
|
113
|
+
In an app or docs repository that has installed this package:
|
|
193
114
|
|
|
194
115
|
```bash
|
|
195
|
-
pnpm exec payload-markdown-docs validate ./docs
|
|
196
|
-
|
|
197
|
-
|
|
116
|
+
pnpm exec payload-markdown-docs validate ./docs --source payload-markdown-docs
|
|
117
|
+
pnpm exec payload-markdown-docs manifest ./docs --source payload-markdown-docs --pretty
|
|
118
|
+
pnpm exec payload-markdown-docs plan ./docs --source payload-markdown-docs
|
|
198
119
|
```
|
|
199
120
|
|
|
200
|
-
|
|
121
|
+
From this package source checkout, use the local source CLI instead:
|
|
201
122
|
|
|
202
123
|
```bash
|
|
203
|
-
pnpm
|
|
204
|
-
--source payload-markdown-docs \
|
|
205
|
-
--route-base /plugins/payload-markdown-docs \
|
|
206
|
-
--pretty
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
```bash
|
|
210
|
-
pnpm exec payload-markdown-docs plan ./docs \
|
|
211
|
-
--source payload-markdown-docs \
|
|
212
|
-
--route-base /plugins/payload-markdown-docs
|
|
124
|
+
pnpm cli validate ./docs --source payload-markdown-docs
|
|
213
125
|
```
|
|
214
126
|
|
|
215
|
-
|
|
127
|
+
In GitHub Actions, `--source` can be omitted when the docs set slug matches the
|
|
128
|
+
repository name. The CLI infers it from `GITHUB_REPOSITORY`.
|
|
216
129
|
|
|
217
|
-
|
|
130
|
+
## Publish From GitHub Actions
|
|
218
131
|
|
|
219
132
|
```yaml
|
|
220
133
|
permissions:
|
|
221
134
|
contents: read
|
|
222
135
|
id-token: write
|
|
223
|
-
```
|
|
224
|
-
|
|
225
|
-
Then push docs to the Payload sync endpoint:
|
|
226
136
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
137
|
+
steps:
|
|
138
|
+
- uses: actions/checkout@v4
|
|
139
|
+
- uses: pnpm/action-setup@v4
|
|
140
|
+
- uses: actions/setup-node@v4
|
|
141
|
+
with:
|
|
142
|
+
node-version: 22
|
|
143
|
+
cache: pnpm
|
|
144
|
+
- run: pnpm install --frozen-lockfile
|
|
145
|
+
- run: pnpm exec payload-markdown-docs validate ./docs
|
|
146
|
+
- run: |
|
|
147
|
+
pnpm exec payload-markdown-docs push ./docs \
|
|
148
|
+
--endpoint "$DOCS_SYNC_ENDPOINT" \
|
|
149
|
+
--repository "$GITHUB_REPOSITORY" \
|
|
150
|
+
--branch "$GITHUB_REF_NAME" \
|
|
151
|
+
--commit "$GITHUB_SHA" \
|
|
152
|
+
--github-oidc \
|
|
153
|
+
--sync \
|
|
154
|
+
--publish
|
|
239
155
|
```
|
|
240
156
|
|
|
241
|
-
`--sync`
|
|
242
|
-
|
|
243
|
-
`target.enableDrafts: true`.
|
|
157
|
+
`--sync` requires `sync.allowWrites: true`. `--publish` also requires
|
|
158
|
+
`sync.allowPublish: true` and a draft-enabled generated docs collection.
|
|
244
159
|
|
|
245
|
-
|
|
160
|
+
## Local Ed25519 Push
|
|
161
|
+
|
|
162
|
+
Generate a keypair, add the public key to `Docs Globals > Keys`, then push with
|
|
163
|
+
the private key:
|
|
246
164
|
|
|
247
165
|
```bash
|
|
248
166
|
pnpm exec payload-markdown-docs keygen --out .docs-sync
|
|
249
167
|
pnpm exec payload-markdown-docs push ./docs \
|
|
250
168
|
--endpoint "$DOCS_SYNC_ENDPOINT" \
|
|
251
169
|
--source payload-markdown-docs \
|
|
252
|
-
--key-id
|
|
253
|
-
--private-key-
|
|
254
|
-
--sync
|
|
255
|
-
--publish
|
|
170
|
+
--key-id local-docs \
|
|
171
|
+
--private-key-file .docs-sync/docs-sync-private.pem \
|
|
172
|
+
--sync
|
|
256
173
|
```
|
|
257
174
|
|
|
258
|
-
##
|
|
259
|
-
|
|
260
|
-
This repo's release workflow publishes the npm package first, then pushes
|
|
261
|
-
`./docs` to:
|
|
262
|
-
|
|
263
|
-
```text
|
|
264
|
-
https://docs.valkyrianlabs.com/api/payload-markdown-docs/sync
|
|
265
|
-
```
|
|
175
|
+
## Advanced Security
|
|
266
176
|
|
|
267
|
-
|
|
177
|
+
You do not need this for normal docs publishing.
|
|
268
178
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
179
|
+
Each docs set has an advanced security section for exact GitHub workflow refs.
|
|
180
|
+
Leave it disabled to allow any workflow from a trusted owner/repository on the
|
|
181
|
+
configured branch. When enabled, add every allowed workflow ref explicitly; an
|
|
182
|
+
empty list rejects all workflow publishing for that docs set.
|
|
273
183
|
|
|
274
184
|
## More Docs
|
|
275
185
|
|
|
276
|
-
- [Installation](docs/getting-started/installation.md)
|
|
277
186
|
- [Quick Start](docs/getting-started/quick-start.md)
|
|
278
187
|
- [Plugin Config](docs/configuration/plugin-config.md)
|
|
279
|
-
- [GitHub OIDC](docs/configuration/github-oidc.md)
|
|
280
188
|
- [GitHub Actions](docs/workflow/ci-github-actions.md)
|
|
281
|
-
- [
|
|
282
|
-
- [
|
|
189
|
+
- [CLI](docs/reference/cli.md)
|
|
190
|
+
- [Migration Notes](docs/reference/migration.md)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { DEFAULT_DOCS_COLLECTION_SLUG, DEFAULT_DOCS_SETS_COLLECTION_SLUG } from '../constants.js';
|
|
2
|
+
import { DEFAULT_DOCS_COLLECTION_SLUG, DEFAULT_DOCS_GROUPS_COLLECTION_SLUG, DEFAULT_DOCS_SETS_COLLECTION_SLUG } from '../constants.js';
|
|
3
3
|
import { getDocsSetManagerData } from './docsSetManagerData.js';
|
|
4
4
|
const getFieldCustom = (field)=>{
|
|
5
5
|
const custom = 'custom' in field ? field.custom : undefined;
|
|
@@ -208,6 +208,7 @@ const Summary = ({ data })=>/*#__PURE__*/ _jsxs("dl", {
|
|
|
208
208
|
export const DocsSetManager = async ({ id, field, payload, req })=>{
|
|
209
209
|
const custom = getFieldCustom(field);
|
|
210
210
|
const docsCollectionSlug = custom.docsCollectionSlug ?? DEFAULT_DOCS_COLLECTION_SLUG;
|
|
211
|
+
const docsGroupsCollectionSlug = custom.docsGroupsCollectionSlug ?? DEFAULT_DOCS_GROUPS_COLLECTION_SLUG;
|
|
211
212
|
const docsSetsCollectionSlug = custom.docsSetsCollectionSlug ?? DEFAULT_DOCS_SETS_COLLECTION_SLUG;
|
|
212
213
|
if (!id) {
|
|
213
214
|
return /*#__PURE__*/ _jsxs("section", {
|
|
@@ -224,6 +225,7 @@ export const DocsSetManager = async ({ id, field, payload, req })=>{
|
|
|
224
225
|
const data = await getDocsSetManagerData({
|
|
225
226
|
adminRoute: req.payload.config.routes.admin,
|
|
226
227
|
docsCollectionSlug,
|
|
228
|
+
docsGroupsCollectionSlug,
|
|
227
229
|
docsSetId: String(id),
|
|
228
230
|
docsSetsCollectionSlug,
|
|
229
231
|
payload: payload
|
|
@@ -247,10 +249,10 @@ export const DocsSetManager = async ({ id, field, payload, req })=>{
|
|
|
247
249
|
/*#__PURE__*/ _jsxs("section", {
|
|
248
250
|
children: [
|
|
249
251
|
/*#__PURE__*/ _jsx("h3", {
|
|
250
|
-
children: "Route
|
|
252
|
+
children: "Effective Route"
|
|
251
253
|
}),
|
|
252
254
|
/*#__PURE__*/ _jsx("p", {
|
|
253
|
-
children: data.docsSet.routeBase || 'No route
|
|
255
|
+
children: data.docsSet.routeBase || 'No route available yet'
|
|
254
256
|
})
|
|
255
257
|
]
|
|
256
258
|
}),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/admin/DocsSetManager.tsx"],"sourcesContent":["import type { UIFieldServerProps } from 'payload'\nimport type { ReactNode } from 'react'\n\nimport type {\n DocsSetManagerData,\n DocsSetManagerDocItem,\n DocsSetManagerPayloadOperations,\n} from './docsSetManagerTypes.js'\n\nimport {\n DEFAULT_DOCS_COLLECTION_SLUG,\n DEFAULT_DOCS_SETS_COLLECTION_SLUG,\n} from '../constants.js'\nimport { getDocsSetManagerData } from './docsSetManagerData.js'\n\ntype DocsSetManagerFieldCustom = {\n docsCollectionSlug?: string\n docsSetsCollectionSlug?: string\n}\n\nconst getFieldCustom = (\n field: UIFieldServerProps['field'],\n): DocsSetManagerFieldCustom => {\n const custom = 'custom' in field ? field.custom : undefined\n\n if (!custom || typeof custom !== 'object') {\n return {}\n }\n\n return custom as DocsSetManagerFieldCustom\n}\n\nconst formatDate = (value?: string): string => {\n if (!value) {\n return 'Never'\n }\n\n const date = new Date(value)\n\n if (Number.isNaN(date.getTime())) {\n return value\n }\n\n return date.toISOString()\n}\n\nconst StatusLabel = ({ item }: { item: DocsSetManagerDocItem }) => {\n if (item.archived) {\n return <span>archived</span>\n }\n\n if (item.draft) {\n return <span>draft</span>\n }\n\n if (item.published) {\n return <span>published</span>\n }\n\n return <span>synced</span>\n}\n\nconst OverrideSummary = ({ item }: { item: DocsSetManagerDocItem }) => {\n if (item.overrideSummary.length === 0) {\n return <span>none</span>\n }\n\n return <span>{item.overrideSummary.join(', ')}</span>\n}\n\nconst renderDocItem = (item: DocsSetManagerDocItem): ReactNode => {\n if (item.kind === 'folder') {\n return (\n <details key={item.id}>\n <summary>{item.title}</summary>\n <div>\n {item.children?.map((child) => renderDocItem(child))}\n </div>\n </details>\n )\n }\n\n return (\n <details key={item.id}>\n <summary>{item.sourcePath}</summary>\n <dl>\n <div>\n <dt>Route</dt>\n <dd>{item.route || 'Missing route'}</dd>\n </div>\n <div>\n <dt>Title</dt>\n <dd>{item.title}</dd>\n </div>\n <div>\n <dt>Status</dt>\n <dd>\n <StatusLabel item={item} />\n </dd>\n </div>\n <div>\n <dt>Overrides</dt>\n <dd>\n <OverrideSummary item={item} />\n </dd>\n </div>\n </dl>\n {item.adminURL ? <a href={item.adminURL}>Open generated doc</a> : null}\n </details>\n )\n}\n\nconst Summary = ({ data }: { data: DocsSetManagerData }) => (\n <dl>\n <div>\n <dt>Docs</dt>\n <dd>{data.summary.total}</dd>\n </div>\n <div>\n <dt>Archived</dt>\n <dd>{data.summary.archived}</dd>\n </div>\n <div>\n <dt>Drafts</dt>\n <dd>{data.summary.drafts}</dd>\n </div>\n <div>\n <dt>Published</dt>\n <dd>{data.summary.published}</dd>\n </div>\n <div>\n <dt>Hidden from nav</dt>\n <dd>{data.summary.hiddenFromNav}</dd>\n </div>\n <div>\n <dt>With overrides</dt>\n <dd>{data.summary.withOverrides}</dd>\n </div>\n <div>\n <dt>Last sync</dt>\n <dd>{formatDate(data.sync?.lastSyncedAt)}</dd>\n </div>\n <div>\n <dt>Last status</dt>\n <dd>{data.sync?.lastStatus ?? 'unknown'}</dd>\n </div>\n </dl>\n)\n\nexport const DocsSetManager = async ({\n id,\n field,\n payload,\n req,\n}: UIFieldServerProps) => {\n const custom = getFieldCustom(field)\n const docsCollectionSlug = custom.docsCollectionSlug ?? DEFAULT_DOCS_COLLECTION_SLUG\n const docsSetsCollectionSlug =\n custom.docsSetsCollectionSlug ?? DEFAULT_DOCS_SETS_COLLECTION_SLUG\n\n if (!id) {\n return (\n <section>\n <h2>Generated Docs</h2>\n <p>Save this docs set before reviewing generated docs records.</p>\n </section>\n )\n }\n\n const data = await getDocsSetManagerData({\n adminRoute: req.payload.config.routes.admin,\n docsCollectionSlug,\n docsSetId: String(id),\n docsSetsCollectionSlug,\n payload: payload as DocsSetManagerPayloadOperations,\n })\n\n return (\n <section>\n <header>\n <h2>Generated Docs</h2>\n <p>\n Review generated docs records for {data.docsSet.title}. Source docs remain\n Git-backed; per-doc overrides can be edited by opening a generated doc.\n </p>\n </header>\n\n <section>\n <h3>Route
|
|
1
|
+
{"version":3,"sources":["../../src/admin/DocsSetManager.tsx"],"sourcesContent":["import type { UIFieldServerProps } from 'payload'\nimport type { ReactNode } from 'react'\n\nimport type {\n DocsSetManagerData,\n DocsSetManagerDocItem,\n DocsSetManagerPayloadOperations,\n} from './docsSetManagerTypes.js'\n\nimport {\n DEFAULT_DOCS_COLLECTION_SLUG,\n DEFAULT_DOCS_GROUPS_COLLECTION_SLUG,\n DEFAULT_DOCS_SETS_COLLECTION_SLUG,\n} from '../constants.js'\nimport { getDocsSetManagerData } from './docsSetManagerData.js'\n\ntype DocsSetManagerFieldCustom = {\n docsCollectionSlug?: string\n docsGroupsCollectionSlug?: string\n docsSetsCollectionSlug?: string\n}\n\nconst getFieldCustom = (\n field: UIFieldServerProps['field'],\n): DocsSetManagerFieldCustom => {\n const custom = 'custom' in field ? field.custom : undefined\n\n if (!custom || typeof custom !== 'object') {\n return {}\n }\n\n return custom as DocsSetManagerFieldCustom\n}\n\nconst formatDate = (value?: string): string => {\n if (!value) {\n return 'Never'\n }\n\n const date = new Date(value)\n\n if (Number.isNaN(date.getTime())) {\n return value\n }\n\n return date.toISOString()\n}\n\nconst StatusLabel = ({ item }: { item: DocsSetManagerDocItem }) => {\n if (item.archived) {\n return <span>archived</span>\n }\n\n if (item.draft) {\n return <span>draft</span>\n }\n\n if (item.published) {\n return <span>published</span>\n }\n\n return <span>synced</span>\n}\n\nconst OverrideSummary = ({ item }: { item: DocsSetManagerDocItem }) => {\n if (item.overrideSummary.length === 0) {\n return <span>none</span>\n }\n\n return <span>{item.overrideSummary.join(', ')}</span>\n}\n\nconst renderDocItem = (item: DocsSetManagerDocItem): ReactNode => {\n if (item.kind === 'folder') {\n return (\n <details key={item.id}>\n <summary>{item.title}</summary>\n <div>\n {item.children?.map((child) => renderDocItem(child))}\n </div>\n </details>\n )\n }\n\n return (\n <details key={item.id}>\n <summary>{item.sourcePath}</summary>\n <dl>\n <div>\n <dt>Route</dt>\n <dd>{item.route || 'Missing route'}</dd>\n </div>\n <div>\n <dt>Title</dt>\n <dd>{item.title}</dd>\n </div>\n <div>\n <dt>Status</dt>\n <dd>\n <StatusLabel item={item} />\n </dd>\n </div>\n <div>\n <dt>Overrides</dt>\n <dd>\n <OverrideSummary item={item} />\n </dd>\n </div>\n </dl>\n {item.adminURL ? <a href={item.adminURL}>Open generated doc</a> : null}\n </details>\n )\n}\n\nconst Summary = ({ data }: { data: DocsSetManagerData }) => (\n <dl>\n <div>\n <dt>Docs</dt>\n <dd>{data.summary.total}</dd>\n </div>\n <div>\n <dt>Archived</dt>\n <dd>{data.summary.archived}</dd>\n </div>\n <div>\n <dt>Drafts</dt>\n <dd>{data.summary.drafts}</dd>\n </div>\n <div>\n <dt>Published</dt>\n <dd>{data.summary.published}</dd>\n </div>\n <div>\n <dt>Hidden from nav</dt>\n <dd>{data.summary.hiddenFromNav}</dd>\n </div>\n <div>\n <dt>With overrides</dt>\n <dd>{data.summary.withOverrides}</dd>\n </div>\n <div>\n <dt>Last sync</dt>\n <dd>{formatDate(data.sync?.lastSyncedAt)}</dd>\n </div>\n <div>\n <dt>Last status</dt>\n <dd>{data.sync?.lastStatus ?? 'unknown'}</dd>\n </div>\n </dl>\n)\n\nexport const DocsSetManager = async ({\n id,\n field,\n payload,\n req,\n}: UIFieldServerProps) => {\n const custom = getFieldCustom(field)\n const docsCollectionSlug = custom.docsCollectionSlug ?? DEFAULT_DOCS_COLLECTION_SLUG\n const docsGroupsCollectionSlug =\n custom.docsGroupsCollectionSlug ?? DEFAULT_DOCS_GROUPS_COLLECTION_SLUG\n const docsSetsCollectionSlug =\n custom.docsSetsCollectionSlug ?? DEFAULT_DOCS_SETS_COLLECTION_SLUG\n\n if (!id) {\n return (\n <section>\n <h2>Generated Docs</h2>\n <p>Save this docs set before reviewing generated docs records.</p>\n </section>\n )\n }\n\n const data = await getDocsSetManagerData({\n adminRoute: req.payload.config.routes.admin,\n docsCollectionSlug,\n docsGroupsCollectionSlug,\n docsSetId: String(id),\n docsSetsCollectionSlug,\n payload: payload as DocsSetManagerPayloadOperations,\n })\n\n return (\n <section>\n <header>\n <h2>Generated Docs</h2>\n <p>\n Review generated docs records for {data.docsSet.title}. Source docs remain\n Git-backed; per-doc overrides can be edited by opening a generated doc.\n </p>\n </header>\n\n <section>\n <h3>Effective Route</h3>\n <p>{data.docsSet.routeBase || 'No route available yet'}</p>\n </section>\n\n <section>\n <h3>Sync Summary</h3>\n <Summary data={data} />\n </section>\n\n {data.warnings.length > 0 ? (\n <section>\n <h3>Warnings</h3>\n <ul>\n {data.warnings.map((warning) => (\n <li key={`${warning.docId ?? 'docs-set'}:${warning.message}`}>\n {warning.sourcePath ? `${warning.sourcePath}: ` : null}\n {warning.message}\n </li>\n ))}\n </ul>\n </section>\n ) : null}\n\n <section>\n <h3>Generated Docs</h3>\n {data.tree.length > 0 ? (\n <div>{data.tree.map((item) => renderDocItem(item))}</div>\n ) : (\n <p>No generated docs records are linked to this docs set yet.</p>\n )}\n </section>\n </section>\n )\n}\n"],"names":["DEFAULT_DOCS_COLLECTION_SLUG","DEFAULT_DOCS_GROUPS_COLLECTION_SLUG","DEFAULT_DOCS_SETS_COLLECTION_SLUG","getDocsSetManagerData","getFieldCustom","field","custom","undefined","formatDate","value","date","Date","Number","isNaN","getTime","toISOString","StatusLabel","item","archived","span","draft","published","OverrideSummary","overrideSummary","length","join","renderDocItem","kind","details","summary","title","div","children","map","child","id","sourcePath","dl","dt","dd","route","adminURL","a","href","Summary","data","total","drafts","hiddenFromNav","withOverrides","sync","lastSyncedAt","lastStatus","DocsSetManager","payload","req","docsCollectionSlug","docsGroupsCollectionSlug","docsSetsCollectionSlug","section","h2","p","adminRoute","config","routes","admin","docsSetId","String","header","docsSet","h3","routeBase","warnings","ul","warning","li","message","docId","tree"],"mappings":"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"}
|
|
@@ -1,23 +1,24 @@
|
|
|
1
|
-
import type { DocsSetManagerData, DocsSetManagerPayloadOperations, RawDocsRecord, RawDocsSetRecord } from './docsSetManagerTypes.js';
|
|
1
|
+
import type { DocsSetManagerData, DocsSetManagerPayloadOperations, RawDocsGroupRecord, RawDocsRecord, RawDocsSetRecord } from './docsSetManagerTypes.js';
|
|
2
2
|
export declare const getGeneratedDocAdminURL: ({ id, adminRoute, docsCollectionSlug, }: {
|
|
3
3
|
adminRoute?: string;
|
|
4
4
|
docsCollectionSlug: string;
|
|
5
5
|
id: string;
|
|
6
6
|
}) => string;
|
|
7
|
-
export declare const buildDocsSetManagerData: ({ adminRoute, docs, docsCollectionSlug, docsSet, }: {
|
|
7
|
+
export declare const buildDocsSetManagerData: ({ adminRoute, docs, docsCollectionSlug, docsGroups, docsSet, }: {
|
|
8
8
|
adminRoute?: string;
|
|
9
9
|
docs: RawDocsRecord[];
|
|
10
10
|
docsCollectionSlug?: string;
|
|
11
|
+
docsGroups?: RawDocsGroupRecord[];
|
|
11
12
|
docsSet: RawDocsSetRecord;
|
|
12
13
|
}) => DocsSetManagerData;
|
|
13
|
-
export declare const isDocsRecordForDocsSet: ({ doc, docsSetId,
|
|
14
|
+
export declare const isDocsRecordForDocsSet: ({ doc, docsSetId, }: {
|
|
14
15
|
doc: RawDocsRecord;
|
|
15
16
|
docsSetId: string;
|
|
16
|
-
sourceId: string;
|
|
17
17
|
}) => boolean;
|
|
18
|
-
export declare const getDocsSetManagerData: ({ adminRoute, docsCollectionSlug, docsSetId, docsSetsCollectionSlug, overrideAccess, payload, }: {
|
|
18
|
+
export declare const getDocsSetManagerData: ({ adminRoute, docsCollectionSlug, docsGroupsCollectionSlug, docsSetId, docsSetsCollectionSlug, overrideAccess, payload, }: {
|
|
19
19
|
adminRoute?: string;
|
|
20
20
|
docsCollectionSlug?: string;
|
|
21
|
+
docsGroupsCollectionSlug?: string;
|
|
21
22
|
docsSetId: string;
|
|
22
23
|
docsSetsCollectionSlug?: string;
|
|
23
24
|
overrideAccess?: boolean;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { DEFAULT_DOCS_COLLECTION_SLUG, DEFAULT_DOCS_SETS_COLLECTION_SLUG } from '../constants.js';
|
|
1
|
+
import { DEFAULT_DOCS_COLLECTION_SLUG, DEFAULT_DOCS_GROUPS_COLLECTION_SLUG, DEFAULT_DOCS_SETS_COLLECTION_SLUG } from '../constants.js';
|
|
2
|
+
import { deriveDocsSetRouteBase, joinRouteSegments } from '../routing/index.js';
|
|
2
3
|
const isRecord = (value)=>typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
3
4
|
const getRecordId = (doc)=>{
|
|
4
5
|
if (!isRecord(doc)) {
|
|
@@ -35,15 +36,6 @@ const getOverrideSummary = (overrides)=>{
|
|
|
35
36
|
if (overrides.hideFromNav === true) {
|
|
36
37
|
summary.push('Hidden from nav');
|
|
37
38
|
}
|
|
38
|
-
if (hasText(overrides.theme)) {
|
|
39
|
-
summary.push('Theme override');
|
|
40
|
-
}
|
|
41
|
-
if (hasText(overrides.heroEyebrow) || hasText(overrides.heroTitle) || hasText(overrides.heroDescription)) {
|
|
42
|
-
summary.push('Hero override');
|
|
43
|
-
}
|
|
44
|
-
if (hasText(overrides.seoTitle) || hasText(overrides.seoDescription)) {
|
|
45
|
-
summary.push('SEO override');
|
|
46
|
-
}
|
|
47
39
|
return summary;
|
|
48
40
|
};
|
|
49
41
|
const getDocStatus = (doc)=>{
|
|
@@ -66,6 +58,44 @@ const getSourcePathSegments = (sourcePath)=>{
|
|
|
66
58
|
}
|
|
67
59
|
return segments;
|
|
68
60
|
};
|
|
61
|
+
const getGroupRoutePath = ({ groupId, groupsById, seen = new Set() })=>{
|
|
62
|
+
if (!groupId || seen.has(groupId)) {
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
const group = groupsById.get(groupId);
|
|
66
|
+
if (!group?.slug) {
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
return joinRouteSegments(getGroupRoutePath({
|
|
70
|
+
groupId: getRelationshipId(group.parent),
|
|
71
|
+
groupsById,
|
|
72
|
+
seen: new Set([
|
|
73
|
+
groupId,
|
|
74
|
+
...seen
|
|
75
|
+
])
|
|
76
|
+
}), group.slug);
|
|
77
|
+
};
|
|
78
|
+
const getDocsSetRouteBase = ({ docsGroups, docsSet })=>{
|
|
79
|
+
if (!docsSet.slug) {
|
|
80
|
+
return '';
|
|
81
|
+
}
|
|
82
|
+
const groupsById = new Map(docsGroups.flatMap((group)=>{
|
|
83
|
+
const id = getRecordId(group);
|
|
84
|
+
return id ? [
|
|
85
|
+
[
|
|
86
|
+
id,
|
|
87
|
+
group
|
|
88
|
+
]
|
|
89
|
+
] : [];
|
|
90
|
+
}));
|
|
91
|
+
return deriveDocsSetRouteBase({
|
|
92
|
+
docsSetSlug: docsSet.slug,
|
|
93
|
+
groupRoutePath: getGroupRoutePath({
|
|
94
|
+
groupId: getRelationshipId(docsSet.group),
|
|
95
|
+
groupsById
|
|
96
|
+
})
|
|
97
|
+
});
|
|
98
|
+
};
|
|
69
99
|
const titleCaseSegment = (segment)=>segment.split(/[-_]+/).filter(Boolean).map((part)=>`${part.charAt(0).toUpperCase()}${part.slice(1)}`).join(' ');
|
|
70
100
|
const compareDocItems = (first, second)=>{
|
|
71
101
|
if (first.order !== second.order) {
|
|
@@ -173,7 +203,7 @@ const toDocItem = ({ adminRoute, doc, docsCollectionSlug, index, warnings })=>{
|
|
|
173
203
|
title
|
|
174
204
|
};
|
|
175
205
|
};
|
|
176
|
-
export const buildDocsSetManagerData = ({ adminRoute, docs, docsCollectionSlug = DEFAULT_DOCS_COLLECTION_SLUG, docsSet })=>{
|
|
206
|
+
export const buildDocsSetManagerData = ({ adminRoute, docs, docsCollectionSlug = DEFAULT_DOCS_COLLECTION_SLUG, docsGroups = [], docsSet })=>{
|
|
177
207
|
const warnings = [];
|
|
178
208
|
const docsSetId = getRecordId(docsSet) ?? 'unknown';
|
|
179
209
|
const sortedDocs = docs.map((doc, index)=>toDocItem({
|
|
@@ -195,8 +225,11 @@ export const buildDocsSetManagerData = ({ adminRoute, docs, docsCollectionSlug =
|
|
|
195
225
|
docs: sortedDocs,
|
|
196
226
|
docsSet: {
|
|
197
227
|
id: docsSetId,
|
|
198
|
-
|
|
199
|
-
|
|
228
|
+
slug: docsSet.slug ?? '',
|
|
229
|
+
routeBase: getDocsSetRouteBase({
|
|
230
|
+
docsGroups,
|
|
231
|
+
docsSet
|
|
232
|
+
}),
|
|
200
233
|
title: docsSet.title ?? docsSetId
|
|
201
234
|
},
|
|
202
235
|
summary: {
|
|
@@ -216,14 +249,11 @@ export const buildDocsSetManagerData = ({ adminRoute, docs, docsCollectionSlug =
|
|
|
216
249
|
warnings
|
|
217
250
|
};
|
|
218
251
|
};
|
|
219
|
-
export const isDocsRecordForDocsSet = ({ doc, docsSetId
|
|
252
|
+
export const isDocsRecordForDocsSet = ({ doc, docsSetId })=>{
|
|
220
253
|
const docDocsSetId = getRelationshipId(doc.docsSet);
|
|
221
|
-
|
|
222
|
-
return docDocsSetId === docsSetId;
|
|
223
|
-
}
|
|
224
|
-
return doc.sync?.sourceId === sourceId;
|
|
254
|
+
return docDocsSetId === docsSetId;
|
|
225
255
|
};
|
|
226
|
-
export const getDocsSetManagerData = async ({ adminRoute, docsCollectionSlug = DEFAULT_DOCS_COLLECTION_SLUG, docsSetId, docsSetsCollectionSlug = DEFAULT_DOCS_SETS_COLLECTION_SLUG, overrideAccess = true, payload })=>{
|
|
256
|
+
export const getDocsSetManagerData = async ({ adminRoute, docsCollectionSlug = DEFAULT_DOCS_COLLECTION_SLUG, docsGroupsCollectionSlug = DEFAULT_DOCS_GROUPS_COLLECTION_SLUG, docsSetId, docsSetsCollectionSlug = DEFAULT_DOCS_SETS_COLLECTION_SLUG, overrideAccess = true, payload })=>{
|
|
227
257
|
const docsSet = await payload.findByID({
|
|
228
258
|
id: docsSetId,
|
|
229
259
|
collection: docsSetsCollectionSlug,
|
|
@@ -236,29 +266,26 @@ export const getDocsSetManagerData = async ({ adminRoute, docsCollectionSlug = D
|
|
|
236
266
|
limit: 1000,
|
|
237
267
|
overrideAccess,
|
|
238
268
|
where: {
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
equals: docsSetId
|
|
243
|
-
}
|
|
244
|
-
},
|
|
245
|
-
{
|
|
246
|
-
'sync.sourceId': {
|
|
247
|
-
equals: docsSet.sourceId
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
]
|
|
269
|
+
docsSet: {
|
|
270
|
+
equals: docsSetId
|
|
271
|
+
}
|
|
251
272
|
}
|
|
252
273
|
});
|
|
274
|
+
const docsGroupsResult = await payload.find({
|
|
275
|
+
collection: docsGroupsCollectionSlug,
|
|
276
|
+
depth: 0,
|
|
277
|
+
limit: 1000,
|
|
278
|
+
overrideAccess
|
|
279
|
+
});
|
|
253
280
|
const docs = docsResult.docs.filter(isRecord).map((doc)=>doc).filter((doc)=>isDocsRecordForDocsSet({
|
|
254
281
|
doc,
|
|
255
|
-
docsSetId
|
|
256
|
-
sourceId: docsSet.sourceId ?? ''
|
|
282
|
+
docsSetId
|
|
257
283
|
}));
|
|
258
284
|
return buildDocsSetManagerData({
|
|
259
285
|
adminRoute,
|
|
260
286
|
docs,
|
|
261
287
|
docsCollectionSlug,
|
|
288
|
+
docsGroups: docsGroupsResult.docs.filter(isRecord).map((group)=>group),
|
|
262
289
|
docsSet
|
|
263
290
|
});
|
|
264
291
|
};
|