@contentful/experience-design-system-cli 2.26.1-dev-build-a852362.0 → 2.26.1-dev-build-f03f014.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 (204) hide show
  1. package/dist/package.json +14 -10
  2. package/dist/src/index.js +34937 -9
  3. package/dist/src/lib/cli-path.d.ts +4 -0
  4. package/dist/src/runs/export-helpers.d.ts +1 -12
  5. package/dist/src/runs/push-helpers.d.ts +1 -6
  6. package/package.json +12 -7
  7. package/skills/generate-components.md +427 -0
  8. package/skills/generate-tokens.md +194 -0
  9. package/skills/select-components.md +224 -0
  10. package/dist/src/analytics/apply.js +0 -30
  11. package/dist/src/analytics/client.js +0 -81
  12. package/dist/src/analytics/constants.js +0 -4
  13. package/dist/src/analytics/env.js +0 -14
  14. package/dist/src/analytics/exit.js +0 -24
  15. package/dist/src/analytics/index.js +0 -9
  16. package/dist/src/analytics/normalize.js +0 -18
  17. package/dist/src/analytics/os.js +0 -13
  18. package/dist/src/analytics/session.js +0 -15
  19. package/dist/src/analytics/tracker.js +0 -126
  20. package/dist/src/analytics/types.js +0 -1
  21. package/dist/src/analyze/build-analyze-view-rows.js +0 -63
  22. package/dist/src/analyze/command.js +0 -599
  23. package/dist/src/analyze/composite-closure.js +0 -0
  24. package/dist/src/analyze/composition/agent-parser/author-prompt.js +0 -22
  25. package/dist/src/analyze/composition/agent-parser/extract-parser.js +0 -44
  26. package/dist/src/analyze/composition/agent-parser/load-prompt.js +0 -31
  27. package/dist/src/analyze/composition/agent-parser/resolve-via-parser.js +0 -88
  28. package/dist/src/analyze/composition/agent-parser/sandbox.js +0 -187
  29. package/dist/src/analyze/composition/apply-mapping.js +0 -67
  30. package/dist/src/analyze/composition/candidate-critic-agent.js +0 -39
  31. package/dist/src/analyze/composition/candidate-critic.js +0 -63
  32. package/dist/src/analyze/composition/candidate-files.js +0 -131
  33. package/dist/src/analyze/composition/composition-cache-key.js +0 -19
  34. package/dist/src/analyze/composition/interchange-schema.js +0 -61
  35. package/dist/src/analyze/composition/manifest-doc-evidence.js +0 -136
  36. package/dist/src/analyze/composition/merge-edges.js +0 -70
  37. package/dist/src/analyze/composition/parse-map-edges.js +0 -55
  38. package/dist/src/analyze/composition/resolve-mapping-cli.js +0 -29
  39. package/dist/src/analyze/composition/resolve-mapping.js +0 -111
  40. package/dist/src/analyze/cycle-detection.js +0 -234
  41. package/dist/src/analyze/cycle-view.js +0 -28
  42. package/dist/src/analyze/fuzzy-search.js +0 -55
  43. package/dist/src/analyze/issue-inheritance.js +0 -108
  44. package/dist/src/analyze/lineage.js +0 -0
  45. package/dist/src/analyze/scope-gate-cascade.js +0 -170
  46. package/dist/src/analyze/search-neighborhood.js +0 -56
  47. package/dist/src/analyze/select/command.js +0 -484
  48. package/dist/src/analyze/select/index.js +0 -5
  49. package/dist/src/analyze/select/parser.js +0 -53
  50. package/dist/src/analyze/select/persistence.js +0 -80
  51. package/dist/src/analyze/select/preview-annotations.js +0 -62
  52. package/dist/src/analyze/select/stdout.js +0 -3
  53. package/dist/src/analyze/select/tui/App.js +0 -483
  54. package/dist/src/analyze/select/tui/components/ComponentDetail.js +0 -48
  55. package/dist/src/analyze/select/tui/components/ComponentRationalePanel.js +0 -125
  56. package/dist/src/analyze/select/tui/components/FieldEditor.js +0 -1131
  57. package/dist/src/analyze/select/tui/components/FinalizeDialog.js +0 -36
  58. package/dist/src/analyze/select/tui/components/GotoBanner.js +0 -30
  59. package/dist/src/analyze/select/tui/components/GroupedSidebar.js +0 -517
  60. package/dist/src/analyze/select/tui/components/HelpOverlay.js +0 -17
  61. package/dist/src/analyze/select/tui/components/JsonEditor.js +0 -131
  62. package/dist/src/analyze/select/tui/components/JsonPanel.js +0 -66
  63. package/dist/src/analyze/select/tui/components/LineagePanel.js +0 -22
  64. package/dist/src/analyze/select/tui/components/PreviewSummaryBar.js +0 -29
  65. package/dist/src/analyze/select/tui/components/QuitDialog.js +0 -14
  66. package/dist/src/analyze/select/tui/components/RationalePanel.js +0 -80
  67. package/dist/src/analyze/select/tui/components/Sidebar.js +0 -92
  68. package/dist/src/analyze/select/tui/components/SourcePanel.js +0 -52
  69. package/dist/src/analyze/select/tui/components/StatusBar.js +0 -7
  70. package/dist/src/analyze/select/tui/components/TopBar.js +0 -10
  71. package/dist/src/analyze/select/tui/components/removed-components-text.js +0 -11
  72. package/dist/src/analyze/select/tui/hooks/scroll-offset.js +0 -26
  73. package/dist/src/analyze/select/tui/hooks/useImmediateInput.js +0 -66
  74. package/dist/src/analyze/select/tui/hooks/useKeymap.js +0 -67
  75. package/dist/src/analyze/select/tui/hooks/useSession.js +0 -52
  76. package/dist/src/analyze/select/tui/hooks/useUndo.js +0 -26
  77. package/dist/src/analyze/select/tui/theme.js +0 -28
  78. package/dist/src/analyze/select/types.js +0 -39
  79. package/dist/src/analyze/select-agent/command.js +0 -558
  80. package/dist/src/analyze/select-agent/context-builder.js +0 -197
  81. package/dist/src/analyze/select-agent/show-rationale.js +0 -92
  82. package/dist/src/analyze/selection-cascade.js +0 -19
  83. package/dist/src/analyze/slot-graph.js +0 -17
  84. package/dist/src/analyze/tui/AnalyzeView.js +0 -64
  85. package/dist/src/apply/api-client.js +0 -440
  86. package/dist/src/apply/command.js +0 -845
  87. package/dist/src/apply/manifest.js +0 -1
  88. package/dist/src/apply/preview-utils.js +0 -26
  89. package/dist/src/apply/tui/SelectView.js +0 -34
  90. package/dist/src/apply/tui/ServerApplyView.js +0 -49
  91. package/dist/src/apply/tui/ServerPreviewView.js +0 -23
  92. package/dist/src/credentials-store.js +0 -74
  93. package/dist/src/generate/command.js +0 -597
  94. package/dist/src/generate/edit/command.js +0 -127
  95. package/dist/src/generate/tui/GenerateView.js +0 -10
  96. package/dist/src/host-utils.js +0 -26
  97. package/dist/src/import/agent-model-resolve.js +0 -35
  98. package/dist/src/import/auto-filter-resolve.js +0 -16
  99. package/dist/src/import/command.js +0 -380
  100. package/dist/src/import/cycle-auto-reject.js +0 -14
  101. package/dist/src/import/orchestrator.js +0 -603
  102. package/dist/src/import/path-utils.js +0 -30
  103. package/dist/src/import/picker-dispatch.js +0 -44
  104. package/dist/src/import/print-prompt.js +0 -31
  105. package/dist/src/import/strip-allowed-components.js +0 -22
  106. package/dist/src/import/tui/CustomPromptBanner.js +0 -8
  107. package/dist/src/import/tui/WizardApp.js +0 -1670
  108. package/dist/src/import/tui/ai-flag.js +0 -6
  109. package/dist/src/import/tui/auto-filter-error.js +0 -29
  110. package/dist/src/import/tui/autocomplete.js +0 -32
  111. package/dist/src/import/tui/components/AutoFilterBanner.js +0 -19
  112. package/dist/src/import/tui/components/CounterStrip.js +0 -12
  113. package/dist/src/import/tui/components/LegendEntry.js +0 -6
  114. package/dist/src/import/tui/cycle-panel-scroll.js +0 -33
  115. package/dist/src/import/tui/final-review-host.js +0 -25
  116. package/dist/src/import/tui/group-collapse.js +0 -11
  117. package/dist/src/import/tui/history.js +0 -53
  118. package/dist/src/import/tui/hooks/useLineage.js +0 -50
  119. package/dist/src/import/tui/hooks/useOverlayPanel.js +0 -27
  120. package/dist/src/import/tui/lineage-layout.js +0 -82
  121. package/dist/src/import/tui/merge-ai-decisions.js +0 -22
  122. package/dist/src/import/tui/push-decision-gate-helpers.js +0 -8
  123. package/dist/src/import/tui/push-progress.js +0 -1
  124. package/dist/src/import/tui/run-print-files-helpers.js +0 -8
  125. package/dist/src/import/tui/run-teaser.js +0 -9
  126. package/dist/src/import/tui/runLivePreview.js +0 -82
  127. package/dist/src/import/tui/runScopeGate.js +0 -28
  128. package/dist/src/import/tui/scope-gate-columns.js +0 -94
  129. package/dist/src/import/tui/scope-gate-host.js +0 -28
  130. package/dist/src/import/tui/sidebar-width.js +0 -3
  131. package/dist/src/import/tui/spawn-generate.js +0 -53
  132. package/dist/src/import/tui/step-filters.js +0 -42
  133. package/dist/src/import/tui/steps/AtomicGenerateReviewStep.js +0 -726
  134. package/dist/src/import/tui/steps/AtomicScopeGateStep.js +0 -210
  135. package/dist/src/import/tui/steps/CredentialsStep.js +0 -108
  136. package/dist/src/import/tui/steps/DoneStep.js +0 -24
  137. package/dist/src/import/tui/steps/ErrorStep.js +0 -16
  138. package/dist/src/import/tui/steps/GateStep.js +0 -22
  139. package/dist/src/import/tui/steps/GenerateReviewStep.js +0 -1618
  140. package/dist/src/import/tui/steps/PathValidationStep.js +0 -152
  141. package/dist/src/import/tui/steps/PreviewStep.js +0 -37
  142. package/dist/src/import/tui/steps/PreviewValidationErrorStep.js +0 -23
  143. package/dist/src/import/tui/steps/PushDecisionGateStep.js +0 -73
  144. package/dist/src/import/tui/steps/PushingStep.js +0 -24
  145. package/dist/src/import/tui/steps/RunningStep.js +0 -21
  146. package/dist/src/import/tui/steps/ScopeGateStep.js +0 -907
  147. package/dist/src/import/tui/steps/TokenInputStep.js +0 -88
  148. package/dist/src/import/tui/steps/WelcomeStep.js +0 -34
  149. package/dist/src/import/tui/steps/WizardPreviewStep.js +0 -169
  150. package/dist/src/import/tui/steps/auto-reject-decision.js +0 -9
  151. package/dist/src/import/tui/steps/breaking-change-format.js +0 -24
  152. package/dist/src/import/tui/steps/enumerate-cycle-breaks.js +0 -0
  153. package/dist/src/import/tui/steps/preview-diff.js +0 -175
  154. package/dist/src/import/tui/useFinalizePreview.js +0 -0
  155. package/dist/src/import/tui/useLivePreview.js +0 -122
  156. package/dist/src/import/tui/wizard-422-helpers.js +0 -60
  157. package/dist/src/import/tui/wizard-generate-progress.js +0 -25
  158. package/dist/src/import/tui/wizard-save-flow.js +0 -20
  159. package/dist/src/import/tui/wizard-state-transitions.js +0 -32
  160. package/dist/src/lib/agent-model-options.js +0 -15
  161. package/dist/src/lib/command-options.js +0 -30
  162. package/dist/src/lib/composition-mode.js +0 -39
  163. package/dist/src/lib/contentful-urls.js +0 -27
  164. package/dist/src/lib/debug-logger.js +0 -229
  165. package/dist/src/lib/debug-preamble.js +0 -33
  166. package/dist/src/lib/error-parser.js +0 -269
  167. package/dist/src/lib/prompt-overrides.js +0 -69
  168. package/dist/src/lib/terminal-capabilities.js +0 -51
  169. package/dist/src/lib/user-agent.js +0 -29
  170. package/dist/src/output/format.js +0 -110
  171. package/dist/src/print/command.js +0 -221
  172. package/dist/src/print/validate/tui/ValidateView.js +0 -37
  173. package/dist/src/print/validate/validators/cdf-validator.js +0 -104
  174. package/dist/src/print/validate/validators/dtcg-validator.js +0 -110
  175. package/dist/src/print/validate/validators/format-errors.js +0 -18
  176. package/dist/src/program.js +0 -105
  177. package/dist/src/runs/export-helpers.js +0 -59
  178. package/dist/src/runs/fingerprint.js +0 -75
  179. package/dist/src/runs/ls-command.js +0 -137
  180. package/dist/src/runs/modify-launcher.js +0 -42
  181. package/dist/src/runs/path-prompt.js +0 -72
  182. package/dist/src/runs/push-creds-prompt.js +0 -39
  183. package/dist/src/runs/push-helpers.js +0 -72
  184. package/dist/src/runs/push-launcher.js +0 -77
  185. package/dist/src/runs/replay-helpers.js +0 -164
  186. package/dist/src/runs/resolve-run-target.js +0 -45
  187. package/dist/src/runs/run-picker-mount.js +0 -72
  188. package/dist/src/runs/run-picker.js +0 -129
  189. package/dist/src/runs/save-conflict.js +0 -56
  190. package/dist/src/runs/save-path-resolver.js +0 -75
  191. package/dist/src/runs/staleness.js +0 -140
  192. package/dist/src/runs/store.js +0 -136
  193. package/dist/src/session/cache-keys.js +0 -44
  194. package/dist/src/session/command.js +0 -261
  195. package/dist/src/session/db.js +0 -1538
  196. package/dist/src/session/migration.js +0 -117
  197. package/dist/src/session/session-id.js +0 -212
  198. package/dist/src/session/stats.js +0 -89
  199. package/dist/src/setup/analytics-prompt.js +0 -24
  200. package/dist/src/setup/auto-filter-prompt.js +0 -24
  201. package/dist/src/setup/command.js +0 -966
  202. package/dist/src/setup/composition-mode-prompt.js +0 -37
  203. package/dist/src/setup/debug-mode-prompt.js +0 -22
  204. package/dist/src/types.js +0 -1
@@ -1,60 +0,0 @@
1
- import { parsePreviewValidationErrors } from '../../apply/api-client.js';
2
- import { patchReviewStateWithValidationErrors, rejectComponentsByName } from '../../analyze/select/command.js';
3
- /**
4
- * Decide what to do with an `ApiError` raised by `previewImport()`.
5
- * Returns `not-422` if the caller should fall through to its other branches
6
- * (404 / 401 / 403 / generic), `unparseable` if the body cannot be parsed
7
- * into structured component-level errors (caller should route to the generic
8
- * error step), or `validation-error` with the patched-state side effects
9
- * already applied.
10
- *
11
- * Pure decision logic + a single delegated side effect to
12
- * `patchReviewStateWithValidationErrors`. Extracted from `WizardApp.runPreview`
13
- * so the routing is unit-testable without driving the full TUI.
14
- */
15
- export async function handlePreview422(err, extractSessionId, patchFn = patchReviewStateWithValidationErrors) {
16
- if (err.status !== 422)
17
- return { kind: 'not-422' };
18
- const errors = parsePreviewValidationErrors(err.body);
19
- if (errors.length === 0)
20
- return { kind: 'unparseable', message: err.message };
21
- let missingNames = [];
22
- if (extractSessionId) {
23
- const result = await patchFn(extractSessionId, errors);
24
- missingNames = result.missingNames;
25
- }
26
- return { kind: 'validation-error', errors, missingNames };
27
- }
28
- /**
29
- * The WizardState patch the wizard should spread into any update that
30
- * transitions OUT of the preview-validation-error step (e.g. into
31
- * preview-gate after a successful retry). Without this, the validation-error
32
- * arrays linger in state and any future code path that reads them sees stale
33
- * data from a prior failed attempt.
34
- */
35
- export function clearedValidationErrorState() {
36
- return {
37
- previewValidationErrors: [],
38
- previewValidationMissingNames: [],
39
- };
40
- }
41
- /**
42
- * Run the "skip and retry" side effect: dedup the offending component
43
- * names from a list of errors and call `rejectComponentsByName`. Returns
44
- * the deduped names so the caller can log them or include them in test
45
- * assertions. No-op when sessionId is null or errors are empty.
46
- *
47
- * The DB update inside `rejectComponentsByName` is what makes the next
48
- * preview see a manifest with the offenders excluded — see SP-3 retro
49
- * Bug 1: writing to the JSON state file alone is not enough because
50
- * `loadCDFComponents` reads from the pipeline DB.
51
- */
52
- export async function applySkipValidationErrors(sessionId, errors, rejectFn = rejectComponentsByName) {
53
- if (!sessionId)
54
- return [];
55
- const names = [...new Set(errors.map((e) => e.componentName))];
56
- if (names.length === 0)
57
- return [];
58
- await rejectFn(sessionId, names);
59
- return names;
60
- }
@@ -1,25 +0,0 @@
1
- const PROGRESS_LINE = /^progress=generate:(\d+)\/(\d+):(.+)$/;
2
- const LEGACY_LINE = /\[(\d+)\/(\d+)\]\s+(.+)/;
3
- export function parseGenerateStderrChunk(chunk, prev) {
4
- let state = prev;
5
- for (const line of chunk.split('\n')) {
6
- const progressMatch = PROGRESS_LINE.exec(line);
7
- if (progressMatch) {
8
- state = {
9
- done: Number(progressMatch[1]),
10
- total: Number(progressMatch[2]),
11
- current: progressMatch[3].trim(),
12
- };
13
- continue;
14
- }
15
- const legacyMatch = LEGACY_LINE.exec(line);
16
- if (legacyMatch) {
17
- state = {
18
- done: state?.done ?? 0,
19
- total: Number(legacyMatch[2]),
20
- current: legacyMatch[3].trim(),
21
- };
22
- }
23
- }
24
- return state;
25
- }
@@ -1,20 +0,0 @@
1
- import { appendRun } from '../../runs/store.js';
2
- import { resolveSavePath } from '../../runs/save-path-resolver.js';
3
- export async function planSaveFlow(input) {
4
- if (input.outDirOverride) {
5
- if (input.onConflict) {
6
- const resolved = await resolveSavePath(input.outDirOverride, { onConflict: input.onConflict });
7
- if (resolved.kind === 'write')
8
- return { kind: 'write', path: resolved.path };
9
- if (resolved.kind === 'fail')
10
- return { kind: 'fail', conflict: resolved.conflict };
11
- // `no-conflict` / `conflict` never come back when onConflict is set.
12
- return { kind: 'write', path: input.outDirOverride };
13
- }
14
- return { kind: 'write', path: input.outDirOverride };
15
- }
16
- return { kind: 'prompt', defaultPath: input.defaultPath };
17
- }
18
- export async function recordRunAfterSave(input) {
19
- return appendRun(input);
20
- }
@@ -1,32 +0,0 @@
1
- export function nextStepAfterScopeGate(opts) {
2
- if (opts.acceptedCount > 0) {
3
- return opts.noPush ? 'generating' : 'credentials';
4
- }
5
- return opts.noPush ? 'print-gate' : 'credentials';
6
- }
7
- export function nextStepAfterCredentialsValidated(opts) {
8
- return opts.acceptedCount > 0 ? 'generating' : 'push-decision-gate';
9
- }
10
- export function shouldSkipFinalReviewAfterCredentials(state) {
11
- return state.finalReviewPassed && state.generateSessionId != null;
12
- }
13
- export function resolveNoCacheForGenerate(opts) {
14
- return opts.cliNoCache;
15
- }
16
- export function shouldBypassPreview(state) {
17
- return state.credentialsSkipped === true;
18
- }
19
- export function buildSkippedPreviewTransition() {
20
- return { step: 'push-decision-gate', serverPreview: null };
21
- }
22
- export function resolveCycleGateAction(opts) {
23
- if (!opts.hasCycles)
24
- return 'proceed';
25
- return opts.autoRejectCycles ? 'auto-reject' : 'block';
26
- }
27
- export function shouldRefusePush(state) {
28
- return state.credentialsSkipped === true;
29
- }
30
- export function buildSkippedPushTransition() {
31
- return { step: 'print-gate' };
32
- }
@@ -1,15 +0,0 @@
1
- import { AGENT_NAMES } from '@contentful/experience-design-system-generation';
2
- export const AGENT_DESCRIPTION = `Agent to use: ${AGENT_NAMES.join(', ')} (defaults to value saved by experiences setup)`;
3
- export const MODEL_DESCRIPTION = 'Model to use (defaults to a lightweight per-agent model; override with EDS_AGENT_MODEL_<AGENT>)';
4
- /**
5
- * Register --agent and optionally --model flags to a Commander command, with customizable descriptions.
6
- * Pass `includeModel: false` for commands where the model dimension is not applicable (e.g., mapping-resolution agents that select an agent for logic, not model choice).
7
- */
8
- export function addAgentModelOptions(cmd, config = {}) {
9
- const { agentDescription = AGENT_DESCRIPTION, includeModel = true, modelDescription = MODEL_DESCRIPTION } = config;
10
- cmd.option('--agent <name>', agentDescription);
11
- if (includeModel) {
12
- cmd.option('--model <name>', modelDescription);
13
- }
14
- return cmd;
15
- }
@@ -1,30 +0,0 @@
1
- export function addArtifactInputOptions(cmd) {
2
- return cmd
3
- .option('--components <path>', 'Path to components.json (CDF)')
4
- .option('--tokens <path>', 'Path to tokens.json (DTCG)')
5
- .option('--session <id>', 'Pipeline session ID to load generated components from');
6
- }
7
- export function addContentfulTargetOptions(cmd) {
8
- return cmd
9
- .requiredOption('--space-id <id>', 'Contentful space ID')
10
- .requiredOption('--environment-id <id>', 'Contentful environment ID')
11
- .option('--cma-token <token>', 'CMA personal access token (or set CONTENTFUL_MANAGEMENT_TOKEN)')
12
- .option('--host <url>', 'Override API base URL');
13
- }
14
- export function addCompositionOptions(cmd) {
15
- return cmd
16
- .option('--composite', 'Import embedded-component hierarchy (opt in; default is atomic)')
17
- .option('--atomic', 'Import flat components with no embedded-component hierarchy (default)');
18
- }
19
- function collectOptionValue(value, previous) {
20
- return [...previous, value];
21
- }
22
- export function addSelectionOptions(cmd) {
23
- return cmd
24
- .option('--select-all', 'Select all entities without launching TUI')
25
- .option('--select <pattern>', 'Select entities by ID pattern (repeatable)', collectOptionValue, [])
26
- .option('--deselect <pattern>', 'Deselect entities by ID pattern (repeatable)', collectOptionValue, []);
27
- }
28
- export function addAllowDeletionsOption(cmd) {
29
- return cmd.option('--allow-deletions', 'Allow the push to delete remote ComponentTypes/DesignTokens missing from the manifest (default: skip them)');
30
- }
@@ -1,39 +0,0 @@
1
- export const COMPOSITION_MODES = ['composite', 'atomic'];
2
- export function isCompositionMode(value) {
3
- return COMPOSITION_MODES.includes(value);
4
- }
5
- function hasCompositionSource(opts) {
6
- return !!opts.compositionMap || !!opts.compositionAgent || !!opts.compositionRefresh || !!opts.generateMap;
7
- }
8
- /**
9
- * Resolve the effective composition mode with precedence
10
- * `explicit flag > implied source > env > persisted config > default`.
11
- * Default is `atomic` (composition OFF); `--composite` opts into the hierarchy
12
- * machinery.
13
- *
14
- * `--atomic` is accepted for symmetry and wins when passed — even alongside a
15
- * composition source, since it's an explicit "no" that overrides the implicit
16
- * opt-in. If both `--composite` and `--atomic` are present, `--composite`
17
- * wins. Passing a composition source (`--composition-map/-agent`,
18
- * `--composition-refresh`, or `--generate-map`) implies composite without a
19
- * separate `--composite`.
20
- */
21
- export function resolveCompositionMode(opts, configMode) {
22
- if (opts.composite)
23
- return 'composite';
24
- if (opts.atomic)
25
- return 'atomic';
26
- // A composition source is an explicit opt-in for this invocation — it beats
27
- // env/config, but not an explicit --atomic (handled above).
28
- if (hasCompositionSource(opts))
29
- return 'composite';
30
- const env = process.env['EXPERIENCES_COMPOSITION_MODE'];
31
- if (env !== undefined && env !== '') {
32
- const v = env.toLowerCase();
33
- if (isCompositionMode(v))
34
- return v;
35
- }
36
- if (configMode && isCompositionMode(configMode))
37
- return configMode;
38
- return 'atomic';
39
- }
@@ -1,27 +0,0 @@
1
- /**
2
- * Shared Contentful webapp URL builders.
3
- *
4
- * The wizard's `done` step and the `experiences import` orchestrator both used
5
- * to inline the same post-push URL formatter. This module centralizes that
6
- * formatter so the wizard, `apply push`, and `apply select` all emit the same
7
- * URL shape.
8
- */
9
- function normalizeHost(host) {
10
- return host
11
- .trim()
12
- .replace(/^https?:\/\//i, '')
13
- .replace(/\/+$/, '');
14
- }
15
- /**
16
- * Map a Contentful API host to the corresponding webapp host. For api.*.com
17
- * inputs this swaps the `api.` prefix to `app.`; any other host is returned
18
- * as-is (callers get the raw host, no guessing).
19
- */
20
- export function apiHostToAppHost(host) {
21
- const normalized = normalizeHost(host);
22
- return normalized.replace(/^api\./, 'app.');
23
- }
24
- export function buildPostPushUrl({ host, spaceId, environmentId, view = 'components' }) {
25
- const appHost = apiHostToAppHost(host);
26
- return `https://${appHost}/spaces/${spaceId}/environments/${environmentId}/views/${view}`;
27
- }
@@ -1,229 +0,0 @@
1
- import { mkdirSync, appendFileSync } from 'node:fs';
2
- import { join, dirname } from 'node:path';
3
- import { homedir } from 'node:os';
4
- // ── Redaction ────────────────────────────────────────────────────────────────
5
- // Blocklist of secret-shaped keys; matched case-insensitively.
6
- const SECRET_KEY_PATTERNS = [
7
- /token/i,
8
- /secret/i,
9
- /password/i,
10
- /authorization/i,
11
- /^auth$/i,
12
- /apikey/i,
13
- /api_key/i,
14
- /credential/i,
15
- /bearer/i,
16
- /^cma$/i,
17
- /cmaToken/i,
18
- ];
19
- // Value-side patterns for strings that look like tokens even under innocuous keys.
20
- const SECRET_VALUE_PATTERNS = [
21
- /^Bearer\s+\S+/i,
22
- /CFPAT-[A-Za-z0-9_-]{20,}/,
23
- /sk-[A-Za-z0-9_-]{20,}/,
24
- /xox[baprs]-[A-Za-z0-9-]{10,}/,
25
- ];
26
- const REDACTED = '«redacted»';
27
- const MAX_STRING_LEN = 4000;
28
- function redactValue(value, seen) {
29
- if (value === null || value === undefined)
30
- return value;
31
- if (typeof value === 'string') {
32
- if (SECRET_VALUE_PATTERNS.some((r) => r.test(value)))
33
- return REDACTED;
34
- return value.length > MAX_STRING_LEN
35
- ? value.slice(0, MAX_STRING_LEN) + `…«+${value.length - MAX_STRING_LEN}»`
36
- : value;
37
- }
38
- if (typeof value !== 'object')
39
- return value;
40
- if (seen.has(value))
41
- return '«cycle»';
42
- seen.add(value);
43
- if (Array.isArray(value))
44
- return value.map((v) => redactValue(v, seen));
45
- const out = {};
46
- for (const [k, v] of Object.entries(value)) {
47
- if (SECRET_KEY_PATTERNS.some((r) => r.test(k))) {
48
- out[k] = REDACTED;
49
- }
50
- else {
51
- out[k] = redactValue(v, seen);
52
- }
53
- }
54
- return out;
55
- }
56
- export function redactForDebug(payload) {
57
- return redactValue(payload, new WeakSet());
58
- }
59
- // ── Path resolution ──────────────────────────────────────────────────────────
60
- const DEBUG_ROOT_ENV = 'EDSI_DEBUG_ROOT';
61
- const DEBUG_LOG_ENV = 'EDSI_DEBUG_LOG';
62
- function defaultDebugRoot() {
63
- return process.env[DEBUG_ROOT_ENV] ?? join(homedir(), '.contentful', 'experience-design-system-cli', 'debug');
64
- }
65
- // Session timestamp source. Deterministic-friendly: honors EDSI_DEBUG_TS for tests.
66
- function makeSessionTimestamp() {
67
- const override = process.env['EDSI_DEBUG_TS'];
68
- if (override)
69
- return override;
70
- const now = new Date();
71
- const pad = (n, w = 2) => n.toString().padStart(w, '0');
72
- return (`${now.getUTCFullYear()}${pad(now.getUTCMonth() + 1)}${pad(now.getUTCDate())}` +
73
- `T${pad(now.getUTCHours())}${pad(now.getUTCMinutes())}${pad(now.getUTCSeconds())}Z`);
74
- }
75
- // ── Singleton ───────────────────────────────────────────────────────────────
76
- let singleton = null;
77
- class NoopDebugLogger {
78
- enabled = false;
79
- path = null;
80
- event() {
81
- /* no-op */
82
- }
83
- }
84
- class FileDebugLogger {
85
- enabled = true;
86
- path;
87
- sessionStart;
88
- constructor(path) {
89
- this.path = path;
90
- this.sessionStart = Date.now();
91
- mkdirSync(dirname(path), { recursive: true });
92
- // Header event — records the process context.
93
- this.write({
94
- ts: new Date().toISOString(),
95
- category: 'config',
96
- name: 'session.open',
97
- pid: process.pid,
98
- ppid: process.ppid,
99
- cwd: process.cwd(),
100
- argv: process.argv.slice(1),
101
- node: process.version,
102
- platform: process.platform,
103
- });
104
- }
105
- event(category, name, payload = {}) {
106
- const redacted = redactForDebug(payload);
107
- this.write({
108
- ts: new Date().toISOString(),
109
- elapsedMs: Date.now() - this.sessionStart,
110
- category,
111
- name,
112
- pid: process.pid,
113
- ...redacted,
114
- });
115
- }
116
- write(record) {
117
- try {
118
- appendFileSync(this.path, JSON.stringify(record) + '\n', { encoding: 'utf8' });
119
- }
120
- catch {
121
- // Debug logging must never crash the CLI. Swallow.
122
- }
123
- }
124
- }
125
- /**
126
- * Initialize the process-wide debug logger. Safe to call multiple times —
127
- * subsequent calls return the existing instance.
128
- *
129
- * If EDSI_DEBUG_LOG is already set in the environment, this process joins
130
- * that log file (used by spawned subprocesses so a whole `experiences import`
131
- * flow lands in a single file).
132
- */
133
- export function initDebugLogger(opts) {
134
- if (singleton)
135
- return singleton;
136
- // Inherited from parent process — always join the existing file, regardless
137
- // of the local flag/env decision. Parent already made the choice.
138
- const inherited = process.env[DEBUG_LOG_ENV];
139
- if (inherited) {
140
- singleton = new FileDebugLogger(inherited);
141
- if (opts.command)
142
- singleton.event('config', 'subprocess.start', { command: opts.command });
143
- return singleton;
144
- }
145
- if (!opts.enabled) {
146
- singleton = new NoopDebugLogger();
147
- return singleton;
148
- }
149
- const root = opts.root ?? defaultDebugRoot();
150
- const ts = makeSessionTimestamp();
151
- const suffix = opts.command ? `-${opts.command}` : '';
152
- const path = join(root, `${ts}${suffix}.jsonl`);
153
- singleton = new FileDebugLogger(path);
154
- process.env[DEBUG_LOG_ENV] = path; // propagate to spawned children
155
- if (opts.command)
156
- singleton.event('config', 'command.start', { command: opts.command });
157
- // Emit a close event on process exit. Best-effort — writeFileSync-based, so
158
- // it works from within an 'exit' handler.
159
- process.on('exit', (code) => {
160
- if (singleton && singleton.enabled) {
161
- singleton.event('config', 'session.close', { exitCode: code });
162
- }
163
- });
164
- return singleton;
165
- }
166
- export function getDebugLogger() {
167
- return singleton ?? new NoopDebugLogger();
168
- }
169
- /** Test-only: reset the singleton. */
170
- export function __resetDebugLoggerForTest() {
171
- singleton = null;
172
- delete process.env[DEBUG_LOG_ENV];
173
- }
174
- // ── Resolver ────────────────────────────────────────────────────────────────
175
- /**
176
- * Resolve effective debug-mode setting from three sources.
177
- *
178
- * Precedence (highest first):
179
- * 1. `--debug` / `--no-debug` CLI flag
180
- * 2. `EDSI_DEBUG` env var (truthy: 1, true, yes, on)
181
- * 3. Persisted `debug` field in credentials.json
182
- * 4. Default: OFF
183
- */
184
- export function resolveDebugMode(opts, configDebug) {
185
- if (opts.debug !== undefined)
186
- return opts.debug;
187
- const env = process.env['EDSI_DEBUG'];
188
- if (env !== undefined && env !== '') {
189
- const v = env.toLowerCase();
190
- if (v === '1' || v === 'true' || v === 'yes' || v === 'on')
191
- return true;
192
- if (v === '0' || v === 'false' || v === 'no' || v === 'off')
193
- return false;
194
- }
195
- if (configDebug !== undefined)
196
- return configDebug;
197
- return false;
198
- }
199
- // ── Bright-green banner ─────────────────────────────────────────────────────
200
- /**
201
- * Emit the bright-green "debug logs at <path>" banner to stderr.
202
- * No-op when debug is disabled or stderr is not a TTY-friendly stream.
203
- * Callers should invoke this once at start and once at end of the command.
204
- */
205
- export function printDebugBanner(logger, phase) {
206
- if (!logger.enabled || !logger.path)
207
- return;
208
- const prefix = phase === 'start' ? '\x1b[92m[debug]\x1b[0m ' : '\x1b[92m[debug]\x1b[0m ';
209
- const label = phase === 'start' ? 'debug logs at' : 'debug logs written to';
210
- // Bright green (92) + bold (1); reset with 0.
211
- const line = `${prefix}\x1b[1m\x1b[92m${label} ${logger.path}\x1b[0m\n`;
212
- try {
213
- process.stderr.write(line);
214
- }
215
- catch {
216
- /* ignore */
217
- }
218
- }
219
- /** Directory that contains the current process's debug log, if any. */
220
- export function debugLogPath() {
221
- return singleton?.path ?? process.env[DEBUG_LOG_ENV] ?? null;
222
- }
223
- /** Ensure spawned children join the same debug log by including EDSI_DEBUG_LOG in their env. */
224
- export function debugEnvForSubprocess(env = process.env) {
225
- const path = debugLogPath();
226
- if (!path)
227
- return env;
228
- return { ...env, [DEBUG_LOG_ENV]: path };
229
- }
@@ -1,33 +0,0 @@
1
- import { initDebugLogger, printDebugBanner, resolveDebugMode } from './debug-logger.js';
2
- import { readExperiencesCredentials } from '../credentials-store.js';
3
- let endBannerRegistered = false;
4
- /**
5
- * Preamble every top-level command action should call before doing work.
6
- *
7
- * Resolves the effective debug decision (flag > env > persisted config),
8
- * initializes the singleton, and prints the bright-green start banner.
9
- * Registers a process-exit handler that prints the end banner once.
10
- *
11
- * Returns the logger so the caller can emit events without a second import.
12
- * When debug is disabled, the returned logger is a no-op.
13
- */
14
- export async function beginCommand(command, opts) {
15
- let configDebug;
16
- try {
17
- const creds = await readExperiencesCredentials();
18
- configDebug = creds.debug;
19
- }
20
- catch {
21
- // Missing credentials.json is fine — the resolver falls through to default OFF.
22
- }
23
- const enabled = resolveDebugMode(opts, configDebug);
24
- const logger = initDebugLogger({ enabled, command });
25
- if (logger.enabled) {
26
- printDebugBanner(logger, 'start');
27
- if (!endBannerRegistered) {
28
- endBannerRegistered = true;
29
- process.on('exit', () => printDebugBanner(logger, 'end'));
30
- }
31
- }
32
- return logger;
33
- }