@valkyrianlabs/payload-markdown-docs 0.1.0-canary.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 +195 -0
- package/dist/admin/DocsSetManager.d.ts +2 -0
- package/dist/admin/DocsSetManager.js +298 -0
- package/dist/admin/DocsSetManager.js.map +1 -0
- package/dist/admin/docsSetManagerData.d.ts +25 -0
- package/dist/admin/docsSetManagerData.js +266 -0
- package/dist/admin/docsSetManagerData.js.map +1 -0
- package/dist/admin/docsSetManagerTypes.d.ts +103 -0
- package/dist/admin/docsSetManagerTypes.js +3 -0
- package/dist/admin/docsSetManagerTypes.js.map +1 -0
- package/dist/admin/index.d.ts +3 -0
- package/dist/admin/index.js +4 -0
- package/dist/admin/index.js.map +1 -0
- package/dist/cli/commands/install.d.ts +2 -0
- package/dist/cli/commands/install.js +211 -0
- package/dist/cli/commands/install.js.map +1 -0
- package/dist/cli/commands/keygen.d.ts +2 -0
- package/dist/cli/commands/keygen.js +89 -0
- package/dist/cli/commands/keygen.js.map +1 -0
- package/dist/cli/commands/manifest.d.ts +2 -0
- package/dist/cli/commands/manifest.js +50 -0
- package/dist/cli/commands/manifest.js.map +1 -0
- package/dist/cli/commands/plan.d.ts +2 -0
- package/dist/cli/commands/plan.js +110 -0
- package/dist/cli/commands/plan.js.map +1 -0
- package/dist/cli/commands/push.d.ts +3 -0
- package/dist/cli/commands/push.js +308 -0
- package/dist/cli/commands/push.js.map +1 -0
- package/dist/cli/commands/validate.d.ts +3 -0
- package/dist/cli/commands/validate.js +109 -0
- package/dist/cli/commands/validate.js.map +1 -0
- package/dist/cli/filesystem.d.ts +20 -0
- package/dist/cli/filesystem.js +96 -0
- package/dist/cli/filesystem.js.map +1 -0
- package/dist/cli/format.d.ts +35 -0
- package/dist/cli/format.js +76 -0
- package/dist/cli/format.js.map +1 -0
- package/dist/cli/http.d.ts +19 -0
- package/dist/cli/http.js +39 -0
- package/dist/cli/http.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.js +214 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/parseArgs.d.ts +5 -0
- package/dist/cli/parseArgs.js +219 -0
- package/dist/cli/parseArgs.js.map +1 -0
- package/dist/cli/types.d.ts +51 -0
- package/dist/cli/types.js +3 -0
- package/dist/cli/types.js.map +1 -0
- package/dist/collections/docs.d.ts +9 -0
- package/dist/collections/docs.js +168 -0
- package/dist/collections/docs.js.map +1 -0
- package/dist/collections/docsGroups.d.ts +5 -0
- package/dist/collections/docsGroups.js +57 -0
- package/dist/collections/docsGroups.js.map +1 -0
- package/dist/collections/docsSets.d.ts +8 -0
- package/dist/collections/docsSets.js +158 -0
- package/dist/collections/docsSets.js.map +1 -0
- package/dist/collections/index.d.ts +10 -0
- package/dist/collections/index.js +7 -0
- package/dist/collections/index.js.map +1 -0
- package/dist/collections/nonces.d.ts +6 -0
- package/dist/collections/nonces.js +57 -0
- package/dist/collections/nonces.js.map +1 -0
- package/dist/collections/syncRuns.d.ts +5 -0
- package/dist/collections/syncRuns.js +139 -0
- package/dist/collections/syncRuns.js.map +1 -0
- package/dist/constants.d.ts +21 -0
- package/dist/constants.js +23 -0
- package/dist/constants.js.map +1 -0
- package/dist/endpoints/index.d.ts +2 -0
- package/dist/endpoints/index.js +3 -0
- package/dist/endpoints/index.js.map +1 -0
- package/dist/endpoints/sync.d.ts +47 -0
- package/dist/endpoints/sync.js +616 -0
- package/dist/endpoints/sync.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/next/PayloadMarkdownDocsPage.d.ts +7 -0
- package/dist/next/PayloadMarkdownDocsPage.js +142 -0
- package/dist/next/PayloadMarkdownDocsPage.js.map +1 -0
- package/dist/next/index.d.ts +9 -0
- package/dist/next/index.js +7 -0
- package/dist/next/index.js.map +1 -0
- package/dist/next/markdown.d.ts +14 -0
- package/dist/next/markdown.js +232 -0
- package/dist/next/markdown.js.map +1 -0
- package/dist/next/metadata.d.ts +3 -0
- package/dist/next/metadata.js +33 -0
- package/dist/next/metadata.js.map +1 -0
- package/dist/next/records.d.ts +14 -0
- package/dist/next/records.js +146 -0
- package/dist/next/records.js.map +1 -0
- package/dist/next/route.d.ts +6 -0
- package/dist/next/route.js +271 -0
- package/dist/next/route.js.map +1 -0
- package/dist/next/sidebar.d.ts +15 -0
- package/dist/next/sidebar.js +137 -0
- package/dist/next/sidebar.js.map +1 -0
- package/dist/next/types.d.ts +117 -0
- package/dist/next/types.js +3 -0
- package/dist/next/types.js.map +1 -0
- package/dist/payload/applyDocsSync.d.ts +54 -0
- package/dist/payload/applyDocsSync.js +176 -0
- package/dist/payload/applyDocsSync.js.map +1 -0
- package/dist/payload/docsConflicts.d.ts +12 -0
- package/dist/payload/docsConflicts.js +34 -0
- package/dist/payload/docsConflicts.js.map +1 -0
- package/dist/payload/docsData.d.ts +23 -0
- package/dist/payload/docsData.js +59 -0
- package/dist/payload/docsData.js.map +1 -0
- package/dist/payload/docsSets.d.ts +38 -0
- package/dist/payload/docsSets.js +57 -0
- package/dist/payload/docsSets.js.map +1 -0
- package/dist/payload/existingDocs.d.ts +43 -0
- package/dist/payload/existingDocs.js +97 -0
- package/dist/payload/existingDocs.js.map +1 -0
- package/dist/payload/index.d.ts +15 -0
- package/dist/payload/index.js +10 -0
- package/dist/payload/index.js.map +1 -0
- package/dist/payload/routeCollisions.d.ts +31 -0
- package/dist/payload/routeCollisions.js +104 -0
- package/dist/payload/routeCollisions.js.map +1 -0
- package/dist/payload/syncRuns.d.ts +60 -0
- package/dist/payload/syncRuns.js +53 -0
- package/dist/payload/syncRuns.js.map +1 -0
- package/dist/plugin.d.ts +3 -0
- package/dist/plugin.js +165 -0
- package/dist/plugin.js.map +1 -0
- package/dist/routing/index.d.ts +3 -0
- package/dist/routing/index.js +4 -0
- package/dist/routing/index.js.map +1 -0
- package/dist/routing/paths.d.ts +7 -0
- package/dist/routing/paths.js +23 -0
- package/dist/routing/paths.js.map +1 -0
- package/dist/routing/reservations.d.ts +37 -0
- package/dist/routing/reservations.js +79 -0
- package/dist/routing/reservations.js.map +1 -0
- package/dist/security/canonical.d.ts +12 -0
- package/dist/security/canonical.js +24 -0
- package/dist/security/canonical.js.map +1 -0
- package/dist/security/githubOidc.d.ts +45 -0
- package/dist/security/githubOidc.js +177 -0
- package/dist/security/githubOidc.js.map +1 -0
- package/dist/security/headers.d.ts +22 -0
- package/dist/security/headers.js +44 -0
- package/dist/security/headers.js.map +1 -0
- package/dist/security/index.d.ts +15 -0
- package/dist/security/index.js +9 -0
- package/dist/security/index.js.map +1 -0
- package/dist/security/jwks.d.ts +20 -0
- package/dist/security/jwks.js +40 -0
- package/dist/security/jwks.js.map +1 -0
- package/dist/security/jwt.d.ts +10 -0
- package/dist/security/jwt.js +42 -0
- package/dist/security/jwt.js.map +1 -0
- package/dist/security/nonce.d.ts +34 -0
- package/dist/security/nonce.js +43 -0
- package/dist/security/nonce.js.map +1 -0
- package/dist/security/sign.d.ts +13 -0
- package/dist/security/sign.js +39 -0
- package/dist/security/sign.js.map +1 -0
- package/dist/security/verify.d.ts +28 -0
- package/dist/security/verify.js +54 -0
- package/dist/security/verify.js.map +1 -0
- package/dist/skills/codex/SKILL.md +173 -0
- package/dist/skills/codex/examples/docs-page.md +42 -0
- package/dist/skills/codex/examples/github-actions.md +64 -0
- package/dist/skills/codex/reference/admin.md +28 -0
- package/dist/skills/codex/reference/frontmatter.md +39 -0
- package/dist/skills/codex/reference/payload-markdown-directives.md +77 -0
- package/dist/skills/codex/reference/routing.md +35 -0
- package/dist/skills/codex/reference/sync.md +35 -0
- package/dist/skills/codex/reference/troubleshooting.md +53 -0
- package/dist/skills/codex/reference/workflow.md +39 -0
- package/dist/sync/aiExportManifest.d.ts +58 -0
- package/dist/sync/aiExportManifest.js +430 -0
- package/dist/sync/aiExportManifest.js.map +1 -0
- package/dist/sync/frontmatter.d.ts +28 -0
- package/dist/sync/frontmatter.js +210 -0
- package/dist/sync/frontmatter.js.map +1 -0
- package/dist/sync/hash.d.ts +1 -0
- package/dist/sync/hash.js +8 -0
- package/dist/sync/hash.js.map +1 -0
- package/dist/sync/index.d.ts +12 -0
- package/dist/sync/index.js +9 -0
- package/dist/sync/index.js.map +1 -0
- package/dist/sync/manifest.d.ts +58 -0
- package/dist/sync/manifest.js +21 -0
- package/dist/sync/manifest.js.map +1 -0
- package/dist/sync/paths.d.ts +16 -0
- package/dist/sync/paths.js +116 -0
- package/dist/sync/paths.js.map +1 -0
- package/dist/sync/plan.d.ts +29 -0
- package/dist/sync/plan.js +72 -0
- package/dist/sync/plan.js.map +1 -0
- package/dist/sync/validate.d.ts +26 -0
- package/dist/sync/validate.js +308 -0
- package/dist/sync/validate.js.map +1 -0
- package/dist/types.d.ts +84 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +143 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { DocsManifest, DocsManifestFile, DocsManifestSource, ValidatedDocsManifest } from './manifest.js';
|
|
2
|
+
export type DocsValidationErrorCode = 'duplicate_existing_path' | 'duplicate_path' | 'empty_manifest' | 'file_too_large' | 'invalid_ai_export_manifest' | 'invalid_delete_behavior' | 'invalid_frontmatter' | 'invalid_hash' | 'invalid_manifest' | 'invalid_mode' | 'invalid_path' | 'invalid_source' | 'invalid_version' | 'manifest_too_large' | 'missing_ai_export_order_path' | 'non_markdown_file' | 'path_traversal' | 'too_many_files';
|
|
3
|
+
export type DocsValidationIssue = {
|
|
4
|
+
code: DocsValidationErrorCode;
|
|
5
|
+
message: string;
|
|
6
|
+
path?: string;
|
|
7
|
+
};
|
|
8
|
+
export type DocsValidationResult<T = unknown> = {
|
|
9
|
+
data: T;
|
|
10
|
+
issues: DocsValidationIssue[];
|
|
11
|
+
ok: true;
|
|
12
|
+
warnings: DocsValidationIssue[];
|
|
13
|
+
} | {
|
|
14
|
+
issues: DocsValidationIssue[];
|
|
15
|
+
ok: false;
|
|
16
|
+
warnings: DocsValidationIssue[];
|
|
17
|
+
};
|
|
18
|
+
export type DocsValidationOptions = {
|
|
19
|
+
allowedSourceIds?: string[];
|
|
20
|
+
maxFileBytes?: number;
|
|
21
|
+
maxFiles?: number;
|
|
22
|
+
maxTotalBytes?: number;
|
|
23
|
+
routeBase?: string;
|
|
24
|
+
};
|
|
25
|
+
export declare const validateDocsManifest: (manifest: unknown, options?: DocsValidationOptions) => DocsValidationResult<ValidatedDocsManifest>;
|
|
26
|
+
export type { DocsManifest, DocsManifestFile, DocsManifestSource };
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import { DEFAULT_DOCS_ROUTE_BASE, DEFAULT_MAX_DOCS_FILE_BYTES, DEFAULT_MAX_DOCS_FILES, DEFAULT_MAX_DOCS_TOTAL_BYTES } from '../constants.js';
|
|
2
|
+
import { validateDocsAiExportManifest } from './aiExportManifest.js';
|
|
3
|
+
import { parseDocsFrontmatter, resolveDocsTitle } from './frontmatter.js';
|
|
4
|
+
import { sha256Hex } from './hash.js';
|
|
5
|
+
import { deriveRouteFromSourcePath, normalizeDocsPath } from './paths.js';
|
|
6
|
+
const syncModes = new Set([
|
|
7
|
+
'dry-run',
|
|
8
|
+
'sync'
|
|
9
|
+
]);
|
|
10
|
+
const deleteBehaviors = new Set([
|
|
11
|
+
'archive',
|
|
12
|
+
'delete',
|
|
13
|
+
'draft',
|
|
14
|
+
'ignore'
|
|
15
|
+
]);
|
|
16
|
+
const isRecord = (value)=>typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
17
|
+
const createIssue = ({ code, message, path })=>({
|
|
18
|
+
code,
|
|
19
|
+
message,
|
|
20
|
+
path
|
|
21
|
+
});
|
|
22
|
+
const byteLength = (content)=>Buffer.byteLength(content, 'utf8');
|
|
23
|
+
const validateSource = ({ allowedSourceIds, source })=>{
|
|
24
|
+
if (!isRecord(source) || typeof source.id !== 'string' || source.id.trim() === '') {
|
|
25
|
+
return {
|
|
26
|
+
issues: [
|
|
27
|
+
createIssue({
|
|
28
|
+
code: 'invalid_source',
|
|
29
|
+
message: 'Manifest source.id is required.'
|
|
30
|
+
})
|
|
31
|
+
]
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
if (allowedSourceIds && !allowedSourceIds.includes(source.id)) {
|
|
35
|
+
return {
|
|
36
|
+
issues: [
|
|
37
|
+
createIssue({
|
|
38
|
+
code: 'invalid_source',
|
|
39
|
+
message: `Manifest source.id "${source.id}" is not allowed.`
|
|
40
|
+
})
|
|
41
|
+
]
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
issues: [],
|
|
46
|
+
source: {
|
|
47
|
+
id: source.id,
|
|
48
|
+
branch: typeof source.branch === 'string' ? source.branch : undefined,
|
|
49
|
+
commit: typeof source.commit === 'string' ? source.commit : undefined,
|
|
50
|
+
repository: typeof source.repository === 'string' ? source.repository : undefined,
|
|
51
|
+
root: typeof source.root === 'string' ? source.root : undefined
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
const validateMode = (mode)=>{
|
|
56
|
+
if (mode === undefined) {
|
|
57
|
+
return {
|
|
58
|
+
issues: [],
|
|
59
|
+
mode: 'dry-run'
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
if (syncModes.has(mode)) {
|
|
63
|
+
return {
|
|
64
|
+
issues: [],
|
|
65
|
+
mode: mode
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
issues: [
|
|
70
|
+
createIssue({
|
|
71
|
+
code: 'invalid_mode',
|
|
72
|
+
message: 'Manifest mode must be "dry-run" or "sync".'
|
|
73
|
+
})
|
|
74
|
+
],
|
|
75
|
+
mode: 'dry-run'
|
|
76
|
+
};
|
|
77
|
+
};
|
|
78
|
+
const validateDeleteBehavior = (deleteBehavior)=>{
|
|
79
|
+
if (deleteBehavior === undefined) {
|
|
80
|
+
return {
|
|
81
|
+
deleteBehavior: 'archive',
|
|
82
|
+
issues: []
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
if (deleteBehaviors.has(deleteBehavior)) {
|
|
86
|
+
return {
|
|
87
|
+
deleteBehavior: deleteBehavior,
|
|
88
|
+
issues: []
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
deleteBehavior: 'archive',
|
|
93
|
+
issues: [
|
|
94
|
+
createIssue({
|
|
95
|
+
code: 'invalid_delete_behavior',
|
|
96
|
+
message: 'Manifest deleteBehavior must be archive, delete, draft, or ignore.'
|
|
97
|
+
})
|
|
98
|
+
]
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
const validateManifestFile = ({ file, maxFileBytes, routeBase })=>{
|
|
102
|
+
const issues = [];
|
|
103
|
+
const warnings = [];
|
|
104
|
+
if (!isRecord(file)) {
|
|
105
|
+
return {
|
|
106
|
+
fileBytes: 0,
|
|
107
|
+
issues: [
|
|
108
|
+
createIssue({
|
|
109
|
+
code: 'invalid_manifest',
|
|
110
|
+
message: 'Manifest file entries must be objects.'
|
|
111
|
+
})
|
|
112
|
+
],
|
|
113
|
+
warnings
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
const path = typeof file.path === 'string' ? file.path : undefined;
|
|
117
|
+
const content = typeof file.content === 'string' ? file.content : undefined;
|
|
118
|
+
if (!path || content === undefined) {
|
|
119
|
+
return {
|
|
120
|
+
fileBytes: 0,
|
|
121
|
+
issues: [
|
|
122
|
+
createIssue({
|
|
123
|
+
code: 'invalid_manifest',
|
|
124
|
+
message: 'Manifest file entries require string path and content.',
|
|
125
|
+
path
|
|
126
|
+
})
|
|
127
|
+
],
|
|
128
|
+
warnings
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
const normalizedPath = normalizeDocsPath(path);
|
|
132
|
+
if (!normalizedPath.ok) {
|
|
133
|
+
return {
|
|
134
|
+
fileBytes: 0,
|
|
135
|
+
issues: [
|
|
136
|
+
createIssue({
|
|
137
|
+
code: normalizedPath.code,
|
|
138
|
+
message: normalizedPath.message,
|
|
139
|
+
path
|
|
140
|
+
})
|
|
141
|
+
],
|
|
142
|
+
warnings
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
const fileBytes = byteLength(content);
|
|
146
|
+
if (fileBytes > maxFileBytes) {
|
|
147
|
+
issues.push(createIssue({
|
|
148
|
+
code: 'file_too_large',
|
|
149
|
+
message: `File exceeds maximum size of ${maxFileBytes} bytes.`,
|
|
150
|
+
path: normalizedPath.path
|
|
151
|
+
}));
|
|
152
|
+
}
|
|
153
|
+
const computedHash = sha256Hex(content);
|
|
154
|
+
if (file.sha256 !== undefined && (typeof file.sha256 !== 'string' || !/^[a-f0-9]{64}$/i.test(file.sha256) || file.sha256.toLowerCase() !== computedHash)) {
|
|
155
|
+
issues.push(createIssue({
|
|
156
|
+
code: 'invalid_hash',
|
|
157
|
+
message: 'Manifest file sha256 does not match content.',
|
|
158
|
+
path: normalizedPath.path
|
|
159
|
+
}));
|
|
160
|
+
}
|
|
161
|
+
const parsedFrontmatter = parseDocsFrontmatter(content, {
|
|
162
|
+
path: normalizedPath.path
|
|
163
|
+
});
|
|
164
|
+
issues.push(...parsedFrontmatter.issues);
|
|
165
|
+
warnings.push(...parsedFrontmatter.warnings);
|
|
166
|
+
const route = deriveRouteFromSourcePath({
|
|
167
|
+
slug: parsedFrontmatter.frontmatter.slug,
|
|
168
|
+
routeBase,
|
|
169
|
+
sourcePath: normalizedPath.path
|
|
170
|
+
});
|
|
171
|
+
return {
|
|
172
|
+
fileBytes,
|
|
173
|
+
issues,
|
|
174
|
+
normalizedPath: normalizedPath.path,
|
|
175
|
+
validatedFile: {
|
|
176
|
+
content: parsedFrontmatter.content,
|
|
177
|
+
frontmatter: parsedFrontmatter.frontmatter,
|
|
178
|
+
path: normalizedPath.path,
|
|
179
|
+
route,
|
|
180
|
+
sha256: computedHash,
|
|
181
|
+
title: resolveDocsTitle({
|
|
182
|
+
content: parsedFrontmatter.content,
|
|
183
|
+
frontmatter: parsedFrontmatter.frontmatter,
|
|
184
|
+
sourcePath: normalizedPath.path
|
|
185
|
+
})
|
|
186
|
+
},
|
|
187
|
+
warnings
|
|
188
|
+
};
|
|
189
|
+
};
|
|
190
|
+
export const validateDocsManifest = (manifest, options = {})=>{
|
|
191
|
+
const issues = [];
|
|
192
|
+
const warnings = [];
|
|
193
|
+
const maxFileBytes = options.maxFileBytes ?? DEFAULT_MAX_DOCS_FILE_BYTES;
|
|
194
|
+
const maxFiles = options.maxFiles ?? DEFAULT_MAX_DOCS_FILES;
|
|
195
|
+
const maxTotalBytes = options.maxTotalBytes ?? DEFAULT_MAX_DOCS_TOTAL_BYTES;
|
|
196
|
+
const routeBase = options.routeBase ?? DEFAULT_DOCS_ROUTE_BASE;
|
|
197
|
+
if (!isRecord(manifest)) {
|
|
198
|
+
return {
|
|
199
|
+
issues: [
|
|
200
|
+
createIssue({
|
|
201
|
+
code: 'invalid_manifest',
|
|
202
|
+
message: 'Manifest must be an object.'
|
|
203
|
+
})
|
|
204
|
+
],
|
|
205
|
+
ok: false,
|
|
206
|
+
warnings
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
if (manifest.version !== 1) {
|
|
210
|
+
issues.push(createIssue({
|
|
211
|
+
code: 'invalid_version',
|
|
212
|
+
message: 'Manifest version must be 1.'
|
|
213
|
+
}));
|
|
214
|
+
}
|
|
215
|
+
const sourceValidation = validateSource({
|
|
216
|
+
allowedSourceIds: options.allowedSourceIds,
|
|
217
|
+
source: manifest.source
|
|
218
|
+
});
|
|
219
|
+
issues.push(...sourceValidation.issues);
|
|
220
|
+
const modeValidation = validateMode(manifest.mode);
|
|
221
|
+
issues.push(...modeValidation.issues);
|
|
222
|
+
const deleteBehaviorValidation = validateDeleteBehavior(manifest.deleteBehavior);
|
|
223
|
+
issues.push(...deleteBehaviorValidation.issues);
|
|
224
|
+
const publish = manifest.publish === undefined ? false : manifest.publish === true ? true : false;
|
|
225
|
+
if (manifest.publish !== undefined && typeof manifest.publish !== 'boolean') {
|
|
226
|
+
issues.push(createIssue({
|
|
227
|
+
code: 'invalid_manifest',
|
|
228
|
+
message: 'Manifest publish must be a boolean.'
|
|
229
|
+
}));
|
|
230
|
+
}
|
|
231
|
+
const files = Array.isArray(manifest.files) ? manifest.files : undefined;
|
|
232
|
+
if (!files || files.length === 0) {
|
|
233
|
+
issues.push(createIssue({
|
|
234
|
+
code: 'empty_manifest',
|
|
235
|
+
message: 'Manifest must include at least one file.'
|
|
236
|
+
}));
|
|
237
|
+
}
|
|
238
|
+
if (files && files.length > maxFiles) {
|
|
239
|
+
issues.push(createIssue({
|
|
240
|
+
code: 'too_many_files',
|
|
241
|
+
message: `Manifest exceeds maximum file count of ${maxFiles}.`
|
|
242
|
+
}));
|
|
243
|
+
}
|
|
244
|
+
const validatedFiles = [];
|
|
245
|
+
const normalizedPaths = new Set();
|
|
246
|
+
let totalBytes = 0;
|
|
247
|
+
for (const file of files ?? []){
|
|
248
|
+
const fileValidation = validateManifestFile({
|
|
249
|
+
file,
|
|
250
|
+
maxFileBytes,
|
|
251
|
+
routeBase
|
|
252
|
+
});
|
|
253
|
+
totalBytes += fileValidation.fileBytes;
|
|
254
|
+
issues.push(...fileValidation.issues);
|
|
255
|
+
warnings.push(...fileValidation.warnings);
|
|
256
|
+
if (fileValidation.normalizedPath) {
|
|
257
|
+
if (normalizedPaths.has(fileValidation.normalizedPath)) {
|
|
258
|
+
issues.push(createIssue({
|
|
259
|
+
code: 'duplicate_path',
|
|
260
|
+
message: 'Manifest contains duplicate normalized paths.',
|
|
261
|
+
path: fileValidation.normalizedPath
|
|
262
|
+
}));
|
|
263
|
+
}
|
|
264
|
+
normalizedPaths.add(fileValidation.normalizedPath);
|
|
265
|
+
}
|
|
266
|
+
if (fileValidation.validatedFile) {
|
|
267
|
+
validatedFiles.push(fileValidation.validatedFile);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
if (totalBytes > maxTotalBytes) {
|
|
271
|
+
issues.push(createIssue({
|
|
272
|
+
code: 'manifest_too_large',
|
|
273
|
+
message: `Manifest content exceeds maximum total size of ${maxTotalBytes} bytes.`
|
|
274
|
+
}));
|
|
275
|
+
}
|
|
276
|
+
const aiExportValidation = manifest.aiExport === undefined ? undefined : validateDocsAiExportManifest(manifest.aiExport, {
|
|
277
|
+
knownDocsPaths: normalizedPaths
|
|
278
|
+
});
|
|
279
|
+
if (aiExportValidation) {
|
|
280
|
+
issues.push(...aiExportValidation.issues);
|
|
281
|
+
warnings.push(...aiExportValidation.warnings);
|
|
282
|
+
}
|
|
283
|
+
if (issues.length > 0 || !sourceValidation.source || aiExportValidation?.ok === false) {
|
|
284
|
+
return {
|
|
285
|
+
issues,
|
|
286
|
+
ok: false,
|
|
287
|
+
warnings
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
return {
|
|
291
|
+
data: {
|
|
292
|
+
deleteBehavior: deleteBehaviorValidation.deleteBehavior,
|
|
293
|
+
...aiExportValidation?.ok ? {
|
|
294
|
+
aiExport: aiExportValidation.manifest
|
|
295
|
+
} : {},
|
|
296
|
+
files: validatedFiles,
|
|
297
|
+
mode: modeValidation.mode,
|
|
298
|
+
publish,
|
|
299
|
+
source: sourceValidation.source,
|
|
300
|
+
version: 1
|
|
301
|
+
},
|
|
302
|
+
issues,
|
|
303
|
+
ok: true,
|
|
304
|
+
warnings
|
|
305
|
+
};
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
//# sourceMappingURL=validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/sync/validate.ts"],"sourcesContent":["import type {\n DocsDeleteBehavior,\n DocsManifest,\n DocsManifestFile,\n DocsManifestSource,\n DocsSyncMode,\n ValidatedDocsManifest,\n ValidatedDocsManifestFile,\n} from './manifest.js'\n\nimport {\n DEFAULT_DOCS_ROUTE_BASE,\n DEFAULT_MAX_DOCS_FILE_BYTES,\n DEFAULT_MAX_DOCS_FILES,\n DEFAULT_MAX_DOCS_TOTAL_BYTES,\n} from '../constants.js'\nimport { validateDocsAiExportManifest } from './aiExportManifest.js'\nimport {\n parseDocsFrontmatter,\n resolveDocsTitle,\n} from './frontmatter.js'\nimport { sha256Hex } from './hash.js'\nimport { deriveRouteFromSourcePath, normalizeDocsPath } from './paths.js'\n\nexport type DocsValidationErrorCode =\n | 'duplicate_existing_path'\n | 'duplicate_path'\n | 'empty_manifest'\n | 'file_too_large'\n | 'invalid_ai_export_manifest'\n | 'invalid_delete_behavior'\n | 'invalid_frontmatter'\n | 'invalid_hash'\n | 'invalid_manifest'\n | 'invalid_mode'\n | 'invalid_path'\n | 'invalid_source'\n | 'invalid_version'\n | 'manifest_too_large'\n | 'missing_ai_export_order_path'\n | 'non_markdown_file'\n | 'path_traversal'\n | 'too_many_files'\n\nexport type DocsValidationIssue = {\n code: DocsValidationErrorCode\n message: string\n path?: string\n}\n\nexport type DocsValidationResult<T = unknown> =\n | {\n data: T\n issues: DocsValidationIssue[]\n ok: true\n warnings: DocsValidationIssue[]\n }\n | {\n issues: DocsValidationIssue[]\n ok: false\n warnings: DocsValidationIssue[]\n }\n\nexport type DocsValidationOptions = {\n allowedSourceIds?: string[]\n maxFileBytes?: number\n maxFiles?: number\n maxTotalBytes?: number\n routeBase?: string\n}\n\nconst syncModes = new Set<DocsSyncMode>(['dry-run', 'sync'])\nconst deleteBehaviors = new Set<DocsDeleteBehavior>([\n 'archive',\n 'delete',\n 'draft',\n 'ignore',\n])\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n\nconst createIssue = ({\n code,\n message,\n path,\n}: DocsValidationIssue): DocsValidationIssue => ({\n code,\n message,\n path,\n})\n\nconst byteLength = (content: string): number => Buffer.byteLength(content, 'utf8')\n\nconst validateSource = ({\n allowedSourceIds,\n source,\n}: {\n allowedSourceIds?: string[]\n source: unknown\n}): {\n issues: DocsValidationIssue[]\n source?: DocsManifestSource\n} => {\n if (!isRecord(source) || typeof source.id !== 'string' || source.id.trim() === '') {\n return {\n issues: [\n createIssue({\n code: 'invalid_source',\n message: 'Manifest source.id is required.',\n }),\n ],\n }\n }\n\n if (allowedSourceIds && !allowedSourceIds.includes(source.id)) {\n return {\n issues: [\n createIssue({\n code: 'invalid_source',\n message: `Manifest source.id \"${source.id}\" is not allowed.`,\n }),\n ],\n }\n }\n\n return {\n issues: [],\n source: {\n id: source.id,\n branch: typeof source.branch === 'string' ? source.branch : undefined,\n commit: typeof source.commit === 'string' ? source.commit : undefined,\n repository: typeof source.repository === 'string' ? source.repository : undefined,\n root: typeof source.root === 'string' ? source.root : undefined,\n },\n }\n}\n\nconst validateMode = (mode: unknown): {\n issues: DocsValidationIssue[]\n mode: DocsSyncMode\n} => {\n if (mode === undefined) {\n return {\n issues: [],\n mode: 'dry-run',\n }\n }\n\n if (syncModes.has(mode as DocsSyncMode)) {\n return {\n issues: [],\n mode: mode as DocsSyncMode,\n }\n }\n\n return {\n issues: [\n createIssue({\n code: 'invalid_mode',\n message: 'Manifest mode must be \"dry-run\" or \"sync\".',\n }),\n ],\n mode: 'dry-run',\n }\n}\n\nconst validateDeleteBehavior = (deleteBehavior: unknown): {\n deleteBehavior: DocsDeleteBehavior\n issues: DocsValidationIssue[]\n} => {\n if (deleteBehavior === undefined) {\n return {\n deleteBehavior: 'archive',\n issues: [],\n }\n }\n\n if (deleteBehaviors.has(deleteBehavior as DocsDeleteBehavior)) {\n return {\n deleteBehavior: deleteBehavior as DocsDeleteBehavior,\n issues: [],\n }\n }\n\n return {\n deleteBehavior: 'archive',\n issues: [\n createIssue({\n code: 'invalid_delete_behavior',\n message: 'Manifest deleteBehavior must be archive, delete, draft, or ignore.',\n }),\n ],\n }\n}\n\nconst validateManifestFile = ({\n file,\n maxFileBytes,\n routeBase,\n}: {\n file: unknown\n maxFileBytes: number\n routeBase: string\n}): {\n fileBytes: number\n issues: DocsValidationIssue[]\n normalizedPath?: string\n validatedFile?: ValidatedDocsManifestFile\n warnings: DocsValidationIssue[]\n} => {\n const issues: DocsValidationIssue[] = []\n const warnings: DocsValidationIssue[] = []\n\n if (!isRecord(file)) {\n return {\n fileBytes: 0,\n issues: [\n createIssue({\n code: 'invalid_manifest',\n message: 'Manifest file entries must be objects.',\n }),\n ],\n warnings,\n }\n }\n\n const path = typeof file.path === 'string' ? file.path : undefined\n const content = typeof file.content === 'string' ? file.content : undefined\n\n if (!path || content === undefined) {\n return {\n fileBytes: 0,\n issues: [\n createIssue({\n code: 'invalid_manifest',\n message: 'Manifest file entries require string path and content.',\n path,\n }),\n ],\n warnings,\n }\n }\n\n const normalizedPath = normalizeDocsPath(path)\n\n if (!normalizedPath.ok) {\n return {\n fileBytes: 0,\n issues: [\n createIssue({\n code: normalizedPath.code,\n message: normalizedPath.message,\n path,\n }),\n ],\n warnings,\n }\n }\n\n const fileBytes = byteLength(content)\n\n if (fileBytes > maxFileBytes) {\n issues.push(\n createIssue({\n code: 'file_too_large',\n message: `File exceeds maximum size of ${maxFileBytes} bytes.`,\n path: normalizedPath.path,\n }),\n )\n }\n\n const computedHash = sha256Hex(content)\n\n if (\n file.sha256 !== undefined &&\n (typeof file.sha256 !== 'string' ||\n !/^[a-f0-9]{64}$/i.test(file.sha256) ||\n file.sha256.toLowerCase() !== computedHash)\n ) {\n issues.push(\n createIssue({\n code: 'invalid_hash',\n message: 'Manifest file sha256 does not match content.',\n path: normalizedPath.path,\n }),\n )\n }\n\n const parsedFrontmatter = parseDocsFrontmatter(content, {\n path: normalizedPath.path,\n })\n\n issues.push(...parsedFrontmatter.issues)\n warnings.push(...parsedFrontmatter.warnings)\n\n const route = deriveRouteFromSourcePath({\n slug: parsedFrontmatter.frontmatter.slug,\n routeBase,\n sourcePath: normalizedPath.path,\n })\n\n return {\n fileBytes,\n issues,\n normalizedPath: normalizedPath.path,\n validatedFile: {\n content: parsedFrontmatter.content,\n frontmatter: parsedFrontmatter.frontmatter,\n path: normalizedPath.path,\n route,\n sha256: computedHash,\n title: resolveDocsTitle({\n content: parsedFrontmatter.content,\n frontmatter: parsedFrontmatter.frontmatter,\n sourcePath: normalizedPath.path,\n }),\n },\n warnings,\n }\n}\n\nexport const validateDocsManifest = (\n manifest: unknown,\n options: DocsValidationOptions = {},\n): DocsValidationResult<ValidatedDocsManifest> => {\n const issues: DocsValidationIssue[] = []\n const warnings: DocsValidationIssue[] = []\n const maxFileBytes = options.maxFileBytes ?? DEFAULT_MAX_DOCS_FILE_BYTES\n const maxFiles = options.maxFiles ?? DEFAULT_MAX_DOCS_FILES\n const maxTotalBytes = options.maxTotalBytes ?? DEFAULT_MAX_DOCS_TOTAL_BYTES\n const routeBase = options.routeBase ?? DEFAULT_DOCS_ROUTE_BASE\n\n if (!isRecord(manifest)) {\n return {\n issues: [\n createIssue({\n code: 'invalid_manifest',\n message: 'Manifest must be an object.',\n }),\n ],\n ok: false,\n warnings,\n }\n }\n\n if (manifest.version !== 1) {\n issues.push(\n createIssue({\n code: 'invalid_version',\n message: 'Manifest version must be 1.',\n }),\n )\n }\n\n const sourceValidation = validateSource({\n allowedSourceIds: options.allowedSourceIds,\n source: manifest.source,\n })\n\n issues.push(...sourceValidation.issues)\n\n const modeValidation = validateMode(manifest.mode)\n issues.push(...modeValidation.issues)\n\n const deleteBehaviorValidation = validateDeleteBehavior(manifest.deleteBehavior)\n issues.push(...deleteBehaviorValidation.issues)\n\n const publish =\n manifest.publish === undefined ? false : manifest.publish === true ? true : false\n\n if (manifest.publish !== undefined && typeof manifest.publish !== 'boolean') {\n issues.push(\n createIssue({\n code: 'invalid_manifest',\n message: 'Manifest publish must be a boolean.',\n }),\n )\n }\n\n const files = Array.isArray(manifest.files) ? manifest.files : undefined\n\n if (!files || files.length === 0) {\n issues.push(\n createIssue({\n code: 'empty_manifest',\n message: 'Manifest must include at least one file.',\n }),\n )\n }\n\n if (files && files.length > maxFiles) {\n issues.push(\n createIssue({\n code: 'too_many_files',\n message: `Manifest exceeds maximum file count of ${maxFiles}.`,\n }),\n )\n }\n\n const validatedFiles: ValidatedDocsManifestFile[] = []\n const normalizedPaths = new Set<string>()\n let totalBytes = 0\n\n for (const file of files ?? []) {\n const fileValidation = validateManifestFile({\n file,\n maxFileBytes,\n routeBase,\n })\n\n totalBytes += fileValidation.fileBytes\n issues.push(...fileValidation.issues)\n warnings.push(...fileValidation.warnings)\n\n if (fileValidation.normalizedPath) {\n if (normalizedPaths.has(fileValidation.normalizedPath)) {\n issues.push(\n createIssue({\n code: 'duplicate_path',\n message: 'Manifest contains duplicate normalized paths.',\n path: fileValidation.normalizedPath,\n }),\n )\n }\n\n normalizedPaths.add(fileValidation.normalizedPath)\n }\n\n if (fileValidation.validatedFile) {\n validatedFiles.push(fileValidation.validatedFile)\n }\n }\n\n if (totalBytes > maxTotalBytes) {\n issues.push(\n createIssue({\n code: 'manifest_too_large',\n message: `Manifest content exceeds maximum total size of ${maxTotalBytes} bytes.`,\n }),\n )\n }\n\n const aiExportValidation =\n manifest.aiExport === undefined\n ? undefined\n : validateDocsAiExportManifest(manifest.aiExport, {\n knownDocsPaths: normalizedPaths,\n })\n\n if (aiExportValidation) {\n issues.push(...aiExportValidation.issues)\n warnings.push(...aiExportValidation.warnings)\n }\n\n if (\n issues.length > 0 ||\n !sourceValidation.source ||\n aiExportValidation?.ok === false\n ) {\n return {\n issues,\n ok: false,\n warnings,\n }\n }\n\n return {\n data: {\n deleteBehavior: deleteBehaviorValidation.deleteBehavior,\n ...(aiExportValidation?.ok ? { aiExport: aiExportValidation.manifest } : {}),\n files: validatedFiles,\n mode: modeValidation.mode,\n publish,\n source: sourceValidation.source,\n version: 1,\n },\n issues,\n ok: true,\n warnings,\n }\n}\n\nexport type { DocsManifest, DocsManifestFile, DocsManifestSource }\n"],"names":["DEFAULT_DOCS_ROUTE_BASE","DEFAULT_MAX_DOCS_FILE_BYTES","DEFAULT_MAX_DOCS_FILES","DEFAULT_MAX_DOCS_TOTAL_BYTES","validateDocsAiExportManifest","parseDocsFrontmatter","resolveDocsTitle","sha256Hex","deriveRouteFromSourcePath","normalizeDocsPath","syncModes","Set","deleteBehaviors","isRecord","value","Array","isArray","createIssue","code","message","path","byteLength","content","Buffer","validateSource","allowedSourceIds","source","id","trim","issues","includes","branch","undefined","commit","repository","root","validateMode","mode","has","validateDeleteBehavior","deleteBehavior","validateManifestFile","file","maxFileBytes","routeBase","warnings","fileBytes","normalizedPath","ok","push","computedHash","sha256","test","toLowerCase","parsedFrontmatter","route","slug","frontmatter","sourcePath","validatedFile","title","validateDocsManifest","manifest","options","maxFiles","maxTotalBytes","version","sourceValidation","modeValidation","deleteBehaviorValidation","publish","files","length","validatedFiles","normalizedPaths","totalBytes","fileValidation","add","aiExportValidation","aiExport","knownDocsPaths","data"],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
export type PayloadMarkdownDocsConfig = {
|
|
2
|
+
auth?: PayloadMarkdownDocsAuthConfig;
|
|
3
|
+
collections?: PayloadMarkdownDocsCollectionsConfig;
|
|
4
|
+
enabled?: boolean;
|
|
5
|
+
endpoint?: PayloadMarkdownDocsEndpointConfig;
|
|
6
|
+
routing?: PayloadMarkdownDocsRoutingConfig;
|
|
7
|
+
sources?: PayloadMarkdownDocsSourceConfig[];
|
|
8
|
+
sync?: PayloadMarkdownDocsSyncConfig;
|
|
9
|
+
target?: PayloadMarkdownDocsTargetConfig;
|
|
10
|
+
};
|
|
11
|
+
export type PayloadMarkdownDocsEndpointConfig = {
|
|
12
|
+
maxBodyBytes?: number;
|
|
13
|
+
path?: string;
|
|
14
|
+
};
|
|
15
|
+
export type PayloadMarkdownDocsAuthConfig = {
|
|
16
|
+
allowedEnvironments?: string[];
|
|
17
|
+
allowedRefs?: string[];
|
|
18
|
+
allowedRepositories?: string[];
|
|
19
|
+
allowedRepositoryOwners?: string[];
|
|
20
|
+
allowedWorkflowRefs?: string[];
|
|
21
|
+
allowedWorkflows?: string[];
|
|
22
|
+
allowPullRequests?: boolean;
|
|
23
|
+
audience: string;
|
|
24
|
+
issuer?: string;
|
|
25
|
+
jwksUrl?: string;
|
|
26
|
+
maxSkewSeconds?: number;
|
|
27
|
+
mode: 'github-oidc';
|
|
28
|
+
} | {
|
|
29
|
+
keys: PayloadMarkdownDocsEd25519Key[];
|
|
30
|
+
maxSkewSeconds?: number;
|
|
31
|
+
mode: 'ed25519';
|
|
32
|
+
nonceTtlSeconds?: number;
|
|
33
|
+
} | {
|
|
34
|
+
mode: 'disabled';
|
|
35
|
+
};
|
|
36
|
+
export type PayloadMarkdownDocsEd25519Key = {
|
|
37
|
+
id: string;
|
|
38
|
+
publicKey: string;
|
|
39
|
+
};
|
|
40
|
+
export type PayloadMarkdownDocsCollectionConfig = {
|
|
41
|
+
enabled?: boolean;
|
|
42
|
+
slug?: string;
|
|
43
|
+
};
|
|
44
|
+
export type PayloadMarkdownDocsCollectionsConfig = {
|
|
45
|
+
docs?: PayloadMarkdownDocsCollectionConfig;
|
|
46
|
+
docsGroups?: PayloadMarkdownDocsCollectionConfig;
|
|
47
|
+
docsSets?: PayloadMarkdownDocsCollectionConfig;
|
|
48
|
+
nonces?: PayloadMarkdownDocsCollectionConfig;
|
|
49
|
+
syncRuns?: PayloadMarkdownDocsCollectionConfig;
|
|
50
|
+
};
|
|
51
|
+
export type PayloadMarkdownDocsPagesRoutingConfig = {
|
|
52
|
+
allowBridgePages?: boolean;
|
|
53
|
+
bridgeField?: string;
|
|
54
|
+
collection?: string;
|
|
55
|
+
enabled?: boolean;
|
|
56
|
+
routeField?: string;
|
|
57
|
+
};
|
|
58
|
+
export type PayloadMarkdownDocsRoutingConfig = {
|
|
59
|
+
pages?: PayloadMarkdownDocsPagesRoutingConfig;
|
|
60
|
+
};
|
|
61
|
+
export type PayloadMarkdownDocsSourceConfig = {
|
|
62
|
+
id: string;
|
|
63
|
+
root?: string;
|
|
64
|
+
routeBase: string;
|
|
65
|
+
};
|
|
66
|
+
export type PayloadMarkdownDocsTargetConfig = {
|
|
67
|
+
collection: string;
|
|
68
|
+
markdownField: string;
|
|
69
|
+
routeField?: string;
|
|
70
|
+
type: 'existingCollection';
|
|
71
|
+
} | {
|
|
72
|
+
enableDrafts?: boolean;
|
|
73
|
+
markdownField?: string;
|
|
74
|
+
slug?: string;
|
|
75
|
+
type: 'docsCollection';
|
|
76
|
+
};
|
|
77
|
+
export type PayloadMarkdownDocsSyncConfig = {
|
|
78
|
+
allowHardDelete?: boolean;
|
|
79
|
+
allowPublish?: boolean;
|
|
80
|
+
allowWrites?: boolean;
|
|
81
|
+
defaultPublishMode?: 'draft' | 'preserve' | 'published';
|
|
82
|
+
deleteBehavior?: 'archive' | 'delete' | 'draft' | 'ignore';
|
|
83
|
+
requireDryRunBeforeApply?: boolean;
|
|
84
|
+
};
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["export type PayloadMarkdownDocsConfig = {\n auth?: PayloadMarkdownDocsAuthConfig\n collections?: PayloadMarkdownDocsCollectionsConfig\n enabled?: boolean\n endpoint?: PayloadMarkdownDocsEndpointConfig\n routing?: PayloadMarkdownDocsRoutingConfig\n sources?: PayloadMarkdownDocsSourceConfig[]\n sync?: PayloadMarkdownDocsSyncConfig\n target?: PayloadMarkdownDocsTargetConfig\n}\n\nexport type PayloadMarkdownDocsEndpointConfig = {\n maxBodyBytes?: number\n path?: string\n}\n\nexport type PayloadMarkdownDocsAuthConfig =\n | {\n allowedEnvironments?: string[]\n allowedRefs?: string[]\n allowedRepositories?: string[]\n allowedRepositoryOwners?: string[]\n allowedWorkflowRefs?: string[]\n allowedWorkflows?: string[]\n allowPullRequests?: boolean\n audience: string\n issuer?: string\n jwksUrl?: string\n maxSkewSeconds?: number\n mode: 'github-oidc'\n }\n | {\n keys: PayloadMarkdownDocsEd25519Key[]\n maxSkewSeconds?: number\n mode: 'ed25519'\n nonceTtlSeconds?: number\n }\n | {\n mode: 'disabled'\n }\n\nexport type PayloadMarkdownDocsEd25519Key = {\n id: string\n publicKey: string\n}\n\nexport type PayloadMarkdownDocsCollectionConfig = {\n enabled?: boolean\n slug?: string\n}\n\nexport type PayloadMarkdownDocsCollectionsConfig = {\n docs?: PayloadMarkdownDocsCollectionConfig\n docsGroups?: PayloadMarkdownDocsCollectionConfig\n docsSets?: PayloadMarkdownDocsCollectionConfig\n nonces?: PayloadMarkdownDocsCollectionConfig\n syncRuns?: PayloadMarkdownDocsCollectionConfig\n}\n\nexport type PayloadMarkdownDocsPagesRoutingConfig = {\n allowBridgePages?: boolean\n bridgeField?: string\n collection?: string\n enabled?: boolean\n routeField?: string\n}\n\nexport type PayloadMarkdownDocsRoutingConfig = {\n pages?: PayloadMarkdownDocsPagesRoutingConfig\n}\n\nexport type PayloadMarkdownDocsSourceConfig = {\n id: string\n root?: string\n routeBase: string\n}\n\nexport type PayloadMarkdownDocsTargetConfig =\n | {\n collection: string\n markdownField: string\n routeField?: string\n type: 'existingCollection'\n }\n | {\n enableDrafts?: boolean\n markdownField?: string\n slug?: string\n type: 'docsCollection'\n }\n\nexport type PayloadMarkdownDocsSyncConfig = {\n allowHardDelete?: boolean\n allowPublish?: boolean\n allowWrites?: boolean\n defaultPublishMode?: 'draft' | 'preserve' | 'published'\n deleteBehavior?: 'archive' | 'delete' | 'draft' | 'ignore'\n requireDryRunBeforeApply?: boolean\n}\n"],"names":[],"mappings":"AA2FA,WAOC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@valkyrianlabs/payload-markdown-docs",
|
|
3
|
+
"version": "0.1.0-canary.0",
|
|
4
|
+
"description": "Git-backed Markdown documentation sync for Payload CMS, powered by payload-markdown.",
|
|
5
|
+
"bin": {
|
|
6
|
+
"payload-markdown-docs": "./dist/cli/index.js"
|
|
7
|
+
},
|
|
8
|
+
"keywords": [
|
|
9
|
+
"payload",
|
|
10
|
+
"payload-plugin",
|
|
11
|
+
"markdown",
|
|
12
|
+
"documentation",
|
|
13
|
+
"docs"
|
|
14
|
+
],
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"type": "module",
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"import": "./src/index.ts",
|
|
20
|
+
"types": "./src/index.ts",
|
|
21
|
+
"default": "./src/index.ts"
|
|
22
|
+
},
|
|
23
|
+
"./admin": {
|
|
24
|
+
"import": "./src/admin/index.ts",
|
|
25
|
+
"types": "./src/admin/index.ts",
|
|
26
|
+
"default": "./src/admin/index.ts"
|
|
27
|
+
},
|
|
28
|
+
"./next": {
|
|
29
|
+
"import": "./src/next/index.ts",
|
|
30
|
+
"types": "./src/next/index.ts",
|
|
31
|
+
"default": "./src/next/index.ts"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"main": "./src/index.ts",
|
|
35
|
+
"types": "./src/index.ts",
|
|
36
|
+
"files": [
|
|
37
|
+
"dist"
|
|
38
|
+
],
|
|
39
|
+
"scripts": {
|
|
40
|
+
"build": "pnpm clean && pnpm copyfiles && pnpm build:types && pnpm build:swc",
|
|
41
|
+
"build:swc": "swc ./src -d ./dist --config-file .swcrc --strip-leading-paths --ignore \"**/*.spec.ts\"",
|
|
42
|
+
"build:types": "tsc -p tsconfig.build.json --outDir dist --rootDir ./src",
|
|
43
|
+
"clean": "rimraf {dist,*.tsbuildinfo}",
|
|
44
|
+
"copyfiles": "copyfiles -u 1 \"src/**/*.{html,css,scss,ttf,woff,woff2,eot,svg,jpg,png,json,md}\" dist/",
|
|
45
|
+
"dev": "next dev dev --turbo",
|
|
46
|
+
"dev:docs:keygen": "pnpm dev:payload run ./dev/scripts/create-docs-keypair.ts",
|
|
47
|
+
"dev:docs:manifest": "node --import @swc-node/register/esm-register ./src/cli/index.ts manifest ./dev/docs-fixtures/basic --source payload-markdown-docs --root docs --route-base /plugins/payload-markdown-docs --pretty",
|
|
48
|
+
"dev:docs:plan": "node --import @swc-node/register/esm-register ./src/cli/index.ts plan ./dev/docs-fixtures/basic --source payload-markdown-docs --root docs --route-base /plugins/payload-markdown-docs",
|
|
49
|
+
"dev:docs:reset": "pnpm dev:payload run ./dev/scripts/reset-docs.ts",
|
|
50
|
+
"dev:docs:seed": "pnpm dev:payload run ./dev/scripts/seed-docs.ts",
|
|
51
|
+
"dev:docs:validate": "node --import @swc-node/register/esm-register ./src/cli/index.ts validate ./dev/docs-fixtures/basic --source payload-markdown-docs --root docs --route-base /plugins/payload-markdown-docs",
|
|
52
|
+
"dev:generate-importmap": "pnpm dev:payload generate:importmap",
|
|
53
|
+
"dev:generate-types": "pnpm dev:payload generate:types",
|
|
54
|
+
"dev:payload": "cross-env PAYLOAD_CONFIG_PATH=./dev/payload.config.ts payload",
|
|
55
|
+
"generate:importmap": "pnpm dev:generate-importmap",
|
|
56
|
+
"generate:types": "pnpm dev:generate-types",
|
|
57
|
+
"lint": "eslint",
|
|
58
|
+
"lint:fix": "eslint ./src --fix",
|
|
59
|
+
"prepack": "pnpm build",
|
|
60
|
+
"test": "pnpm test:int && pnpm test:e2e",
|
|
61
|
+
"test:e2e": "playwright test",
|
|
62
|
+
"test:int": "vitest"
|
|
63
|
+
},
|
|
64
|
+
"devDependencies": {
|
|
65
|
+
"@eslint/eslintrc": "^3.3.5",
|
|
66
|
+
"@payloadcms/db-postgres": "latest",
|
|
67
|
+
"@payloadcms/db-sqlite": "latest",
|
|
68
|
+
"@payloadcms/eslint-config": "3.28.0",
|
|
69
|
+
"@payloadcms/next": "latest",
|
|
70
|
+
"@payloadcms/richtext-lexical": "latest",
|
|
71
|
+
"@payloadcms/ui": "latest",
|
|
72
|
+
"@playwright/test": "1.58.2",
|
|
73
|
+
"@swc-node/register": "1.10.9",
|
|
74
|
+
"@swc/cli": "0.6.0",
|
|
75
|
+
"@types/node": "22.19.9",
|
|
76
|
+
"@types/react": "19.2.14",
|
|
77
|
+
"@types/react-dom": "19.2.3",
|
|
78
|
+
"copyfiles": "2.4.1",
|
|
79
|
+
"cross-env": "^7.0.3",
|
|
80
|
+
"eslint": "^9.39.4",
|
|
81
|
+
"eslint-config-next": "16.2.3",
|
|
82
|
+
"graphql": "^16.13.2",
|
|
83
|
+
"mongodb-memory-server": "10.1.4",
|
|
84
|
+
"next": "16.2.3",
|
|
85
|
+
"open": "^10.2.0",
|
|
86
|
+
"payload": "latest",
|
|
87
|
+
"prettier": "^3.8.3",
|
|
88
|
+
"qs-esm": "8.0.1",
|
|
89
|
+
"react": "19.2.4",
|
|
90
|
+
"react-dom": "19.2.4",
|
|
91
|
+
"rimraf": "3.0.2",
|
|
92
|
+
"sharp": "0.34.2",
|
|
93
|
+
"sort-package-json": "^2.15.1",
|
|
94
|
+
"typescript": "5.7.3",
|
|
95
|
+
"vite-tsconfig-paths": "6.0.5",
|
|
96
|
+
"vitest": "4.0.18",
|
|
97
|
+
"tailwindcss": "^4.2.4",
|
|
98
|
+
"@tailwindcss/typography": "^0.5.19",
|
|
99
|
+
"@tailwindcss/postcss": "^4.2.4",
|
|
100
|
+
"postcss": "^8.5.13"
|
|
101
|
+
},
|
|
102
|
+
"peerDependencies": {
|
|
103
|
+
"payload": ">=3.0.0"
|
|
104
|
+
},
|
|
105
|
+
"engines": {
|
|
106
|
+
"node": "^18.20.2 || >=20.9.0",
|
|
107
|
+
"pnpm": "^9 || ^10"
|
|
108
|
+
},
|
|
109
|
+
"publishConfig": {
|
|
110
|
+
"exports": {
|
|
111
|
+
".": {
|
|
112
|
+
"import": "./dist/index.js",
|
|
113
|
+
"types": "./dist/index.d.ts",
|
|
114
|
+
"default": "./dist/index.js"
|
|
115
|
+
},
|
|
116
|
+
"./admin": {
|
|
117
|
+
"import": "./dist/admin/index.js",
|
|
118
|
+
"types": "./dist/admin/index.d.ts",
|
|
119
|
+
"default": "./dist/admin/index.js"
|
|
120
|
+
},
|
|
121
|
+
"./next": {
|
|
122
|
+
"import": "./dist/next/index.js",
|
|
123
|
+
"types": "./dist/next/index.d.ts",
|
|
124
|
+
"default": "./dist/next/index.js"
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
"main": "./dist/index.js",
|
|
128
|
+
"types": "./dist/index.d.ts"
|
|
129
|
+
},
|
|
130
|
+
"pnpm": {
|
|
131
|
+
"onlyBuiltDependencies": [
|
|
132
|
+
"@swc/core",
|
|
133
|
+
"esbuild",
|
|
134
|
+
"mongodb-memory-server",
|
|
135
|
+
"sharp",
|
|
136
|
+
"unrs-resolver"
|
|
137
|
+
]
|
|
138
|
+
},
|
|
139
|
+
"registry": "https://registry.npmjs.org/",
|
|
140
|
+
"dependencies": {
|
|
141
|
+
"@valkyrianlabs/payload-markdown": "latest"
|
|
142
|
+
}
|
|
143
|
+
}
|