@se-studio/contentful-cms 3.13.1 → 3.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.
Files changed (106) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/HOSTED.md +3 -3
  3. package/README.md +8 -10
  4. package/dist/cli/parse-boolean.d.ts +3 -0
  5. package/dist/cli/parse-boolean.d.ts.map +1 -0
  6. package/dist/cli/parse-boolean.js +9 -0
  7. package/dist/cli/parse-boolean.js.map +1 -0
  8. package/dist/cli/program.d.ts.map +1 -1
  9. package/dist/cli/program.js +3 -1
  10. package/dist/cli/program.js.map +1 -1
  11. package/dist/commands/create-person.d.ts.map +1 -1
  12. package/dist/commands/create-person.js +9 -0
  13. package/dist/commands/create-person.js.map +1 -1
  14. package/dist/commands/create-taxonomy.d.ts +8 -3
  15. package/dist/commands/create-taxonomy.d.ts.map +1 -1
  16. package/dist/commands/create-taxonomy.js +54 -0
  17. package/dist/commands/create-taxonomy.js.map +1 -1
  18. package/dist/commands/release.d.ts +4 -0
  19. package/dist/commands/release.d.ts.map +1 -0
  20. package/dist/commands/release.js +331 -0
  21. package/dist/commands/release.js.map +1 -0
  22. package/dist/contentful/cda-sync.d.ts.map +1 -1
  23. package/dist/contentful/cda-sync.js +5 -1
  24. package/dist/contentful/cda-sync.js.map +1 -1
  25. package/dist/contentful/cma-user-agent.d.ts +1 -1
  26. package/dist/contentful/entry-fields.d.ts +7 -1
  27. package/dist/contentful/entry-fields.d.ts.map +1 -1
  28. package/dist/contentful/entry-fields.js +39 -0
  29. package/dist/contentful/entry-fields.js.map +1 -1
  30. package/dist/contentful/person-create.d.ts +4 -0
  31. package/dist/contentful/person-create.d.ts.map +1 -1
  32. package/dist/contentful/person-create.js +7 -0
  33. package/dist/contentful/person-create.js.map +1 -1
  34. package/dist/contentful/person-type-resolve.d.ts +8 -0
  35. package/dist/contentful/person-type-resolve.d.ts.map +1 -0
  36. package/dist/contentful/person-type-resolve.js +20 -0
  37. package/dist/contentful/person-type-resolve.js.map +1 -0
  38. package/dist/editor-pack/capabilities.d.ts.map +1 -1
  39. package/dist/editor-pack/capabilities.js +9 -2
  40. package/dist/editor-pack/capabilities.js.map +1 -1
  41. package/dist/editor-pack/generate.d.ts.map +1 -1
  42. package/dist/editor-pack/generate.js +2 -1
  43. package/dist/editor-pack/generate.js.map +1 -1
  44. package/dist/generated/help-topics.d.ts +1 -1
  45. package/dist/generated/help-topics.d.ts.map +1 -1
  46. package/dist/generated/help-topics.js +2 -2
  47. package/dist/generated/help-topics.js.map +1 -1
  48. package/dist/generated/version.d.ts +1 -1
  49. package/dist/generated/version.js +1 -1
  50. package/dist/hosted/next/routes/mcp.d.ts.map +1 -1
  51. package/dist/hosted/next/routes/mcp.js +18 -0
  52. package/dist/hosted/next/routes/mcp.js.map +1 -1
  53. package/dist/index/schema.d.ts +2 -2
  54. package/dist/index/schema.d.ts.map +1 -1
  55. package/dist/index/schema.js +1 -0
  56. package/dist/index/schema.js.map +1 -1
  57. package/dist/mcp/tools/cms-edit.d.ts +1 -1
  58. package/dist/mcp/tools/cms-edit.d.ts.map +1 -1
  59. package/dist/mcp/tools/cms-edit.js +4 -3
  60. package/dist/mcp/tools/cms-edit.js.map +1 -1
  61. package/dist/project/types.d.ts +3 -0
  62. package/dist/project/types.d.ts.map +1 -1
  63. package/dist/project/types.js +19 -1
  64. package/dist/project/types.js.map +1 -1
  65. package/dist/publish/attribution.d.ts +16 -0
  66. package/dist/publish/attribution.d.ts.map +1 -0
  67. package/dist/publish/attribution.js +28 -0
  68. package/dist/publish/attribution.js.map +1 -0
  69. package/dist/publish/classify.d.ts +15 -0
  70. package/dist/publish/classify.d.ts.map +1 -0
  71. package/dist/publish/classify.js +79 -0
  72. package/dist/publish/classify.js.map +1 -0
  73. package/dist/publish/cma.d.ts +33 -0
  74. package/dist/publish/cma.d.ts.map +1 -0
  75. package/dist/publish/cma.js +267 -0
  76. package/dist/publish/cma.js.map +1 -0
  77. package/dist/publish/fields.d.ts +9 -0
  78. package/dist/publish/fields.d.ts.map +1 -0
  79. package/dist/publish/fields.js +56 -0
  80. package/dist/publish/fields.js.map +1 -0
  81. package/dist/publish/permissions.d.ts +23 -0
  82. package/dist/publish/permissions.d.ts.map +1 -0
  83. package/dist/publish/permissions.js +131 -0
  84. package/dist/publish/permissions.js.map +1 -0
  85. package/dist/publish/plan.d.ts +116 -0
  86. package/dist/publish/plan.d.ts.map +1 -0
  87. package/dist/publish/plan.js +361 -0
  88. package/dist/publish/plan.js.map +1 -0
  89. package/dist/publish/revalidate-request.d.ts +29 -0
  90. package/dist/publish/revalidate-request.d.ts.map +1 -0
  91. package/dist/publish/revalidate-request.js +26 -0
  92. package/dist/publish/revalidate-request.js.map +1 -0
  93. package/dist/publish/store.d.ts +13 -0
  94. package/dist/publish/store.d.ts.map +1 -0
  95. package/dist/publish/store.js +102 -0
  96. package/dist/publish/store.js.map +1 -0
  97. package/dist/runtime/context.d.ts +5 -0
  98. package/dist/runtime/context.d.ts.map +1 -1
  99. package/dist/runtime/context.js.map +1 -1
  100. package/docs/FUNCTIONAL_SPEC.md +10 -7
  101. package/docs/editor-tasks/publish-handoff.md +24 -23
  102. package/docs/help/index.md +4 -2
  103. package/docs/help/person-from-json.md +2 -1
  104. package/docs/help/publish.md +45 -0
  105. package/package.json +2 -2
  106. package/skills/core/SKILL.md +4 -4
@@ -0,0 +1,361 @@
1
+ import { attributeChange } from './attribution.js';
2
+ import { cascadeNote, classifyContentType, isSharedTemplate } from './classify.js';
3
+ export const PLAN_TTL_MS = 30 * 60 * 1000;
4
+ export const MAX_TARGETS = 50;
5
+ export const MAX_UPSTREAM = 50;
6
+ export function needsPublish(node) {
7
+ if (node.archived)
8
+ return false;
9
+ if (node.publishedVersion == null)
10
+ return true;
11
+ return node.version > node.publishedVersion + 1;
12
+ }
13
+ export function isPublishedClean(node) {
14
+ if (node.archived || node.publishedVersion == null)
15
+ return false;
16
+ return node.version === node.publishedVersion + 1;
17
+ }
18
+ export function assertPlannedVersion(current, expected) {
19
+ if (current !== expected) {
20
+ throw new Error(`This entry changed after the plan was made (now version ${current}, plan saw ${expected}). Run plan again.`);
21
+ }
22
+ }
23
+ export function assertStillClean(version, publishedVersion) {
24
+ if (publishedVersion == null || version !== publishedVersion + 1) {
25
+ throw new Error('This entry is no longer a clean published version. Run plan again.');
26
+ }
27
+ }
28
+ function itemFor(node, role, depth, userId, steps, draftParents = []) {
29
+ const attribution = steps.includes('touch')
30
+ ? 'clean'
31
+ : attributeChange({
32
+ userId,
33
+ version: node.version,
34
+ publishedVersion: node.publishedVersion,
35
+ updatedById: node.updatedById,
36
+ createdById: node.createdById,
37
+ });
38
+ return {
39
+ entityId: node.id,
40
+ kind: node.kind,
41
+ contentType: node.contentType,
42
+ label: node.label,
43
+ version: node.version,
44
+ publishedVersion: node.publishedVersion,
45
+ attribution,
46
+ role,
47
+ depth,
48
+ steps,
49
+ slug: node.slug,
50
+ draftParents,
51
+ };
52
+ }
53
+ /** Roots and webhook types refresh production. They publish after the drafts they depend on. */
54
+ function publishesLast(item, extraRoots) {
55
+ if (item.role === 'touch')
56
+ return true;
57
+ const contentClass = classifyContentType(item.contentType, extraRoots);
58
+ return contentClass === 'root' || contentClass === 'webhook';
59
+ }
60
+ function sortItems(items, extraRoots) {
61
+ return [...items].sort((a, b) => {
62
+ const aLast = publishesLast(a, extraRoots) ? 1 : 0;
63
+ const bLast = publishesLast(b, extraRoots) ? 1 : 0;
64
+ if (aLast !== bLast)
65
+ return aLast - bLast;
66
+ if (a.depth !== b.depth)
67
+ return b.depth - a.depth;
68
+ if (a.kind !== b.kind)
69
+ return a.kind === 'asset' ? -1 : 1;
70
+ return a.label.localeCompare(b.label);
71
+ });
72
+ }
73
+ export function buildPublishPlan(input) {
74
+ const extraRoots = input.extraRoots;
75
+ const nodes = input.nodes;
76
+ const targetIds = input.targetIds.slice(0, MAX_TARGETS);
77
+ const targetSet = new Set(targetIds);
78
+ const depth = new Map();
79
+ const fromTarget = new Map();
80
+ const seen = new Set();
81
+ const blocked = [];
82
+ const queue = targetIds.map((id) => ({ id, depth: 0, fromTarget: id }));
83
+ while (queue.length > 0) {
84
+ const current = queue.shift();
85
+ if (!current || seen.has(current.id))
86
+ continue;
87
+ fromTarget.set(current.id, current.fromTarget);
88
+ const node = nodes.get(current.id);
89
+ if (!node) {
90
+ blocked.push({ id: current.id, reason: 'Entry or asset could not be loaded.' });
91
+ continue;
92
+ }
93
+ if (node.contentType === 'redirect') {
94
+ blocked.push({
95
+ id: node.id,
96
+ contentType: 'redirect',
97
+ label: node.label,
98
+ reason: 'Redirects go live on the next deploy, not when an entry is published.',
99
+ });
100
+ continue;
101
+ }
102
+ seen.add(current.id);
103
+ depth.set(current.id, current.depth);
104
+ if (node.kind === 'asset')
105
+ continue;
106
+ for (const link of node.links) {
107
+ if (seen.has(link.id))
108
+ continue;
109
+ const child = nodes.get(link.id);
110
+ if (!child) {
111
+ blocked.push({ id: link.id, reason: 'Linked entry or asset could not be loaded.' });
112
+ continue;
113
+ }
114
+ if (child.contentType === 'redirect') {
115
+ blocked.push({
116
+ id: child.id,
117
+ contentType: 'redirect',
118
+ label: child.label,
119
+ reason: 'Redirects go live on the next deploy, not when an entry is published.',
120
+ });
121
+ continue;
122
+ }
123
+ if (child.kind === 'entry' && !targetSet.has(child.id)) {
124
+ const childClass = classifyContentType(child.contentType, extraRoots);
125
+ if (childClass === 'root') {
126
+ if (child.publishedVersion == null) {
127
+ blocked.push({
128
+ id: child.id,
129
+ contentType: child.contentType,
130
+ label: child.label,
131
+ reason: `Referenced ${child.contentType ?? 'entry'} is not published. It is not included in this publish.`,
132
+ });
133
+ }
134
+ else if (needsPublish(child)) {
135
+ blocked.push({
136
+ id: child.id,
137
+ contentType: child.contentType,
138
+ label: child.label,
139
+ reason: `Referenced ${child.contentType ?? 'entry'} has unpublished changes. It is not included in this publish.`,
140
+ });
141
+ }
142
+ continue;
143
+ }
144
+ if (isSharedTemplate(child.contentType))
145
+ continue;
146
+ }
147
+ queue.push({
148
+ id: link.id,
149
+ depth: current.depth + 1,
150
+ fromTarget: current.fromTarget,
151
+ });
152
+ }
153
+ }
154
+ const items = [];
155
+ const dirtyIds = new Set();
156
+ for (const id of seen) {
157
+ const node = nodes.get(id);
158
+ if (!node || !needsPublish(node))
159
+ continue;
160
+ dirtyIds.add(id);
161
+ const parents = input.parentsByEntryId?.get(id) ?? [];
162
+ const draftParents = parents
163
+ .filter((parent) => parent.draftLinks && parent.publishedLinks === false)
164
+ .map((parent) => ({
165
+ id: parent.id,
166
+ contentType: parent.contentType,
167
+ label: parent.label,
168
+ }));
169
+ items.push(itemFor(node, targetSet.has(id) ? 'target' : 'dependency', depth.get(id) ?? 0, input.userId, ['publish'], draftParents));
170
+ }
171
+ for (const id of targetIds) {
172
+ const node = nodes.get(id);
173
+ if (!node || dirtyIds.has(id) || node.kind === 'asset')
174
+ continue;
175
+ const contentClass = classifyContentType(node.contentType, extraRoots);
176
+ if (contentClass !== 'root' && contentClass !== 'embedded')
177
+ continue;
178
+ const hasDirtyDescendant = items.some((item) => item.entityId !== id && fromTarget.get(item.entityId) === id);
179
+ if (!hasDirtyDescendant || !isPublishedClean(node))
180
+ continue;
181
+ items.push(itemFor(node, 'touch', 0, input.userId, ['touch']));
182
+ }
183
+ const upstream = [];
184
+ for (const rootId of (input.upstreamRootIds ?? []).slice(0, MAX_UPSTREAM)) {
185
+ const root = nodes.get(rootId);
186
+ if (!root)
187
+ continue;
188
+ upstream.push({ id: root.id, contentType: root.contentType, label: root.label });
189
+ if (targetSet.has(root.id) || items.some((item) => item.entityId === root.id))
190
+ continue;
191
+ if (needsPublish(root)) {
192
+ items.push(itemFor(root, 'target', -1, input.userId, ['publish']));
193
+ }
194
+ else if (isPublishedClean(root)) {
195
+ items.push(itemFor(root, 'touch', -1, input.userId, ['touch']));
196
+ }
197
+ }
198
+ const notes = [];
199
+ const notedTypes = new Set();
200
+ for (const id of targetIds) {
201
+ const node = nodes.get(id);
202
+ const note = cascadeNote(node?.contentType);
203
+ if (note && node?.contentType && !notedTypes.has(node.contentType)) {
204
+ const contentClass = classifyContentType(node.contentType, extraRoots);
205
+ if (contentClass === 'webhook') {
206
+ notedTypes.add(node.contentType);
207
+ notes.push(note);
208
+ }
209
+ }
210
+ }
211
+ for (const parent of upstream) {
212
+ if (classifyContentType(parent.contentType, extraRoots) !== 'webhook')
213
+ continue;
214
+ const note = cascadeNote(parent.contentType);
215
+ if (note && parent.contentType && !notedTypes.has(parent.contentType)) {
216
+ notedTypes.add(parent.contentType);
217
+ notes.push(note);
218
+ }
219
+ }
220
+ for (const item of items) {
221
+ for (const parent of item.draftParents) {
222
+ notes.push(`${item.label} is linked from unpublished ${parent.contentType} "${parent.label}". Publishing the ${item.contentType ?? 'entry'} does not add it to the live page.`);
223
+ }
224
+ }
225
+ if ((input.upstreamRootIds?.length ?? 0) > MAX_UPSTREAM) {
226
+ notes.push(`Upstream pages are capped at ${MAX_UPSTREAM}.`);
227
+ }
228
+ if (input.upstreamTruncated) {
229
+ notes.push('Parent lookup stopped early. Some pages that use this content may be missing.');
230
+ }
231
+ if (input.truncated || input.targetIds.length > MAX_TARGETS) {
232
+ notes.push(`Only the first ${MAX_TARGETS} targets are in this plan.`);
233
+ }
234
+ const conflicts = items.filter((item) => item.attribution === 'theirs' || item.attribution === 'mixed');
235
+ if (conflicts.length > 0) {
236
+ notes.push('Someone else also changed part of this publish. Choose all (publish those entries too) or mine (skip them). One entry cannot be split by field.');
237
+ }
238
+ const createdAt = input.now.toISOString();
239
+ return {
240
+ id: input.id,
241
+ userId: input.userId,
242
+ spaceId: input.spaceId,
243
+ action: 'publish',
244
+ createdAt,
245
+ expiresAt: new Date(input.now.getTime() + PLAN_TTL_MS).toISOString(),
246
+ scope: conflicts.length > 0 ? null : 'all',
247
+ awaitingChoice: conflicts.length > 0,
248
+ items: sortItems(items, extraRoots),
249
+ blocked,
250
+ upstream,
251
+ notes,
252
+ truncated: input.truncated === true ||
253
+ input.upstreamTruncated === true ||
254
+ input.targetIds.length > MAX_TARGETS,
255
+ };
256
+ }
257
+ export function buildEntryActionPlan(input) {
258
+ const items = input.nodes.map((node) => {
259
+ const published = node.publishedVersion != null && !node.archived;
260
+ const steps = input.action === 'archive'
261
+ ? published
262
+ ? ['unpublish', 'archive']
263
+ : ['archive']
264
+ : ['unpublish'];
265
+ return {
266
+ entityId: node.id,
267
+ kind: node.kind,
268
+ contentType: node.contentType,
269
+ label: node.label,
270
+ version: node.version,
271
+ publishedVersion: node.publishedVersion,
272
+ attribution: 'mine',
273
+ role: 'target',
274
+ depth: 0,
275
+ steps,
276
+ slug: node.slug,
277
+ draftParents: [],
278
+ };
279
+ });
280
+ const notes = [];
281
+ if (input.upstream.length > 0) {
282
+ notes.push('These entries are still linked from other content. Unpublishing them removes them from the live site everywhere they are used. Child entries are not unpublished.');
283
+ }
284
+ if (input.action === 'archive') {
285
+ notes.push('A published entry is unpublished first, then archived.');
286
+ }
287
+ return {
288
+ id: input.id,
289
+ userId: input.userId,
290
+ spaceId: input.spaceId,
291
+ action: input.action,
292
+ createdAt: input.now.toISOString(),
293
+ expiresAt: new Date(input.now.getTime() + PLAN_TTL_MS).toISOString(),
294
+ scope: 'all',
295
+ awaitingChoice: false,
296
+ items,
297
+ blocked: [],
298
+ upstream: input.upstream,
299
+ notes,
300
+ truncated: false,
301
+ };
302
+ }
303
+ export function buildRevalidatePlan(input) {
304
+ return {
305
+ id: input.id,
306
+ userId: input.userId,
307
+ spaceId: input.spaceId,
308
+ action: 'revalidate',
309
+ createdAt: input.now.toISOString(),
310
+ expiresAt: new Date(input.now.getTime() + PLAN_TTL_MS).toISOString(),
311
+ scope: 'all',
312
+ awaitingChoice: false,
313
+ items: input.nodes.map((node) => ({
314
+ entityId: node.id,
315
+ kind: 'entry',
316
+ contentType: node.contentType,
317
+ label: node.label,
318
+ version: node.version,
319
+ publishedVersion: node.publishedVersion,
320
+ attribution: 'clean',
321
+ role: 'target',
322
+ depth: 0,
323
+ steps: ['revalidate'],
324
+ slug: node.slug,
325
+ draftParents: [],
326
+ })),
327
+ blocked: [],
328
+ upstream: [],
329
+ notes: [
330
+ 'This refreshes production cache for these pages. It does not publish Contentful drafts.',
331
+ ],
332
+ truncated: false,
333
+ };
334
+ }
335
+ export function choosePlanScope(plan, scope) {
336
+ if (!plan.awaitingChoice) {
337
+ throw new Error('This plan has no conflict to choose.');
338
+ }
339
+ return { ...plan, scope, awaitingChoice: false };
340
+ }
341
+ export function itemsForScope(plan) {
342
+ if (plan.scope === 'mine') {
343
+ return plan.items.filter((item) => item.attribution === 'mine' || item.attribution === 'clean');
344
+ }
345
+ return plan.items;
346
+ }
347
+ export function assertPlanApplicable(plan, userId, now) {
348
+ if (plan.userId !== userId) {
349
+ throw new Error('This plan belongs to a different Contentful user.');
350
+ }
351
+ if (Date.parse(plan.expiresAt) <= now.getTime()) {
352
+ throw new Error('This plan has expired. Run plan again.');
353
+ }
354
+ if (plan.awaitingChoice || plan.scope == null) {
355
+ throw new Error('Someone else changed entries in this plan. Choose all or mine, then apply only after the user says yes.');
356
+ }
357
+ if (plan.appliedAt) {
358
+ throw new Error('This plan was already applied.');
359
+ }
360
+ }
361
+ //# sourceMappingURL=plan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan.js","sourceRoot":"","sources":["../../src/publish/plan.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ export interface RevalidateEntryPayload {
2
+ sys: {
3
+ type: 'Entry';
4
+ id: string;
5
+ contentType: {
6
+ sys: {
7
+ type: 'Link';
8
+ linkType: 'ContentType';
9
+ id: string;
10
+ };
11
+ };
12
+ };
13
+ fields: Record<string, Record<string, string>>;
14
+ }
15
+ export interface RevalidateRequest {
16
+ url: string;
17
+ headers: Record<string, string>;
18
+ body: RevalidateEntryPayload;
19
+ }
20
+ export declare function buildRevalidateRequest(input: {
21
+ productionSiteUrl: string;
22
+ secret: string;
23
+ bypassToken?: string;
24
+ entryId: string;
25
+ contentType: string;
26
+ slug?: string;
27
+ locale: string;
28
+ }): RevalidateRequest;
29
+ //# sourceMappingURL=revalidate-request.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"revalidate-request.d.ts","sourceRoot":"","sources":["../../src/publish/revalidate-request.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,sBAAsB;IACrC,GAAG,EAAE;QACH,IAAI,EAAE,OAAO,CAAC;QACd,EAAE,EAAE,MAAM,CAAC;QACX,WAAW,EAAE;YAAE,GAAG,EAAE;gBAAE,IAAI,EAAE,MAAM,CAAC;gBAAC,QAAQ,EAAE,aAAa,CAAC;gBAAC,EAAE,EAAE,MAAM,CAAA;aAAE,CAAA;SAAE,CAAC;KAC7E,CAAC;IACF,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAChD;AAED,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,EAAE,sBAAsB,CAAC;CAC9B;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE;IAC5C,iBAAiB,EAAE,MAAM,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,iBAAiB,CAuBpB"}
@@ -0,0 +1,26 @@
1
+ export function buildRevalidateRequest(input) {
2
+ const base = input.productionSiteUrl.replace(/\/$/, '');
3
+ const headers = {
4
+ 'content-type': 'application/json',
5
+ REVALIDATION_SECRET: input.secret,
6
+ };
7
+ if (input.bypassToken) {
8
+ headers['x-vercel-protection-bypass'] = input.bypassToken;
9
+ }
10
+ const fields = {};
11
+ if (input.slug)
12
+ fields['slug'] = { [input.locale]: input.slug };
13
+ return {
14
+ url: `${base}/api/revalidate`,
15
+ headers,
16
+ body: {
17
+ sys: {
18
+ type: 'Entry',
19
+ id: input.entryId,
20
+ contentType: { sys: { type: 'Link', linkType: 'ContentType', id: input.contentType } },
21
+ },
22
+ fields,
23
+ },
24
+ };
25
+ }
26
+ //# sourceMappingURL=revalidate-request.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"revalidate-request.js","sourceRoot":"","sources":["../../src/publish/revalidate-request.ts"],"names":[],"mappings":"AAeA,MAAM,UAAU,sBAAsB,CAAC,KAQtC;IACC,MAAM,IAAI,GAAG,KAAK,CAAC,iBAAiB,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACxD,MAAM,OAAO,GAA2B;QACtC,cAAc,EAAE,kBAAkB;QAClC,mBAAmB,EAAE,KAAK,CAAC,MAAM;KAClC,CAAC;IACF,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;QACtB,OAAO,CAAC,4BAA4B,CAAC,GAAG,KAAK,CAAC,WAAW,CAAC;IAC5D,CAAC;IACD,MAAM,MAAM,GAA2C,EAAE,CAAC;IAC1D,IAAI,KAAK,CAAC,IAAI;QAAE,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC;IAChE,OAAO;QACL,GAAG,EAAE,GAAG,IAAI,iBAAiB;QAC7B,OAAO;QACP,IAAI,EAAE;YACJ,GAAG,EAAE;gBACH,IAAI,EAAE,OAAO;gBACb,EAAE,EAAE,KAAK,CAAC,OAAO;gBACjB,WAAW,EAAE,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,EAAE,EAAE,KAAK,CAAC,WAAW,EAAE,EAAE;aACvF;YACD,MAAM;SACP;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { RedisClient } from '../session/session-store.js';
2
+ import { type ReleasePlan } from './plan.js';
3
+ export interface PlanStore {
4
+ save(plan: ReleasePlan): Promise<void>;
5
+ load(userId: string, planId: string): Promise<ReleasePlan | null>;
6
+ /** Stamp appliedAt only if this caller wins. False means another apply already claimed it. */
7
+ claim(plan: ReleasePlan): Promise<boolean>;
8
+ }
9
+ export declare function memoryPlanStore(): PlanStore;
10
+ export declare function filePlanStore(root?: string): PlanStore;
11
+ export declare function redisPlanStore(redis: RedisClient): PlanStore;
12
+ export declare function getPlanStore(): PlanStore;
13
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/publish/store.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AAE1D,MAAM,WAAW,SAAS;IACxB,IAAI,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAClE,8FAA8F;IAC9F,KAAK,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC5C;AAQD,wBAAgB,eAAe,IAAI,SAAS,CAgB3C;AAED,wBAAgB,aAAa,CAAC,IAAI,SAAuB,GAAG,SAAS,CA+BpE;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,GAAG,SAAS,CA8B5D;AAED,wBAAgB,YAAY,IAAI,SAAS,CAOxC"}
@@ -0,0 +1,102 @@
1
+ import { mkdir, open, readFile, writeFile } from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { getCmsEditDataRoot } from '../config/data-root.js';
4
+ import { getRuntimeContext } from '../runtime/context.js';
5
+ import { PLAN_TTL_MS } from './plan.js';
6
+ const memoryPlans = new Map();
7
+ function memoryKey(userId, planId) {
8
+ return `${userId}:${planId}`;
9
+ }
10
+ export function memoryPlanStore() {
11
+ return {
12
+ async save(plan) {
13
+ memoryPlans.set(memoryKey(plan.userId, plan.id), plan);
14
+ },
15
+ async load(userId, planId) {
16
+ return memoryPlans.get(memoryKey(userId, planId)) ?? null;
17
+ },
18
+ async claim(plan) {
19
+ const key = memoryKey(plan.userId, plan.id);
20
+ const existing = memoryPlans.get(key);
21
+ if (!existing || existing.appliedAt)
22
+ return false;
23
+ memoryPlans.set(key, plan);
24
+ return true;
25
+ },
26
+ };
27
+ }
28
+ export function filePlanStore(root = getCmsEditDataRoot()) {
29
+ const dir = path.join(root, '.cms-edit', 'plans');
30
+ return {
31
+ async save(plan) {
32
+ await mkdir(dir, { recursive: true });
33
+ const file = path.join(dir, `${plan.userId}-${plan.id}.json`);
34
+ await writeFile(file, JSON.stringify(plan));
35
+ },
36
+ async load(userId, planId) {
37
+ try {
38
+ const raw = await readFile(path.join(dir, `${userId}-${planId}.json`), 'utf8');
39
+ return JSON.parse(raw);
40
+ }
41
+ catch {
42
+ return null;
43
+ }
44
+ },
45
+ async claim(plan) {
46
+ await mkdir(dir, { recursive: true });
47
+ const lock = path.join(dir, `${plan.userId}-${plan.id}.applied`);
48
+ try {
49
+ const handle = await open(lock, 'wx');
50
+ await handle.writeFile(plan.appliedAt ?? 'applied');
51
+ await handle.close();
52
+ }
53
+ catch (err) {
54
+ if (err.code === 'EEXIST')
55
+ return false;
56
+ throw err;
57
+ }
58
+ await writeFile(path.join(dir, `${plan.userId}-${plan.id}.json`), JSON.stringify(plan));
59
+ return true;
60
+ },
61
+ };
62
+ }
63
+ export function redisPlanStore(redis) {
64
+ const keyFor = (userId, planId) => `cms-edit:plan:${userId}:${planId}`;
65
+ return {
66
+ async save(plan) {
67
+ await redis.set(keyFor(plan.userId, plan.id), JSON.stringify(plan), {
68
+ ex: Math.ceil(PLAN_TTL_MS / 1000),
69
+ });
70
+ },
71
+ async load(userId, planId) {
72
+ const raw = await redis.get(keyFor(userId, planId));
73
+ if (raw == null)
74
+ return null;
75
+ if (typeof raw === 'string')
76
+ return JSON.parse(raw);
77
+ return raw;
78
+ },
79
+ async claim(plan) {
80
+ const won = await redis.set(`${keyFor(plan.userId, plan.id)}:applied`, plan.appliedAt ?? 'applied', {
81
+ nx: true,
82
+ ex: Math.ceil(PLAN_TTL_MS / 1000),
83
+ });
84
+ if (won !== true)
85
+ return false;
86
+ await redis.set(keyFor(plan.userId, plan.id), JSON.stringify(plan), {
87
+ ex: Math.ceil(PLAN_TTL_MS / 1000),
88
+ });
89
+ return true;
90
+ },
91
+ };
92
+ }
93
+ export function getPlanStore() {
94
+ const fromContext = getRuntimeContext()?.planStore;
95
+ if (fromContext)
96
+ return fromContext;
97
+ if (process.env['VERCEL'] === '1') {
98
+ throw new Error('Publish plans need Redis on the hosted cms-edit deployment.');
99
+ }
100
+ return filePlanStore();
101
+ }
102
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/publish/store.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,7 @@ import { AsyncLocalStorage } from 'node:async_hooks';
2
2
  import type { CmsEditConfig } from '../config/types.js';
3
3
  import type { IndexCacheStore } from '../index/cache-store.js';
4
4
  import type { MediaPipelineJobStore } from '../media-pipeline/job-store.js';
5
+ import type { PlanStore } from '../publish/store.js';
5
6
  import type { SessionStore } from '../session/session-store.js';
6
7
  import type { StagedUploadStore } from '../staged-upload/store.js';
7
8
  export interface ContentfulUserIdentity {
@@ -17,6 +18,10 @@ export interface CmsEditRuntimeContext {
17
18
  indexCacheStore?: IndexCacheStore;
18
19
  /** Contentful user for session key isolation in hosted mode. */
19
20
  user?: ContentfulUserIdentity;
21
+ /** Publish / unpublish / archive / revalidate plans. Redis on hosted. */
22
+ planStore?: PlanStore;
23
+ /** Site roots beyond the default routable types (project.json publish.extraRootContentTypes). */
24
+ extraRootContentTypes?: string[];
20
25
  /** Staged file uploads for hosted asset upload (Redis). */
21
26
  stagedUploadStore?: StagedUploadStore;
22
27
  /** Media pipeline job ownership + rate limits (Redis on hosted). */
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/runtime/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAC5E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAEnE,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,qBAAqB;IACpC,sEAAsE;IACtE,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,qEAAqE;IACrE,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,2EAA2E;IAC3E,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,gEAAgE;IAChE,IAAI,CAAC,EAAE,sBAAsB,CAAC;IAC9B,2DAA2D;IAC3D,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC,oEAAoE;IACpE,qBAAqB,CAAC,EAAE,qBAAqB,CAAC;IAC9C,sEAAsE;IACtE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wEAAwE;IACxE,iBAAiB,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACzC;AAED,eAAO,MAAM,cAAc,0CAAiD,CAAC;AAE7E,wBAAgB,iBAAiB,IAAI,qBAAqB,GAAG,SAAS,CAErE;AAED,wBAAgB,qBAAqB,CAAC,CAAC,EACrC,OAAO,EAAE,qBAAqB,EAC9B,EAAE,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GACvB,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAEhB"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/runtime/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAC5E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAEnE,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,qBAAqB;IACpC,sEAAsE;IACtE,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,qEAAqE;IACrE,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,2EAA2E;IAC3E,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,gEAAgE;IAChE,IAAI,CAAC,EAAE,sBAAsB,CAAC;IAC9B,yEAAyE;IACzE,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,iGAAiG;IACjG,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC;IACjC,2DAA2D;IAC3D,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC,oEAAoE;IACpE,qBAAqB,CAAC,EAAE,qBAAqB,CAAC;IAC9C,sEAAsE;IACtE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wEAAwE;IACxE,iBAAiB,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACzC;AAED,eAAO,MAAM,cAAc,0CAAiD,CAAC;AAE7E,wBAAgB,iBAAiB,IAAI,qBAAqB,GAAG,SAAS,CAErE;AAED,wBAAgB,qBAAqB,CAAC,CAAC,EACrC,OAAO,EAAE,qBAAqB,EAC9B,EAAE,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GACvB,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAEhB"}
@@ -1 +1 @@
1
- {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/runtime/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AA+BrD,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,iBAAiB,EAAyB,CAAC;AAE7E,MAAM,UAAU,iBAAiB;IAC/B,OAAO,cAAc,CAAC,QAAQ,EAAE,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,OAA8B,EAC9B,EAAwB;IAExB,OAAO,cAAc,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;AACzC,CAAC"}
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/runtime/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAoCrD,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,iBAAiB,EAAyB,CAAC;AAE7E,MAAM,UAAU,iBAAiB;IAC/B,OAAO,cAAc,CAAC,QAAQ,EAAE,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,OAA8B,EAC9B,EAAwB;IAExB,OAAO,cAAc,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;AACzC,CAAC"}
@@ -149,6 +149,7 @@ Each resolved entry is assigned a stable `@ref` label (`@c0` = the root, `@c1`,
149
149
  | `create taxonomy-from-json --file <path>` | Batch-create tagType, articleType, and tag entries from JSON |
150
150
  | `create tag-type --slug <slug> --name "X"` | Create a tagType entry (draft) |
151
151
  | `create article-type --slug <slug> --name "X"` | Create an articleType entry (draft) |
152
+ | `create person-type --slug <slug> --name "X" [--person-template-id <id>] [--indexed true\|false] [--hidden true\|false]` | Create a personType entry (draft). Indexed defaults on, Hidden off. |
152
153
  | `create tag --slug <slug> --name "X" --tag-type <slug>` | Create a tag entry (draft); `--tag-type-slug`, `--tag-type-name`; `--description`, `--featured-image`; cmsLabel auto `"<tagType> — <name>"` |
153
154
  | `create tag-type\|tag\|article-type … --if-not-exists` | Idempotent taxonomy create (returns existing entry when slug matches) |
154
155
  | `add <entry-type> --content-type <ct>` | Create a new child entry of a given content type, link it into the current open entry's content array, and assign it a @ref |
@@ -246,21 +247,23 @@ If a version conflict cannot be resolved cleanly, an error is returned and the e
246
247
 
247
248
  ## 10. Permission Constraints
248
249
 
249
- The tool enforces a hard boundary between editing and publishing:
250
+ `save` still writes drafts only. Publish, unpublish, and archive are separate commands.
250
251
 
251
- **Permitted:**
252
+ **Permitted when the signed-in Contentful role allows it:**
252
253
  - Read entries and assets
253
254
  - Create draft entries
254
255
  - Update draft and published entries (saving as new draft versions)
255
256
  - Delete draft-only entries (never-published)
257
+ - `publish plan` then `publish apply --plan <id>` after the user says yes
258
+ - `unpublish` and `archive` with the same plan-then-yes flow
259
+ - `revalidate plan` then `revalidate apply` to refresh production cache without publishing
256
260
 
257
- **Not permitted (not exposed by the tool):**
258
- - Publish entries
259
- - Unpublish entries
260
- - Archive entries
261
+ **Not permitted:**
261
262
  - Delete published entries
263
+ - Scheduled publish
264
+ - Applying a plan without an explicit yes, or when the Contentful role does not allow that action
262
265
 
263
- This boundary is enforced at two levels: the tool exposes no publish/unpublish/archive/delete commands, and the expected Contentful management token role should not have those permissions either.
266
+ The Contentful role is checked before a plan is saved. If the role policies cannot be read, the command stops. AI Editor (no publish) cannot publish. A role that can publish, unpublish, or archive can do those actions through cms-edit.
264
267
 
265
268
  ---
266
269