@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
|
@@ -2,14 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* @file Tests for build's page ranker: long ideas, head nouns, family bases,
|
|
5
|
-
* rare-word weighting,
|
|
5
|
+
* rare-word weighting, keywords, family words taken from the templates
|
|
6
|
+
* themselves, and parts told from pages by the system's own components.
|
|
6
7
|
*/
|
|
7
8
|
|
|
8
9
|
import {describe, it, expect} from 'vitest';
|
|
9
10
|
import * as path from 'node:path';
|
|
10
11
|
import {fileURLToPath} from 'node:url';
|
|
11
|
-
import {pickStart, rankPages} from './rank.mjs';
|
|
12
|
-
import {loadPageTemplates} from '../_adapter.mjs';
|
|
12
|
+
import {ideaKind, pickStart, rankPages} from './rank.mjs';
|
|
13
|
+
import {loadComponents, loadPageTemplates} from '../_adapter.mjs';
|
|
13
14
|
|
|
14
15
|
// api/build/kit/ -> up 5 = repo root (has packages/core and the templates).
|
|
15
16
|
const REPO = path.resolve(
|
|
@@ -17,14 +18,24 @@ const REPO = path.resolve(
|
|
|
17
18
|
'../../../../..',
|
|
18
19
|
);
|
|
19
20
|
|
|
20
|
-
/**
|
|
21
|
-
|
|
21
|
+
/**
|
|
22
|
+
* @param {string} name
|
|
23
|
+
* @param {string} category
|
|
24
|
+
* @param {string} description
|
|
25
|
+
* @param {string[]} [keywords]
|
|
26
|
+
*/
|
|
27
|
+
const page = (name, category, description, keywords = []) => ({
|
|
22
28
|
name,
|
|
23
29
|
displayName: name,
|
|
24
30
|
category,
|
|
25
31
|
description,
|
|
32
|
+
keywords,
|
|
33
|
+
command: `astryx template ${name} --type page`,
|
|
26
34
|
});
|
|
27
35
|
|
|
36
|
+
/** @param {string} name @param {string[]} [keywords] */
|
|
37
|
+
const component = (name, keywords = []) => ({name, keywords});
|
|
38
|
+
|
|
28
39
|
describe('rankPages on the shipped page templates', () => {
|
|
29
40
|
/** @param {string} query */
|
|
30
41
|
const start = async query =>
|
|
@@ -49,6 +60,19 @@ describe('rankPages on the shipped page templates', () => {
|
|
|
49
60
|
);
|
|
50
61
|
});
|
|
51
62
|
|
|
63
|
+
it('keeps the family base when a variant shares one incidental word', async () => {
|
|
64
|
+
// "comparison" and "cohort" name dashboard variants, but here each is one
|
|
65
|
+
// small part of a general dashboard.
|
|
66
|
+
expect(
|
|
67
|
+
await start(
|
|
68
|
+
'support dashboard with ticket volume charts and a small comparison note',
|
|
69
|
+
),
|
|
70
|
+
).toBe('dashboard');
|
|
71
|
+
expect(
|
|
72
|
+
await start('sales dashboard with a cohort filter and weekly charts'),
|
|
73
|
+
).toBe('dashboard');
|
|
74
|
+
});
|
|
75
|
+
|
|
52
76
|
it('lets the head noun decide between families', async () => {
|
|
53
77
|
// Both ideas mention a table and summary numbers; the head says which
|
|
54
78
|
// page it is.
|
|
@@ -64,6 +88,14 @@ describe('rankPages on the shipped page templates', () => {
|
|
|
64
88
|
).toMatch(/^table-/);
|
|
65
89
|
});
|
|
66
90
|
|
|
91
|
+
it('keeps a variant that leads when its family base cannot start alone', async () => {
|
|
92
|
+
// The dashboard base matches only the family word here; the funnel
|
|
93
|
+
// dashboard matches the idea.
|
|
94
|
+
expect(await start('a funnel for a dashboard')).toBe(
|
|
95
|
+
'dashboard-cohort-funnel',
|
|
96
|
+
);
|
|
97
|
+
});
|
|
98
|
+
|
|
67
99
|
it('does not start from one rare word', async () => {
|
|
68
100
|
// "board" is the kanban board's own word; a game board is not a kanban.
|
|
69
101
|
expect(
|
|
@@ -75,11 +107,10 @@ describe('rankPages on the shipped page templates', () => {
|
|
|
75
107
|
describe('rankPages on any catalog', () => {
|
|
76
108
|
it('ranks only the templates it is given', () => {
|
|
77
109
|
const ranked = rankPages('dashboard', [
|
|
78
|
-
page(
|
|
110
|
+
page('dashboard', 'Dashboard - Analytics', 'Tiles, charts, tables.', [
|
|
79
111
|
'dashboard',
|
|
80
|
-
'
|
|
81
|
-
|
|
82
|
-
),
|
|
112
|
+
'metrics',
|
|
113
|
+
]),
|
|
83
114
|
]);
|
|
84
115
|
expect(ranked.map(r => r.name)).toEqual(['dashboard']);
|
|
85
116
|
});
|
|
@@ -88,17 +119,14 @@ describe('rankPages on any catalog', () => {
|
|
|
88
119
|
// An integration's family: its word is in two of its ids, so an idea
|
|
89
120
|
// naming it picks the family, and its base template leads it.
|
|
90
121
|
const catalog = [
|
|
91
|
-
page(
|
|
122
|
+
page('dashboard', 'Dashboard - Analytics', 'Tiles, charts, tables.', [
|
|
92
123
|
'dashboard',
|
|
93
|
-
'
|
|
94
|
-
|
|
95
|
-
),
|
|
96
|
-
page('widget', 'Widget -
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
'Widget - Grid',
|
|
100
|
-
'Many compact cards in a grid. Widget wall.',
|
|
101
|
-
),
|
|
124
|
+
'metrics',
|
|
125
|
+
]),
|
|
126
|
+
page('widget', 'Widget - Basic', 'One compact card.', ['widget', 'tile']),
|
|
127
|
+
page('widget-grid', 'Widget - Grid', 'Many compact cards in a grid.', [
|
|
128
|
+
'widget wall',
|
|
129
|
+
]),
|
|
102
130
|
];
|
|
103
131
|
const ranked = rankPages('weather widget with charts', catalog);
|
|
104
132
|
expect(ranked[0].name).toBe('widget');
|
|
@@ -106,15 +134,41 @@ describe('rankPages on any catalog', () => {
|
|
|
106
134
|
expect(pickStart(ranked)?.name).toBe('widget');
|
|
107
135
|
});
|
|
108
136
|
|
|
137
|
+
it("counts a template's keywords above words in its description", () => {
|
|
138
|
+
// Both mention uptime; only one names it as an idea it serves.
|
|
139
|
+
const catalog = [
|
|
140
|
+
page('ops', 'Dashboard - Ops', 'Uptime strips beside alert rows.'),
|
|
141
|
+
page('health', 'Dashboard - Health', 'Status tiles over time charts.', [
|
|
142
|
+
'uptime',
|
|
143
|
+
]),
|
|
144
|
+
];
|
|
145
|
+
expect(rankPages('uptime overview', catalog)[0].name).toBe('health');
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it("lets a variant displace its family's base only with two words of its own", () => {
|
|
149
|
+
const catalog = [
|
|
150
|
+
page('widget', 'Widget - Basic', 'One compact card.', ['widget']),
|
|
151
|
+
page('widget-weather', 'Widget - Weather', 'A forecast card.', [
|
|
152
|
+
'weather',
|
|
153
|
+
'forecast',
|
|
154
|
+
'radar',
|
|
155
|
+
]),
|
|
156
|
+
];
|
|
157
|
+
// One word of the variant's own: still the family's base.
|
|
158
|
+
expect(rankPages('weather widget', catalog)[0].name).toBe('widget');
|
|
159
|
+
// Two: the variant.
|
|
160
|
+
expect(rankPages('weather widget with radar', catalog)[0].name).toBe(
|
|
161
|
+
'widget-weather',
|
|
162
|
+
);
|
|
163
|
+
});
|
|
164
|
+
|
|
109
165
|
it('weighs a word by how rare it is among page templates', () => {
|
|
110
166
|
const catalog = [
|
|
111
|
-
page('alpha', 'Dashboard - Alpha', 'Status tiles.
|
|
112
|
-
page('beta', 'Dashboard - Beta', 'Status rows.
|
|
113
|
-
page(
|
|
114
|
-
'
|
|
115
|
-
|
|
116
|
-
'Funnel of stages. Funnel conversion.',
|
|
117
|
-
),
|
|
167
|
+
page('alpha', 'Dashboard - Alpha', 'Status tiles.', ['status overview']),
|
|
168
|
+
page('beta', 'Dashboard - Beta', 'Status rows.', ['status list']),
|
|
169
|
+
page('gamma', 'Dashboard - Gamma', 'Funnel of stages.', [
|
|
170
|
+
'funnel conversion',
|
|
171
|
+
]),
|
|
118
172
|
];
|
|
119
173
|
// "status" is on two templates, "funnel" on one: the rare word wins.
|
|
120
174
|
const ranked = rankPages('status funnel', catalog);
|
|
@@ -127,22 +181,24 @@ describe('rankPages structure signals', () => {
|
|
|
127
181
|
page(
|
|
128
182
|
'dialog-panel',
|
|
129
183
|
'Settings - Dialog',
|
|
130
|
-
'Preferences inside a modal container.
|
|
131
|
-
|
|
132
|
-
page(
|
|
133
|
-
'tree-table',
|
|
134
|
-
'Table - Tree',
|
|
135
|
-
'Nested rows under parents. Tree, nested rows, file browser.',
|
|
136
|
-
),
|
|
137
|
-
page(
|
|
138
|
-
'item-detail',
|
|
139
|
-
'Content - Item Detail',
|
|
140
|
-
'One item with its media. Product, listing, or item detail.',
|
|
184
|
+
'Preferences inside a modal container.',
|
|
185
|
+
['settings', 'modal dialog'],
|
|
141
186
|
),
|
|
187
|
+
page('tree-table', 'Table - Tree', 'Nested rows under parents.', [
|
|
188
|
+
'tree',
|
|
189
|
+
'nested rows',
|
|
190
|
+
'file browser',
|
|
191
|
+
]),
|
|
192
|
+
page('item-detail', 'Content - Item Detail', 'One item with its media.', [
|
|
193
|
+
'product',
|
|
194
|
+
'listing',
|
|
195
|
+
'item detail',
|
|
196
|
+
]),
|
|
142
197
|
page(
|
|
143
198
|
'docs-catalog',
|
|
144
199
|
'Content - Documentation Catalog',
|
|
145
|
-
'A grid of category cards.
|
|
200
|
+
'A grid of category cards.',
|
|
201
|
+
['documentation', 'docs', 'api index'],
|
|
146
202
|
),
|
|
147
203
|
];
|
|
148
204
|
|
|
@@ -179,18 +235,145 @@ describe('rankPages structure signals', () => {
|
|
|
179
235
|
it('does not treat a synonym as a family name', () => {
|
|
180
236
|
// "landing" is a synonym of "hero" in search, not a family word here.
|
|
181
237
|
const heroes = [
|
|
182
|
-
page(
|
|
183
|
-
'hero
|
|
184
|
-
'
|
|
185
|
-
'
|
|
186
|
-
),
|
|
187
|
-
page(
|
|
188
|
-
'hero
|
|
189
|
-
'
|
|
190
|
-
|
|
191
|
-
),
|
|
238
|
+
page('hero-centered', 'Gallery - Hero', 'A centered hero.', [
|
|
239
|
+
'hero',
|
|
240
|
+
'banner',
|
|
241
|
+
'landing',
|
|
242
|
+
]),
|
|
243
|
+
page('hero-split', 'Gallery - Hero Split', 'A split hero.', [
|
|
244
|
+
'hero',
|
|
245
|
+
'splash',
|
|
246
|
+
]),
|
|
192
247
|
];
|
|
193
248
|
const ranked = rankPages('internal landing page', heroes);
|
|
194
249
|
expect(ranked.every(r => !r.familyNamed)).toBe(true);
|
|
195
250
|
});
|
|
196
251
|
});
|
|
252
|
+
|
|
253
|
+
describe('ideaKind: a part of a page, told by the components the system ships', () => {
|
|
254
|
+
const pages = [
|
|
255
|
+
page('table', 'Table - Basic', 'Rows of records.'),
|
|
256
|
+
page('table-filter', 'Table - Filtering', 'Rows narrowed by filters.'),
|
|
257
|
+
page('settings', 'Settings', 'Grouped preferences.'),
|
|
258
|
+
];
|
|
259
|
+
const components = [
|
|
260
|
+
component('DateRangeInput', ['date picker']),
|
|
261
|
+
component('Tooltip'),
|
|
262
|
+
component('Calendar'),
|
|
263
|
+
component('Table'),
|
|
264
|
+
component('Dialog', ['modal']),
|
|
265
|
+
];
|
|
266
|
+
/** @param {string} idea @param {object[]} [using] */
|
|
267
|
+
const kind = (idea, using = components) => ideaKind(idea, pages, using);
|
|
268
|
+
|
|
269
|
+
it('takes a part from a component name or keyword at the head', () => {
|
|
270
|
+
expect(kind('a date range input')).toBe('part');
|
|
271
|
+
expect(kind('a date picker with presets')).toBe('part');
|
|
272
|
+
expect(kind('a tooltip')).toBe('part');
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
it('takes a page word or a family word at the head as a page', () => {
|
|
276
|
+
expect(kind('a calendar')).toBe('part');
|
|
277
|
+
expect(kind('a team calendar page')).toBe('page');
|
|
278
|
+
// Table is a component, but table is also a family of page templates.
|
|
279
|
+
expect(kind('a data table with filters')).toBe('page');
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
it("reads parts from the project's own components", () => {
|
|
283
|
+
// An integration's component joins the vocabulary by existing.
|
|
284
|
+
expect(kind('a revenue gauge')).toBe('page');
|
|
285
|
+
expect(
|
|
286
|
+
kind('a revenue gauge', [...components, component('AcmeGauge')]),
|
|
287
|
+
).toBe('part');
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
it("takes an idea that lists a page's worth of pieces as a page", () => {
|
|
291
|
+
expect(kind('a calendar with a tooltip')).toBe('part');
|
|
292
|
+
expect(kind('a calendar, a tooltip, and a date range input')).toBe('page');
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
it('takes the frame of a container phrase as the frame, not the head', () => {
|
|
296
|
+
expect(kind('a dialog')).toBe('part');
|
|
297
|
+
expect(kind('saved drafts in a modal')).toBe('page');
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
it('takes a change to an existing page or part as an edit', () => {
|
|
301
|
+
expect(kind('add a sort toggle to the existing reports table')).toBe(
|
|
302
|
+
'edit',
|
|
303
|
+
);
|
|
304
|
+
expect(kind('reuse the existing tooltip on the chart')).toBe('edit');
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
it('does not take "existing" that names no page or part as an edit', () => {
|
|
308
|
+
expect(kind('a new settings page inspired by the existing one')).toBe(
|
|
309
|
+
'page',
|
|
310
|
+
);
|
|
311
|
+
expect(kind('show existing users in a settings page')).toBe('page');
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
it('does not take a request for a new page as an edit', () => {
|
|
315
|
+
expect(
|
|
316
|
+
kind('a new settings page based on the existing settings page'),
|
|
317
|
+
).toBe('page');
|
|
318
|
+
expect(kind('clone the existing table as a new page')).toBe('page');
|
|
319
|
+
// "A new column" asks for a part, so the change stays a change.
|
|
320
|
+
expect(kind('add a new column to the existing reports table')).toBe('edit');
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
describe('pickStart on parts and edits (spec:AST-048/FR3)', () => {
|
|
325
|
+
const shipped = Promise.all([loadPageTemplates(REPO), loadComponents(REPO)]);
|
|
326
|
+
/** @param {string} query */
|
|
327
|
+
const start = async query => {
|
|
328
|
+
const [catalog, components] = await shipped;
|
|
329
|
+
const kind = ideaKind(query, catalog, components);
|
|
330
|
+
return pickStart(rankPages(query, catalog), kind)?.name ?? null;
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
it('starts a part from the page it names, else from the app shell', async () => {
|
|
334
|
+
expect(await start('an empty state for a settings page')).toBe('settings');
|
|
335
|
+
expect(await start('a date range picker')).toBeNull();
|
|
336
|
+
expect(await start('compact status pill with a tooltip')).toBeNull();
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
it('starts an edit of an existing page or part from the app shell', async () => {
|
|
340
|
+
for (const idea of [
|
|
341
|
+
'add a sparkline column to the existing incidents table',
|
|
342
|
+
'add a sort toggle to the existing reports dashboard',
|
|
343
|
+
'swap the existing banner for a toast',
|
|
344
|
+
]) {
|
|
345
|
+
expect(await start(idea)).toBeNull();
|
|
346
|
+
}
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
it('starts a new page that mentions something existing from its template', async () => {
|
|
350
|
+
expect(await start('a new dashboard inspired by the existing one')).toBe(
|
|
351
|
+
'dashboard',
|
|
352
|
+
);
|
|
353
|
+
expect(await start('show existing users in a table page')).toMatch(
|
|
354
|
+
/^table/,
|
|
355
|
+
);
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
it('starts a new page that names an existing one from its template', async () => {
|
|
359
|
+
for (const idea of [
|
|
360
|
+
'a new dashboard based on the existing dashboard',
|
|
361
|
+
'a new dashboard like the existing dashboard',
|
|
362
|
+
'clone the existing dashboard as a new page',
|
|
363
|
+
]) {
|
|
364
|
+
expect(await start(idea)).toBe('dashboard');
|
|
365
|
+
}
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
it('reads a bare "existing" phrase that names a page as the builder\'s page', async () => {
|
|
369
|
+
expect(
|
|
370
|
+
await start('existing reports dashboard with a date filter'),
|
|
371
|
+
).toBeNull();
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
it('still starts a whole page from its template', async () => {
|
|
375
|
+
expect(
|
|
376
|
+
await start('saved drafts in a modal with resume and delete row actions'),
|
|
377
|
+
).toBe('settings-dialog');
|
|
378
|
+
});
|
|
379
|
+
});
|
|
@@ -68,6 +68,16 @@ export function requireCoreDir(cwd: string): string;
|
|
|
68
68
|
* @returns {Promise<import('../../foundation/integrations/integrations.mjs').LoadedIntegration[]>}
|
|
69
69
|
*/
|
|
70
70
|
export function loadIntegrationsSafely(cwd: string): Promise<import("../../foundation/integrations/integrations.mjs").LoadedIntegration[]>;
|
|
71
|
+
/**
|
|
72
|
+
* Read the exact installed version available to a package-qualified component
|
|
73
|
+
* selector. Legacy docs packages do not expose a reliable version here, so a
|
|
74
|
+
* version-qualified lookup never falls through to them.
|
|
75
|
+
* @param {string} coreDir
|
|
76
|
+
* @param {import('../../foundation/integrations/integrations.mjs').LoadedIntegration[]} loadedIntegrations
|
|
77
|
+
* @param {string} packageName
|
|
78
|
+
* @returns {string|null}
|
|
79
|
+
*/
|
|
80
|
+
export function installedComponentPackageVersion(coreDir: string, loadedIntegrations: import("../../foundation/integrations/integrations.mjs").LoadedIntegration[], packageName: string): string | null;
|
|
71
81
|
/**
|
|
72
82
|
* Build the set of OWNER packages that provide a component with this name
|
|
73
83
|
* across core + every loaded integration. This is what lets the CLI
|
|
@@ -180,6 +190,20 @@ export function scopeSubComponent(docs: LoadedComponentDoc, dirName: string, cor
|
|
|
180
190
|
matchingComponent: any;
|
|
181
191
|
} | null;
|
|
182
192
|
export { CORE_PACKAGE };
|
|
193
|
+
/**
|
|
194
|
+
* Internal ambiguity marker. Single-component callers still receive the same
|
|
195
|
+
* AstryxError code, message, and suggestions; batch callers can additionally
|
|
196
|
+
* project every installed candidate without parsing prose.
|
|
197
|
+
*/
|
|
198
|
+
export class ComponentAmbiguityError extends AstryxError {
|
|
199
|
+
/**
|
|
200
|
+
* @param {ComponentOwner[]} owners
|
|
201
|
+
* @param {string} dirName
|
|
202
|
+
*/
|
|
203
|
+
constructor(owners: ComponentOwner[], dirName: string);
|
|
204
|
+
/** @type {import('./component.type.mjs').ComponentBatchCandidate[]} */
|
|
205
|
+
candidates: import("./component.type.mjs").ComponentBatchCandidate[];
|
|
206
|
+
}
|
|
183
207
|
/**
|
|
184
208
|
* A loaded component doc. The shared validated loader accepts stamped and legacy
|
|
185
209
|
* component docs; this loose view captures the fields the API reads across both.
|
|
@@ -258,3 +282,4 @@ export type ResolvedUnscopedDoc = {
|
|
|
258
282
|
resolvedSourcePath: string | null;
|
|
259
283
|
};
|
|
260
284
|
import { CORE_PACKAGE } from '../../foundation/discovery/component-discovery.mjs';
|
|
285
|
+
import { AstryxError } from '../error.mjs';
|
|
@@ -18,6 +18,8 @@
|
|
|
18
18
|
* deduped, so each leaf stays a thin projection.
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
+
import * as fs from 'node:fs';
|
|
22
|
+
import * as path from 'node:path';
|
|
21
23
|
import {ERROR_CODES} from '../../foundation/response/error-codes.mjs';
|
|
22
24
|
import {
|
|
23
25
|
findCoreDir,
|
|
@@ -146,6 +148,34 @@ function findLoadedIntegration(loadedIntegrations, packageName) {
|
|
|
146
148
|
return loadedIntegrations.find(i => i.name === packageName) ?? null;
|
|
147
149
|
}
|
|
148
150
|
|
|
151
|
+
/**
|
|
152
|
+
* Read the exact installed version available to a package-qualified component
|
|
153
|
+
* selector. Legacy docs packages do not expose a reliable version here, so a
|
|
154
|
+
* version-qualified lookup never falls through to them.
|
|
155
|
+
* @param {string} coreDir
|
|
156
|
+
* @param {import('../../foundation/integrations/integrations.mjs').LoadedIntegration[]} loadedIntegrations
|
|
157
|
+
* @param {string} packageName
|
|
158
|
+
* @returns {string|null}
|
|
159
|
+
*/
|
|
160
|
+
export function installedComponentPackageVersion(
|
|
161
|
+
coreDir,
|
|
162
|
+
loadedIntegrations,
|
|
163
|
+
packageName,
|
|
164
|
+
) {
|
|
165
|
+
if (packageName === CORE_PACKAGE) {
|
|
166
|
+
try {
|
|
167
|
+
const pkg = JSON.parse(
|
|
168
|
+
fs.readFileSync(path.join(coreDir, 'package.json'), 'utf8'),
|
|
169
|
+
);
|
|
170
|
+
return typeof pkg.version === 'string' ? pkg.version : null;
|
|
171
|
+
} catch {
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
const integration = findLoadedIntegration(loadedIntegrations, packageName);
|
|
176
|
+
return typeof integration?.version === 'string' ? integration.version : null;
|
|
177
|
+
}
|
|
178
|
+
|
|
149
179
|
/**
|
|
150
180
|
* Resolve an external package by name from the discovered externals list.
|
|
151
181
|
* @param {string} packageName - e.g. '@acme/xds-widgets'
|
|
@@ -244,6 +274,34 @@ export function classifyScope(
|
|
|
244
274
|
return {kind: 'legacy', ext};
|
|
245
275
|
}
|
|
246
276
|
|
|
277
|
+
/**
|
|
278
|
+
* Internal ambiguity marker. Single-component callers still receive the same
|
|
279
|
+
* AstryxError code, message, and suggestions; batch callers can additionally
|
|
280
|
+
* project every installed candidate without parsing prose.
|
|
281
|
+
*/
|
|
282
|
+
export class ComponentAmbiguityError extends AstryxError {
|
|
283
|
+
/** @type {import('./component.type.mjs').ComponentBatchCandidate[]} */
|
|
284
|
+
candidates;
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* @param {ComponentOwner[]} owners
|
|
288
|
+
* @param {string} dirName
|
|
289
|
+
*/
|
|
290
|
+
constructor(owners, dirName) {
|
|
291
|
+
super(
|
|
292
|
+
`Component "${dirName}" is provided by multiple packages. Re-run with --package <pkg> to choose one.`,
|
|
293
|
+
owners.map(o => ({name: o.package, reason: 'provides this component'})),
|
|
294
|
+
ERROR_CODES.ERR_UNKNOWN_COMPONENT,
|
|
295
|
+
);
|
|
296
|
+
this.candidates = owners.map(owner => ({
|
|
297
|
+
package: owner.package,
|
|
298
|
+
component: dirName,
|
|
299
|
+
kind: 'component',
|
|
300
|
+
installed: true,
|
|
301
|
+
}));
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
247
305
|
/**
|
|
248
306
|
* Refuse to guess when the name is owned by MORE THAN ONE package (core and/or
|
|
249
307
|
* integrations) and the caller did not scope with --package. Legacy
|
|
@@ -254,11 +312,7 @@ export function classifyScope(
|
|
|
254
312
|
*/
|
|
255
313
|
export function assertUnambiguousOwners(owners, dirName) {
|
|
256
314
|
if (owners.length > 1) {
|
|
257
|
-
throw new
|
|
258
|
-
`Component "${dirName}" is provided by multiple packages. Re-run with --package <pkg> to choose one.`,
|
|
259
|
-
owners.map(o => ({name: o.package, reason: 'provides this component'})),
|
|
260
|
-
ERROR_CODES.ERR_UNKNOWN_COMPONENT,
|
|
261
|
-
);
|
|
315
|
+
throw new ComponentAmbiguityError(owners, dirName);
|
|
262
316
|
}
|
|
263
317
|
}
|
|
264
318
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// DO NOT EDIT — run `pnpm sync:api-types` to regenerate.
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* @param {string} [name]
|
|
5
|
+
* @param {string|string[]} [name]
|
|
6
6
|
* @param {object} [options]
|
|
7
7
|
* @param {string} [options.cwd]
|
|
8
8
|
* @param {boolean} [options.list]
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
* @param {boolean} [options.dense]
|
|
19
19
|
* @returns {Promise<(
|
|
20
20
|
* import('./component.type.mjs').ComponentListResponse
|
|
21
|
+
* | import('./component.type.mjs').ComponentBatchResponse
|
|
21
22
|
* | import('./component.type.mjs').ComponentDetailResponse
|
|
22
23
|
* | import('./component.type.mjs').ComponentDetailPropsResponse
|
|
23
24
|
* | import('./component.type.mjs').ComponentDetailSourceResponse
|
|
@@ -25,7 +26,7 @@
|
|
|
25
26
|
* | import('./component.type.mjs').ComponentDetailBlocksResponse
|
|
26
27
|
* )>}
|
|
27
28
|
*/
|
|
28
|
-
export function component(name?: string, options?: {
|
|
29
|
+
export function component(name?: string | string[], options?: {
|
|
29
30
|
cwd?: string | undefined;
|
|
30
31
|
list?: boolean | undefined;
|
|
31
32
|
category?: string | undefined;
|
|
@@ -38,4 +39,6 @@ export function component(name?: string, options?: {
|
|
|
38
39
|
lang?: string | undefined;
|
|
39
40
|
zh?: boolean | undefined;
|
|
40
41
|
dense?: boolean | undefined;
|
|
41
|
-
}): Promise<(import("./component.type.mjs").ComponentListResponse | import("./component.type.mjs").ComponentDetailResponse | import("./component.type.mjs").ComponentDetailPropsResponse | import("./component.type.mjs").ComponentDetailSourceResponse | import("./component.type.mjs").ComponentDetailShowcaseResponse | import("./component.type.mjs").ComponentDetailBlocksResponse)>;
|
|
42
|
+
}): Promise<(import("./component.type.mjs").ComponentListResponse | import("./component.type.mjs").ComponentBatchResponse | import("./component.type.mjs").ComponentDetailResponse | import("./component.type.mjs").ComponentDetailPropsResponse | import("./component.type.mjs").ComponentDetailSourceResponse | import("./component.type.mjs").ComponentDetailShowcaseResponse | import("./component.type.mjs").ComponentDetailBlocksResponse)>;
|
|
43
|
+
/** Maximum selectors accepted before any component resolution starts. */
|
|
44
|
+
export const COMPONENT_BATCH_SELECTOR_LIMIT: 100;
|
|
@@ -15,16 +15,16 @@ export const doc = {
|
|
|
15
15
|
namespace: 'cli/api',
|
|
16
16
|
displayName: 'component()',
|
|
17
17
|
summary:
|
|
18
|
-
'Resolve
|
|
18
|
+
'Resolve one or several components by name, or list the catalog, with optional focused slices (props, source, showcase, blocks).',
|
|
19
19
|
description:
|
|
20
|
-
'Routes on its arguments:
|
|
21
|
-
'integration packages
|
|
22
|
-
'
|
|
23
|
-
'
|
|
24
|
-
'
|
|
20
|
+
'Routes on its arguments: one string resolves that component across core and ' +
|
|
21
|
+
'integration packages; an array returns one ordered result row per selector at ' +
|
|
22
|
+
'every array length; and no name returns the catalog grouped by category. ' +
|
|
23
|
+
'Boolean flags narrow each resolved component to just its props, source, ' +
|
|
24
|
+
'showcase, or example blocks.',
|
|
25
25
|
importPath: '@astryxdesign/cli/api',
|
|
26
26
|
signature:
|
|
27
|
-
'component(name?: string, options?: ComponentOptions): Promise<ComponentListResponse | ComponentDetailResponse | ComponentDetailPropsResponse | ComponentDetailSourceResponse | ComponentDetailShowcaseResponse | ComponentDetailBlocksResponse>',
|
|
27
|
+
'component(name?: string | string[], options?: ComponentOptions): Promise<ComponentListResponse | ComponentBatchResponse | ComponentDetailResponse | ComponentDetailPropsResponse | ComponentDetailSourceResponse | ComponentDetailShowcaseResponse | ComponentDetailBlocksResponse>',
|
|
28
28
|
keywords: [
|
|
29
29
|
'component',
|
|
30
30
|
'components',
|
|
@@ -37,14 +37,15 @@ export const doc = {
|
|
|
37
37
|
params: [
|
|
38
38
|
{
|
|
39
39
|
name: 'name',
|
|
40
|
-
type: 'string',
|
|
40
|
+
type: 'string | string[]',
|
|
41
41
|
description:
|
|
42
|
-
"
|
|
42
|
+
"Pass one selector string for the existing single-result response, or an array of at most 100 selectors for an ordered component.batch response. The limit counts duplicates in every projection mode. An array always requests a batch, including [] and ['Button']. Use 'Button', 'widgets/Button', '@acme/widgets/Button', or '@acme/widgets@1.2.3/Button'. A version applies to the package and must match the installed version. Omit the argument to list the catalog.",
|
|
43
43
|
},
|
|
44
44
|
{
|
|
45
45
|
name: 'options.cwd',
|
|
46
46
|
type: 'string',
|
|
47
47
|
description: 'Directory to resolve @astryxdesign/core from.',
|
|
48
|
+
default: 'process.cwd()',
|
|
48
49
|
},
|
|
49
50
|
{
|
|
50
51
|
name: 'options.list',
|
|
@@ -54,13 +55,14 @@ export const doc = {
|
|
|
54
55
|
{
|
|
55
56
|
name: 'options.category',
|
|
56
57
|
type: 'string',
|
|
57
|
-
description:
|
|
58
|
+
description:
|
|
59
|
+
"List only the components in this group: a key of the unfiltered list (each component's group field), such as 'Layout' or 'Button'. It is not the category field of a component detail.",
|
|
58
60
|
},
|
|
59
61
|
{
|
|
60
62
|
name: 'options.package',
|
|
61
63
|
type: 'string',
|
|
62
64
|
description:
|
|
63
|
-
"Scope lookup to a specific external package (e.g. '@acme/
|
|
65
|
+
"Scope lookup to a specific external package (e.g. '@acme/widgets').",
|
|
64
66
|
},
|
|
65
67
|
{
|
|
66
68
|
name: 'options.props',
|
|
@@ -87,7 +89,8 @@ export const doc = {
|
|
|
87
89
|
name: 'options.detail',
|
|
88
90
|
type: "'full' | 'compact' | 'brief'",
|
|
89
91
|
description: 'Detail level for list views.',
|
|
90
|
-
default:
|
|
92
|
+
default:
|
|
93
|
+
"'full' for a named component; 'brief' for lists (returned as data.detail: 'names')",
|
|
91
94
|
},
|
|
92
95
|
{
|
|
93
96
|
name: 'options.lang',
|
|
@@ -110,7 +113,12 @@ export const doc = {
|
|
|
110
113
|
{
|
|
111
114
|
type: 'component.list',
|
|
112
115
|
description:
|
|
113
|
-
"The catalog grouped by
|
|
116
|
+
"The catalog grouped by component group. data.detail is the level ('names' | 'compact' | 'full') and data.components is the grouped map: names entries with name, package, and an optional canonical import for integration and legacy package components; brief entries; or full ComponentDoc entries.",
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
type: 'component.batch',
|
|
120
|
+
description:
|
|
121
|
+
'An explicit selector array returns one ordered receipt at every array length: count and one results row per selector, including duplicates. ComponentBatchResponse specializes the shared BatchResponse and BatchRow types. Each row carries selector and status (found, not_found, ambiguous, or error); found rows carry the single-selector result, ambiguous rows carry installed candidates ({package, component, kind, installed}), and failed rows carry code, error, and optional suggestions.',
|
|
114
122
|
},
|
|
115
123
|
{
|
|
116
124
|
type: 'component.detail',
|
|
@@ -137,6 +145,10 @@ export const doc = {
|
|
|
137
145
|
},
|
|
138
146
|
],
|
|
139
147
|
throws: [
|
|
148
|
+
{
|
|
149
|
+
code: 'ERR_INVALID_ARGUMENT',
|
|
150
|
+
when: 'a selector array has more than 100 entries, a package-shaped selector has no component item, or its package conflicts with options.package',
|
|
151
|
+
},
|
|
140
152
|
{
|
|
141
153
|
code: 'ERR_INVALID_DETAIL',
|
|
142
154
|
when: "options.detail is not 'full', 'compact', or 'brief'",
|
|
@@ -151,7 +163,7 @@ export const doc = {
|
|
|
151
163
|
},
|
|
152
164
|
{
|
|
153
165
|
code: 'ERR_UNKNOWN_CATEGORY',
|
|
154
|
-
when: 'options.category is not a string or matches no
|
|
166
|
+
when: 'options.category is not a string or matches no component group',
|
|
155
167
|
},
|
|
156
168
|
{
|
|
157
169
|
code: 'ERR_UNKNOWN_COMPONENT',
|
|
@@ -159,12 +171,16 @@ export const doc = {
|
|
|
159
171
|
},
|
|
160
172
|
{
|
|
161
173
|
code: 'ERR_UNKNOWN_PACKAGE',
|
|
162
|
-
when: 'options.package names a legacy external package that cannot be found',
|
|
174
|
+
when: 'options.package names a legacy external package that cannot be found, or a package-qualified selector requests a version that is not installed',
|
|
163
175
|
},
|
|
164
176
|
{
|
|
165
177
|
code: 'ERR_NO_DOC',
|
|
166
178
|
when: 'the resolved component has no .doc.mjs typed doc file',
|
|
167
179
|
},
|
|
180
|
+
{
|
|
181
|
+
code: 'ERR_INVALID_DOC',
|
|
182
|
+
when: "the resolved component's .doc.mjs fails to load or validate",
|
|
183
|
+
},
|
|
168
184
|
{
|
|
169
185
|
code: 'ERR_NO_SOURCE',
|
|
170
186
|
when: 'options.source is set but the component has no source file',
|
|
@@ -179,10 +195,14 @@ export const doc = {
|
|
|
179
195
|
label: 'Look up a component',
|
|
180
196
|
code: "const r = await component('Button');",
|
|
181
197
|
},
|
|
198
|
+
{
|
|
199
|
+
label: 'Look up several components',
|
|
200
|
+
code: "await component(['Button', 'Badge']);",
|
|
201
|
+
},
|
|
182
202
|
{label: 'Props only', code: "await component('Button', {props: true});"},
|
|
183
203
|
{
|
|
184
|
-
label: 'Browse
|
|
185
|
-
code: "await component(undefined, {category: '
|
|
204
|
+
label: 'Browse one group',
|
|
205
|
+
code: "await component(undefined, {category: 'Layout', detail: 'compact'});",
|
|
186
206
|
},
|
|
187
207
|
],
|
|
188
208
|
command: 'component',
|