@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.
- package/dist/package.json +14 -10
- package/dist/src/index.js +34937 -9
- package/dist/src/lib/cli-path.d.ts +4 -0
- package/dist/src/runs/export-helpers.d.ts +1 -12
- package/dist/src/runs/push-helpers.d.ts +1 -6
- package/package.json +12 -7
- package/skills/generate-components.md +427 -0
- package/skills/generate-tokens.md +194 -0
- package/skills/select-components.md +224 -0
- package/dist/src/analytics/apply.js +0 -30
- package/dist/src/analytics/client.js +0 -81
- package/dist/src/analytics/constants.js +0 -4
- package/dist/src/analytics/env.js +0 -14
- package/dist/src/analytics/exit.js +0 -24
- package/dist/src/analytics/index.js +0 -9
- package/dist/src/analytics/normalize.js +0 -18
- package/dist/src/analytics/os.js +0 -13
- package/dist/src/analytics/session.js +0 -15
- package/dist/src/analytics/tracker.js +0 -126
- package/dist/src/analytics/types.js +0 -1
- package/dist/src/analyze/build-analyze-view-rows.js +0 -63
- package/dist/src/analyze/command.js +0 -599
- package/dist/src/analyze/composite-closure.js +0 -0
- package/dist/src/analyze/composition/agent-parser/author-prompt.js +0 -22
- package/dist/src/analyze/composition/agent-parser/extract-parser.js +0 -44
- package/dist/src/analyze/composition/agent-parser/load-prompt.js +0 -31
- package/dist/src/analyze/composition/agent-parser/resolve-via-parser.js +0 -88
- package/dist/src/analyze/composition/agent-parser/sandbox.js +0 -187
- package/dist/src/analyze/composition/apply-mapping.js +0 -67
- package/dist/src/analyze/composition/candidate-critic-agent.js +0 -39
- package/dist/src/analyze/composition/candidate-critic.js +0 -63
- package/dist/src/analyze/composition/candidate-files.js +0 -131
- package/dist/src/analyze/composition/composition-cache-key.js +0 -19
- package/dist/src/analyze/composition/interchange-schema.js +0 -61
- package/dist/src/analyze/composition/manifest-doc-evidence.js +0 -136
- package/dist/src/analyze/composition/merge-edges.js +0 -70
- package/dist/src/analyze/composition/parse-map-edges.js +0 -55
- package/dist/src/analyze/composition/resolve-mapping-cli.js +0 -29
- package/dist/src/analyze/composition/resolve-mapping.js +0 -111
- package/dist/src/analyze/cycle-detection.js +0 -234
- package/dist/src/analyze/cycle-view.js +0 -28
- package/dist/src/analyze/fuzzy-search.js +0 -55
- package/dist/src/analyze/issue-inheritance.js +0 -108
- package/dist/src/analyze/lineage.js +0 -0
- package/dist/src/analyze/scope-gate-cascade.js +0 -170
- package/dist/src/analyze/search-neighborhood.js +0 -56
- package/dist/src/analyze/select/command.js +0 -484
- package/dist/src/analyze/select/index.js +0 -5
- package/dist/src/analyze/select/parser.js +0 -53
- package/dist/src/analyze/select/persistence.js +0 -80
- package/dist/src/analyze/select/preview-annotations.js +0 -62
- package/dist/src/analyze/select/stdout.js +0 -3
- package/dist/src/analyze/select/tui/App.js +0 -483
- package/dist/src/analyze/select/tui/components/ComponentDetail.js +0 -48
- package/dist/src/analyze/select/tui/components/ComponentRationalePanel.js +0 -125
- package/dist/src/analyze/select/tui/components/FieldEditor.js +0 -1131
- package/dist/src/analyze/select/tui/components/FinalizeDialog.js +0 -36
- package/dist/src/analyze/select/tui/components/GotoBanner.js +0 -30
- package/dist/src/analyze/select/tui/components/GroupedSidebar.js +0 -517
- package/dist/src/analyze/select/tui/components/HelpOverlay.js +0 -17
- package/dist/src/analyze/select/tui/components/JsonEditor.js +0 -131
- package/dist/src/analyze/select/tui/components/JsonPanel.js +0 -66
- package/dist/src/analyze/select/tui/components/LineagePanel.js +0 -22
- package/dist/src/analyze/select/tui/components/PreviewSummaryBar.js +0 -29
- package/dist/src/analyze/select/tui/components/QuitDialog.js +0 -14
- package/dist/src/analyze/select/tui/components/RationalePanel.js +0 -80
- package/dist/src/analyze/select/tui/components/Sidebar.js +0 -92
- package/dist/src/analyze/select/tui/components/SourcePanel.js +0 -52
- package/dist/src/analyze/select/tui/components/StatusBar.js +0 -7
- package/dist/src/analyze/select/tui/components/TopBar.js +0 -10
- package/dist/src/analyze/select/tui/components/removed-components-text.js +0 -11
- package/dist/src/analyze/select/tui/hooks/scroll-offset.js +0 -26
- package/dist/src/analyze/select/tui/hooks/useImmediateInput.js +0 -66
- package/dist/src/analyze/select/tui/hooks/useKeymap.js +0 -67
- package/dist/src/analyze/select/tui/hooks/useSession.js +0 -52
- package/dist/src/analyze/select/tui/hooks/useUndo.js +0 -26
- package/dist/src/analyze/select/tui/theme.js +0 -28
- package/dist/src/analyze/select/types.js +0 -39
- package/dist/src/analyze/select-agent/command.js +0 -558
- package/dist/src/analyze/select-agent/context-builder.js +0 -197
- package/dist/src/analyze/select-agent/show-rationale.js +0 -92
- package/dist/src/analyze/selection-cascade.js +0 -19
- package/dist/src/analyze/slot-graph.js +0 -17
- package/dist/src/analyze/tui/AnalyzeView.js +0 -64
- package/dist/src/apply/api-client.js +0 -440
- package/dist/src/apply/command.js +0 -845
- package/dist/src/apply/manifest.js +0 -1
- package/dist/src/apply/preview-utils.js +0 -26
- package/dist/src/apply/tui/SelectView.js +0 -34
- package/dist/src/apply/tui/ServerApplyView.js +0 -49
- package/dist/src/apply/tui/ServerPreviewView.js +0 -23
- package/dist/src/credentials-store.js +0 -74
- package/dist/src/generate/command.js +0 -597
- package/dist/src/generate/edit/command.js +0 -127
- package/dist/src/generate/tui/GenerateView.js +0 -10
- package/dist/src/host-utils.js +0 -26
- package/dist/src/import/agent-model-resolve.js +0 -35
- package/dist/src/import/auto-filter-resolve.js +0 -16
- package/dist/src/import/command.js +0 -380
- package/dist/src/import/cycle-auto-reject.js +0 -14
- package/dist/src/import/orchestrator.js +0 -603
- package/dist/src/import/path-utils.js +0 -30
- package/dist/src/import/picker-dispatch.js +0 -44
- package/dist/src/import/print-prompt.js +0 -31
- package/dist/src/import/strip-allowed-components.js +0 -22
- package/dist/src/import/tui/CustomPromptBanner.js +0 -8
- package/dist/src/import/tui/WizardApp.js +0 -1670
- package/dist/src/import/tui/ai-flag.js +0 -6
- package/dist/src/import/tui/auto-filter-error.js +0 -29
- package/dist/src/import/tui/autocomplete.js +0 -32
- package/dist/src/import/tui/components/AutoFilterBanner.js +0 -19
- package/dist/src/import/tui/components/CounterStrip.js +0 -12
- package/dist/src/import/tui/components/LegendEntry.js +0 -6
- package/dist/src/import/tui/cycle-panel-scroll.js +0 -33
- package/dist/src/import/tui/final-review-host.js +0 -25
- package/dist/src/import/tui/group-collapse.js +0 -11
- package/dist/src/import/tui/history.js +0 -53
- package/dist/src/import/tui/hooks/useLineage.js +0 -50
- package/dist/src/import/tui/hooks/useOverlayPanel.js +0 -27
- package/dist/src/import/tui/lineage-layout.js +0 -82
- package/dist/src/import/tui/merge-ai-decisions.js +0 -22
- package/dist/src/import/tui/push-decision-gate-helpers.js +0 -8
- package/dist/src/import/tui/push-progress.js +0 -1
- package/dist/src/import/tui/run-print-files-helpers.js +0 -8
- package/dist/src/import/tui/run-teaser.js +0 -9
- package/dist/src/import/tui/runLivePreview.js +0 -82
- package/dist/src/import/tui/runScopeGate.js +0 -28
- package/dist/src/import/tui/scope-gate-columns.js +0 -94
- package/dist/src/import/tui/scope-gate-host.js +0 -28
- package/dist/src/import/tui/sidebar-width.js +0 -3
- package/dist/src/import/tui/spawn-generate.js +0 -53
- package/dist/src/import/tui/step-filters.js +0 -42
- package/dist/src/import/tui/steps/AtomicGenerateReviewStep.js +0 -726
- package/dist/src/import/tui/steps/AtomicScopeGateStep.js +0 -210
- package/dist/src/import/tui/steps/CredentialsStep.js +0 -108
- package/dist/src/import/tui/steps/DoneStep.js +0 -24
- package/dist/src/import/tui/steps/ErrorStep.js +0 -16
- package/dist/src/import/tui/steps/GateStep.js +0 -22
- package/dist/src/import/tui/steps/GenerateReviewStep.js +0 -1618
- package/dist/src/import/tui/steps/PathValidationStep.js +0 -152
- package/dist/src/import/tui/steps/PreviewStep.js +0 -37
- package/dist/src/import/tui/steps/PreviewValidationErrorStep.js +0 -23
- package/dist/src/import/tui/steps/PushDecisionGateStep.js +0 -73
- package/dist/src/import/tui/steps/PushingStep.js +0 -24
- package/dist/src/import/tui/steps/RunningStep.js +0 -21
- package/dist/src/import/tui/steps/ScopeGateStep.js +0 -907
- package/dist/src/import/tui/steps/TokenInputStep.js +0 -88
- package/dist/src/import/tui/steps/WelcomeStep.js +0 -34
- package/dist/src/import/tui/steps/WizardPreviewStep.js +0 -169
- package/dist/src/import/tui/steps/auto-reject-decision.js +0 -9
- package/dist/src/import/tui/steps/breaking-change-format.js +0 -24
- package/dist/src/import/tui/steps/enumerate-cycle-breaks.js +0 -0
- package/dist/src/import/tui/steps/preview-diff.js +0 -175
- package/dist/src/import/tui/useFinalizePreview.js +0 -0
- package/dist/src/import/tui/useLivePreview.js +0 -122
- package/dist/src/import/tui/wizard-422-helpers.js +0 -60
- package/dist/src/import/tui/wizard-generate-progress.js +0 -25
- package/dist/src/import/tui/wizard-save-flow.js +0 -20
- package/dist/src/import/tui/wizard-state-transitions.js +0 -32
- package/dist/src/lib/agent-model-options.js +0 -15
- package/dist/src/lib/command-options.js +0 -30
- package/dist/src/lib/composition-mode.js +0 -39
- package/dist/src/lib/contentful-urls.js +0 -27
- package/dist/src/lib/debug-logger.js +0 -229
- package/dist/src/lib/debug-preamble.js +0 -33
- package/dist/src/lib/error-parser.js +0 -269
- package/dist/src/lib/prompt-overrides.js +0 -69
- package/dist/src/lib/terminal-capabilities.js +0 -51
- package/dist/src/lib/user-agent.js +0 -29
- package/dist/src/output/format.js +0 -110
- package/dist/src/print/command.js +0 -221
- package/dist/src/print/validate/tui/ValidateView.js +0 -37
- package/dist/src/print/validate/validators/cdf-validator.js +0 -104
- package/dist/src/print/validate/validators/dtcg-validator.js +0 -110
- package/dist/src/print/validate/validators/format-errors.js +0 -18
- package/dist/src/program.js +0 -105
- package/dist/src/runs/export-helpers.js +0 -59
- package/dist/src/runs/fingerprint.js +0 -75
- package/dist/src/runs/ls-command.js +0 -137
- package/dist/src/runs/modify-launcher.js +0 -42
- package/dist/src/runs/path-prompt.js +0 -72
- package/dist/src/runs/push-creds-prompt.js +0 -39
- package/dist/src/runs/push-helpers.js +0 -72
- package/dist/src/runs/push-launcher.js +0 -77
- package/dist/src/runs/replay-helpers.js +0 -164
- package/dist/src/runs/resolve-run-target.js +0 -45
- package/dist/src/runs/run-picker-mount.js +0 -72
- package/dist/src/runs/run-picker.js +0 -129
- package/dist/src/runs/save-conflict.js +0 -56
- package/dist/src/runs/save-path-resolver.js +0 -75
- package/dist/src/runs/staleness.js +0 -140
- package/dist/src/runs/store.js +0 -136
- package/dist/src/session/cache-keys.js +0 -44
- package/dist/src/session/command.js +0 -261
- package/dist/src/session/db.js +0 -1538
- package/dist/src/session/migration.js +0 -117
- package/dist/src/session/session-id.js +0 -212
- package/dist/src/session/stats.js +0 -89
- package/dist/src/setup/analytics-prompt.js +0 -24
- package/dist/src/setup/auto-filter-prompt.js +0 -24
- package/dist/src/setup/command.js +0 -966
- package/dist/src/setup/composition-mode-prompt.js +0 -37
- package/dist/src/setup/debug-mode-prompt.js +0 -22
- 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
|
-
}
|