@astryxdesign/cli 0.6.4 → 0.6.5-canary.01972bc
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
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// @generated by scripts/sync-api-types.mjs from the JSDoc in api/**/*.mjs.
|
|
2
|
+
// DO NOT EDIT — run `pnpm sync:api-types` to regenerate.
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Find one item of a package: an installed package's own templates, docs,
|
|
6
|
+
* themes, and codemods first, then what a discover source lists for the
|
|
7
|
+
* package. Returns null when neither has it, so the caller can report the
|
|
8
|
+
* component lookup's own error.
|
|
9
|
+
*
|
|
10
|
+
* @param {import('../../_adapter.mjs').InstalledPackage[]} packages
|
|
11
|
+
* @param {string} packageName
|
|
12
|
+
* @param {string} itemName
|
|
13
|
+
* @param {{
|
|
14
|
+
* catalog?: import('../../_catalog-view.mjs').CatalogPackage,
|
|
15
|
+
* version?: string,
|
|
16
|
+
* add?: (name: string, version?: string) => string,
|
|
17
|
+
* installedAs?: string,
|
|
18
|
+
* }} [options]
|
|
19
|
+
* @returns {import('../../discover.type.mjs').DiscoverItemResponse | null}
|
|
20
|
+
*/
|
|
21
|
+
export function item(packages: import("../../_adapter.mjs").InstalledPackage[], packageName: string, itemName: string, options?: {
|
|
22
|
+
catalog?: import("../../_catalog-view.mjs").CatalogPackage;
|
|
23
|
+
version?: string;
|
|
24
|
+
add?: (name: string, version?: string) => string;
|
|
25
|
+
installedAs?: string;
|
|
26
|
+
}): import("../../discover.type.mjs").DiscoverItemResponse | null;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file discover.item leaf — one item a package adds, when it is not an
|
|
5
|
+
* installed component (those keep resolving to their full doc through
|
|
6
|
+
* ../doc).
|
|
7
|
+
*
|
|
8
|
+
* @position api/discover/detail/item — pure projection over the packages and
|
|
9
|
+
* catalog entry resolved by ../../_adapter.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import {KIND_FIELDS} from '../../_adapter.mjs';
|
|
13
|
+
import {defaultVersion} from '../../_catalog-view.mjs';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Find one item of a package: an installed package's own templates, docs,
|
|
17
|
+
* themes, and codemods first, then what a discover source lists for the
|
|
18
|
+
* package. Returns null when neither has it, so the caller can report the
|
|
19
|
+
* component lookup's own error.
|
|
20
|
+
*
|
|
21
|
+
* @param {import('../../_adapter.mjs').InstalledPackage[]} packages
|
|
22
|
+
* @param {string} packageName
|
|
23
|
+
* @param {string} itemName
|
|
24
|
+
* @param {{
|
|
25
|
+
* catalog?: import('../../_catalog-view.mjs').CatalogPackage,
|
|
26
|
+
* version?: string,
|
|
27
|
+
* add?: (name: string, version?: string) => string,
|
|
28
|
+
* installedAs?: string,
|
|
29
|
+
* }} [options]
|
|
30
|
+
* @returns {import('../../discover.type.mjs').DiscoverItemResponse | null}
|
|
31
|
+
*/
|
|
32
|
+
export function item(packages, packageName, itemName, options = {}) {
|
|
33
|
+
const {catalog, version, add, installedAs} = options;
|
|
34
|
+
const pkg = packages.find(p => p.name === packageName);
|
|
35
|
+
if (pkg && (!version || version === pkg.version)) {
|
|
36
|
+
for (const [kind, field] of KIND_FIELDS) {
|
|
37
|
+
if (kind === 'component') continue;
|
|
38
|
+
const names = /** @type {Record<string, unknown>} */ (pkg)[field];
|
|
39
|
+
if (Array.isArray(names) && names.includes(itemName)) {
|
|
40
|
+
return {
|
|
41
|
+
type: 'discover.item',
|
|
42
|
+
data: {
|
|
43
|
+
package: packageName,
|
|
44
|
+
...(pkg.version ? {version: pkg.version} : {}),
|
|
45
|
+
kind,
|
|
46
|
+
name: itemName,
|
|
47
|
+
installed: true,
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const lower = itemName.toLowerCase();
|
|
55
|
+
const found =
|
|
56
|
+
catalog?.contributions.find(c => c.name === itemName) ??
|
|
57
|
+
catalog?.contributions.find(c => c.name.toLowerCase() === lower);
|
|
58
|
+
if (!catalog || !found) return null;
|
|
59
|
+
const shown = version ?? defaultVersion(catalog);
|
|
60
|
+
return {
|
|
61
|
+
type: 'discover.item',
|
|
62
|
+
data: {
|
|
63
|
+
package: packageName,
|
|
64
|
+
...(shown ? {version: shown} : {}),
|
|
65
|
+
kind: found.kind,
|
|
66
|
+
name: found.name,
|
|
67
|
+
...(found.title ? {title: found.title} : {}),
|
|
68
|
+
...(found.summary ? {summary: found.summary} : {}),
|
|
69
|
+
...(found.keywords ? {keywords: found.keywords} : {}),
|
|
70
|
+
installed: pkg != null,
|
|
71
|
+
...(pkg == null && installedAs ? {installedAs} : {}),
|
|
72
|
+
...(pkg == null && !installedAs && add
|
|
73
|
+
? {install: add(packageName, version)}
|
|
74
|
+
: {}),
|
|
75
|
+
source: catalog.source,
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file Tests for the discover.item leaf, a pure projection over installed
|
|
5
|
+
* packages and a source's catalog entry.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {describe, expect, it} from 'vitest';
|
|
9
|
+
import {item} from './item.mjs';
|
|
10
|
+
|
|
11
|
+
/** @type {any[]} */
|
|
12
|
+
const PACKAGES = [
|
|
13
|
+
{
|
|
14
|
+
name: '@acme/widgets',
|
|
15
|
+
category: '@acme/widgets',
|
|
16
|
+
version: '1.2.3',
|
|
17
|
+
components: ['Alpha'],
|
|
18
|
+
templates: ['pages/Home'],
|
|
19
|
+
docs: ['guide'],
|
|
20
|
+
},
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
/** @type {any} */
|
|
24
|
+
const CATALOG = {
|
|
25
|
+
package: '@acme/charts',
|
|
26
|
+
integration: 'acme-charts',
|
|
27
|
+
aliases: [],
|
|
28
|
+
latest: '2.0.0',
|
|
29
|
+
source: 'Acme',
|
|
30
|
+
versions: [],
|
|
31
|
+
contributions: [{kind: 'template', name: 'pages/Report', title: 'Report page'}],
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/** @param {string} name @param {string} [version] */
|
|
35
|
+
const add = (name, version) => `pnpm add ${version ? `${name}@${version}` : name}`;
|
|
36
|
+
|
|
37
|
+
describe('discover.item leaf', () => {
|
|
38
|
+
it("finds an installed package's own template, doc, theme, or codemod", () => {
|
|
39
|
+
expect(item(PACKAGES, '@acme/widgets', 'pages/Home')).toEqual({
|
|
40
|
+
type: 'discover.item',
|
|
41
|
+
data: {
|
|
42
|
+
package: '@acme/widgets',
|
|
43
|
+
version: '1.2.3',
|
|
44
|
+
kind: 'template',
|
|
45
|
+
name: 'pages/Home',
|
|
46
|
+
installed: true,
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('finds an item a source lists, with the command that adds its package', () => {
|
|
52
|
+
expect(
|
|
53
|
+
item(PACKAGES, '@acme/charts', 'pages/report', {catalog: CATALOG, add}),
|
|
54
|
+
).toEqual({
|
|
55
|
+
type: 'discover.item',
|
|
56
|
+
data: {
|
|
57
|
+
package: '@acme/charts',
|
|
58
|
+
version: '2.0.0',
|
|
59
|
+
kind: 'template',
|
|
60
|
+
name: 'pages/Report',
|
|
61
|
+
title: 'Report page',
|
|
62
|
+
installed: false,
|
|
63
|
+
install: 'pnpm add @acme/charts',
|
|
64
|
+
source: 'Acme',
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('returns null when neither the project nor a source has it', () => {
|
|
70
|
+
expect(item(PACKAGES, '@acme/widgets', 'Nope')).toBeNull();
|
|
71
|
+
expect(item(PACKAGES, '@acme/charts', 'Nope', {catalog: CATALOG})).toBeNull();
|
|
72
|
+
});
|
|
73
|
+
});
|
|
@@ -3,19 +3,13 @@
|
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* @param {string} [query]
|
|
6
|
-
* @param {
|
|
7
|
-
* @param {boolean} [options.components]
|
|
8
|
-
* @param {string} [options.lang]
|
|
9
|
-
* @param {boolean} [options.zh]
|
|
6
|
+
* @param {import('./discover.type.mjs').DiscoverOptions} [options]
|
|
10
7
|
* @returns {Promise<
|
|
11
8
|
* import('./discover.type.mjs').DiscoverListResponse |
|
|
12
9
|
* import('./discover.type.mjs').DiscoverDetailResponse |
|
|
13
10
|
* import('./discover.type.mjs').DiscoverDetailDocResponse |
|
|
11
|
+
* import('./discover.type.mjs').DiscoverItemResponse |
|
|
14
12
|
* import('./discover.type.mjs').DiscoverSearchResponse
|
|
15
13
|
* >}
|
|
16
14
|
*/
|
|
17
|
-
export function discover(query?: string, options?:
|
|
18
|
-
components?: boolean | undefined;
|
|
19
|
-
lang?: string | undefined;
|
|
20
|
-
zh?: boolean | undefined;
|
|
21
|
-
}): Promise<import("./discover.type.mjs").DiscoverListResponse | import("./discover.type.mjs").DiscoverDetailResponse | import("./discover.type.mjs").DiscoverDetailDocResponse | import("./discover.type.mjs").DiscoverSearchResponse>;
|
|
15
|
+
export function discover(query?: string, options?: import("./discover.type.mjs").DiscoverOptions): Promise<import("./discover.type.mjs").DiscoverListResponse | import("./discover.type.mjs").DiscoverDetailResponse | import("./discover.type.mjs").DiscoverDetailDocResponse | import("./discover.type.mjs").DiscoverItemResponse | import("./discover.type.mjs").DiscoverSearchResponse>;
|
|
@@ -13,22 +13,25 @@ export const doc = {
|
|
|
13
13
|
name: 'discover',
|
|
14
14
|
namespace: 'cli/api',
|
|
15
15
|
displayName: 'discover()',
|
|
16
|
-
summary:
|
|
16
|
+
summary:
|
|
17
|
+
'Browse and search integrations: the ones a project has and, through discover sources, the ones it could add.',
|
|
17
18
|
description:
|
|
18
|
-
'
|
|
19
|
-
'the
|
|
20
|
-
'
|
|
21
|
-
"
|
|
22
|
-
'
|
|
19
|
+
'Lists the integrations a project loads and, when the project or an integration provides a discover source, ' +
|
|
20
|
+
'the packages it could add, with what each one adds per kind. An @scope/name query shows one package with every ' +
|
|
21
|
+
'version its source knows; @scope/name@version shows one version; @scope/name/Component returns an installed ' +
|
|
22
|
+
"component's validated doc, and any other item path returns that item. A free-text term searches every item and " +
|
|
23
|
+
'package. Discover only reads: it prints the command that adds a package and never runs it.',
|
|
23
24
|
importPath: '@astryxdesign/cli/api',
|
|
24
25
|
signature:
|
|
25
|
-
'discover(query?: string, options?: DiscoverOptions): Promise<DiscoverListResponse | DiscoverDetailResponse | DiscoverDetailDocResponse | DiscoverSearchResponse>',
|
|
26
|
+
'discover(query?: string, options?: DiscoverOptions): Promise<DiscoverListResponse | DiscoverDetailResponse | DiscoverDetailDocResponse | DiscoverItemResponse | DiscoverSearchResponse>',
|
|
26
27
|
keywords: [
|
|
27
28
|
'discover',
|
|
28
29
|
'packages',
|
|
29
30
|
'integrations',
|
|
30
31
|
'external',
|
|
31
32
|
'components',
|
|
33
|
+
'catalog',
|
|
34
|
+
'versions',
|
|
32
35
|
'search',
|
|
33
36
|
],
|
|
34
37
|
params: [
|
|
@@ -36,13 +39,39 @@ export const doc = {
|
|
|
36
39
|
name: 'query',
|
|
37
40
|
type: 'string',
|
|
38
41
|
description:
|
|
39
|
-
'
|
|
42
|
+
'A package (@scope/name, optionally @version), an item path (@scope/name/<item>), or a free-text term. Omit to list packages.',
|
|
40
43
|
},
|
|
41
44
|
{
|
|
42
45
|
name: 'options.components',
|
|
43
46
|
type: 'boolean',
|
|
44
47
|
description:
|
|
45
|
-
'In the CLI package list, print every component of each package instead of the first 10. A display flag for the CLI renderer; the programmatic response is unchanged.',
|
|
48
|
+
'In the CLI package list, print every component, and every other item, of each package instead of the first 10. A display flag for the CLI renderer; the programmatic response is unchanged.',
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: 'options.type',
|
|
52
|
+
type: "'component' | 'template' | 'doc' | 'theme' | 'codemod' | 'agent-doc'",
|
|
53
|
+
description:
|
|
54
|
+
'Only one kind: in the list, packages that add it; in a search, items of that kind.',
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
name: 'options.installed',
|
|
58
|
+
type: 'boolean',
|
|
59
|
+
description:
|
|
60
|
+
'Only what the project has. Cannot be set with options.available.',
|
|
61
|
+
default: 'false',
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
name: 'options.available',
|
|
65
|
+
type: 'boolean',
|
|
66
|
+
description:
|
|
67
|
+
'Only what the project could add. Cannot be set with options.installed.',
|
|
68
|
+
default: 'false',
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
name: 'options.limit',
|
|
72
|
+
type: 'number',
|
|
73
|
+
description: 'Max number of search results, a positive integer.',
|
|
74
|
+
default: '20',
|
|
46
75
|
},
|
|
47
76
|
{
|
|
48
77
|
name: 'options.lang',
|
|
@@ -60,21 +89,27 @@ export const doc = {
|
|
|
60
89
|
{
|
|
61
90
|
type: 'discover.list',
|
|
62
91
|
description:
|
|
63
|
-
'The
|
|
92
|
+
'The installed integrations (name, category, components, version, and a list per other kind they add). With a discover source, meta.available lists what the project could add and meta.sources reports each source. When the list is empty it carries meta.configured.',
|
|
64
93
|
},
|
|
65
94
|
{
|
|
66
95
|
type: 'discover.detail',
|
|
67
|
-
description:
|
|
96
|
+
description:
|
|
97
|
+
'One package: what the shown version adds, whether the project has it, its versions and latest release when a source knows them, and the command that adds it when the project does not have it.',
|
|
68
98
|
},
|
|
69
99
|
{
|
|
70
100
|
type: 'discover.detail.doc',
|
|
71
101
|
description:
|
|
72
|
-
'The validated ComponentDoc for one
|
|
102
|
+
'The validated ComponentDoc for one installed component, for an @scope/name/Component query.',
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
type: 'discover.item',
|
|
106
|
+
description:
|
|
107
|
+
'One item that is not an installed component: its kind, name, the package and version that add it, and whether the project has the package.',
|
|
73
108
|
},
|
|
74
109
|
{
|
|
75
110
|
type: 'discover.search',
|
|
76
111
|
description:
|
|
77
|
-
'The query echoed back plus
|
|
112
|
+
'The query echoed back plus every matching item and package, each with its kind and whether the project has it, even when one name matches exactly or only one item matches; total is set when the limit cut the list.',
|
|
78
113
|
},
|
|
79
114
|
],
|
|
80
115
|
throws: [
|
|
@@ -82,17 +117,21 @@ export const doc = {
|
|
|
82
117
|
code: 'ERR_INVALID_ARGUMENT',
|
|
83
118
|
when: 'the query is a non-string value, or a free-text search is run with an empty query',
|
|
84
119
|
},
|
|
120
|
+
{
|
|
121
|
+
code: 'ERR_INVALID_OPTION',
|
|
122
|
+
when: 'options.type is not a known kind, options.limit is not a positive integer, or options.installed and options.available are both set',
|
|
123
|
+
},
|
|
85
124
|
{
|
|
86
125
|
code: 'ERR_UNKNOWN_PACKAGE',
|
|
87
|
-
when: 'the
|
|
126
|
+
when: 'neither the project nor any discover source has the package',
|
|
88
127
|
},
|
|
89
128
|
{
|
|
90
129
|
code: 'ERR_UNKNOWN_COMPONENT',
|
|
91
|
-
when: 'the
|
|
130
|
+
when: 'the item is not in the named package',
|
|
92
131
|
},
|
|
93
132
|
{
|
|
94
133
|
code: 'ERR_NOT_FOUND',
|
|
95
|
-
when: 'a free-text term matches
|
|
134
|
+
when: 'a free-text term matches nothing, or the requested version is not published',
|
|
96
135
|
},
|
|
97
136
|
{
|
|
98
137
|
code: 'ERR_INVALID_DOC',
|
|
@@ -100,10 +139,14 @@ export const doc = {
|
|
|
100
139
|
},
|
|
101
140
|
],
|
|
102
141
|
examples: [
|
|
103
|
-
{label: 'List packages', code: 'const {data} = await discover();'},
|
|
142
|
+
{label: 'List packages', code: 'const {data, meta} = await discover();'},
|
|
104
143
|
{label: 'Browse a package', code: "await discover('@acme/ui');"},
|
|
144
|
+
{label: 'One version', code: "await discover('@acme/ui@2.1.0');"},
|
|
105
145
|
{label: 'Show a component doc', code: "await discover('@acme/ui/Button');"},
|
|
106
|
-
{
|
|
146
|
+
{
|
|
147
|
+
label: 'Search templates to add',
|
|
148
|
+
code: "await discover('dashboard', {type: 'template', available: true});",
|
|
149
|
+
},
|
|
107
150
|
],
|
|
108
151
|
command: 'discover',
|
|
109
152
|
related: ['component', 'search', 'template'],
|
|
@@ -3,55 +3,193 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* @file Programmatic API for the discover command — dispatcher + barrel.
|
|
5
5
|
*
|
|
6
|
-
* `discover()`
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* owns each response shape:
|
|
6
|
+
* `discover()` browses the integrations a project has and, through discover
|
|
7
|
+
* sources, the ones it could add. It only reads: the package manager installs.
|
|
8
|
+
* Its job is to resolve the project and its sources (via ./_adapter) and route
|
|
9
|
+
* to the leaf that owns each response shape:
|
|
10
10
|
*
|
|
11
|
-
* discover
|
|
12
|
-
* discover
|
|
13
|
-
* discover
|
|
14
|
-
* discover
|
|
11
|
+
* discover -> ./list/list.mjs discover.list
|
|
12
|
+
* discover <package>[@<version>] -> ./detail/detail.mjs discover.detail
|
|
13
|
+
* discover <package>/<Component> -> ./detail/doc/doc.mjs discover.detail.doc
|
|
14
|
+
* discover <package>/<item> -> ./detail/item/item.mjs discover.item
|
|
15
|
+
* discover <words> -> ./search/search.mjs discover.search (always a list)
|
|
15
16
|
*
|
|
16
|
-
*
|
|
17
|
+
* Source results are additive: they ride in `meta.available`/`meta.sources`,
|
|
18
|
+
* in extra fields, or as extra search matches, so every existing field keeps
|
|
19
|
+
* its meaning.
|
|
20
|
+
*
|
|
21
|
+
* @position api/discover — thin router over ./_adapter, ./_catalog-view, and
|
|
22
|
+
* the discover leaves.
|
|
17
23
|
*/
|
|
18
24
|
|
|
19
|
-
import {
|
|
25
|
+
import {
|
|
26
|
+
addCommand,
|
|
27
|
+
callSources,
|
|
28
|
+
declaredDependencies,
|
|
29
|
+
describeInstalled,
|
|
30
|
+
discoverPackages,
|
|
31
|
+
findComponent,
|
|
32
|
+
hasSources,
|
|
33
|
+
} from './_adapter.mjs';
|
|
34
|
+
import {
|
|
35
|
+
availableEntries,
|
|
36
|
+
catalogState,
|
|
37
|
+
searchItems,
|
|
38
|
+
withLatest,
|
|
39
|
+
} from './_catalog-view.mjs';
|
|
20
40
|
import {list} from './list/list.mjs';
|
|
21
41
|
import {detail} from './detail/detail.mjs';
|
|
22
|
-
import {doc} from './detail/doc/doc.mjs';
|
|
42
|
+
import {doc, docFromResult} from './detail/doc/doc.mjs';
|
|
43
|
+
import {item} from './detail/item/item.mjs';
|
|
23
44
|
import {search} from './search/search.mjs';
|
|
24
45
|
import {AstryxError} from '../error.mjs';
|
|
25
46
|
import {ERROR_CODES} from '../../foundation/response/error-codes.mjs';
|
|
47
|
+
import {levenshteinDistance} from '../../foundation/text/string-utils.mjs';
|
|
48
|
+
import {DISCOVER_KINDS} from '../../authoring/discover/parse.mjs';
|
|
49
|
+
|
|
50
|
+
const DEFAULT_LIMIT = 20;
|
|
51
|
+
|
|
52
|
+
/** @type {import('./_adapter.mjs').CatalogResult} */
|
|
53
|
+
const NO_CATALOG = {sources: [], packages: []};
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Split a package-shaped query: `name`, `name@version`, or `name/item`, with an
|
|
57
|
+
* optional `@scope/` prefix on the name.
|
|
58
|
+
* @param {string} query
|
|
59
|
+
* @returns {{scoped: boolean, name: string, version?: string, item?: string}}
|
|
60
|
+
*/
|
|
61
|
+
function splitTarget(query) {
|
|
62
|
+
const scoped = query.startsWith('@');
|
|
63
|
+
const firstSlash = query.indexOf('/');
|
|
64
|
+
let head = query;
|
|
65
|
+
/** @type {string | undefined} */
|
|
66
|
+
let rest;
|
|
67
|
+
const split = scoped
|
|
68
|
+
? firstSlash < 0
|
|
69
|
+
? -1
|
|
70
|
+
: query.indexOf('/', firstSlash + 1)
|
|
71
|
+
: firstSlash;
|
|
72
|
+
if (split > 0) {
|
|
73
|
+
head = query.slice(0, split);
|
|
74
|
+
rest = query.slice(split + 1) || undefined;
|
|
75
|
+
}
|
|
76
|
+
const at = head.indexOf('@', 1);
|
|
77
|
+
return {
|
|
78
|
+
scoped,
|
|
79
|
+
name: at > 0 ? head.slice(0, at) : head,
|
|
80
|
+
...(at > 0 && head.slice(at + 1) ? {version: head.slice(at + 1)} : {}),
|
|
81
|
+
...(rest ? {item: rest} : {}),
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* @param {{type?: unknown, installed?: boolean, available?: boolean, limit?: unknown}} options
|
|
87
|
+
*/
|
|
88
|
+
function checkOptions({type, installed, available, limit}) {
|
|
89
|
+
if (
|
|
90
|
+
type != null &&
|
|
91
|
+
!(/** @type {readonly unknown[]} */ (DISCOVER_KINDS).includes(type))
|
|
92
|
+
) {
|
|
93
|
+
throw new AstryxError(
|
|
94
|
+
`Unknown --type "${String(type)}"`,
|
|
95
|
+
DISCOVER_KINDS.map(kind => ({name: kind, reason: 'item kind'})),
|
|
96
|
+
ERROR_CODES.ERR_INVALID_OPTION,
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
if (installed && available) {
|
|
100
|
+
throw new AstryxError(
|
|
101
|
+
'--installed and --available cannot be used together',
|
|
102
|
+
undefined,
|
|
103
|
+
ERROR_CODES.ERR_INVALID_OPTION,
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
if (
|
|
107
|
+
limit != null &&
|
|
108
|
+
!(typeof limit === 'number' && Number.isInteger(limit) && limit > 0)
|
|
109
|
+
) {
|
|
110
|
+
throw new AstryxError(
|
|
111
|
+
`--limit must be a positive integer, not "${String(limit)}"`,
|
|
112
|
+
undefined,
|
|
113
|
+
ERROR_CODES.ERR_INVALID_OPTION,
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Items a source lists for a package that look like the one asked for: names
|
|
120
|
+
* that contain it, else the closest few by spelling.
|
|
121
|
+
* @param {import('../../authoring/discover/type.js').DiscoverPackage} entry
|
|
122
|
+
* @param {string} wanted
|
|
123
|
+
* @returns {Array<{name: string, reason: string}>}
|
|
124
|
+
*/
|
|
125
|
+
function similarItems(entry, wanted) {
|
|
126
|
+
const lower = wanted.toLowerCase();
|
|
127
|
+
const names = [...new Set(entry.contributions.map(c => c.name))];
|
|
128
|
+
const hits = names.filter(name => name.toLowerCase().includes(lower));
|
|
129
|
+
const picked =
|
|
130
|
+
hits.length > 0
|
|
131
|
+
? hits.slice(0, 5)
|
|
132
|
+
: names
|
|
133
|
+
.map(name => ({
|
|
134
|
+
name,
|
|
135
|
+
distance: levenshteinDistance(lower, name.toLowerCase()),
|
|
136
|
+
}))
|
|
137
|
+
.filter(m => m.distance <= 3)
|
|
138
|
+
.sort((a, b) => a.distance - b.distance)
|
|
139
|
+
.slice(0, 5)
|
|
140
|
+
.map(m => m.name);
|
|
141
|
+
return picked.map(name => ({
|
|
142
|
+
name: `${entry.package}/${name}`,
|
|
143
|
+
reason: 'similar name',
|
|
144
|
+
}));
|
|
145
|
+
}
|
|
26
146
|
|
|
27
147
|
/**
|
|
28
148
|
* @param {string} [query]
|
|
29
|
-
* @param {
|
|
30
|
-
* @param {boolean} [options.components]
|
|
31
|
-
* @param {string} [options.lang]
|
|
32
|
-
* @param {boolean} [options.zh]
|
|
149
|
+
* @param {import('./discover.type.mjs').DiscoverOptions} [options]
|
|
33
150
|
* @returns {Promise<
|
|
34
151
|
* import('./discover.type.mjs').DiscoverListResponse |
|
|
35
152
|
* import('./discover.type.mjs').DiscoverDetailResponse |
|
|
36
153
|
* import('./discover.type.mjs').DiscoverDetailDocResponse |
|
|
154
|
+
* import('./discover.type.mjs').DiscoverItemResponse |
|
|
37
155
|
* import('./discover.type.mjs').DiscoverSearchResponse
|
|
38
156
|
* >}
|
|
39
157
|
*/
|
|
40
158
|
export async function discover(query, options = {}) {
|
|
41
|
-
const {lang = null, zh = false} = options;
|
|
42
|
-
|
|
159
|
+
const {lang = null, zh = false, type, limit} = options;
|
|
160
|
+
checkOptions(options);
|
|
161
|
+
const only = options.installed
|
|
162
|
+
? /** @type {const} */ ('installed')
|
|
163
|
+
: options.available
|
|
164
|
+
? /** @type {const} */ ('available')
|
|
165
|
+
: undefined;
|
|
166
|
+
|
|
167
|
+
const {packages: scanned, configured, project} = await discoverPackages();
|
|
168
|
+
const withSources = hasSources(project);
|
|
169
|
+
const packages = await describeInstalled(project, scanned);
|
|
170
|
+
const declared = declaredDependencies(project);
|
|
171
|
+
const add = addCommand(project);
|
|
43
172
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
if (packages.length === 0) return list(packages, {configured});
|
|
173
|
+
/** @param {{package?: string, version?: string}} [request] */
|
|
174
|
+
const catalogFor = async request =>
|
|
175
|
+
withSources ? await callSources(project, request) : NO_CATALOG;
|
|
48
176
|
|
|
49
|
-
// No query: the
|
|
50
|
-
if (!query
|
|
177
|
+
// No query, or nothing to look through: the list.
|
|
178
|
+
if (!query || (packages.length === 0 && !withSources)) {
|
|
179
|
+
if (!withSources) return list(packages, {configured, type, only});
|
|
180
|
+
const catalog = await catalogFor();
|
|
181
|
+
return list(withLatest(packages, catalog), {
|
|
182
|
+
configured,
|
|
183
|
+
type,
|
|
184
|
+
only,
|
|
185
|
+
available: availableEntries(catalog, packages, declared),
|
|
186
|
+
sources: catalog.sources,
|
|
187
|
+
});
|
|
188
|
+
}
|
|
51
189
|
|
|
52
|
-
// A non-string (truthy) query would crash
|
|
53
|
-
//
|
|
54
|
-
//
|
|
190
|
+
// A non-string (truthy) query would crash the parsing below with a raw
|
|
191
|
+
// TypeError (no ERR_* code → downgrades to ERR_UNKNOWN). The CLI only ever
|
|
192
|
+
// passes a string, but the public API must fail with a code.
|
|
55
193
|
if (typeof query !== 'string') {
|
|
56
194
|
throw new AstryxError(
|
|
57
195
|
`Invalid query "${String(query)}"`,
|
|
@@ -60,17 +198,63 @@ export async function discover(query, options = {}) {
|
|
|
60
198
|
);
|
|
61
199
|
}
|
|
62
200
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
201
|
+
const target = splitTarget(query);
|
|
202
|
+
const installedNames = new Set(packages.map(p => p.name));
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* One package, one version, or one item, once `target.name` is known to be
|
|
206
|
+
* a package the project or a source has.
|
|
207
|
+
* @param {import('./_adapter.mjs').CatalogResult} catalog
|
|
208
|
+
*/
|
|
209
|
+
const packageView = async catalog => {
|
|
210
|
+
const entry = catalog.packages.find(p => p.package === target.name);
|
|
211
|
+
const installedAs = entry
|
|
212
|
+
? catalogState(entry, installedNames, declared).installedAs
|
|
213
|
+
: undefined;
|
|
214
|
+
const context = {catalog: entry, version: target.version, add, installedAs};
|
|
215
|
+
if (!target.item) return detail(packages, target.name, context);
|
|
216
|
+
const found = item(packages, target.name, target.item, context);
|
|
217
|
+
if (found) return found;
|
|
218
|
+
// Only an installed package has docs to fall back to. For one that is
|
|
219
|
+
// only in a source, the item is what is unknown, not the package.
|
|
220
|
+
if (entry && !packages.some(p => p.name === target.name)) {
|
|
221
|
+
throw new AstryxError(
|
|
222
|
+
`"${target.item}" not found in ${target.name}`,
|
|
223
|
+
similarItems(entry, target.item),
|
|
224
|
+
ERROR_CODES.ERR_UNKNOWN_COMPONENT,
|
|
225
|
+
);
|
|
70
226
|
}
|
|
71
|
-
return
|
|
227
|
+
return await doc(packages, target.name, target.item, {lang, zh});
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
// An installed component keeps resolving to its full doc, before any source
|
|
231
|
+
// is asked anything.
|
|
232
|
+
const installedPkg = packages.find(p => p.name === target.name);
|
|
233
|
+
if (installedPkg && target.item && !target.version) {
|
|
234
|
+
const resolved = findComponent([installedPkg], target.item);
|
|
235
|
+
if (resolved) return await docFromResult(resolved, {lang, zh});
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (target.scoped) {
|
|
239
|
+
return await packageView(
|
|
240
|
+
await catalogFor({package: target.name, version: target.version}),
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const listing = await catalogFor();
|
|
245
|
+
const isPackage =
|
|
246
|
+
installedPkg != null ||
|
|
247
|
+
listing.packages.some(p => p.package === target.name);
|
|
248
|
+
if (isPackage && (target.version || target.item || target.name === query)) {
|
|
249
|
+
return await packageView(
|
|
250
|
+
await catalogFor({package: target.name, version: target.version}),
|
|
251
|
+
);
|
|
72
252
|
}
|
|
73
253
|
|
|
74
|
-
|
|
75
|
-
|
|
254
|
+
return await search(packages, query, {
|
|
255
|
+
items: searchItems(packages, listing, declared),
|
|
256
|
+
type,
|
|
257
|
+
only,
|
|
258
|
+
limit: limit ?? DEFAULT_LIMIT,
|
|
259
|
+
});
|
|
76
260
|
}
|
|
@@ -68,10 +68,19 @@ describe('discover() dispatcher routing', () => {
|
|
|
68
68
|
it('free-text query with multiple matches -> discover.search envelope', async () => {
|
|
69
69
|
// 'a' is a substring of both Alpha and Beta (no exact match), so the search
|
|
70
70
|
// leaf returns the multi-match discover.search envelope. Proves free-text
|
|
71
|
-
// routing reaches the search leaf and projects its envelope.
|
|
71
|
+
// routing reaches the search leaf and projects its envelope. Search also
|
|
72
|
+
// matches package names, so the package itself is listed after them.
|
|
72
73
|
const r = await discover('a');
|
|
73
74
|
expect(r.type).toBe('discover.search');
|
|
74
|
-
expect(
|
|
75
|
+
expect(
|
|
76
|
+
r.data.matches.filter(m => m.kind === 'component').map(m => m.component),
|
|
77
|
+
).toEqual(['Alpha', 'Beta']);
|
|
78
|
+
expect(r.data.matches).toContainEqual({
|
|
79
|
+
package: '@acme/widgets',
|
|
80
|
+
component: '@acme/widgets',
|
|
81
|
+
kind: 'package',
|
|
82
|
+
installed: true,
|
|
83
|
+
});
|
|
75
84
|
});
|
|
76
85
|
|
|
77
86
|
it('free-text query with no match still routes to the search leaf (coded not-found)', async () => {
|