@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
|
@@ -16,10 +16,10 @@
|
|
|
16
16
|
* astryx search button --json Typed JSON envelope
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
import {
|
|
20
|
-
import {jsonOut, humanLog} from '
|
|
21
|
-
import {cliError} from '
|
|
22
|
-
import {search as searchApi, SEARCH_DOMAINS} from '
|
|
19
|
+
import {getCliInvocation, formatCliCommand} from '../../utils/package-manager.mjs';
|
|
20
|
+
import {jsonOut, humanLog} from '../../lib/json.mjs';
|
|
21
|
+
import {cliError} from '../../lib/cli-error.mjs';
|
|
22
|
+
import {search as searchApi, SEARCH_DOMAINS} from '../../api/search/search.mjs';
|
|
23
23
|
|
|
24
24
|
const DOMAIN_LABEL = {
|
|
25
25
|
component: 'component',
|
|
@@ -28,6 +28,9 @@ const DOMAIN_LABEL = {
|
|
|
28
28
|
template: 'template',
|
|
29
29
|
};
|
|
30
30
|
|
|
31
|
+
/**
|
|
32
|
+
* @param {import('commander').Command} program
|
|
33
|
+
*/
|
|
31
34
|
export function registerSearch(program) {
|
|
32
35
|
program
|
|
33
36
|
.command('search <query>')
|
|
@@ -35,7 +38,7 @@ export function registerSearch(program) {
|
|
|
35
38
|
.option('--type <domain>', `Filter to one domain (${SEARCH_DOMAINS.join('|')})`)
|
|
36
39
|
.option('--limit <n>', 'Max number of results (default 20)')
|
|
37
40
|
.option('--detail', 'Verbose output (include import paths and match reason)')
|
|
38
|
-
.action(async (query, options) => {
|
|
41
|
+
.action(async (/** @type {string} */ query, /** @type {{type?: import('../../types/search').SearchDomain, limit?: string, detail?: boolean}} */ options) => {
|
|
39
42
|
const json = program.opts().json || false;
|
|
40
43
|
|
|
41
44
|
let limit = 20;
|
|
@@ -48,22 +51,26 @@ export function registerSearch(program) {
|
|
|
48
51
|
limit = parsed;
|
|
49
52
|
}
|
|
50
53
|
|
|
54
|
+
/** @type {import('../../types/search').SearchResponse} */
|
|
51
55
|
let result;
|
|
52
56
|
try {
|
|
53
|
-
result =
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
57
|
+
result = /** @type {import('../../types/search').SearchResponse} */ (
|
|
58
|
+
await searchApi(query, {
|
|
59
|
+
cwd: process.cwd(),
|
|
60
|
+
type: options.type,
|
|
61
|
+
limit,
|
|
62
|
+
})
|
|
63
|
+
);
|
|
58
64
|
} catch (e) {
|
|
59
|
-
|
|
65
|
+
const err = /** @type {import('../../api/error.mjs').AstryxError} */ (e);
|
|
66
|
+
cliError(err.message, {suggestions: err.suggestions});
|
|
60
67
|
return;
|
|
61
68
|
}
|
|
62
69
|
|
|
63
70
|
if (json) return jsonOut(result.type, result.data);
|
|
64
71
|
|
|
65
72
|
// ── Text output ──────────────────────────────────────────────
|
|
66
|
-
const run =
|
|
73
|
+
const run = getCliInvocation();
|
|
67
74
|
const {query: q, results} = result.data;
|
|
68
75
|
|
|
69
76
|
// No matches is a valid, successful outcome — clean message, exit 0.
|
|
@@ -71,7 +78,7 @@ export function registerSearch(program) {
|
|
|
71
78
|
humanLog('');
|
|
72
79
|
humanLog(`No results for "${q}".`);
|
|
73
80
|
humanLog('');
|
|
74
|
-
humanLog(`Try a broader term, or browse: ${run}
|
|
81
|
+
humanLog(`Try a broader term, or browse: ${run} component --list`);
|
|
75
82
|
humanLog('');
|
|
76
83
|
return;
|
|
77
84
|
}
|
|
@@ -86,7 +93,7 @@ export function registerSearch(program) {
|
|
|
86
93
|
if (r.description) {
|
|
87
94
|
humanLog(` ${r.description}`);
|
|
88
95
|
}
|
|
89
|
-
humanLog(` → ${
|
|
96
|
+
humanLog(` → ${formatCliCommand(r.command)}`);
|
|
90
97
|
if (options.detail) {
|
|
91
98
|
if (r.import) humanLog(` import: ${r.import}`);
|
|
92
99
|
humanLog(` match: ${r.reason} (score ${r.score})`);
|
|
@@ -97,4 +104,4 @@ export function registerSearch(program) {
|
|
|
97
104
|
}
|
|
98
105
|
|
|
99
106
|
// Re-export the API for external consumers.
|
|
100
|
-
export {search, SEARCH_DOMAINS} from '
|
|
107
|
+
export {search, SEARCH_DOMAINS} from '../../api/search/search.mjs';
|
|
@@ -14,7 +14,7 @@ import {describe, it, expect} from 'vitest';
|
|
|
14
14
|
import {spawnSync} from 'node:child_process';
|
|
15
15
|
import * as path from 'node:path';
|
|
16
16
|
import {fileURLToPath} from 'node:url';
|
|
17
|
-
import {search, scoreCandidate, SEARCH_DOMAINS} from '
|
|
17
|
+
import {search, scoreCandidate, SEARCH_DOMAINS} from '../../api/search/search.mjs';
|
|
18
18
|
|
|
19
19
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
20
20
|
const CLI_BIN = path.resolve(__dirname, '../../bin/astryx.mjs');
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file Guardrail tests — the centralized setup check + enforcement layer 3.
|
|
5
|
+
*
|
|
6
|
+
* Unit: isAstryxInitialized() detects the Astryx marker across EVERY agent-doc
|
|
7
|
+
* location (including the previously-missed Hermes files) and legacy XDS blocks.
|
|
8
|
+
*
|
|
9
|
+
* Integration: the CLI nudges (stderr) before a command when the project hasn't
|
|
10
|
+
* run init — INCLUDING in --json mode (agents pass --json, and stderr never
|
|
11
|
+
* corrupts the stdout JSON envelope). Quiet once set up, outside a project, and
|
|
12
|
+
* for the installer command itself.
|
|
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
|
+
import {isAstryxInitialized} from '../../lib/agent-docs/agent-docs.mjs';
|
|
22
|
+
|
|
23
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
24
|
+
const CLI = path.resolve(__dirname, '..', '..', 'bin', 'astryx.mjs');
|
|
25
|
+
const MARKER = '<!-- ASTRYX:START -->';
|
|
26
|
+
const NUDGE = /finish setup and install the Astryx agent prompt/;
|
|
27
|
+
|
|
28
|
+
let tmp;
|
|
29
|
+
beforeEach(() => {
|
|
30
|
+
tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'astryx-setup-nudge-'));
|
|
31
|
+
});
|
|
32
|
+
afterEach(() => {
|
|
33
|
+
fs.rmSync(tmp, {recursive: true, force: true});
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
function write(rel, body) {
|
|
37
|
+
const p = path.join(tmp, rel);
|
|
38
|
+
fs.mkdirSync(path.dirname(p), {recursive: true});
|
|
39
|
+
fs.writeFileSync(p, body);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function run(args, cwd = tmp) {
|
|
43
|
+
return spawnSync(process.execPath, [CLI, ...args], {
|
|
44
|
+
cwd,
|
|
45
|
+
encoding: 'utf8',
|
|
46
|
+
timeout: 30_000,
|
|
47
|
+
env: {...process.env, FORCE_COLOR: '0'},
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
describe('isAstryxInitialized — centralized setup check (one place)', () => {
|
|
52
|
+
it('is false in an empty project', () => {
|
|
53
|
+
expect(isAstryxInitialized(tmp)).toBe(false);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// Covers EVERY location a preset can write — .hermes.md/HERMES.md were the gap.
|
|
57
|
+
it.each(['AGENTS.md', 'CLAUDE.md', '.claude/CLAUDE.md', '.cursorrules', '.hermes.md', 'HERMES.md'])(
|
|
58
|
+
'detects the marker in %s',
|
|
59
|
+
file => {
|
|
60
|
+
write(file, `# doc\n${MARKER}\nbody`);
|
|
61
|
+
expect(isAstryxInitialized(tmp)).toBe(true);
|
|
62
|
+
},
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
it('detects the legacy XDS marker for back-compat', () => {
|
|
66
|
+
write('AGENTS.md', '<!-- XDS:START -->');
|
|
67
|
+
expect(isAstryxInitialized(tmp)).toBe(true);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('is false when a doc file exists WITHOUT the marker', () => {
|
|
71
|
+
write('AGENTS.md', 'project notes, no astryx block');
|
|
72
|
+
expect(isAstryxInitialized(tmp)).toBe(false);
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
describe('enforcement layer 3 — per-command setup nudge', () => {
|
|
77
|
+
const asProject = () => write('package.json', '{"name":"t"}');
|
|
78
|
+
|
|
79
|
+
it('nudges on stderr after a command when not set up', () => {
|
|
80
|
+
asProject();
|
|
81
|
+
const r = run(['docs', 'tokens']);
|
|
82
|
+
expect(r.stderr).toMatch(NUDGE);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('is suppressed in --json (machine mode stays clean), stdout valid JSON', () => {
|
|
86
|
+
asProject();
|
|
87
|
+
const r = run(['--json', 'docs', 'tokens']);
|
|
88
|
+
// --json is machine output with a clean stdout+stderr contract; the human
|
|
89
|
+
// nudge must NOT leak into it (json-shim: error envelopes have empty stderr).
|
|
90
|
+
expect(r.stderr).not.toMatch(NUDGE);
|
|
91
|
+
expect(() => JSON.parse(r.stdout)).not.toThrow();
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('is quiet once set up (marker present)', () => {
|
|
95
|
+
asProject();
|
|
96
|
+
write('AGENTS.md', MARKER);
|
|
97
|
+
expect(run(['docs', 'tokens']).stderr).not.toMatch(NUDGE);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('is quiet outside a project (no package.json)', () => {
|
|
101
|
+
expect(run(['docs', 'tokens']).stderr).not.toMatch(NUDGE);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it('does not nudge for the installer command itself', () => {
|
|
105
|
+
asProject();
|
|
106
|
+
expect(run(['init']).stderr).not.toMatch(NUDGE);
|
|
107
|
+
});
|
|
108
|
+
});
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file swizzle command — thin wrapper around api/swizzle.
|
|
5
|
+
*
|
|
6
|
+
* Copies a component's source into the consumer project for customization
|
|
7
|
+
* (imports rewritten to the owner package's subpaths). All logic — owner
|
|
8
|
+
* resolution, copy, import rewriting, StyleX detection, maintainer feedback —
|
|
9
|
+
* lives in api/swizzle; this file only parses flags, prints, and prefixes
|
|
10
|
+
* commands for the caller's package manager.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import {jsonOut, humanLog} from '../../lib/json.mjs';
|
|
14
|
+
import {cliError} from '../../lib/cli-error.mjs';
|
|
15
|
+
import {getCliInvocation} from '../../utils/package-manager.mjs';
|
|
16
|
+
import {swizzle as swizzleApi} from '../../api/swizzle/swizzle.mjs';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @param {import('commander').Command} program
|
|
20
|
+
*/
|
|
21
|
+
export function registerSwizzle(program) {
|
|
22
|
+
program
|
|
23
|
+
.command('swizzle [component]')
|
|
24
|
+
.description('Copy component source for customization')
|
|
25
|
+
.option('--output <dir>', 'Output directory', './components/astryx')
|
|
26
|
+
.option('--package <pkg>', 'Scope to a specific owning package')
|
|
27
|
+
.option('--list', 'List available components')
|
|
28
|
+
.option('-f, --overwrite', 'Overwrite existing files without prompting')
|
|
29
|
+
.action(async (/** @type {string | undefined} */ component, /** @type {{output: string, package?: string, list?: boolean, overwrite?: boolean}} */ options) => {
|
|
30
|
+
const json = program.opts().json || false;
|
|
31
|
+
const run = getCliInvocation();
|
|
32
|
+
|
|
33
|
+
/** @type {import('../../types/swizzle').SwizzleListResponse | import('../../types/swizzle').SwizzleCopyResponse} */
|
|
34
|
+
let result;
|
|
35
|
+
try {
|
|
36
|
+
result = await swizzleApi(component, {
|
|
37
|
+
cwd: process.cwd(),
|
|
38
|
+
output: options.output,
|
|
39
|
+
package: options.package,
|
|
40
|
+
list: options.list,
|
|
41
|
+
overwrite: options.overwrite,
|
|
42
|
+
});
|
|
43
|
+
} catch (e) {
|
|
44
|
+
const err = /** @type {import('../../api/error.mjs').AstryxError} */ (e);
|
|
45
|
+
cliError(err.message, {suggestions: err.suggestions, code: err.code});
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (json) return jsonOut(result.type, result.data);
|
|
50
|
+
|
|
51
|
+
if (result.type === 'swizzle.list') {
|
|
52
|
+
const components = result.data;
|
|
53
|
+
humanLog('\nAvailable components:\n');
|
|
54
|
+
for (const name of components) {
|
|
55
|
+
humanLog(` ${name}`);
|
|
56
|
+
}
|
|
57
|
+
humanLog(`\nUsage: ${run} swizzle <component>\n`);
|
|
58
|
+
humanLog(`Example: ${run} swizzle Button`);
|
|
59
|
+
humanLog(` ${run} swizzle XDSButton (XDS prefix also works)\n`);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const {package: ownerPackage, outputDir, filesCopied, usesStyleX, feedback} =
|
|
64
|
+
result.data;
|
|
65
|
+
|
|
66
|
+
humanLog(`\n✓ Copied ${filesCopied} files to ${outputDir}/\n`);
|
|
67
|
+
humanLog(`Relative imports have been rewritten to use ${ownerPackage}.`);
|
|
68
|
+
humanLog('You can now customize the component source freely.\n');
|
|
69
|
+
|
|
70
|
+
// StyleX build requirement — swizzled StyleX source renders unstyled with
|
|
71
|
+
// no error unless the consumer's build runs a StyleX compiler.
|
|
72
|
+
if (usesStyleX) {
|
|
73
|
+
humanLog(
|
|
74
|
+
'⚠ These components use StyleX and require a StyleX compiler in your build.',
|
|
75
|
+
);
|
|
76
|
+
humanLog(
|
|
77
|
+
' Without one they render unstyled (no error). See setup per framework:',
|
|
78
|
+
);
|
|
79
|
+
humanLog(` ${run} docs styling`);
|
|
80
|
+
humanLog(
|
|
81
|
+
' Next.js note: the StyleX Babel plugin disables SWC and breaks next/font —',
|
|
82
|
+
);
|
|
83
|
+
humanLog(
|
|
84
|
+
' use an SWC-based StyleX transform instead (covered in the guide).',
|
|
85
|
+
);
|
|
86
|
+
humanLog('');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Maintainer feedback note (skipped when the owner ships no issues URL).
|
|
90
|
+
if (feedback) {
|
|
91
|
+
humanLog(
|
|
92
|
+
'Customizing a component often signals a gap in the design system.',
|
|
93
|
+
);
|
|
94
|
+
humanLog('Let the maintainers know what you needed:');
|
|
95
|
+
if (feedback.ghCommand) {
|
|
96
|
+
humanLog(` ${feedback.ghCommand}`);
|
|
97
|
+
} else {
|
|
98
|
+
humanLog(` ${feedback.issuesUrl}`);
|
|
99
|
+
}
|
|
100
|
+
humanLog('');
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
}
|
|
@@ -6,25 +6,44 @@
|
|
|
6
6
|
|
|
7
7
|
import * as path from 'node:path';
|
|
8
8
|
import * as fs from 'node:fs';
|
|
9
|
-
import
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
9
|
+
import {jsonOut, humanLog} from '../../lib/json.mjs';
|
|
10
|
+
import {cliError} from '../../lib/cli-error.mjs';
|
|
11
|
+
import {ERROR_CODES} from '../../lib/error-codes.mjs';
|
|
12
|
+
import {template as templateApi} from '../../api/template/template.mjs';
|
|
13
|
+
import {Project} from '../../lib/project.mjs';
|
|
14
|
+
import {warnOnIntegrationIssues} from '../../lib/integration-warnings.mjs';
|
|
15
|
+
import {getCliInvocation} from '../../utils/package-manager.mjs';
|
|
16
|
+
|
|
17
|
+
export {discoverTemplates, listTemplates} from '../../api/template/template.mjs';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* A template entry as produced by the discover* helpers in api/template.mjs.
|
|
21
|
+
* The api layer returns these as `object[]`; this local shape captures the
|
|
22
|
+
* fields the command consumes. Remove once api/template.mjs exports a precise
|
|
23
|
+
* type for its discovered templates.
|
|
24
|
+
* @typedef {object} DiscoveredTemplate
|
|
25
|
+
* @property {'page' | 'block'} type
|
|
26
|
+
* @property {string} dirName
|
|
27
|
+
* @property {string} name
|
|
28
|
+
* @property {string} filePath
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The discriminated response returned by the template API. The api layer
|
|
33
|
+
* currently declares `{type: string, data: unknown}`; narrow it here to the
|
|
34
|
+
* precise union so the switch below type-checks. Replace with the api's own
|
|
35
|
+
* return type once it is tightened.
|
|
36
|
+
* @typedef {(
|
|
37
|
+
* import('../../types/template').TemplateListResponse |
|
|
38
|
+
* import('../../types/template').TemplateShowResponse |
|
|
39
|
+
* import('../../types/template').TemplateSkeletonResponse |
|
|
40
|
+
* import('../../types/template').TemplateCopyResponse
|
|
41
|
+
* )} TemplateResponse
|
|
42
|
+
*/
|
|
27
43
|
|
|
44
|
+
/**
|
|
45
|
+
* @param {import('commander').Command} program
|
|
46
|
+
*/
|
|
28
47
|
export function registerTemplate(program) {
|
|
29
48
|
program
|
|
30
49
|
.command('template [name] [path]')
|
|
@@ -34,15 +53,27 @@ export function registerTemplate(program) {
|
|
|
34
53
|
.option('--package <pkg>', 'Narrow to templates from a specific package')
|
|
35
54
|
.option('--skeleton', 'Show layout skeleton with spatial annotations (padding, gap, nesting)')
|
|
36
55
|
.option('-f, --overwrite', 'Overwrite existing files without prompting')
|
|
37
|
-
.action(
|
|
56
|
+
.action(
|
|
57
|
+
/**
|
|
58
|
+
* @param {string | undefined} name
|
|
59
|
+
* @param {string | undefined} targetPath
|
|
60
|
+
* @param {{list?: boolean, type?: string, package?: string, skeleton?: boolean, overwrite?: boolean}} options
|
|
61
|
+
*/
|
|
62
|
+
async (name, targetPath, options) => {
|
|
38
63
|
const json = program.opts().json || false;
|
|
64
|
+
const run = getCliInvocation();
|
|
39
65
|
|
|
40
66
|
// Non-blocking nudge: if any configured integration has validation
|
|
41
67
|
// issues, print one compact line to stderr pointing at
|
|
42
68
|
// validate-integration. Best-effort; suppressed in --json mode.
|
|
43
69
|
try {
|
|
44
70
|
const project = await Project.load(process.cwd());
|
|
45
|
-
await warnOnIntegrationIssues(
|
|
71
|
+
await warnOnIntegrationIssues(
|
|
72
|
+
/** @type {Array<import('../../lib/integrations.mjs').LoadedIntegration>} */ (
|
|
73
|
+
project.loadedIntegrations
|
|
74
|
+
),
|
|
75
|
+
{json},
|
|
76
|
+
);
|
|
46
77
|
} catch {
|
|
47
78
|
// Never let the nudge break the command.
|
|
48
79
|
}
|
|
@@ -59,40 +90,32 @@ export function registerTemplate(program) {
|
|
|
59
90
|
const collision = await detectTemplateCollision(name, targetPath);
|
|
60
91
|
if (collision && !options.overwrite) {
|
|
61
92
|
const rel = path.relative(process.cwd(), collision) || collision;
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
const confirmed = isCancel(
|
|
70
|
-
await p.confirm({
|
|
71
|
-
message: `Overwrite existing file ${rel}?`,
|
|
72
|
-
initialValue: false,
|
|
73
|
-
}),
|
|
74
|
-
);
|
|
75
|
-
if (!confirmed) {
|
|
76
|
-
humanLog('Aborted. Re-run with --overwrite to replace the file.');
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
93
|
+
const msg =
|
|
94
|
+
`Refusing to overwrite existing file ${rel}. ` +
|
|
95
|
+
`Re-run with --overwrite (or -f) to replace it.`;
|
|
96
|
+
cliError(msg, {code: ERROR_CODES.ERR_FILE_EXISTS});
|
|
97
|
+
return;
|
|
79
98
|
}
|
|
80
99
|
}
|
|
81
100
|
|
|
101
|
+
/** @type {TemplateResponse} */
|
|
82
102
|
let result;
|
|
83
103
|
try {
|
|
84
|
-
result =
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
104
|
+
result = /** @type {TemplateResponse} */ (
|
|
105
|
+
await templateApi(name, {
|
|
106
|
+
list: options.list,
|
|
107
|
+
skeleton: options.skeleton,
|
|
108
|
+
type: /** @type {'page' | 'block' | undefined} */ (options.type),
|
|
109
|
+
package: options.package,
|
|
110
|
+
targetPath,
|
|
111
|
+
cwd: process.cwd(),
|
|
112
|
+
})
|
|
113
|
+
);
|
|
92
114
|
} catch (e) {
|
|
93
115
|
// template API throws structured errors with {name, reason} suggestions —
|
|
94
116
|
// pass them through untouched so the CLI envelope matches the API.
|
|
95
|
-
|
|
117
|
+
const err = /** @type {import('../../api/error.mjs').AstryxError} */ (e);
|
|
118
|
+
cliError(err.message, {suggestions: err.suggestions || [], code: err.code});
|
|
96
119
|
return;
|
|
97
120
|
}
|
|
98
121
|
|
|
@@ -102,6 +125,7 @@ export function registerTemplate(program) {
|
|
|
102
125
|
case 'template.list': {
|
|
103
126
|
const pages = result.data.filter(t => t.type === 'page');
|
|
104
127
|
const blocks = result.data.filter(t => t.type === 'block');
|
|
128
|
+
/** @param {import('../../types/template').TemplateListEntry} t */
|
|
105
129
|
const renderEntry = t => {
|
|
106
130
|
const status = t.isReady ? '' : ' (WIP)';
|
|
107
131
|
const pkg =
|
|
@@ -120,10 +144,10 @@ export function registerTemplate(program) {
|
|
|
120
144
|
for (const t of blocks) renderEntry(t);
|
|
121
145
|
}
|
|
122
146
|
humanLog('\nUsage:');
|
|
123
|
-
humanLog(
|
|
124
|
-
humanLog(
|
|
125
|
-
humanLog(
|
|
126
|
-
humanLog(
|
|
147
|
+
humanLog(` ${run} template <id> [target-path] Scaffold page or block`);
|
|
148
|
+
humanLog(` ${run} template <id> --skeleton Layout reference`);
|
|
149
|
+
humanLog(` ${run} template --list --type block List only blocks`);
|
|
150
|
+
humanLog(` ${run} template --list --package <pkg> List from one package\n`);
|
|
127
151
|
break;
|
|
128
152
|
}
|
|
129
153
|
|
|
@@ -159,12 +183,19 @@ export function registerTemplate(program) {
|
|
|
159
183
|
* Path-safety enforcement happens inside the API; here we only need
|
|
160
184
|
* enough precision to check existence — a false negative just means the
|
|
161
185
|
* API will catch the issue and abort.
|
|
186
|
+
*
|
|
187
|
+
* @param {string} name
|
|
188
|
+
* @param {string} targetPath
|
|
189
|
+
* @returns {Promise<string | null>}
|
|
162
190
|
*/
|
|
163
191
|
async function detectTemplateCollision(name, targetPath) {
|
|
164
|
-
const {discoverTemplates} = await import('
|
|
192
|
+
const {discoverTemplates} = await import('../../api/template/template.mjs');
|
|
193
|
+
/** @type {DiscoveredTemplate[]} */
|
|
165
194
|
let templates;
|
|
166
195
|
try {
|
|
167
|
-
templates =
|
|
196
|
+
templates = /** @type {DiscoveredTemplate[]} */ (
|
|
197
|
+
await discoverTemplates(process.cwd())
|
|
198
|
+
);
|
|
168
199
|
} catch {
|
|
169
200
|
return null;
|
|
170
201
|
}
|
|
@@ -177,7 +208,7 @@ async function detectTemplateCollision(name, targetPath) {
|
|
|
177
208
|
const resolved = path.resolve(process.cwd(), targetPath);
|
|
178
209
|
|
|
179
210
|
// File-arg branch: targetPath looks like `./foo.tsx`.
|
|
180
|
-
const {isFilePathArg} = await import('
|
|
211
|
+
const {isFilePathArg} = await import('../../utils/path-safety.mjs');
|
|
181
212
|
let dest;
|
|
182
213
|
if (isFilePathArg(targetPath)) {
|
|
183
214
|
dest = resolved;
|
|
@@ -18,7 +18,7 @@ let templateApi;
|
|
|
18
18
|
|
|
19
19
|
beforeEach(async () => {
|
|
20
20
|
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'astryx-template-paths-'));
|
|
21
|
-
templateApi = (await import('
|
|
21
|
+
templateApi = (await import('../../api/template/template.mjs')).template;
|
|
22
22
|
});
|
|
23
23
|
afterEach(() => {
|
|
24
24
|
fs.rmSync(tmpDir, {recursive: true, force: true});
|
|
@@ -57,7 +57,7 @@ describe('template path safety', () => {
|
|
|
57
57
|
fs.mkdirSync(cwd, {recursive: true});
|
|
58
58
|
|
|
59
59
|
// Use a real template name from the discovered set.
|
|
60
|
-
const {discoverTemplates} = await import('
|
|
60
|
+
const {discoverTemplates} = await import('../../api/template/template.mjs');
|
|
61
61
|
const all = await discoverTemplates();
|
|
62
62
|
const page = all.find(t => t.type === 'page');
|
|
63
63
|
if (!page) {
|