@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
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
* - An updated JS module that references the built className
|
|
9
9
|
*
|
|
10
10
|
* Usage:
|
|
11
|
-
*
|
|
12
|
-
*
|
|
11
|
+
* astryx theme build ./src/themes/ocean.ts
|
|
12
|
+
* astryx theme build ./src/themes/ocean.ts --out ./dist/ocean.css
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
import * as fs from 'node:fs';
|
|
@@ -17,26 +17,27 @@ import * as path from 'node:path';
|
|
|
17
17
|
import {pathToFileURL, fileURLToPath} from 'node:url';
|
|
18
18
|
import {spawn} from 'node:child_process';
|
|
19
19
|
import {createJiti} from 'jiti';
|
|
20
|
-
import {
|
|
20
|
+
import {getCliInvocation} from '../../utils/package-manager.mjs';
|
|
21
21
|
import {
|
|
22
22
|
sanitizeName,
|
|
23
23
|
PathSafetyError,
|
|
24
|
-
|
|
25
|
-
} from '
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
import {themeAdd, listThemes} from '../api/theme-add.mjs';
|
|
24
|
+
} from '../../utils/path-safety.mjs';
|
|
25
|
+
import {jsonOut, humanLog} from '../../lib/json.mjs';
|
|
26
|
+
import {cliError} from '../../lib/cli-error.mjs';
|
|
27
|
+
import {ERROR_CODES} from '../../lib/error-codes.mjs';
|
|
28
|
+
import {themeAdd} from '../../api/theme/theme-add.mjs';
|
|
30
29
|
|
|
31
30
|
// Import shared theme processing from core. `astryx theme build` MUST produce the
|
|
32
31
|
// exact same CSS as the `<Theme>` runtime, so it has exactly one generation
|
|
33
32
|
// path: core's generator. There is no in-CLI fallback implementation — if this
|
|
34
33
|
// import fails, the build fails (see the ERR_CORE_NOT_FOUND guard in the theme
|
|
35
34
|
// action). A built, resolvable `@astryxdesign/core` is a hard requirement.
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
let
|
|
39
|
-
let
|
|
35
|
+
// A built, resolvable `@astryxdesign/core` is a hard requirement. These are
|
|
36
|
+
// populated from a dynamic import (a runtime boundary), so `any` is intentional.
|
|
37
|
+
/** @type {any} */ let _defineTheme = null;
|
|
38
|
+
/** @type {any} */ let _generateThemeRulesSplit = null;
|
|
39
|
+
/** @type {any} */ let _generateOnMediaCSS = null;
|
|
40
|
+
/** @type {any} */ let _coreImportError = null;
|
|
40
41
|
try {
|
|
41
42
|
const coreTheme = await import('@astryxdesign/core/theme');
|
|
42
43
|
_defineTheme = coreTheme.defineTheme;
|
|
@@ -76,9 +77,11 @@ function generatedHeader(sourceFile, lang = 'js', command) {
|
|
|
76
77
|
/**
|
|
77
78
|
* Convert a theme name to a valid JS identifier.
|
|
78
79
|
* e.g. 'default-minimal' → 'defaultMinimal', 'ocean' → 'ocean'
|
|
80
|
+
* @param {string} name
|
|
81
|
+
* @returns {string}
|
|
79
82
|
*/
|
|
80
83
|
function toIdentifier(name) {
|
|
81
|
-
return name.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
|
|
84
|
+
return name.replace(/-([a-z])/g, (/** @type {string} */ _, /** @type {string} */ c) => c.toUpperCase());
|
|
82
85
|
}
|
|
83
86
|
|
|
84
87
|
/**
|
|
@@ -86,6 +89,9 @@ function toIdentifier(name) {
|
|
|
86
89
|
* from the cwd-relative dir (most consumers import from a file under src/) but
|
|
87
90
|
* keeps the rest of the path (e.g. `themes/gothic`). Callers note the path is
|
|
88
91
|
* relative to the consumer's file.
|
|
92
|
+
* @param {string} relDir
|
|
93
|
+
* @param {string} base
|
|
94
|
+
* @returns {string}
|
|
89
95
|
*/
|
|
90
96
|
function importSpecifier(relDir, base) {
|
|
91
97
|
const normalized = relDir === '.' ? '' : relDir;
|
|
@@ -96,11 +102,13 @@ function importSpecifier(relDir, base) {
|
|
|
96
102
|
/**
|
|
97
103
|
* Convert a kebab-case component name to PascalCase.
|
|
98
104
|
* e.g. 'button' → 'Button', 'progress-bar' → 'ProgressBar', 'avatar-status-dot' → 'AvatarStatusDot'
|
|
105
|
+
* @param {string} name
|
|
106
|
+
* @returns {string}
|
|
99
107
|
*/
|
|
100
108
|
function toPascalCase(name) {
|
|
101
109
|
return name
|
|
102
110
|
.split('-')
|
|
103
|
-
.map(part => part.charAt(0).toUpperCase() + part.slice(1))
|
|
111
|
+
.map((/** @type {string} */ part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
104
112
|
.join('');
|
|
105
113
|
}
|
|
106
114
|
|
|
@@ -108,6 +116,8 @@ function toPascalCase(name) {
|
|
|
108
116
|
* Load known built-in values for a component's visual props from its .doc.mjs file.
|
|
109
117
|
* Parses the type string (e.g. "'info' | 'warning' | 'error' | 'success'") to extract values.
|
|
110
118
|
* Returns a map of { propName: string[] } for props that are visual (listed in theming targets).
|
|
119
|
+
* @param {string} componentName
|
|
120
|
+
* @returns {Promise<Record<string, string[]>>}
|
|
111
121
|
*/
|
|
112
122
|
async function loadKnownValues(componentName) {
|
|
113
123
|
// Resolve core src relative to the CLI package, not cwd (which may be a theme package)
|
|
@@ -141,6 +151,7 @@ async function loadKnownValues(componentName) {
|
|
|
141
151
|
if (allProps.length === 0) return {};
|
|
142
152
|
|
|
143
153
|
// Collect visual prop names from theming targets
|
|
154
|
+
/** @type {Set<string>} */
|
|
144
155
|
const visualProps = new Set();
|
|
145
156
|
for (const target of doc.theming.targets) {
|
|
146
157
|
if (target.visualProps) {
|
|
@@ -149,6 +160,7 @@ async function loadKnownValues(componentName) {
|
|
|
149
160
|
}
|
|
150
161
|
|
|
151
162
|
// Extract values from prop type strings
|
|
163
|
+
/** @type {Record<string, string[]>} */
|
|
152
164
|
const result = {};
|
|
153
165
|
for (const prop of allProps) {
|
|
154
166
|
if (!visualProps.has(prop.name)) continue;
|
|
@@ -157,7 +169,7 @@ async function loadKnownValues(componentName) {
|
|
|
157
169
|
// Parse union type: "'info' | 'warning' | 'error' | 'success'" → ['info', 'warning', 'error', 'success']
|
|
158
170
|
const matches = prop.type.match(/'([^']+)'/g);
|
|
159
171
|
if (matches) {
|
|
160
|
-
result[prop.name] = matches.map(m => m.replace(/'/g, ''));
|
|
172
|
+
result[prop.name] = matches.map((/** @type {string} */ m) => m.replace(/'/g, ''));
|
|
161
173
|
}
|
|
162
174
|
}
|
|
163
175
|
return result;
|
|
@@ -167,12 +179,17 @@ async function loadKnownValues(componentName) {
|
|
|
167
179
|
}
|
|
168
180
|
|
|
169
181
|
// Cache for loaded known values
|
|
182
|
+
/** @type {Map<string, Record<string, string[]>>} */
|
|
170
183
|
const _knownValuesCache = new Map();
|
|
184
|
+
/**
|
|
185
|
+
* @param {string} componentName
|
|
186
|
+
* @returns {Promise<Record<string, string[]>>}
|
|
187
|
+
*/
|
|
171
188
|
async function getKnownValues(componentName) {
|
|
172
189
|
if (!_knownValuesCache.has(componentName)) {
|
|
173
190
|
_knownValuesCache.set(componentName, await loadKnownValues(componentName));
|
|
174
191
|
}
|
|
175
|
-
return _knownValuesCache.get(componentName);
|
|
192
|
+
return _knownValuesCache.get(componentName) ?? {};
|
|
176
193
|
}
|
|
177
194
|
|
|
178
195
|
/**
|
|
@@ -196,10 +213,15 @@ function resolveCoreRoot() {
|
|
|
196
213
|
* actually sees), falling back to the `src/<Component>/index.ts` in the
|
|
197
214
|
* monorepo. Returns the file contents, or '' if nothing is found.
|
|
198
215
|
*/
|
|
216
|
+
/** @type {Map<string, string>} */
|
|
199
217
|
const _componentDeclCache = new Map();
|
|
218
|
+
/**
|
|
219
|
+
* @param {string} pascalName
|
|
220
|
+
* @returns {string}
|
|
221
|
+
*/
|
|
200
222
|
function readComponentDeclarations(pascalName) {
|
|
201
223
|
if (_componentDeclCache.has(pascalName)) {
|
|
202
|
-
return _componentDeclCache.get(pascalName);
|
|
224
|
+
return _componentDeclCache.get(pascalName) ?? '';
|
|
203
225
|
}
|
|
204
226
|
let contents = '';
|
|
205
227
|
const coreRoot = resolveCoreRoot();
|
|
@@ -231,6 +253,9 @@ function readComponentDeclarations(pascalName) {
|
|
|
231
253
|
* `HeadingType`, `ButtonSize`) are NOT augmentable, so a generated augmentation
|
|
232
254
|
* against them is dead code. We check that the name is exported (directly or
|
|
233
255
|
* re-exported) as a type/interface.
|
|
256
|
+
* @param {string} pascalName
|
|
257
|
+
* @param {string} interfaceName
|
|
258
|
+
* @returns {boolean}
|
|
234
259
|
*/
|
|
235
260
|
function componentHasAugmentableInterface(pascalName, interfaceName) {
|
|
236
261
|
const decl = readComponentDeclarations(pascalName);
|
|
@@ -255,7 +280,7 @@ function componentHasAugmentableInterface(pascalName, interfaceName) {
|
|
|
255
280
|
* generating a `declare module` block for them would be dead code — those are
|
|
256
281
|
* skipped.
|
|
257
282
|
*
|
|
258
|
-
* @param {
|
|
283
|
+
* @param {{components?: Record<string, Record<string, Record<string, unknown>>>}} themeDef - Theme definition (resolved by defineTheme)
|
|
259
284
|
* @returns {Promise<string|null>} TypeScript declaration content, or null if no augmentations needed
|
|
260
285
|
*/
|
|
261
286
|
async function generateVariantDeclarationsAsync(themeDef) {
|
|
@@ -264,6 +289,7 @@ async function generateVariantDeclarationsAsync(themeDef) {
|
|
|
264
289
|
}
|
|
265
290
|
|
|
266
291
|
// Collect custom values: { component: { prop: [value, ...] } }
|
|
292
|
+
/** @type {Record<string, Record<string, Set<string>>>} */
|
|
267
293
|
const customValues = {};
|
|
268
294
|
|
|
269
295
|
for (const [component, rules] of Object.entries(themeDef.components)) {
|
|
@@ -337,6 +363,8 @@ async function generateVariantDeclarationsAsync(themeDef) {
|
|
|
337
363
|
|
|
338
364
|
/**
|
|
339
365
|
* Resolve a token value — [light, dark] tuple becomes light-dark()
|
|
366
|
+
* @param {unknown} value
|
|
367
|
+
* @returns {unknown}
|
|
340
368
|
*/
|
|
341
369
|
function resolveTokenValue(value) {
|
|
342
370
|
if (Array.isArray(value)) {
|
|
@@ -348,12 +376,14 @@ function resolveTokenValue(value) {
|
|
|
348
376
|
// Theme @scope selector helpers. Keep the `astryx` literal in sync with
|
|
349
377
|
// packages/core/src/naming.ts (NAMESPACE) and generateThemeRules.ts.
|
|
350
378
|
// Theme scopes to data-astryx-theme; the static build path must match.
|
|
351
|
-
const themeScopeStart = name => `[data-astryx-theme="${name}"]`;
|
|
379
|
+
const themeScopeStart = (/** @type {string} */ name) => `[data-astryx-theme="${name}"]`;
|
|
352
380
|
const THEME_SCOPE_TO = `[data-astryx-theme]`;
|
|
353
381
|
|
|
354
382
|
/**
|
|
355
383
|
* Import a theme module using jiti and find the defineTheme() result.
|
|
356
384
|
* Returns the resolved DefinedTheme object.
|
|
385
|
+
* @param {string} filePath
|
|
386
|
+
* @returns {Promise<any>}
|
|
357
387
|
*/
|
|
358
388
|
async function importThemeModule(filePath) {
|
|
359
389
|
const jiti = createJiti(import.meta.url, {
|
|
@@ -377,6 +407,10 @@ async function importThemeModule(filePath) {
|
|
|
377
407
|
);
|
|
378
408
|
}
|
|
379
409
|
|
|
410
|
+
/**
|
|
411
|
+
* @param {any} value
|
|
412
|
+
* @returns {boolean}
|
|
413
|
+
*/
|
|
380
414
|
function isThemeObject(value) {
|
|
381
415
|
return (
|
|
382
416
|
value &&
|
|
@@ -390,6 +424,8 @@ function isThemeObject(value) {
|
|
|
390
424
|
/**
|
|
391
425
|
* Extract the theme definition from a JS/TS file.
|
|
392
426
|
* Tries jiti first (full TS support), falls back to regex+eval.
|
|
427
|
+
* @param {string} filePath
|
|
428
|
+
* @returns {Promise<any>}
|
|
393
429
|
*/
|
|
394
430
|
async function extractThemeDefinition(filePath) {
|
|
395
431
|
try {
|
|
@@ -398,8 +434,9 @@ async function extractThemeDefinition(filePath) {
|
|
|
398
434
|
try {
|
|
399
435
|
return extractThemeDefinitionLegacy(filePath);
|
|
400
436
|
} catch {
|
|
437
|
+
const je = /** @type {Error} */ (jitiError);
|
|
401
438
|
throw new Error(
|
|
402
|
-
`Failed to load theme from ${filePath}: ${
|
|
439
|
+
`Failed to load theme from ${filePath}: ${je.message}\n` +
|
|
403
440
|
`Make sure all imports in the theme file are resolvable.`,
|
|
404
441
|
);
|
|
405
442
|
}
|
|
@@ -409,6 +446,8 @@ async function extractThemeDefinition(filePath) {
|
|
|
409
446
|
/**
|
|
410
447
|
* Fallback extraction via regex + eval.
|
|
411
448
|
* Only works for plain object literals — can't follow imports or variables.
|
|
449
|
+
* @param {string} filePath
|
|
450
|
+
* @returns {any}
|
|
412
451
|
*/
|
|
413
452
|
function extractThemeDefinitionLegacy(filePath) {
|
|
414
453
|
const content = fs.readFileSync(filePath, 'utf8');
|
|
@@ -434,8 +473,9 @@ function extractThemeDefinitionLegacy(filePath) {
|
|
|
434
473
|
|
|
435
474
|
return eval(`(${objStr})`);
|
|
436
475
|
} catch (e) {
|
|
476
|
+
const err = /** @type {Error} */ (e);
|
|
437
477
|
throw new Error(
|
|
438
|
-
`Failed to parse theme definition in ${filePath}: ${
|
|
478
|
+
`Failed to parse theme definition in ${filePath}: ${err.message}\n` +
|
|
439
479
|
`Make sure the defineTheme() argument is a plain object literal.`,
|
|
440
480
|
{cause: e},
|
|
441
481
|
);
|
|
@@ -449,6 +489,8 @@ function extractThemeDefinitionLegacy(filePath) {
|
|
|
449
489
|
* Looks for patterns like:
|
|
450
490
|
* import { defaultIconRegistry } from './icons';
|
|
451
491
|
* icons: defaultIconRegistry,
|
|
492
|
+
* @param {string} filePath
|
|
493
|
+
* @returns {{exportName: string, importPath: string} | null}
|
|
452
494
|
*/
|
|
453
495
|
function extractIconInfo(filePath) {
|
|
454
496
|
const content = fs.readFileSync(filePath, 'utf8');
|
|
@@ -457,7 +499,7 @@ function extractIconInfo(filePath) {
|
|
|
457
499
|
const iconsMatch = content.match(/icons:\s*([a-zA-Z_][a-zA-Z0-9_]*)/);
|
|
458
500
|
if (!iconsMatch) return null;
|
|
459
501
|
|
|
460
|
-
const varName = iconsMatch[1];
|
|
502
|
+
const varName = /** @type {string} */ (iconsMatch[1]);
|
|
461
503
|
|
|
462
504
|
// Find the import for that variable
|
|
463
505
|
const importRegex = new RegExp(
|
|
@@ -468,7 +510,7 @@ function extractIconInfo(filePath) {
|
|
|
468
510
|
|
|
469
511
|
return {
|
|
470
512
|
exportName: varName,
|
|
471
|
-
importPath: importMatch[1],
|
|
513
|
+
importPath: /** @type {string} */ (importMatch[1]),
|
|
472
514
|
};
|
|
473
515
|
}
|
|
474
516
|
|
|
@@ -476,6 +518,9 @@ function extractIconInfo(filePath) {
|
|
|
476
518
|
* Generate a minimal JS module for a built theme.
|
|
477
519
|
* Includes the theme name, marker, and re-exports the icon registry.
|
|
478
520
|
* All styling is in the CSS file.
|
|
521
|
+
* @param {any} themeDef
|
|
522
|
+
* @param {{exportName: string, importPath: string} | null} iconInfo
|
|
523
|
+
* @returns {string}
|
|
479
524
|
*/
|
|
480
525
|
function generateBuiltModule(themeDef, iconInfo) {
|
|
481
526
|
const iconImport = iconInfo
|
|
@@ -487,6 +532,7 @@ function generateBuiltModule(themeDef, iconInfo) {
|
|
|
487
532
|
: '';
|
|
488
533
|
|
|
489
534
|
// Resolve token values — tuples become light-dark() strings
|
|
535
|
+
/** @type {Record<string, unknown>} */
|
|
490
536
|
const resolvedTokens = {};
|
|
491
537
|
if (themeDef.tokens) {
|
|
492
538
|
for (const [key, value] of Object.entries(themeDef.tokens)) {
|
|
@@ -500,7 +546,7 @@ function generateBuiltModule(themeDef, iconInfo) {
|
|
|
500
546
|
.join('\n');
|
|
501
547
|
|
|
502
548
|
return `${iconImport}/**
|
|
503
|
-
* ${themeDef.name} theme — built by \`${
|
|
549
|
+
* ${themeDef.name} theme — built by \`${getCliInvocation()} theme build\`
|
|
504
550
|
* Import the CSS file alongside this module:
|
|
505
551
|
*
|
|
506
552
|
* import { ${toIdentifier(themeDef.name)}Theme } from './${themeDef.name}';
|
|
@@ -517,6 +563,10 @@ ${iconReExport}`;
|
|
|
517
563
|
|
|
518
564
|
/**
|
|
519
565
|
* Generate TypeScript declarations for a built theme module.
|
|
566
|
+
* @param {any} themeDef
|
|
567
|
+
* @param {{exportName: string, importPath: string} | null} iconInfo
|
|
568
|
+
* @param {string | null} variantsFileName
|
|
569
|
+
* @returns {string}
|
|
520
570
|
*/
|
|
521
571
|
function generateBuiltTypes(themeDef, iconInfo, variantsFileName) {
|
|
522
572
|
const iconType = iconInfo
|
|
@@ -544,6 +594,7 @@ ${iconType}export declare const ${toIdentifier(themeDef.name)}Theme: DefinedThem
|
|
|
544
594
|
/**
|
|
545
595
|
* Known Astryx component names and their visual props.
|
|
546
596
|
* Used to warn on typos in defineTheme component overrides.
|
|
597
|
+
* @type {Record<string, string[]>}
|
|
547
598
|
*/
|
|
548
599
|
const KNOWN_COMPONENTS = {
|
|
549
600
|
appshell: ['position'],
|
|
@@ -605,8 +656,11 @@ const KNOWN_COMPONENTS = {
|
|
|
605
656
|
* Validate component overrides in a theme definition.
|
|
606
657
|
* Warns on unknown component names and unknown prop names.
|
|
607
658
|
* Returns array of warning strings.
|
|
659
|
+
* @param {{components?: Record<string, Record<string, unknown>>}} themeDef
|
|
660
|
+
* @returns {string[]}
|
|
608
661
|
*/
|
|
609
662
|
function validateComponentOverrides(themeDef) {
|
|
663
|
+
/** @type {string[]} */
|
|
610
664
|
const warnings = [];
|
|
611
665
|
if (!themeDef.components) return warnings;
|
|
612
666
|
|
|
@@ -669,8 +723,11 @@ function validateComponentOverrides(themeDef) {
|
|
|
669
723
|
* (e.g. borderRadius, padding) instead.
|
|
670
724
|
*
|
|
671
725
|
* Returns array of error strings.
|
|
726
|
+
* @param {{components?: Record<string, Record<string, Record<string, unknown>>>}} themeDef
|
|
727
|
+
* @returns {string[]}
|
|
672
728
|
*/
|
|
673
729
|
function validatePrivateVars(themeDef) {
|
|
730
|
+
/** @type {string[]} */
|
|
674
731
|
const errors = [];
|
|
675
732
|
if (!themeDef.components) return errors;
|
|
676
733
|
|
|
@@ -707,14 +764,14 @@ function resolveCliBin() {
|
|
|
707
764
|
* Resolves with the child's exit code; never rejects.
|
|
708
765
|
*
|
|
709
766
|
* @param {string} file - The theme file argument, as the user passed it.
|
|
710
|
-
* @param {
|
|
767
|
+
* @param {{out?: string}} options - Parsed command options (only `out` is forwarded).
|
|
711
768
|
* @returns {Promise<number>}
|
|
712
769
|
*/
|
|
713
770
|
function runThemeBuildOnceChild(file, options) {
|
|
714
771
|
const cliBin = resolveCliBin();
|
|
715
772
|
const args = [cliBin, 'theme', 'build', file];
|
|
716
773
|
if (options.out) args.push('--out', options.out);
|
|
717
|
-
return new Promise(resolve => {
|
|
774
|
+
return new Promise((/** @type {(code: number) => void} */ resolve) => {
|
|
718
775
|
const child = spawn(process.execPath, args, {
|
|
719
776
|
stdio: 'inherit',
|
|
720
777
|
env: process.env,
|
|
@@ -733,7 +790,7 @@ function runThemeBuildOnceChild(file, options) {
|
|
|
733
790
|
*
|
|
734
791
|
* @param {string} file - The theme file argument, as the user passed it.
|
|
735
792
|
* @param {string} filePath - Absolute path to the theme file.
|
|
736
|
-
* @param {
|
|
793
|
+
* @param {{out?: string}} options - Parsed command options.
|
|
737
794
|
* @returns {Promise<void>} Resolves when the watcher is stopped (Ctrl-C).
|
|
738
795
|
*/
|
|
739
796
|
async function runThemeBuildWatch(file, filePath, options) {
|
|
@@ -746,7 +803,8 @@ async function runThemeBuildWatch(file, filePath, options) {
|
|
|
746
803
|
|
|
747
804
|
let building = false;
|
|
748
805
|
let queued = false;
|
|
749
|
-
|
|
806
|
+
/** @type {ReturnType<typeof setTimeout> | undefined} */
|
|
807
|
+
let debounce;
|
|
750
808
|
|
|
751
809
|
const rebuild = async () => {
|
|
752
810
|
if (building) {
|
|
@@ -777,7 +835,7 @@ async function runThemeBuildWatch(file, filePath, options) {
|
|
|
777
835
|
debounce = setTimeout(rebuild, 100);
|
|
778
836
|
});
|
|
779
837
|
|
|
780
|
-
await new Promise(resolve => {
|
|
838
|
+
await new Promise((/** @type {(value?: void) => void} */ resolve) => {
|
|
781
839
|
const stop = () => {
|
|
782
840
|
clearTimeout(debounce);
|
|
783
841
|
watcher.close();
|
|
@@ -789,11 +847,14 @@ async function runThemeBuildWatch(file, filePath, options) {
|
|
|
789
847
|
});
|
|
790
848
|
}
|
|
791
849
|
|
|
850
|
+
/**
|
|
851
|
+
* @param {import('commander').Command} program
|
|
852
|
+
*/
|
|
792
853
|
export function registerTheme(program) {
|
|
793
854
|
const theme = program
|
|
794
855
|
.command('theme')
|
|
795
856
|
.description('Theme tools — build, export, and manage themes')
|
|
796
|
-
.action((options, cmd) => {
|
|
857
|
+
.action((/** @type {unknown} */ options, /** @type {import('commander').Command} */ cmd) => {
|
|
797
858
|
// Parent group has no default behaviour. If the user passed an
|
|
798
859
|
// unknown subcommand (e.g. `astryx theme bogus`), Commander hands it to
|
|
799
860
|
// us as a positional in cmd.args — exit 1 with a clear error.
|
|
@@ -817,7 +878,7 @@ export function registerTheme(program) {
|
|
|
817
878
|
'-w, --watch',
|
|
818
879
|
'Rebuild automatically when the theme file changes (Ctrl-C to stop)',
|
|
819
880
|
)
|
|
820
|
-
.action(async (file, options) => {
|
|
881
|
+
.action(async (/** @type {string} */ file, /** @type {{out?: string, watch?: boolean}} */ options) => {
|
|
821
882
|
const filePath = path.resolve(process.cwd(), file);
|
|
822
883
|
const json = program.opts().json || false;
|
|
823
884
|
|
|
@@ -847,7 +908,8 @@ export function registerTheme(program) {
|
|
|
847
908
|
try {
|
|
848
909
|
themeDef = await extractThemeDefinition(filePath);
|
|
849
910
|
} catch (e) {
|
|
850
|
-
|
|
911
|
+
const err = /** @type {Error} */ (e);
|
|
912
|
+
cliError(err.message, {code: ERROR_CODES.ERR_THEME_LOAD});
|
|
851
913
|
return;
|
|
852
914
|
}
|
|
853
915
|
|
|
@@ -993,7 +1055,10 @@ export function registerTheme(program) {
|
|
|
993
1055
|
const augmentationSource = resolvedTheme || themeDef;
|
|
994
1056
|
const variantDecl = await generateVariantDeclarationsAsync(augmentationSource);
|
|
995
1057
|
const variantsFileName = variantDecl ? `${baseName}.variants.d.ts` : null;
|
|
996
|
-
const variantDtsPath =
|
|
1058
|
+
const variantDtsPath =
|
|
1059
|
+
variantDecl && variantsFileName
|
|
1060
|
+
? path.join(outDir, variantsFileName)
|
|
1061
|
+
: null;
|
|
997
1062
|
const variantContent = variantDecl
|
|
998
1063
|
? generatedHeader(sourceRelative, 'ts', buildCommand) + variantDecl
|
|
999
1064
|
: null;
|
|
@@ -1014,11 +1079,12 @@ export function registerTheme(program) {
|
|
|
1014
1079
|
{dest: jsPath, content: jsContent},
|
|
1015
1080
|
{dest: dtsPath, content: dtsContent},
|
|
1016
1081
|
];
|
|
1017
|
-
if (variantDtsPath) {
|
|
1082
|
+
if (variantDtsPath && variantContent) {
|
|
1018
1083
|
writes.push({dest: variantDtsPath, content: variantContent});
|
|
1019
1084
|
}
|
|
1020
1085
|
|
|
1021
1086
|
fs.mkdirSync(outDir, {recursive: true});
|
|
1087
|
+
/** @type {Array<{tmp: string, dest: string}>} */
|
|
1022
1088
|
const staged = [];
|
|
1023
1089
|
try {
|
|
1024
1090
|
for (const w of writes) {
|
|
@@ -1034,7 +1100,7 @@ export function registerTheme(program) {
|
|
|
1034
1100
|
for (const s of staged) {
|
|
1035
1101
|
try { fs.rmSync(s.tmp, {force: true}); } catch { /* best-effort */ }
|
|
1036
1102
|
}
|
|
1037
|
-
const msg = `Failed to write theme outputs: ${err.message}`;
|
|
1103
|
+
const msg = `Failed to write theme outputs: ${/** @type {Error} */ (err).message}`;
|
|
1038
1104
|
cliError(msg, {code: ERROR_CODES.ERR_WRITE_FAILED});
|
|
1039
1105
|
return;
|
|
1040
1106
|
}
|
|
@@ -1045,7 +1111,7 @@ export function registerTheme(program) {
|
|
|
1045
1111
|
humanLog(` ${size} KB`);
|
|
1046
1112
|
humanLog(`✓ ${path.relative(process.cwd(), jsPath)}`);
|
|
1047
1113
|
humanLog(`✓ ${path.relative(process.cwd(), dtsPath)}`);
|
|
1048
|
-
if (variantDtsPath) {
|
|
1114
|
+
if (variantDtsPath && variantDecl) {
|
|
1049
1115
|
const augCount = (variantDecl.match(/': true;/g) || []).length;
|
|
1050
1116
|
humanLog(`✓ ${path.relative(process.cwd(), variantDtsPath)} (${augCount} type augmentations)`);
|
|
1051
1117
|
}
|
|
@@ -1061,7 +1127,7 @@ export function registerTheme(program) {
|
|
|
1061
1127
|
css: path.relative(process.cwd(), outPath),
|
|
1062
1128
|
js: path.relative(process.cwd(), jsPath),
|
|
1063
1129
|
dts: path.relative(process.cwd(), dtsPath),
|
|
1064
|
-
...(variantDecl ? {variantsDts: path.relative(process.cwd(), variantDtsPath)} : {}),
|
|
1130
|
+
...(variantDecl && variantDtsPath ? {variantsDts: path.relative(process.cwd(), variantDtsPath)} : {}),
|
|
1065
1131
|
},
|
|
1066
1132
|
warnings: warningMessages,
|
|
1067
1133
|
});
|
|
@@ -1108,15 +1174,21 @@ Or with a <link> tag:
|
|
|
1108
1174
|
.description('List themes available to add')
|
|
1109
1175
|
.action(async () => {
|
|
1110
1176
|
const json = program.opts().json || false;
|
|
1177
|
+
/** @type {import('../../types/theme').ThemeListResponse} */
|
|
1111
1178
|
let result;
|
|
1112
1179
|
try {
|
|
1113
|
-
result =
|
|
1180
|
+
result = /** @type {import('../../types/theme').ThemeListResponse} */ (
|
|
1181
|
+
await themeAdd(undefined, {list: true, cwd: process.cwd()})
|
|
1182
|
+
);
|
|
1114
1183
|
} catch (e) {
|
|
1115
|
-
|
|
1184
|
+
const err = /** @type {import('../../api/error.mjs').AstryxError} */ (e);
|
|
1185
|
+
cliError(err.message, {suggestions: err.suggestions || [], code: err.code});
|
|
1116
1186
|
return;
|
|
1117
1187
|
}
|
|
1118
1188
|
|
|
1119
|
-
|
|
1189
|
+
// theme.list is not registered in CLIResponseType (base.d.ts, owned by the
|
|
1190
|
+
// coordinator) — cast the discriminant until it is added there.
|
|
1191
|
+
if (json) return jsonOut(/** @type {any} */ (result.type), result.data);
|
|
1120
1192
|
|
|
1121
1193
|
const themes = result.data;
|
|
1122
1194
|
if (themes.length === 0) {
|
|
@@ -1130,7 +1202,7 @@ Or with a <link> tag:
|
|
|
1130
1202
|
if (t.description) humanLog(` ${t.description}`);
|
|
1131
1203
|
}
|
|
1132
1204
|
humanLog('\nUsage:');
|
|
1133
|
-
humanLog(
|
|
1205
|
+
humanLog(` ${getCliInvocation()} theme add <slug> [target-path] Scaffold a theme file you own\n`);
|
|
1134
1206
|
});
|
|
1135
1207
|
|
|
1136
1208
|
theme
|
|
@@ -1138,49 +1210,32 @@ Or with a <link> tag:
|
|
|
1138
1210
|
.description('Scaffold a theme into your project as editable source')
|
|
1139
1211
|
.option('-f, --overwrite', 'Overwrite existing files without prompting')
|
|
1140
1212
|
.option('--list', 'List available themes')
|
|
1141
|
-
.action(async (slug, targetPath, options) => {
|
|
1213
|
+
.action(async (/** @type {string | undefined} */ slug, /** @type {string | undefined} */ targetPath, /** @type {{list?: boolean, overwrite?: boolean}} */ options) => {
|
|
1142
1214
|
const json = program.opts().json || false;
|
|
1143
1215
|
|
|
1144
|
-
//
|
|
1145
|
-
//
|
|
1146
|
-
// ERR_FILE_EXISTS guard.
|
|
1147
|
-
|
|
1148
|
-
!json && !isNonInteractive({json}) && Boolean(process.stdin.isTTY);
|
|
1149
|
-
if (slug && !options.list && !options.overwrite && interactive) {
|
|
1150
|
-
const collision = await detectThemeCollision(slug, targetPath);
|
|
1151
|
-
if (collision) {
|
|
1152
|
-
const rel = path.relative(process.cwd(), collision) || collision;
|
|
1153
|
-
const p = await import('@clack/prompts');
|
|
1154
|
-
const confirmed = await p.confirm({
|
|
1155
|
-
message: `Overwrite existing file ${rel}?`,
|
|
1156
|
-
initialValue: false,
|
|
1157
|
-
});
|
|
1158
|
-
if (p.isCancel(confirmed)) {
|
|
1159
|
-
p.cancel('Cancelled.');
|
|
1160
|
-
return;
|
|
1161
|
-
}
|
|
1162
|
-
if (!confirmed) {
|
|
1163
|
-
humanLog('Aborted. Re-run with --overwrite to replace the file.');
|
|
1164
|
-
return;
|
|
1165
|
-
}
|
|
1166
|
-
options.overwrite = true;
|
|
1167
|
-
}
|
|
1168
|
-
}
|
|
1169
|
-
|
|
1216
|
+
// The CLI is non-interactive: never prompt to confirm an overwrite.
|
|
1217
|
+
// Existing files require an explicit --overwrite; otherwise themeAdd's
|
|
1218
|
+
// ERR_FILE_EXISTS guard rejects the write.
|
|
1219
|
+
/** @type {import('../../types/theme').ThemeListResponse | import('../../types/theme').ThemeAddResponse} */
|
|
1170
1220
|
let result;
|
|
1171
1221
|
try {
|
|
1172
|
-
result =
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1222
|
+
result = /** @type {import('../../types/theme').ThemeListResponse | import('../../types/theme').ThemeAddResponse} */ (
|
|
1223
|
+
await themeAdd(slug, {
|
|
1224
|
+
list: options.list,
|
|
1225
|
+
targetPath,
|
|
1226
|
+
overwrite: options.overwrite,
|
|
1227
|
+
cwd: process.cwd(),
|
|
1228
|
+
})
|
|
1229
|
+
);
|
|
1178
1230
|
} catch (e) {
|
|
1179
|
-
|
|
1231
|
+
const err = /** @type {import('../../api/error.mjs').AstryxError} */ (e);
|
|
1232
|
+
cliError(err.message, {suggestions: err.suggestions || [], code: err.code});
|
|
1180
1233
|
return;
|
|
1181
1234
|
}
|
|
1182
1235
|
|
|
1183
|
-
|
|
1236
|
+
// theme.list/theme.add are not registered in CLIResponseType (base.d.ts,
|
|
1237
|
+
// owned by the coordinator) — cast the discriminant until they are added.
|
|
1238
|
+
if (json) return jsonOut(/** @type {any} */ (result.type), result.data);
|
|
1184
1239
|
|
|
1185
1240
|
if (result.type === 'theme.list') {
|
|
1186
1241
|
const themes = result.data;
|
|
@@ -1191,7 +1246,7 @@ Or with a <link> tag:
|
|
|
1191
1246
|
if (t.description) humanLog(` ${t.description}`);
|
|
1192
1247
|
}
|
|
1193
1248
|
humanLog('\nUsage:');
|
|
1194
|
-
humanLog(
|
|
1249
|
+
humanLog(` ${getCliInvocation()} theme add <slug> [target-path] Scaffold a theme file you own\n`);
|
|
1195
1250
|
return;
|
|
1196
1251
|
}
|
|
1197
1252
|
|
|
@@ -1219,40 +1274,3 @@ This is your copy of the ${displayName} theme — edit ${entry} to make it your
|
|
|
1219
1274
|
});
|
|
1220
1275
|
}
|
|
1221
1276
|
|
|
1222
|
-
/**
|
|
1223
|
-
* First existing file that scaffolding <slug> into <targetPath> would clobber,
|
|
1224
|
-
* or null. Used to prompt before invoking the API; the API re-validates and
|
|
1225
|
-
* owns any authoritative error.
|
|
1226
|
-
*
|
|
1227
|
-
* @param {string} slug
|
|
1228
|
-
* @param {string} [targetPath]
|
|
1229
|
-
* @returns {Promise<string|null>}
|
|
1230
|
-
*/
|
|
1231
|
-
async function detectThemeCollision(slug, targetPath) {
|
|
1232
|
-
let themes;
|
|
1233
|
-
try {
|
|
1234
|
-
themes = listThemes();
|
|
1235
|
-
} catch {
|
|
1236
|
-
return null;
|
|
1237
|
-
}
|
|
1238
|
-
const match = themes.find(t => t.slug.toLowerCase() === slug.toLowerCase());
|
|
1239
|
-
if (!match) return null;
|
|
1240
|
-
|
|
1241
|
-
const rawTarget = targetPath || path.join('src', 'themes', match.slug);
|
|
1242
|
-
let resolvedDir;
|
|
1243
|
-
try {
|
|
1244
|
-
// Fail soft (null) on traversal; the API surfaces the real error.
|
|
1245
|
-
const {assertWithin} = await import('../utils/path-safety.mjs');
|
|
1246
|
-
resolvedDir = assertWithin(rawTarget, process.cwd(), {
|
|
1247
|
-
label: 'theme target path',
|
|
1248
|
-
});
|
|
1249
|
-
} catch {
|
|
1250
|
-
return null;
|
|
1251
|
-
}
|
|
1252
|
-
|
|
1253
|
-
for (const name of match.files) {
|
|
1254
|
-
const dest = path.join(resolvedDir, name);
|
|
1255
|
-
if (fs.existsSync(dest)) return dest;
|
|
1256
|
-
}
|
|
1257
|
-
return null;
|
|
1258
|
-
}
|