@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
package/src/commands/build.mjs
DELETED
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @file build command — the page-building assistant.
|
|
5
|
-
*
|
|
6
|
-
* Two modes:
|
|
7
|
-
* astryx build → the PLAYBOOK: how to build a page with Astryx
|
|
8
|
-
* astryx build "<what>" → a COMPOSITION KIT for what you're building:
|
|
9
|
-
* the closest page template (scaffold or layout
|
|
10
|
-
* reference), the blocks that cover parts, and
|
|
11
|
-
* the components to fill gaps, plus a one-line
|
|
12
|
-
* "Compose:" suggestion.
|
|
13
|
-
*
|
|
14
|
-
* `build` is the opinionated "assemble a page" verb. For a neutral lookup across
|
|
15
|
-
* the whole CLI, use `astryx search <query>` instead.
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
import {getRunPrefix} from '../utils/package-manager.mjs';
|
|
19
|
-
import {jsonOut, humanLog} from '../lib/json.mjs';
|
|
20
|
-
import {cliError} from '../lib/cli-error.mjs';
|
|
21
|
-
import {search as searchApi} from '../api/search.mjs';
|
|
22
|
-
|
|
23
|
-
/** A page scoring at/above this is confident enough to call a direct match. */
|
|
24
|
-
const PAGE_DIRECT = 95;
|
|
25
|
-
/** Below this a page is too weak to even offer as a layout reference. */
|
|
26
|
-
const PAGE_FLOOR = 50;
|
|
27
|
-
/** Below this a block/domain-component match is incidental noise, not surfaced. */
|
|
28
|
-
const DOMAIN_FLOOR = 55;
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Always-surfaced primitives. Every page needs a shell + layout/typography/
|
|
32
|
-
* action atoms, but these never keyword-match an idea ("dashboard" != "Stack"),
|
|
33
|
-
* so search alone never returns them. We list them unconditionally so an agent
|
|
34
|
-
* composing from scratch has the whole kit (esp. off-template).
|
|
35
|
-
*/
|
|
36
|
-
const FRAME = ['AppShell', 'TopNav', 'SideNav', 'Layout'];
|
|
37
|
-
const FOUNDATION = [
|
|
38
|
-
'VStack', 'HStack', 'Grid', 'StackItem', 'Card', 'Section',
|
|
39
|
-
'Text', 'Heading', 'Button', 'Icon', 'Badge', 'Divider',
|
|
40
|
-
];
|
|
41
|
-
const ALWAYS = new Set([...FRAME, ...FOUNDATION]);
|
|
42
|
-
|
|
43
|
-
/** Print the build playbook (shown when `build` is run with no query). */
|
|
44
|
-
function printPlaybook(run) {
|
|
45
|
-
const lines = [
|
|
46
|
-
'',
|
|
47
|
-
'How to build a page with Astryx',
|
|
48
|
-
'',
|
|
49
|
-
"1. Find a starting point for what you're building:",
|
|
50
|
-
` ${run} astryx build "<what you're building>"`,
|
|
51
|
-
' → returns the closest [page] template, the [block]s that cover parts,',
|
|
52
|
-
' and the [component]s to fill the gaps, with a "Compose:" suggestion.',
|
|
53
|
-
'',
|
|
54
|
-
'2. If a [page] template matches → scaffold it and adapt:',
|
|
55
|
-
` ${run} astryx template <name> [path]`,
|
|
56
|
-
'',
|
|
57
|
-
'3. If nothing matches exactly → compose:',
|
|
58
|
-
` ${run} astryx template <name> --skeleton # study a close page's layout`,
|
|
59
|
-
` ${run} astryx template <BlockName> # drop in each block from the kit`,
|
|
60
|
-
` ${run} astryx component <Name> # fill remaining gaps (read props)`,
|
|
61
|
-
'',
|
|
62
|
-
'4. Rules (keep it on-system):',
|
|
63
|
-
' - No <div>/raw HTML for layout — use VStack/HStack/Grid/Stack/Card etc.',
|
|
64
|
-
' - No style={{}} — use component props; design tokens via `astryx docs tokens`.',
|
|
65
|
-
' - Wrap the app in <Theme theme={...}> and import core reset.css + astryx.css.',
|
|
66
|
-
'',
|
|
67
|
-
`Tip: \`${run} astryx build "<idea>"\` is the fastest way in. For a neutral`,
|
|
68
|
-
`lookup of any component/doc/template, use \`${run} astryx search <query>\`.`,
|
|
69
|
-
'',
|
|
70
|
-
];
|
|
71
|
-
for (const l of lines) humanLog(l);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export function registerBuild(program) {
|
|
75
|
-
program
|
|
76
|
-
.command('build [query]')
|
|
77
|
-
.description('Build a page: composition kit for an idea, or the workflow playbook (no args)')
|
|
78
|
-
.option('--type <domain>', 'Filter the kit to one domain (component|hook|template)')
|
|
79
|
-
.option('--limit <n>', 'Max candidates to draw from (default 60)')
|
|
80
|
-
.option('--detail', 'Verbose output (include import paths and match reason)')
|
|
81
|
-
.action(async (query, options) => {
|
|
82
|
-
const run = getRunPrefix();
|
|
83
|
-
const json = program.opts().json || false;
|
|
84
|
-
|
|
85
|
-
// No query → print the playbook (the "how to build" skill).
|
|
86
|
-
if (!query || !String(query).trim()) {
|
|
87
|
-
if (json) return jsonOut('build.help', {playbook: true});
|
|
88
|
-
printPlaybook(run);
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Default to a deep pool so each role section has candidates after grouping.
|
|
93
|
-
let limit = 60;
|
|
94
|
-
if (options.limit != null) {
|
|
95
|
-
const parsed = Number.parseInt(options.limit, 10);
|
|
96
|
-
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
97
|
-
cliError(`Invalid --limit value "${options.limit}". Must be a positive integer.`);
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
limit = parsed;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
let result;
|
|
104
|
-
try {
|
|
105
|
-
result = await searchApi(query, {cwd: process.cwd(), type: options.type, limit});
|
|
106
|
-
} catch (e) {
|
|
107
|
-
cliError(e.message, {suggestions: e.suggestions});
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
if (json) return jsonOut(result.type, result.data);
|
|
112
|
-
|
|
113
|
-
const {query: q, results} = result.data;
|
|
114
|
-
|
|
115
|
-
if (results.length === 0) {
|
|
116
|
-
humanLog('');
|
|
117
|
-
humanLog(`No matches for "${q}".`);
|
|
118
|
-
humanLog(`Try a broader term, or browse: ${run} astryx component --list`);
|
|
119
|
-
humanLog('');
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// ── Group results by role (the build kit) ──────────────────────
|
|
124
|
-
const pages = results
|
|
125
|
-
.filter(r => r.domain === 'template' && r.kind !== 'block' && r.score >= PAGE_FLOOR)
|
|
126
|
-
.slice(0, 3);
|
|
127
|
-
const blocks = results
|
|
128
|
-
.filter(r => r.domain === 'template' && r.kind === 'block' && r.score >= DOMAIN_FLOOR)
|
|
129
|
-
.slice(0, 5);
|
|
130
|
-
// Idea-specific atoms = matched components/hooks MINUS the always-on kit.
|
|
131
|
-
const domain = results
|
|
132
|
-
.filter(r => (r.domain === 'component' || r.domain === 'hook') && r.score >= DOMAIN_FLOOR && !ALWAYS.has(r.name))
|
|
133
|
-
.slice(0, 6);
|
|
134
|
-
const directMatch = pages.length > 0 && pages[0].score >= PAGE_DIRECT;
|
|
135
|
-
|
|
136
|
-
const printItem = (r, label) => {
|
|
137
|
-
const display = r.domain === 'template' && r.displayName ? r.displayName : r.name;
|
|
138
|
-
humanLog('');
|
|
139
|
-
humanLog(` [${label}] ${display}`);
|
|
140
|
-
if (r.description) humanLog(` ${r.description}`);
|
|
141
|
-
humanLog(` → ${run} ${r.command}`);
|
|
142
|
-
if (options.detail) {
|
|
143
|
-
if (r.import) humanLog(` import: ${r.import}`);
|
|
144
|
-
humanLog(` match: ${r.reason} (score ${r.score})`);
|
|
145
|
-
}
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
humanLog('');
|
|
149
|
-
humanLog(`Building "${q}":`);
|
|
150
|
-
|
|
151
|
-
// START — the single recommended path.
|
|
152
|
-
humanLog('');
|
|
153
|
-
if (directMatch) {
|
|
154
|
-
humanLog(`START → Scaffold the \`${pages[0].name}\` page template, then adapt: ${run} astryx template ${pages[0].name} ./src/App.tsx`);
|
|
155
|
-
} else if (pages.length) {
|
|
156
|
-
humanLog(`START → No exact page template. Use \`${pages[0].name}\` as a layout reference (${run} astryx template ${pages[0].name} --skeleton) and compose the pieces below.`);
|
|
157
|
-
} else {
|
|
158
|
-
humanLog(`START → No page template fits. Frame with AppShell and compose the blocks + components below.`);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
// PAGE
|
|
162
|
-
if (pages.length) {
|
|
163
|
-
humanLog('');
|
|
164
|
-
humanLog(directMatch ? 'PAGE TEMPLATE — direct match:' : 'CLOSEST PAGE TEMPLATES — layout reference:');
|
|
165
|
-
pages.forEach(p => printItem(p, directMatch ? 'page' : 'closest'));
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
// FRAME — always (the page shell).
|
|
169
|
-
humanLog('');
|
|
170
|
-
humanLog(`FRAME — page shell (always): ${FRAME.join(', ')}`);
|
|
171
|
-
humanLog(` full-page → AppShell; or Layout + SideNav/TopNav. ${run} astryx component AppShell`);
|
|
172
|
-
|
|
173
|
-
// BLOCKS — idea-specific composed patterns.
|
|
174
|
-
if (blocks.length) {
|
|
175
|
-
humanLog('');
|
|
176
|
-
humanLog('BLOCKS — drop-in patterns that cover parts of it:');
|
|
177
|
-
blocks.forEach(b => printItem(b, 'block'));
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
// DOMAIN COMPONENTS — idea-specific atoms.
|
|
181
|
-
if (domain.length) {
|
|
182
|
-
humanLog('');
|
|
183
|
-
humanLog('DOMAIN COMPONENTS — specific to this idea:');
|
|
184
|
-
domain.forEach(c => printItem(c, c.domain === 'hook' ? 'hook' : 'component'));
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// FOUNDATION — always (layout/typography/actions).
|
|
188
|
-
humanLog('');
|
|
189
|
-
humanLog(`FOUNDATION — always available (layout/text/actions): ${FOUNDATION.join(' ')}`);
|
|
190
|
-
|
|
191
|
-
// SETUP — so it renders / stays on-system.
|
|
192
|
-
humanLog('');
|
|
193
|
-
humanLog('SETUP — import "@astryxdesign/core/reset.css" + "astryx.css". No <div>/style for layout — use Stack/Grid + tokens.');
|
|
194
|
-
humanLog('');
|
|
195
|
-
});
|
|
196
|
-
}
|
package/src/commands/init.mjs
DELETED
|
@@ -1,288 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @file init command — Interactive initialization wizard + feature installer
|
|
5
|
-
*
|
|
6
|
-
* Interactive: `astryx init` walks through all features
|
|
7
|
-
* Non-interactive: `astryx init --features agents,theme,template`
|
|
8
|
-
* Re-runnable: safe to run multiple times, idempotent
|
|
9
|
-
*
|
|
10
|
-
* Features:
|
|
11
|
-
* agents — Install AGENTS.md/CLAUDE.md cheat sheet for AI coding agents
|
|
12
|
-
* theme — Scaffold a custom theme file
|
|
13
|
-
* template — Copy a starter page template
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
import * as p from '@clack/prompts';
|
|
17
|
-
import * as path from 'node:path';
|
|
18
|
-
import * as fs from 'node:fs';
|
|
19
|
-
import {CLI_ROOT} from '../utils/paths.mjs';
|
|
20
|
-
import {PathSafetyError} from '../utils/path-safety.mjs';
|
|
21
|
-
import {getRunPrefix} from '../utils/package-manager.mjs';
|
|
22
|
-
import {installAgentDocs, removeAgentDocs} from './agent-docs.mjs';
|
|
23
|
-
import {listTemplates} from './template.mjs';
|
|
24
|
-
import {humanLog} from '../lib/json.mjs';
|
|
25
|
-
import {cliError} from '../lib/cli-error.mjs';
|
|
26
|
-
import {ERROR_CODES} from '../lib/error-codes.mjs';
|
|
27
|
-
import {requireInteractive} from '../utils/interactive.mjs';
|
|
28
|
-
|
|
29
|
-
const VALID_FEATURES = ['agents', 'theme', 'template'];
|
|
30
|
-
const run = getRunPrefix();
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Build the "Next steps" lines printed at the end of `astryx init`.
|
|
34
|
-
*
|
|
35
|
-
* Theme guidance must match the runtime recommendation emitted by core's
|
|
36
|
-
* <Theme> component (packages/core/src/theme/Theme.tsx): the pre-built theme
|
|
37
|
-
* path (`/built` import + `theme.css`) plus the base CSS import, so users
|
|
38
|
-
* don't end up with an unstyled app or the slower runtime style-injection
|
|
39
|
-
* path. See https://github.com/facebook/astryx/issues/3080.
|
|
40
|
-
*
|
|
41
|
-
* Exported for testing.
|
|
42
|
-
*
|
|
43
|
-
* @param {string} runPrefix package-manager run prefix (e.g. `npx`)
|
|
44
|
-
* @returns {string[]} ordered list of human-facing lines
|
|
45
|
-
*/
|
|
46
|
-
export function getNextSteps(runPrefix) {
|
|
47
|
-
return [
|
|
48
|
-
'',
|
|
49
|
-
' Next steps:',
|
|
50
|
-
" 1. Import base styles: import '@astryxdesign/core/reset.css'",
|
|
51
|
-
" and import '@astryxdesign/core/astryx.css'",
|
|
52
|
-
" 2. Import components: import { Button } from '@astryxdesign/core'",
|
|
53
|
-
' 3. Optionally add a theme (use the pre-built path for performance):',
|
|
54
|
-
" import { neutralTheme } from '@astryxdesign/theme-neutral/built'",
|
|
55
|
-
" import '@astryxdesign/theme-neutral/theme.css'",
|
|
56
|
-
' <Theme theme={neutralTheme}>...</Theme>',
|
|
57
|
-
` For custom themes, run \`${runPrefix} astryx theme build <file>\` to generate the built artifacts.`,
|
|
58
|
-
` 4. ${runPrefix} astryx --help for all commands`,
|
|
59
|
-
'',
|
|
60
|
-
];
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function isCancel(value) {
|
|
64
|
-
if (p.isCancel(value)) {
|
|
65
|
-
p.cancel('Setup cancelled.');
|
|
66
|
-
process.exit(0);
|
|
67
|
-
}
|
|
68
|
-
return value;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// ─── Feature: agents ─────────────────────────────────────────────────────────
|
|
72
|
-
|
|
73
|
-
function runAgents(targetDir, {interactive = true, agent, agentDocsPath} = {}) {
|
|
74
|
-
try {
|
|
75
|
-
const paths = agentDocsPath
|
|
76
|
-
? Array.isArray(agentDocsPath)
|
|
77
|
-
? agentDocsPath
|
|
78
|
-
: [agentDocsPath]
|
|
79
|
-
: undefined;
|
|
80
|
-
const written = installAgentDocs(targetDir, {agent, paths});
|
|
81
|
-
const summary = written.join(', ');
|
|
82
|
-
if (interactive) {
|
|
83
|
-
p.log.success(`AI agent docs installed → ${summary}`);
|
|
84
|
-
} else {
|
|
85
|
-
humanLog(`✓ AI agent docs installed → ${summary}`);
|
|
86
|
-
}
|
|
87
|
-
} catch (err) {
|
|
88
|
-
// PathSafetyError carries a precise, user-actionable message —
|
|
89
|
-
// surface it instead of the generic "could not install" warning so
|
|
90
|
-
// misconfigured --agent-docs-path values aren't silently swallowed.
|
|
91
|
-
if (err instanceof PathSafetyError) {
|
|
92
|
-
const msg = `Error: ${err.message}`;
|
|
93
|
-
if (interactive) {
|
|
94
|
-
p.log.error(msg);
|
|
95
|
-
} else {
|
|
96
|
-
console.error(msg);
|
|
97
|
-
}
|
|
98
|
-
process.exitCode = 1;
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
const msg = `Could not install agent docs. Try again with \`${run} astryx init --features agents\`.`;
|
|
102
|
-
if (interactive) {
|
|
103
|
-
p.log.warning(msg);
|
|
104
|
-
} else {
|
|
105
|
-
console.error(msg);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// ─── Feature: theme ──────────────────────────────────────────────────────────
|
|
111
|
-
|
|
112
|
-
async function runTheme({interactive = true} = {}) {
|
|
113
|
-
if (!interactive) {
|
|
114
|
-
humanLog(`✓ Theme scaffolding requires interactive mode. Run \`${run} astryx theme\` instead.`);
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
p.note(
|
|
119
|
-
'Create a custom theme with your brand colors.\n' +
|
|
120
|
-
`Run \`${run} astryx theme\` for the full theme wizard.\n` +
|
|
121
|
-
`Run \`${run} astryx theme --list\` to see existing themes.`,
|
|
122
|
-
'Themes',
|
|
123
|
-
);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// ─── Feature: template ───────────────────────────────────────────────────────
|
|
127
|
-
|
|
128
|
-
async function runTemplate(targetDir, {interactive = true, templateName} = {}) {
|
|
129
|
-
const templates = listTemplates();
|
|
130
|
-
if (templates.length === 0) return;
|
|
131
|
-
|
|
132
|
-
if (!interactive) {
|
|
133
|
-
if (!templateName) {
|
|
134
|
-
// Point agents at the build workflow rather than dumping page-template
|
|
135
|
-
// names — `build` surfaces pages AND blocks AND components for an idea,
|
|
136
|
-
// and `build` with no args is the full how-to-build playbook.
|
|
137
|
-
humanLog('✓ To build UI, use these commands:');
|
|
138
|
-
humanLog('');
|
|
139
|
-
humanLog(` ${run} astryx build "<what you're building>" build a page — kit: closest template + blocks + components`);
|
|
140
|
-
humanLog(` ${run} astryx build the how-to-build workflow (read this first)`);
|
|
141
|
-
humanLog(` ${run} astryx search <query> find anything — components, docs, templates, blocks`);
|
|
142
|
-
humanLog('');
|
|
143
|
-
return;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
if (!templates.includes(templateName)) {
|
|
147
|
-
cliError(`Unknown template "${templateName}". Available: ${templates.join(', ')}`, {code: ERROR_CODES.ERR_UNKNOWN_TEMPLATE});
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
const outputDir = path.resolve(targetDir, `./src/pages/${templateName}`);
|
|
152
|
-
const srcPath = path.join(CLI_ROOT, 'templates', 'pages', templateName, 'page.tsx');
|
|
153
|
-
fs.mkdirSync(outputDir, {recursive: true});
|
|
154
|
-
fs.copyFileSync(srcPath, path.join(outputDir, 'page.tsx'));
|
|
155
|
-
humanLog(`✓ Template created at ${path.relative(targetDir, outputDir)}/page.tsx`);
|
|
156
|
-
return;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
const TEMPLATE_OPTIONS = [
|
|
160
|
-
{value: 'skip', label: 'Skip — No template'},
|
|
161
|
-
{value: 'blank', label: 'Blank Page — Minimal scaffold'},
|
|
162
|
-
{value: 'table', label: 'Table Page — Data table with actions'},
|
|
163
|
-
{value: 'login', label: 'Login Page — Auth form with inputs'},
|
|
164
|
-
];
|
|
165
|
-
|
|
166
|
-
const templateChoice = isCancel(
|
|
167
|
-
await p.select({
|
|
168
|
-
message: 'Start with a page template?',
|
|
169
|
-
options: TEMPLATE_OPTIONS,
|
|
170
|
-
}),
|
|
171
|
-
);
|
|
172
|
-
|
|
173
|
-
if (templateChoice === 'skip') return;
|
|
174
|
-
|
|
175
|
-
const targetPath = isCancel(
|
|
176
|
-
await p.text({
|
|
177
|
-
message: 'Where should the template be created?',
|
|
178
|
-
initialValue: `./src/pages/${templateChoice}`,
|
|
179
|
-
placeholder: `./src/pages/${templateChoice}`,
|
|
180
|
-
}),
|
|
181
|
-
);
|
|
182
|
-
|
|
183
|
-
const outputDir = path.resolve(targetDir, targetPath);
|
|
184
|
-
const srcPath = path.join(CLI_ROOT, 'templates', 'pages', templateChoice, 'page.tsx');
|
|
185
|
-
|
|
186
|
-
fs.mkdirSync(outputDir, {recursive: true});
|
|
187
|
-
fs.copyFileSync(srcPath, path.join(outputDir, 'page.tsx'));
|
|
188
|
-
|
|
189
|
-
p.log.success(`Template created at ${path.relative(targetDir, outputDir)}/page.tsx`);
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
// ─── Command ─────────────────────────────────────────────────────────────────
|
|
193
|
-
|
|
194
|
-
export function registerInit(program) {
|
|
195
|
-
program
|
|
196
|
-
.command('init')
|
|
197
|
-
.description('Initialize the design system in your project')
|
|
198
|
-
.option('--features <list>', 'Comma-separated features to install (agents, theme, template)')
|
|
199
|
-
.option('--all', 'Install all features, no prompts')
|
|
200
|
-
.option('--remove-agents', 'Remove AI agent docs from all agent doc files')
|
|
201
|
-
.option('--agent <tool>', 'Target AI tool for agent docs: claude, cursor, codex, hermes, all')
|
|
202
|
-
.option('--agent-docs-path <path...>', 'Explicit file path(s) for agent docs')
|
|
203
|
-
.action(async (options) => {
|
|
204
|
-
const targetDir = process.cwd();
|
|
205
|
-
|
|
206
|
-
// Remove mode
|
|
207
|
-
if (options.removeAgents) {
|
|
208
|
-
removeAgentDocs(targetDir);
|
|
209
|
-
humanLog('✓ AI agent docs removed.');
|
|
210
|
-
return;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// Non-interactive: --features or --all
|
|
214
|
-
if (options.features || options.all) {
|
|
215
|
-
const features = options.all
|
|
216
|
-
? VALID_FEATURES
|
|
217
|
-
: options.features.split(',').map(f => f.trim().toLowerCase());
|
|
218
|
-
|
|
219
|
-
const invalid = features.filter(f => !VALID_FEATURES.includes(f));
|
|
220
|
-
if (invalid.length > 0) {
|
|
221
|
-
cliError(`Unknown features: ${invalid.join(', ')}. Valid features: ${VALID_FEATURES.join(', ')}`, {code: ERROR_CODES.ERR_UNKNOWN_FEATURE});
|
|
222
|
-
return;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
for (const feature of features) {
|
|
226
|
-
if (feature === 'agents') runAgents(targetDir, {
|
|
227
|
-
interactive: false,
|
|
228
|
-
agent: options.agent,
|
|
229
|
-
agentDocsPath: options.agentDocsPath,
|
|
230
|
-
});
|
|
231
|
-
if (feature === 'theme') await runTheme({interactive: false});
|
|
232
|
-
if (feature === 'template') await runTemplate(targetDir, {interactive: false});
|
|
233
|
-
}
|
|
234
|
-
return;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
// Interactive wizard
|
|
238
|
-
//
|
|
239
|
-
// Guard: this wizard blocks on prompts. In a non-interactive context
|
|
240
|
-
// (CI, piped stdin/stdout, no TTY) it would hang forever. Fail fast
|
|
241
|
-
// with actionable guidance via the shared interactivity contract.
|
|
242
|
-
requireInteractive({
|
|
243
|
-
command: 'init',
|
|
244
|
-
hint: `\`${run} astryx init --all\` or \`--features agents,theme,template\``,
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
p.intro('Welcome to the design system');
|
|
248
|
-
|
|
249
|
-
p.note(
|
|
250
|
-
'A design system for building internal tools\nwith 300+ React components.',
|
|
251
|
-
'About',
|
|
252
|
-
);
|
|
253
|
-
|
|
254
|
-
// Feature: agents
|
|
255
|
-
const shouldInstallAgents = isCancel(
|
|
256
|
-
await p.confirm({
|
|
257
|
-
message: 'Install AI agent support? (adds a design system cheat sheet to AGENTS.md)',
|
|
258
|
-
initialValue: true,
|
|
259
|
-
}),
|
|
260
|
-
);
|
|
261
|
-
|
|
262
|
-
if (shouldInstallAgents) {
|
|
263
|
-
const s = p.spinner();
|
|
264
|
-
s.start('Installing agent docs');
|
|
265
|
-
runAgents(targetDir);
|
|
266
|
-
s.stop('Done');
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
// Feature: swizzle awareness
|
|
270
|
-
p.note(
|
|
271
|
-
`You can customize any component with:\n ${run} astryx swizzle Button\n ${run} astryx swizzle --list`,
|
|
272
|
-
'Component Customization',
|
|
273
|
-
);
|
|
274
|
-
|
|
275
|
-
// Feature: template
|
|
276
|
-
await runTemplate(targetDir);
|
|
277
|
-
|
|
278
|
-
// Feature: theme awareness
|
|
279
|
-
await runTheme();
|
|
280
|
-
|
|
281
|
-
// Outro
|
|
282
|
-
p.outro('Design system initialized!');
|
|
283
|
-
|
|
284
|
-
for (const line of getNextSteps(run)) {
|
|
285
|
-
humanLog(line);
|
|
286
|
-
}
|
|
287
|
-
});
|
|
288
|
-
}
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @file Subprocess no-hang tests for the interactivity contract.
|
|
5
|
-
*
|
|
6
|
-
* The wizard command `init` blocks on @clack/prompts. In a
|
|
7
|
-
* non-interactive context it must fail fast (exit 1) instead of hanging.
|
|
8
|
-
* These tests spawn the CLI as a real subprocess with stdin/stdout NOT a TTY
|
|
9
|
-
* (stdio 'ignore'/'pipe'), which is exactly the CI / piped condition. If the
|
|
10
|
-
* guard were missing, spawnSync would hit the timeout (signal SIGTERM,
|
|
11
|
-
* status null) — so asserting `signal === null && status === 1` proves the
|
|
12
|
-
* process exited cleanly rather than hanging.
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
import {describe, it, expect, beforeEach, afterEach} from 'vitest';
|
|
16
|
-
import {spawnSync} from 'node:child_process';
|
|
17
|
-
import * as fs from 'node:fs';
|
|
18
|
-
import * as path from 'node:path';
|
|
19
|
-
import * as os from 'node:os';
|
|
20
|
-
import {fileURLToPath} from 'node:url';
|
|
21
|
-
|
|
22
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
23
|
-
const CLI = path.resolve(__dirname, '..', '..', 'bin', 'astryx.mjs');
|
|
24
|
-
|
|
25
|
-
let tmpDir;
|
|
26
|
-
|
|
27
|
-
function runCli(args) {
|
|
28
|
-
return spawnSync(process.execPath, [CLI, ...args], {
|
|
29
|
-
cwd: tmpDir,
|
|
30
|
-
encoding: 'utf8',
|
|
31
|
-
timeout: 20_000,
|
|
32
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
33
|
-
env: {...process.env, FORCE_COLOR: '0', CI: ''},
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
beforeEach(() => {
|
|
38
|
-
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'astryx-interactive-guard-'));
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
afterEach(() => {
|
|
42
|
-
fs.rmSync(tmpDir, {recursive: true, force: true});
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
describe('init non-interactive safety', () => {
|
|
46
|
-
it('fails fast (exit 1, no hang) and writes no files', () => {
|
|
47
|
-
const r = runCli(['init']);
|
|
48
|
-
expect(r.signal).toBeNull();
|
|
49
|
-
expect(r.status).toBe(1);
|
|
50
|
-
expect(fs.readdirSync(tmpDir)).toEqual([]);
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
it('prints actionable guidance (--all / --features)', () => {
|
|
54
|
-
const out = (() => {
|
|
55
|
-
const r = runCli(['init']);
|
|
56
|
-
return r.stderr + r.stdout;
|
|
57
|
-
})();
|
|
58
|
-
expect(out).toMatch(/requires a TTY/i);
|
|
59
|
-
expect(out).toMatch(/--all/);
|
|
60
|
-
expect(out).toMatch(/--features/);
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
it('still runs --features agents non-interactively (guard does not over-catch)', () => {
|
|
64
|
-
const r = runCli(['init', '--features', 'agents']);
|
|
65
|
-
expect(r.signal).toBeNull();
|
|
66
|
-
expect(r.status).toBe(0);
|
|
67
|
-
expect(fs.readdirSync(tmpDir).length).toBeGreaterThan(0);
|
|
68
|
-
});
|
|
69
|
-
});
|