@astryxdesign/cli 0.1.8-canary.0c4d8d7 → 0.1.8-canary.0db5dfd
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/{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 +11 -8
- 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 +125 -46
- package/{src → cli}/commands/build.mjs +33 -57
- package/{src → cli}/commands/component/index.mjs +49 -22
- 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 +17 -8
- package/{src → cli}/commands/docs.mjs +39 -7
- 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 +37 -14
- package/{src → cli}/commands/import-hint-correctness.test.mjs +1 -1
- package/{src → cli}/commands/init.mjs +20 -9
- package/{src → cli}/commands/layout.mjs +58 -18
- package/{src → cli}/commands/search.mjs +19 -12
- package/{src → cli}/commands/search.test.mjs +1 -1
- package/{src → cli}/commands/setup-nudge.test.mjs +1 -1
- package/cli/commands/swizzle.mjs +103 -0
- package/{src → cli}/commands/template.mjs +73 -22
- 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 +160 -52
- package/{src → cli}/commands/upgrade.test.mjs +1 -1
- package/{src → cli}/commands/validate-integration.mjs +17 -37
- package/{src → cli}/index.mjs +17 -15
- package/{src/codemods → codemods}/ensure-jscodeshift.mjs +1 -1
- 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 +3 -1
- package/{src/codemods → codemods}/run-codemod.mjs +17 -10
- package/{src/codemods → codemods}/runner.mjs +22 -12
- 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/drop-xds-prefix-imports.mjs +19 -14
- 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 +16 -11
- 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/{src/codemods → codemods}/transforms/v0.1.8/rename-avatar-size-scale.mjs +15 -10
- package/docs/internationalization.doc.mjs +92 -46
- package/{src/commands → lib/agent-docs}/agent-docs.mjs +30 -11
- package/{src/commands → lib/agent-docs}/agent-docs.path-safety.test.mjs +1 -1
- package/{src/lib → lib}/component-discovery.mjs +44 -2
- package/{src/lib → lib}/component-format.mjs +65 -24
- 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 +10 -5
- package/{src/lib → lib}/json-shim.test.mjs +1 -1
- 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/{src/lib → lib}/term-log.mjs +12 -3
- 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 +33 -26
- package/scripts/postinstall.mjs +4 -4
- package/templates/blocks/components/Avatar/AvatarShowcase.tsx +1 -1
- 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/{src/types → types}/api.contract.assert.ts +17 -8
- package/{src/types → types}/api.d.ts +106 -0
- package/{src/types → types}/base.d.ts +17 -2
- 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/types/jscodeshift.d.ts +19 -0
- package/types/layout.d.ts +74 -0
- package/types/theme.d.ts +53 -0
- package/{src/types → types}/upgrade.d.ts +8 -1
- package/{src/utils → utils}/paths.mjs +4 -1
- package/src/commands/swizzle.mjs +0 -417
- package/src/types/build.d.ts +0 -23
- package/src/types/codemod.d.ts +0 -81
- package/src/types/theme.d.ts +0 -23
- /package/{src/api → api/docs}/docOverlays.test.mjs +0 -0
- /package/{src/api → api}/error.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/cli-postinstall.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/init.next-steps.test.mjs +0 -0
- /package/{src → cli}/commands/interactive-guard.test.mjs +0 -0
- /package/{src → cli}/commands/json-contract.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__/registry.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__/drop-xds-prefix-imports.test.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__/migrate-xds-module-specifiers.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/codemods → codemods}/transforms/v0.1.8/__tests__/rename-avatar-size-scale.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.1.8/index.mjs +0 -0
- /package/{src/commands → lib/agent-docs}/agent-docs.test.mjs +0 -0
- /package/{src/lib → lib}/cli-error.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}/json.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}/index.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}/swizzle.d.ts +0 -0
- /package/{src/types → types}/template-api.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}/package-manager.mjs +0 -0
- /package/{src/utils → utils}/package-manager.test.mjs +0 -0
- /package/{src/utils → utils}/path-safety.mjs +0 -0
- /package/{src/utils → utils}/path-safety.test.mjs +0 -0
- /package/{src/utils → utils}/paths.test.mjs +0 -0
- /package/{src/utils → utils}/semver.mjs +0 -0
- /package/{src/utils → utils}/semver.test.mjs +0 -0
- /package/{src/utils → utils}/update-check.mjs +0 -0
- /package/{src/utils → utils}/update-check.test.mjs +0 -0
|
@@ -80,7 +80,7 @@ const UNIQUE = new Set(['tiny', 'xsmall']);
|
|
|
80
80
|
* Unwraps `'small' as const`. In non-precise contexts, ambiguous names are
|
|
81
81
|
* skipped. Returns true when a rename occurred.
|
|
82
82
|
*/
|
|
83
|
-
function renameValue(node, {precise = false} = {}) {
|
|
83
|
+
function renameValue(/** @type {any} */ node, {precise = false} = {}) {
|
|
84
84
|
if (!node) return false;
|
|
85
85
|
const target = node.type === 'TSAsExpression' ? node.expression : node;
|
|
86
86
|
const isString =
|
|
@@ -95,7 +95,7 @@ function renameValue(node, {precise = false} = {}) {
|
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
/** Extract a plain string value from a literal-ish node, or null. */
|
|
98
|
-
function literalString(node) {
|
|
98
|
+
function literalString(/** @type {any} */ node) {
|
|
99
99
|
const target = node?.type === 'TSAsExpression' ? node.expression : node;
|
|
100
100
|
if (
|
|
101
101
|
target &&
|
|
@@ -107,6 +107,11 @@ function literalString(node) {
|
|
|
107
107
|
return null;
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
+
/**
|
|
111
|
+
* @param {import('../../../types/codemod').AstryxCodemodFile} file
|
|
112
|
+
* @param {import('../../../types/codemod').CodemodTransformApi} api
|
|
113
|
+
* @returns {string | null | undefined}
|
|
114
|
+
*/
|
|
110
115
|
export default function transformer(file, api) {
|
|
111
116
|
const j = api.jscodeshift;
|
|
112
117
|
const root = j(file.source);
|
|
@@ -114,7 +119,7 @@ export default function transformer(file, api) {
|
|
|
114
119
|
|
|
115
120
|
// Track alias-aware local names for the target components.
|
|
116
121
|
const targetLocals = new Set();
|
|
117
|
-
root.find(j.ImportDeclaration).forEach((path) => {
|
|
122
|
+
root.find(j.ImportDeclaration).forEach((/** @type {any} */ path) => {
|
|
118
123
|
if (!IMPORT_SOURCES.has(path.node.source.value)) return;
|
|
119
124
|
for (const spec of path.node.specifiers ?? []) {
|
|
120
125
|
if (
|
|
@@ -128,14 +133,14 @@ export default function transformer(file, api) {
|
|
|
128
133
|
|
|
129
134
|
if (targetLocals.size === 0) return undefined;
|
|
130
135
|
|
|
131
|
-
function renameArrayElements(node) {
|
|
136
|
+
function renameArrayElements(/** @type {any} */ node) {
|
|
132
137
|
let arr = node;
|
|
133
138
|
if (arr.type === 'TSAsExpression') arr = arr.expression;
|
|
134
139
|
if (arr.type !== 'ArrayExpression') return;
|
|
135
140
|
// If the array contains a name unique to Avatar's scale (tiny/xsmall), the
|
|
136
141
|
// whole collection is unambiguously the Avatar size enum, so it is safe to
|
|
137
142
|
// rename the ambiguous members too. Otherwise stay conservative.
|
|
138
|
-
const precise = arr.elements.some((el) => UNIQUE.has(literalString(el)));
|
|
143
|
+
const precise = arr.elements.some((/** @type {any} */ el) => UNIQUE.has(literalString(el)));
|
|
139
144
|
for (const el of arr.elements) {
|
|
140
145
|
if (renameValue(el, {precise})) hasChanges = true;
|
|
141
146
|
}
|
|
@@ -143,7 +148,7 @@ export default function transformer(file, api) {
|
|
|
143
148
|
|
|
144
149
|
// 1. `size` JSX attributes on target components — PRECISE (component known),
|
|
145
150
|
// so all five names, including the ambiguous ones, are renamed here.
|
|
146
|
-
root.find(j.JSXOpeningElement).forEach((path) => {
|
|
151
|
+
root.find(j.JSXOpeningElement).forEach((/** @type {any} */ path) => {
|
|
147
152
|
const name = path.node.name;
|
|
148
153
|
const componentName = name.type === 'JSXIdentifier' ? name.name : null;
|
|
149
154
|
if (!componentName || !targetLocals.has(componentName)) return;
|
|
@@ -182,7 +187,7 @@ export default function transformer(file, api) {
|
|
|
182
187
|
// arrays — NON-PRECISE (the component isn't known here), so only the
|
|
183
188
|
// unique names tiny/xsmall are renamed.
|
|
184
189
|
const PropertyType = j.ObjectProperty ?? j.Property;
|
|
185
|
-
root.find(PropertyType).forEach((path) => {
|
|
190
|
+
root.find(PropertyType).forEach((/** @type {any} */ path) => {
|
|
186
191
|
const key = path.node.key;
|
|
187
192
|
const keyName =
|
|
188
193
|
key.type === 'Identifier'
|
|
@@ -204,7 +209,7 @@ export default function transformer(file, api) {
|
|
|
204
209
|
// size: { control: 'select', options: ['tiny', ...] }
|
|
205
210
|
if (value.type === 'ObjectExpression') {
|
|
206
211
|
const optionsProp = value.properties.find(
|
|
207
|
-
(p) => p.key && (p.key.name === 'options' || p.key.value === 'options'),
|
|
212
|
+
(/** @type {any} */ p) => p.key && (p.key.name === 'options' || p.key.value === 'options'),
|
|
208
213
|
);
|
|
209
214
|
if (optionsProp) renameArrayElements(optionsProp.value);
|
|
210
215
|
}
|
|
@@ -216,7 +221,7 @@ export default function transformer(file, api) {
|
|
|
216
221
|
// are renamed. This avoids corrupting unrelated unions that happen to use
|
|
217
222
|
// common words like 'medium' (e.g. a priority or breakpoint type) in a
|
|
218
223
|
// file that also imports Avatar.
|
|
219
|
-
root.find(j.TSLiteralType).forEach((path) => {
|
|
224
|
+
root.find(j.TSLiteralType).forEach((/** @type {any} */ path) => {
|
|
220
225
|
if (renameValue(path.node.literal)) hasChanges = true;
|
|
221
226
|
});
|
|
222
227
|
|
|
@@ -225,7 +230,7 @@ export default function transformer(file, api) {
|
|
|
225
230
|
// e.g. `(['tiny', 'xsmall', 'small', 'medium', 'large'] as const).map(...)`
|
|
226
231
|
// used to render every size. The unique name proves the whole array is the
|
|
227
232
|
// Avatar enum, so its ambiguous members can be renamed safely.
|
|
228
|
-
root.find(j.ArrayExpression).forEach((path) => {
|
|
233
|
+
root.find(j.ArrayExpression).forEach((/** @type {any} */ path) => {
|
|
229
234
|
renameArrayElements(path.node);
|
|
230
235
|
});
|
|
231
236
|
|
|
@@ -7,7 +7,7 @@ export const docs = {
|
|
|
7
7
|
title: 'Internationalization',
|
|
8
8
|
category: 'guide',
|
|
9
9
|
description:
|
|
10
|
-
'
|
|
10
|
+
'Set the active locale for astryx components, load locale catalogs, coexist with your own i18n library, swap languages at runtime, and test translations with the pseudo locale.',
|
|
11
11
|
|
|
12
12
|
sections: [
|
|
13
13
|
{
|
|
@@ -16,13 +16,13 @@ export const docs = {
|
|
|
16
16
|
content: [
|
|
17
17
|
{
|
|
18
18
|
type: 'prose',
|
|
19
|
-
text: 'Internationalization ships with `@astryxdesign/core`. There is nothing to install. Wrap your app in `<InternationalizationProvider>` and set
|
|
19
|
+
text: 'Internationalization ships with `@astryxdesign/core`. There is nothing to install. Wrap your app in `<InternationalizationProvider>` and set the active `locale`; astryx components pick up localized strings from that provider.',
|
|
20
20
|
},
|
|
21
21
|
{
|
|
22
22
|
type: 'code',
|
|
23
23
|
lang: 'tsx',
|
|
24
24
|
label: 'Wrap your app',
|
|
25
|
-
code: `import {InternationalizationProvider} from '@astryxdesign/core';
|
|
25
|
+
code: `import {InternationalizationProvider} from '@astryxdesign/core/i18n';
|
|
26
26
|
|
|
27
27
|
function App() {
|
|
28
28
|
return (
|
|
@@ -32,53 +32,56 @@ function App() {
|
|
|
32
32
|
);
|
|
33
33
|
}`,
|
|
34
34
|
},
|
|
35
|
+
{
|
|
36
|
+
type: 'prose',
|
|
37
|
+
text: 'The provider always has the built-in English catalog. Pass additional catalogs through `messages` when you enable another locale.',
|
|
38
|
+
},
|
|
35
39
|
{
|
|
36
40
|
type: 'code',
|
|
37
41
|
lang: 'tsx',
|
|
38
|
-
label: '
|
|
39
|
-
code: `import {
|
|
42
|
+
label: 'Load an astryx locale catalog',
|
|
43
|
+
code: `import {InternationalizationProvider} from '@astryxdesign/core/i18n';
|
|
44
|
+
import fr from '@astryxdesign/core/locales/fr.json';
|
|
40
45
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}`,
|
|
46
|
+
<InternationalizationProvider locale="fr" messages={{fr}}>
|
|
47
|
+
<App />
|
|
48
|
+
</InternationalizationProvider>;`,
|
|
45
49
|
},
|
|
46
50
|
{
|
|
47
51
|
type: 'prose',
|
|
48
|
-
text: '
|
|
52
|
+
text: 'Astryx ships English today, with first-party translations for other locales on the roadmap. Until a locale is available from `@astryxdesign/core/locales/*`, apps can pass a local catalog with the same shape. See `@astryxdesign/core/locales/en.json` for the current key inventory. Missing keys fall back through the locale chain to English (for example, `pt-BR` walks to `pt`, then to shipped `en`).',
|
|
49
53
|
},
|
|
50
54
|
{
|
|
51
55
|
type: 'prose',
|
|
52
|
-
text:
|
|
56
|
+
text: 'Locale catalogs only affect astryx strings. Your app can continue using its own i18n system for product copy.',
|
|
53
57
|
},
|
|
54
58
|
],
|
|
55
59
|
},
|
|
56
60
|
{
|
|
57
|
-
title: '
|
|
61
|
+
title: 'Runtime language swap',
|
|
58
62
|
category: 'guide',
|
|
59
63
|
content: [
|
|
60
64
|
{
|
|
61
65
|
type: 'prose',
|
|
62
|
-
text: '
|
|
66
|
+
text: 'Re-render `<InternationalizationProvider>` with a new `locale` prop and every astryx string updates live. No reload, no separate API call.',
|
|
63
67
|
},
|
|
64
68
|
{
|
|
65
69
|
type: 'code',
|
|
66
70
|
lang: 'tsx',
|
|
67
|
-
label: '
|
|
68
|
-
code: `
|
|
69
|
-
import fr from './locales/astryx/fr.json';
|
|
71
|
+
label: 'Toggle between locales',
|
|
72
|
+
code: `const [locale, setLocale] = useState<'en' | 'fr'>('en');
|
|
70
73
|
|
|
71
|
-
<InternationalizationProvider locale=
|
|
74
|
+
<InternationalizationProvider locale={locale} messages={{fr}}>
|
|
75
|
+
<Button
|
|
76
|
+
label={locale === 'en' ? 'Français' : 'English'}
|
|
77
|
+
onClick={() => setLocale(l => (l === 'en' ? 'fr' : 'en'))}
|
|
78
|
+
/>
|
|
72
79
|
<App />
|
|
73
80
|
</InternationalizationProvider>;`,
|
|
74
81
|
},
|
|
75
82
|
{
|
|
76
83
|
type: 'prose',
|
|
77
|
-
text: "
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
type: 'prose',
|
|
81
|
-
text: 'A community-maintained set of astryx translations is on the roadmap but not shipped yet. For now, consumer apps that ship in multiple languages own their astryx catalogs alongside their app catalogs. Contributions to a first-party set are welcome; track discussion at https://github.com/facebook/astryx/issues/3641.',
|
|
84
|
+
text: "Persisting the user's choice (localStorage, cookie, URL segment, account setting) is up to the consumer. Astryx reads whatever `locale` you pass in.",
|
|
82
85
|
},
|
|
83
86
|
],
|
|
84
87
|
},
|
|
@@ -119,7 +122,7 @@ import fr from './locales/astryx/fr.json';
|
|
|
119
122
|
type: 'code',
|
|
120
123
|
lang: 'tsx',
|
|
121
124
|
label: 'Astryx + react-intl side by side',
|
|
122
|
-
code: `import {InternationalizationProvider} from '@astryxdesign/core';
|
|
125
|
+
code: `import {InternationalizationProvider} from '@astryxdesign/core/i18n';
|
|
123
126
|
import {Selector} from '@astryxdesign/core/Selector';
|
|
124
127
|
import {Button} from '@astryxdesign/core/Button';
|
|
125
128
|
import {FormattedMessage, IntlProvider, useIntl} from 'react-intl';
|
|
@@ -169,35 +172,56 @@ export default function App() {
|
|
|
169
172
|
},
|
|
170
173
|
{
|
|
171
174
|
type: 'prose',
|
|
172
|
-
text: "Single-catalog usage (where an external i18n runtime like react-intl or i18next resolves both your app strings AND astryx's strings through one provider) is on the roadmap via a `Translator` adapter. Track https://github.com/facebook/astryx/issues/4029. For now, run the two providers side by side as shown above.",
|
|
175
|
+
text: "Single-catalog usage (where an external i18n runtime like react-intl or i18next resolves both your app strings AND astryx's strings through one provider) is on the roadmap via a `Translator` adapter. Track [facebook/astryx#4029](https://github.com/facebook/astryx/issues/4029). For now, run the two providers side by side as shown above.",
|
|
173
176
|
},
|
|
174
177
|
],
|
|
175
178
|
},
|
|
176
179
|
{
|
|
177
|
-
title: '
|
|
180
|
+
title: 'Using astryx as your i18n library',
|
|
178
181
|
category: 'guide',
|
|
179
182
|
content: [
|
|
180
183
|
{
|
|
181
184
|
type: 'prose',
|
|
182
|
-
text:
|
|
185
|
+
text: "For production apps with substantial localization needs, we recommend a dedicated i18n library such as react-intl, i18next, next-intl, or LinguiJS. If your app is small or you do not want another runtime, you can resolve your own strings through astryx too. Keep app keys in a separate namespace from `@astryx.*`, and include your own `en` catalog because astryx's built-in English fallback only contains astryx component strings.",
|
|
183
186
|
},
|
|
184
187
|
{
|
|
185
188
|
type: 'code',
|
|
186
189
|
lang: 'tsx',
|
|
187
|
-
label: '
|
|
188
|
-
code: `
|
|
190
|
+
label: 'Translate app strings with astryx',
|
|
191
|
+
code: `import {Button} from '@astryxdesign/core/Button';
|
|
192
|
+
import {
|
|
193
|
+
InternationalizationProvider,
|
|
194
|
+
useTranslator,
|
|
195
|
+
type Catalog,
|
|
196
|
+
type MessagesByLocale,
|
|
197
|
+
} from '@astryxdesign/core/i18n';
|
|
189
198
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
199
|
+
const en: Catalog = {
|
|
200
|
+
'@myapp.actions.save': {defaultMessage: 'Save'},
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
const fr: Catalog = {
|
|
204
|
+
'@myapp.actions.save': {defaultMessage: 'Enregistrer'},
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
const messages: MessagesByLocale = {en, fr};
|
|
208
|
+
|
|
209
|
+
function SaveButton() {
|
|
210
|
+
const t = useTranslator();
|
|
211
|
+
return <Button label={t('@myapp.actions.save')} />;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export default function App() {
|
|
215
|
+
return (
|
|
216
|
+
<InternationalizationProvider locale="fr" messages={messages}>
|
|
217
|
+
<SaveButton />
|
|
218
|
+
</InternationalizationProvider>
|
|
219
|
+
);
|
|
220
|
+
}`,
|
|
197
221
|
},
|
|
198
222
|
{
|
|
199
223
|
type: 'prose',
|
|
200
|
-
text:
|
|
224
|
+
text: '`Catalog` types a single locale file; `MessagesByLocale` types the map passed to `messages`. A catalog entry uses the same `{defaultMessage, description?}` shape as `@astryxdesign/core/locales/en.json`.',
|
|
201
225
|
},
|
|
202
226
|
],
|
|
203
227
|
},
|
|
@@ -207,36 +231,58 @@ export default function App() {
|
|
|
207
231
|
content: [
|
|
208
232
|
{
|
|
209
233
|
type: 'prose',
|
|
210
|
-
text: 'Astryx generates a `pseudo` locale that wraps every string in `⟦…⟧` and replaces letters with accented look-alikes.
|
|
234
|
+
text: 'Astryx generates a `pseudo` locale that wraps every string in `⟦…⟧` and replaces letters with accented look-alikes. Switch to it in development to catch hardcoded astryx strings and layout issues caused by longer text.',
|
|
211
235
|
},
|
|
212
236
|
{
|
|
213
237
|
type: 'code',
|
|
214
238
|
lang: 'tsx',
|
|
215
239
|
label: 'Turn on pseudo-localization',
|
|
216
|
-
code: `import
|
|
240
|
+
code: `import {InternationalizationProvider} from '@astryxdesign/core/i18n';
|
|
241
|
+
import pseudo from '@astryxdesign/core/locales/pseudo.json';
|
|
217
242
|
|
|
218
243
|
<InternationalizationProvider locale="pseudo" messages={{pseudo}}>
|
|
219
244
|
<App />
|
|
220
245
|
</InternationalizationProvider>;`,
|
|
221
246
|
},
|
|
222
|
-
{
|
|
223
|
-
type: 'prose',
|
|
224
|
-
text: 'Any bare English text you still see on screen is a hardcoded string that needs to be routed through `useTranslator`.',
|
|
225
|
-
},
|
|
226
|
-
{
|
|
227
|
-
type: 'prose',
|
|
228
|
-
text: "Pseudoloc also has a subtle caveat worth knowing: the pseudo catalog is complete (astryx generates it from every shipped key), so a component using an astryx-shipped key will always render its pseudo version. Your handwritten translation catalogs, on the other hand, only cover the keys you translated; anything missing falls back to English. That means \"looks perfect in pseudo\" is not the same guarantee as \"looks perfect in French.\" Check each real locale by hand for coverage gaps.",
|
|
229
|
-
},
|
|
230
247
|
],
|
|
231
248
|
},
|
|
232
249
|
{
|
|
233
250
|
title: 'For contributors',
|
|
234
251
|
category: 'guide',
|
|
235
252
|
content: [
|
|
253
|
+
{
|
|
254
|
+
type: 'heading',
|
|
255
|
+
level: 3,
|
|
256
|
+
text: 'Developers',
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
type: 'prose',
|
|
260
|
+
text: 'Astryx component authors read strings with `useTranslator()` rather than hardcoding user-facing text.',
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
type: 'code',
|
|
264
|
+
lang: 'tsx',
|
|
265
|
+
label: 'Read an astryx string',
|
|
266
|
+
code: `import {useTranslator} from '@astryxdesign/core/i18n';
|
|
267
|
+
|
|
268
|
+
function SaveButton() {
|
|
269
|
+
const t = useTranslator();
|
|
270
|
+
return <button>{t('@astryx.actions.save')}</button>;
|
|
271
|
+
}`,
|
|
272
|
+
},
|
|
236
273
|
{
|
|
237
274
|
type: 'prose',
|
|
238
275
|
text: "Astryx's own strings live in `packages/core/locales/en.json`. New user-facing strings must go through `useTranslator`; this is enforced by the `@astryx/no-hardcoded-i18n-string` ESLint rule. See the AI contribution guide for the alias-and-resolve pattern used when adding new keys.",
|
|
239
276
|
},
|
|
277
|
+
{
|
|
278
|
+
type: 'heading',
|
|
279
|
+
level: 3,
|
|
280
|
+
text: 'Translators',
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
type: 'prose',
|
|
284
|
+
text: 'Crowdin is the preferred way to contribute — [join a language](https://crowdin.com/project/astryx), translate strings in the web UI, and your work syncs back to the repo without opening a PR. Direct PRs against `packages/core/locales/*.json` also work if you prefer that flow.',
|
|
285
|
+
},
|
|
240
286
|
],
|
|
241
287
|
},
|
|
242
288
|
],
|
|
@@ -20,13 +20,13 @@
|
|
|
20
20
|
|
|
21
21
|
import * as fs from 'node:fs';
|
|
22
22
|
import * as path from 'node:path';
|
|
23
|
-
import {findCoreDir, CLI_ROOT} from '
|
|
24
|
-
import {assertWithin, PathSafetyError} from '
|
|
25
|
-
import {getCliInvocation} from '
|
|
26
|
-
import {discoverComponents} from '
|
|
27
|
-
import {humanLog} from '
|
|
28
|
-
import {cliError} from '
|
|
29
|
-
import {ERROR_CODES} from '
|
|
23
|
+
import {findCoreDir, CLI_ROOT} from '../../utils/paths.mjs';
|
|
24
|
+
import {assertWithin, PathSafetyError} from '../../utils/path-safety.mjs';
|
|
25
|
+
import {getCliInvocation} from '../../utils/package-manager.mjs';
|
|
26
|
+
import {discoverComponents} from '../../lib/component-discovery.mjs';
|
|
27
|
+
import {humanLog} from '../../lib/json.mjs';
|
|
28
|
+
import {cliError} from '../../lib/cli-error.mjs';
|
|
29
|
+
import {ERROR_CODES} from '../../lib/error-codes.mjs';
|
|
30
30
|
|
|
31
31
|
const AGENTS_MD = 'AGENTS.md';
|
|
32
32
|
const CLAUDE_MD = 'CLAUDE.md';
|
|
@@ -143,9 +143,11 @@ export function parseBlockVersion(content) {
|
|
|
143
143
|
*/
|
|
144
144
|
export function inspectAgentDocs(targetDir, installedVersion) {
|
|
145
145
|
const version = installedVersion ?? getXdsVersion(findCoreDir(targetDir));
|
|
146
|
+
/** @type {Array<{path: string, blockVersion: string|null, legacy: boolean, stale: boolean}>} */
|
|
146
147
|
const files = [];
|
|
147
148
|
|
|
148
149
|
for (const rel of discoverAgentDocs(targetDir)) {
|
|
150
|
+
/** @type {string} */
|
|
149
151
|
let content;
|
|
150
152
|
try {
|
|
151
153
|
content = fs.readFileSync(path.join(targetDir, rel), 'utf-8');
|
|
@@ -165,9 +167,10 @@ export function inspectAgentDocs(targetDir, installedVersion) {
|
|
|
165
167
|
const staleEntries = files.filter(f => f.stale);
|
|
166
168
|
const staleFiles = staleEntries.map(f => f.path);
|
|
167
169
|
const blockVersions = [
|
|
168
|
-
...new Set(staleEntries.map(f => f.blockVersion).filter(
|
|
170
|
+
...new Set(staleEntries.map(f => f.blockVersion).filter(/** @returns {v is string} */ (v) => v != null)),
|
|
169
171
|
];
|
|
170
172
|
|
|
173
|
+
/** @type {'missing' | 'stale' | 'current'} */
|
|
171
174
|
let status;
|
|
172
175
|
if (files.length === 0) status = 'missing';
|
|
173
176
|
else if (staleFiles.length > 0) status = 'stale';
|
|
@@ -195,7 +198,7 @@ export function resolveAgentPaths(targetDir, agent) {
|
|
|
195
198
|
return {inject: [], create: [AGENTS_MD, CLAUDE_DIR_MD]};
|
|
196
199
|
}
|
|
197
200
|
|
|
198
|
-
const searchPaths = AGENT_PRESETS[agent];
|
|
201
|
+
const searchPaths = /** @type {Record<string, string[]>} */ (AGENT_PRESETS)[agent];
|
|
199
202
|
if (!searchPaths) {
|
|
200
203
|
return {inject: [], create: [AGENTS_MD]};
|
|
201
204
|
}
|
|
@@ -258,6 +261,10 @@ export function detectStylingSystem(targetDir) {
|
|
|
258
261
|
* `stylingSystem` tailors the custom-styling guidance to what the project has
|
|
259
262
|
* configured (see {@link detectStylingSystem}) so the agent never reaches for a
|
|
260
263
|
* styling path that isn't compiled here.
|
|
264
|
+
*
|
|
265
|
+
* @param {string} version
|
|
266
|
+
* @param {{coreDir?: string|null, invocation?: string, stylingSystem?: 'stylex'|'tailwind'|'css', zh?: boolean, lang?: string}} [options]
|
|
267
|
+
* @returns {string}
|
|
261
268
|
*/
|
|
262
269
|
export function generateCompressedIndex(version, {coreDir, invocation = getCliInvocation(), stylingSystem = 'css'} = {}) {
|
|
263
270
|
const run = invocation;
|
|
@@ -337,7 +344,7 @@ export function generateCompressedIndex(version, {coreDir, invocation = getCliIn
|
|
|
337
344
|
if (fs.existsSync(docsDir)) {
|
|
338
345
|
const topics = fs.readdirSync(docsDir)
|
|
339
346
|
.map(f => f.match(/^(\w+)\.doc\.mjs$/))
|
|
340
|
-
.filter(
|
|
347
|
+
.filter(/** @returns {m is RegExpMatchArray} */ (m) => m != null)
|
|
341
348
|
.map(m => m[1])
|
|
342
349
|
.sort();
|
|
343
350
|
if (topics.length > 0) lines.push(` docs <topic> ${topics.join(', ')}`);
|
|
@@ -351,6 +358,8 @@ export function generateCompressedIndex(version, {coreDir, invocation = getCliIn
|
|
|
351
358
|
|
|
352
359
|
/**
|
|
353
360
|
* Get Astryx version from core package.
|
|
361
|
+
* @param {string|null} coreDir
|
|
362
|
+
* @returns {string}
|
|
354
363
|
*/
|
|
355
364
|
export function getXdsVersion(coreDir) {
|
|
356
365
|
if (coreDir) {
|
|
@@ -419,6 +428,9 @@ export function injectXdsBlock(filePath, compressedIndex, {createIfMissing = fal
|
|
|
419
428
|
/**
|
|
420
429
|
* Inject or update Astryx section in AGENTS.md.
|
|
421
430
|
* Always creates the file if it doesn't exist.
|
|
431
|
+
*
|
|
432
|
+
* @param {string} targetDir
|
|
433
|
+
* @param {string} version
|
|
422
434
|
*/
|
|
423
435
|
export function injectAgentsMd(targetDir, version) {
|
|
424
436
|
const agentsPath = path.join(targetDir, AGENTS_MD);
|
|
@@ -436,6 +448,8 @@ export function injectAgentsMd(targetDir, version) {
|
|
|
436
448
|
* Inject or update Astryx section in CLAUDE.md.
|
|
437
449
|
* Only injects if CLAUDE.md already exists.
|
|
438
450
|
*
|
|
451
|
+
* @param {string} targetDir
|
|
452
|
+
* @param {string} version
|
|
439
453
|
* @returns {boolean} Whether the file was written
|
|
440
454
|
*/
|
|
441
455
|
export function injectClaudeMd(targetDir, version) {
|
|
@@ -451,6 +465,8 @@ export function injectClaudeMd(targetDir, version) {
|
|
|
451
465
|
* Remove Astryx section from a file.
|
|
452
466
|
* If the file becomes empty (only boilerplate header remains), deletes it.
|
|
453
467
|
*
|
|
468
|
+
* @param {string} filePath
|
|
469
|
+
* @param {{deleteIfEmpty?: boolean}} [options]
|
|
454
470
|
* @returns {boolean} Whether the Astryx section was found and removed
|
|
455
471
|
*/
|
|
456
472
|
export function removeXdsBlock(filePath, {deleteIfEmpty = false} = {}) {
|
|
@@ -487,6 +503,7 @@ export function removeXdsBlock(filePath, {deleteIfEmpty = false} = {}) {
|
|
|
487
503
|
|
|
488
504
|
/**
|
|
489
505
|
* Remove Astryx section from all known agent doc files.
|
|
506
|
+
* @param {string} targetDir
|
|
490
507
|
*/
|
|
491
508
|
export function removeAgentDocs(targetDir) {
|
|
492
509
|
const allPaths = discoverAgentDocs(targetDir);
|
|
@@ -528,6 +545,7 @@ export function installAgentDocs(targetDir, {zh = false, lang, agent, paths, onl
|
|
|
528
545
|
const invocation = getCliInvocation(targetDir);
|
|
529
546
|
const stylingSystem = detectStylingSystem(targetDir);
|
|
530
547
|
const compressedIndex = generateCompressedIndex(version, {coreDir, zh, lang, invocation, stylingSystem});
|
|
548
|
+
/** @type {string[]} */
|
|
531
549
|
const written = [];
|
|
532
550
|
|
|
533
551
|
// Explicit paths override everything
|
|
@@ -603,6 +621,7 @@ export function installAgentDocs(targetDir, {zh = false, lang, agent, paths, onl
|
|
|
603
621
|
|
|
604
622
|
const VALID_AGENTS = ['claude', 'cursor', 'codex', 'hermes', 'all'];
|
|
605
623
|
|
|
624
|
+
/** @param {import('commander').Command} program */
|
|
606
625
|
export function registerAgentDocs(program) {
|
|
607
626
|
program
|
|
608
627
|
.command('agent-docs')
|
|
@@ -610,7 +629,7 @@ export function registerAgentDocs(program) {
|
|
|
610
629
|
.option('--remove', 'Remove the design system section from all agent doc files')
|
|
611
630
|
.option('--agent <tool>', 'Target tool: claude, cursor, codex, hermes, all')
|
|
612
631
|
.option('--agent-docs-path <path...>', 'Explicit file path(s) to write to')
|
|
613
|
-
.action(options => {
|
|
632
|
+
.action(/** @param {{remove?: boolean, agent?: string, agentDocsPath?: string|string[]}} options */ options => {
|
|
614
633
|
const targetDir = process.cwd();
|
|
615
634
|
const coreDir = findCoreDir(targetDir);
|
|
616
635
|
const version = getXdsVersion(coreDir);
|
|
@@ -16,7 +16,7 @@ import * as fs from 'node:fs';
|
|
|
16
16
|
import * as path from 'node:path';
|
|
17
17
|
import * as os from 'node:os';
|
|
18
18
|
import {installAgentDocs} from './agent-docs.mjs';
|
|
19
|
-
import {PathSafetyError} from '
|
|
19
|
+
import {PathSafetyError} from '../../utils/path-safety.mjs';
|
|
20
20
|
|
|
21
21
|
let tmpDir;
|
|
22
22
|
beforeEach(() => {
|