@astryxdesign/cli 0.1.7 → 0.1.8-canary.07362a9
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/CHANGELOG.md +40 -0
- package/README.md +115 -19
- package/{src/api → api/blog}/blog.mjs +42 -6
- package/{src/api → api/blog}/blog.test.mjs +2 -2
- package/api/build/build.mjs +92 -0
- package/api/build/build.test.mjs +92 -0
- package/{src/api → api/component}/component.mjs +49 -26
- package/{src/api → api/discover}/discover.mjs +55 -18
- package/{src/api → api/docs}/docs.mjs +47 -21
- package/{src/api → api/doctor}/doctor.mjs +13 -10
- package/{src/api → api}/error.mjs +2 -2
- package/{src/api → api/hook}/hook.mjs +11 -11
- package/{src/api → api}/index.mjs +16 -9
- package/{src/api → api/integration}/validate-integration.mjs +48 -15
- package/{src/api → api/integration}/validate-integration.test.mjs +1 -1
- package/{src/api → api/layout}/layout.mjs +66 -17
- package/{src/api → api/layout}/layout.test.mjs +1 -1
- package/{src/api → api/search}/search.mjs +71 -12
- package/api/swizzle/swizzle.mjs +283 -0
- package/{src/commands → api/swizzle}/swizzle.test.mjs +26 -1
- package/{src/api → api/template}/template-integration.test.mjs +2 -2
- package/{src/api → api/template}/template-suffix.test.mjs +3 -3
- package/{src/api → api/template}/template.mjs +96 -19
- package/{src/api → api/theme}/theme-add.mjs +35 -7
- package/{src → authoring}/codemod.mjs +6 -6
- package/{src → authoring}/config.test.mjs +1 -1
- package/{src → authoring}/doc.mjs +1 -1
- package/{src → authoring}/doc.test.mjs +1 -1
- package/{src → authoring}/template.mjs +1 -1
- package/bin/astryx.mjs +12 -10
- package/{src → cli}/commands/blog.mjs +48 -7
- package/{src → cli}/commands/build-theme.mjs +133 -115
- package/cli/commands/build.mjs +172 -0
- package/cli/commands/cli-postinstall.test.mjs +42 -0
- package/{src → cli}/commands/component/index.mjs +52 -25
- package/{src → cli}/commands/component-ownership.test.mjs +3 -3
- package/{src → cli}/commands/component-package.test.mjs +1 -1
- package/{src → cli}/commands/component-resolution.test.mjs +2 -2
- package/{src → cli}/commands/discover.mjs +23 -12
- package/{src → cli}/commands/docs.mjs +42 -10
- package/{src → cli}/commands/docs.test.mjs +1 -1
- package/{src → cli}/commands/doctor.mjs +3 -3
- package/{src → cli}/commands/doctor.test.mjs +2 -2
- package/{src → cli}/commands/ensure-core-built.mjs +3 -2
- package/{src → cli}/commands/external-showcase.test.mjs +1 -1
- package/{src → cli}/commands/hook/index.mjs +40 -17
- package/{src → cli}/commands/import-hint-correctness.test.mjs +1 -1
- package/cli/commands/init.mjs +195 -0
- package/{src → cli}/commands/init.next-steps.test.mjs +1 -1
- package/cli/commands/interactive-guard.test.mjs +66 -0
- package/{src → cli}/commands/json-contract.test.mjs +2 -2
- package/{src → cli}/commands/layout.mjs +59 -19
- package/{src → cli}/commands/search.mjs +22 -15
- package/{src → cli}/commands/search.test.mjs +1 -1
- package/cli/commands/setup-nudge.test.mjs +108 -0
- package/cli/commands/swizzle.mjs +103 -0
- package/{src → cli}/commands/template.mjs +84 -53
- package/{src → cli}/commands/template.path-safety.test.mjs +2 -2
- package/{src → cli}/commands/upgrade.integration-policy.test.mjs +1 -1
- package/{src → cli}/commands/upgrade.mjs +291 -77
- package/cli/commands/upgrade.test.mjs +314 -0
- package/{src → cli}/commands/validate-integration.mjs +17 -37
- package/{src → cli}/index.mjs +55 -19
- package/{src/codemods → codemods}/__tests__/registry.test.mjs +1 -0
- package/{src/codemods → codemods}/ensure-jscodeshift.mjs +12 -28
- package/{src/codemods → codemods}/integration-discovery.mjs +6 -3
- package/{src/codemods → codemods}/integration-discovery.test.mjs +1 -1
- package/{src/codemods → codemods}/integration-runner.mjs +8 -3
- package/{src/codemods → codemods}/registry.mjs +4 -1
- package/{src/codemods → codemods}/run-codemod.mjs +18 -11
- package/{src/codemods → codemods}/runner.mjs +24 -14
- package/{src/codemods → codemods}/transforms/v0.0.10/remove-size-props.mjs +9 -4
- package/{src/codemods → codemods}/transforms/v0.0.12/add-is-icon-only.mjs +27 -22
- package/{src/codemods → codemods}/transforms/v0.0.13/icon-name-deprecations.mjs +12 -5
- package/{src/codemods → codemods}/transforms/v0.0.13/rename-attachments-to-drawer.mjs +15 -8
- package/{src/codemods → codemods}/transforms/v0.0.13/toolbar-density-to-size.mjs +10 -4
- package/{src/codemods → codemods}/transforms/v0.0.14/rename-action-props.mjs +11 -5
- package/{src/codemods → codemods}/transforms/v0.0.14/rename-section-wash-to-muted.mjs +11 -6
- package/{src/codemods → codemods}/transforms/v0.0.14/rename-status-variants.mjs +15 -10
- package/{src/codemods → codemods}/transforms/v0.0.15/migrate-item-children-to-endcontent.mjs +13 -8
- package/{src/codemods → codemods}/transforms/v0.0.15/migrate-selector-children-to-render-option.mjs +18 -13
- package/{src/codemods → codemods}/transforms/v0.0.15/migrate-theme-selectors-to-data-attrs.mjs +8 -4
- package/{src/codemods → codemods}/transforms/v0.0.15/rename-date-picker-to-input.mjs +11 -6
- package/{src/codemods → codemods}/transforms/v0.0.15/rename-imperative-ref-to-handleRef.mjs +6 -1
- package/{src/codemods → codemods}/transforms/v0.0.15/rename-isStreaming-to-isStopShown.mjs +6 -1
- package/{src/codemods → codemods}/transforms/v0.0.15/rename-stack-element-to-as.mjs +8 -3
- package/{src/codemods → codemods}/transforms/v0.0.2/migrate-badge-dot-to-statusdot.mjs +17 -10
- package/{src/codemods → codemods}/transforms/v0.0.2/migrate-gap-to-numeric.mjs +7 -1
- package/{src/codemods → codemods}/transforms/v0.0.2/migrate-isFullBleed-to-padding.mjs +9 -4
- package/{src/codemods → codemods}/transforms/v0.0.2/migrate-useXDSIcon-to-getIcon.mjs +12 -7
- package/{src/codemods → codemods}/transforms/v0.0.2/rename-banner-endButton-to-endContent.mjs +7 -2
- package/{src/codemods → codemods}/transforms/v0.0.2/rename-form-tooltip-startIcon.mjs +8 -2
- package/{src/codemods → codemods}/transforms/v0.0.2/rename-isShown-to-isOpen.mjs +7 -2
- package/{src/codemods → codemods}/transforms/v0.0.2/rename-selector-items-to-options.mjs +7 -2
- package/{src/codemods → codemods}/transforms/v0.0.2/rename-sidenav-header-to-heading.mjs +11 -4
- package/{src/codemods → codemods}/transforms/v0.0.2/rename-topnav-title-to-heading.mjs +10 -4
- package/{src/codemods → codemods}/transforms/v0.0.2/unify-uncontrolled-to-defaultX.mjs +7 -2
- package/{src/codemods → codemods}/transforms/v0.0.2/unify-visibility-to-onOpenChange.mjs +10 -5
- package/{src/codemods → codemods}/transforms/v0.0.6/migrate-badge-children-to-label.mjs +7 -2
- package/{src/codemods → codemods}/transforms/v0.0.6/migrate-collapse-to-collapsible.mjs +9 -3
- package/{src/codemods → codemods}/transforms/v0.0.6/migrate-radius-tokens.mjs +11 -5
- package/{src/codemods → codemods}/transforms/v0.0.6/migrate-shadow-tokens.mjs +13 -6
- package/{src/codemods → codemods}/transforms/v0.0.6/migrate-skeleton-radius.mjs +7 -1
- package/{src/codemods → codemods}/transforms/v0.0.6/migrate-token-names.mjs +11 -5
- package/{src/codemods → codemods}/transforms/v0.0.7/rename-banner-variant-to-container.mjs +8 -3
- package/{src/codemods → codemods}/transforms/v0.0.8/migrate-token-renames.mjs +15 -8
- package/{src/codemods → codemods}/transforms/v0.0.8/rename-endslot-to-endcontent.mjs +7 -2
- package/{src/codemods → codemods}/transforms/v0.1.0/__tests__/drop-xds-prefix-imports.test.mjs +42 -7
- package/{src/codemods → codemods}/transforms/v0.1.0/__tests__/migrate-xds-module-specifiers.test.mjs +43 -0
- package/{src/codemods → codemods}/transforms/v0.1.0/drop-xds-prefix-imports.mjs +117 -13
- package/{src/codemods → codemods}/transforms/v0.1.0/migrate-xds-css-surfaces.mjs +21 -17
- package/{src/codemods → codemods}/transforms/v0.1.0/migrate-xds-declare-module.mjs +7 -2
- package/{src/codemods → codemods}/transforms/v0.1.0/migrate-xds-module-specifiers.mjs +86 -15
- package/{src/codemods → codemods}/transforms/v0.1.2/rename-text-color-active-to-accent.mjs +15 -9
- package/{src/codemods → codemods}/transforms/v0.1.3/migrate-layout-components-to-experimental.mjs +17 -12
- package/{src/codemods → codemods}/transforms/v0.1.5/rename-switch-label-spacing-default-to-hug.mjs +15 -9
- package/{src/codemods → codemods}/transforms/v0.1.7/migrate-table-tableprops-to-direct-props.mjs +17 -10
- package/{src/codemods → codemods}/transforms/v0.1.7/rename-table-renderprops-styles-to-xstyle.mjs +18 -13
- package/codemods/transforms/v0.1.8/__tests__/rename-avatar-size-scale.test.mjs +161 -0
- package/codemods/transforms/v0.1.8/index.mjs +19 -0
- package/codemods/transforms/v0.1.8/rename-avatar-size-scale.mjs +239 -0
- package/docs/cli-integrations.doc.mjs +150 -0
- package/docs/elevation.doc.mjs +79 -1
- package/docs/getting-started.doc.mjs +9 -9
- package/docs/internationalization.doc.mjs +92 -46
- package/docs/migration.doc.mjs +18 -18
- package/docs/principles.doc.dense.mjs +1 -1
- package/docs/principles.doc.mjs +6 -6
- package/docs/principles.doc.zh.mjs +1 -1
- package/docs/styling-libraries.doc.mjs +3 -3
- package/docs/styling.doc.mjs +4 -4
- package/docs/theme.doc.dense.mjs +2 -2
- package/docs/theme.doc.mjs +7 -7
- package/docs/theme.doc.zh.mjs +1 -1
- package/docs/tokens.doc.mjs +1 -1
- package/docs/working-with-ai.doc.mjs +19 -19
- package/{src/commands → lib/agent-docs}/agent-docs.mjs +164 -29
- package/{src/commands → lib/agent-docs}/agent-docs.path-safety.test.mjs +1 -1
- package/{src/commands → lib/agent-docs}/agent-docs.test.mjs +123 -10
- package/{src/lib → lib}/cli-error.mjs +2 -2
- package/{src/lib → lib}/component-discovery.mjs +44 -2
- package/{src/lib → lib}/component-format.mjs +67 -25
- package/{src/lib → lib}/component-loader.mjs +27 -13
- package/{src/lib → lib}/componentDocOverlay.test.mjs +0 -1
- package/{src/lib → lib}/error-codes.test.mjs +1 -1
- package/{src/lib → lib}/hook-discovery.mjs +14 -1
- package/{src/lib → lib}/hook-format.mjs +29 -5
- package/{src/lib → lib}/integration-warnings.mjs +2 -2
- package/{src/lib → lib}/integrations.mjs +20 -0
- package/{src/lib → lib}/integrations.test.mjs +1 -1
- package/{src/lib → lib}/json-contract.test.mjs +1 -1
- package/{src/lib → lib}/json-shim.mjs +11 -6
- package/{src/lib → lib}/json-shim.test.mjs +1 -1
- package/{src/lib → lib}/json.mjs +3 -3
- package/{src/lib → lib}/levenshtein.mjs +6 -0
- package/{src/lib → lib}/manifest.mjs +7 -5
- package/{src/lib → lib}/manifest.test.mjs +2 -2
- package/{src/lib → lib}/module-loader.mjs +1 -0
- package/{src/lib → lib}/package-scanner.mjs +47 -0
- package/{src/lib → lib}/project.mjs +48 -18
- package/{src/lib → lib}/project.test.mjs +1 -1
- package/{src/lib → lib}/resolve-theme.mjs +5 -0
- package/{src/lib → lib}/string-utils.mjs +15 -0
- package/lib/term-log.mjs +57 -0
- package/{src/lib → lib}/xle/browser.mjs +18 -8
- package/{src/lib → lib}/xle/expand.mjs +155 -22
- package/{src/lib → lib}/xle/parse.mjs +119 -13
- package/{src/lib → lib}/xle/print.mjs +54 -14
- package/{src/lib → lib}/xle/registry-core.mjs +28 -3
- package/{src/lib → lib}/xle/registry.mjs +9 -4
- package/{src/lib → lib}/xle/splice.mjs +13 -2
- package/{src/lib → lib}/xle/validate.mjs +95 -14
- package/lib/xle/xle-ast.d.ts +214 -0
- package/package.json +37 -28
- package/scripts/postinstall.mjs +74 -0
- package/templates/blocks/components/Avatar/AvatarFallbackChain.tsx +4 -4
- package/templates/blocks/components/Avatar/AvatarGroup.tsx +2 -2
- package/templates/blocks/components/Avatar/AvatarInitialsFallback.tsx +1 -1
- package/templates/blocks/components/Avatar/AvatarShowcase.tsx +5 -5
- package/templates/blocks/components/Avatar/AvatarUserCard.tsx +1 -1
- package/templates/blocks/components/Avatar/AvatarWithImage.tsx +4 -4
- package/templates/blocks/components/Avatar/AvatarWithStatus.tsx +3 -3
- package/templates/blocks/components/AvatarGroup/AvatarGroupShowcase.tsx +2 -2
- package/templates/blocks/components/AvatarGroupOverflow/AvatarGroupOverflowCustomText.tsx +1 -1
- package/templates/blocks/components/AvatarGroupOverflow/AvatarGroupOverflowDefault.tsx +1 -1
- package/templates/blocks/components/AvatarGroupOverflow/AvatarGroupOverflowShowcase.tsx +2 -2
- package/templates/blocks/components/AvatarStatusDot/AvatarStatusDotShowcase.tsx +3 -3
- package/templates/blocks/components/AvatarStatusDot/AvatarStatusDotVariants.tsx +3 -3
- package/templates/blocks/components/Banner/BannerFloating.doc.mjs +14 -0
- package/templates/blocks/components/Banner/BannerFloating.tsx +16 -0
- package/templates/blocks/components/Button/ButtonFloating.doc.mjs +14 -0
- package/templates/blocks/components/Button/ButtonFloating.tsx +37 -0
- package/templates/blocks/components/ButtonGroup/ButtonGroupFloating.doc.mjs +14 -0
- package/templates/blocks/components/ButtonGroup/ButtonGroupFloating.tsx +23 -0
- package/templates/blocks/components/Card/CardElevations.doc.mjs +14 -0
- package/templates/blocks/components/Card/CardElevations.tsx +32 -0
- package/templates/blocks/components/Card/ClickableCardElevated.doc.mjs +14 -0
- package/templates/blocks/components/Card/ClickableCardElevated.tsx +21 -0
- package/templates/blocks/components/Card/SelectableCardElevated.doc.mjs +14 -0
- package/templates/blocks/components/Card/SelectableCardElevated.tsx +37 -0
- package/templates/blocks/components/Carousel/CarouselSnap.tsx +1 -1
- package/templates/blocks/components/ChatComposer/ChatComposerFlat.doc.mjs +14 -0
- package/templates/blocks/components/ChatComposer/ChatComposerFlat.tsx +75 -0
- package/templates/blocks/components/ChatMessage/ChatMessageAvatarName.tsx +2 -2
- package/templates/blocks/components/ChatMessage/ChatMessageMultiBubble.tsx +1 -1
- package/templates/blocks/components/ChatMessageBubble/ChatMessageBubbleGrouping.tsx +1 -1
- package/templates/blocks/components/ChatMessageBubble/ChatMessageBubbleMetadata.tsx +1 -1
- package/templates/blocks/components/ChatMessageList/ChatMessageListDensity.tsx +5 -9
- package/templates/blocks/components/ChatMessageList/ChatMessageListFullFeatured.tsx +1 -1
- package/templates/blocks/components/CodeBlock/CodeBlockTerminal.tsx +1 -1
- package/templates/blocks/components/HoverCard/HoverCardShowcase.tsx +1 -1
- package/templates/blocks/components/IconButton/IconButtonFloating.doc.mjs +14 -0
- package/templates/blocks/components/IconButton/IconButtonFloating.tsx +37 -0
- package/templates/blocks/components/InternationalizationProvider/InternationalizationProvider01ShippedLocale.doc.mjs +19 -0
- package/templates/blocks/components/InternationalizationProvider/InternationalizationProvider01ShippedLocale.tsx +46 -0
- package/templates/blocks/components/InternationalizationProvider/InternationalizationProvider02Overrides.doc.mjs +14 -0
- package/templates/blocks/components/InternationalizationProvider/InternationalizationProvider02Overrides.tsx +33 -0
- package/templates/blocks/components/Item/ItemWithMedia.tsx +2 -2
- package/templates/blocks/components/ListItem/ListItemWithMedia.tsx +2 -2
- package/templates/blocks/components/OverflowList/OverflowListCappedToolbar.doc.mjs +14 -0
- package/templates/blocks/components/OverflowList/OverflowListCappedToolbar.tsx +39 -0
- package/templates/blocks/components/OverflowList/OverflowListMultiRowTags.doc.mjs +14 -0
- package/templates/blocks/components/OverflowList/OverflowListMultiRowTags.tsx +44 -0
- package/templates/blocks/components/Pagination/PaginationDotsCarousel.tsx +2 -6
- package/templates/blocks/components/Stack/StackFillItem.tsx +2 -6
- package/templates/blocks/components/TabList/TabListTabsWithActions.doc.mjs +1 -1
- package/templates/blocks/components/TabList/TabListTabsWithActions.tsx +2 -7
- package/templates/blocks/components/Table/TableRowStatusTable.doc.mjs +14 -0
- package/templates/blocks/components/Table/TableRowStatusTable.tsx +59 -0
- package/templates/blocks/components/Thumbnail/ThumbnailDisabled.tsx +6 -1
- package/templates/blocks/components/Thumbnail/ThumbnailGallery.tsx +1 -0
- package/templates/blocks/components/Thumbnail/ThumbnailRemovable.tsx +1 -0
- package/templates/blocks/components/TypeaheadItem/TypeaheadItemShowcase.tsx +1 -1
- package/templates/pages/ai-chat/page.tsx +4 -4
- package/templates/pages/dashboard-portfolio/page.tsx +3 -11
- package/templates/pages/detail-page/page.tsx +5 -12
- package/templates/pages/documentation-design/page.tsx +1 -1
- package/templates/pages/messaging-shell/page.tsx +6 -8
- package/templates/pages/table-grouped/page.tsx +9 -14
- package/templates/pages/table-page/page.tsx +7 -9
- package/templates/pages/table-page-heatmap-status/page.tsx +5 -13
- package/{src/types → types}/api.contract.assert.ts +17 -8
- package/{src/types → types}/api.d.ts +110 -9
- package/{src/types → types}/base.d.ts +40 -4
- package/types/build.d.ts +53 -0
- package/types/codemod.d.ts +166 -0
- package/{src/types → types}/component.d.ts +1 -1
- package/{src/types → types}/discover.d.ts +1 -1
- package/{src/types → types}/docs.d.ts +1 -4
- package/{src/types → types}/hook.d.ts +1 -1
- package/{src/types → types}/index.d.ts +1 -0
- package/types/jscodeshift.d.ts +19 -0
- package/types/layout.d.ts +74 -0
- package/{src/types → types}/swizzle.d.ts +4 -0
- package/{src/types → types}/template-api.d.ts +4 -1
- package/types/theme.d.ts +53 -0
- package/types/upgrade.d.ts +108 -0
- package/utils/package-manager.mjs +178 -0
- package/utils/package-manager.test.mjs +220 -0
- package/{src/utils → utils}/path-safety.mjs +0 -18
- package/{src/utils → utils}/paths.mjs +4 -1
- package/{src/utils → utils}/update-check.mjs +5 -4
- package/{src/utils → utils}/update-check.test.mjs +3 -3
- package/docs/integration-authoring.md +0 -105
- package/src/commands/build.mjs +0 -196
- package/src/commands/init.mjs +0 -288
- package/src/commands/interactive-guard.test.mjs +0 -69
- package/src/commands/swizzle.mjs +0 -440
- package/src/commands/upgrade.test.mjs +0 -160
- package/src/types/codemod.d.ts +0 -81
- package/src/types/theme.d.ts +0 -23
- package/src/types/upgrade.d.ts +0 -64
- package/src/utils/interactive.mjs +0 -76
- package/src/utils/interactive.test.mjs +0 -70
- package/src/utils/package-manager.mjs +0 -74
- package/src/utils/package-manager.test.mjs +0 -113
- /package/{src/api → api/docs}/docOverlays.test.mjs +0 -0
- /package/{src/api → api/integration}/integration-block-exports.test.mjs +0 -0
- /package/{src/api → api/template}/template.test.mjs +0 -0
- /package/{src → authoring}/codemod.test.mjs +0 -0
- /package/{src → authoring}/config.mjs +0 -0
- /package/{src → authoring}/integration.mjs +0 -0
- /package/{src → authoring}/template.test.mjs +0 -0
- /package/{src → cli}/cli-exit-codes.test.mjs +0 -0
- /package/{src → cli}/commands/build-theme.color-scheme.test.mjs +0 -0
- /package/{src → cli}/commands/build-theme.import-path.test.mjs +0 -0
- /package/{src → cli}/commands/build-theme.path-safety.test.mjs +0 -0
- /package/{src → cli}/commands/build-theme.prose.test.mjs +0 -0
- /package/{src → cli}/commands/build-theme.variants.test.mjs +0 -0
- /package/{src → cli}/commands/build-theme.watch.test.mjs +0 -0
- /package/{src → cli}/commands/component.test.mjs +0 -0
- /package/{src → cli}/commands/detail-levels.test.mjs +0 -0
- /package/{src → cli}/commands/swizzle.path-safety.test.mjs +0 -0
- /package/{src → cli}/commands/swizzle.routing.test.mjs +0 -0
- /package/{src → cli}/commands/template.test.mjs +0 -0
- /package/{src → cli}/commands/upgrade.config-ordering.test.mjs +0 -0
- /package/{src → cli}/commands/validate-integration.test.mjs +0 -0
- /package/{src → cli}/update-hint-commands.test.mjs +0 -0
- /package/{src/codemods → codemods}/__tests__/rename-imperative-ref-to-handleRef.test.mjs +0 -0
- /package/{src/codemods → codemods}/__tests__/rename-isStreaming-to-isStopShown.test.mjs +0 -0
- /package/{src/codemods → codemods}/__tests__/rename-section-wash-to-muted.test.mjs +0 -0
- /package/{src/codemods → codemods}/__tests__/runner.test.mjs +0 -0
- /package/{src/codemods → codemods}/__tests__/toolbar-density-to-size.test.mjs +0 -0
- /package/{src/codemods → codemods}/__tests__/validation.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.10/__tests__/remove-size-props.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.10/index.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.12/__tests__/add-is-icon-only.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.12/index.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.13/__tests__/icon-name-deprecations.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.13/__tests__/rename-attachments-to-drawer.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.13/index.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.14/__tests__/rename-action-props.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.14/__tests__/rename-status-variants.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.14/index.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.15/__tests__/migrate-item-children-to-endcontent.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.15/__tests__/migrate-selector-children-to-render-option.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.15/__tests__/migrate-theme-selectors-to-data-attrs.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.15/__tests__/rename-date-picker-to-input.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.15/__tests__/rename-stack-element-to-as.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.15/index.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/migrate-badge-dot-to-statusdot.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/migrate-gap-to-numeric.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/migrate-isFullBleed-to-padding.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/migrate-useXDSIcon-to-getIcon.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/rename-banner-endButton-to-endContent.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/rename-form-tooltip-startIcon.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/rename-isShown-to-isOpen.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/rename-selector-items-to-options.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/rename-sidenav-header-to-heading.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/rename-topnav-title-to-heading.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/unify-uncontrolled-to-defaultX.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/unify-visibility-to-onOpenChange.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.2/index.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.6/__tests__/migrate-collapse-to-collapsible.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.6/__tests__/migrate-radius-tokens.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.6/__tests__/migrate-shadow-tokens.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.6/__tests__/migrate-skeleton-radius.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.6/__tests__/migrate-token-names.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.6/index.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.7/__tests__/rename-banner-variant-to-container.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.7/index.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.8/__tests__/migrate-token-renames.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.8/__tests__/rename-endslot-to-endcontent.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.8/index.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.1.0/__tests__/migrate-xds-css-surfaces.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.1.0/__tests__/migrate-xds-declare-module.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.1.0/__tests__/v0.1.0-ordering.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.1.0/index.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.1.2/__tests__/rename-text-color-active-to-accent.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.1.2/index.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.1.3/__tests__/migrate-layout-components-to-experimental.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.1.3/index.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.1.5/__tests__/rename-switch-label-spacing-default-to-hug.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.1.5/index.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.1.7/__tests__/migrate-table-tableprops-to-direct-props.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.1.7/__tests__/rename-table-renderprops-styles-to-xstyle.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.1.7/index.mjs +0 -0
- /package/{src/lib → lib}/cli-error.test.mjs +0 -0
- /package/{src/lib → lib}/component-discovery.importpath.test.mjs +0 -0
- /package/{src/lib → lib}/component-format.test.mjs +0 -0
- /package/{src/lib → lib}/component-loader.test.mjs +0 -0
- /package/{src/lib → lib}/config-cache.mjs +0 -0
- /package/{src/lib → lib}/config-cache.test.mjs +0 -0
- /package/{src/lib → lib}/config-schema.mjs +0 -0
- /package/{src/lib → lib}/error-codes.mjs +0 -0
- /package/{src/lib → lib}/integration-warnings.test.mjs +0 -0
- /package/{src/lib → lib}/module-loader.test.mjs +0 -0
- /package/{src/lib → lib}/node-version.mjs +0 -0
- /package/{src/lib → lib}/node-version.test.mjs +0 -0
- /package/{src/lib → lib}/parse.mjs +0 -0
- /package/{src/lib → lib}/site.mjs +0 -0
- /package/{src/lib → lib}/xle/browser.d.ts +0 -0
- /package/{src/lib → lib}/xle/xle.test.mjs +0 -0
- /package/{src/schemas → schemas}/doc-schema.mjs +0 -0
- /package/{src/schemas → schemas}/template-schema.mjs +0 -0
- /package/{src/types → types}/config.d.ts +0 -0
- /package/{src/types → types}/doc.d.ts +0 -0
- /package/{src/types → types}/doctor.d.ts +0 -0
- /package/{src/types → types}/error-codes.d.ts +0 -0
- /package/{src/types → types}/integration.d.ts +0 -0
- /package/{src/types → types}/manifest.d.ts +0 -0
- /package/{src/types → types}/search.d.ts +0 -0
- /package/{src/types → types}/template.d.ts +0 -0
- /package/{src/types → types}/validate-integration.d.ts +0 -0
- /package/{src/utils → utils}/github.mjs +0 -0
- /package/{src/utils → utils}/path-safety.test.mjs +0 -0
- /package/{src/utils → utils}/paths.test.mjs +0 -0
- /package/{src/utils → utils}/semver.mjs +0 -0
- /package/{src/utils → utils}/semver.test.mjs +0 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file build command — thin wrapper around api/build.
|
|
5
|
+
*
|
|
6
|
+
* astryx build → the PLAYBOOK (how to build a page)
|
|
7
|
+
* astryx build "<what>" → a COMPOSITION KIT (closest page template,
|
|
8
|
+
* blocks, components) with a recommended START.
|
|
9
|
+
*
|
|
10
|
+
* All grouping/scoring lives in api/build; this file only parses flags and
|
|
11
|
+
* renders. Command strings are prefixed for the caller's package manager here
|
|
12
|
+
* (never in the API payload) via formatCliCommand/getCliInvocation.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import {getCliInvocation, formatCliCommand} from '../../utils/package-manager.mjs';
|
|
16
|
+
import {jsonOut, humanLog} from '../../lib/json.mjs';
|
|
17
|
+
import {cliError} from '../../lib/cli-error.mjs';
|
|
18
|
+
import {build as buildApi} from '../../api/build/build.mjs';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Print the build playbook (shown when `build` is run with no query).
|
|
22
|
+
* @param {string} run - The CLI invocation prefix (e.g. `npx astryx`).
|
|
23
|
+
*/
|
|
24
|
+
function printPlaybook(run) {
|
|
25
|
+
const lines = [
|
|
26
|
+
'',
|
|
27
|
+
'How to build a page with Astryx',
|
|
28
|
+
'',
|
|
29
|
+
"1. Find a starting point for what you're building:",
|
|
30
|
+
` ${run} build "<what you're building>"`,
|
|
31
|
+
' → returns the closest [page] template, the [block]s that cover parts,',
|
|
32
|
+
' and the [component]s to fill the gaps, with a "Compose:" suggestion.',
|
|
33
|
+
'',
|
|
34
|
+
'2. If a [page] template matches → scaffold it and adapt:',
|
|
35
|
+
` ${run} template <name> [path]`,
|
|
36
|
+
'',
|
|
37
|
+
'3. If nothing matches exactly → compose:',
|
|
38
|
+
` ${run} template <name> --skeleton # study a close page's layout`,
|
|
39
|
+
` ${run} template <BlockName> # drop in each block from the kit`,
|
|
40
|
+
` ${run} component <Name> # fill remaining gaps (read props)`,
|
|
41
|
+
'',
|
|
42
|
+
'4. Rules (keep it on-system):',
|
|
43
|
+
' - No <div>/raw HTML for layout — use VStack/HStack/Grid/Stack/Card etc.',
|
|
44
|
+
` - No style={{}} — use component props; design tokens via \`${run} docs tokens\`.`,
|
|
45
|
+
' - Wrap the app in <Theme theme={...}> and import core reset.css + astryx.css.',
|
|
46
|
+
'',
|
|
47
|
+
`Tip: \`${run} build "<idea>"\` is the fastest way in. For a neutral`,
|
|
48
|
+
`lookup of any component/doc/template, use \`${run} search <query>\`.`,
|
|
49
|
+
'',
|
|
50
|
+
];
|
|
51
|
+
for (const l of lines) humanLog(l);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @param {import('commander').Command} program
|
|
56
|
+
*/
|
|
57
|
+
export function registerBuild(program) {
|
|
58
|
+
program
|
|
59
|
+
.command('build [query]')
|
|
60
|
+
.description('Build a page: composition kit for an idea, or the workflow playbook (no args)')
|
|
61
|
+
.option('--type <domain>', 'Filter the kit to one domain (component|hook|template)')
|
|
62
|
+
.option('--limit <n>', 'Max candidates to draw from (default 60)')
|
|
63
|
+
.option('--detail', 'Verbose output (include import paths and match reason)')
|
|
64
|
+
.action(async (/** @type {string | undefined} */ query, /** @type {{type?: import('../../types/search').SearchDomain, limit?: string, detail?: boolean}} */ options) => {
|
|
65
|
+
const run = getCliInvocation();
|
|
66
|
+
const json = program.opts().json || false;
|
|
67
|
+
|
|
68
|
+
// No query → the playbook. Still routed through the API for the envelope.
|
|
69
|
+
if (!query || !String(query).trim()) {
|
|
70
|
+
const result = await buildApi(undefined, {cwd: process.cwd()});
|
|
71
|
+
if (json) return jsonOut(result.type, result.data);
|
|
72
|
+
printPlaybook(run);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Arg validation stays in the CLI.
|
|
77
|
+
let limit = 60;
|
|
78
|
+
if (options.limit != null) {
|
|
79
|
+
const parsed = Number.parseInt(options.limit, 10);
|
|
80
|
+
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
81
|
+
cliError(`Invalid --limit value "${options.limit}". Must be a positive integer.`);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
limit = parsed;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** @type {import('../../types/build').BuildKitResponse} */
|
|
88
|
+
let result;
|
|
89
|
+
try {
|
|
90
|
+
result = /** @type {import('../../types/build').BuildKitResponse} */ (
|
|
91
|
+
await buildApi(query, {cwd: process.cwd(), type: options.type, limit})
|
|
92
|
+
);
|
|
93
|
+
} catch (e) {
|
|
94
|
+
const err = /** @type {import('../../api/error.mjs').AstryxError} */ (e);
|
|
95
|
+
cliError(err.message, {suggestions: err.suggestions});
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (json) return jsonOut(result.type, result.data);
|
|
100
|
+
|
|
101
|
+
const {query: q, hasResults, directMatch, pages, blocks, domain, frame, foundation} =
|
|
102
|
+
result.data;
|
|
103
|
+
|
|
104
|
+
if (!hasResults) {
|
|
105
|
+
humanLog('');
|
|
106
|
+
humanLog(`No matches for "${q}".`);
|
|
107
|
+
humanLog(`Try a broader term, or browse: ${run} component --list`);
|
|
108
|
+
humanLog('');
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const printItem = (/** @type {import('../../types/search').SearchResultEntry} */ r, /** @type {string} */ label) => {
|
|
113
|
+
const display = r.domain === 'template' && r.displayName ? r.displayName : r.name;
|
|
114
|
+
humanLog('');
|
|
115
|
+
humanLog(` [${label}] ${display}`);
|
|
116
|
+
if (r.description) humanLog(` ${r.description}`);
|
|
117
|
+
humanLog(` → ${formatCliCommand(r.command)}`);
|
|
118
|
+
if (options.detail) {
|
|
119
|
+
if (r.import) humanLog(` import: ${r.import}`);
|
|
120
|
+
humanLog(` match: ${r.reason} (score ${r.score})`);
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
humanLog('');
|
|
125
|
+
humanLog(`Building "${q}":`);
|
|
126
|
+
|
|
127
|
+
// START — the single recommended path.
|
|
128
|
+
humanLog('');
|
|
129
|
+
if (directMatch) {
|
|
130
|
+
humanLog(`START → Scaffold the \`${pages[0].name}\` page template, then adapt: ${run} template ${pages[0].name} ./src/App.tsx`);
|
|
131
|
+
} else if (pages.length) {
|
|
132
|
+
humanLog(`START → No exact page template. Use \`${pages[0].name}\` as a layout reference (${run} template ${pages[0].name} --skeleton) and compose the pieces below.`);
|
|
133
|
+
} else {
|
|
134
|
+
humanLog(`START → No page template fits. Frame with AppShell and compose the blocks + components below.`);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// PAGE
|
|
138
|
+
if (pages.length) {
|
|
139
|
+
humanLog('');
|
|
140
|
+
humanLog(directMatch ? 'PAGE TEMPLATE — direct match:' : 'CLOSEST PAGE TEMPLATES — layout reference:');
|
|
141
|
+
pages.forEach(p => printItem(p, directMatch ? 'page' : 'closest'));
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// FRAME — always (the page shell).
|
|
145
|
+
humanLog('');
|
|
146
|
+
humanLog(`FRAME — page shell (always): ${frame.join(', ')}`);
|
|
147
|
+
humanLog(` full-page → AppShell; or Layout + SideNav/TopNav. ${run} component AppShell`);
|
|
148
|
+
|
|
149
|
+
// BLOCKS — idea-specific composed patterns.
|
|
150
|
+
if (blocks.length) {
|
|
151
|
+
humanLog('');
|
|
152
|
+
humanLog('BLOCKS — drop-in patterns that cover parts of it:');
|
|
153
|
+
blocks.forEach(b => printItem(b, 'block'));
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// DOMAIN COMPONENTS — idea-specific atoms.
|
|
157
|
+
if (domain.length) {
|
|
158
|
+
humanLog('');
|
|
159
|
+
humanLog('DOMAIN COMPONENTS — specific to this idea:');
|
|
160
|
+
domain.forEach(c => printItem(c, c.domain === 'hook' ? 'hook' : 'component'));
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// FOUNDATION — always (layout/typography/actions).
|
|
164
|
+
humanLog('');
|
|
165
|
+
humanLog(`FOUNDATION — always available (layout/text/actions): ${foundation.join(' ')}`);
|
|
166
|
+
|
|
167
|
+
// SETUP — so it renders / stays on-system.
|
|
168
|
+
humanLog('');
|
|
169
|
+
humanLog('SETUP — import "@astryxdesign/core/reset.css" + "astryx.css". No <div>/style for layout — use Stack/Grid + tokens.');
|
|
170
|
+
humanLog('');
|
|
171
|
+
});
|
|
172
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file Guardrail tests for the @astryxdesign/cli postinstall nudge (layer 2).
|
|
5
|
+
*
|
|
6
|
+
* Tests the pure decision matrix (shouldNudge) — nudges for a real dependency
|
|
7
|
+
* install when not set up; stays quiet in the monorepo/source, during npx's
|
|
8
|
+
* transient fetch (path _npx or npm_command=exec), and once set up.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import {describe, it, expect} from 'vitest';
|
|
12
|
+
import {shouldNudge} from '../../scripts/postinstall.mjs';
|
|
13
|
+
|
|
14
|
+
const DEP = '/proj/node_modules/@astryxdesign/cli/scripts/postinstall.mjs'; // real dep install
|
|
15
|
+
const NPX = '/Users/x/.npm/_npx/a1b2/node_modules/@astryxdesign/cli/scripts/postinstall.mjs';
|
|
16
|
+
const REPO = '/repo/packages/cli/scripts/postinstall.mjs'; // monorepo/source
|
|
17
|
+
|
|
18
|
+
describe('cli postinstall — shouldNudge', () => {
|
|
19
|
+
it('nudges for a real dependency install when not set up', () => {
|
|
20
|
+
expect(shouldNudge({scriptPath: DEP, npmCommand: 'install', isSetUp: false})).toBe(true);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('quiet in the monorepo/source (not under node_modules)', () => {
|
|
24
|
+
expect(shouldNudge({scriptPath: REPO, npmCommand: 'install', isSetUp: false})).toBe(false);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('quiet during npx transient install (path contains _npx)', () => {
|
|
28
|
+
expect(shouldNudge({scriptPath: NPX, npmCommand: 'install', isSetUp: false})).toBe(false);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('quiet during npx (npm_command=exec) — avoids double-nudge before init', () => {
|
|
32
|
+
expect(shouldNudge({scriptPath: DEP, npmCommand: 'exec', isSetUp: false})).toBe(false);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('quiet once the project is already set up', () => {
|
|
36
|
+
expect(shouldNudge({scriptPath: DEP, npmCommand: 'install', isSetUp: true})).toBe(false);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('quiet with no script path (defensive)', () => {
|
|
40
|
+
expect(shouldNudge({})).toBe(false);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
@@ -6,27 +6,47 @@
|
|
|
6
6
|
* Global options: --detail full|compact|brief, --lang en|zh|dense
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import {findCoreDir} from '
|
|
9
|
+
import {findCoreDir} from '../../../utils/paths.mjs';
|
|
10
10
|
import {
|
|
11
11
|
resolveImportPath,
|
|
12
|
-
} from '
|
|
12
|
+
} from '../../../lib/component-discovery.mjs';
|
|
13
13
|
import {
|
|
14
14
|
formatFull,
|
|
15
15
|
formatCompact,
|
|
16
16
|
formatBrief,
|
|
17
17
|
formatProps,
|
|
18
18
|
formatBriefAll,
|
|
19
|
-
} from '
|
|
20
|
-
import {resolveTheme} from '
|
|
21
|
-
import {
|
|
22
|
-
import {jsonOut, humanLog} from '
|
|
23
|
-
import {cliError} from '
|
|
24
|
-
import {ERROR_CODES} from '
|
|
25
|
-
import {component as componentApi} from '
|
|
26
|
-
import {findRelatedBlocks} from '
|
|
27
|
-
import {Project} from '
|
|
28
|
-
import {warnOnIntegrationIssues} from '
|
|
19
|
+
} from '../../../lib/component-format.mjs';
|
|
20
|
+
import {resolveTheme} from '../../../lib/resolve-theme.mjs';
|
|
21
|
+
import {getCliInvocation} from '../../../utils/package-manager.mjs';
|
|
22
|
+
import {jsonOut, humanLog} from '../../../lib/json.mjs';
|
|
23
|
+
import {cliError} from '../../../lib/cli-error.mjs';
|
|
24
|
+
import {ERROR_CODES} from '../../../lib/error-codes.mjs';
|
|
25
|
+
import {component as componentApi} from '../../../api/component/component.mjs';
|
|
26
|
+
import {findRelatedBlocks} from '../../../api/template/template.mjs';
|
|
27
|
+
import {Project} from '../../../lib/project.mjs';
|
|
28
|
+
import {warnOnIntegrationIssues} from '../../../lib/integration-warnings.mjs';
|
|
29
29
|
|
|
30
|
+
/**
|
|
31
|
+
* The api layer's component() widens its return to `{type: string, data: unknown}`,
|
|
32
|
+
* so annotate the command-local result with the precise discriminated union from
|
|
33
|
+
* src/types/component to get narrowing + typed data.
|
|
34
|
+
*
|
|
35
|
+
* @typedef {(
|
|
36
|
+
* | import('../../../types/component').ComponentListResponse
|
|
37
|
+
* | import('../../../types/component').ComponentBriefResponse
|
|
38
|
+
* | import('../../../types/component').ComponentFullResponse
|
|
39
|
+
* | import('../../../types/component').ComponentDetailResponse
|
|
40
|
+
* | import('../../../types/component').ComponentDetailPropsResponse
|
|
41
|
+
* | import('../../../types/component').ComponentDetailSourceResponse
|
|
42
|
+
* | import('../../../types/component').ComponentDetailShowcaseResponse
|
|
43
|
+
* | import('../../../types/component').ComponentDetailBlocksResponse
|
|
44
|
+
* )} ComponentResult
|
|
45
|
+
*/
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @param {import('commander').Command} program
|
|
49
|
+
*/
|
|
30
50
|
export function registerComponent(program) {
|
|
31
51
|
program
|
|
32
52
|
.command('component [name]')
|
|
@@ -38,8 +58,8 @@ export function registerComponent(program) {
|
|
|
38
58
|
.option('--showcase', 'Print showcase source code')
|
|
39
59
|
.option('--blocks', 'List example blocks: showcase, examples, and related')
|
|
40
60
|
.option('--package <name>', 'Scope lookup to an external package (e.g. @acme/xds-widgets)')
|
|
41
|
-
.action(async (name, options) => {
|
|
42
|
-
const run =
|
|
61
|
+
.action(async (/** @type {string | undefined} */ name, /** @type {{list?: boolean, category?: string, props?: boolean, source?: boolean, showcase?: boolean, blocks?: boolean, package?: string}} */ options) => {
|
|
62
|
+
const run = getCliInvocation();
|
|
43
63
|
const zh = program.opts().zh || false;
|
|
44
64
|
const dense = program.opts().dense || false;
|
|
45
65
|
const lang = program.opts().lang || null;
|
|
@@ -67,9 +87,10 @@ export function registerComponent(program) {
|
|
|
67
87
|
// Never let the nudge break the command.
|
|
68
88
|
}
|
|
69
89
|
|
|
90
|
+
/** @type {ComponentResult} */
|
|
70
91
|
let result;
|
|
71
92
|
try {
|
|
72
|
-
result = await componentApi(name, {
|
|
93
|
+
result = /** @type {ComponentResult} */ (await componentApi(name, {
|
|
73
94
|
cwd: process.cwd(),
|
|
74
95
|
list: options.list,
|
|
75
96
|
category: options.category,
|
|
@@ -80,16 +101,19 @@ export function registerComponent(program) {
|
|
|
80
101
|
blocks: options.blocks,
|
|
81
102
|
detail,
|
|
82
103
|
lang, zh, dense,
|
|
83
|
-
});
|
|
104
|
+
}));
|
|
84
105
|
} catch (e) {
|
|
85
|
-
|
|
106
|
+
const err = /** @type {import('../../../api/error.mjs').AstryxError} */ (e);
|
|
107
|
+
cliError(err.message, {suggestions: err.suggestions, code: err.code});
|
|
86
108
|
return;
|
|
87
109
|
}
|
|
88
110
|
|
|
89
111
|
if (json) return jsonOut(result.type, result.data);
|
|
90
112
|
|
|
91
113
|
// ── Text output ────────────────────────────────────────────
|
|
92
|
-
|
|
114
|
+
// The api layer already resolved against core (result exists), so core is
|
|
115
|
+
// present on this path; narrow away the null branch findCoreDir allows.
|
|
116
|
+
const coreDir = /** @type {string} */ (findCoreDir(process.cwd()));
|
|
93
117
|
const themeData = resolveTheme(process.cwd());
|
|
94
118
|
|
|
95
119
|
switch (result.type) {
|
|
@@ -101,6 +125,7 @@ export function registerComponent(program) {
|
|
|
101
125
|
const CORE_PKG = '@astryxdesign/core';
|
|
102
126
|
// Names that appear under more than one package across the whole
|
|
103
127
|
// listing — these must always be package-qualified to disambiguate.
|
|
128
|
+
/** @type {Map<string, Set<string>>} */
|
|
104
129
|
const nameCounts = new Map();
|
|
105
130
|
for (const items of Object.values(result.data)) {
|
|
106
131
|
for (const item of items) {
|
|
@@ -109,7 +134,9 @@ export function registerComponent(program) {
|
|
|
109
134
|
nameCounts.set(item.name, set);
|
|
110
135
|
}
|
|
111
136
|
}
|
|
137
|
+
/** @param {string} n */
|
|
112
138
|
const isCollision = n => (nameCounts.get(n)?.size ?? 0) > 1;
|
|
139
|
+
/** @param {import('../../../types/component').ComponentListEntry} item */
|
|
113
140
|
const pkgSuffix = item => {
|
|
114
141
|
if (item.package !== CORE_PKG) return ` [${item.package}]`;
|
|
115
142
|
if (isCollision(item.name)) return ` [${item.package}]`;
|
|
@@ -142,7 +169,7 @@ export function registerComponent(program) {
|
|
|
142
169
|
}
|
|
143
170
|
humanLog('');
|
|
144
171
|
humanLog(`Import from the path shown (e.g. import {Button} from '@astryxdesign/core/Button')`);
|
|
145
|
-
humanLog(`Usage: ${run}
|
|
172
|
+
humanLog(`Usage: ${run} component <name>`);
|
|
146
173
|
humanLog('');
|
|
147
174
|
}
|
|
148
175
|
break;
|
|
@@ -165,7 +192,7 @@ export function registerComponent(program) {
|
|
|
165
192
|
humanLog('');
|
|
166
193
|
}
|
|
167
194
|
humanLog(`Import from the path shown (e.g. import {Button} from '@astryxdesign/core/Button')`);
|
|
168
|
-
humanLog(`Usage: ${run}
|
|
195
|
+
humanLog(`Usage: ${run} component <name>`);
|
|
169
196
|
humanLog('');
|
|
170
197
|
break;
|
|
171
198
|
}
|
|
@@ -251,8 +278,8 @@ export function registerComponent(program) {
|
|
|
251
278
|
|
|
252
279
|
// Re-export lib functions for backward compatibility
|
|
253
280
|
// (agent-docs.mjs, tests, and generate-skill-doc.sh import from here)
|
|
254
|
-
export {discoverComponents, discoverExternalComponents, discoverExternalComponentsGrouped, findComponentReadme, findComponentSource, findExternalComponentDoc, resolveImportPath} from '
|
|
255
|
-
export {discoverExternalPackages} from '
|
|
256
|
-
export {loadDocs} from '
|
|
257
|
-
export {formatFull, formatCompact, formatBrief, formatProps, formatBriefAll} from '
|
|
258
|
-
export {levenshteinDistance, findClosestComponents, searchComponents} from '
|
|
281
|
+
export {discoverComponents, discoverExternalComponents, discoverExternalComponentsGrouped, findComponentReadme, findComponentSource, findExternalComponentDoc, resolveImportPath} from '../../../lib/component-discovery.mjs';
|
|
282
|
+
export {discoverExternalPackages} from '../../../utils/paths.mjs';
|
|
283
|
+
export {loadDocs} from '../../../lib/component-loader.mjs';
|
|
284
|
+
export {formatFull, formatCompact, formatBrief, formatProps, formatBriefAll} from '../../../lib/component-format.mjs';
|
|
285
|
+
export {levenshteinDistance, findClosestComponents, searchComponents} from '../../../lib/string-utils.mjs';
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
findIntegrationComponentDoc,
|
|
11
11
|
findIntegrationComponentSource,
|
|
12
12
|
CORE_PACKAGE,
|
|
13
|
-
} from '
|
|
13
|
+
} from '../../lib/component-discovery.mjs';
|
|
14
14
|
|
|
15
15
|
// The api `component()` reads integrations via Project.load(). In the vitest
|
|
16
16
|
// environment, Vite's `server.fs.allow` only permits loading modules from
|
|
@@ -20,12 +20,12 @@ import {
|
|
|
20
20
|
// produces) while keeping the integration's `components` dir on disk under
|
|
21
21
|
// node_modules so its `.doc.mjs` files load normally.
|
|
22
22
|
const projectLoadMock = vi.fn();
|
|
23
|
-
vi.mock('
|
|
23
|
+
vi.mock('../../lib/project.mjs', () => ({
|
|
24
24
|
Project: {load: (...args) => projectLoadMock(...args)},
|
|
25
25
|
}));
|
|
26
26
|
|
|
27
27
|
// Import the api AFTER the mock is registered.
|
|
28
|
-
const {component} = await import('
|
|
28
|
+
const {component} = await import('../../api/component/component.mjs');
|
|
29
29
|
|
|
30
30
|
let tmpDir;
|
|
31
31
|
|
|
@@ -4,7 +4,7 @@ import {describe, it, expect, beforeEach, afterEach} from 'vitest';
|
|
|
4
4
|
import * as fs from 'node:fs';
|
|
5
5
|
import * as path from 'node:path';
|
|
6
6
|
import * as os from 'node:os';
|
|
7
|
-
import {component} from '
|
|
7
|
+
import {component} from '../../api/component/component.mjs';
|
|
8
8
|
|
|
9
9
|
// These tests create a minimal monorepo fixture with:
|
|
10
10
|
// - packages/core (symlinked to real @astryxdesign/core for loadDocs compatibility)
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
2
|
|
|
3
3
|
import {describe, it, expect} from 'vitest';
|
|
4
|
-
import {component} from '
|
|
5
|
-
import {findShowcase, findRelatedBlocks} from '
|
|
4
|
+
import {component} from '../../api/component/component.mjs';
|
|
5
|
+
import {findShowcase, findRelatedBlocks} from '../../api/template/template.mjs';
|
|
6
6
|
|
|
7
7
|
const CWD = {cwd: '.'};
|
|
8
8
|
|
|
@@ -10,27 +10,38 @@
|
|
|
10
10
|
* astryx discover searchterm Search across all packages
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import {formatFull, formatBrief, formatCompact} from '
|
|
14
|
-
import {jsonOut, humanLog} from '
|
|
15
|
-
import {cliError} from '
|
|
16
|
-
import {discover as discoverApi} from '
|
|
13
|
+
import {formatFull, formatBrief, formatCompact} from '../../lib/component-format.mjs';
|
|
14
|
+
import {jsonOut, humanLog} from '../../lib/json.mjs';
|
|
15
|
+
import {cliError} from '../../lib/cli-error.mjs';
|
|
16
|
+
import {discover as discoverApi} from '../../api/discover/discover.mjs';
|
|
17
|
+
import {getCliInvocation} from '../../utils/package-manager.mjs';
|
|
17
18
|
|
|
19
|
+
/**
|
|
20
|
+
* @param {import('commander').Command} program
|
|
21
|
+
*/
|
|
18
22
|
export function registerDiscover(program) {
|
|
19
23
|
program
|
|
20
24
|
.command('discover [query]')
|
|
21
25
|
.description('Discover external packages and components')
|
|
22
26
|
.option('--components', 'List components only')
|
|
23
|
-
.action(
|
|
27
|
+
.action(
|
|
28
|
+
/**
|
|
29
|
+
* @param {string | undefined} query
|
|
30
|
+
* @param {{components?: boolean}} options
|
|
31
|
+
*/
|
|
32
|
+
async (query, options) => {
|
|
24
33
|
const detail = program.opts().detail || 'full';
|
|
25
34
|
const json = program.opts().json || false;
|
|
26
35
|
const lang = program.opts().lang || null;
|
|
27
36
|
const zh = program.opts().zh || false;
|
|
37
|
+
const run = getCliInvocation();
|
|
28
38
|
|
|
29
39
|
let result;
|
|
30
40
|
try {
|
|
31
41
|
result = await discoverApi(query, {components: options.components, lang, zh});
|
|
32
42
|
} catch (e) {
|
|
33
|
-
|
|
43
|
+
const err = /** @type {import('../../api/error.mjs').AstryxError} */ (e);
|
|
44
|
+
cliError(err.message, {suggestions: err.suggestions, code: err.code});
|
|
34
45
|
return;
|
|
35
46
|
}
|
|
36
47
|
|
|
@@ -38,7 +49,7 @@ export function registerDiscover(program) {
|
|
|
38
49
|
// Forward optional meta (e.g. configured flag for discover.list) as a
|
|
39
50
|
// sibling of data via jsonOut, so the envelope still carries
|
|
40
51
|
// apiVersion and goes through the single sanctioned emit path.
|
|
41
|
-
return jsonOut(result.type, result.data, result.meta);
|
|
52
|
+
return jsonOut(result.type, result.data, 'meta' in result ? result.meta : undefined);
|
|
42
53
|
}
|
|
43
54
|
|
|
44
55
|
switch (result.type) {
|
|
@@ -80,9 +91,9 @@ export function registerDiscover(program) {
|
|
|
80
91
|
humanLog('');
|
|
81
92
|
}
|
|
82
93
|
humanLog('Usage:');
|
|
83
|
-
humanLog(
|
|
84
|
-
humanLog(
|
|
85
|
-
humanLog(
|
|
94
|
+
humanLog(` ${run} discover <package> Browse a package`);
|
|
95
|
+
humanLog(` ${run} discover <package>/Component View component docs`);
|
|
96
|
+
humanLog(` ${run} discover <search> Search all packages`);
|
|
86
97
|
humanLog('');
|
|
87
98
|
}
|
|
88
99
|
break;
|
|
@@ -99,7 +110,7 @@ export function registerDiscover(program) {
|
|
|
99
110
|
humanLog('');
|
|
100
111
|
for (const comp of result.data.components) humanLog(' ' + comp);
|
|
101
112
|
humanLog('');
|
|
102
|
-
humanLog(
|
|
113
|
+
humanLog(`Usage: ${run} discover ` + result.data.name + '/<ComponentName>');
|
|
103
114
|
humanLog('');
|
|
104
115
|
break;
|
|
105
116
|
}
|
|
@@ -122,7 +133,7 @@ export function registerDiscover(program) {
|
|
|
122
133
|
humanLog('Found ' + result.data.matches.length + ' matches for "' + result.data.query + '":');
|
|
123
134
|
humanLog('');
|
|
124
135
|
for (const m of result.data.matches) {
|
|
125
|
-
humanLog(
|
|
136
|
+
humanLog(` ${run} discover ` + m.package + '/' + m.component);
|
|
126
137
|
}
|
|
127
138
|
humanLog('');
|
|
128
139
|
break;
|
|
@@ -12,13 +12,18 @@
|
|
|
12
12
|
* astryx docs <topic> <section> Print one section
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
import {
|
|
16
|
-
import {jsonOut, humanLog} from '
|
|
17
|
-
import {cliError} from '
|
|
18
|
-
import {docs as docsApi} from '
|
|
15
|
+
import {getCliInvocation} from '../../utils/package-manager.mjs';
|
|
16
|
+
import {jsonOut, humanLog} from '../../lib/json.mjs';
|
|
17
|
+
import {cliError} from '../../lib/cli-error.mjs';
|
|
18
|
+
import {docs as docsApi} from '../../api/docs/docs.mjs';
|
|
19
19
|
|
|
20
20
|
// ─── Formatting ──────────────────────────────────────────────────────────────
|
|
21
21
|
|
|
22
|
+
/**
|
|
23
|
+
* @param {string[]} headers
|
|
24
|
+
* @param {string[][]} rows
|
|
25
|
+
* @returns {string}
|
|
26
|
+
*/
|
|
22
27
|
function formatTable(headers, rows) {
|
|
23
28
|
const widths = headers.map((h, i) =>
|
|
24
29
|
Math.max(h.length, ...rows.map(r => (r[i] || '').length)),
|
|
@@ -31,15 +36,28 @@ function formatTable(headers, rows) {
|
|
|
31
36
|
return `${head}\n${sep}\n${body}`;
|
|
32
37
|
}
|
|
33
38
|
|
|
39
|
+
/**
|
|
40
|
+
* @param {string[]} headers
|
|
41
|
+
* @param {string[][]} rows
|
|
42
|
+
* @returns {string}
|
|
43
|
+
*/
|
|
34
44
|
function formatTableCompact(headers, rows) {
|
|
35
45
|
return rows.map(r => r.join(' = ')).join('\n');
|
|
36
46
|
}
|
|
37
47
|
|
|
48
|
+
/**
|
|
49
|
+
* @param {import('../../../core/src/docs-types').ContentBlock} block
|
|
50
|
+
* @param {'full' | 'compact' | 'brief'} detail
|
|
51
|
+
* @returns {string | null}
|
|
52
|
+
*/
|
|
38
53
|
function formatBlock(block, detail) {
|
|
39
54
|
switch (block.type) {
|
|
40
55
|
case 'prose':
|
|
41
56
|
return block.text;
|
|
42
57
|
|
|
58
|
+
case 'heading':
|
|
59
|
+
return `${'#'.repeat(block.level || 3)} ${block.text}`;
|
|
60
|
+
|
|
43
61
|
case 'code':
|
|
44
62
|
if (detail === 'compact' || detail === 'brief') return null;
|
|
45
63
|
{
|
|
@@ -57,7 +75,7 @@ function formatBlock(block, detail) {
|
|
|
57
75
|
return formatTable(block.headers, block.rows);
|
|
58
76
|
|
|
59
77
|
case 'list': {
|
|
60
|
-
const prefix = block.style === 'ordered' ? (i) => `${i + 1}. `
|
|
78
|
+
const prefix = block.style === 'ordered' ? (/** @type {number} */ i) => `${i + 1}. `
|
|
61
79
|
: block.style === 'dont' ? () => '❌ '
|
|
62
80
|
: block.style === 'do' ? () => '✓ '
|
|
63
81
|
: () => '- ';
|
|
@@ -69,6 +87,11 @@ function formatBlock(block, detail) {
|
|
|
69
87
|
}
|
|
70
88
|
}
|
|
71
89
|
|
|
90
|
+
/**
|
|
91
|
+
* @param {import('../../../core/src/docs-types').ReferenceSection} section
|
|
92
|
+
* @param {'full' | 'compact' | 'brief'} detail
|
|
93
|
+
* @returns {string}
|
|
94
|
+
*/
|
|
72
95
|
function formatSection(section, detail) {
|
|
73
96
|
const blocks = section.content
|
|
74
97
|
.map(b => formatBlock(b, detail))
|
|
@@ -83,6 +106,11 @@ function formatSection(section, detail) {
|
|
|
83
106
|
return `${heading}\n\n${blocks.join('\n\n')}`;
|
|
84
107
|
}
|
|
85
108
|
|
|
109
|
+
/**
|
|
110
|
+
* @param {import('../../../core/src/docs-types').ReferenceDoc} docs
|
|
111
|
+
* @param {'full' | 'compact' | 'brief'} detail
|
|
112
|
+
* @returns {string}
|
|
113
|
+
*/
|
|
86
114
|
function formatReferenceFull(docs, detail) {
|
|
87
115
|
if (detail === 'brief') {
|
|
88
116
|
const header = `${docs.title}: ${docs.description}`;
|
|
@@ -100,12 +128,15 @@ function formatReferenceFull(docs, detail) {
|
|
|
100
128
|
|
|
101
129
|
// ─── Command ─────────────────────────────────────────────────────────────────
|
|
102
130
|
|
|
131
|
+
/**
|
|
132
|
+
* @param {import('commander').Command} program
|
|
133
|
+
*/
|
|
103
134
|
export function registerDocs(program) {
|
|
104
135
|
program
|
|
105
136
|
.command('docs [topic] [section]')
|
|
106
137
|
.description('Print reference docs')
|
|
107
|
-
.action(async (topic, section) => {
|
|
108
|
-
const run =
|
|
138
|
+
.action(async (/** @type {string | undefined} */ topic, /** @type {string | undefined} */ section) => {
|
|
139
|
+
const run = getCliInvocation();
|
|
109
140
|
const lang = program.opts().lang || null;
|
|
110
141
|
const zh = program.opts().zh || false;
|
|
111
142
|
const dense = program.opts().dense || false;
|
|
@@ -118,7 +149,8 @@ export function registerDocs(program) {
|
|
|
118
149
|
} catch (e) {
|
|
119
150
|
// docs API throws structured errors with {name, reason} suggestions —
|
|
120
151
|
// pass them through untouched so the CLI envelope matches the API.
|
|
121
|
-
|
|
152
|
+
const err = /** @type {import('../../api/error.mjs').AstryxError} */ (e);
|
|
153
|
+
cliError(err.message, {suggestions: err.suggestions || [], code: err.code});
|
|
122
154
|
return;
|
|
123
155
|
}
|
|
124
156
|
|
|
@@ -130,8 +162,8 @@ export function registerDocs(program) {
|
|
|
130
162
|
for (const entry of result.data) {
|
|
131
163
|
humanLog(` ${entry.topic.padEnd(14)} ${entry.description}`);
|
|
132
164
|
}
|
|
133
|
-
humanLog(`\nUsage: ${run}
|
|
134
|
-
humanLog(` ${run}
|
|
165
|
+
humanLog(`\nUsage: ${run} docs <topic>`);
|
|
166
|
+
humanLog(` ${run} docs <topic> <section>\n`);
|
|
135
167
|
break;
|
|
136
168
|
}
|
|
137
169
|
|
|
@@ -71,7 +71,7 @@ describe('hyphenated doc filenames', () => {
|
|
|
71
71
|
});
|
|
72
72
|
|
|
73
73
|
it('returns docs.detail via API for hyphenated topic', async () => {
|
|
74
|
-
const {docs: docsApi} = await import('
|
|
74
|
+
const {docs: docsApi} = await import('../../api/docs/docs.mjs');
|
|
75
75
|
const result = await docsApi('getting-started');
|
|
76
76
|
expect(result.type).toBe('docs.detail');
|
|
77
77
|
expect(result.data).toBeDefined();
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
* as a CI gate.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import {runChecks} from '
|
|
14
|
-
import {jsonOut, humanLog} from '
|
|
13
|
+
import {runChecks} from '../../api/doctor/doctor.mjs';
|
|
14
|
+
import {jsonOut, humanLog} from '../../lib/json.mjs';
|
|
15
15
|
|
|
16
16
|
/** Status → human glyph (monochrome, matching the rest of the CLI). */
|
|
17
17
|
const GLYPH = {
|
|
@@ -23,7 +23,7 @@ const GLYPH = {
|
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* Render the report as a human-readable checklist.
|
|
26
|
-
* @param {import('
|
|
26
|
+
* @param {import('../../api/doctor/doctor.mjs').DoctorReport} report
|
|
27
27
|
*/
|
|
28
28
|
function printHuman(report) {
|
|
29
29
|
humanLog('astryx doctor — diagnosing your setup\n');
|