@contentful/experience-design-system-cli 2.34.5-dev-build-75bf00ac.0 → 2.35.0-alpha.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 CHANGED
@@ -32,11 +32,18 @@ All intermediate data flows through a local SQLite session database (`~/.content
32
32
 
33
33
  A **composite component** is one that renders other components inside it — a `Card` that slots a `Button` and an `Icon`, a `Tabs` that slots `Tab` panels. When you import composite components, the CLI can populate each slot's `$allowedComponents` so the parent→child relationships survive into Contentful.
34
34
 
35
- All imports use composite mode: embedded-component relationships are resolved and preserved in the generated CDF.
35
+ ### Atomic vs. composite
36
+
37
+ Imports are **atomic by default** — flat components, no embedded hierarchy. This is the right choice when you just want each component registered on its own. Opt into hierarchy resolution with `--composite` (or any composition flag, which implies it).
38
+
39
+ | Mode | Flag | Behavior |
40
+ |---|---|---|
41
+ | Atomic | default | Flat import; composition stripped before push |
42
+ | Composite | `--composite` | Resolve and import the parent→child hierarchy |
36
43
 
37
44
  ### How composition is resolved
38
45
 
39
- Relationships are resolved from the highest-confidence source available, in this precedence order:
46
+ Under `--composite`, relationships are resolved from the highest-confidence source available, in this precedence order:
40
47
 
41
48
  1. **Typed slots (code)** — slots the source already declares, e.g. React `ReactElement<XProps>` / `children`, Svelte `Snippet<[XProps]>`, or an explicit `@allowedComponents` JSDoc tag. Fully deterministic; picked up automatically.
42
49
  2. **Agent** — direct edge emission for codebases that encode composition in *code patterns* rather than typed slots (common in real-world design systems). It is enabled automatically in composite mode and only runs when the deterministic sources above find nothing.
@@ -79,7 +86,7 @@ The CLI invokes the agent non-interactively in a subprocess. If the binary is no
79
86
 
80
87
  ### Contentful credentials
81
88
 
82
- `apply` and `import` (when pushing) require access to a Contentful space. Configure these environment variables or run `experiences setup`:
89
+ `apply` and `import` (when pushing) require access to a Contentful space. Set these environment variables or pass the equivalent flags:
83
90
 
84
91
  ```bash
85
92
  export CONTENTFUL_MANAGEMENT_TOKEN=<your-cma-token> # required
@@ -106,8 +113,8 @@ experiences import [flags]
106
113
  ```
107
114
  welcome
108
115
  ↓
109
- extracting — runs analyze extract with composite relationships enabled;
110
- spawns internal generation in parallel (prefetch)
116
+ extracting — runs analyze extract (atomic by default; resolves composition
117
+ under --composite, see below); spawns internal generation in parallel (prefetch)
111
118
  ↓
112
119
  [auto-filter] — analyze select-agent runs automatically
113
120
  ↓
@@ -147,7 +154,8 @@ Custom `.md` skill prompt paths can be saved via `experiences setup`; the CLI em
147
154
  | `--project <path>` | `.` | Project root to analyze |
148
155
  | `--agent <name>` | saved by setup / `claude` | Agent for `analyze select-agent` and internal generation |
149
156
  | `--model <name>` | agent default | Model name |
150
- | `--composition-map <path>` | — | Consume a hand-authored parent→children interchange map |
157
+ | `--composite` | — | Import the embedded-component hierarchy (any composition flag implies this) |
158
+ | `--composition-map <path>` | — | Consume a hand-authored parent→children interchange map (implies `--composite`) |
151
159
  | `--prompt <stage=value>` | — | Override a stage prompt (repeatable); value is a file path or literal text, e.g. `--prompt composition=./p.md` |
152
160
  | `--skip-map-tokens` | — | Skip the `map tokens` step between internal generation and apply |
153
161
  | `--no-cache` | cache on | Bypass extract/select/internal-generation/map-tokens/composition caches and force re-run |
@@ -180,15 +188,15 @@ experiences print validate [--components <path>] [--tokens <path>]
180
188
 
181
189
  ### `apply`
182
190
 
183
- This command is the non-wizard route to the same diff and push logic. It accepts one CDF file containing all component and design token definitions.
191
+ This command is the non-wizard route to the same diff and push logic. Its flag surface is unchanged.
184
192
 
185
193
  `apply` emits a Contentful webapp view URL for the imported components in its JSON summary (`viewUrl`) so callers can deep-link into the management UI after a successful push.
186
194
 
187
195
  ```bash
188
- experiences apply <file>
196
+ experiences apply
189
197
  ```
190
198
 
191
- `apply` is interactive and loads credentials from `experiences setup` or environment variables. Remote ComponentTypes and DesignTokens missing from the pushed manifest are always skipped.
199
+ Shared flags: `--components`, `--tokens`. `apply` is interactive and loads credentials from `experiences setup` or environment variables. Remote ComponentTypes and DesignTokens missing from the pushed manifest are always skipped.
192
200
 
193
201
  Design tokens are written first (component types may reference token kinds). Each entity write is recorded in the session database atomically — interrupted pushes resume from where they left off.
194
202
 
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentful/experience-design-system-cli",
3
- "version": "2.34.5-dev-build-75bf00ac.0",
3
+ "version": "2.35.0-alpha.0",
4
4
  "description": "Contentful Experiences design system import CLI",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1,3 +1,4 @@
1
+ import { type CompositionMode } from './lib/composition-mode.js';
1
2
  export type ExperiencesCredentials = {
2
3
  spaceId: string;
3
4
  environmentId: string;
@@ -11,6 +12,12 @@ export type ExperiencesCredentials = {
11
12
  debug?: boolean;
12
13
  /** Persisted opt-out for anonymous CLI usage analytics, set via `experiences setup`. */
13
14
  analyticsDisabled?: boolean;
15
+ /**
16
+ * Feature (atomic mode): default composition mode. `atomic` (default) imports
17
+ * flat components with no embedded-component hierarchy; `composite` opts into
18
+ * the slot-graph machinery. Resolved `flag > env > this > default`.
19
+ */
20
+ compositionMode?: CompositionMode;
14
21
  };
15
22
  /**
16
23
  * Read persisted Contentful credentials.
@@ -0,0 +1,18 @@
1
+ import type { CDFComponentEntry } from '@contentful/experience-design-system-types';
2
+ /**
3
+ * Atomic-mode normalization (spec T8, option a): keep every slot's structure
4
+ * but drop its `$allowedComponents` composition constraint. Applied over the
5
+ * loaded component array regardless of source (`--session` or `--components`),
6
+ * so the atomic bypass cannot leak a live composition link into the pushed
7
+ * CDF document. Starving `$allowedComponents` at this single point also makes
8
+ * slot-cycle detection structurally return zero (see T12).
9
+ *
10
+ * Returns a new array with cloned entries; inputs are not mutated.
11
+ */
12
+ export declare function stripAllowedComponents(components: Array<{
13
+ key: string;
14
+ entry: CDFComponentEntry;
15
+ }>): Array<{
16
+ key: string;
17
+ entry: CDFComponentEntry;
18
+ }>;
@@ -1,4 +1,5 @@
1
1
  import React from 'react';
2
+ import type { CompositionMode } from '../../lib/composition-mode.js';
2
3
  export declare function buildGenerateComponentsArgs(opts: {
3
4
  sessionId: string;
4
5
  tokensPath?: string;
@@ -10,13 +11,6 @@ export declare function buildGenerateComponentsArgs(opts: {
10
11
  promptOverrides?: string[];
11
12
  existingEntitiesPath?: string;
12
13
  }): string[];
13
- export declare function buildGenerateTokensArgs(opts: {
14
- rawTokensPath: string;
15
- agent: string;
16
- model?: string;
17
- bedrock?: boolean;
18
- noCache?: boolean;
19
- }): string[];
20
14
  export declare function buildMapTokensArgs(opts: {
21
15
  sessionId: string;
22
16
  agent: string;
@@ -44,6 +38,7 @@ export type WizardAppProps = {
44
38
  bedrock?: boolean;
45
39
  initialProjectPath?: string;
46
40
  host?: string;
41
+ compositionMode?: CompositionMode;
47
42
  compositionMap?: string;
48
43
  promptOverrides?: string[];
49
44
  noCache?: boolean;
@@ -52,4 +47,4 @@ export type WizardAppProps = {
52
47
  skipMapTokens?: boolean;
53
48
  initialRawTokensPath?: string;
54
49
  };
55
- export declare function WizardApp({ initialSpaceId, initialEnvironmentId, initialCmaToken, initialHost, initialAgent, initialModel, bedrock, initialProjectPath, host, compositionMap, promptOverrides, noCache, livePreview, generatePromptPath, skipMapTokens, initialRawTokensPath, }?: WizardAppProps): React.ReactElement;
50
+ export declare function WizardApp({ initialSpaceId, initialEnvironmentId, initialCmaToken, initialHost, initialAgent, initialModel, bedrock, initialProjectPath, host, compositionMode, compositionMap, promptOverrides, noCache, livePreview, generatePromptPath, skipMapTokens, initialRawTokensPath, }?: WizardAppProps): React.ReactElement;
@@ -1,6 +1,8 @@
1
1
  import React from 'react';
2
+ import type { CompositionMode } from '../../lib/composition-mode.js';
2
3
  import type { ReviewStepProps } from './review-step-props.js';
3
4
  export type FinalReviewHostProps = Omit<ReviewStepProps, 'extractSessionId'> & {
4
5
  extractSessionId: string | null;
6
+ compositionMode?: CompositionMode;
5
7
  };
6
- export declare function FinalReviewHost({ extractSessionId, tokenSessionId, onFinalize, onQuit, livePreview, spaceId, environmentId, cmaToken, host, tokensPath, initialFinalizeError, }: FinalReviewHostProps): React.ReactElement;
8
+ export declare function FinalReviewHost({ extractSessionId, tokenSessionId, compositionMode, onFinalize, onQuit, livePreview, spaceId, environmentId, cmaToken, host, tokensPath, initialFinalizeError, }: FinalReviewHostProps): React.ReactElement;
@@ -5,8 +5,8 @@ type LineageInputKey = {
5
5
  tab: boolean;
6
6
  return: boolean;
7
7
  };
8
- export declare function handleLineageNavigation({ key, cursor, jumpables, onCursorChange, onJump, onClose, allowTab, }: {
9
- input?: string;
8
+ export declare function handleLineageNavigation({ input, key, cursor, jumpables, onCursorChange, onJump, onClose, allowTab, }: {
9
+ input: string;
10
10
  key: LineageInputKey;
11
11
  cursor: number;
12
12
  jumpables: LineageJumpable[];
@@ -1,8 +1,10 @@
1
1
  import React from 'react';
2
2
  import type { ScopeComponent } from './steps/ScopeGateStep.js';
3
+ import type { CompositionMode } from '../../lib/composition-mode.js';
3
4
  export type { ScopeComponent };
4
5
  export type ScopeGateHostProps = {
5
6
  components: ReadonlyArray<ScopeComponent>;
7
+ compositionMode?: CompositionMode;
6
8
  onConfirm: (decisions: {
7
9
  accepted: string[];
8
10
  rejected: string[];
@@ -16,4 +18,4 @@ export type ScopeGateHostProps = {
16
18
  } | null;
17
19
  aiFilterError?: string | null;
18
20
  };
19
- export declare function ScopeGateHost({ components, onConfirm, onQuit }: ScopeGateHostProps): React.ReactElement;
21
+ export declare function ScopeGateHost({ components, compositionMode, onConfirm, onQuit, }: ScopeGateHostProps): React.ReactElement;
@@ -0,0 +1,28 @@
1
+ import React from 'react';
2
+ type GenerateReviewStepProps = {
3
+ extractSessionId: string;
4
+ tokenSessionId?: string | null;
5
+ onFinalize: (accepted: number, rejected: number, unresolved: number) => void;
6
+ onQuit: () => void;
7
+ /**
8
+ * Feature 2 (live preview after every save). When `true` (default), the
9
+ * wizard re-runs `previewImport` after each successful FieldEditor Ctrl+S
10
+ * (debounced 500ms) and refreshes the sidebar's previewAnnotation badges.
11
+ * Live preview is enabled for the wizard flow.
12
+ */
13
+ livePreview?: boolean;
14
+ spaceId?: string;
15
+ environmentId?: string;
16
+ cmaToken?: string;
17
+ host?: string;
18
+ tokensPath?: string;
19
+ /**
20
+ * INTEG-4411 refined: initial value for the inline `finalizeError` banner.
21
+ * The wizard sets this when it routes back to `final-review` after the
22
+ * preview API returned an empty diff (pure no-op push). Cleared on the
23
+ * next `a` / `A` keystroke.
24
+ */
25
+ initialFinalizeError?: string | null;
26
+ };
27
+ export declare function AtomicGenerateReviewStep({ extractSessionId, tokenSessionId, onFinalize, onQuit, livePreview, spaceId, environmentId, cmaToken, host, tokensPath, initialFinalizeError, }: GenerateReviewStepProps): React.ReactElement;
28
+ export {};
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ import type { ScopeGateStepProps } from './ScopeGateStep.js';
3
+ export declare function AtomicScopeGateStep({ components, onConfirm, onQuit }: ScopeGateStepProps): React.ReactElement;