@contentful/experience-design-system-cli 2.32.1-dev-build-0e6dd6e.0 → 2.32.1-dev-build-00d288d.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/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentful/experience-design-system-cli",
3
- "version": "2.32.1-dev-build-0e6dd6e.0",
3
+ "version": "2.32.1-dev-build-00d288d.0",
4
4
  "description": "Contentful Experiences design system import CLI",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -43,6 +43,7 @@
43
43
  "@segment/analytics-node": "^3.0.0",
44
44
  "@vue/compiler-sfc": "^3.5.31",
45
45
  "commander": "^13.1.0",
46
+ "contentful-management": "^12.17.0",
46
47
  "ink": "^4.4.1",
47
48
  "react": "^18.3.1",
48
49
  "react-devtools-core": "^4.19.1",
@@ -0,0 +1,17 @@
1
+ import { type PlainClientAPI } from 'contentful-management';
2
+ interface CreateCmaClientOptions {
3
+ cmaToken: string;
4
+ /**
5
+ * Optional CMA host override. Accepts either a full URL
6
+ * (`https://api.contentful.com`) or a bare hostname (`api.contentful.com`);
7
+ * contentful-management wants the bare form so we normalize here.
8
+ */
9
+ host?: string;
10
+ }
11
+ /**
12
+ * Build a plain contentful-management client. Single place that picks the
13
+ * `{ type: 'plain' }` overload so callers never have to think about it,
14
+ * and normalizes host into the bare-hostname shape the SDK expects.
15
+ */
16
+ export declare function createCmaClient(opts: CreateCmaClientOptions): PlainClientAPI;
17
+ export {};
@@ -0,0 +1,16 @@
1
+ import { type ComponentProps, type DesignTokenProps, type PlainClientAPI } from 'contentful-management';
2
+ export interface ExistingEntities {
3
+ components: ComponentProps[];
4
+ tokens: DesignTokenProps[];
5
+ }
6
+ interface FetchExistingEntitiesParams {
7
+ spaceId: string;
8
+ environmentId: string;
9
+ }
10
+ /**
11
+ * Fetch all existing Components + DesignTokens for a space+env. Pagination
12
+ * is delegated to the SDK's `fetchAll()` helper. Caller supplies the
13
+ * pre-built plain client (see `createCmaClient()`).
14
+ */
15
+ export declare function fetchExistingEntities(client: PlainClientAPI, params: FetchExistingEntitiesParams): Promise<ExistingEntities>;
16
+ export {};
@@ -28,6 +28,7 @@ export interface PipelineOptions {
28
28
  /** When true, auto-reject cycle participants and retry push instead of surfacing an error. */
29
29
  autoRejectCycles?: boolean;
30
30
  allowDeletions?: boolean;
31
+ withSpaceContext?: boolean;
31
32
  compositionMode?: CompositionMode;
32
33
  compositionMap?: string;
33
34
  compositionAgent?: boolean;
package/dist/src/index.js CHANGED
@@ -16647,7 +16647,7 @@ var init_save_path_resolver = __esm({
16647
16647
  });
16648
16648
 
16649
16649
  // packages/experience-design-system-cli/src/runs/store.ts
16650
- import { readFile as readFile22, writeFile as writeFile5, mkdir as mkdir6, rename } from "node:fs/promises";
16650
+ import { readFile as readFile22, writeFile as writeFile6, mkdir as mkdir6, rename } from "node:fs/promises";
16651
16651
  import { join as join20 } from "node:path";
16652
16652
  import { homedir as homedir7 } from "node:os";
16653
16653
  import { randomBytes as randomBytes2 } from "node:crypto";
@@ -16710,7 +16710,7 @@ async function writeAtomic(file) {
16710
16710
  await mkdir6(RUNS_DIR, { recursive: true });
16711
16711
  const body = JSON.stringify(file, null, 2) + "\n";
16712
16712
  const tmp = `${RUNS_PATH}.${process.pid}.${Date.now()}.tmp`;
16713
- await writeFile5(tmp, body, { mode: 384 });
16713
+ await writeFile6(tmp, body, { mode: 384 });
16714
16714
  await rename(tmp, RUNS_PATH);
16715
16715
  }
16716
16716
  async function appendRun(input) {
@@ -34416,14 +34416,38 @@ init_db();
34416
34416
  init_command();
34417
34417
  init_manifest();
34418
34418
  init_api_client();
34419
+ import { mkdir as mkdir5, writeFile as writeFile5 } from "node:fs/promises";
34420
+ import { join as join18, resolve as resolve21 } from "node:path";
34421
+ import { execFile as execFile2 } from "node:child_process";
34422
+
34423
+ // packages/experience-design-system-cli/src/helpers/fetch-existing-entities.ts
34424
+ import { fetchAll } from "contentful-management";
34425
+ async function fetchExistingEntities(client2, params) {
34426
+ const scope = { spaceId: params.spaceId, environmentId: params.environmentId, query: {} };
34427
+ const components = await fetchAll(client2.component.getMany, scope);
34428
+ const tokens = await fetchAll(client2.designToken.getMany, scope);
34429
+ return { components, tokens };
34430
+ }
34431
+
34432
+ // packages/experience-design-system-cli/src/helpers/cma-client.ts
34433
+ init_host_utils();
34434
+ import { createClient as createClient2 } from "contentful-management";
34435
+ function createCmaClient(opts) {
34436
+ return createClient2(
34437
+ {
34438
+ accessToken: opts.cmaToken,
34439
+ ...opts.host ? { host: toConfiguredHost(opts.host) } : {}
34440
+ },
34441
+ { type: "plain" }
34442
+ );
34443
+ }
34444
+
34445
+ // packages/experience-design-system-cli/src/import/orchestrator.ts
34419
34446
  init_contentful_urls();
34420
34447
  init_debug_logger();
34421
34448
  init_analytics();
34422
34449
  init_env();
34423
34450
  init_cli_path();
34424
- import { mkdir as mkdir5 } from "node:fs/promises";
34425
- import { join as join18, resolve as resolve21 } from "node:path";
34426
- import { execFile as execFile2 } from "node:child_process";
34427
34451
  async function runStep(args, cliPath, analyticsSessionId, env = {}, streamStderr = false) {
34428
34452
  const debug = getDebugLogger();
34429
34453
  const startedAt = Date.now();
@@ -34531,11 +34555,70 @@ async function runPipeline(opts, progressWriter, cliPathOverride) {
34531
34555
  await mkdir5(outDir, { recursive: true });
34532
34556
  const steps = [];
34533
34557
  let stepNum = 0;
34534
- const totalSteps = 5 + (opts.print ? 1 : 0);
34558
+ const wantsSpaceContext = opts.withSpaceContext === true;
34559
+ const canFetchSpaceContext = wantsSpaceContext && !!opts.spaceId && !!opts.environmentId && !!opts.cmaToken;
34560
+ const totalSteps = 5 + (opts.print ? 1 : 0) + (canFetchSpaceContext ? 1 : 0);
34535
34561
  function stepLabel(name) {
34536
34562
  stepNum++;
34537
34563
  return ` Step ${stepNum}/${totalSteps} ${name} `;
34538
34564
  }
34565
+ if (wantsSpaceContext && !canFetchSpaceContext) {
34566
+ progressWriter(
34567
+ " Note: --with-space-context requires --space-id, --environment-id, and --cma-token; skipping context fetch."
34568
+ );
34569
+ }
34570
+ if (canFetchSpaceContext) {
34571
+ const fetchLabel = stepLabel("Fetching existing components + design tokens");
34572
+ const fetchStepId = createStep(db, sessionId2, "fetch existing entities", {
34573
+ spaceId: opts.spaceId,
34574
+ environmentId: opts.environmentId
34575
+ });
34576
+ const t0 = Date.now();
34577
+ try {
34578
+ const cmaClient = createCmaClient({
34579
+ cmaToken: opts.cmaToken,
34580
+ ...opts.host ? { host: opts.host } : {}
34581
+ });
34582
+ const existingComponentsAndTokens = await fetchExistingEntities(cmaClient, {
34583
+ spaceId: opts.spaceId,
34584
+ environmentId: opts.environmentId
34585
+ });
34586
+ const fetchDurationMs = Date.now() - t0;
34587
+ const existingEntitiesPath = join18(outDir, ".existing-entities.json");
34588
+ await writeFile5(existingEntitiesPath, JSON.stringify(existingComponentsAndTokens, null, 2), "utf8");
34589
+ updateStep(db, fetchStepId, "complete", {
34590
+ components: String(existingComponentsAndTokens.components.length),
34591
+ tokens: String(existingComponentsAndTokens.tokens.length),
34592
+ path: existingEntitiesPath
34593
+ });
34594
+ progressWriter(
34595
+ `${fetchLabel}\u2713 ${existingComponentsAndTokens.components.length} component${existingComponentsAndTokens.components.length === 1 ? "" : "s"}, ${existingComponentsAndTokens.tokens.length} token${existingComponentsAndTokens.tokens.length === 1 ? "" : "s"} (${(fetchDurationMs / 1e3).toFixed(1)}s)`
34596
+ );
34597
+ steps.push({
34598
+ step: "fetch existing entities",
34599
+ status: "complete",
34600
+ durationMs: fetchDurationMs,
34601
+ detail: {
34602
+ components: existingComponentsAndTokens.components.length,
34603
+ tokens: existingComponentsAndTokens.tokens.length
34604
+ }
34605
+ });
34606
+ } catch (error) {
34607
+ const fetchDurationMs = Date.now() - t0;
34608
+ const message = error instanceof Error ? error.message : String(error);
34609
+ updateStep(db, fetchStepId, "complete", {}, message);
34610
+ progressWriter(
34611
+ `${fetchLabel}\u26A0 fetch failed, continuing without space context (${(fetchDurationMs / 1e3).toFixed(1)}s)`
34612
+ );
34613
+ progressWriter(` ${message.split("\n")[0]}`);
34614
+ steps.push({
34615
+ step: "fetch existing entities",
34616
+ status: "skipped",
34617
+ durationMs: fetchDurationMs,
34618
+ reason: `fetch failed: ${message.split("\n")[0]}`
34619
+ });
34620
+ }
34621
+ }
34539
34622
  const analyzeLabel = stepLabel("Statically analyzing project");
34540
34623
  const analyzeSkipped = !opts.noCache && opts.skipAnalyze;
34541
34624
  let extractSessionId = null;
@@ -35490,7 +35573,10 @@ function registerImportCommand(program) {
35490
35573
  "Override a stage prompt (repeatable). value is a file path or literal text, e.g. --prompt composition=./p.md",
35491
35574
  (v, acc) => [...acc, v],
35492
35575
  []
35493
- ).option("--auto-reject-cycles", "Automatically reject components involved in slot cycles and retry").option("--auto-filter", "Force the AI auto-filter ON (overrides the credentials.json autoFilter preference)").option(
35576
+ ).option("--auto-reject-cycles", "Automatically reject components involved in slot cycles and retry").option(
35577
+ "--with-space-context",
35578
+ "Fetch existing Components + DesignTokens from the target space+env and persist them under <out>/.existing-entities.json for future agent-context enrichment. Requires --space-id, --environment-id, and --cma-token."
35579
+ ).option("--auto-filter", "Force the AI auto-filter ON (overrides the credentials.json autoFilter preference)").option(
35494
35580
  "--no-auto-filter",
35495
35581
  "Skip the automatic AI pre-filter; jump straight to manual scope-gate (overrides the credentials.json autoFilter preference; no-op when paired with --auto-accept-scope)"
35496
35582
  ).option(
@@ -35837,6 +35923,7 @@ function registerImportCommand(program) {
35837
35923
  dryRun: dryRunForward,
35838
35924
  selectPromptPath: opts.selectPromptPath,
35839
35925
  autoRejectCycles: opts.autoRejectCycles ?? false,
35926
+ withSpaceContext: opts.withSpaceContext ?? false,
35840
35927
  allowDeletions: opts.allowDeletions ?? false,
35841
35928
  compositionMode: headlessCompositionMode,
35842
35929
  ...opts.compositionMap ? { compositionMap: opts.compositionMap } : {},
@@ -5,7 +5,7 @@ import type { ToolCall, TokenToolCall, ComponentSourceRef } from '@contentful/ex
5
5
  import type { ComponentTypeSummary } from '@contentful/experience-design-system-types';
6
6
  import type { SlotCycle, SlotEdge } from '../analyze/cycle-detection.js';
7
7
  export type StepStatus = 'pending' | 'complete' | 'failed' | 'interrupted';
8
- export type CommandName = 'analyze extract' | 'analyze select' | 'generate components' | 'generate tokens' | 'generate edit' | 'apply preview' | 'apply select' | 'apply push' | 'print components' | 'print tokens' | 'map tokens' | 'import';
8
+ export type CommandName = 'analyze extract' | 'analyze select' | 'generate components' | 'generate tokens' | 'generate edit' | 'apply preview' | 'apply select' | 'apply push' | 'print components' | 'print tokens' | 'map tokens' | 'fetch existing entities' | 'import';
9
9
  export interface SessionRow {
10
10
  id: string;
11
11
  name: string | null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentful/experience-design-system-cli",
3
- "version": "2.32.1-dev-build-0e6dd6e.0",
3
+ "version": "2.32.1-dev-build-00d288d.0",
4
4
  "description": "Contentful Experiences design system import CLI",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -32,6 +32,7 @@
32
32
  "@segment/analytics-node": "^3.0.0",
33
33
  "@vue/compiler-sfc": "^3.5.31",
34
34
  "commander": "^13.1.0",
35
+ "contentful-management": "^12.17.0",
35
36
  "ink": "^4.4.1",
36
37
  "react": "^18.3.1",
37
38
  "react-devtools-core": "^4.19.1",
@@ -39,8 +40,8 @@
39
40
  "svelte": "^5.56.4",
40
41
  "ts-morph": "^27.0.2",
41
42
  "typescript": "^5.9.3",
42
- "@contentful/experience-design-system-cli-v2": "2.32.1-dev-build-0e6dd6e.0",
43
- "@contentful/experience-design-system-types": "2.32.1-dev-build-0e6dd6e.0"
43
+ "@contentful/experience-design-system-types": "2.32.1-dev-build-00d288d.0",
44
+ "@contentful/experience-design-system-cli-v2": "2.32.1-dev-build-00d288d.0"
44
45
  },
45
46
  "devDependencies": {
46
47
  "@tsconfig/node24": "^24.0.4",
@@ -52,9 +53,9 @@
52
53
  "ink-testing-library": "^4.0.0",
53
54
  "typescript-eslint": "^8.67.0",
54
55
  "vitest": "^4.0.16",
55
- "@contentful/experience-design-system-client": "2.32.1-dev-build-0e6dd6e.0",
56
- "@contentful/experience-design-system-extraction": "2.32.1-dev-build-0e6dd6e.0",
57
- "@contentful/experience-design-system-generation": "2.32.1-dev-build-0e6dd6e.0"
56
+ "@contentful/experience-design-system-client": "2.32.1-dev-build-00d288d.0",
57
+ "@contentful/experience-design-system-extraction": "2.32.1-dev-build-00d288d.0",
58
+ "@contentful/experience-design-system-generation": "2.32.1-dev-build-00d288d.0"
58
59
  },
59
60
  "repository": {
60
61
  "type": "git",