@contentful/experience-design-system-cli 2.37.1-dev-build-dbc9f30e.0 → 2.37.1-dev-build-8b126ca1.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 (83) hide show
  1. package/dist/app.d.ts +2 -6
  2. package/dist/app.js +8558 -448
  3. package/dist/index.js +9021 -516
  4. package/dist/package.json +1 -1
  5. package/dist/src/commands/import-options.d.ts +0 -1
  6. package/dist/src/tui/import/steps/07-scope-gate/graph/cycle-detection.d.ts +5 -0
  7. package/dist/src/tui/import/steps/09-review/components/ComponentRationalePanel.d.ts +10 -0
  8. package/dist/src/tui/import/steps/09-review/components/FieldEditor.d.ts +67 -0
  9. package/dist/src/tui/import/steps/09-review/components/FinalizeDialog.d.ts +22 -0
  10. package/dist/src/tui/import/steps/09-review/components/HighlightedLine.d.ts +9 -0
  11. package/dist/src/tui/import/steps/09-review/components/JsonPanel.d.ts +11 -0
  12. package/dist/src/tui/import/steps/09-review/components/LivePreviewSummary.d.ts +14 -0
  13. package/dist/src/tui/import/steps/09-review/components/QuitDialog.d.ts +8 -0
  14. package/dist/src/tui/import/steps/09-review/components/RationaleLine.d.ts +21 -0
  15. package/dist/src/tui/import/steps/09-review/components/RationalePanel.d.ts +15 -0
  16. package/dist/src/tui/import/steps/09-review/components/ReviewComponentPanel.d.ts +33 -0
  17. package/dist/src/tui/import/steps/09-review/components/ReviewDetailsEditor.d.ts +15 -0
  18. package/dist/src/tui/import/steps/09-review/components/ReviewDialogs.d.ts +28 -0
  19. package/dist/src/tui/import/steps/09-review/components/ReviewStatus.d.ts +15 -0
  20. package/dist/src/tui/import/steps/09-review/components/ScrollablePanel.d.ts +14 -0
  21. package/dist/src/tui/import/steps/09-review/components/TokenReviewPanel.d.ts +30 -0
  22. package/dist/src/tui/import/steps/09-review/components/removed-components-text.d.ts +7 -0
  23. package/dist/src/tui/import/steps/09-review/components/wrap-text.d.ts +1 -0
  24. package/dist/src/tui/import/steps/09-review/generate-review-step.d.ts +37 -0
  25. package/dist/src/tui/import/steps/09-review/graph/cycle-auto-reject.d.ts +4 -0
  26. package/dist/src/tui/import/steps/09-review/graph/cycle-view.d.ts +7 -0
  27. package/dist/src/tui/import/steps/09-review/graph/issue-inheritance.d.ts +8 -0
  28. package/dist/src/tui/import/steps/09-review/graph/selection-cascade.d.ts +3 -0
  29. package/dist/src/tui/import/steps/09-review/helpers/auto-reject-decision.d.ts +7 -0
  30. package/dist/src/tui/import/steps/09-review/helpers/breaking-change-format.d.ts +2 -0
  31. package/dist/src/tui/import/steps/09-review/helpers/cycle-panel-scroll.d.ts +8 -0
  32. package/dist/src/tui/import/steps/09-review/helpers/enumerate-cycle-breaks.d.ts +14 -0
  33. package/dist/src/tui/import/steps/09-review/helpers/sidebar-width.d.ts +1 -0
  34. package/dist/src/tui/import/steps/09-review/history.d.ts +23 -0
  35. package/dist/src/tui/import/steps/09-review/preview-annotations.d.ts +26 -0
  36. package/dist/src/tui/import/steps/09-review/review-details-panel.d.ts +26 -0
  37. package/dist/src/tui/import/steps/09-review/review-input.d.ts +39 -0
  38. package/dist/src/tui/import/steps/09-review/review-json-panel.d.ts +7 -0
  39. package/dist/src/tui/import/steps/09-review/run-live-preview.d.ts +45 -0
  40. package/dist/src/tui/import/steps/09-review/scroll-offset.d.ts +30 -0
  41. package/dist/src/tui/import/steps/09-review/session.d.ts +26 -0
  42. package/dist/src/tui/import/steps/09-review/theme.d.ts +9 -0
  43. package/dist/src/tui/import/steps/09-review/token-suggestions.d.ts +8 -0
  44. package/dist/src/tui/import/steps/09-review/types.d.ts +19 -0
  45. package/dist/src/tui/import/steps/09-review/use-finalize-preview.d.ts +39 -0
  46. package/dist/src/tui/import/steps/09-review/use-live-preview.d.ts +39 -0
  47. package/dist/src/tui/import/steps/09-review/use-review-editor.d.ts +47 -0
  48. package/dist/src/tui/import/steps/09-review/use-review-preview.d.ts +25 -0
  49. package/dist/src/tui/import/steps/09-review/use-review-session.d.ts +65 -0
  50. package/dist/src/tui/import/steps/09-review/use-review-surface-state.d.ts +12 -0
  51. package/dist/src/tui/import/steps/10-flow/components/CustomPromptBanner.d.ts +5 -0
  52. package/dist/src/tui/import/steps/10-flow/components/SpaceEnvironment.d.ts +7 -0
  53. package/dist/src/tui/import/steps/10-flow/components/StepHeader.d.ts +8 -0
  54. package/dist/src/tui/import/steps/10-flow/flow/build-flow-start.d.ts +21 -0
  55. package/dist/src/tui/import/steps/10-flow/flow/controller.d.ts +65 -0
  56. package/dist/src/tui/import/steps/10-flow/flow/preview.d.ts +56 -0
  57. package/dist/src/tui/import/steps/10-flow/flow/push.d.ts +43 -0
  58. package/dist/src/tui/import/steps/10-flow/flow/save.d.ts +50 -0
  59. package/dist/src/tui/import/steps/10-flow/flow/screen.d.ts +17 -0
  60. package/dist/src/tui/import/steps/10-flow/flow/types.d.ts +71 -0
  61. package/dist/src/tui/import/steps/10-flow/flow/use-flow.d.ts +9 -0
  62. package/dist/src/tui/import/steps/10-flow/screens/DoneStep.d.ts +28 -0
  63. package/dist/src/tui/import/steps/10-flow/screens/PathPrompt.d.ts +8 -0
  64. package/dist/src/tui/import/steps/10-flow/screens/PushingStep.d.ts +9 -0
  65. package/dist/src/tui/import/steps/10-flow/screens/WizardPreviewStep.d.ts +20 -0
  66. package/dist/src/tui/import/steps/10-flow/support/contentful-urls.d.ts +15 -0
  67. package/dist/src/tui/import/steps/10-flow/support/path-utils.d.ts +15 -0
  68. package/dist/src/tui/import/steps/10-flow/support/preview-confirmation-input.d.ts +5 -0
  69. package/dist/src/tui/import/steps/10-flow/support/preview-diff.d.ts +10 -0
  70. package/dist/src/tui/import/steps/10-flow/support/push-progress.d.ts +9 -0
  71. package/dist/src/tui/import/steps/10-flow/support/run-print-files-helpers.d.ts +26 -0
  72. package/dist/src/tui/import/steps/10-flow/support/run-teaser.d.ts +5 -0
  73. package/dist/src/tui/import/steps/10-flow/support/use-blinking-cursor.d.ts +1 -0
  74. package/dist/src/tui/import/steps/10-flow/support/use-timed-spinner.d.ts +4 -0
  75. package/dist/src/tui/import/steps/10-flow/support/wizard-state-transitions.d.ts +17 -0
  76. package/dist/src/tui/import/steps/10-flow/theme.d.ts +13 -0
  77. package/dist/src/tui/import/steps/preview-validation-error/logic.d.ts +12 -0
  78. package/dist/src/tui/import/steps/preview-validation-error/screen.d.ts +11 -0
  79. package/dist/src/tui/user-agent.d.ts +5 -0
  80. package/legacy/package.json +1 -1
  81. package/package.json +4 -4
  82. package/dist/src/tui/import/spawn-v1-import.d.ts +0 -36
  83. package/dist/src/tui/import/terminal-input.d.ts +0 -2
@@ -0,0 +1,45 @@
1
+ import type { ServerPreviewResponse } from '@contentful/experience-design-system-types';
2
+ export declare class TimeoutError extends Error {
3
+ constructor(message?: string);
4
+ }
5
+ export type LivePreviewResult = {
6
+ generation: number;
7
+ response: ServerPreviewResponse | null;
8
+ };
9
+ export type RunLivePreviewOptions = {
10
+ sessionId: string;
11
+ tokensPath: string;
12
+ spaceId: string;
13
+ environmentId: string;
14
+ cmaToken: string;
15
+ host: string;
16
+ generation: number;
17
+ timeoutMs?: number;
18
+ /** When true and no components are accepted, preview an empty-but-present
19
+ * components manifest so the server returns the full delete-all diff
20
+ * (every existing component as `removed`) instead of rejecting an empty
21
+ * manifest. Lets the final-review UI show what a push would delete. */
22
+ deleteAllComponents?: boolean;
23
+ /** Restrict the preview to these component keys (the operator's accepted
24
+ * set). Undefined = all generated components in the session. An empty set
25
+ * narrows to zero components — pair with `deleteAllComponents` to preview a
26
+ * full delete. Lets the Finalize dialog show exactly what the accepted push
27
+ * would delete, independent of the session's on-disk generated rows. */
28
+ acceptedKeys?: ReadonlySet<string>;
29
+ };
30
+ /**
31
+ * Pure async helper used by `useLivePreview` to re-fire `previewImport` after a
32
+ * FieldEditor save in the wizard's final-review step. A side-effect-bearing
33
+ * pure orchestrator that owns no React state.
34
+ *
35
+ * Skips silently (returns `{ response: null }`) when any of `spaceId`,
36
+ * `environmentId`, or `cmaToken` is missing — live preview is an enhancement
37
+ * and the caller treats `null` as a no-op. Throws on API errors so the caller
38
+ * (`useLivePreview`) can downgrade to local-only mode on 401/403 and log a
39
+ * warning otherwise. Wraps the API call in a timeout so a hung backend doesn't
40
+ * leave the spinner stuck.
41
+ *
42
+ * Does NOT run the second-pass seeding from `WizardApp.runPreview`; that's a
43
+ * one-shot wizard-step concern and would re-seed on every save.
44
+ */
45
+ export declare function runLivePreview(opts: RunLivePreviewOptions): Promise<LivePreviewResult>;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Pure helper for computing the next scroll offset when the operator presses
3
+ * a navigation key inside a scrollable TUI panel (JSON view, rationale view,
4
+ * etc.). Extracted as a shared module so multiple panels can reuse the same
5
+ * scroll bindings without duplicating logic.
6
+ *
7
+ * Returns the new offset, or `null` if the input doesn't match any scroll
8
+ * binding (caller should NOT update state in that case).
9
+ *
10
+ * Supported bindings:
11
+ * - downArrow → +1 line
12
+ * - upArrow → -1 line
13
+ * - Ctrl+d → +half-page (floor(panelHeight / 2))
14
+ * - Ctrl+u → -half-page
15
+ * - PageDown → +panelHeight
16
+ * - PageUp → -panelHeight
17
+ * - G → jump to maxOffset
18
+ *
19
+ * `j`/`k` are intentionally not handled here because they are field-navigation
20
+ * keys in the editor. `g` (single-tap) and `gg` (double-tap → jump to 0) are handled separately
21
+ * by the caller via a pending-flag ref, since they need transient state.
22
+ */
23
+ export type ScrollKeyState = {
24
+ upArrow?: boolean;
25
+ downArrow?: boolean;
26
+ pageUp?: boolean;
27
+ pageDown?: boolean;
28
+ ctrl?: boolean;
29
+ };
30
+ export declare function computeNextScrollOffset(current: number, input: string, key: ScrollKeyState, totalLines: number, panelHeight: number): number | null;
@@ -0,0 +1,26 @@
1
+ import type { DatabaseSync } from 'node:sqlite';
2
+ import type { HistorySnapshot } from './history.js';
3
+ import type { CdfReviewEntry, ReviewComponentStatus, TokenReviewToken } from './types.js';
4
+ export type ReviewSessionLoadResult<TExtra = undefined> = {
5
+ entries: CdfReviewEntry[];
6
+ tokens: TokenReviewToken[];
7
+ error: string | null;
8
+ extra?: TExtra;
9
+ };
10
+ export type ReviewSessionLoaderOptions<TExtra = undefined> = {
11
+ extractSessionId: string;
12
+ tokenSessionId?: string | null;
13
+ loadExtra?: (db: DatabaseSync, sessionId: string) => TExtra;
14
+ sortEntries: (entries: CdfReviewEntry[], extra: TExtra | undefined) => CdfReviewEntry[];
15
+ };
16
+ export declare function loadReviewSessionState<TExtra = undefined>({ extractSessionId, tokenSessionId, loadExtra, sortEntries, }: ReviewSessionLoaderOptions<TExtra>): ReviewSessionLoadResult<TExtra>;
17
+ export declare function createReviewHistorySnapshot(components: CdfReviewEntry[], options?: {
18
+ autoRejected?: readonly string[];
19
+ undoSnapshot?: ReadonlyMap<string, ReviewComponentStatus> | null;
20
+ }): HistorySnapshot;
21
+ export type ReviewFinalizeCounts = {
22
+ accepted: number;
23
+ rejected: number;
24
+ unresolved: number;
25
+ };
26
+ export declare function finalizeReviewSession(extractSessionId: string, components: CdfReviewEntry[]): ReviewFinalizeCounts;
@@ -0,0 +1,9 @@
1
+ export declare const PALETTE: {
2
+ readonly info: "#1773EB";
3
+ readonly success: "#00C459";
4
+ readonly error: "#E44F20";
5
+ readonly warning: "#FFDA00";
6
+ readonly muted: "#8B8D91";
7
+ readonly border: "#C4D1DE";
8
+ readonly inverse: "#FFFFFF";
9
+ };
@@ -0,0 +1,8 @@
1
+ import type { CDFComponentEntry } from '@contentful/experience-design-system-types';
2
+ import type { TokenPropSuggestion, TokenReviewToken } from './types.js';
3
+ /**
4
+ * Design-token props on `entry` with a declared token kind. `paths` is the
5
+ * full compatible token universe when a token catalog is available; `allowed`
6
+ * remains the current subset.
7
+ */
8
+ export declare function collectTokenSuggestions(entry: CDFComponentEntry, availableTokens?: TokenReviewToken[]): TokenPropSuggestion[];
@@ -0,0 +1,19 @@
1
+ import type { CDFComponentEntry } from '@contentful/experience-design-system-types';
2
+ export type ReviewComponentStatus = 'needs-review' | 'reviewed' | 'accepted' | 'rejected';
3
+ export type CdfReviewEntry = {
4
+ key: string;
5
+ entry: CDFComponentEntry;
6
+ status: ReviewComponentStatus;
7
+ };
8
+ export type ReviewPanel = 'none' | 'prop-rationale' | 'component-rationale' | 'source' | 'token-review';
9
+ export type TokenReviewToken = {
10
+ path: string;
11
+ kind: string;
12
+ };
13
+ export type TokenPropSuggestion = {
14
+ propName: string;
15
+ paths: string[];
16
+ suggested: string[];
17
+ allowed: string[];
18
+ };
19
+ export type PreviewAnnotation = 'new' | 'changed' | 'removed' | 'breaking';
@@ -0,0 +1,39 @@
1
+ import type { ComponentTypeSummary } from '@contentful/experience-design-system-types';
2
+ type FinalizePreviewStatus = 'idle' | 'running' | 'done' | 'error';
3
+ export type UseFinalizePreviewOptions = {
4
+ /** True while the Finalize dialog is open. Toggling true (re)fires the preview. */
5
+ open: boolean;
6
+ extractSessionId: string | null;
7
+ tokensPath: string;
8
+ spaceId: string;
9
+ environmentId: string;
10
+ cmaToken: string;
11
+ host: string;
12
+ /** Component keys the operator has accepted; drives the scoped preview. */
13
+ acceptedKeys: ReadonlySet<string>;
14
+ };
15
+ export type UseFinalizePreviewReturn = {
16
+ status: FinalizePreviewStatus;
17
+ removed: ComponentTypeSummary[];
18
+ scrollOffset: number;
19
+ /** Adjust the removed-list scroll (clamped to the window). */
20
+ scrollBy: (delta: number) => void;
21
+ };
22
+ export type UseReviewFinalizePreviewOptions = Omit<UseFinalizePreviewOptions, 'acceptedKeys'> & {
23
+ components: ReadonlyArray<{
24
+ key: string;
25
+ status: string;
26
+ }>;
27
+ };
28
+ export declare function useReviewFinalizePreview({ components, ...options }: UseReviewFinalizePreviewOptions): UseFinalizePreviewReturn;
29
+ /**
30
+ * Shared Finalize-dialog preview, used by both the composite and atomic
31
+ * generate-review steps.
32
+ *
33
+ * When the dialog opens it fires a preview scoped to the ACCEPTED set (so the
34
+ * result reflects exactly what the push does, independent of the session's
35
+ * not-yet-reclassified generated rows), tracks loading/error, and owns the
36
+ * scroll offset for the preview list.
37
+ */
38
+ export declare function useFinalizePreview(opts: UseFinalizePreviewOptions): UseFinalizePreviewReturn;
39
+ export {};
@@ -0,0 +1,39 @@
1
+ import type { ServerPreviewResponse } from '@contentful/experience-design-system-types';
2
+ export type UseLivePreviewOptions = {
3
+ enabled: boolean;
4
+ sessionId: string;
5
+ tokensPath: string;
6
+ spaceId: string;
7
+ environmentId: string;
8
+ cmaToken: string;
9
+ host: string;
10
+ onResult: (response: ServerPreviewResponse | null) => void;
11
+ debounceMs?: number;
12
+ /** Preview an empty-but-present CDF document (delete-all diff) when nothing
13
+ * is accepted, so the final-review UI can show what a push would delete. */
14
+ deleteAllComponents?: boolean;
15
+ };
16
+ type LivePreviewStatus = 'idle' | 'running';
17
+ export type UseLivePreviewReturn = {
18
+ trigger: () => void;
19
+ status: LivePreviewStatus;
20
+ disabled: boolean;
21
+ };
22
+ /**
23
+ * Hook that owns the post-save live-preview side effect for the wizard's
24
+ * final-review step. Centralizes:
25
+ *
26
+ * - 500ms debounce so rapid Ctrl+S spam collapses to a single API call.
27
+ * - Generation tag on every fire so a stale in-flight call's response is
28
+ * discarded if a newer fire has already kicked off (in lieu of an
29
+ * AbortController for v1).
30
+ * - Disable-for-session on 401/403: subsequent triggers no-op until the
31
+ * wizard exits. One-line stderr warning. No modal, no re-prompt — the
32
+ * operator is mid-edit and we must not interrupt the flow.
33
+ * - Status state for the sidebar spinner (`'idle' | 'running'`).
34
+ *
35
+ * Cred-missing / disabled / not-enabled cases short-circuit BEFORE the timer
36
+ * is set so we don't accumulate dead timers.
37
+ */
38
+ export declare function useLivePreview(opts: UseLivePreviewOptions): UseLivePreviewReturn;
39
+ export {};
@@ -0,0 +1,47 @@
1
+ import { type Dispatch, type SetStateAction } from 'react';
2
+ import type { CdfReviewEntry, ReviewPanel, TokenPropSuggestion, TokenReviewToken } from './types.js';
3
+ type UseReviewEditorOptions = {
4
+ components: CdfReviewEntry[];
5
+ selectedIdx: number;
6
+ extractSessionId: string;
7
+ availableTokens: TokenReviewToken[];
8
+ setComponents: Dispatch<SetStateAction<CdfReviewEntry[]>>;
9
+ pushHistorySnapshot: (entries: CdfReviewEntry[], label: string) => void;
10
+ onEditSaved: (entries: CdfReviewEntry[]) => void;
11
+ onTokenSaved: (entries: CdfReviewEntry[]) => void;
12
+ };
13
+ export type UseReviewEditorResult = {
14
+ panelOpen: ReviewPanel;
15
+ setPanelOpen: Dispatch<SetStateAction<ReviewPanel>>;
16
+ panelScrollOffset: number;
17
+ setPanelScrollOffset: Dispatch<SetStateAction<number>>;
18
+ jsonScrollOffset: number;
19
+ setJsonScrollOffset: Dispatch<SetStateAction<number>>;
20
+ textEntryActive: boolean;
21
+ setTextEntryActive: Dispatch<SetStateAction<boolean>>;
22
+ showJson: boolean;
23
+ setShowJson: Dispatch<SetStateAction<boolean>>;
24
+ showHiddenProps: boolean;
25
+ setShowHiddenProps: Dispatch<SetStateAction<boolean>>;
26
+ draftValue: string;
27
+ setDraftValue: Dispatch<SetStateAction<string>>;
28
+ saveError: string | null;
29
+ setSaveError: Dispatch<SetStateAction<string | null>>;
30
+ tokenReviewRow: number;
31
+ setTokenReviewRow: Dispatch<SetStateAction<number>>;
32
+ tokenReviewEditing: boolean;
33
+ setTokenReviewEditing: Dispatch<SetStateAction<boolean>>;
34
+ tokenReviewEditCursor: number;
35
+ setTokenReviewEditCursor: Dispatch<SetStateAction<number>>;
36
+ tokenReviewEditSelection: Set<string>;
37
+ setTokenReviewEditSelection: Dispatch<SetStateAction<Set<string>>>;
38
+ pendingGRef: {
39
+ current: boolean;
40
+ };
41
+ currentTokenSuggestions: () => TokenPropSuggestion[];
42
+ handleEditSave: () => void;
43
+ handleEditDiscard: () => void;
44
+ handleTokenEditSave: (suggestion: TokenPropSuggestion) => void;
45
+ };
46
+ export declare function useReviewEditor({ components, selectedIdx, extractSessionId, availableTokens, setComponents, pushHistorySnapshot, onEditSaved, onTokenSaved, }: UseReviewEditorOptions): UseReviewEditorResult;
47
+ export {};
@@ -0,0 +1,25 @@
1
+ import type { ComponentTypeSummary, ServerPreviewResponse } from '@contentful/experience-design-system-types';
2
+ import type { PreviewAnnotation } from './types.js';
3
+ import { type UseLivePreviewReturn } from './use-live-preview.js';
4
+ export type UseReviewPreviewOptions = {
5
+ components: ReadonlyArray<{
6
+ key: string;
7
+ }>;
8
+ loading: boolean;
9
+ livePreview: boolean;
10
+ sessionId: string;
11
+ tokensPath: string;
12
+ spaceId: string;
13
+ environmentId: string;
14
+ cmaToken: string;
15
+ host: string;
16
+ deleteAllComponents?: boolean;
17
+ onResult?: (response: ServerPreviewResponse) => void;
18
+ };
19
+ export type UseReviewPreviewResult = {
20
+ previewAnnotations: Map<string, PreviewAnnotation>;
21
+ removedComponents: ComponentTypeSummary[];
22
+ livePreviewHook: UseLivePreviewReturn;
23
+ livePreviewSpinner: string;
24
+ };
25
+ export declare function useReviewPreview({ components, loading, livePreview, sessionId, tokensPath, spaceId, environmentId, cmaToken, host, deleteAllComponents, onResult, }: UseReviewPreviewOptions): UseReviewPreviewResult;
@@ -0,0 +1,65 @@
1
+ import { type Dispatch, type SetStateAction } from 'react';
2
+ import { type ComponentRationale, type ComponentReviewMetadata } from '@contentful/experience-design-system-backend-pipeline';
3
+ import { type HistorySnapshot } from './history.js';
4
+ import { type ReviewSessionLoadResult } from './session.js';
5
+ import type { CdfReviewEntry, TokenReviewToken } from './types.js';
6
+ type UseReviewSessionOptions<TExtra> = {
7
+ loadSession: () => ReviewSessionLoadResult<TExtra>;
8
+ tokensPath?: string;
9
+ onExtraLoaded?: (extra: TExtra | undefined) => void;
10
+ };
11
+ type UseReviewSessionResult<TExtra> = {
12
+ components: CdfReviewEntry[];
13
+ setComponents: Dispatch<SetStateAction<CdfReviewEntry[]>>;
14
+ loading: boolean;
15
+ loadError: string | null;
16
+ availableTokens: TokenReviewToken[];
17
+ reloadFromSave: () => ReviewSessionLoadResult<TExtra> | null;
18
+ };
19
+ export declare function useReviewSession<TExtra = undefined>({ loadSession, tokensPath, onExtraLoaded, }: UseReviewSessionOptions<TExtra>): UseReviewSessionResult<TExtra>;
20
+ type UseReviewMetadataOptions = {
21
+ components: CdfReviewEntry[];
22
+ selectedIdx: number;
23
+ extractSessionId: string;
24
+ };
25
+ export declare function useReviewMetadata({ components, selectedIdx, extractSessionId }: UseReviewMetadataOptions): {
26
+ reviewMetadata: ComponentReviewMetadata | null;
27
+ componentRationale: ComponentRationale | null;
28
+ };
29
+ type UseReviewHistoryOptions = {
30
+ loading: boolean;
31
+ components: CdfReviewEntry[];
32
+ createSnapshot: (components: CdfReviewEntry[]) => HistorySnapshot;
33
+ applySnapshot: (snapshot: HistorySnapshot) => void;
34
+ };
35
+ export declare function useReviewHistory({ loading, components, createSnapshot, applySnapshot }: UseReviewHistoryOptions): {
36
+ historySeededRef: {
37
+ current: boolean;
38
+ };
39
+ pushHistorySnapshot: (entries: CdfReviewEntry[], label: string) => void;
40
+ handleUndo: () => void;
41
+ handleRedo: () => void;
42
+ resetHistory: (snapshot: HistorySnapshot) => void;
43
+ };
44
+ export type UseReviewFinalizeOptions = {
45
+ showFinalize: boolean;
46
+ extractSessionId: string;
47
+ tokensPath: string;
48
+ spaceId: string;
49
+ environmentId: string;
50
+ cmaToken: string;
51
+ host: string;
52
+ components: CdfReviewEntry[];
53
+ onFinalize: (accepted: number, rejected: number, unresolved: number) => void;
54
+ };
55
+ /**
56
+ * Shared by both the composite and atomic generate-review steps: the Finalize
57
+ * dialog's scoped preview (`useReviewFinalizePreview`) plus the confirm
58
+ * handler that reclassifies rejected/unresolved components and reports the
59
+ * final counts back to the wizard.
60
+ */
61
+ export declare function useReviewFinalize({ showFinalize, extractSessionId, tokensPath, spaceId, environmentId, cmaToken, host, components, onFinalize, }: UseReviewFinalizeOptions): {
62
+ finalizePreview: import("./use-finalize-preview.js").UseFinalizePreviewReturn;
63
+ handleFinalizeConfirm: () => void;
64
+ };
65
+ export {};
@@ -0,0 +1,12 @@
1
+ import { type Dispatch, type SetStateAction } from 'react';
2
+ export type UseReviewSurfaceStateResult = {
3
+ sidebarFocused: boolean;
4
+ setSidebarFocused: Dispatch<SetStateAction<boolean>>;
5
+ showFinalize: boolean;
6
+ setShowFinalize: Dispatch<SetStateAction<boolean>>;
7
+ showQuit: boolean;
8
+ setShowQuit: Dispatch<SetStateAction<boolean>>;
9
+ finalizeError: string | null;
10
+ setFinalizeError: Dispatch<SetStateAction<string | null>>;
11
+ };
12
+ export declare function useReviewSurfaceState(initialFinalizeError?: string | null): UseReviewSurfaceStateResult;
@@ -0,0 +1,5 @@
1
+ import React from 'react';
2
+ export interface CustomPromptBannerProps {
3
+ generatePromptPath?: string;
4
+ }
5
+ export declare function CustomPromptBanner({ generatePromptPath }: CustomPromptBannerProps): React.ReactElement | null;
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ type SpaceEnvironmentProps = {
3
+ spaceId: string;
4
+ environmentId: string;
5
+ };
6
+ export declare function SpaceEnvironment({ spaceId, environmentId }: SpaceEnvironmentProps): React.ReactElement;
7
+ export {};
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ type StepHeaderProps = {
3
+ stepNumber: number;
4
+ totalSteps: number;
5
+ title: string;
6
+ };
7
+ export declare function StepHeader({ stepNumber, totalSteps, title }: StepHeaderProps): React.ReactElement;
8
+ export {};
@@ -0,0 +1,21 @@
1
+ import type { ImportHandoff } from '@contentful/experience-design-system-types/handoff';
2
+ import type { ExtractionInput } from '../../06-extraction/types.js';
3
+ import type { FlowStart } from './controller.js';
4
+ interface SavedCredentials {
5
+ spaceId?: string;
6
+ environmentId?: string;
7
+ cmaToken?: string;
8
+ host?: string;
9
+ }
10
+ /**
11
+ * What the flow starts from. The credentials are the ones the user confirmed. When they skipped validation there are none
12
+ * to use, so the saved ones stand in, which is what the wizard did: it always read them from the store. The review's
13
+ * live preview and the push use them.
14
+ */
15
+ export declare function buildFlowStart(input: {
16
+ extraction: ExtractionInput;
17
+ handoff: ImportHandoff;
18
+ saved?: SavedCredentials;
19
+ generatePromptPath?: string;
20
+ }): FlowStart;
21
+ export {};
@@ -0,0 +1,65 @@
1
+ import { type PreviewValidationError } from '@contentful/experience-design-system-backend-pipeline';
2
+ import type { ImportHandoff } from '@contentful/experience-design-system-types/handoff';
3
+ import { type PreviewDeps } from './preview.js';
4
+ import { type PushDeps } from './push.js';
5
+ import { type SaveDeps } from './save.js';
6
+ import { type FlowPatch, type FlowState } from './types.js';
7
+ /** What the flow starts from: what the earlier stages produced, and the user's saved settings. */
8
+ export interface FlowStart {
9
+ handoff: ImportHandoff;
10
+ agent: string;
11
+ projectPath: string;
12
+ /** Where the files are saved by default. */
13
+ outDir: string;
14
+ rawTokensPath: string;
15
+ credentials: {
16
+ spaceId: string;
17
+ environmentId: string;
18
+ cmaToken: string;
19
+ host: string;
20
+ };
21
+ /** A custom prompt for `generate components`, shown as a warning above every step. */
22
+ generatePromptPath?: string;
23
+ }
24
+ /** The outside world the flow talks to besides the preview, push and save steps. */
25
+ export interface FlowDeps {
26
+ preview: PreviewDeps;
27
+ push: PushDeps;
28
+ save: SaveDeps;
29
+ /** Reads the accepted components, for the cycle check at finalize. */
30
+ loadAcceptedComponents: (sessionId: string) => Array<{
31
+ key: string;
32
+ entry: unknown;
33
+ }>;
34
+ mkdir: (path: string) => Promise<void>;
35
+ detectSaveConflict: (path: string) => Promise<boolean>;
36
+ buildTimestampedSubdir: (path: string) => string;
37
+ rejectComponentsByName: (sessionId: string, names: string[]) => Promise<unknown>;
38
+ /** Writes one line of the wizard's step log. */
39
+ log: (entry: Record<string, unknown>) => void;
40
+ stderr: (text: string) => void;
41
+ }
42
+ export declare function startWizardLog(): void;
43
+ export declare function realFlowDeps(): FlowDeps;
44
+ /** The state the flow begins in, from what the earlier stages handed over. */
45
+ export declare function initialFlowState(start: FlowStart): FlowState;
46
+ /** What the log gets: the state change without the token, the document, or the whole of a large server response. */
47
+ export declare function sanitizeForLog(partial: FlowPatch): Record<string, unknown>;
48
+ /** The names of the components the errors are about, once each. */
49
+ export declare function namesToSkip(errors: readonly PreviewValidationError[]): string[];
50
+ export interface FlowController {
51
+ getState(): FlowState;
52
+ subscribe(listener: () => void): () => void;
53
+ finalize(accepted: number, rejected: number, unresolved: number): void;
54
+ submitPath(path: string): Promise<void>;
55
+ confirmPreview(acknowledgeBreakingChanges: boolean): void;
56
+ acknowledgeBreakingChanges(): void;
57
+ editDefinitions(): void;
58
+ skipValidationErrors(): Promise<void>;
59
+ }
60
+ /**
61
+ * The wizard's state machine, taken out of the screen so each transition can be tested without a terminal. It holds the
62
+ * state, applies the patches the steps return, and decides what runs next. It never exits the process: leaving is the
63
+ * screen's decision.
64
+ */
65
+ export declare function createFlowController(start: FlowStart, deps: FlowDeps): FlowController;
@@ -0,0 +1,56 @@
1
+ import type { DatabaseSync } from 'node:sqlite';
2
+ import { ApiError, patchReviewStateWithValidationErrors, type PreviewValidationError } from '@contentful/experience-design-system-backend-pipeline';
3
+ import { type CDFDocument, type DTCGTokenEntry, type ServerPreviewResponse } from '@contentful/experience-design-system-types';
4
+ import type { FlowPatch, FlowState } from './types.js';
5
+ type PreviewClient = {
6
+ previewImport(cdf: CDFDocument): Promise<ServerPreviewResponse>;
7
+ };
8
+ /** The outside world `runPreview` talks to, so each branch can be tested without a database or a network. */
9
+ export interface PreviewDeps {
10
+ createClient: (options: {
11
+ cmaToken: string;
12
+ spaceId: string;
13
+ environmentId: string;
14
+ host: string;
15
+ }) => PreviewClient;
16
+ openDb: () => DatabaseSync;
17
+ readTokens: (path: string) => Promise<DTCGTokenEntry[]>;
18
+ patchReviewState: typeof patchReviewStateWithValidationErrors;
19
+ verboseErrors: boolean;
20
+ }
21
+ export declare const realPreviewDeps: () => PreviewDeps;
22
+ export interface RunPreviewInput {
23
+ state: Pick<FlowState, 'credentialsSkipped'>;
24
+ extractSessionId: string | null;
25
+ tokensPath: string;
26
+ spaceId: string;
27
+ environmentId: string;
28
+ cmaToken: string;
29
+ host: string;
30
+ /** Set when nothing was accepted, so the document is present but empty and the server shows what would be deleted. */
31
+ deleteAll: boolean;
32
+ }
33
+ /** What to do with a 422 from the preview: show the components that failed, or fall through to the generic error. */
34
+ type Preview422Outcome = {
35
+ kind: 'validation-error';
36
+ errors: PreviewValidationError[];
37
+ missingNames: string[];
38
+ } | {
39
+ kind: 'unparseable';
40
+ message: string;
41
+ } | {
42
+ kind: 'not-422';
43
+ };
44
+ export declare function handlePreview422(err: ApiError, extractSessionId: string | null, patchFn: PreviewDeps['patchReviewState']): Promise<Preview422Outcome>;
45
+ /** The patch to spread into any update that leaves the validation error step, so stale errors do not linger. */
46
+ export declare function clearedValidationErrorState(): Pick<FlowState, 'previewValidationErrors' | 'previewValidationMissingNames'>;
47
+ /**
48
+ * Loads what would be pushed and asks the server what that would change. Returns the patch the wizard applied: the
49
+ * preview gate, a terminal "done" when nothing would change, the validation error step for a 422, or an error.
50
+ *
51
+ * It also repairs two things the server's answer can reveal: components it says would be removed that are in fact local
52
+ * (the review dropped their CDF), and defaults it would change. Both are re-seeded from the response, and the preview is
53
+ * taken again.
54
+ */
55
+ export declare function runPreview(input: RunPreviewInput, deps: PreviewDeps): Promise<FlowPatch>;
56
+ export {};
@@ -0,0 +1,43 @@
1
+ import { updateRun } from '@contentful/experience-design-system-backend-pipeline';
2
+ import { type ApplyOperationResponse, type CDFDocument, type ServerPreviewResponse } from '@contentful/experience-design-system-types';
3
+ import type { FlowPatch, FlowState } from './types.js';
4
+ type PushClient = {
5
+ applyImport(cdf: CDFDocument, options: {
6
+ acknowledgeBreakingChanges: boolean;
7
+ }): Promise<ApplyOperationResponse>;
8
+ pollOperation(operationId: string, options: {
9
+ onProgress?: (operation: ApplyOperationResponse) => void;
10
+ }): Promise<ApplyOperationResponse>;
11
+ };
12
+ /** The outside world `runPush` talks to, so each branch can be tested without a network or a run history. */
13
+ export interface PushDeps {
14
+ createClient: (options: {
15
+ cmaToken: string;
16
+ spaceId: string;
17
+ environmentId: string;
18
+ host: string;
19
+ }) => PushClient;
20
+ updateRun: typeof updateRun;
21
+ /** Where the wizard's step log goes. A log that cannot be written is reported on stderr and never stops the push. */
22
+ log: (entry: Record<string, unknown>) => void;
23
+ warn: (message: string) => void;
24
+ verboseErrors: boolean;
25
+ }
26
+ export declare const realPushDeps: (log: PushDeps["log"]) => PushDeps;
27
+ export interface RunPushInput {
28
+ state: Pick<FlowState, 'credentialsSkipped' | 'lastRunId'>;
29
+ cdf: CDFDocument;
30
+ spaceId: string;
31
+ environmentId: string;
32
+ cmaToken: string;
33
+ host: string;
34
+ acknowledgeBreakingChanges: boolean;
35
+ preview?: ServerPreviewResponse | null;
36
+ }
37
+ /**
38
+ * Pushes the previewed document: the checks that refuse a push that cannot work, then the apply, polling its progress,
39
+ * and the result as the counts the done screen shows. `onPatch` receives the progress while it polls; the returned patch
40
+ * is where the flow ends up.
41
+ */
42
+ export declare function runPush(input: RunPushInput, deps: PushDeps, onPatch: (patch: FlowPatch) => void): Promise<FlowPatch>;
43
+ export {};
@@ -0,0 +1,50 @@
1
+ import type { DatabaseSync } from 'node:sqlite';
2
+ import { appendRun, buildSourceFingerprint } from '@contentful/experience-design-system-backend-pipeline';
3
+ import { type CDFComponentEntry, type CDFDocument, type DTCGTokenEntry } from '@contentful/experience-design-system-types';
4
+ import type { FlowPatch, FlowState } from './types.js';
5
+ /** How long the confirmation of a written file stays up before the flow moves on to the preview. */
6
+ export declare const SAVE_CONFIRMATION_DELAY_MS = 1000;
7
+ /** The document written to `components.json`: the components and tokens as one schema-valid CDF. */
8
+ export declare function buildSavedCDF(components: Array<{
9
+ key: string;
10
+ entry: CDFComponentEntry;
11
+ }>, tokens: DTCGTokenEntry[], opts?: {
12
+ deleteAll?: boolean;
13
+ }): CDFDocument;
14
+ /** The outside world saving talks to, so each branch can be tested without a disk, a database or a clock. */
15
+ export interface SaveDeps {
16
+ openDb: () => DatabaseSync;
17
+ readTokens: (path: string) => Promise<DTCGTokenEntry[]>;
18
+ writeFile: (path: string, contents: string) => Promise<void>;
19
+ appendRun: typeof appendRun;
20
+ buildSourceFingerprint: typeof buildSourceFingerprint;
21
+ sleep: (ms: number) => Promise<void>;
22
+ warn: (message: string) => void;
23
+ }
24
+ export declare const realSaveDeps: () => SaveDeps;
25
+ export interface WriteFilesInput {
26
+ extractSessionId: string | null;
27
+ outDir: string;
28
+ tokenSessionId?: string | null;
29
+ tokensPath?: string;
30
+ skipGate?: boolean;
31
+ allowEmpty?: boolean;
32
+ }
33
+ /**
34
+ * Writes `components.json` to `outDir`. Returns the patch for the step after (the print gate, or nothing when the save
35
+ * is part of a push and goes straight on), or an error patch when the document could not be built or written.
36
+ * `onPatch` receives the "printing" step while it works.
37
+ */
38
+ export declare function runPrintFiles(input: WriteFilesInput, deps: SaveDeps, onPatch: (patch: FlowPatch) => void): Promise<{
39
+ ok: true;
40
+ patch: FlowPatch;
41
+ } | {
42
+ ok: false;
43
+ patch: FlowPatch;
44
+ }>;
45
+ export interface RecordRunInput {
46
+ state: Pick<FlowState, 'extractSessionId' | 'rawTokensPath' | 'projectPath' | 'generatedAcceptedCount' | 'generatedCount' | 'tokenCount' | 'tokenSessionId' | 'tokensPath' | 'agent' | 'generateSessionId'>;
47
+ savePath: string;
48
+ }
49
+ /** Records the run, so it can be found and pushed later. A run that cannot be recorded is warned about, never fatal. */
50
+ export declare function recordRun(input: RecordRunInput, deps: SaveDeps): Promise<string | null>;