multisite-cms-mcp 1.0.21 → 1.0.22
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate-manifest.d.ts","sourceRoot":"","sources":["../../src/tools/validate-manifest.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"validate-manifest.d.ts","sourceRoot":"","sources":["../../src/tools/validate-manifest.ts"],"names":[],"mappings":"AAyCA;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA4N5E"}
|
|
@@ -8,7 +8,8 @@ const pageSchema = zod_1.z.object({
|
|
|
8
8
|
title: zod_1.z.string(),
|
|
9
9
|
editable: zod_1.z.boolean().optional(),
|
|
10
10
|
});
|
|
11
|
-
|
|
11
|
+
// Built-in collection templates
|
|
12
|
+
const builtInTemplatesSchema = zod_1.z.object({
|
|
12
13
|
blogIndex: zod_1.z.string().optional(),
|
|
13
14
|
blogIndexPath: zod_1.z.string().startsWith('/').optional(),
|
|
14
15
|
blogPost: zod_1.z.string().optional(),
|
|
@@ -20,8 +21,17 @@ const cmsTemplatesSchema = zod_1.z.object({
|
|
|
20
21
|
authorsIndex: zod_1.z.string().optional(),
|
|
21
22
|
authorDetail: zod_1.z.string().optional(),
|
|
22
23
|
authorsIndexPath: zod_1.z.string().startsWith('/').optional(),
|
|
24
|
+
// Legacy format - deprecated
|
|
23
25
|
collectionPaths: zod_1.z.record(zod_1.z.string().startsWith('/')).optional(),
|
|
24
|
-
|
|
26
|
+
collectionTemplates: zod_1.z.record(zod_1.z.object({
|
|
27
|
+
path: zod_1.z.string().startsWith('/').optional(),
|
|
28
|
+
indexTemplate: zod_1.z.string().optional(),
|
|
29
|
+
detailTemplate: zod_1.z.string().optional(),
|
|
30
|
+
})).optional(),
|
|
31
|
+
});
|
|
32
|
+
// Custom collection templates use flat format: {slug}Index, {slug}Detail, {slug}IndexPath, {slug}DetailPath
|
|
33
|
+
// This schema allows any additional string keys for custom collections
|
|
34
|
+
const cmsTemplatesSchema = builtInTemplatesSchema.catchall(zod_1.z.string()).optional();
|
|
25
35
|
const manifestSchema = zod_1.z.object({
|
|
26
36
|
pages: zod_1.z.array(pageSchema),
|
|
27
37
|
cmsTemplates: cmsTemplatesSchema,
|
|
@@ -85,6 +95,7 @@ The manifest.json file is not valid JSON. Check for:
|
|
|
85
95
|
}
|
|
86
96
|
// Check cmsTemplates
|
|
87
97
|
const templates = m.cmsTemplates;
|
|
98
|
+
const customCollections = new Set();
|
|
88
99
|
if (templates) {
|
|
89
100
|
// Check template file paths
|
|
90
101
|
const templateFields = ['blogIndex', 'blogPost', 'team', 'downloads', 'authorsIndex', 'authorDetail'];
|
|
@@ -120,9 +131,85 @@ The manifest.json file is not valid JSON. Check for:
|
|
|
120
131
|
if (templates.authorDetail && !templates.authorsIndex) {
|
|
121
132
|
warnings.push('- authorDetail template defined but no authorsIndex - authors need both templates');
|
|
122
133
|
}
|
|
134
|
+
// Detect and validate custom collection templates (flat format)
|
|
135
|
+
// Pattern: {slug}Index, {slug}Detail, {slug}IndexPath, {slug}DetailPath
|
|
136
|
+
const allKeys = Object.keys(templates);
|
|
137
|
+
for (const key of allKeys) {
|
|
138
|
+
// Skip built-in keys
|
|
139
|
+
if (['blogIndex', 'blogIndexPath', 'blogPost', 'blogPostPath', 'team', 'teamPath',
|
|
140
|
+
'downloads', 'downloadsPath', 'authorsIndex', 'authorDetail', 'authorsIndexPath',
|
|
141
|
+
'collectionPaths', 'collectionTemplates'].includes(key)) {
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
// Extract collection slug from key pattern
|
|
145
|
+
let slug = null;
|
|
146
|
+
if (key.endsWith('Index') && !key.endsWith('IndexPath')) {
|
|
147
|
+
slug = key.slice(0, -5); // Remove 'Index'
|
|
148
|
+
}
|
|
149
|
+
else if (key.endsWith('Detail') && !key.endsWith('DetailPath')) {
|
|
150
|
+
slug = key.slice(0, -6); // Remove 'Detail'
|
|
151
|
+
}
|
|
152
|
+
else if (key.endsWith('IndexPath')) {
|
|
153
|
+
slug = key.slice(0, -9); // Remove 'IndexPath'
|
|
154
|
+
}
|
|
155
|
+
else if (key.endsWith('DetailPath')) {
|
|
156
|
+
slug = key.slice(0, -10); // Remove 'DetailPath'
|
|
157
|
+
}
|
|
158
|
+
if (slug && slug.length > 0) {
|
|
159
|
+
customCollections.add(slug);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
// Validate each custom collection
|
|
163
|
+
for (const slug of customCollections) {
|
|
164
|
+
const indexTemplate = templates[`${slug}Index`];
|
|
165
|
+
const detailTemplate = templates[`${slug}Detail`];
|
|
166
|
+
const indexPath = templates[`${slug}IndexPath`];
|
|
167
|
+
const detailPath = templates[`${slug}DetailPath`];
|
|
168
|
+
// Check template file paths
|
|
169
|
+
if (typeof indexTemplate === 'string') {
|
|
170
|
+
if (!indexTemplate.endsWith('.html')) {
|
|
171
|
+
warnings.push(`- cmsTemplates.${slug}Index: should end with .html (got: ${indexTemplate})`);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
if (typeof detailTemplate === 'string') {
|
|
175
|
+
if (!detailTemplate.endsWith('.html')) {
|
|
176
|
+
warnings.push(`- cmsTemplates.${slug}Detail: should end with .html (got: ${detailTemplate})`);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
// Check path format
|
|
180
|
+
if (typeof indexPath === 'string' && !indexPath.startsWith('/')) {
|
|
181
|
+
errors.push(`- cmsTemplates.${slug}IndexPath: must start with "/" (got: ${indexPath})`);
|
|
182
|
+
}
|
|
183
|
+
if (typeof detailPath === 'string' && !detailPath.startsWith('/')) {
|
|
184
|
+
errors.push(`- cmsTemplates.${slug}DetailPath: must start with "/" (got: ${detailPath})`);
|
|
185
|
+
}
|
|
186
|
+
// Check consistency - if you have one, you should have the others
|
|
187
|
+
if (indexTemplate && !indexPath) {
|
|
188
|
+
warnings.push(`- Custom collection "${slug}": has ${slug}Index but no ${slug}IndexPath`);
|
|
189
|
+
}
|
|
190
|
+
if (detailTemplate && !detailPath) {
|
|
191
|
+
warnings.push(`- Custom collection "${slug}": has ${slug}Detail but no ${slug}DetailPath`);
|
|
192
|
+
}
|
|
193
|
+
if (indexPath && !indexTemplate) {
|
|
194
|
+
warnings.push(`- Custom collection "${slug}": has ${slug}IndexPath but no ${slug}Index template`);
|
|
195
|
+
}
|
|
196
|
+
if (detailPath && !detailTemplate) {
|
|
197
|
+
warnings.push(`- Custom collection "${slug}": has ${slug}DetailPath but no ${slug}Detail template`);
|
|
198
|
+
}
|
|
199
|
+
// Note: indexPath and detailPath can be the same (e.g., both "/videos")
|
|
200
|
+
// The system distinguishes by whether a slug segment exists after the path
|
|
201
|
+
}
|
|
202
|
+
// Warn about deprecated collectionTemplates format
|
|
203
|
+
if (templates.collectionTemplates) {
|
|
204
|
+
warnings.push('- cmsTemplates.collectionTemplates: This nested format is deprecated. Use flat format instead: {slug}Index, {slug}Detail, {slug}IndexPath, {slug}DetailPath');
|
|
205
|
+
}
|
|
123
206
|
}
|
|
124
207
|
// Build result
|
|
125
208
|
let output = '';
|
|
209
|
+
// Build custom collections summary
|
|
210
|
+
const customCollectionsSummary = customCollections.size > 0
|
|
211
|
+
? `\n- Custom collections: ${Array.from(customCollections).join(', ')} (using flat format: {slug}Index, {slug}Detail, {slug}IndexPath, {slug}DetailPath)`
|
|
212
|
+
: '';
|
|
126
213
|
if (errors.length === 0 && warnings.length === 0) {
|
|
127
214
|
output = `✅ MANIFEST VALID
|
|
128
215
|
|
|
@@ -130,7 +217,7 @@ The manifest.json structure is correct.
|
|
|
130
217
|
|
|
131
218
|
Summary:
|
|
132
219
|
- ${m.pages?.length || 0} static page(s) defined
|
|
133
|
-
- CMS templates: ${templates ? 'configured in manifest' : 'not configured (can be set via Settings → CMS Templates after upload)'}
|
|
220
|
+
- CMS templates: ${templates ? 'configured in manifest' : 'not configured (can be set via Settings → CMS Templates after upload)'}${customCollectionsSummary}
|
|
134
221
|
- Head HTML: ${m.defaultHeadHtml ? 'configured' : 'not configured'}`;
|
|
135
222
|
}
|
|
136
223
|
else if (errors.length === 0) {
|
package/package.json
CHANGED