@astryxdesign/cli 0.6.4 → 0.6.5-canary.00f1ed9
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 +56 -0
- package/README.md +103 -95
- package/api/build/_adapter.d.mts +36 -2
- package/api/build/_adapter.mjs +41 -10
- package/api/build/build.doc.mjs +8 -3
- package/api/build/build.test.mjs +60 -2
- package/api/build/kit/kit.mjs +109 -26
- package/api/build/kit/rank.d.mts +24 -8
- package/api/build/kit/rank.mjs +277 -97
- package/api/build/kit/rank.test.mjs +231 -48
- package/api/component/_adapter.d.mts +25 -0
- package/api/component/_adapter.mjs +59 -5
- package/api/component/component.d.mts +6 -3
- package/api/component/component.doc.mjs +37 -17
- package/api/component/component.mjs +249 -9
- package/api/component/component.type.d.mts +25 -0
- package/api/component/component.type.mjs +44 -0
- package/api/discover/_adapter.d.mts +114 -6
- package/api/discover/_adapter.mjs +372 -17
- package/api/discover/_adapter.test.mjs +215 -0
- package/api/discover/_catalog-view.d.mts +115 -0
- package/api/discover/_catalog-view.mjs +203 -0
- package/api/discover/_catalog-view.test.mjs +128 -0
- package/api/discover/detail/detail.d.mts +18 -6
- package/api/discover/detail/detail.mjs +67 -13
- package/api/discover/detail/detail.test.mjs +85 -0
- package/api/discover/detail/item/item.d.mts +26 -0
- package/api/discover/detail/item/item.mjs +78 -0
- package/api/discover/detail/item/item.test.mjs +73 -0
- package/api/discover/discover.d.mts +3 -9
- package/api/discover/discover.doc.mjs +61 -18
- package/api/discover/discover.mjs +220 -36
- package/api/discover/discover.test.mjs +11 -2
- package/api/discover/discover.type.d.mts +147 -8
- package/api/discover/discover.type.mjs +102 -12
- package/api/discover/list/list.d.mts +20 -6
- package/api/discover/list/list.mjs +45 -12
- package/api/discover/list/list.test.mjs +46 -0
- package/api/discover/search/search.d.mts +18 -16
- package/api/discover/search/search.mjs +102 -56
- package/api/discover/search/search.test.mjs +144 -10
- package/api/docs/_adapter.d.mts +8 -3
- package/api/docs/_adapter.mjs +14 -6
- package/api/docs/docOverlays.test.mjs +27 -1
- package/api/docs/docs.doc.mjs +2 -2
- package/api/docs/docs.test.mjs +54 -18
- package/api/docs/integration-tree.test.mjs +17 -0
- package/api/docs/integrationDocs.test.mjs +27 -5
- package/api/doctor/doctor.d.mts +8 -3
- package/api/doctor/doctor.doc.mjs +17 -8
- package/api/doctor/doctor.mjs +90 -9
- package/api/doctor/doctor.test.mjs +122 -10
- package/api/doctor/doctor.type.d.mts +1 -1
- package/api/doctor/doctor.type.mjs +1 -1
- package/api/error.d.mts +22 -0
- package/api/error.mjs +42 -0
- package/api/gap-report/gap-report.doc.mjs +19 -10
- package/api/hook/hook.doc.mjs +6 -3
- package/api/index.d.mts +1 -0
- package/api/index.mjs +5 -3
- package/api/init/init.doc.mjs +17 -12
- package/api/integration/add-contribution.d.mts +2 -1
- package/api/integration/add-contribution.mjs +7 -3
- package/api/integration/add-contribution.test.mjs +3 -3
- package/api/integration/add-helpers.d.mts +5 -2
- package/api/integration/add-helpers.mjs +36 -9
- package/api/integration/add-theme.mjs +266 -23
- package/api/integration/add-theme.test.mjs +247 -0
- package/api/integration/authoring-checks.mjs +12 -9
- package/api/integration/authoring-checks.type.d.mts +8 -0
- package/api/integration/authoring-checks.type.mjs +7 -3
- package/api/integration/integration-authoring.type.d.mts +4 -1
- package/api/integration/integration-authoring.type.mjs +6 -1
- package/api/integration/integrationAdd.doc.mjs +6 -0
- package/api/integration/integrationAddTheme.doc.mjs +10 -0
- package/api/integration/integrationComponentConflicts.doc.mjs +1 -1
- package/api/integration/integrationDocConflicts.doc.mjs +1 -1
- package/api/integration/integrationPackCheck.doc.mjs +3 -3
- package/api/integration/integrationTemplateConflicts.doc.mjs +1 -1
- package/api/integration/pack-check.lifecycle-output.test.mjs +107 -0
- package/api/integration/pack-check.mjs +92 -10
- package/api/integration/pack-check.test.mjs +140 -1
- package/api/integration/pack-check.type.mjs +1 -1
- package/api/integration/validate-integration.d.mts +4 -2
- package/api/integration/validate-integration.mjs +7 -2
- package/api/integration/validate-integration.test.mjs +55 -0
- package/api/integration/validate-integration.type.d.mts +5 -0
- package/api/integration/validate-integration.type.mjs +5 -1
- package/api/integration/validateIntegration.doc.mjs +1 -1
- package/api/json/assertResponse.doc.mjs +1 -1
- package/api/json/isError.doc.mjs +1 -1
- package/api/layout/expand/expand.mjs +12 -7
- package/api/layout/expand/expand.receipt.test.mjs +74 -0
- package/api/layout/layout.type.d.mts +1 -0
- package/api/layout/layout.type.mjs +1 -0
- package/api/layout/layoutExpand.doc.mjs +1 -1
- package/api/search/search.d.mts +51 -1
- package/api/search/search.doc.mjs +2 -2
- package/api/search/search.mjs +299 -17
- package/api/search/search.test.mjs +216 -18
- package/api/swizzle/copy/copy.mjs +66 -3
- package/api/swizzle/swizzle.doc.mjs +11 -5
- package/api/template/copy/copy.mjs +15 -9
- package/api/template/copy/copy.receipt.test.mjs +77 -0
- package/api/template/copy/copy.test.mjs +9 -0
- package/api/template/show/show.mjs +15 -4
- package/api/template/show/show.test.mjs +76 -0
- package/api/template/template-integration.test.mjs +14 -0
- package/api/template/template.d.mts +1 -1
- package/api/template/template.doc.mjs +8 -3
- package/api/template/template.mjs +1 -0
- package/api/template/template.type.d.mts +2 -0
- package/api/template/template.type.mjs +2 -0
- package/api/theme/add/add.mjs +17 -25
- package/api/theme/add/add.rollback.test.mjs +158 -0
- package/api/theme/add/add.staging.test.mjs +40 -23
- package/api/theme/build/build.d.mts +24 -0
- package/api/theme/build/build.family.test.mjs +7 -12
- package/api/theme/build/build.mjs +243 -26
- package/api/theme/build/build.project-core.test.mjs +165 -0
- package/api/theme/build/build.rollback.test.mjs +148 -0
- package/api/theme/generateTonalPalette.doc.mjs +1 -2
- package/api/theme/listThemes.doc.mjs +1 -1
- package/api/theme/themeAdd.doc.mjs +9 -10
- package/api/theme/themeBuild.doc.mjs +13 -13
- package/api/theme/themeList.doc.mjs +1 -1
- package/api/theme/themeListAvailable.doc.mjs +2 -1
- package/api/theme/themePaletteGenerate.doc.mjs +15 -8
- package/api/theme/themeTargets.doc.mjs +3 -2
- package/api/theme/themeTemplate.doc.mjs +2 -1
- package/api/upgrade/run/files-changed.test.mjs +111 -0
- package/api/upgrade/run/run.mjs +25 -6
- package/api/upgrade/run/run.test.mjs +45 -1
- package/api/upgrade/upgrade.doc.mjs +24 -22
- package/api/upgrade/upgrade.type.d.mts +1 -0
- package/api/upgrade/upgrade.type.mjs +3 -2
- package/assets/codemods/__tests__/runner.test.mjs +3 -1
- package/assets/codemods/file-count.test.mjs +163 -0
- package/assets/codemods/integration-runner.mjs +3 -3
- package/assets/codemods/runner.mjs +5 -4
- package/assets/docs/README.md +4 -2
- package/assets/docs/browser-support.doc.mjs +11 -11
- package/assets/docs/color.doc.mjs +8 -2
- package/assets/docs/elevation.doc.mjs +6 -4
- package/assets/docs/getting-started.doc.mjs +5 -16
- package/assets/docs/icons.doc.mjs +3 -21
- package/assets/docs/illustrations.doc.mjs +7 -15
- package/assets/docs/internationalization.doc.mjs +7 -5
- package/assets/docs/layout.doc.dense.mjs +130 -82
- package/assets/docs/layout.doc.mjs +133 -77
- package/assets/docs/migration.doc.mjs +19 -21
- package/assets/docs/motion.doc.mjs +16 -3
- package/assets/docs/principles.doc.dense.mjs +5 -5
- package/assets/docs/principles.doc.mjs +8 -0
- package/assets/docs/principles.doc.zh.mjs +6 -6
- package/assets/docs/shape.doc.mjs +8 -3
- package/assets/docs/spacing.doc.mjs +7 -2
- package/assets/docs/styling-libraries.doc.mjs +6 -2
- package/assets/docs/styling.doc.mjs +19 -23
- package/assets/docs/theme.doc.dense.mjs +58 -18
- package/assets/docs/theme.doc.mjs +57 -47
- package/assets/docs/theme.doc.zh.mjs +9 -8
- package/assets/docs/tokens.doc.dense.mjs +2 -2
- package/assets/docs/tokens.doc.mjs +389 -8
- package/assets/docs/tokens.doc.zh.mjs +2 -2
- package/assets/docs/tree/add-a-component.doc.mjs +75 -0
- package/assets/docs/tree/add-a-theme.doc.mjs +85 -0
- package/assets/docs/tree/add-a-topic.doc.mjs +144 -0
- package/assets/docs/tree/agent-guidance.doc.mjs +138 -0
- package/assets/docs/tree/block-template.doc.mjs +130 -0
- package/assets/docs/tree/build-the-template.doc.mjs +28 -0
- package/assets/docs/tree/building-blocks.doc.mjs +46 -0
- package/assets/docs/tree/check-your-docs.doc.mjs +137 -0
- package/assets/docs/tree/checks.doc.mjs +119 -0
- package/assets/docs/tree/codemods.doc.mjs +147 -0
- package/assets/docs/tree/component-family.doc.mjs +113 -0
- package/assets/docs/tree/component-imports.doc.mjs +69 -0
- package/assets/docs/tree/component-lookups.doc.mjs +149 -0
- package/assets/docs/tree/components.doc.mjs +23 -0
- package/assets/docs/tree/configuration.doc.mjs +23 -0
- package/assets/docs/tree/debug-and-gap-reports.doc.mjs +182 -0
- package/assets/docs/tree/define-the-theme.doc.mjs +118 -0
- package/assets/docs/tree/describe-the-component.doc.mjs +57 -0
- package/assets/docs/tree/docs.doc.mjs +21 -0
- package/assets/docs/tree/document-the-template.doc.mjs +28 -0
- package/assets/docs/tree/document-the-theme.doc.mjs +68 -0
- package/assets/docs/tree/export-template-assets.doc.mjs +147 -0
- package/assets/docs/tree/extend-or-replace.doc.mjs +103 -0
- package/assets/docs/tree/fonts-and-assets.doc.mjs +106 -0
- package/assets/docs/tree/generate-a-palette.doc.mjs +66 -0
- package/assets/docs/tree/grade-template-with-agent.doc.mjs +105 -0
- package/assets/docs/tree/help.doc.mjs +16 -0
- package/assets/docs/tree/integrations.doc.mjs +25 -451
- package/assets/docs/tree/links.doc.mjs +98 -0
- package/assets/docs/tree/package-and-test.doc.mjs +32 -0
- package/assets/docs/tree/page-template.doc.mjs +71 -0
- package/assets/docs/tree/publishing.doc.mjs +111 -0
- package/assets/docs/tree/quick-start.doc.mjs +272 -0
- package/assets/docs/tree/replace-a-core-component.doc.mjs +104 -0
- package/assets/docs/tree/replace-a-core-template.doc.mjs +172 -0
- package/assets/docs/tree/sections-and-placement.doc.mjs +108 -0
- package/assets/docs/tree/see-it-in-an-app.doc.mjs +59 -0
- package/assets/docs/tree/ship.doc.mjs +16 -0
- package/assets/docs/tree/short-and-findable.doc.mjs +108 -0
- package/assets/docs/tree/single-component.doc.mjs +165 -0
- package/assets/docs/tree/start-a-template.doc.mjs +143 -0
- package/assets/docs/tree/subcomponent.doc.mjs +115 -0
- package/assets/docs/tree/template-assets.doc.mjs +64 -0
- package/assets/docs/tree/template-doc-overview.doc.mjs +121 -0
- package/assets/docs/tree/template-fonts.doc.mjs +102 -0
- package/assets/docs/tree/template-grading-rubric.doc.mjs +452 -0
- package/assets/docs/tree/template-icons.doc.mjs +97 -0
- package/assets/docs/tree/template-images-media.doc.mjs +127 -0
- package/assets/docs/tree/template-styles.doc.mjs +93 -0
- package/assets/docs/tree/templates.doc.mjs +34 -0
- package/assets/docs/tree/test-in-an-app.doc.mjs +115 -0
- package/assets/docs/tree/test-template-in-app.doc.mjs +128 -0
- package/assets/docs/tree/themes.doc.mjs +39 -0
- package/assets/docs/tree/troubleshooting.doc.mjs +153 -0
- package/assets/docs/tree/upgrading.doc.mjs +103 -0
- package/assets/docs/tree/use-a-theme-in-an-app.doc.mjs +51 -0
- package/assets/docs/tree/verify-packed-template.doc.mjs +77 -0
- package/assets/docs/tree/versioning.doc.mjs +162 -0
- package/assets/docs/tree/write-good-templates.doc.mjs +64 -0
- package/assets/docs/tree/write-the-template-file.doc.mjs +154 -0
- package/assets/docs/typography.doc.mjs +24 -4
- package/assets/docs/working-with-ai.doc.mjs +30 -22
- package/assets/templates/blocks/components/InternationalizationProvider/InternationalizationProvider01ShippedLocale.tsx +1 -1
- package/assets/templates/pages/ai-chat/template.doc.mjs +16 -1
- package/assets/templates/pages/ai-chat-landing/template.doc.mjs +9 -1
- package/assets/templates/pages/blank/template.doc.mjs +3 -1
- package/assets/templates/pages/canvas-editor/template.doc.mjs +9 -1
- package/assets/templates/pages/centered-hero/template.doc.mjs +3 -1
- package/assets/templates/pages/checkout-wizard/template.doc.mjs +1 -0
- package/assets/templates/pages/classic-gallery/template.doc.mjs +3 -1
- package/assets/templates/pages/contact-form/template.doc.mjs +16 -1
- package/assets/templates/pages/dashboard/template.doc.mjs +15 -1
- package/assets/templates/pages/dashboard-alert-rail/template.doc.mjs +23 -1
- package/assets/templates/pages/dashboard-cohort-funnel/template.doc.mjs +10 -1
- package/assets/templates/pages/dashboard-comparison/template.doc.mjs +9 -1
- package/assets/templates/pages/dashboard-composition/template.doc.mjs +10 -1
- package/assets/templates/pages/dashboard-progress/template.doc.mjs +17 -1
- package/assets/templates/pages/dashboard-scorecard/template.doc.mjs +2 -1
- package/assets/templates/pages/detail-page/template.doc.mjs +8 -0
- package/assets/templates/pages/documentation/template.doc.mjs +10 -1
- package/assets/templates/pages/documentation-design/template.doc.mjs +10 -1
- package/assets/templates/pages/documentation-technical/template.doc.mjs +10 -1
- package/assets/templates/pages/editor/template.doc.mjs +9 -1
- package/assets/templates/pages/file-explorer/template.doc.mjs +3 -1
- package/assets/templates/pages/form-two-column/template.doc.mjs +17 -1
- package/assets/templates/pages/form-wizard/template.doc.mjs +14 -1
- package/assets/templates/pages/form-wizard-dialog/template.doc.mjs +1 -0
- package/assets/templates/pages/gallery-hero/template.doc.mjs +10 -1
- package/assets/templates/pages/ide/template.doc.mjs +9 -1
- package/assets/templates/pages/incident-console/template.doc.mjs +10 -1
- package/assets/templates/pages/kanban-board/template.doc.mjs +11 -1
- package/assets/templates/pages/library/template.doc.mjs +15 -1
- package/assets/templates/pages/login/template.doc.mjs +10 -1
- package/assets/templates/pages/login-card/template.doc.mjs +11 -1
- package/assets/templates/pages/login-split/template.doc.mjs +10 -1
- package/assets/templates/pages/login-sso/template.doc.mjs +10 -1
- package/assets/templates/pages/messaging-shell/template.doc.mjs +11 -1
- package/assets/templates/pages/mixed-gallery/template.doc.mjs +10 -1
- package/assets/templates/pages/payment-form/template.doc.mjs +3 -1
- package/assets/templates/pages/product-detail/template.doc.mjs +9 -1
- package/assets/templates/pages/product-gallery/template.doc.mjs +10 -1
- package/assets/templates/pages/settings/template.doc.mjs +3 -1
- package/assets/templates/pages/settings-dialog/template.doc.mjs +9 -1
- package/assets/templates/pages/settings-sidebar/template.doc.mjs +9 -1
- package/assets/templates/pages/shell-nav/template.doc.mjs +10 -1
- package/assets/templates/pages/shell-side-nav/template.doc.mjs +14 -1
- package/assets/templates/pages/shell-top-nav/template.doc.mjs +11 -1
- package/assets/templates/pages/side-gallery/template.doc.mjs +3 -1
- package/assets/templates/pages/table/template.doc.mjs +11 -1
- package/assets/templates/pages/table-filter/template.doc.mjs +21 -1
- package/assets/templates/pages/table-grouped/template.doc.mjs +15 -1
- package/assets/templates/pages/table-inbox/template.doc.mjs +18 -6
- package/assets/templates/pages/table-page/template.doc.mjs +20 -1
- package/assets/templates/pages/table-tree/template.doc.mjs +14 -1
- package/assets/templates/pages/theme-showcase/template.doc.mjs +10 -1
- package/assets/templates/pages/work-item-detail/template.doc.mjs +10 -0
- package/assets/templates/themes/butter/icons.tsx +2 -0
- package/assets/templates/themes/chocolate/icons.tsx +2 -0
- package/assets/templates/themes/gothic/icons.tsx +2 -0
- package/assets/templates/themes/matcha/icons.tsx +2 -0
- package/assets/templates/themes/neutral/icons.tsx +2 -0
- package/assets/templates/themes/stone/icons.tsx +2 -0
- package/assets/templates/themes/y2k/icons.tsx +2 -0
- package/authoring/config/config.doc.mjs +9 -1
- package/authoring/config/parse.d.mts +2 -0
- package/authoring/config/parse.mjs +19 -0
- package/authoring/config/parse.test.mjs +8 -0
- package/authoring/config/type.ts +11 -0
- package/authoring/discover/discover.doc.d.mts +13 -0
- package/authoring/discover/discover.doc.mjs +138 -0
- package/authoring/discover/parse.d.mts +24 -0
- package/authoring/discover/parse.mjs +128 -0
- package/authoring/discover/parse.test.mjs +124 -0
- package/authoring/discover/type.ts +87 -0
- package/authoring/doctypes/_schema.d.mts +3 -2
- package/authoring/doctypes/_schema.mjs +6 -0
- package/authoring/doctypes/base/graph-fields.doc.mjs +3 -3
- package/authoring/doctypes/base/type.ts +4 -2
- package/authoring/doctypes/component/component.doc.mjs +6 -0
- package/authoring/doctypes/component/type.ts +8 -0
- package/authoring/doctypes/reference/reference.doc.mjs +7 -0
- package/authoring/doctypes/reference/type.ts +5 -0
- package/authoring/doctypes/schema/schema.doc.mjs +2 -2
- package/authoring/doctypes/template/parse.d.mts +2 -0
- package/authoring/doctypes/template/parse.mjs +1 -0
- package/authoring/doctypes/template/parse.test.mjs +21 -0
- package/authoring/doctypes/template/template.doc.mjs +7 -1
- package/authoring/doctypes/template/type.ts +12 -2
- package/authoring/index.d.mts +1 -0
- package/authoring/index.d.ts +10 -0
- package/authoring/index.mjs +1 -0
- package/authoring/integration/integration.doc.mjs +12 -10
- package/clients/cli/commands/component/index.mjs +152 -55
- package/clients/cli/commands/component-batch.test.mjs +341 -0
- package/clients/cli/commands/component-ownership.test.mjs +89 -0
- package/clients/cli/commands/component.doc.mjs +27 -9
- package/clients/cli/commands/discover.doc.mjs +53 -9
- package/clients/cli/commands/discover.mjs +393 -118
- package/clients/cli/commands/discover.sources.test.mjs +267 -0
- package/clients/cli/commands/docs.doc.mjs +1 -1
- package/clients/cli/commands/docs.mjs +60 -17
- package/clients/cli/commands/docs.test.mjs +113 -24
- package/clients/cli/commands/doctor-integration-docs.doc.mjs +3 -2
- package/clients/cli/commands/doctor-integration.test.mjs +53 -0
- package/clients/cli/commands/doctor.doc.mjs +3 -1
- package/clients/cli/commands/doctor.mjs +53 -9
- package/clients/cli/commands/gap-report.doc.mjs +10 -9
- package/clients/cli/commands/init.doc.mjs +9 -6
- package/clients/cli/commands/integration-add.doc.mjs +17 -7
- package/clients/cli/commands/integration-authoring.test.mjs +70 -9
- package/clients/cli/commands/integration-pack.doc.mjs +5 -9
- package/clients/cli/commands/integration-real-world.test.mjs +1 -1
- package/clients/cli/commands/integration-verify.doc.mjs +22 -0
- package/clients/cli/commands/integration.doc.mjs +4 -4
- package/clients/cli/commands/integration.mjs +76 -43
- package/clients/cli/commands/layout-expand.doc.mjs +3 -1
- package/clients/cli/commands/layout.expand-receipt.test.mjs +94 -0
- package/clients/cli/commands/layout.mjs +16 -0
- package/clients/cli/commands/manifest.doc.mjs +1 -1
- package/clients/cli/commands/search.doc.mjs +10 -3
- package/clients/cli/commands/search.mjs +21 -2
- package/clients/cli/commands/search.test.mjs +21 -4
- package/clients/cli/commands/swizzle.doc.mjs +1 -1
- package/clients/cli/commands/template.copy-receipt.test.mjs +60 -0
- package/clients/cli/commands/template.doc.mjs +1 -1
- package/clients/cli/commands/template.mjs +19 -5
- package/clients/cli/commands/template.show-media.test.mjs +62 -0
- package/clients/cli/commands/text-json-parity.test.mjs +7 -1
- package/clients/cli/commands/theme-add.doc.mjs +1 -1
- package/clients/cli/commands/theme-palette-generate.doc.mjs +3 -2
- package/clients/cli/commands/theme-palette.doc.mjs +1 -2
- package/clients/cli/commands/theme-targets.doc.mjs +2 -2
- package/clients/cli/commands/theme.doc.mjs +2 -1
- package/clients/cli/commands/upgrade.ascii-output.test.mjs +14 -0
- package/clients/cli/commands/upgrade.doc.mjs +62 -3
- package/clients/cli/commands/write-failure.test.mjs +175 -0
- package/clients/cli/index.mjs +28 -6
- package/clients/cli/lib/define-command.mjs +28 -4
- package/clients/cli/lib/define-command.test.mjs +54 -0
- package/clients/cli/lib/exit-codes.test.mjs +17 -1
- package/clients/cli/lib/json-shim.mjs +24 -14
- package/clients/cli/lib/manifest.mjs +48 -156
- package/clients/cli/lib/manifest.test.mjs +103 -9
- package/clients/cli/lib/parse-error-format.test.mjs +81 -0
- package/foundation/agent-docs/agent-docs.mjs +1 -1
- package/foundation/agent-docs/agent-docs.test.mjs +3 -2
- package/foundation/discovery/authoring-self-docs.mjs +1 -0
- package/foundation/discovery/authoring-self-docs.test.mjs +6 -2
- package/foundation/discovery/cli-self-docs.mjs +16 -2
- package/foundation/discovery/cli-self-docs.test.mjs +20 -0
- package/foundation/discovery/docs-discovery.mjs +5 -1
- package/foundation/discovery/docs-discovery.test.mjs +21 -0
- package/foundation/discovery/docs-section-key.d.mts +1 -1
- package/foundation/discovery/docs-section-key.mjs +1 -1
- package/foundation/discovery/template-adapter.d.mts +14 -0
- package/foundation/discovery/template-adapter.fixture-refs.test.mjs +37 -1
- package/foundation/discovery/template-adapter.mjs +21 -1
- package/foundation/doc-compiler/doc-loads.test.mjs +5 -4
- package/foundation/doc-compiler/inputs.test.mjs +0 -1
- package/foundation/doc-compiler/tree.d.mts +4 -0
- package/foundation/doc-compiler/tree.mjs +6 -1
- package/foundation/doc-compiler/tree.test.mjs +65 -14
- package/foundation/integrations/cli-requirement.d.mts +75 -11
- package/foundation/integrations/cli-requirement.mjs +120 -23
- package/foundation/integrations/cli-requirement.test.mjs +141 -9
- package/foundation/integrations/contribution-inventory.mjs +1 -1
- package/foundation/integrations/integrations.d.mts +14 -1
- package/foundation/integrations/integrations.mjs +41 -1
- package/foundation/integrations/integrations.test.mjs +31 -0
- package/foundation/response/batch.type.d.mts +33 -0
- package/foundation/response/batch.type.mjs +34 -0
- package/foundation/response/error-codes.doc.mjs +6 -8
- package/foundation/response/error-codes.test.mjs +30 -5
- package/foundation/response/response-types.doc.d.mts +5 -4
- package/foundation/response/response-types.doc.mjs +49 -19
- package/foundation/response/response-types.doc.test.mjs +23 -0
- package/foundation/response/response.doc.mjs +11 -10
- package/package.json +9 -9
- package/assets/docs/tree/integrations.test.mjs +0 -62
- package/assets/docs/tree/writing-docs.doc.mjs +0 -286
|
@@ -44,6 +44,7 @@ export const doc = {
|
|
|
44
44
|
type: 'string',
|
|
45
45
|
description:
|
|
46
46
|
'Project directory used for integration discovery and target paths.',
|
|
47
|
+
default: 'process.cwd()',
|
|
47
48
|
},
|
|
48
49
|
{
|
|
49
50
|
name: 'options.package',
|
|
@@ -57,11 +58,6 @@ export const doc = {
|
|
|
57
58
|
description:
|
|
58
59
|
'Copy receipt with slug, displayName, maintained flag, owner package, outputDir, entry, exportName, and files.',
|
|
59
60
|
},
|
|
60
|
-
{
|
|
61
|
-
type: 'theme.list',
|
|
62
|
-
description:
|
|
63
|
-
'The CLI list affordance routes a bare `astryx theme add` or `--list` to themeListAvailable() and returns every available theme with its owner.',
|
|
64
|
-
},
|
|
65
61
|
],
|
|
66
62
|
throws: [
|
|
67
63
|
{
|
|
@@ -74,7 +70,10 @@ export const doc = {
|
|
|
74
70
|
when: 'the selected installed package has a blocking integration or theme-descriptor error',
|
|
75
71
|
},
|
|
76
72
|
{code: 'ERR_PATH_TRAVERSAL', when: 'the target path escapes cwd'},
|
|
77
|
-
{
|
|
73
|
+
{
|
|
74
|
+
code: 'ERR_NO_SOURCE',
|
|
75
|
+
when: 'the bundled theme descriptors cannot be read, or a theme file to copy is missing',
|
|
76
|
+
},
|
|
78
77
|
{
|
|
79
78
|
code: 'ERR_FILE_EXISTS',
|
|
80
79
|
when: 'a destination exists and overwrite is not set',
|
|
@@ -82,12 +81,12 @@ export const doc = {
|
|
|
82
81
|
{code: 'ERR_WRITE_FAILED', when: 'writing files fails'},
|
|
83
82
|
],
|
|
84
83
|
examples: [
|
|
85
|
-
{label: 'Copy a bundled theme', code: "await themeAdd('
|
|
84
|
+
{label: 'Copy a bundled theme', code: "await themeAdd('butter');"},
|
|
86
85
|
{
|
|
87
|
-
label: '
|
|
88
|
-
code: "await themeAdd('
|
|
86
|
+
label: 'Name the owner package and the destination',
|
|
87
|
+
code: "await themeAdd('butter', {package: '@astryxdesign/cli', targetPath: 'src/brand-theme'});",
|
|
89
88
|
},
|
|
90
89
|
],
|
|
91
90
|
command: 'theme add',
|
|
92
|
-
related: ['
|
|
91
|
+
related: ['themeListAvailable', 'themeTemplate', 'listThemes'],
|
|
93
92
|
};
|
|
@@ -14,14 +14,13 @@ export const doc = {
|
|
|
14
14
|
name: 'themeBuild',
|
|
15
15
|
namespace: 'cli/api',
|
|
16
16
|
displayName: 'themeBuild()',
|
|
17
|
-
summary:
|
|
17
|
+
summary:
|
|
18
|
+
'Compile a defineTheme() file to scoped CSS, a JS module, and type declarations, or check committed outputs for drift in CI.',
|
|
18
19
|
description:
|
|
19
|
-
'The compiler behind `astryx theme build`. Reads a file that calls defineTheme() and
|
|
20
|
-
|
|
21
|
-
'
|
|
22
|
-
'
|
|
23
|
-
'theme adds custom prop values). When another build step emits the icon registry, ' +
|
|
24
|
-
'{iconsSpecifier} declares the fully specified module path for the generated JS import. ' +
|
|
20
|
+
'The compiler behind `astryx theme build`. Reads a file that calls defineTheme() and ' +
|
|
21
|
+
'writes a scoped CSS file, a JS module that re-exports the built theme, and a .d.ts ' +
|
|
22
|
+
'(plus an optional .variants.d.ts when the theme adds custom prop values). It uses ' +
|
|
23
|
+
"@astryxdesign/core's own generator, so the CSS matches what the <Theme> runtime emits. " +
|
|
25
24
|
'With {check: true} it writes nothing and instead compares ' +
|
|
26
25
|
'each output against disk, returning the drift: the CI guard for committed, generated theme CSS.',
|
|
27
26
|
importPath: '@astryxdesign/cli/api',
|
|
@@ -48,7 +47,7 @@ export const doc = {
|
|
|
48
47
|
name: 'options.out',
|
|
49
48
|
type: 'string',
|
|
50
49
|
description:
|
|
51
|
-
'Override the output CSS path
|
|
50
|
+
'Override the output CSS path. The .js, .d.ts and any .variants.d.ts are written in the same directory, named after the theme (<name>.js), not after the CSS file. A relative path must stay within cwd.',
|
|
52
51
|
},
|
|
53
52
|
{
|
|
54
53
|
name: 'options.check',
|
|
@@ -61,13 +60,14 @@ export const doc = {
|
|
|
61
60
|
name: 'options.iconsSpecifier',
|
|
62
61
|
type: 'string',
|
|
63
62
|
description:
|
|
64
|
-
'Override the
|
|
63
|
+
'Override the import specifier of the icon registry in the generated JS module, for example ./icons.mjs. Takes effect only when the theme sets icons: to a named import; when omitted, the source specifier is kept.',
|
|
65
64
|
},
|
|
66
65
|
{
|
|
67
66
|
name: 'ctx.cwd',
|
|
68
67
|
type: 'string',
|
|
69
68
|
description:
|
|
70
|
-
'Directory the theme file and
|
|
69
|
+
'Directory the theme file, a relative out path, and the returned output paths resolve against.',
|
|
70
|
+
default: 'process.cwd()',
|
|
71
71
|
},
|
|
72
72
|
],
|
|
73
73
|
returns: [
|
|
@@ -79,7 +79,7 @@ export const doc = {
|
|
|
79
79
|
{
|
|
80
80
|
type: 'theme.build.check',
|
|
81
81
|
description:
|
|
82
|
-
'The {check: true} receipt: theme name, an upToDate flag, the stale outputs (each {path, reason: "missing" | "outdated"}), and the full list of checked paths. Writes nothing.',
|
|
82
|
+
'The {check: true} receipt: theme name, an upToDate flag, the stale outputs (each {path, reason: "missing" | "outdated"}), and the full list of checked paths. Writes nothing. Resolves to null, like a normal build, when the theme produces no CSS.',
|
|
83
83
|
},
|
|
84
84
|
],
|
|
85
85
|
throws: [
|
|
@@ -102,7 +102,7 @@ export const doc = {
|
|
|
102
102
|
},
|
|
103
103
|
{
|
|
104
104
|
code: 'ERR_CORE_INCOMPATIBLE',
|
|
105
|
-
when: 'the
|
|
105
|
+
when: 'the installed @astryxdesign/core does not export generateAdaptationCSS and the theme either declares ordered adaptations or has lineage whose adaptation use could not be observed (upgrade core)',
|
|
106
106
|
},
|
|
107
107
|
{
|
|
108
108
|
code: 'ERR_WRITE_FAILED',
|
|
@@ -124,5 +124,5 @@ export const doc = {
|
|
|
124
124
|
},
|
|
125
125
|
],
|
|
126
126
|
command: 'theme build',
|
|
127
|
-
related: ['themeAdd', '
|
|
127
|
+
related: ['themeTemplate', 'themeAdd', 'themeListAvailable', 'listThemes'],
|
|
128
128
|
};
|
|
@@ -13,7 +13,7 @@ export const doc = {
|
|
|
13
13
|
displayName: 'themeList()',
|
|
14
14
|
summary: 'List themes bundled with this CLI build.',
|
|
15
15
|
description:
|
|
16
|
-
'
|
|
16
|
+
'Synchronous list of the themes bundled with the CLI. It does not include themes from installed integrations; use themeListAvailable() for the list `astryx theme list` shows.',
|
|
17
17
|
importPath: '@astryxdesign/cli/api',
|
|
18
18
|
signature: 'themeList(): ThemeListResponse',
|
|
19
19
|
keywords: ['theme', 'list', 'themes', 'bundled', 'available'],
|
|
@@ -13,7 +13,7 @@ export const doc = {
|
|
|
13
13
|
displayName: 'themeListAvailable()',
|
|
14
14
|
summary: 'List bundled and installed integration themes.',
|
|
15
15
|
description:
|
|
16
|
-
'
|
|
16
|
+
'Lists the bundled themes plus source themes from integrations installed in cwd, each with its owner package. If the project configuration cannot be read, it falls back to the bundled themes.',
|
|
17
17
|
importPath: '@astryxdesign/cli/api',
|
|
18
18
|
signature:
|
|
19
19
|
'themeListAvailable(options?: {cwd?: string, package?: string}): Promise<ThemeListResponse>',
|
|
@@ -24,6 +24,7 @@ export const doc = {
|
|
|
24
24
|
type: 'string',
|
|
25
25
|
description:
|
|
26
26
|
'Project directory whose installed integrations contribute themes.',
|
|
27
|
+
default: 'process.cwd()',
|
|
27
28
|
},
|
|
28
29
|
{
|
|
29
30
|
name: 'options.package',
|
|
@@ -27,30 +27,34 @@ export const doc = {
|
|
|
27
27
|
{
|
|
28
28
|
name: 'configPath',
|
|
29
29
|
type: 'string',
|
|
30
|
-
description:
|
|
30
|
+
description:
|
|
31
|
+
'Path to a JSON file holding a TonalPaletteGenerationInput (the object generateTonalPalette() takes), resolved within cwd.',
|
|
31
32
|
required: true,
|
|
32
33
|
},
|
|
33
34
|
{
|
|
34
35
|
name: 'options.out',
|
|
35
36
|
type: 'string',
|
|
36
37
|
description:
|
|
37
|
-
'
|
|
38
|
+
'Where to write the candidate: a path ending in .ts (a TypeScript module) or .json. A sibling <name>.receipt.json is written next to it.',
|
|
38
39
|
},
|
|
39
40
|
{
|
|
40
41
|
name: 'options.preview',
|
|
41
42
|
type: 'string',
|
|
42
|
-
description:
|
|
43
|
+
description:
|
|
44
|
+
'Optional path, ending in .html, for a self-contained HTML review page.',
|
|
43
45
|
},
|
|
44
46
|
{
|
|
45
47
|
name: 'options.overwrite',
|
|
46
48
|
type: 'boolean',
|
|
47
|
-
description:
|
|
49
|
+
description:
|
|
50
|
+
"Replace existing candidate, receipt and preview files. Without it, if any target exists, nothing is written and the result has written: false, reason: 'exists'.",
|
|
48
51
|
default: 'false',
|
|
49
52
|
},
|
|
50
53
|
{
|
|
51
54
|
name: 'ctx.cwd',
|
|
52
55
|
type: 'string',
|
|
53
56
|
description: 'Directory used to resolve the input and output paths.',
|
|
57
|
+
default: 'process.cwd()',
|
|
54
58
|
},
|
|
55
59
|
],
|
|
56
60
|
returns: [
|
|
@@ -64,17 +68,20 @@ export const doc = {
|
|
|
64
68
|
{code: 'ERR_FILE_NOT_FOUND', when: 'the config file does not exist'},
|
|
65
69
|
{
|
|
66
70
|
code: 'ERR_PALETTE_GENERATION',
|
|
67
|
-
when: 'the request, seed, stop layout, mode
|
|
71
|
+
when: 'the config is not valid JSON; the request, seed, stop layout, mode or anchor is invalid; out does not end in .ts or .json; or preview does not end in .html',
|
|
68
72
|
},
|
|
69
73
|
{
|
|
70
74
|
code: 'ERR_PATH_TRAVERSAL',
|
|
71
75
|
when: 'an input or output path escapes cwd, or output would replace input',
|
|
72
76
|
},
|
|
73
|
-
{
|
|
77
|
+
{
|
|
78
|
+
code: 'ERR_WRITE_FAILED',
|
|
79
|
+
when: 'the candidate, receipt or preview file cannot be written',
|
|
80
|
+
},
|
|
74
81
|
],
|
|
75
82
|
examples: [
|
|
76
83
|
{
|
|
77
|
-
label: '
|
|
84
|
+
label: 'Generate a candidate without writing files',
|
|
78
85
|
code: "themePaletteGenerate('palette.config.json');",
|
|
79
86
|
},
|
|
80
87
|
{
|
|
@@ -83,5 +90,5 @@ export const doc = {
|
|
|
83
90
|
},
|
|
84
91
|
],
|
|
85
92
|
command: 'theme palette generate',
|
|
86
|
-
related: ['themeBuild', 'themeTemplate'],
|
|
93
|
+
related: ['generateTonalPalette', 'themeBuild', 'themeTemplate'],
|
|
87
94
|
};
|
|
@@ -22,7 +22,7 @@ export const doc = {
|
|
|
22
22
|
'Same source as the Theming table `astryx component <Name>` prints ' +
|
|
23
23
|
'(the component docs), so the list cannot drift from the components, and `theme build` ' +
|
|
24
24
|
'validates overrides against this exact set. A filter naming a component gives that ' +
|
|
25
|
-
"component's set; anything else is a substring search over
|
|
25
|
+
"component's set; anything else is a case-insensitive substring search over each target's key, class and component.",
|
|
26
26
|
importPath: '@astryxdesign/cli/api',
|
|
27
27
|
signature:
|
|
28
28
|
'themeTargets(filter?: string, ctx?: {cwd?: string}): Promise<ThemeTargetsResponse>',
|
|
@@ -41,13 +41,14 @@ export const doc = {
|
|
|
41
41
|
name: 'filter',
|
|
42
42
|
type: 'string',
|
|
43
43
|
description:
|
|
44
|
-
'A component name (exact, case-insensitive) or a substring of a target key. Omit for the whole surface.',
|
|
44
|
+
'A component name (exact, case-insensitive), or a substring of a target key, class or component. Omit for the whole surface.',
|
|
45
45
|
},
|
|
46
46
|
{
|
|
47
47
|
name: 'ctx.cwd',
|
|
48
48
|
type: 'string',
|
|
49
49
|
description:
|
|
50
50
|
"Directory the project's @astryxdesign/core is resolved from.",
|
|
51
|
+
default: 'process.cwd()',
|
|
51
52
|
},
|
|
52
53
|
],
|
|
53
54
|
returns: [
|
|
@@ -43,6 +43,7 @@ export const doc = {
|
|
|
43
43
|
name: 'options.cwd',
|
|
44
44
|
type: 'string',
|
|
45
45
|
description: 'Directory the target path resolves against.',
|
|
46
|
+
default: 'process.cwd()',
|
|
46
47
|
},
|
|
47
48
|
],
|
|
48
49
|
returns: [
|
|
@@ -64,5 +65,5 @@ export const doc = {
|
|
|
64
65
|
},
|
|
65
66
|
],
|
|
66
67
|
command: 'theme template',
|
|
67
|
-
related: ['themeAdd', 'themeBuild', '
|
|
68
|
+
related: ['themeAdd', 'themeBuild', 'themeListAvailable', 'themeTargets'],
|
|
68
69
|
};
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file The upgrade receipt counts a file once when a core codemod AND an
|
|
5
|
+
* integration codemod both change it: `filesChanged` is the union of the two
|
|
6
|
+
* runners' files, while `transformsApplied` adds their changes.
|
|
7
|
+
*
|
|
8
|
+
* Uses a real consumer under a repo-local temp dir (Vite blocks dynamic import
|
|
9
|
+
* of config and integration modules from /tmp), the real core registry, and an
|
|
10
|
+
* installed integration whose code codemod stamps the same file.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import {describe, it, expect, afterEach} from 'vitest';
|
|
14
|
+
import * as fs from 'node:fs';
|
|
15
|
+
import * as path from 'node:path';
|
|
16
|
+
import {upgrade} from '../upgrade.mjs';
|
|
17
|
+
import {
|
|
18
|
+
latestVersion,
|
|
19
|
+
versions,
|
|
20
|
+
getTransformsBetween,
|
|
21
|
+
} from '../../../assets/codemods/registry.mjs';
|
|
22
|
+
|
|
23
|
+
const SLOW = 60_000;
|
|
24
|
+
|
|
25
|
+
/** The registry version whose manifest ships the authoring migration. */
|
|
26
|
+
async function authoringTier() {
|
|
27
|
+
const all = await getTransformsBetween('0.0.0', latestVersion);
|
|
28
|
+
const tier = all.find(({transforms}) =>
|
|
29
|
+
transforms.some(t => t.name === 'migrate-authoring-imports'),
|
|
30
|
+
);
|
|
31
|
+
if (!tier) throw new Error('no registry version ships the authoring migration');
|
|
32
|
+
return tier.version;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* A consumer with installed core at the registry's latest version and one
|
|
37
|
+
* old-surface file that the core authoring codemods rewrite.
|
|
38
|
+
* @param {string} dir
|
|
39
|
+
* @param {{integrationCodemod: boolean}} options
|
|
40
|
+
*/
|
|
41
|
+
function seed(dir, {integrationCodemod}) {
|
|
42
|
+
fs.writeFileSync(
|
|
43
|
+
path.join(dir, 'package.json'),
|
|
44
|
+
JSON.stringify({name: 'consumer', version: '1.0.0'}),
|
|
45
|
+
);
|
|
46
|
+
const core = path.join(dir, 'node_modules', '@astryxdesign', 'core');
|
|
47
|
+
fs.mkdirSync(core, {recursive: true});
|
|
48
|
+
fs.writeFileSync(
|
|
49
|
+
path.join(core, 'package.json'),
|
|
50
|
+
JSON.stringify({name: '@astryxdesign/core', version: latestVersion}),
|
|
51
|
+
);
|
|
52
|
+
fs.mkdirSync(path.join(dir, 'src'), {recursive: true});
|
|
53
|
+
fs.writeFileSync(
|
|
54
|
+
path.join(dir, 'src', 'Button.doc.mjs'),
|
|
55
|
+
[
|
|
56
|
+
"import {createComponentDoc} from '@astryxdesign/core/authoring';",
|
|
57
|
+
"export default createComponentDoc({name: 'Button', props: []});",
|
|
58
|
+
'',
|
|
59
|
+
].join('\n'),
|
|
60
|
+
);
|
|
61
|
+
if (!integrationCodemod) return;
|
|
62
|
+
fs.writeFileSync(
|
|
63
|
+
path.join(dir, 'astryx.config.mjs'),
|
|
64
|
+
"export default {integrations: ['@acme/widgets']};\n",
|
|
65
|
+
);
|
|
66
|
+
const pkg = path.join(dir, 'node_modules', '@acme', 'widgets');
|
|
67
|
+
fs.mkdirSync(path.join(pkg, 'codemods', latestVersion), {recursive: true});
|
|
68
|
+
fs.writeFileSync(
|
|
69
|
+
path.join(pkg, 'package.json'),
|
|
70
|
+
JSON.stringify({name: '@acme/widgets', version: '1.0.0'}),
|
|
71
|
+
);
|
|
72
|
+
fs.writeFileSync(
|
|
73
|
+
path.join(pkg, 'astryx.integration.mjs'),
|
|
74
|
+
"export default {codemods: './codemods'};\n",
|
|
75
|
+
);
|
|
76
|
+
fs.writeFileSync(
|
|
77
|
+
path.join(pkg, 'codemods', latestVersion, 'acme-stamp.mjs'),
|
|
78
|
+
"export default {type: 'code', title: 'Stamp', transform: file => (file.source.includes('// acme') ? null : `${file.source}// acme\\n`)};\n",
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
describe('upgrade receipt — filesChanged across core and integration codemods', () => {
|
|
83
|
+
/** @type {string[]} */
|
|
84
|
+
const dirs = [];
|
|
85
|
+
afterEach(() => {
|
|
86
|
+
for (const dir of dirs.splice(0)) fs.rmSync(dir, {recursive: true, force: true});
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
/** @param {{integrationCodemod: boolean}} options */
|
|
90
|
+
async function run(options) {
|
|
91
|
+
const dir = fs.mkdtempSync(path.join(process.cwd(), '.astryx-files-changed-'));
|
|
92
|
+
dirs.push(dir);
|
|
93
|
+
seed(dir, options);
|
|
94
|
+
const tier = await authoringTier();
|
|
95
|
+
const from = versions[versions.indexOf(tier) - 1];
|
|
96
|
+
const res = await upgrade({from, path: 'src'}, {cwd: dir});
|
|
97
|
+
expect(res.type).toBe('upgrade.run');
|
|
98
|
+
return res.data;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
it('counts a file changed by both a core and an integration codemod once', async () => {
|
|
102
|
+
const coreOnly = await run({integrationCodemod: false});
|
|
103
|
+
expect(coreOnly.filesChanged).toBe(1);
|
|
104
|
+
expect(coreOnly.transformsApplied).toBeGreaterThan(0);
|
|
105
|
+
|
|
106
|
+
const both = await run({integrationCodemod: true});
|
|
107
|
+
expect(both.integrations).toEqual(['@acme/widgets']);
|
|
108
|
+
expect(both.filesChanged).toBe(1);
|
|
109
|
+
expect(both.transformsApplied).toBe(coreOnly.transformsApplied + 1);
|
|
110
|
+
}, SLOW);
|
|
111
|
+
});
|
package/api/upgrade/run/run.mjs
CHANGED
|
@@ -137,6 +137,12 @@ export async function run(options = {}, {cwd = process.cwd()} = {}) {
|
|
|
137
137
|
}
|
|
138
138
|
const apply = options.apply ?? false;
|
|
139
139
|
|
|
140
|
+
// One fact about the resolved source directory, captured before anything
|
|
141
|
+
// runs. `--path` defaults to `./src`, so a project laid out as `app/` (or a
|
|
142
|
+
// typo) skips every code codemod; without this the receipt is byte-identical
|
|
143
|
+
// to a clean, fully migrated project.
|
|
144
|
+
const sourcePathFound = fs.existsSync(path_);
|
|
145
|
+
|
|
140
146
|
const currentVersion = /** @type {string} */ (options.from);
|
|
141
147
|
const installed = detectInstalledTargetVersion(cwd);
|
|
142
148
|
if (!installed) {
|
|
@@ -282,6 +288,7 @@ export async function run(options = {}, {cwd = process.cwd()} = {}) {
|
|
|
282
288
|
refreshed: false,
|
|
283
289
|
action: 'none',
|
|
284
290
|
},
|
|
291
|
+
sourcePathFound,
|
|
285
292
|
filesChanged: coreResult?.totalFilesChanged ?? 0,
|
|
286
293
|
transformsApplied: coreResult?.totalTransformsApplied ?? 0,
|
|
287
294
|
modifiedFiles: uniqueFiles(coreResult?.changedFiles).map(file =>
|
|
@@ -407,6 +414,12 @@ export async function run(options = {}, {cwd = process.cwd()} = {}) {
|
|
|
407
414
|
refreshed: false,
|
|
408
415
|
action: 'none',
|
|
409
416
|
}),
|
|
417
|
+
// A missing source directory is the one way this command can migrate
|
|
418
|
+
// nothing and still look complete: every codemod is skipped, filesChanged
|
|
419
|
+
// stays 0, and errors stays empty. The receipt carries the fact so a
|
|
420
|
+
// machine consumer can tell "nothing needed changing" from "nothing was
|
|
421
|
+
// ever read" — the human text says so via the runner's own error line.
|
|
422
|
+
sourcePathFound,
|
|
410
423
|
};
|
|
411
424
|
|
|
412
425
|
let integrationResult = null;
|
|
@@ -437,9 +450,11 @@ export async function run(options = {}, {cwd = process.cwd()} = {}) {
|
|
|
437
450
|
|
|
438
451
|
const registryResult = await reconcileCompositions();
|
|
439
452
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
(
|
|
453
|
+
// A file a core codemod AND an integration codemod both changed is one file.
|
|
454
|
+
const mergedFilesChanged = new Set([
|
|
455
|
+
...(coreResult?.changedFiles ?? []),
|
|
456
|
+
...(integrationResult?.changedFiles ?? []),
|
|
457
|
+
]).size;
|
|
443
458
|
const mergedTransformsApplied =
|
|
444
459
|
(coreResult?.totalTransformsApplied ?? 0) +
|
|
445
460
|
(integrationResult?.totalTransformsApplied ?? 0);
|
|
@@ -640,12 +655,16 @@ export async function run(options = {}, {cwd = process.cwd()} = {}) {
|
|
|
640
655
|
}
|
|
641
656
|
|
|
642
657
|
const registryOk = receipt.registryCompositions?.ok ?? true;
|
|
658
|
+
const done = apply ? 'Upgrade complete' : 'Dry run complete';
|
|
643
659
|
logger.log(
|
|
644
660
|
protectedFiles.length > 0
|
|
645
661
|
? 'Upgrade incomplete: protected changes remain\n'
|
|
646
|
-
: registryOk
|
|
647
|
-
?
|
|
648
|
-
:
|
|
662
|
+
: !registryOk
|
|
663
|
+
? 'Upgrade finished with unresolved registry items\n'
|
|
664
|
+
: sourcePathFound
|
|
665
|
+
? done + '\n'
|
|
666
|
+
: `${done}, but ${path.relative(cwd, path_) || '.'} does not exist, so no source files were scanned. ` +
|
|
667
|
+
`Pass --path <your source directory> if your code does not live in ./src.\n`,
|
|
649
668
|
);
|
|
650
669
|
return {
|
|
651
670
|
type: 'upgrade.run',
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* @file Colocated tests for the upgrade.run leaf — the --path scan dir must be
|
|
5
5
|
* confined to cwd (upgrade rewrites source in place with --apply, so an escaping
|
|
6
|
-
* or out-of-tree path must be rejected)
|
|
6
|
+
* or out-of-tree path must be rejected), and the receipt must say whether that
|
|
7
|
+
* dir existed at all.
|
|
7
8
|
*/
|
|
8
9
|
|
|
9
10
|
import {describe, it, expect, beforeEach, afterEach} from 'vitest';
|
|
@@ -51,3 +52,46 @@ describe('upgrade.run — --path confinement', () => {
|
|
|
51
52
|
).rejects.toMatchObject({code: 'ERR_PATH_TRAVERSAL'});
|
|
52
53
|
}, SLOW);
|
|
53
54
|
});
|
|
55
|
+
|
|
56
|
+
describe('upgrade.run — sourcePathFound', () => {
|
|
57
|
+
let dir;
|
|
58
|
+
beforeEach(() => {
|
|
59
|
+
dir = fs.mkdtempSync(path.join(os.tmpdir(), 'upg-srcpath-'));
|
|
60
|
+
seedProject(dir);
|
|
61
|
+
});
|
|
62
|
+
afterEach(() => fs.rmSync(dir, {recursive: true, force: true}));
|
|
63
|
+
|
|
64
|
+
// The receipt for a project whose source lives somewhere other than ./src was
|
|
65
|
+
// byte-identical to a fully migrated one: exit 0, filesChanged 0, errors [].
|
|
66
|
+
// The only signal was a human log line --json suppresses by design.
|
|
67
|
+
it('reports false when the resolved source directory is missing, and still counts nothing', async () => {
|
|
68
|
+
fs.rmSync(path.join(dir, 'src'), {recursive: true, force: true});
|
|
69
|
+
fs.mkdirSync(path.join(dir, 'app'), {recursive: true});
|
|
70
|
+
fs.writeFileSync(path.join(dir, 'app', 'index.ts'), 'const x = 1;\n');
|
|
71
|
+
|
|
72
|
+
const res = await upgrade({from: '0.0.1', apply: true}, {cwd: dir});
|
|
73
|
+
|
|
74
|
+
expect(res.type).toBe('upgrade.run');
|
|
75
|
+
expect(res.data.sourcePathFound).toBe(false);
|
|
76
|
+
expect(res.data.filesChanged).toBe(0);
|
|
77
|
+
expect(res.data.errors).toEqual([]);
|
|
78
|
+
}, SLOW);
|
|
79
|
+
|
|
80
|
+
it('reports true for a source directory that exists', async () => {
|
|
81
|
+
const res = await upgrade({from: '0.0.1', apply: true}, {cwd: dir});
|
|
82
|
+
|
|
83
|
+
expect(res.type).toBe('upgrade.run');
|
|
84
|
+
expect(res.data.sourcePathFound).toBe(true);
|
|
85
|
+
}, SLOW);
|
|
86
|
+
|
|
87
|
+
it('follows --path, so the right directory under another name reports true', async () => {
|
|
88
|
+
fs.rmSync(path.join(dir, 'src'), {recursive: true, force: true});
|
|
89
|
+
fs.mkdirSync(path.join(dir, 'app'), {recursive: true});
|
|
90
|
+
fs.writeFileSync(path.join(dir, 'app', 'index.ts'), 'const x = 1;\n');
|
|
91
|
+
|
|
92
|
+
const res = await upgrade({from: '0.0.1', path: 'app'}, {cwd: dir});
|
|
93
|
+
|
|
94
|
+
expect(res.type).toBe('upgrade.run');
|
|
95
|
+
expect(res.data.sourcePathFound).toBe(true);
|
|
96
|
+
}, SLOW);
|
|
97
|
+
});
|
|
@@ -13,19 +13,16 @@ export const doc = {
|
|
|
13
13
|
name: 'upgrade',
|
|
14
14
|
namespace: 'cli/api',
|
|
15
15
|
displayName: 'upgrade()',
|
|
16
|
-
summary:
|
|
16
|
+
summary:
|
|
17
|
+
'After bumping @astryxdesign/core, migrate project source with codemods and update copied compositions.',
|
|
17
18
|
description:
|
|
18
|
-
'
|
|
19
|
-
'
|
|
20
|
-
'
|
|
21
|
-
'
|
|
22
|
-
'
|
|
23
|
-
'
|
|
24
|
-
'
|
|
25
|
-
'the config is loaded so a config codemod can repair an otherwise-invalid ' +
|
|
26
|
-
'astryx.config. Copied compositions carry adjacent receipts with exact canonical and format-specific install bases; upgrade ' +
|
|
27
|
-
'compares those installed bases with the matching registry release, updates pristine ' +
|
|
28
|
-
'files, merges non-overlapping edits, and leaves conflicting originals untouched.',
|
|
19
|
+
'Runs the codemods between `from` and the installed Core version, then refreshes the ' +
|
|
20
|
+
'managed agent-docs block. Dry-run by default; `apply` writes changes only after the ' +
|
|
21
|
+
'selected codemods and hooks succeed. Config codemods run before astryx.config is ' +
|
|
22
|
+
'loaded, so they can repair an invalid config. Also updates copied compositions from ' +
|
|
23
|
+
'their install receipts: unchanged files are updated, non-overlapping edits are merged, ' +
|
|
24
|
+
'and conflicts are left untouched. `list` only lists codemods; `registry` only updates ' +
|
|
25
|
+
'copied compositions.',
|
|
29
26
|
importPath: '@astryxdesign/cli/api',
|
|
30
27
|
signature:
|
|
31
28
|
'upgrade(options?: UpgradeOptions, ctx?: {cwd?: string}): Promise<UpgradeListResponse | UpgradeRegistryResponse | UpgradeStatusResponse | UpgradeRunResponse>',
|
|
@@ -42,7 +39,7 @@ export const doc = {
|
|
|
42
39
|
name: 'options.from',
|
|
43
40
|
type: 'string',
|
|
44
41
|
description:
|
|
45
|
-
'Version before the dependency bump. Required unless `list` or `registry` is set.',
|
|
42
|
+
'Version before the dependency bump; the target is the installed @astryxdesign/core (or legacy @xds/core). Required unless `list` or `registry` is set.',
|
|
46
43
|
},
|
|
47
44
|
{
|
|
48
45
|
name: 'options.apply',
|
|
@@ -55,11 +52,13 @@ export const doc = {
|
|
|
55
52
|
type: 'boolean',
|
|
56
53
|
description:
|
|
57
54
|
'Run codemods even when `from` is at/after the installed version.',
|
|
55
|
+
default: 'false',
|
|
58
56
|
},
|
|
59
57
|
{
|
|
60
58
|
name: 'options.codemod',
|
|
61
59
|
type: 'string',
|
|
62
|
-
description:
|
|
60
|
+
description:
|
|
61
|
+
'Run only this codemod. Optional codemods run only when named here. Setting it also skips copied-composition reconciliation.',
|
|
63
62
|
},
|
|
64
63
|
{
|
|
65
64
|
name: 'options.skipCodemod',
|
|
@@ -83,23 +82,26 @@ export const doc = {
|
|
|
83
82
|
type: 'boolean',
|
|
84
83
|
description:
|
|
85
84
|
'Install jscodeshift when it is missing; otherwise a missing jscodeshift throws ERR_DEP_MISSING.',
|
|
85
|
+
default: 'false',
|
|
86
86
|
},
|
|
87
87
|
{
|
|
88
88
|
name: 'options.registry',
|
|
89
89
|
type: 'boolean',
|
|
90
90
|
description:
|
|
91
|
-
'
|
|
91
|
+
'Only reconcile copied compositions from their install receipts; `from` is not required. Cannot be combined with `list`, `from`, `force`, `codemod`, `skipCodemod`, `integration` or `installDeps`.',
|
|
92
92
|
default: 'false',
|
|
93
93
|
},
|
|
94
94
|
{
|
|
95
95
|
name: 'options.list',
|
|
96
96
|
type: 'boolean',
|
|
97
97
|
description: 'Return the available codemods instead of running any.',
|
|
98
|
+
default: 'false',
|
|
98
99
|
},
|
|
99
100
|
{
|
|
100
101
|
name: 'ctx.cwd',
|
|
101
102
|
type: 'string',
|
|
102
103
|
description: 'Directory to run the upgrade in.',
|
|
104
|
+
default: 'process.cwd()',
|
|
103
105
|
},
|
|
104
106
|
],
|
|
105
107
|
returns: [
|
|
@@ -116,36 +118,36 @@ export const doc = {
|
|
|
116
118
|
{
|
|
117
119
|
type: 'upgrade.status',
|
|
118
120
|
description:
|
|
119
|
-
'A short-circuit outcome (no codemods executed): `up_to_date` (`from` is at/after the installed target and no `force`), `no_codemods` (none apply to the range), or `config_fixable` (dry-run preview that a pending config codemod would repair an invalid astryx.config).
|
|
121
|
+
'A short-circuit outcome (no codemods executed): `up_to_date` (`from` is at/after the installed target and no `force`), `no_codemods` (none apply to the range), or `config_fixable` (dry-run preview that a pending config codemod would repair an invalid astryx.config). up_to_date and no_codemods carry the agent-docs summary and, when receipts are found, the copied-composition summary; config_fixable carries configError, configCodemods, suggestedCommand, message, note, and the agent-docs summary.',
|
|
120
122
|
},
|
|
121
123
|
{
|
|
122
124
|
type: 'upgrade.run',
|
|
123
125
|
description:
|
|
124
|
-
'The terminal run receipt: from
|
|
126
|
+
'The terminal run receipt: from, to, codemods (count), integrations, agentDocs, agentDocsRefreshed, registryCompositions (when receipts are found), sourcePathFound (false when the resolved `path` does not exist, so nothing was scanned), filesChanged, transformsApplied, modifiedFiles, protectedFiles, declinedCandidates, errors, and complete. When a protected file still requires a change, complete is false and errorCode is ERR_CODEMOD_PROTECTED; the CLI exits nonzero while preserving the structured receipt.',
|
|
125
127
|
},
|
|
126
128
|
],
|
|
127
129
|
throws: [
|
|
128
130
|
{
|
|
129
131
|
code: 'ERR_INVALID_ARGUMENT',
|
|
130
|
-
when: '`from` is missing (and neither `list` nor `registry` is set)
|
|
132
|
+
when: '`from` is missing (and neither `list` nor `registry` is set); `list` and `registry` are both set; `registry` is combined with `from`, `force`, `codemod`, `skipCodemod`, `integration` or `installDeps`; an `integration` specifier is invalid or not installed; or astryx.config fails to load or validate and no pending config codemod repairs it',
|
|
131
133
|
},
|
|
132
134
|
{code: 'ERR_INVALID_VERSION', when: '`from` is not a valid semver string'},
|
|
133
135
|
{code: 'ERR_PATH_TRAVERSAL', when: '`path` resolves outside cwd'},
|
|
134
136
|
{
|
|
135
137
|
code: 'ERR_VERSION_DETECT',
|
|
136
|
-
when: '
|
|
138
|
+
when: 'neither @astryxdesign/core nor legacy @xds/core is installed in cwd; with `registry`, only when copied-composition receipts exist and @astryxdesign/core is not installed',
|
|
137
139
|
},
|
|
138
140
|
{
|
|
139
141
|
code: 'ERR_DEP_MISSING',
|
|
140
|
-
when: 'jscodeshift is
|
|
142
|
+
when: 'jscodeshift is missing and `installDeps` is not set, or installing it failed',
|
|
141
143
|
},
|
|
142
144
|
{
|
|
143
145
|
code: 'ERR_UNKNOWN_CODEMOD',
|
|
144
|
-
when: '
|
|
146
|
+
when: 'the version range has codemods but none remain selected: `codemod` names no codemod in the range, or `skipCodemod` excludes all of them',
|
|
145
147
|
},
|
|
146
148
|
{
|
|
147
149
|
code: 'ERR_CODEMOD_FAILED',
|
|
148
|
-
when: 'one or more codemods failed, or a post-codemod hook failed',
|
|
150
|
+
when: 'one or more codemods failed, or a post-codemod hook failed, and no protected file still needs a change (otherwise an upgrade.run receipt with complete: false is returned)',
|
|
149
151
|
},
|
|
150
152
|
{
|
|
151
153
|
code: 'ERR_CODEMOD_PROTECTION_SOURCE',
|
|
@@ -168,6 +168,7 @@ export type UpgradeRunResponse = {
|
|
|
168
168
|
integrations: string[];
|
|
169
169
|
agentDocsRefreshed: boolean;
|
|
170
170
|
agentDocs: AgentDocsSummary;
|
|
171
|
+
sourcePathFound: boolean;
|
|
171
172
|
registryCompositions?: RegistryCompositionSummary | undefined;
|
|
172
173
|
complete?: boolean | undefined;
|
|
173
174
|
errorCode?: "ERR_CODEMOD_PROTECTED" | undefined;
|