@contentful/experience-design-system-cli 2.14.2 → 2.15.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 +64 -2
- package/dist/package.json +3 -2
- package/dist/src/analyze/command.d.ts +11 -0
- package/dist/src/analyze/command.js +298 -3
- package/dist/src/analyze/composite-closure.d.ts +25 -0
- package/dist/src/analyze/composite-closure.js +0 -0
- package/dist/src/analyze/composition/agent-parser/author-prompt.d.ts +4 -0
- package/dist/src/analyze/composition/agent-parser/author-prompt.js +22 -0
- package/dist/src/analyze/composition/agent-parser/extract-parser.d.ts +8 -0
- package/dist/src/analyze/composition/agent-parser/extract-parser.js +44 -0
- package/dist/src/analyze/composition/agent-parser/load-prompt.d.ts +7 -0
- package/dist/src/analyze/composition/agent-parser/load-prompt.js +31 -0
- package/dist/src/analyze/composition/agent-parser/resolve-via-parser.d.ts +46 -0
- package/dist/src/analyze/composition/agent-parser/resolve-via-parser.js +88 -0
- package/dist/src/analyze/composition/agent-parser/sandbox.d.ts +45 -0
- package/dist/src/analyze/composition/agent-parser/sandbox.js +187 -0
- package/dist/src/analyze/composition/apply-mapping.d.ts +22 -0
- package/dist/src/analyze/composition/apply-mapping.js +67 -0
- package/dist/src/analyze/composition/candidate-critic-agent.d.ts +7 -0
- package/dist/src/analyze/composition/candidate-critic-agent.js +39 -0
- package/dist/src/analyze/composition/candidate-critic.d.ts +32 -0
- package/dist/src/analyze/composition/candidate-critic.js +63 -0
- package/dist/src/analyze/composition/candidate-files.d.ts +34 -0
- package/dist/src/analyze/composition/candidate-files.js +131 -0
- package/dist/src/analyze/composition/composition-cache-key.d.ts +19 -0
- package/dist/src/analyze/composition/composition-cache-key.js +19 -0
- package/dist/src/analyze/composition/interchange-schema.d.ts +37 -0
- package/dist/src/analyze/composition/interchange-schema.js +61 -0
- package/dist/src/analyze/composition/merge-edges.d.ts +19 -0
- package/dist/src/analyze/composition/merge-edges.js +50 -0
- package/dist/src/analyze/composition/parse-map-edges.d.ts +16 -0
- package/dist/src/analyze/composition/parse-map-edges.js +55 -0
- package/dist/src/analyze/composition/resolve-mapping-cli.d.ts +23 -0
- package/dist/src/analyze/composition/resolve-mapping-cli.js +29 -0
- package/dist/src/analyze/composition/resolve-mapping.d.ts +59 -0
- package/dist/src/analyze/composition/resolve-mapping.js +94 -0
- package/dist/src/analyze/cycle-detection.d.ts +27 -0
- package/dist/src/analyze/cycle-detection.js +234 -0
- package/dist/src/analyze/cycle-view.d.ts +7 -0
- package/dist/src/analyze/cycle-view.js +28 -0
- package/dist/src/analyze/fuzzy-search.d.ts +3 -0
- package/dist/src/analyze/fuzzy-search.js +55 -0
- package/dist/src/analyze/issue-inheritance.d.ts +12 -0
- package/dist/src/analyze/issue-inheritance.js +108 -0
- package/dist/src/analyze/lineage.d.ts +29 -0
- package/dist/src/analyze/lineage.js +0 -0
- package/dist/src/analyze/scope-gate-cascade.d.ts +11 -0
- package/dist/src/analyze/scope-gate-cascade.js +170 -0
- package/dist/src/analyze/search-neighborhood.d.ts +3 -0
- package/dist/src/analyze/search-neighborhood.js +56 -0
- package/dist/src/analyze/select/tui/App.js +5 -16
- package/dist/src/analyze/select/tui/components/ComponentRationalePanel.d.ts +0 -4
- package/dist/src/analyze/select/tui/components/ComponentRationalePanel.js +3 -15
- package/dist/src/analyze/select/tui/components/FieldEditor.d.ts +29 -38
- package/dist/src/analyze/select/tui/components/FieldEditor.js +309 -185
- package/dist/src/analyze/select/tui/components/FinalizeDialog.d.ts +13 -1
- package/dist/src/analyze/select/tui/components/FinalizeDialog.js +23 -2
- package/dist/src/analyze/select/tui/components/GotoBanner.d.ts +31 -0
- package/dist/src/analyze/select/tui/components/GotoBanner.js +30 -0
- package/dist/src/analyze/select/tui/components/GroupedSidebar.d.ts +91 -0
- package/dist/src/analyze/select/tui/components/GroupedSidebar.js +497 -0
- package/dist/src/analyze/select/tui/components/HelpOverlay.d.ts +13 -1
- package/dist/src/analyze/select/tui/components/HelpOverlay.js +9 -3
- package/dist/src/analyze/select/tui/components/JsonEditor.js +3 -3
- package/dist/src/analyze/select/tui/components/LineagePanel.d.ts +14 -0
- package/dist/src/analyze/select/tui/components/LineagePanel.js +22 -0
- package/dist/src/analyze/select/tui/components/RationalePanel.d.ts +0 -7
- package/dist/src/analyze/select/tui/components/RationalePanel.js +3 -15
- package/dist/src/analyze/select/tui/components/Sidebar.d.ts +0 -6
- package/dist/src/analyze/select/tui/components/Sidebar.js +11 -27
- package/dist/src/analyze/select/tui/components/StatusBar.js +2 -1
- package/dist/src/analyze/select/tui/components/removed-components-text.d.ts +7 -0
- package/dist/src/analyze/select/tui/components/removed-components-text.js +11 -0
- package/dist/src/analyze/select/tui/hooks/useImmediateInput.d.ts +1 -5
- package/dist/src/analyze/select/tui/hooks/useImmediateInput.js +8 -10
- package/dist/src/analyze/select/tui/theme.d.ts +15 -0
- package/dist/src/analyze/select/tui/theme.js +28 -0
- package/dist/src/analyze/selection-cascade.d.ts +3 -0
- package/dist/src/analyze/selection-cascade.js +19 -0
- package/dist/src/analyze/slot-graph.d.ts +11 -0
- package/dist/src/analyze/slot-graph.js +17 -0
- package/dist/src/apply/api-client.d.ts +2 -1
- package/dist/src/apply/api-client.js +40 -6
- package/dist/src/apply/command.d.ts +17 -1
- package/dist/src/apply/command.js +69 -11
- package/dist/src/apply/error-parser.d.ts +16 -0
- package/dist/src/apply/error-parser.js +117 -0
- package/dist/src/apply/tui/ServerPreviewView.js +3 -1
- package/dist/src/credentials-store.d.ts +6 -0
- package/dist/src/credentials-store.js +5 -1
- package/dist/src/generate/agent-runner.d.ts +6 -0
- package/dist/src/generate/agent-runner.js +24 -8
- package/dist/src/import/command.js +69 -31
- package/dist/src/import/cycle-auto-reject.d.ts +4 -0
- package/dist/src/import/cycle-auto-reject.js +14 -0
- package/dist/src/import/orchestrator.d.ts +20 -7
- package/dist/src/import/orchestrator.js +139 -35
- package/dist/src/import/strip-allowed-components.d.ts +18 -0
- package/dist/src/import/strip-allowed-components.js +22 -0
- package/dist/src/import/tui/CustomPromptBanner.d.ts +0 -5
- package/dist/src/import/tui/CustomPromptBanner.js +2 -1
- package/dist/src/import/tui/WizardApp.d.ts +10 -74
- package/dist/src/import/tui/WizardApp.js +234 -246
- package/dist/src/import/tui/ai-flag.d.ts +5 -0
- package/dist/src/import/tui/ai-flag.js +6 -0
- package/dist/src/import/tui/autocomplete.d.ts +5 -0
- package/dist/src/import/tui/autocomplete.js +32 -0
- package/dist/src/import/tui/components/AutoFilterBanner.d.ts +10 -0
- package/dist/src/import/tui/components/AutoFilterBanner.js +19 -0
- package/dist/src/import/tui/components/CounterStrip.d.ts +12 -0
- package/dist/src/import/tui/components/CounterStrip.js +12 -0
- package/dist/src/import/tui/components/LegendEntry.d.ts +2 -0
- package/dist/src/import/tui/components/LegendEntry.js +6 -0
- package/dist/src/import/tui/cycle-panel-scroll.d.ts +8 -0
- package/dist/src/import/tui/cycle-panel-scroll.js +33 -0
- package/dist/src/import/tui/final-review-host.d.ts +3 -7
- package/dist/src/import/tui/final-review-host.js +9 -4
- package/dist/src/import/tui/group-collapse.d.ts +2 -0
- package/dist/src/import/tui/group-collapse.js +11 -0
- package/dist/src/import/tui/history.d.ts +22 -0
- package/dist/src/import/tui/history.js +53 -0
- package/dist/src/import/tui/hooks/useLineage.d.ts +32 -0
- package/dist/src/import/tui/hooks/useLineage.js +50 -0
- package/dist/src/import/tui/hooks/useOverlayPanel.d.ts +13 -0
- package/dist/src/import/tui/hooks/useOverlayPanel.js +27 -0
- package/dist/src/import/tui/lineage-layout.d.ts +75 -0
- package/dist/src/import/tui/lineage-layout.js +82 -0
- package/dist/src/import/tui/runLivePreview.d.ts +11 -0
- package/dist/src/import/tui/runLivePreview.js +7 -1
- package/dist/src/import/tui/scope-gate-columns.d.ts +31 -0
- package/dist/src/import/tui/scope-gate-columns.js +94 -0
- package/dist/src/import/tui/scope-gate-host.d.ts +3 -1
- package/dist/src/import/tui/scope-gate-host.js +11 -3
- package/dist/src/import/tui/sidebar-width.d.ts +1 -0
- package/dist/src/import/tui/sidebar-width.js +3 -0
- package/dist/src/import/tui/step-filters.d.ts +19 -0
- package/dist/src/import/tui/step-filters.js +42 -0
- package/dist/src/import/tui/steps/AtomicGenerateReviewStep.d.ts +42 -0
- package/dist/src/import/tui/steps/AtomicGenerateReviewStep.js +726 -0
- package/dist/src/import/tui/steps/AtomicScopeGateStep.d.ts +3 -0
- package/dist/src/import/tui/steps/AtomicScopeGateStep.js +211 -0
- package/dist/src/import/tui/steps/CredentialsStep.js +5 -18
- package/dist/src/import/tui/steps/DoneStep.d.ts +0 -2
- package/dist/src/import/tui/steps/DoneStep.js +3 -2
- package/dist/src/import/tui/steps/ErrorStep.js +2 -1
- package/dist/src/import/tui/steps/GenerateReviewStep.d.ts +19 -25
- package/dist/src/import/tui/steps/GenerateReviewStep.js +1258 -229
- package/dist/src/import/tui/steps/PathValidationStep.js +3 -2
- package/dist/src/import/tui/steps/PreviewStep.js +2 -1
- package/dist/src/import/tui/steps/PushDecisionGateStep.d.ts +0 -7
- package/dist/src/import/tui/steps/PushDecisionGateStep.js +3 -6
- package/dist/src/import/tui/steps/PushingStep.js +2 -1
- package/dist/src/import/tui/steps/RunningStep.d.ts +4 -1
- package/dist/src/import/tui/steps/RunningStep.js +3 -2
- package/dist/src/import/tui/steps/ScopeGateStep.d.ts +24 -0
- package/dist/src/import/tui/steps/ScopeGateStep.js +850 -193
- package/dist/src/import/tui/steps/TokenInputStep.js +2 -1
- package/dist/src/import/tui/steps/WelcomeStep.js +2 -1
- package/dist/src/import/tui/steps/WizardPreviewStep.d.ts +6 -0
- package/dist/src/import/tui/steps/WizardPreviewStep.js +95 -56
- package/dist/src/import/tui/steps/auto-reject-decision.d.ts +7 -0
- package/dist/src/import/tui/steps/auto-reject-decision.js +9 -0
- package/dist/src/import/tui/steps/breaking-change-format.d.ts +2 -0
- package/dist/src/import/tui/steps/breaking-change-format.js +24 -0
- package/dist/src/import/tui/steps/enumerate-cycle-breaks.d.ts +14 -0
- package/dist/src/import/tui/steps/enumerate-cycle-breaks.js +0 -0
- package/dist/src/import/tui/steps/preview-diff.js +48 -5
- package/dist/src/import/tui/useFinalizePreview.d.ts +34 -0
- package/dist/src/import/tui/useFinalizePreview.js +0 -0
- package/dist/src/import/tui/useLivePreview.d.ts +3 -0
- package/dist/src/import/tui/useLivePreview.js +1 -0
- package/dist/src/import/tui/wizard-state-transitions.d.ts +5 -59
- package/dist/src/import/tui/wizard-state-transitions.js +5 -60
- package/dist/src/lib/composition-mode.d.ts +28 -0
- package/dist/src/lib/composition-mode.js +37 -0
- package/dist/src/lib/prompt-overrides.d.ts +38 -0
- package/dist/src/lib/prompt-overrides.js +69 -0
- package/dist/src/print/command.js +19 -1
- package/dist/src/runs/modify-launcher.d.ts +3 -0
- package/dist/src/runs/modify-launcher.js +2 -0
- package/dist/src/runs/replay-helpers.js +1 -0
- package/dist/src/runs/run-picker.js +2 -18
- package/dist/src/runs/store.d.ts +4 -0
- package/dist/src/session/db.d.ts +23 -40
- package/dist/src/session/db.js +110 -138
- package/dist/src/setup/composition-mode-prompt.d.ts +14 -0
- package/dist/src/setup/composition-mode-prompt.js +37 -0
- package/package.json +5 -4
- package/prompts/composition-dir-critic.md +7 -0
- package/prompts/composition-edges.md +8 -0
- package/prompts/composition-parser-repair-empty.md +1 -0
- package/prompts/composition-parser-repair-error.md +2 -0
- package/prompts/composition-parser.md +42 -0
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { PALETTE } from '../theme.js';
|
|
2
3
|
import { Box, Text } from 'ink';
|
|
3
|
-
/**
|
|
4
|
-
* Word-wrap a single rationale paragraph to fit within `innerWidth` columns.
|
|
5
|
-
* Returns an array of wrapped lines. Empty input → single empty line so the
|
|
6
|
-
* row still occupies vertical space.
|
|
7
|
-
*/
|
|
8
4
|
function wrapText(text, innerWidth) {
|
|
9
5
|
if (!text)
|
|
10
6
|
return [''];
|
|
@@ -16,7 +12,6 @@ function wrapText(text, innerWidth) {
|
|
|
16
12
|
let current = '';
|
|
17
13
|
for (const w of words) {
|
|
18
14
|
if (current.length === 0) {
|
|
19
|
-
// Word longer than width — hard-break.
|
|
20
15
|
if (w.length > width) {
|
|
21
16
|
let rest = w;
|
|
22
17
|
while (rest.length > width) {
|
|
@@ -52,13 +47,6 @@ function wrapText(text, innerWidth) {
|
|
|
52
47
|
lines.push(current);
|
|
53
48
|
return lines.length > 0 ? lines : [''];
|
|
54
49
|
}
|
|
55
|
-
/**
|
|
56
|
-
* Flatten `rows` to a list of rendered lines so scrollOffset slicing matches
|
|
57
|
-
* what the operator sees. Layout per row:
|
|
58
|
-
* <name> ← bold
|
|
59
|
-
* <wrapped text> ← one or more lines
|
|
60
|
-
* <blank> ← spacer (omitted after the final row)
|
|
61
|
-
*/
|
|
62
50
|
export function renderRationaleLines(rows, innerWidth) {
|
|
63
51
|
const out = [];
|
|
64
52
|
rows.forEach((row, idx) => {
|
|
@@ -80,12 +68,12 @@ export function RationalePanel({ componentName, rows, scrollOffset, width, heigh
|
|
|
80
68
|
const overflowed = totalLines > height;
|
|
81
69
|
const visibleStart = totalLines === 0 ? 0 : scrollOffset + 1;
|
|
82
70
|
const visibleEnd = Math.min(totalLines, scrollOffset + height);
|
|
83
|
-
return (_jsxs(Box, { flexDirection: "column", width: width, height: height + 2, borderStyle: "single", borderColor: active ?
|
|
71
|
+
return (_jsxs(Box, { flexDirection: "column", width: width, height: height + 2, borderStyle: "single", borderColor: active ? PALETTE.inverse : undefined, children: [_jsxs(Box, { children: [_jsx(Text, { bold: true, dimColor: !active, children: `RATIONALE — ${componentName}` }), overflowed && (_jsxs(_Fragment, { children: [_jsx(Box, { flexGrow: 1 }), _jsx(Text, { dimColor: !active, children: `↕ ${visibleStart}-${visibleEnd}/${totalLines}` })] }))] }), visible.map((line, i) => {
|
|
84
72
|
if (line.kind === 'blank') {
|
|
85
73
|
return (_jsx(Box, { children: _jsx(Text, { children: " " }) }, i));
|
|
86
74
|
}
|
|
87
75
|
if (line.kind === 'name') {
|
|
88
|
-
return (_jsxs(Box, { children: [_jsx(Text, { bold: true, color:
|
|
76
|
+
return (_jsxs(Box, { children: [_jsx(Text, { bold: true, color: PALETTE.info, dimColor: !active, children: line.text }), line.isSlot && _jsx(Text, { dimColor: true, children: " (slot)" })] }, i));
|
|
89
77
|
}
|
|
90
78
|
return (_jsx(Box, { children: _jsx(Text, { dimColor: !active, children: line.text }) }, i));
|
|
91
79
|
})] }));
|
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { PreviewAnnotation, ReviewComponentSummary, ReviewComponentStatus } from '../../types.js';
|
|
3
|
-
/**
|
|
4
|
-
* Pilot-2026-06-23 R2: render a single-character preview-diff badge directly
|
|
5
|
-
* before each component name in the sidebar so operators can scan the diff
|
|
6
|
-
* shape at a glance without opening each row. Returns null for unannotated
|
|
7
|
-
* rows so the row falls back to its existing single-space layout.
|
|
8
|
-
*/
|
|
9
3
|
export declare function previewBadge(annotation: PreviewAnnotation | undefined): {
|
|
10
4
|
char: string;
|
|
11
5
|
color: string;
|
|
@@ -1,21 +1,16 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Box, Text } from 'ink';
|
|
3
|
-
|
|
4
|
-
* Pilot-2026-06-23 R2: render a single-character preview-diff badge directly
|
|
5
|
-
* before each component name in the sidebar so operators can scan the diff
|
|
6
|
-
* shape at a glance without opening each row. Returns null for unannotated
|
|
7
|
-
* rows so the row falls back to its existing single-space layout.
|
|
8
|
-
*/
|
|
3
|
+
import { PALETTE } from '../theme.js';
|
|
9
4
|
export function previewBadge(annotation) {
|
|
10
5
|
switch (annotation) {
|
|
11
6
|
case 'new':
|
|
12
|
-
return { char: '+', color:
|
|
7
|
+
return { char: '+', color: PALETTE.success };
|
|
13
8
|
case 'changed':
|
|
14
|
-
return { char: '~', color:
|
|
9
|
+
return { char: '~', color: PALETTE.warning };
|
|
15
10
|
case 'removed':
|
|
16
|
-
return { char: '-', color:
|
|
11
|
+
return { char: '-', color: PALETTE.error, dim: true };
|
|
17
12
|
case 'breaking':
|
|
18
|
-
return { char: '!', color:
|
|
13
|
+
return { char: '!', color: PALETTE.error, bold: true };
|
|
19
14
|
default:
|
|
20
15
|
return null;
|
|
21
16
|
}
|
|
@@ -25,7 +20,6 @@ export function statusIcon(status, validationErrorCount,
|
|
|
25
20
|
// decision must remain visible. Color is already yellow via statusColor for
|
|
26
21
|
// warning-only components, so the warning cue is preserved.
|
|
27
22
|
_validationWarningCount) {
|
|
28
|
-
// Errors override — a structurally broken component should never render as ✓/✗.
|
|
29
23
|
if (validationErrorCount > 0)
|
|
30
24
|
return '⚠';
|
|
31
25
|
switch (status) {
|
|
@@ -41,18 +35,18 @@ _validationWarningCount) {
|
|
|
41
35
|
}
|
|
42
36
|
export function statusColor(status, validationErrorCount, validationWarningCount) {
|
|
43
37
|
if (validationErrorCount > 0)
|
|
44
|
-
return
|
|
38
|
+
return PALETTE.error;
|
|
45
39
|
if (validationWarningCount > 0)
|
|
46
|
-
return
|
|
40
|
+
return PALETTE.warning;
|
|
47
41
|
switch (status) {
|
|
48
42
|
case 'accepted':
|
|
49
|
-
return
|
|
43
|
+
return PALETTE.success;
|
|
50
44
|
case 'rejected':
|
|
51
|
-
return
|
|
45
|
+
return PALETTE.error;
|
|
52
46
|
case 'reviewed':
|
|
53
|
-
return
|
|
47
|
+
return PALETTE.warning;
|
|
54
48
|
case 'needs-review':
|
|
55
|
-
return
|
|
49
|
+
return PALETTE.muted;
|
|
56
50
|
}
|
|
57
51
|
}
|
|
58
52
|
function truncateName(name, maxLen) {
|
|
@@ -60,13 +54,6 @@ function truncateName(name, maxLen) {
|
|
|
60
54
|
return name;
|
|
61
55
|
return name.slice(0, maxLen) + '…';
|
|
62
56
|
}
|
|
63
|
-
/**
|
|
64
|
-
* Sort key for stable secondary ordering within a validation tier:
|
|
65
|
-
* needs-review components first, then by extractionConfidence ascending
|
|
66
|
-
* (lowest confidence first, null treated as highest = last). Used to be
|
|
67
|
-
* applied inline in App.tsx, then this helper sorted again — pulled in
|
|
68
|
-
* here so the sort happens once.
|
|
69
|
-
*/
|
|
70
57
|
function withinTierComparator(a, b) {
|
|
71
58
|
const aPending = a.needsReview && a.status === 'needs-review' ? 0 : 1;
|
|
72
59
|
const bPending = b.needsReview && b.status === 'needs-review' ? 0 : 1;
|
|
@@ -95,9 +82,6 @@ export function Sidebar({ components, selectedId, focused, scrollOffset, visible
|
|
|
95
82
|
const icon = statusIcon(component.status, component.validationErrorCount, component.validationWarningCount);
|
|
96
83
|
const color = statusColor(component.status, component.validationErrorCount, component.validationWarningCount);
|
|
97
84
|
const badge = previewBadge(component.previewAnnotation);
|
|
98
|
-
// Reserve one column for the preview badge regardless of whether this
|
|
99
|
-
// row has one — keeps name truncation stable across rows so the column
|
|
100
|
-
// width doesn't jitter as annotations flip in/out.
|
|
101
85
|
const maxNameLen = Math.max(1, width - 5);
|
|
102
86
|
const name = truncateName(component.name, maxNameLen);
|
|
103
87
|
if (collapsed) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { Box, Text } from 'ink';
|
|
3
|
+
import { PALETTE } from '../theme.js';
|
|
3
4
|
export function StatusBar({ accepted, rejected, reviewed, needsReview }) {
|
|
4
5
|
const allResolved = needsReview === 0;
|
|
5
|
-
return (_jsxs(Box, { gap: 2, flexWrap: "wrap", children: [_jsxs(Text, { color:
|
|
6
|
+
return (_jsxs(Box, { gap: 2, flexWrap: "wrap", children: [_jsxs(Text, { color: PALETTE.success, children: [accepted, " accepted"] }), _jsxs(Text, { color: PALETTE.error, children: [rejected, " rejected"] }), _jsxs(Text, { dimColor: true, children: [needsReview, " pending"] }), _jsxs(Text, { color: PALETTE.info, children: [reviewed, " reviewed"] }), _jsx(Text, { dimColor: true, children: "\u00B7" }), _jsx(Text, { dimColor: true, children: "[A] accept all" }), _jsx(Text, { bold: allResolved, color: allResolved ? PALETTE.success : PALETTE.fg, children: "[F] finalize" })] }));
|
|
6
7
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ComponentTypeSummary } from '@contentful/experience-design-system-types';
|
|
2
|
+
/** Header line for the removed-components surfaces (deletion panel + finalize
|
|
3
|
+
* dialog). Kept in one place so both read identically. `withExpandHint` adds
|
|
4
|
+
* the panel's "[d] to expand/collapse" affordance, which the dialog omits. */
|
|
5
|
+
export declare function removedComponentsHeader(count: number, withExpandHint: boolean): string;
|
|
6
|
+
/** One bullet line per removed component, matching the deletion panel. */
|
|
7
|
+
export declare function removedComponentLine(rc: ComponentTypeSummary): string;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Header line for the removed-components surfaces (deletion panel + finalize
|
|
2
|
+
* dialog). Kept in one place so both read identically. `withExpandHint` adds
|
|
3
|
+
* the panel's "[d] to expand/collapse" affordance, which the dialog omits. */
|
|
4
|
+
export function removedComponentsHeader(count, withExpandHint) {
|
|
5
|
+
const hint = withExpandHint ? ' (press [d] to expand/collapse)' : '';
|
|
6
|
+
return `Removed components (${count}) — will be DELETED from target space${hint}`;
|
|
7
|
+
}
|
|
8
|
+
/** One bullet line per removed component, matching the deletion panel. */
|
|
9
|
+
export function removedComponentLine(rc) {
|
|
10
|
+
return `- ${rc.name}${rc.id ? ` (${rc.id})` : ''}`;
|
|
11
|
+
}
|
|
@@ -10,15 +10,11 @@ type Key = {
|
|
|
10
10
|
ctrl: boolean;
|
|
11
11
|
shift: boolean;
|
|
12
12
|
tab: boolean;
|
|
13
|
+
shiftTab: boolean;
|
|
13
14
|
backspace: boolean;
|
|
14
15
|
delete: boolean;
|
|
15
16
|
meta: boolean;
|
|
16
17
|
};
|
|
17
18
|
type InputHandler = (input: string, key: Key) => void;
|
|
18
|
-
/**
|
|
19
|
-
* Like Ink's useInput, but uses useLayoutEffect so the listener is registered
|
|
20
|
-
* synchronously after render. This allows stdin.write() calls in tests to work
|
|
21
|
-
* immediately after render() without awaiting effects.
|
|
22
|
-
*/
|
|
23
19
|
export declare function useImmediateInput(handler: InputHandler): void;
|
|
24
20
|
export {};
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { useLayoutEffect, useRef } from 'react';
|
|
2
2
|
import { useStdin } from 'ink';
|
|
3
3
|
function parseInput(data) {
|
|
4
|
+
// Shift-Tab in most terminals emits CSI Z (\x1b[Z). We surface it as both
|
|
5
|
+
// `tab` and `shiftTab` so callers that already branch on `tab` still fire,
|
|
6
|
+
// and new callers can distinguish direction via `shiftTab`.
|
|
7
|
+
const isShiftTab = data === '\x1b[Z';
|
|
4
8
|
const key = {
|
|
5
9
|
upArrow: data === '\x1b[A',
|
|
6
10
|
downArrow: data === '\x1b[B',
|
|
@@ -11,22 +15,21 @@ function parseInput(data) {
|
|
|
11
15
|
return: data === '\r' || data === '\n',
|
|
12
16
|
escape: data === '\x1b',
|
|
13
17
|
ctrl: false,
|
|
14
|
-
shift:
|
|
15
|
-
tab: data === '\t',
|
|
18
|
+
shift: isShiftTab,
|
|
19
|
+
tab: data === '\t' || isShiftTab,
|
|
20
|
+
shiftTab: isShiftTab,
|
|
16
21
|
backspace: data === '\x7f' || data === '\b',
|
|
17
22
|
delete: data === '\x1b[3~',
|
|
18
23
|
meta: data === '\x1b',
|
|
19
24
|
};
|
|
20
25
|
let input = data;
|
|
21
|
-
// Ctrl+letter: data is \x01-\x1a (Ctrl+A through Ctrl+Z)
|
|
22
26
|
if (data.length === 1) {
|
|
23
27
|
const code = data.charCodeAt(0);
|
|
24
28
|
if (code >= 1 && code <= 26) {
|
|
25
29
|
key.ctrl = true;
|
|
26
|
-
input = String.fromCharCode(code + 96);
|
|
30
|
+
input = String.fromCharCode(code + 96);
|
|
27
31
|
}
|
|
28
32
|
}
|
|
29
|
-
// Arrow keys and special keys produce no printable input
|
|
30
33
|
if (key.upArrow ||
|
|
31
34
|
key.downArrow ||
|
|
32
35
|
key.leftArrow ||
|
|
@@ -43,11 +46,6 @@ function parseInput(data) {
|
|
|
43
46
|
}
|
|
44
47
|
return { input, key };
|
|
45
48
|
}
|
|
46
|
-
/**
|
|
47
|
-
* Like Ink's useInput, but uses useLayoutEffect so the listener is registered
|
|
48
|
-
* synchronously after render. This allows stdin.write() calls in tests to work
|
|
49
|
-
* immediately after render() without awaiting effects.
|
|
50
|
-
*/
|
|
51
49
|
export function useImmediateInput(handler) {
|
|
52
50
|
const { stdin, setRawMode } = useStdin();
|
|
53
51
|
const handlerRef = useRef(handler);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ReviewComponentStatus } from '../types.js';
|
|
2
|
+
export declare const PALETTE: {
|
|
3
|
+
readonly info: "#1773EB";
|
|
4
|
+
readonly success: "#00C459";
|
|
5
|
+
readonly error: "#E44F20";
|
|
6
|
+
readonly warning: "#FFDA00";
|
|
7
|
+
readonly fg: "#000000";
|
|
8
|
+
readonly inverse: "#FFFFFF";
|
|
9
|
+
readonly muted: "#A6B5C7";
|
|
10
|
+
readonly border: "#C4D1DE";
|
|
11
|
+
readonly subtle: "#DDE5EC";
|
|
12
|
+
readonly bg: "#EFF2F6";
|
|
13
|
+
};
|
|
14
|
+
export type PaletteRole = keyof typeof PALETTE;
|
|
15
|
+
export declare function statusPaletteColor(status: ReviewComponentStatus, validationErrorCount: number, validationWarningCount: number): string;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export const PALETTE = {
|
|
2
|
+
info: '#1773EB',
|
|
3
|
+
success: '#00C459',
|
|
4
|
+
error: '#E44F20',
|
|
5
|
+
warning: '#FFDA00',
|
|
6
|
+
fg: '#000000',
|
|
7
|
+
inverse: '#FFFFFF',
|
|
8
|
+
muted: '#A6B5C7',
|
|
9
|
+
border: '#C4D1DE',
|
|
10
|
+
subtle: '#DDE5EC',
|
|
11
|
+
bg: '#EFF2F6',
|
|
12
|
+
};
|
|
13
|
+
export function statusPaletteColor(status, validationErrorCount, validationWarningCount) {
|
|
14
|
+
if (validationErrorCount > 0)
|
|
15
|
+
return PALETTE.error;
|
|
16
|
+
if (validationWarningCount > 0)
|
|
17
|
+
return PALETTE.warning;
|
|
18
|
+
switch (status) {
|
|
19
|
+
case 'accepted':
|
|
20
|
+
return PALETTE.success;
|
|
21
|
+
case 'rejected':
|
|
22
|
+
return PALETTE.error;
|
|
23
|
+
case 'reviewed':
|
|
24
|
+
return PALETTE.warning;
|
|
25
|
+
case 'needs-review':
|
|
26
|
+
return PALETTE.muted;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { ComponentGraphNode } from './composite-closure.js';
|
|
2
|
+
export declare function computeRejectCascade(target: string, components: ComponentGraphNode[]): Set<string>;
|
|
3
|
+
export declare function computeAcceptCascade(target: string, components: ComponentGraphNode[]): Set<string>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { computeClosure } from './composite-closure.js';
|
|
2
|
+
import { findAllAncestors } from './lineage.js';
|
|
3
|
+
export function computeRejectCascade(target, components) {
|
|
4
|
+
const out = new Set();
|
|
5
|
+
out.add(target);
|
|
6
|
+
for (const ancestor of findAllAncestors(target, components)) {
|
|
7
|
+
out.add(ancestor);
|
|
8
|
+
}
|
|
9
|
+
return out;
|
|
10
|
+
}
|
|
11
|
+
export function computeAcceptCascade(target, components) {
|
|
12
|
+
const out = new Set();
|
|
13
|
+
out.add(target);
|
|
14
|
+
const closure = computeClosure(target, components);
|
|
15
|
+
for (const node of closure.nodes) {
|
|
16
|
+
out.add(node.name);
|
|
17
|
+
}
|
|
18
|
+
return out;
|
|
19
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { CDFComponentEntry } from '@contentful/experience-design-system-types';
|
|
2
|
+
import type { ComponentGraphNode } from './composite-closure.js';
|
|
3
|
+
export interface SlotGraphInput {
|
|
4
|
+
key: string;
|
|
5
|
+
entry: CDFComponentEntry;
|
|
6
|
+
status?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface BuildOptions {
|
|
9
|
+
stripRejectedEdges?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare function buildComponentGraph(components: SlotGraphInput[], opts?: BuildOptions): ComponentGraphNode[];
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const REJECTED_STATUSES = new Set(['error', 'rejected']);
|
|
2
|
+
export function buildComponentGraph(components, opts) {
|
|
3
|
+
const stripRejectedEdges = opts?.stripRejectedEdges === true;
|
|
4
|
+
return components.map((row) => {
|
|
5
|
+
if (stripRejectedEdges && row.status !== undefined && REJECTED_STATUSES.has(row.status)) {
|
|
6
|
+
return { name: row.key, slots: [] };
|
|
7
|
+
}
|
|
8
|
+
const slotDefs = row.entry.$slots ?? {};
|
|
9
|
+
const slots = Object.entries(slotDefs).map(([slotName, slotDef]) => ({
|
|
10
|
+
name: slotName,
|
|
11
|
+
allowedComponents: Array.isArray(slotDef?.$allowedComponents)
|
|
12
|
+
? slotDef.$allowedComponents.filter((v) => typeof v === 'string')
|
|
13
|
+
: [],
|
|
14
|
+
}));
|
|
15
|
+
return { name: row.key, slots };
|
|
16
|
+
});
|
|
17
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ManifestPayload, ServerPreviewResponse, ApplyOperationResponse } from '@contentful/experience-design-system-types';
|
|
1
|
+
import type { ManifestPayload, ServerPreviewResponse, ApplyOperationResponse, BreakingChange } from '@contentful/experience-design-system-types';
|
|
2
2
|
export declare const DEFAULT_HOST = "https://api.contentful.com";
|
|
3
3
|
export declare const PREVIEW_ERROR_PREFIX = "preview failed:";
|
|
4
4
|
export declare const APPLY_ERROR_PREFIX = "apply failed:";
|
|
@@ -31,6 +31,7 @@ export interface PreviewValidationError {
|
|
|
31
31
|
* the field-level detail.
|
|
32
32
|
*/
|
|
33
33
|
export declare function parsePreviewValidationErrors(body: string): PreviewValidationError[];
|
|
34
|
+
export declare function sanitizeBreakingChanges(raw: unknown): BreakingChange[];
|
|
34
35
|
export declare class ImportApiClient {
|
|
35
36
|
private host;
|
|
36
37
|
private token;
|
|
@@ -2,8 +2,6 @@ import { DEFAULT_API_HOST, toApiHost } from '../host-utils.js';
|
|
|
2
2
|
import { getDebugLogger } from '../lib/debug-logger.js';
|
|
3
3
|
import { buildUserAgent } from '../lib/user-agent.js';
|
|
4
4
|
export const DEFAULT_HOST = DEFAULT_API_HOST;
|
|
5
|
-
// Phase-prefix constants used at the two ApiError throw sites below and
|
|
6
|
-
// imported by orchestrator.ts to identify preview-phase 422s for retry.
|
|
7
5
|
export const PREVIEW_ERROR_PREFIX = 'preview failed:';
|
|
8
6
|
export const APPLY_ERROR_PREFIX = 'apply failed:';
|
|
9
7
|
// Substring match the orchestrator uses to distinguish a parseable
|
|
@@ -31,9 +29,6 @@ export class ApiError extends Error {
|
|
|
31
29
|
this.status = status;
|
|
32
30
|
this.body = body;
|
|
33
31
|
if (body) {
|
|
34
|
-
// Append a (possibly trimmed) version of the response body so callers
|
|
35
|
-
// that only log e.message don't silently swallow the server's error
|
|
36
|
-
// detail.
|
|
37
32
|
const trimmed = body.length > ERROR_BODY_LOG_CAP ? body.slice(0, ERROR_BODY_LOG_CAP) + '…' : body;
|
|
38
33
|
this.message = `${message}\n${trimmed}`;
|
|
39
34
|
}
|
|
@@ -83,6 +78,45 @@ export function parsePreviewValidationErrors(body) {
|
|
|
83
78
|
}
|
|
84
79
|
return out;
|
|
85
80
|
}
|
|
81
|
+
const PROPERTY_BREAKING_REASONS = new Set([
|
|
82
|
+
'removed',
|
|
83
|
+
'added_required_no_default',
|
|
84
|
+
'type_changed',
|
|
85
|
+
'validation_narrowed',
|
|
86
|
+
]);
|
|
87
|
+
const SLOT_BREAKING_REASONS = new Set(['slot_removed', 'slot_allowed_components_narrowed']);
|
|
88
|
+
export function sanitizeBreakingChanges(raw) {
|
|
89
|
+
if (!Array.isArray(raw))
|
|
90
|
+
return [];
|
|
91
|
+
const out = [];
|
|
92
|
+
for (const bc of raw) {
|
|
93
|
+
if (typeof bc !== 'object' || bc === null)
|
|
94
|
+
continue;
|
|
95
|
+
const reason = bc.reason;
|
|
96
|
+
if (typeof reason !== 'string')
|
|
97
|
+
continue;
|
|
98
|
+
if ('propertyId' in bc && typeof bc.propertyId === 'string') {
|
|
99
|
+
if (PROPERTY_BREAKING_REASONS.has(reason))
|
|
100
|
+
out.push(bc);
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
if ('slotId' in bc && typeof bc.slotId === 'string') {
|
|
104
|
+
if (SLOT_BREAKING_REASONS.has(reason))
|
|
105
|
+
out.push(bc);
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return out;
|
|
110
|
+
}
|
|
111
|
+
function sanitizePreviewResponse(res) {
|
|
112
|
+
for (const item of res.components?.changed ?? []) {
|
|
113
|
+
const cc = item.changeClassification;
|
|
114
|
+
if (cc && Array.isArray(cc.breakingChanges)) {
|
|
115
|
+
cc.breakingChanges = sanitizeBreakingChanges(cc.breakingChanges);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return res;
|
|
119
|
+
}
|
|
86
120
|
async function request(url, options) {
|
|
87
121
|
const headers = {
|
|
88
122
|
Authorization: `Bearer ${options.token}`,
|
|
@@ -155,7 +189,7 @@ export class ImportApiClient {
|
|
|
155
189
|
}
|
|
156
190
|
const parsed = (await res.json());
|
|
157
191
|
debug.event('apply', 'preview.ok', { status: res.status, durationMs: Date.now() - startedAt });
|
|
158
|
-
return parsed;
|
|
192
|
+
return sanitizePreviewResponse(parsed);
|
|
159
193
|
}
|
|
160
194
|
async applyImport(manifest, acknowledgeBreakingChanges) {
|
|
161
195
|
const url = `${this.base()}/design_systems/imports/apply`;
|
|
@@ -1,6 +1,22 @@
|
|
|
1
1
|
import type { Command } from 'commander';
|
|
2
|
-
import type { DTCGTokenEntry } from '@contentful/experience-design-system-types';
|
|
2
|
+
import type { CDFComponentEntry, DTCGTokenEntry } from '@contentful/experience-design-system-types';
|
|
3
|
+
import { findSlotCycles } from '../analyze/cycle-detection.js';
|
|
3
4
|
import type { ServerPreviewResponse } from '@contentful/experience-design-system-types';
|
|
4
5
|
export declare function readTokensFromPath(flag: string, p: string): Promise<DTCGTokenEntry[]>;
|
|
6
|
+
export declare function detectSlotCycles(components: Array<{
|
|
7
|
+
key: string;
|
|
8
|
+
entry: CDFComponentEntry;
|
|
9
|
+
}>): ReturnType<typeof findSlotCycles>;
|
|
10
|
+
export declare function formatSlotCycleReport(cycles: ReturnType<typeof findSlotCycles>): string[];
|
|
11
|
+
export declare function assertNoSlotCycles(components: Array<{
|
|
12
|
+
key: string;
|
|
13
|
+
entry: CDFComponentEntry;
|
|
14
|
+
}>): void;
|
|
15
|
+
export declare function extractComponentsFromManifest(manifest: {
|
|
16
|
+
componentsManifest?: Record<string, unknown>;
|
|
17
|
+
} | null | undefined): Array<{
|
|
18
|
+
key: string;
|
|
19
|
+
entry: CDFComponentEntry;
|
|
20
|
+
}>;
|
|
5
21
|
export declare function hasBreakingChangesWithImpact(preview: ServerPreviewResponse): boolean;
|
|
6
22
|
export declare function registerApplyCommand(program: Command): void;
|