@se-studio/contentful-cms 3.3.0 → 3.4.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 (40) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.md +4 -2
  3. package/dist/commands/add.d.ts.map +1 -1
  4. package/dist/commands/add.js +4 -1
  5. package/dist/commands/add.js.map +1 -1
  6. package/dist/commands/batch-assignments.d.ts +4 -4
  7. package/dist/commands/batch-assignments.d.ts.map +1 -1
  8. package/dist/commands/batch-assignments.js +42 -5
  9. package/dist/commands/batch-assignments.js.map +1 -1
  10. package/dist/commands/batch.d.ts.map +1 -1
  11. package/dist/commands/batch.js +36 -17
  12. package/dist/commands/batch.js.map +1 -1
  13. package/dist/commands/open.d.ts.map +1 -1
  14. package/dist/commands/open.js +40 -4
  15. package/dist/commands/open.js.map +1 -1
  16. package/dist/commands/set.d.ts.map +1 -1
  17. package/dist/commands/set.js +148 -27
  18. package/dist/commands/set.js.map +1 -1
  19. package/dist/contentful/set-field-schema.d.ts +5 -0
  20. package/dist/contentful/set-field-schema.d.ts.map +1 -1
  21. package/dist/contentful/set-field-schema.js +30 -1
  22. package/dist/contentful/set-field-schema.js.map +1 -1
  23. package/dist/generated/version.d.ts +1 -1
  24. package/dist/generated/version.js +1 -1
  25. package/dist/mcp/tools/cms-edit.d.ts +1 -1
  26. package/dist/mcp/tools/cms-edit.d.ts.map +1 -1
  27. package/dist/mcp/tools/cms-edit.js +14 -1
  28. package/dist/mcp/tools/cms-edit.js.map +1 -1
  29. package/dist/output/print.d.ts +2 -2
  30. package/dist/output/print.d.ts.map +1 -1
  31. package/dist/output/print.js +3 -3
  32. package/dist/output/print.js.map +1 -1
  33. package/dist/session/dirty.d.ts +20 -0
  34. package/dist/session/dirty.d.ts.map +1 -0
  35. package/dist/session/dirty.js +44 -0
  36. package/dist/session/dirty.js.map +1 -0
  37. package/docs/help/batch.md +29 -13
  38. package/docs/help/index.md +5 -1
  39. package/docs/help/workflow.md +47 -0
  40. package/package.json +1 -1
@@ -22,10 +22,10 @@ export function typeLabel(label) {
22
22
  export function entryLabel(label) {
23
23
  return pc.white(`"${truncate(label, 40)}"`);
24
24
  }
25
- /** Emits an error. In JSON mode: {"ok":false,"error":"..."} to stderr. */
26
- export function errorMsg(msg) {
25
+ /** Emits an error. In JSON mode: {"ok":false,"error":"..."} to stderr. Optional extra fields are merged in JSON mode. */
26
+ export function errorMsg(msg, extra) {
27
27
  if (isJsonMode()) {
28
- console.error(JSON.stringify({ ok: false, error: msg }));
28
+ console.error(JSON.stringify({ ok: false, error: msg, ...extra }));
29
29
  }
30
30
  else {
31
31
  console.error(pc.red(`Error: ${msg}`));
@@ -1 +1 @@
1
- {"version":3,"file":"print.js","sourceRoot":"","sources":["../../src/output/print.ts"],"names":[],"mappings":"AAAA,uFAAuF;AACvF,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,MAAM,UAAU,WAAW,CAAC,MAAmB;IAC7C,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,WAAW;YACd,OAAO,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QACjC,KAAK,OAAO;YACV,OAAO,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC5B,KAAK,SAAS;YACZ,OAAO,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAChC,KAAK,SAAS;YACZ,OAAO,EAAE,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IACnC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,GAAW;IAClC,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,KAAa;IACrC,OAAO,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,OAAO,EAAE,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC;AAC9C,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,QAAQ,CAAC,GAAW;IAClC,IAAI,UAAU,EAAE,EAAE,CAAC;QACjB,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;IAC3D,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,UAAU,GAAG,EAAE,CAAC,CAAC,CAAC;IACzC,CAAC;AACH,CAAC;AAED,+DAA+D;AAC/D,MAAM,UAAU,OAAO,CAAC,GAAW;IACjC,IAAI,UAAU,EAAE,EAAE,CAAC;QACjB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;IAC7C,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,YAAY,GAAG,EAAE,CAAC,CAAC,CAAC;IAC7C,CAAC;AACH,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,IAAI,UAAU,EAAE,EAAE,CAAC;QACjB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;IAC1D,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC,CAAC;IACpC,CAAC;AACH,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,OAAO,CAAC,GAAW;IACjC,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC;QAClB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3B,CAAC;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,GAAW,EAAE,GAAW;IACxC,OAAO,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;AAC9D,CAAC"}
1
+ {"version":3,"file":"print.js","sourceRoot":"","sources":["../../src/output/print.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { SessionState } from './state.js';
2
+ /** True when the session has staged field edits or pending deletions. */
3
+ export declare function isSessionDirty(session: SessionState): boolean;
4
+ export interface DirtyOpenErrorPayload {
5
+ code: 'SESSION_DIRTY';
6
+ unsavedChanges: number;
7
+ pendingDeletions: number;
8
+ rootEntryId: string;
9
+ rootEntryType: string;
10
+ actions: string[];
11
+ }
12
+ export interface DirtyOpenError {
13
+ message: string;
14
+ payload: DirtyOpenErrorPayload;
15
+ }
16
+ /**
17
+ * Agent-facing hard-fail when `open` would replace a session that still has local work.
18
+ */
19
+ export declare function formatDirtyOpenError(session: SessionState): DirtyOpenError;
20
+ //# sourceMappingURL=dirty.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dirty.d.ts","sourceRoot":"","sources":["../../src/session/dirty.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,yEAAyE;AACzE,wBAAgB,cAAc,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAE7D;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,eAAe,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,qBAAqB,CAAC;CAChC;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,YAAY,GAAG,cAAc,CAsC1E"}
@@ -0,0 +1,44 @@
1
+ /** True when the session has staged field edits or pending deletions. */
2
+ export function isSessionDirty(session) {
3
+ return session.modifiedEntryIds.length > 0 || session.pendingDeletions.length > 0;
4
+ }
5
+ /**
6
+ * Agent-facing hard-fail when `open` would replace a session that still has local work.
7
+ */
8
+ export function formatDirtyOpenError(session) {
9
+ const unsavedChanges = session.modifiedEntryIds.length;
10
+ const pendingDeletions = session.pendingDeletions.length;
11
+ const rootEntryId = session.rootEntryId;
12
+ const rootEntryType = session.rootEntryType;
13
+ const actions = [
14
+ 'cms-edit open --resume',
15
+ 'cms-edit diff',
16
+ 'cms-edit save',
17
+ 'cms-edit discard',
18
+ 'cms-edit open --overwrite --id <entryId>',
19
+ ];
20
+ const message = [
21
+ `Cannot open: session has ${unsavedChanges} unsaved entry change(s) and ${pendingDeletions} pending deletion(s).`,
22
+ `Root: ${rootEntryId} (${rootEntryType}) — continue this work, or explicitly abandon it.`,
23
+ '',
24
+ ' Continue current work: cms-edit open --resume',
25
+ ' Review changes: cms-edit diff',
26
+ ' Save drafts: cms-edit save',
27
+ ' Abandon all staged: cms-edit discard',
28
+ ' Abandon and open new: cms-edit open --overwrite --id <entryId>',
29
+ '',
30
+ 'Do not re-run open without --overwrite while changes are staged — that previously wiped session field edits.',
31
+ ].join('\n');
32
+ return {
33
+ message,
34
+ payload: {
35
+ code: 'SESSION_DIRTY',
36
+ unsavedChanges,
37
+ pendingDeletions,
38
+ rootEntryId,
39
+ rootEntryType,
40
+ actions,
41
+ },
42
+ };
43
+ }
44
+ //# sourceMappingURL=dirty.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dirty.js","sourceRoot":"","sources":["../../src/session/dirty.ts"],"names":[],"mappings":"AAEA,yEAAyE;AACzE,MAAM,UAAU,cAAc,CAAC,OAAqB;IAClD,OAAO,OAAO,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,CAAC;AACpF,CAAC;AAgBD;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAqB;IACxD,MAAM,cAAc,GAAG,OAAO,CAAC,gBAAgB,CAAC,MAAM,CAAC;IACvD,MAAM,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC,MAAM,CAAC;IACzD,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;IACxC,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;IAE5C,MAAM,OAAO,GAAG;QACd,wBAAwB;QACxB,eAAe;QACf,eAAe;QACf,kBAAkB;QAClB,0CAA0C;KAC3C,CAAC;IAEF,MAAM,OAAO,GAAG;QACd,4BAA4B,cAAc,gCAAgC,gBAAgB,uBAAuB;QACjH,SAAS,WAAW,KAAK,aAAa,mDAAmD;QACzF,EAAE;QACF,kDAAkD;QAClD,yCAAyC;QACzC,yCAAyC;QACzC,4CAA4C;QAC5C,oEAAoE;QACpE,EAAE;QACF,8GAA8G;KAC/G,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEb,OAAO;QACL,OAAO;QACP,OAAO,EAAE;YACP,IAAI,EAAE,eAAe;YACrB,cAAc;YACd,gBAAgB;YAChB,WAAW;YACX,aAAa;YACb,OAAO;SACR;KACF,CAAC;AACJ,CAAC"}
@@ -1,8 +1,22 @@
1
1
  # Batch edit by entry ID
2
2
 
3
- Edit multiple unrelated Contentful entries without opening a page tree. Useful for link variant sweeps, navigation item tweaks, and other standalone entry updates.
3
+ Edit multiple Contentful entries by ID with scalar field updates. Useful for link variant sweeps, media flags (`autoplay`/`loop`), navigation tweaks, and other standalone updates.
4
4
 
5
- Batch commands use session name **`batch`** by default (override with `--session`). Page sessions from `cms-edit open` are not affected.
5
+ ## Sessions
6
+
7
+ | Context | What happens |
8
+ |---------|----------------|
9
+ | Default CLI (`--session` omitted) | Uses session name **`batch`** (does not touch a separate page session) |
10
+ | Page session already open (e.g. MCP `_mcp`) | `batch set` **stages into that page session** — same `diff` / `save` as article work. Do **not** re-`open`. Do **not** `batch discard` (use `cms-edit discard` only if abandoning everything). |
11
+ | Explicit isolation | `cms-edit --session link-sweep batch set …` |
12
+
13
+ You can also stay on the page session without `batch`:
14
+
15
+ ```bash
16
+ cms-edit set <entryId>:autoplay=true <entryId>:loop=true
17
+ # or
18
+ cms-edit set <entryId> autoplay true
19
+ ```
6
20
 
7
21
  ## Workflow
8
22
 
@@ -16,17 +30,25 @@ cms-edit batch diff
16
30
  # Write all changes as drafts (single save)
17
31
  cms-edit batch save
18
32
 
19
- # Or discard without saving
33
+ # Or discard without saving (pure batch sessions only)
20
34
  cms-edit batch discard
21
35
  ```
22
36
 
37
+ Mid-page (MCP / open article session):
38
+
39
+ ```bash
40
+ cms-edit batch set 5uMh54rIsJRFRQSXDuJiG:autoplay=true
41
+ cms-edit diff
42
+ cms-edit save
43
+ ```
44
+
23
45
  ## Token format
24
46
 
25
47
  ```
26
48
  <entryId>:<fieldId>=<value>
27
49
  ```
28
50
 
29
- - **entryId** — 22-character Contentful entry ID (no `@` prefix)
51
+ - **entryId** — Contentful entry ID (alphanumeric, optional `_`/`-`, length 1–64; **not** fixed at 22 characters)
30
52
  - **fieldId** — field name on that entry's content type
31
53
  - **value** — literal token (no shell quotes needed for simple strings). Coercion follows the field type from Contentful:
32
54
  - **Symbol** / **Text** — always stored as strings (e.g. `order=42` stays `"42"`)
@@ -39,6 +61,7 @@ Examples:
39
61
 
40
62
  ```bash
41
63
  cms-edit batch set abcdefghijklmnopqrstuv:variant=link
64
+ cms-edit batch set 5uMh54rIsJRFRQSXDuJiG:autoplay=true
42
65
  cms-edit batch set abcdefghijklmnopqrstuv:cmsLabel=Footer CTA
43
66
  ```
44
67
 
@@ -60,7 +83,7 @@ When a page is already open, prefer `cms-edit links set @cN <index> variant link
60
83
 
61
84
  Field types and enum validations are loaded from the Contentful Management API. Results are cached:
62
85
 
63
- - In the **batch session file** (`contentTypes` on the session) so `batch set` → `batch save` reuse schema without extra API calls
86
+ - In the **session file** (`contentTypes` on the session) so `batch set` → save reuse schema without extra API calls
64
87
  - On disk at `~/.contentful-cms/content-types/<spaceId>/<environment>/` (24-hour TTL)
65
88
 
66
89
  ## v1 limits
@@ -68,11 +91,4 @@ Field types and enum validations are loaded from the Contentful Management API.
68
91
  - **Scalar fields only** — no rich text, entry links, asset links, or link arrays
69
92
  - **Draft-only** — same as `cms-edit save`; never publishes
70
93
  - **No cross-entry link arrays** — use page session + `cms-edit set --links` for parent arrays
71
- - **Partial save on failure** — if one entry fails during `batch save`, earlier entries may already be saved; the CLI lists failures and reminds you to run `cms-edit batch diff` for remaining changes
72
-
73
- ## Named sessions
74
-
75
- ```bash
76
- cms-edit --session link-sweep batch set idOne123456789012345678:variant=link
77
- cms-edit --session link-sweep batch save
78
- ```
94
+ - **Partial save on failure** — if one entry fails during `batch save`, earlier entries may already be saved; the CLI lists failures and reminds you to run diff for remaining changes
@@ -84,6 +84,10 @@ cms-edit batch run --json '[...]'
84
84
  | Command | Description |
85
85
  |---|---|
86
86
  | `open --page-slug <slug>` | Load a page into the session (see `help lookup`) |
87
+ | `open --resume` | Re-print active session; **keeps** staged edits (no refetch) |
88
+ | `open --overwrite …` | Replace session even if dirty (discards staged field edits) |
89
+ | `set <ref\|id> <field> <value>` | Set field; bare entry IDs allowed mid-session |
90
+ | `set <id>:field=value …` | Scalar multi-set by entry ID (stays on current session) |
87
91
  | `open --id <id>` | Load by Contentful entry ID |
88
92
  | `peek --page-slug <slug>` | Print content tree + root field values without creating a session |
89
93
  | `peek --id <id>` | Same by Contentful entry ID |
@@ -137,7 +141,7 @@ cms-edit batch run --json '[...]'
137
141
  ### Batch Operations
138
142
  | Command | Description |
139
143
  |---|---|
140
- | `batch set <entryId>:field=value …` | Queue scalar updates on multiple entries by ID |
144
+ | `batch set <entryId>:field=value …` | Queue scalar updates by ID (page session OK mid-edit; then `save`) |
141
145
  | `batch diff` / `batch save` / `batch discard` | Review and commit batch session |
142
146
  | `batch run --json <json> or --json-base64 <encoded>` | Execute a JSON batch of operations |
143
147
 
@@ -26,6 +26,25 @@ cms-edit open --id 4xKpzQ2abc123
26
26
 
27
27
  `open` fetches the full entry tree and saves it to a local session file. All subsequent commands operate on this session without re-fetching from Contentful until you `save`.
28
28
 
29
+ ### Critical: do not re-open while edits are staged
30
+
31
+ `set` / `rtf` / parent links from `add` stay in the session until `save`. Calling `open` again **replaces** the session.
32
+
33
+ | Situation | Command |
34
+ |-----------|---------|
35
+ | Session has unsaved changes, need tree again | `cms-edit open --resume` (no refetch; keeps staged edits) |
36
+ | Intentionally abandon staged work and load another entry | `cms-edit open --overwrite --id <id>` (or `discard` then `open`) |
37
+ | Plain `open` while dirty | **Hard fail** with remediation steps |
38
+
39
+ ```bash
40
+ cms-edit open --resume
41
+ cms-edit diff
42
+ cms-edit save
43
+ # or abandon:
44
+ cms-edit discard
45
+ cms-edit open --id <other>
46
+ ```
47
+
29
48
  **Output:**
30
49
  ```
31
50
  ✓ Opened /solutions/hepatology (12 entries)
@@ -72,6 +91,34 @@ cms-edit set @c2 heading "New Heading"
72
91
  cms-edit set @c2 backgroundColour "Navy"
73
92
  ```
74
93
 
94
+ ### Mid-session by Contentful entry ID (e.g. media autoplay)
95
+
96
+ You do **not** need to leave the page session:
97
+
98
+ ```bash
99
+ # Bare entry ID (fetched into the session if not in the tree)
100
+ cms-edit set 5uMh54rIsJRFRQSXDuJiG autoplay true
101
+
102
+ # Same shape as batch set — stays on the current page session
103
+ cms-edit set 5uMh54rIsJRFRQSXDuJiG:autoplay=true 5uMh54rIsJRFRQSXDuJiG:loop=true
104
+ # or: cms-edit batch set … (also allowed mid-page; then cms-edit save)
105
+ ```
106
+
107
+ ### Entry links: `--link` vs `--links` (strict)
108
+
109
+ | Field shape | Flag | Notes |
110
+ |-------------|------|--------|
111
+ | Single Entry link | `--link` | Exactly one id |
112
+ | Array of Entry links | `--links` | Full replace of the array |
113
+ | Append to array | `--links --append` | Add ids |
114
+ | Wrong flag | hard error | Never silently coerces |
115
+
116
+ ```bash
117
+ cms-edit set @c1 visual <mediaEntryId> --link
118
+ cms-edit set @c2 contents <id1>,<id2> --links
119
+ # To change one array item: read the array, edit the list, write all ids back with --links
120
+ ```
121
+
75
122
  ### Rich text fields
76
123
  ```bash
77
124
  # Inline markdown (short content)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@se-studio/contentful-cms",
3
- "version": "3.3.0",
3
+ "version": "3.4.0",
4
4
  "description": "CLI tool for AI agents to read and edit Contentful draft content without publish permissions",
5
5
  "repository": {
6
6
  "type": "git",