@contentful/experience-design-system-cli 2.12.4-dev-build-ff57340.0 → 2.13.1-dev-build-fa478b3.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 (55) hide show
  1. package/dist/package.json +3 -6
  2. package/dist/src/analyze/command.js +2 -22
  3. package/dist/src/analyze/select/command.js +1 -1
  4. package/dist/src/analyze/select/tui/components/FieldEditor.d.ts +1 -24
  5. package/dist/src/analyze/select/tui/components/FieldEditor.js +10 -137
  6. package/dist/src/analyze/select-agent/command.js +1 -1
  7. package/dist/src/apply/command.d.ts +1 -34
  8. package/dist/src/apply/command.js +0 -81
  9. package/dist/src/import/tui/WizardApp.js +10 -59
  10. package/dist/src/import/tui/steps/GenerateReviewStep.d.ts +1 -1
  11. package/dist/src/import/tui/steps/GenerateReviewStep.js +23 -213
  12. package/dist/src/import/tui/steps/WizardPreviewStep.d.ts +0 -10
  13. package/dist/src/import/tui/steps/WizardPreviewStep.js +51 -95
  14. package/dist/src/import/tui/steps/preview-diff.js +0 -48
  15. package/dist/src/session/db.d.ts +0 -9
  16. package/dist/src/session/db.js +0 -46
  17. package/dist/src/types.d.ts +2 -76
  18. package/dist/src/types.js +1 -4
  19. package/package.json +3 -6
  20. package/dist/src/analyze/cycle-detection.d.ts +0 -93
  21. package/dist/src/analyze/cycle-detection.js +0 -326
  22. package/dist/src/analyze/extract/astro.d.ts +0 -5
  23. package/dist/src/analyze/extract/astro.js +0 -289
  24. package/dist/src/analyze/extract/non-authorable-filter.d.ts +0 -16
  25. package/dist/src/analyze/extract/non-authorable-filter.js +0 -60
  26. package/dist/src/analyze/extract/pipeline.d.ts +0 -6
  27. package/dist/src/analyze/extract/pipeline.js +0 -314
  28. package/dist/src/analyze/extract/react.d.ts +0 -2
  29. package/dist/src/analyze/extract/react.js +0 -2041
  30. package/dist/src/analyze/extract/scoring.d.ts +0 -12
  31. package/dist/src/analyze/extract/scoring.js +0 -108
  32. package/dist/src/analyze/extract/slot-allowed-components.d.ts +0 -8
  33. package/dist/src/analyze/extract/slot-allowed-components.js +0 -40
  34. package/dist/src/analyze/extract/slot-detection.d.ts +0 -35
  35. package/dist/src/analyze/extract/slot-detection.js +0 -101
  36. package/dist/src/analyze/extract/source-inspection.d.ts +0 -13
  37. package/dist/src/analyze/extract/source-inspection.js +0 -189
  38. package/dist/src/analyze/extract/stencil.d.ts +0 -2
  39. package/dist/src/analyze/extract/stencil.js +0 -296
  40. package/dist/src/analyze/extract/svelte.d.ts +0 -5
  41. package/dist/src/analyze/extract/svelte.js +0 -1626
  42. package/dist/src/analyze/extract/tsx-shared.d.ts +0 -8
  43. package/dist/src/analyze/extract/tsx-shared.js +0 -263
  44. package/dist/src/analyze/extract/validate.d.ts +0 -16
  45. package/dist/src/analyze/extract/validate.js +0 -94
  46. package/dist/src/analyze/extract/vue-tsx.d.ts +0 -2
  47. package/dist/src/analyze/extract/vue-tsx.js +0 -498
  48. package/dist/src/analyze/extract/vue.d.ts +0 -5
  49. package/dist/src/analyze/extract/vue.js +0 -653
  50. package/dist/src/analyze/extract/web-components.d.ts +0 -2
  51. package/dist/src/analyze/extract/web-components.js +0 -876
  52. package/dist/src/analyze/pre-classify.d.ts +0 -17
  53. package/dist/src/analyze/pre-classify.js +0 -211
  54. package/dist/src/apply/error-parser.d.ts +0 -43
  55. package/dist/src/apply/error-parser.js +0 -163
@@ -1,17 +0,0 @@
1
- import type { RawPropDefinition, RawComponentDefinition } from '../types.js';
2
- export interface PreClassification {
3
- category: 'content' | 'design' | 'state' | 'exclude';
4
- cdfTypeHint?: 'string' | 'enum' | 'richtext' | 'media' | 'boolean';
5
- }
6
- /**
7
- * Deterministic pre-classification rule engine.
8
- * Applies rules in priority order and returns on the first match.
9
- */
10
- export declare function preClassifyProp(prop: RawPropDefinition): PreClassification | undefined;
11
- /**
12
- * Applies pre-classification to all props in a component definition.
13
- * - Leaves existing category values unchanged
14
- * - Sets category for content/design/state matches
15
- * - Does NOT set category for 'exclude' results (leaves undefined)
16
- */
17
- export declare function preClassifyComponent(component: RawComponentDefinition): RawComponentDefinition;
@@ -1,211 +0,0 @@
1
- /**
2
- * Determines whether a type string represents a simple/primitive type
3
- * (string, boolean, number, or string literal union) vs a complex type
4
- * (object, function, array, generic, etc.).
5
- */
6
- function isSimpleType(type) {
7
- const t = type.trim();
8
- if (t === 'string' || t === 'boolean' || t === 'number')
9
- return true;
10
- // String literal union (e.g., "'a' | 'b'")
11
- if (isStringLiteralUnion(t))
12
- return true;
13
- return false;
14
- }
15
- function isStringLiteralUnion(type) {
16
- return type.includes('|') && type.includes("'");
17
- }
18
- function isBooleanType(type) {
19
- return type.trim() === 'boolean';
20
- }
21
- function isStringType(type) {
22
- return type.trim() === 'string';
23
- }
24
- function isNumberType(type) {
25
- return type.trim() === 'number';
26
- }
27
- function isComplexType(type) {
28
- return !isSimpleType(type);
29
- }
30
- const DOM_PASS_THROUGH_PROPS = new Set([
31
- // Bare HTML / framework styling pass-through
32
- 'className',
33
- 'class',
34
- 'classes',
35
- 'classNames',
36
- 'rootClassName',
37
- 'prefixCls',
38
- 'style',
39
- 'styles',
40
- // Bare HTML attributes
41
- 'id',
42
- 'role',
43
- 'tabIndex',
44
- 'tabindex',
45
- 'name',
46
- 'htmlFor',
47
- 'for',
48
- 'slot',
49
- 'is',
50
- 'lang',
51
- 'dir',
52
- 'hidden',
53
- 'draggable',
54
- 'spellCheck',
55
- 'spellcheck',
56
- 'contentEditable',
57
- 'contenteditable',
58
- 'inputMode',
59
- 'inputmode',
60
- 'autoComplete',
61
- 'autocomplete',
62
- 'autoFocus',
63
- 'autofocus',
64
- 'translate',
65
- 'part',
66
- 'exportparts',
67
- 'aria',
68
- // Framework theming / pass-through escape hatches — dev-facing, never marketer-configurable
69
- 'dt',
70
- 'pt',
71
- 'ptOptions',
72
- 'unstyled',
73
- // Polymorphic component props — change rendered HTML/component, not marketer-visible behavior
74
- 'as',
75
- 'element',
76
- 'component',
77
- // QA / vendor test attributes
78
- 'dataQa',
79
- 'data-qa',
80
- // Vue v-model internals — framework wiring, never marketer-configurable
81
- 'modelValue',
82
- 'modelModifiers',
83
- ]);
84
- function isDomPassThroughProp(name) {
85
- if (DOM_PASS_THROUGH_PROPS.has(name))
86
- return true;
87
- // aria-label, aria-hidden, ariaLabel, ariaHidden — both kebab and camel forms
88
- if (/^aria[-A-Z]/.test(name))
89
- return true;
90
- if (name.startsWith('data-'))
91
- return true;
92
- return false;
93
- }
94
- /**
95
- * Deterministic pre-classification rule engine.
96
- * Applies rules in priority order and returns on the first match.
97
- */
98
- export function preClassifyProp(prop) {
99
- const { name, type } = prop;
100
- // Rule 1: Event handlers
101
- // name starts with `on` + uppercase, OR type contains `=> void` or `EventHandler`
102
- if (/^on[A-Z]/.test(name) || type.includes('=> void') || type.includes('EventHandler')) {
103
- return { category: 'exclude' };
104
- }
105
- // Rule 2: Refs
106
- if (name === 'ref' || name === 'innerRef' || type.includes('Ref<') || type.includes('RefObject<')) {
107
- return { category: 'exclude' };
108
- }
109
- // Rule 3: Test IDs
110
- if (name === 'testId' || name === 'data-testid' || name === 'dataTestId') {
111
- return { category: 'exclude' };
112
- }
113
- // Rule 4: Key prop
114
- if (name === 'key') {
115
- return { category: 'exclude' };
116
- }
117
- // Rule 5: Dispatch/setter
118
- if (type.includes('Dispatch<') || type.includes('SetStateAction')) {
119
- return { category: 'exclude' };
120
- }
121
- // Rule 6: DOM / a11y / framework pass-through props
122
- // These are escape hatches developers use to wire components into the DOM.
123
- // Marketers should never configure them in the ExO editor; exposing them
124
- // generates noise that obscures the props that actually carry intent.
125
- if (isDomPassThroughProp(name)) {
126
- return { category: 'exclude' };
127
- }
128
- // Rule 7: String literal union
129
- if (isStringLiteralUnion(type)) {
130
- return { category: 'design', cdfTypeHint: 'enum' };
131
- }
132
- // Rule 8: Design name patterns (only for simple types)
133
- if (!isComplexType(type)) {
134
- const designNameStart = /^(variant|size|spacing|gap|color|bg|theme|align|layout|orientation|position)/i;
135
- const designNameEnd = /(Color|Size|Variant|Style)$/;
136
- if (designNameStart.test(name) || designNameEnd.test(name)) {
137
- return { category: 'design', cdfTypeHint: 'string' };
138
- }
139
- }
140
- // Rule 10: Boolean + state names (checked before rule 9 since state names
141
- // like "disabled" would otherwise match the visual toggle prefix "disable")
142
- if (isBooleanType(type)) {
143
- const stateNames = ['disabled', 'loading', 'expanded', 'isOpen', 'selected', 'checked', 'active', 'preview'];
144
- if (stateNames.includes(name)) {
145
- return { category: 'state', cdfTypeHint: 'boolean' };
146
- }
147
- }
148
- // Rule 9: Boolean + visual toggle name
149
- if (isBooleanType(type)) {
150
- const visualToggle = /^(hide|show|enable|disable|vertical|horizontal|reverse|bold|italic|imageOn|with)/i;
151
- if (visualToggle.test(name)) {
152
- return { category: 'design', cdfTypeHint: 'boolean' };
153
- }
154
- }
155
- // Rule 11: State identifiers
156
- if (name === 'componentId' || name === 'sectionKey' || name === 'locale' || name === 'variantIndex') {
157
- return { category: 'state', cdfTypeHint: 'string' };
158
- }
159
- // Rule 12: URL patterns (string type only)
160
- if (isStringType(type)) {
161
- const urlNameStart = /^(href|url|link|src)/i;
162
- const urlNameEnd = /(Url|Href|Link|Src)$/;
163
- if (urlNameStart.test(name) || urlNameEnd.test(name)) {
164
- return { category: 'content', cdfTypeHint: 'string' };
165
- }
166
- }
167
- // Rule 13: Text patterns (string type only)
168
- if (isStringType(type)) {
169
- const textNameStart = /^(label|title|text|description|caption|heading|subheading|body|alt|name|placeholder|summary)/i;
170
- const textNameEnd = /(Text|Label|Title|Name)$/;
171
- if (textNameStart.test(name) || textNameEnd.test(name)) {
172
- return { category: 'content', cdfTypeHint: 'string' };
173
- }
174
- }
175
- // Rule 14: Remaining strings
176
- if (isStringType(type)) {
177
- return { category: 'content', cdfTypeHint: 'string' };
178
- }
179
- // Rule 15: Remaining booleans
180
- if (isBooleanType(type)) {
181
- return { category: 'design', cdfTypeHint: 'boolean' };
182
- }
183
- // Rule 16: Remaining numbers
184
- if (isNumberType(type)) {
185
- return { category: 'design', cdfTypeHint: 'string' };
186
- }
187
- // Rule 17: Complex/object/function/array types — no hint
188
- return undefined;
189
- }
190
- /**
191
- * Applies pre-classification to all props in a component definition.
192
- * - Leaves existing category values unchanged
193
- * - Sets category for content/design/state matches
194
- * - Does NOT set category for 'exclude' results (leaves undefined)
195
- */
196
- export function preClassifyComponent(component) {
197
- const props = component.props.map((prop) => {
198
- // If category is already set, leave unchanged
199
- if (prop.category) {
200
- return prop;
201
- }
202
- const result = preClassifyProp(prop);
203
- // If no result or excluded, leave unchanged
204
- if (!result || result.category === 'exclude') {
205
- return prop;
206
- }
207
- // Set category hint
208
- return { ...prop, category: result.category };
209
- });
210
- return { ...component, props };
211
- }
@@ -1,43 +0,0 @@
1
- /**
2
- * INTEG-4401 Fix C — parse EDSI failure bodies into a structured shape the
3
- * TUI can render without dumping timestamps + trace ids at operators.
4
- *
5
- * EDSI failure bodies come in three broad shapes today:
6
- *
7
- * 1. Plain JSON error:
8
- * `{"code":"TopoSortCycleError","message":"...","cycle":["CycleA","CycleB"]}`
9
- *
10
- * 2. Wrapper JSON with `details`:
11
- * `{"sys":{"type":"Error"},"message":"...","details":{"code":"...","cycle":[...]}}`
12
- *
13
- * 3. Lambda log-line spill (the response body is the CloudWatch log
14
- * formatting the worker's uncaught exception):
15
- * `2026-07-07T22:26:26.479Z\t<request-id>\tERROR\t[dd.trace_id=... dd.span_id=...] <message> {\n operationId: '...',\n code: 'TopoSortCycleError',\n cycle: [ 'CycleA', 'CycleB' ]\n}`
16
- *
17
- * We parse each shape best-effort and fall back to a cleaned raw message so
18
- * the ErrorStep never has to show the operator a timestamp + trace id.
19
- */
20
- export interface ParsedEdsiError {
21
- /** Server-side error code, if we could extract one. */
22
- code: string | null;
23
- /** Human-readable message, stripped of log/trace decoration. */
24
- message: string;
25
- /** Cycle participants, when `code === 'TopoSortCycleError'`. */
26
- cycle: string[] | null;
27
- /** True when the message survived cleaning as-is (no parseable structure). */
28
- raw: boolean;
29
- }
30
- /**
31
- * Strip the Lambda/CloudWatch log-line decoration from the head of a body so
32
- * the operator-facing message reads as an error sentence, not a log entry.
33
- */
34
- export declare function stripLambdaLogPrefix(body: string): string;
35
- export declare function parseEdsiError(rawInput: string | undefined | null): ParsedEdsiError;
36
- /**
37
- * Render a parsed error into a short multi-line block for the ErrorStep.
38
- * Callers can pass `verbose: true` to include the raw body underneath.
39
- */
40
- export declare function formatParsedEdsiError(parsed: ParsedEdsiError, opts?: {
41
- verbose?: boolean;
42
- raw?: string;
43
- }): string;
@@ -1,163 +0,0 @@
1
- /**
2
- * INTEG-4401 Fix C — parse EDSI failure bodies into a structured shape the
3
- * TUI can render without dumping timestamps + trace ids at operators.
4
- *
5
- * EDSI failure bodies come in three broad shapes today:
6
- *
7
- * 1. Plain JSON error:
8
- * `{"code":"TopoSortCycleError","message":"...","cycle":["CycleA","CycleB"]}`
9
- *
10
- * 2. Wrapper JSON with `details`:
11
- * `{"sys":{"type":"Error"},"message":"...","details":{"code":"...","cycle":[...]}}`
12
- *
13
- * 3. Lambda log-line spill (the response body is the CloudWatch log
14
- * formatting the worker's uncaught exception):
15
- * `2026-07-07T22:26:26.479Z\t<request-id>\tERROR\t[dd.trace_id=... dd.span_id=...] <message> {\n operationId: '...',\n code: 'TopoSortCycleError',\n cycle: [ 'CycleA', 'CycleB' ]\n}`
16
- *
17
- * We parse each shape best-effort and fall back to a cleaned raw message so
18
- * the ErrorStep never has to show the operator a timestamp + trace id.
19
- */
20
- const LAMBDA_LOG_PREFIX_RE = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z\s+[0-9a-f-]+\s+ERROR\s+(?:\[dd\.[^\]]*\]\s*)?/;
21
- const DD_TAG_RE = /\[dd\.(?:trace_id|span_id)=[^\]]*\]\s*/g;
22
- /**
23
- * Strip the Lambda/CloudWatch log-line decoration from the head of a body so
24
- * the operator-facing message reads as an error sentence, not a log entry.
25
- */
26
- export function stripLambdaLogPrefix(body) {
27
- let out = body.replace(LAMBDA_LOG_PREFIX_RE, '');
28
- out = out.replace(DD_TAG_RE, '');
29
- return out.trim();
30
- }
31
- /**
32
- * Extract a JS-object-literal tail like `{ operationId: '...', code: '...', cycle: [ 'A', 'B' ] }`
33
- * that Lambda-spilled errors trail with. Returns `null` if no such structure
34
- * is present or the fields we care about can't be recovered.
35
- */
36
- function parseObjectLiteralTail(body) {
37
- const braceStart = body.lastIndexOf('{');
38
- if (braceStart === -1)
39
- return null;
40
- const tail = body.slice(braceStart);
41
- const codeMatch = tail.match(/code:\s*['"]([^'"]+)['"]/);
42
- const cycleMatch = tail.match(/cycle:\s*\[\s*([^\]]*)\s*\]/);
43
- if (!codeMatch && !cycleMatch)
44
- return null;
45
- const code = codeMatch ? codeMatch[1] : null;
46
- let cycle = null;
47
- if (cycleMatch) {
48
- cycle = cycleMatch[1]
49
- .split(',')
50
- .map((s) => s.trim().replace(/^['"]|['"]$/g, ''))
51
- .filter((s) => s.length > 0);
52
- if (cycle.length === 0)
53
- cycle = null;
54
- }
55
- return { code, cycle };
56
- }
57
- /**
58
- * Best-effort JSON parse walking one level deep into `details`. Fields we
59
- * accept anywhere in the top-level or `details` object: `code`, `message`,
60
- * `cycle`. Returns `null` when the input isn't JSON.
61
- */
62
- function parseJsonBody(body) {
63
- let parsed;
64
- try {
65
- parsed = JSON.parse(body);
66
- }
67
- catch {
68
- return null;
69
- }
70
- if (!parsed || typeof parsed !== 'object')
71
- return null;
72
- const p = parsed;
73
- const details = (p.details && typeof p.details === 'object' ? p.details : {});
74
- const pick = (k) => (p[k] !== undefined ? p[k] : details[k]);
75
- const codeRaw = pick('code');
76
- const messageRaw = pick('message');
77
- const cycleRaw = pick('cycle');
78
- const out = {};
79
- if (typeof codeRaw === 'string')
80
- out.code = codeRaw;
81
- if (typeof messageRaw === 'string')
82
- out.message = messageRaw;
83
- if (Array.isArray(cycleRaw)) {
84
- const strs = cycleRaw.filter((x) => typeof x === 'string');
85
- if (strs.length > 0)
86
- out.cycle = strs;
87
- }
88
- return out;
89
- }
90
- /**
91
- * Parse an EDSI error body (the raw response body, or an `ApiError.message`
92
- * that has the body appended). Always returns a value — the fallback is the
93
- * cleaned raw message with `code: null`.
94
- */
95
- // ApiError.message shape: `${phasePrefix}\n${body}` where phasePrefix looks
96
- // like `apply failed: 400`, `preview failed: 422`, `poll failed: 500`. We
97
- // only strip the prefix line when the first line matches this shape —
98
- // otherwise a raw body that happens to contain a newline (e.g. a Lambda log
99
- // spill with a multi-line object literal) gets truncated mid-structure.
100
- const API_ERROR_PREFIX_RE = /^(?:apply|preview|poll) failed: \d+$/;
101
- export function parseEdsiError(rawInput) {
102
- if (!rawInput)
103
- return { code: null, message: '', cycle: null, raw: true };
104
- const nlIndex = rawInput.indexOf('\n');
105
- let body = rawInput;
106
- let prefix = '';
107
- if (nlIndex !== -1) {
108
- const firstLine = rawInput.slice(0, nlIndex);
109
- if (API_ERROR_PREFIX_RE.test(firstLine)) {
110
- prefix = firstLine;
111
- body = rawInput.slice(nlIndex + 1);
112
- }
113
- }
114
- const cleaned = stripLambdaLogPrefix(body);
115
- const json = parseJsonBody(cleaned) ?? parseJsonBody(body);
116
- if (json && (json.code || json.message || json.cycle)) {
117
- return {
118
- code: json.code ?? null,
119
- message: json.message ?? (cleaned || prefix),
120
- cycle: json.cycle ?? null,
121
- raw: false,
122
- };
123
- }
124
- const literal = parseObjectLiteralTail(cleaned);
125
- if (literal && (literal.code || literal.cycle)) {
126
- // Grab the human-readable head — text before the trailing `{`. This is
127
- // the sentence part of a Lambda log-line spill (e.g. "Apply operation
128
- // <id> rejected: ComponentType slot dependency cycle detected among:
129
- // CycleA, CycleB. Break the cycle by...").
130
- const braceStart = cleaned.lastIndexOf('{');
131
- const head = braceStart === -1 ? cleaned : cleaned.slice(0, braceStart).trim();
132
- return {
133
- code: literal.code ?? null,
134
- message: head || cleaned,
135
- cycle: literal.cycle ?? null,
136
- raw: false,
137
- };
138
- }
139
- return { code: null, message: cleaned || prefix || rawInput, cycle: null, raw: true };
140
- }
141
- /**
142
- * Render a parsed error into a short multi-line block for the ErrorStep.
143
- * Callers can pass `verbose: true` to include the raw body underneath.
144
- */
145
- export function formatParsedEdsiError(parsed, opts = {}) {
146
- const lines = [];
147
- if (parsed.code) {
148
- lines.push(`[${parsed.code}]`);
149
- }
150
- if (parsed.message) {
151
- lines.push(parsed.message);
152
- }
153
- if (parsed.cycle && parsed.cycle.length > 0) {
154
- lines.push(`Cycle: ${parsed.cycle.join(' → ')} → ${parsed.cycle[0]}`);
155
- lines.push('Break the cycle by removing at least one $allowedComponents entry.');
156
- }
157
- if (opts.verbose && opts.raw) {
158
- lines.push('');
159
- lines.push('--- raw ---');
160
- lines.push(opts.raw);
161
- }
162
- return lines.filter(Boolean).join('\n');
163
- }