@contentful/experience-design-system-cli 2.11.4-dev-build-7abd382.0 → 2.11.4-dev-build-601ef74.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentful/experience-design-system-cli",
3
- "version": "2.11.4-dev-build-7abd382.0",
3
+ "version": "2.11.4-dev-build-601ef74.0",
4
4
  "description": "Contentful Experiences design system import CLI",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -196,6 +196,15 @@ export function registerAnalyzeCommand(program) {
196
196
  db.close();
197
197
  const allWarnings = [...extraction.warnings, ...filterWarnings];
198
198
  const { rows: componentRows, totalErrors } = buildAnalyzeViewRows(filteredComponents, validatedComponents, allWarnings);
199
+ // Split warnings: per-component (those whose prefix matches a surviving component name)
200
+ // are rendered under that component in the TUI; global ones (retry summaries,
201
+ // non-authorable skips, anything else) are rendered at the top of the warnings panel
202
+ // so they don't disappear into the count.
203
+ const componentNames = new Set(componentRows.map((r) => r.name));
204
+ const globalWarnings = allWarnings.filter((w) => {
205
+ const prefix = w.split(':', 1)[0]?.trim();
206
+ return !prefix || !componentNames.has(prefix);
207
+ });
199
208
  const analyzeResult = {
200
209
  sourceDirectory,
201
210
  sessionId,
@@ -203,6 +212,7 @@ export function registerAnalyzeCommand(program) {
203
212
  components: componentRows,
204
213
  totalWarnings: allWarnings.length,
205
214
  totalErrors,
215
+ globalWarnings,
206
216
  };
207
217
  if (process.stdout.isTTY) {
208
218
  const { waitUntilExit } = render(createElement(AnalyzeView, {
@@ -202,10 +202,11 @@ async function retryComponentWithProject(component, ctx, project, warnings) {
202
202
  }
203
203
  if (!members || members.length === 0)
204
204
  return false;
205
- // If the only members are Snippet-typed (the partial-heritage signal that
206
- // tripped the original warning), we haven't actually recovered useful props.
207
- if (members.every((m) => m.isSnippet))
208
- return false;
205
+ // If the resolver returned a complete member list even when it's
206
+ // Snippet-only that's a real answer, not a partial one. Apply it and
207
+ // drop `props-type-unresolved`. Whether the resulting component still
208
+ // needs review will be decided by the standard heuristics
209
+ // (no-props-or-slots, infra-fetch, etc.) downstream.
209
210
  const { props, snippetSlots } = extractFromTypeMembersOnly(members);
210
211
  // Merge any template <slot> entries that survived the original pass — we
211
212
  // can't easily re-derive those without re-parsing the fragment, but the
@@ -218,7 +219,9 @@ async function retryComponentWithProject(component, ctx, project, warnings) {
218
219
  const slotNames = new Set(finalSlots.map((s) => s.name));
219
220
  component.props = props.filter((p) => !slotNames.has(p.name));
220
221
  component.slots = finalSlots;
221
- // Drop props-type-unresolved from reasons; recompute confidence.
222
+ // Drop `props-type-unresolved` from reasons: the type DID resolve. Other
223
+ // heuristics (no-props-or-slots, infra-fetch, etc.) decide whether the
224
+ // recovered component still needs review.
222
225
  const remainingReasons = (component.reviewReasons ?? []).filter((r) => r !== 'props-type-unresolved');
223
226
  const score = computeExtractionScore(component, {
224
227
  additionalIssueCount: remainingReasons.length,
@@ -227,8 +230,7 @@ async function retryComponentWithProject(component, ctx, project, warnings) {
227
230
  component.extractionConfidence = score.confidence;
228
231
  component.reviewReasons = score.reasons;
229
232
  component.needsReview = deriveNeedsReview(score.confidence);
230
- // Remove the per-component unresolved-type warning so it doesn't muddy the
231
- // summary line / TUI grouping after recovery.
233
+ // Remove the per-component unresolved-type warning recovery is complete.
232
234
  const componentName = component.name;
233
235
  const idx = warnings.findIndex((w) => w.startsWith(`${componentName}: declared Props type `) && /resolved to /.test(w));
234
236
  if (idx >= 0)
@@ -461,22 +463,26 @@ function extractTypesFromExports(exportsField) {
461
463
  * When a large fraction of components emit the same `declared Props type ...
462
464
  * resolved to ... properties` warning (typical of headless libraries like
463
465
  * skeleton-svelte that extend types from external packages we can't reach),
464
- * collapse them into a single summary line at the top + the per-component
465
- * details below. Per-component reviewReasons and needsReview stay intact;
466
- * this only affects the warnings array's readability.
466
+ * replace ALL of them with a single summary line. Per-component
467
+ * reviewReasons + needsReview flags stay intact, so the user can still
468
+ * drill into any individual component to see the issue — we just don't
469
+ * flood the top-level warnings panel with N near-identical lines.
467
470
  *
468
471
  * Threshold: 3 or more identical-shape warnings. Below that, the literal
469
- * per-component lines are clearer than a summary.
472
+ * per-component lines are short enough to keep as-is.
470
473
  */
471
474
  function collapseUnresolvedTypeWarnings(warnings) {
472
475
  const isUnresolvedWarning = (w) => /declared Props type .* resolved to/.test(w);
473
- const unresolved = warnings.filter(isUnresolvedWarning);
474
- if (unresolved.length < 3)
476
+ const unresolvedCount = warnings.filter(isUnresolvedWarning).length;
477
+ if (unresolvedCount < 3)
475
478
  return warnings;
476
- const summary = `Unresolved component types: ${unresolved.length} components have a declared Props type the parser couldn't fully resolve — ` +
479
+ const others = warnings.filter((w) => !isUnresolvedWarning(w));
480
+ const summary = `Unresolved component types: ${unresolvedCount} components have a declared Props type the parser couldn't fully resolve — ` +
477
481
  `most often a cross-package extends pattern (e.g. an interface that extends a type from a node_modules package). ` +
482
+ `Each affected component is flagged with reviewReasons: ['props-type-unresolved'] and needsReview = true; ` +
483
+ `select one in the TUI to drill in. ` +
478
484
  `See https://github.com/contentful/experience-design-system-sdk-public/pull/44 for context and partner workarounds.`;
479
- return [summary, ...warnings];
485
+ return [summary, ...others];
480
486
  }
481
487
  async function extractFromSvelteFile(filePath, source) {
482
488
  const warnings = [];
@@ -21,6 +21,15 @@ export type AnalyzeViewResult = {
21
21
  }>;
22
22
  totalWarnings: number;
23
23
  totalErrors: number;
24
+ /**
25
+ * Top-level warnings not associated with any surviving component:
26
+ * - retry-pass summary lines
27
+ * - "Skipped non-authorable component: …" — the component was filtered out and has no row to attach to
28
+ * - any other extractor warning whose prefix doesn't match a component in `components`
29
+ * Always rendered at the top of the Warnings panel so they're visible in the TUI.
30
+ * Optional for backwards compatibility with older fixtures; treated as `[]` when absent.
31
+ */
32
+ globalWarnings?: string[];
24
33
  };
25
34
  type AnalyzeViewProps = {
26
35
  result: AnalyzeViewResult;
@@ -57,8 +57,8 @@ export function AnalyzeView({ result, onExit }) {
57
57
  }), showScrollDown && _jsx(Text, { dimColor: true, children: " \u25BC scroll down" }), result.totalErrors > 0 && (_jsxs(_Fragment, { children: [_jsx(Text, { children: " " }), _jsx(Text, { dimColor: true, children: '─'.repeat(70) }), _jsx(Text, { bold: true, color: "red", children: 'Errors (' + result.totalErrors + ')' }), _jsx(Text, { dimColor: true, children: '─'.repeat(70) }), _jsx(Text, { children: " " }), result.components
58
58
  .filter((c) => c.errors.length > 0)
59
59
  .flatMap((c) => c.errors.map((e) => ({ component: c.name, error: e })))
60
- .map((e, i) => (_jsx(Text, { color: "red", children: ' ✗ ' + e.component + ': ' + e.error }, i)))] })), result.totalWarnings > 0 && (_jsxs(_Fragment, { children: [_jsx(Text, { children: " " }), _jsx(Text, { dimColor: true, children: '─'.repeat(70) }), _jsx(Text, { bold: true, color: "yellow", children: 'Warnings (' + result.totalWarnings + ')' }), _jsx(Text, { dimColor: true, children: '─'.repeat(70) }), _jsx(Text, { children: " " }), result.components
60
+ .map((e, i) => (_jsx(Text, { color: "red", children: ' ✗ ' + e.component + ': ' + e.error }, i)))] })), result.totalWarnings > 0 && (_jsxs(_Fragment, { children: [_jsx(Text, { children: " " }), _jsx(Text, { dimColor: true, children: '─'.repeat(70) }), _jsx(Text, { bold: true, color: "yellow", children: 'Warnings (' + result.totalWarnings + ')' }), _jsx(Text, { dimColor: true, children: '─'.repeat(70) }), _jsx(Text, { children: " " }), (result.globalWarnings ?? []).map((w, i) => (_jsx(Text, { color: "yellow", children: ' ⚠ ' + w }, `g${i}`))), result.components
61
61
  .filter((c) => c.warnings.length > 0)
62
62
  .flatMap((c) => c.warnings.map((w) => ({ component: c.name, warning: w })))
63
- .map((w, i) => (_jsx(Text, { color: "yellow", children: ' ⚠ ' + w.component + ': ' + w.warning }, i)))] })), _jsx(Text, { children: " " }), _jsx(Text, { dimColor: true, children: 'Run: analyze select --session ' + result.sessionId }), _jsx(Text, { children: " " })] }), _jsx(Box, { borderStyle: "single", paddingX: 1, children: _jsx(Text, { dimColor: true, children: "Press Enter or q to exit" }) })] }));
63
+ .map((w, i) => (_jsx(Text, { color: "yellow", children: ' ⚠ ' + (w.warning.startsWith(w.component + ': ') ? w.warning : w.component + ': ' + w.warning) }, `c${i}`)))] })), _jsx(Text, { children: " " }), _jsx(Text, { dimColor: true, children: 'Run: analyze select --session ' + result.sessionId }), _jsx(Text, { children: " " })] }), _jsx(Box, { borderStyle: "single", paddingX: 1, children: _jsx(Text, { dimColor: true, children: "Press Enter or q to exit" }) })] }));
64
64
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentful/experience-design-system-cli",
3
- "version": "2.11.4-dev-build-7abd382.0",
3
+ "version": "2.11.4-dev-build-601ef74.0",
4
4
  "description": "Contentful Experiences design system import CLI",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -37,7 +37,7 @@
37
37
  "svelte": "^5.56.4",
38
38
  "ts-morph": "^27.0.2",
39
39
  "typescript": "^5.9.3",
40
- "@contentful/experience-design-system-types": "2.11.4-dev-build-7abd382.0"
40
+ "@contentful/experience-design-system-types": "2.11.4-dev-build-601ef74.0"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@tsconfig/node24": "^24.0.3",