@astryxdesign/cli 0.6.3-canary.ea2f048 → 0.6.3-canary.ee13359
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/README.md +114 -76
- package/api/blog/blog.doc.mjs +1 -0
- package/api/build/build.doc.mjs +4 -3
- package/api/build/build.test.mjs +14 -3
- package/api/build/build.type.d.mts +36 -2
- package/api/build/build.type.mjs +25 -4
- package/api/build/help/help.d.mts +8 -5
- package/api/build/help/help.mjs +56 -6
- package/api/component/_adapter.d.mts +6 -12
- package/api/component/_adapter.mjs +20 -10
- package/api/component/component.doc.mjs +13 -3
- package/api/component/component.mjs +91 -14
- package/api/component/component.test.mjs +38 -0
- package/api/component/component.type.d.mts +22 -11
- package/api/component/component.type.mjs +32 -24
- package/api/component/detail/blocks/blocks.d.mts +2 -1
- package/api/component/detail/blocks/blocks.mjs +4 -3
- package/api/component/list/list.d.mts +0 -5
- package/api/component/list/list.mjs +40 -11
- package/api/discover/discover.doc.mjs +2 -1
- package/api/discover/discover.type.d.mts +4 -4
- package/api/discover/discover.type.mjs +10 -10
- package/api/docs/_adapter.d.mts +230 -41
- package/api/docs/_adapter.mjs +734 -108
- package/api/docs/compiled-topics.test.mjs +78 -0
- package/api/docs/detail/detail.mjs +22 -63
- package/api/docs/detail/section/section.d.mts +1 -1
- package/api/docs/detail/section/section.mjs +54 -19
- package/api/docs/detail/section/section.test.mjs +50 -0
- package/api/docs/docs.d.mts +10 -3
- package/api/docs/docs.doc.mjs +54 -16
- package/api/docs/docs.mjs +53 -10
- package/api/docs/docs.test.mjs +164 -4
- package/api/docs/docs.type.d.mts +205 -5
- package/api/docs/docs.type.mjs +137 -11
- package/api/docs/index/index.d.mts +18 -0
- package/api/docs/index/index.mjs +40 -0
- package/api/docs/index/index.test.mjs +62 -0
- package/api/docs/integration-tree.test.mjs +547 -0
- package/api/docs/integrationDocs.test.mjs +114 -8
- package/api/docs/list/list.mjs +28 -12
- package/api/docs/node/node.d.mts +43 -0
- package/api/docs/node/node.mjs +192 -0
- package/api/doctor/doctor.d.mts +99 -1
- package/api/doctor/doctor.doc.mjs +1 -0
- package/api/doctor/doctor.mjs +544 -1
- package/api/doctor/doctor.test.mjs +610 -1
- package/api/gap-report/gap-report.doc.mjs +8 -4
- package/api/hook/_adapter.mjs +19 -5
- package/api/hook/hook.doc.mjs +1 -0
- package/api/hook/hook.type.d.mts +3 -3
- package/api/hook/hook.type.mjs +11 -11
- package/api/hook/list/list.d.mts +2 -2
- package/api/hook/list/list.mjs +69 -17
- package/api/index.d.mts +1 -1
- package/api/index.mjs +1 -0
- package/api/init/init.doc.mjs +6 -1
- package/api/init/init.test.mjs +41 -1
- package/api/init/remove/remove.mjs +1 -1
- package/api/init/run/run.mjs +20 -10
- package/api/integration/add-contribution.component-names.test.mjs +120 -0
- package/api/integration/add-contribution.d.mts +2 -1
- package/api/integration/add-contribution.mjs +130 -15
- package/api/integration/add-contribution.test.mjs +258 -7
- package/api/integration/add-theme.mjs +34 -64
- package/api/integration/add-theme.test.mjs +105 -21
- package/api/integration/authoring-checks.mjs +108 -31
- package/api/integration/authoring-checks.test.mjs +171 -6
- package/api/integration/authoring-checks.type.d.mts +3 -1
- package/api/integration/authoring-checks.type.mjs +3 -1
- package/api/integration/integration-authoring.type.d.mts +3 -1
- package/api/integration/integration-authoring.type.mjs +2 -0
- package/api/integration/integration-block-exports.test.mjs +10 -6
- package/api/integration/integrationAdd.doc.mjs +14 -4
- package/api/integration/integrationAddAgentDoc.doc.mjs +1 -0
- package/api/integration/integrationAddCodemod.doc.mjs +1 -0
- package/api/integration/integrationAddComponent.doc.mjs +2 -1
- package/api/integration/integrationAddDoc.doc.mjs +8 -1
- package/api/integration/integrationAddTemplate.doc.mjs +1 -0
- package/api/integration/integrationAddTheme.doc.mjs +6 -5
- package/api/integration/integrationComponentConflicts.doc.mjs +1 -0
- package/api/integration/integrationDocConflicts.doc.mjs +2 -1
- package/api/integration/integrationPackCheck.doc.mjs +2 -1
- package/api/integration/integrationTemplateConflicts.doc.mjs +7 -5
- package/api/integration/pack-check.mjs +83 -7
- package/api/integration/pack-check.test.mjs +387 -47
- package/api/integration/pack-check.type.d.mts +26 -2
- package/api/integration/pack-check.type.mjs +14 -1
- package/api/integration/summarizeIssues.doc.mjs +1 -0
- package/api/integration/validate-integration-fixes.test.mjs +1389 -0
- package/api/integration/validate-integration.mjs +52 -102
- package/api/integration/validate-integration.test.mjs +179 -26
- package/api/integration/validate-unread-theme-folders.test.mjs +110 -0
- package/api/integration/validateIntegration.doc.mjs +3 -2
- package/api/json/assertResponse.doc.mjs +1 -0
- package/api/json/envelope-types.test.mjs +76 -0
- package/api/json/index.ts +2 -0
- package/api/json/isError.doc.mjs +1 -0
- package/api/json/parseResponse.doc.mjs +3 -2
- package/api/layout/_adapter.mjs +20 -5
- package/api/layout/expand/expand.mjs +7 -5
- package/api/layout/expand/expand.path-safety.test.mjs +53 -0
- package/api/layout/grammar/grammar.mjs +2 -1
- package/api/layout/layoutCheck.doc.mjs +1 -0
- package/api/layout/layoutExpand.doc.mjs +2 -1
- package/api/layout/layoutGrammar.doc.mjs +1 -0
- package/api/search/search-return-type.test.mjs +54 -0
- package/api/search/search.d.mts +29 -11
- package/api/search/search.doc.mjs +8 -2
- package/api/search/search.mjs +337 -41
- package/api/search/search.test.mjs +124 -1
- package/api/search/search.type.d.mts +15 -3
- package/api/search/search.type.mjs +5 -2
- package/api/swizzle/copy/copy.mjs +28 -11
- package/api/swizzle/swizzle.doc.mjs +2 -1
- package/api/swizzle/swizzle.type.d.mts +2 -2
- package/api/swizzle/swizzle.type.mjs +2 -2
- package/api/template/copy/copy.mjs +17 -23
- package/api/template/copy/copy.test.mjs +17 -0
- package/api/template/list/list.mjs +1 -0
- package/api/template/template-integration.test.mjs +1022 -3
- package/api/template/template-suffix.test.mjs +41 -21
- package/api/template/template.d.mts +1 -1
- package/api/template/template.doc.mjs +30 -8
- package/api/template/template.mjs +45 -8
- package/api/template/template.type.d.mts +12 -14
- package/api/template/template.type.mjs +15 -14
- package/api/theme/_adapter.d.mts +2 -3
- package/api/theme/_adapter.mjs +4 -5
- package/api/theme/add/add.binary.test.mjs +84 -0
- package/api/theme/add/add.mjs +20 -3
- package/api/theme/add/add.staging.test.mjs +66 -0
- package/api/theme/add/add.test.mjs +14 -1
- package/api/theme/build/build.mjs +133 -42
- package/api/theme/build/build.public-component-vars.test.mjs +1 -1
- package/api/theme/build/build.receipt-doc.test.mjs +111 -0
- package/api/theme/build/build.test.mjs +127 -0
- package/api/theme/build/font-warning.mjs +3 -3
- package/api/theme/build/font-warning.test.mjs +5 -2
- package/api/theme/generateTonalPalette.doc.mjs +1 -0
- package/api/theme/integration-themes.test.mjs +39 -28
- package/api/theme/list/list.test.mjs +19 -20
- package/api/theme/listThemes.doc.mjs +6 -5
- package/api/theme/palette/generate/generate.mjs +8 -3
- package/api/theme/palette/generate/generate.test.mjs +96 -0
- package/api/theme/palette/generate/generator.d.mts +10 -13
- package/api/theme/palette/generate/generator.mjs +15 -4
- package/api/theme/palette/generate/generator.test.mjs +10 -0
- package/api/theme/template/template.mjs +11 -2
- package/api/theme/template/template.test.mjs +20 -0
- package/api/theme/theme.type.d.mts +170 -11
- package/api/theme/theme.type.mjs +94 -27
- package/api/theme/themeAdd.doc.mjs +4 -3
- package/api/theme/themeBuild.doc.mjs +8 -4
- package/api/theme/themeList.doc.mjs +6 -3
- package/api/theme/themeListAvailable.doc.mjs +5 -3
- package/api/theme/themePaletteGenerate.doc.mjs +1 -0
- package/api/theme/themeTargets.doc.mjs +1 -0
- package/api/theme/themeTemplate.doc.mjs +6 -2
- package/api/upgrade/_adapter.d.mts +32 -5
- package/api/upgrade/_adapter.mjs +139 -22
- package/api/upgrade/list/list.mjs +2 -1
- package/api/upgrade/list/list.test.mjs +73 -0
- package/api/upgrade/project-context.test.mjs +272 -0
- package/api/upgrade/provider-agreement.test.mjs +152 -0
- package/api/upgrade/run/run.mjs +356 -59
- package/api/upgrade/status/status.mjs +2 -2
- package/api/upgrade/upgrade.doc.mjs +12 -5
- package/api/upgrade/upgrade.type.d.mts +43 -5
- package/api/upgrade/upgrade.type.mjs +27 -11
- package/assets/codemods/__tests__/runner.test.mjs +330 -8
- package/assets/codemods/integration-discovery.mjs +48 -4
- package/assets/codemods/integration-discovery.test.mjs +73 -0
- package/assets/codemods/integration-runner.mjs +56 -4
- package/assets/codemods/integration-runner.protection.test.mjs +153 -0
- package/assets/codemods/run-codemod.mjs +177 -34
- package/assets/codemods/runner.mjs +350 -102
- package/assets/codemods/term-log.mjs +32 -8
- package/assets/codemods/term-log.test.mjs +19 -1
- package/assets/codemods/transform-prop.mjs +109 -0
- package/assets/codemods/transform-prop.test.mjs +95 -0
- package/assets/codemods/transforms/next/__tests__/migrate-native-picker-to-presentation.test.mjs +63 -0
- package/assets/codemods/transforms/next/__tests__/migrate-theme-catalog-to-descriptors.test.mjs +220 -0
- package/assets/codemods/transforms/next/index.mjs +19 -1
- package/assets/codemods/transforms/next/migrate-native-picker-to-presentation.mjs +148 -0
- package/assets/codemods/transforms/next/migrate-theme-catalog-to-descriptors.mjs +141 -0
- package/assets/codemods/transforms/v0.0.14/__tests__/rename-status-variants.test.mjs +86 -165
- package/assets/codemods/transforms/v0.0.14/rename-status-variants.mjs +72 -210
- package/assets/codemods/transforms/v0.1.8/__tests__/rename-avatar-size-scale.test.mjs +83 -115
- package/assets/codemods/transforms/v0.1.8/rename-avatar-size-scale.mjs +57 -186
- package/assets/codemods/transforms/v0.3.0/__tests__/unwrap-authoring-factories.test.mjs +27 -5
- package/assets/codemods/transforms/v0.3.0/unwrap-authoring-factories.mjs +20 -5
- package/assets/codemods/transforms/v0.6.0/__tests__/next-codemods.test.mjs +47 -0
- package/assets/codemods/transforms/v0.6.0/rename-resizable-pixel-bounds.mjs +57 -10
- package/assets/docs/README.md +9 -0
- package/assets/docs/authoring.doc.mjs +14 -0
- package/assets/docs/getting-started.doc.mjs +2 -2
- package/assets/docs/principles.doc.mjs +6 -6
- package/assets/docs/styling-libraries.doc.mjs +3 -3
- package/assets/docs/styling.doc.mjs +4 -4
- package/assets/docs/theme.doc.mjs +4 -4
- package/assets/docs/tokens.doc.mjs +1 -1
- package/assets/docs/tree/api.doc.mjs +30 -0
- package/assets/docs/tree/cli.doc.mjs +23 -0
- package/assets/docs/tree/commands.doc.mjs +25 -0
- package/assets/docs/{cli-integrations.doc.mjs → tree/integrations.doc.mjs} +124 -25
- package/assets/docs/tree/integrations.test.mjs +62 -0
- package/assets/docs/tree/writing-docs.doc.mjs +286 -0
- package/assets/docs/working-with-ai.doc.mjs +1 -1
- package/assets/templates/blocks/components/DateInput/DateInputDateRange.tsx +1 -1
- package/assets/templates/blocks/components/Item/ItemDocumentTabs.doc.mjs +14 -0
- package/assets/templates/blocks/components/Item/ItemDocumentTabs.tsx +100 -0
- package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaInlineRail.doc.mjs +14 -0
- package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaInlineRail.tsx +61 -0
- package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaOverscrollChaining.doc.mjs +14 -0
- package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaOverscrollChaining.tsx +126 -0
- package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaShowcase.doc.mjs +15 -0
- package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaShowcase.tsx +86 -0
- package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyGroupHeaders.doc.mjs +14 -0
- package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyGroupHeaders.tsx +99 -0
- package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyPassthrough.doc.mjs +14 -0
- package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyPassthrough.tsx +122 -0
- package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaTwoAxisBoard.doc.mjs +14 -0
- package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaTwoAxisBoard.tsx +95 -0
- package/assets/templates/blocks/components/TimeInput/TimeInputConstrained.tsx +1 -0
- package/assets/templates/pages/table-tree/page.tsx +1704 -0
- package/assets/templates/pages/table-tree/template.doc.mjs +12 -0
- package/assets/templates/themes/butter/butterTheme.doc.mjs +11 -0
- package/assets/templates/themes/chocolate/chocolateTheme.doc.mjs +11 -0
- package/assets/templates/themes/gothic/gothicTheme.doc.mjs +11 -0
- package/assets/templates/themes/matcha/matchaTheme.doc.mjs +11 -0
- package/assets/templates/themes/neutral/neutralTheme.doc.mjs +11 -0
- package/assets/templates/themes/stone/stoneTheme.doc.mjs +11 -0
- package/assets/templates/themes/y2k/y2kTheme.doc.mjs +11 -0
- package/authoring/_shared/contract.ts +22 -0
- package/authoring/codemod/codemod.doc.mjs +7 -2
- package/authoring/codemod/parse.d.mts +8 -8
- package/authoring/codemod/parse.mjs +8 -6
- package/authoring/codemod/type.ts +12 -0
- package/authoring/config/config.doc.mjs +2 -2
- package/authoring/config/debug-composition.test.mjs +92 -0
- package/authoring/config/parse.d.mts +13 -13
- package/authoring/config/parse.mjs +8 -8
- package/authoring/config/type.ts +18 -6
- package/authoring/debug/debug.doc.d.mts +11 -0
- package/authoring/debug/debug.doc.mjs +182 -0
- package/authoring/debug/parse.d.mts +8 -8
- package/authoring/debug/parse.mjs +3 -3
- package/authoring/doctypes/_schema.d.mts +718 -23
- package/authoring/doctypes/_schema.mjs +519 -39
- package/authoring/doctypes/base/graph-fields.doc.d.mts +9 -0
- package/authoring/doctypes/base/graph-fields.doc.mjs +64 -0
- package/authoring/doctypes/base/type.ts +41 -0
- package/authoring/doctypes/command/command.doc.mjs +4 -3
- package/authoring/doctypes/command/parse.d.mts +2 -2
- package/authoring/doctypes/command/parse.mjs +1 -1
- package/authoring/doctypes/command/type.ts +5 -4
- package/authoring/doctypes/component/component.doc.mjs +6 -3
- package/authoring/doctypes/component/parse.d.mts +2 -2
- package/authoring/doctypes/component/parse.mjs +1 -1
- package/authoring/doctypes/component/type.ts +6 -5
- package/authoring/doctypes/doctypes-new.test.mjs +48 -6
- package/authoring/doctypes/enum/enum.doc.mjs +1 -1
- package/authoring/doctypes/enum/parse.d.mts +2 -2
- package/authoring/doctypes/enum/parse.mjs +1 -1
- package/authoring/doctypes/enum/type.ts +4 -2
- package/authoring/doctypes/function/function.doc.mjs +7 -2
- package/authoring/doctypes/function/parse.d.mts +2 -2
- package/authoring/doctypes/function/parse.mjs +1 -1
- package/authoring/doctypes/function/type.ts +9 -4
- package/authoring/doctypes/hook/hook.doc.mjs +4 -0
- package/authoring/doctypes/hook/parse.d.mts +2 -2
- package/authoring/doctypes/hook/parse.mjs +1 -1
- package/authoring/doctypes/hook/type.ts +5 -4
- package/authoring/doctypes/legacy.d.mts +8 -6
- package/authoring/doctypes/legacy.mjs +5 -4
- package/authoring/doctypes/load-contract.test.mjs +208 -0
- package/authoring/doctypes/namespace/namespace.doc.d.mts +9 -0
- package/authoring/doctypes/namespace/namespace.doc.mjs +128 -0
- package/authoring/doctypes/namespace/parse.d.mts +12 -0
- package/authoring/doctypes/namespace/parse.mjs +25 -0
- package/authoring/doctypes/namespace/parse.test.mjs +163 -0
- package/authoring/doctypes/namespace/type.ts +74 -0
- package/authoring/doctypes/parse.d.mts +22 -18
- package/authoring/doctypes/parse.mjs +22 -11
- package/authoring/doctypes/parse.test.mjs +77 -3
- package/authoring/doctypes/reference/parse.d.mts +2 -2
- package/authoring/doctypes/reference/parse.mjs +8 -5
- package/authoring/doctypes/reference/reference.doc.mjs +20 -5
- package/authoring/doctypes/reference/type.ts +53 -5
- package/authoring/doctypes/schema/parse.d.mts +2 -2
- package/authoring/doctypes/schema/parse.mjs +1 -1
- package/authoring/doctypes/schema/schema.doc.mjs +1 -1
- package/authoring/doctypes/schema/type.ts +4 -4
- package/authoring/doctypes/template/parse.d.mts +94 -1
- package/authoring/doctypes/template/parse.mjs +40 -2
- package/authoring/doctypes/template/parse.test.mjs +26 -2
- package/authoring/doctypes/template/template.doc.mjs +13 -3
- package/authoring/doctypes/template/type.ts +13 -2
- package/authoring/doctypes/theme/parse.d.mts +35 -0
- package/authoring/doctypes/theme/parse.mjs +76 -0
- package/authoring/doctypes/theme/theme.doc.d.mts +9 -0
- package/authoring/doctypes/theme/theme.doc.mjs +79 -0
- package/authoring/doctypes/theme/type.ts +42 -0
- package/authoring/doctypes/types.ts +12 -10
- package/authoring/gap-report/gap-report.doc.d.mts +12 -0
- package/authoring/gap-report/gap-report.doc.mjs +183 -0
- package/authoring/gap-report/parse.d.mts +10 -10
- package/authoring/gap-report/parse.mjs +6 -6
- package/authoring/gap-report/type.ts +1 -1
- package/authoring/identity/identity.doc.d.mts +9 -0
- package/authoring/identity/identity.doc.mjs +61 -0
- package/authoring/identity/type.ts +132 -0
- package/authoring/index.d.mts +2 -0
- package/authoring/index.d.ts +52 -17
- package/authoring/index.mjs +3 -1
- package/authoring/integration/integration.doc.mjs +15 -8
- package/authoring/integration/parse.d.mts +2 -2
- package/authoring/integration/parse.mjs +1 -1
- package/authoring/integration/parse.test.mjs +10 -1
- package/authoring/integration/schema.d.mts +6 -4
- package/authoring/integration/schema.mjs +9 -3
- package/authoring/integration/type.ts +19 -8
- package/authoring/shadcn/receipt.d.mts +6 -6
- package/clients/cli/__tests__/cliManifest.test.ts +27 -29
- package/clients/cli/command-load-failure.test.mjs +83 -0
- package/clients/cli/commands/blog.doc.mjs +1 -1
- package/clients/cli/commands/blog.mjs +23 -8
- package/clients/cli/commands/blog.test.mjs +42 -1
- package/clients/cli/commands/build-theme.adaptations.test.mjs +100 -1
- package/clients/cli/commands/build-theme.ascii-output.test.mjs +161 -0
- package/clients/cli/commands/build-theme.flag-docs.test.mjs +110 -0
- package/clients/cli/commands/build-theme.mjs +16 -50
- package/clients/cli/commands/build-theme.path-safety.test.mjs +86 -1
- package/clients/cli/commands/build-theme.variants.test.mjs +76 -0
- package/clients/cli/commands/build.doc.mjs +5 -2
- package/clients/cli/commands/build.exit-codes-doc.test.mjs +50 -0
- package/clients/cli/commands/build.mjs +37 -49
- package/clients/cli/commands/build.playbook.test.mjs +75 -0
- package/clients/cli/commands/build.text-fields.test.mjs +40 -0
- package/clients/cli/commands/component/index.mjs +3 -8
- package/clients/cli/commands/component-ownership.test.mjs +3 -3
- package/clients/cli/commands/component-package.test.mjs +46 -0
- package/clients/cli/commands/component-resolution.test.mjs +21 -0
- package/clients/cli/commands/component.doc.mjs +1 -1
- package/clients/cli/commands/component.test.mjs +19 -0
- package/clients/cli/commands/detail-levels.test.mjs +2 -2
- package/clients/cli/commands/discover.broken-integration.test.mjs +52 -5
- package/clients/cli/commands/discover.components-flag.test.mjs +97 -0
- package/clients/cli/commands/discover.doc.mjs +5 -3
- package/clients/cli/commands/discover.mjs +4 -4
- package/clients/cli/commands/discover.text-projection.test.mjs +103 -0
- package/clients/cli/commands/docs.doc.mjs +28 -6
- package/clients/cli/commands/docs.mjs +238 -24
- package/clients/cli/commands/docs.test.mjs +193 -1
- package/clients/cli/commands/doctor-integration-components.doc.mjs +1 -1
- package/clients/cli/commands/doctor-integration-docs.doc.mjs +3 -3
- package/clients/cli/commands/doctor-integration-templates.doc.mjs +15 -8
- package/clients/cli/commands/doctor-integration-validate.doc.mjs +1 -1
- package/clients/cli/commands/doctor-integration.doc.mjs +1 -1
- package/clients/cli/commands/doctor-integration.package-json.test.mjs +53 -0
- package/clients/cli/commands/doctor-integration.test.mjs +83 -8
- package/clients/cli/commands/doctor.doc.mjs +1 -1
- package/clients/cli/commands/doctor.mjs +30 -25
- package/clients/cli/commands/doctor.test.mjs +42 -0
- package/clients/cli/commands/gap-report.doc.mjs +17 -6
- package/clients/cli/commands/gap-report.test.mjs +72 -0
- package/clients/cli/commands/hook/index.mjs +7 -17
- package/clients/cli/commands/hook.doc.mjs +1 -1
- package/clients/cli/commands/hook.text-projection.test.mjs +45 -0
- package/clients/cli/commands/init.doc.mjs +20 -9
- package/clients/cli/commands/init.flag-help.test.mjs +153 -0
- package/clients/cli/commands/integration-add.controls.test.mjs +132 -0
- package/clients/cli/commands/integration-add.doc.mjs +32 -6
- package/clients/cli/commands/integration-authoring.test.mjs +13 -9
- package/clients/cli/commands/integration-pack.doc.mjs +1 -1
- package/clients/cli/commands/integration-real-world.test.mjs +3 -9
- package/clients/cli/commands/integration.doc.mjs +1 -1
- package/clients/cli/commands/integration.mjs +1 -0
- package/clients/cli/commands/interactive-guard.test.mjs +101 -24
- package/clients/cli/commands/json-contract.test.mjs +33 -0
- package/clients/cli/commands/layout-check.doc.mjs +15 -4
- package/clients/cli/commands/layout-expand.doc.mjs +22 -5
- package/clients/cli/commands/layout-grammar.doc.mjs +1 -1
- package/clients/cli/commands/layout.doc.mjs +3 -3
- package/clients/cli/commands/layout.mjs +21 -9
- package/clients/cli/commands/layout.path-help.test.mjs +33 -0
- package/clients/cli/commands/layout.stdin-cap.test.mjs +47 -0
- package/clients/cli/commands/layout.text-fields.test.mjs +39 -0
- package/clients/cli/commands/manifest.doc.mjs +1 -1
- package/clients/cli/commands/no-prompt-wording.test.mjs +94 -0
- package/clients/cli/commands/search.doc.mjs +7 -4
- package/clients/cli/commands/search.mjs +28 -9
- package/clients/cli/commands/search.test.mjs +75 -0
- package/clients/cli/commands/setup-nudge.test.mjs +6 -0
- package/clients/cli/commands/swizzle.doc.mjs +3 -2
- package/clients/cli/commands/swizzle.path-safety.test.mjs +42 -0
- package/clients/cli/commands/template.doc.mjs +52 -13
- package/clients/cli/commands/template.flag-help.test.mjs +117 -0
- package/clients/cli/commands/template.mjs +4 -91
- package/clients/cli/commands/template.path-help.test.mjs +40 -0
- package/clients/cli/commands/text-json-parity.test.mjs +719 -0
- package/clients/cli/commands/theme-add.doc.mjs +4 -3
- package/clients/cli/commands/theme-build.doc.mjs +8 -7
- package/clients/cli/commands/theme-list.doc.mjs +2 -2
- package/clients/cli/commands/theme-palette-generate.doc.mjs +9 -5
- package/clients/cli/commands/theme-palette-generate.test.mjs +19 -0
- package/clients/cli/commands/theme-palette.doc.mjs +1 -1
- package/clients/cli/commands/theme-targets.behavior.test.mjs +4 -3
- package/clients/cli/commands/theme-targets.doc.mjs +1 -1
- package/clients/cli/commands/theme-template.behavior.test.mjs +12 -0
- package/clients/cli/commands/theme-template.doc.mjs +2 -2
- package/clients/cli/commands/theme.doc.mjs +1 -1
- package/clients/cli/commands/upgrade.ascii-output.test.mjs +87 -0
- package/clients/cli/commands/upgrade.doc.mjs +22 -10
- package/clients/cli/commands/upgrade.file-protection.test.mjs +228 -0
- package/clients/cli/commands/upgrade.flag-help.test.mjs +188 -0
- package/clients/cli/commands/upgrade.hook-output.test.mjs +88 -0
- package/clients/cli/commands/upgrade.mjs +29 -7
- package/clients/cli/formatters/index.mjs +164 -1
- package/clients/cli/formatters/index.test.mjs +97 -0
- package/clients/cli/index.mjs +21 -30
- package/clients/cli/latest-version-env.test.mjs +50 -0
- package/clients/cli/lib/cli-error.test.mjs +7 -0
- package/clients/cli/lib/component-format.mjs +9 -9
- package/clients/cli/lib/component-format.test.mjs +1 -1
- package/clients/cli/lib/define-command.mjs +32 -6
- package/clients/cli/lib/doc-text-ascii.test.mjs +82 -0
- package/clients/cli/lib/exit-codes.test.mjs +97 -0
- package/clients/cli/lib/hook-format.mjs +19 -10
- package/clients/cli/lib/json-shim.mjs +38 -2
- package/clients/cli/lib/json-shim.test.mjs +83 -0
- package/clients/cli/lib/manifest.d.ts +2 -0
- package/clients/cli/lib/manifest.mjs +36 -2
- package/clients/cli/lib/manifest.test.mjs +17 -0
- package/foundation/agent-docs/agent-docs.d.mts +4 -0
- package/foundation/agent-docs/agent-docs.mjs +70 -3
- package/foundation/agent-docs/agent-docs.path-safety.test.mjs +266 -4
- package/foundation/agent-docs/agent-docs.test.mjs +10 -1
- package/foundation/config/integration-debug.test.mjs +28 -3
- package/foundation/config/project-themes.test.mjs +11 -19
- package/foundation/config/project.d.mts +20 -11
- package/foundation/config/project.mjs +263 -91
- package/foundation/config/project.test.mjs +270 -21
- package/foundation/discovery/authoring-self-docs.d.mts +75 -0
- package/foundation/discovery/authoring-self-docs.mjs +224 -0
- package/foundation/discovery/authoring-self-docs.test.mjs +165 -0
- package/foundation/discovery/authoring-surface.d.mts +74 -0
- package/foundation/discovery/authoring-surface.mjs +525 -0
- package/foundation/discovery/authoring-surface.test.mjs +392 -0
- package/foundation/discovery/cli-self-docs.d.mts +119 -0
- package/foundation/discovery/cli-self-docs.mjs +490 -0
- package/foundation/discovery/cli-self-docs.test.mjs +375 -0
- package/foundation/discovery/component-discovery.d.mts +39 -1
- package/foundation/discovery/component-discovery.mjs +50 -1
- package/foundation/discovery/component-loader.d.mts +35 -38
- package/foundation/discovery/component-loader.mjs +53 -222
- package/foundation/discovery/docs-discovery.d.mts +116 -11
- package/foundation/discovery/docs-discovery.mjs +389 -108
- package/foundation/discovery/docs-discovery.test.mjs +325 -20
- package/foundation/discovery/docs-output-budget.d.mts +28 -0
- package/foundation/discovery/docs-output-budget.mjs +50 -0
- package/foundation/discovery/docs-section-key.d.mts +116 -0
- package/foundation/discovery/docs-section-key.mjs +322 -0
- package/foundation/discovery/docs-section-key.test.mjs +246 -0
- package/foundation/discovery/template-adapter.d.mts +113 -11
- package/foundation/discovery/template-adapter.fixture-refs.test.mjs +248 -0
- package/foundation/discovery/template-adapter.integration-isolation.test.mjs +94 -0
- package/foundation/discovery/template-adapter.mjs +774 -83
- package/foundation/discovery/template-adapter.test.mjs +57 -0
- package/foundation/discovery/theme-discovery.d.mts +67 -7
- package/foundation/discovery/theme-discovery.mjs +916 -186
- package/foundation/discovery/theme-discovery.test.mjs +613 -219
- package/foundation/discovery/theming-targets.test.mjs +4 -0
- package/foundation/doc-compiler/bundle.d.mts +47 -0
- package/foundation/doc-compiler/bundle.mjs +278 -0
- package/foundation/doc-compiler/bundle.test.mjs +266 -0
- package/foundation/doc-compiler/compile.d.mts +343 -0
- package/foundation/doc-compiler/compile.mjs +558 -0
- package/foundation/doc-compiler/diagnostics.d.mts +126 -0
- package/foundation/doc-compiler/diagnostics.mjs +305 -0
- package/foundation/doc-compiler/doc-compiler.test.mjs +714 -0
- package/foundation/doc-compiler/doc-loads.test.mjs +1642 -0
- package/foundation/doc-compiler/import.d.mts +24 -0
- package/foundation/doc-compiler/import.mjs +59 -0
- package/foundation/doc-compiler/inputs.d.mts +102 -0
- package/foundation/doc-compiler/inputs.mjs +291 -0
- package/foundation/doc-compiler/inputs.test.mjs +299 -0
- package/foundation/doc-compiler/ir.d.mts +22 -0
- package/foundation/doc-compiler/ir.mjs +471 -0
- package/foundation/doc-compiler/lenses.d.mts +34 -0
- package/foundation/doc-compiler/lenses.mjs +128 -0
- package/foundation/doc-compiler/links.d.mts +135 -0
- package/foundation/doc-compiler/links.mjs +253 -0
- package/foundation/doc-compiler/links.test.mjs +139 -0
- package/foundation/doc-compiler/lower-doc.test.mjs +495 -0
- package/foundation/doc-compiler/overlays.d.mts +37 -0
- package/foundation/doc-compiler/overlays.mjs +206 -0
- package/foundation/doc-compiler/parse-readable.d.mts +9 -0
- package/foundation/doc-compiler/parse-readable.mjs +29 -0
- package/foundation/doc-compiler/read.d.mts +127 -0
- package/foundation/doc-compiler/read.mjs +325 -0
- package/foundation/doc-compiler/read.test.mjs +313 -0
- package/foundation/doc-compiler/source.d.mts +33 -0
- package/foundation/doc-compiler/source.mjs +128 -0
- package/foundation/doc-compiler/tree.d.mts +288 -0
- package/foundation/doc-compiler/tree.mjs +876 -0
- package/foundation/doc-compiler/tree.test.mjs +598 -0
- package/foundation/fs/file-protection.d.mts +33 -0
- package/foundation/fs/file-protection.mjs +825 -0
- package/foundation/fs/file-protection.test.mjs +250 -0
- package/foundation/fs/module-loader.d.mts +1 -0
- package/foundation/fs/module-loader.mjs +50 -1
- package/foundation/fs/module-loader.stdout.test.mjs +332 -0
- package/foundation/fs/path-safety.d.mts +3 -2
- package/foundation/fs/path-safety.mjs +49 -19
- package/foundation/fs/path-safety.test.mjs +50 -0
- package/foundation/fs/publish-file-hardlink-unavailable.test.mjs +129 -94
- package/foundation/identity/provider-identity.d.mts +90 -0
- package/foundation/identity/provider-identity.mjs +320 -0
- package/foundation/identity/provider-identity.test.mjs +254 -0
- package/foundation/identity/providers.d.mts +7 -0
- package/foundation/identity/providers.mjs +16 -0
- package/foundation/integrations/autolink.d.mts +58 -1
- package/foundation/integrations/autolink.mjs +143 -45
- package/foundation/integrations/autolink.test.mjs +1 -1
- package/foundation/integrations/cli-requirement.d.mts +45 -0
- package/foundation/integrations/cli-requirement.mjs +154 -0
- package/foundation/integrations/cli-requirement.test.mjs +109 -0
- package/foundation/integrations/contribution-fixes.d.mts +145 -0
- package/foundation/integrations/contribution-fixes.mjs +1284 -0
- package/foundation/integrations/contribution-inventory.d.mts +3 -2
- package/foundation/integrations/contribution-inventory.mjs +27 -24
- package/foundation/integrations/contribution-inventory.test.mjs +86 -27
- package/foundation/integrations/integration-warnings.d.mts +9 -2
- package/foundation/integrations/integration-warnings.mjs +52 -21
- package/foundation/integrations/integration-warnings.test.mjs +74 -1
- package/foundation/integrations/integrations.d.mts +49 -2
- package/foundation/integrations/integrations.mjs +81 -8
- package/foundation/integrations/integrations.test.mjs +384 -1
- package/foundation/integrations/provider-conflicts.test.mjs +125 -0
- package/foundation/integrations/provider-ledger.test.mjs +275 -0
- package/foundation/integrations/provider-resolution.d.mts +152 -0
- package/foundation/integrations/provider-resolution.mjs +576 -0
- package/foundation/integrations/provider-resolution.test.mjs +369 -0
- package/foundation/integrations/theme-descriptor.d.mts +8 -0
- package/foundation/integrations/theme-descriptor.mjs +44 -0
- package/foundation/integrations/validate-contributions.d.mts +2 -0
- package/foundation/integrations/validate-contributions.mjs +131 -29
- package/foundation/response/base.d.ts +8 -4
- package/foundation/response/error-codes.d.mts +3 -1
- package/foundation/response/error-codes.d.ts +2 -0
- package/foundation/response/error-codes.doc.mjs +13 -4
- package/foundation/response/error-codes.mjs +8 -2
- package/foundation/response/error-codes.test.mjs +137 -10
- package/foundation/response/json-contract.test.mjs +57 -17
- package/foundation/response/json.d.mts +4 -2
- package/foundation/response/json.mjs +8 -10
- package/foundation/response/response-types.doc.mjs +26 -16
- package/foundation/response/response-types.doc.test.mjs +158 -0
- package/foundation/response/response.doc.mjs +1 -1
- package/foundation/text/string-utils.mjs +22 -10
- package/foundation/xle/expand.d.mts +2 -0
- package/foundation/xle/expand.mjs +4 -3
- package/foundation/xle/expand.test.mjs +54 -0
- package/foundation/xle/xle.test.mjs +13 -0
- package/package.json +10 -11
- package/assets/templates/themes/manifest.json +0 -95
- package/clients/cli/lib/update-check.mjs +0 -83
- package/clients/cli/lib/update-check.test.mjs +0 -137
- package/clients/cli/update-hint-commands.test.mjs +0 -54
package/api/docs/_adapter.mjs
CHANGED
|
@@ -7,26 +7,51 @@
|
|
|
7
7
|
* packages/cli/assets/docs/{topic}.doc.mjs plus every topic the configured
|
|
8
8
|
* integrations contribute — and, when a --dense/--zh overlay is requested,
|
|
9
9
|
* the sibling {topic}.doc.dense.mjs / {topic}.doc.zh.mjs.
|
|
10
|
-
* @output Catalog access,
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* @position Sits beside docs.mjs (api/docs/).
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
import * as path from 'node:path';
|
|
21
|
-
import {pathToFileURL} from 'node:url';
|
|
10
|
+
* @output Catalog access, the compiler input for a topic, and the compiled
|
|
11
|
+
* node for it: lowered (overlaid, extensions merged, keys stamped) or linked
|
|
12
|
+
* (token references resolved too), memoized per catalog.
|
|
13
|
+
* @position Sits beside docs.mjs (api/docs/). Hands topics to
|
|
14
|
+
* foundation/doc-compiler (which loads their files) and memoizes the nodes
|
|
15
|
+
* per catalog, so no leaf, doctor check or search loads, merges, or resolves
|
|
16
|
+
* docs on its own. Discovery itself lives in
|
|
17
|
+
* foundation/discovery/docs-discovery, which the catalog comes from.
|
|
18
|
+
*/
|
|
19
|
+
|
|
22
20
|
import {Project} from '../../foundation/config/project.mjs';
|
|
21
|
+
import {DocsCatalog} from '../../foundation/discovery/docs-discovery.mjs';
|
|
22
|
+
import {
|
|
23
|
+
linkReferenceTopic,
|
|
24
|
+
lowerReferenceTopic,
|
|
25
|
+
} from '../../foundation/doc-compiler/compile.mjs';
|
|
26
|
+
import {
|
|
27
|
+
deepFreeze,
|
|
28
|
+
loadTopicFile,
|
|
29
|
+
loadTopicInput,
|
|
30
|
+
OVERLAY_LANGUAGES,
|
|
31
|
+
overlayLanguages,
|
|
32
|
+
} from '../../foundation/doc-compiler/read.mjs';
|
|
33
|
+
import {
|
|
34
|
+
buildDocsTree,
|
|
35
|
+
loadTreeInputs,
|
|
36
|
+
} from '../../foundation/doc-compiler/tree.mjs';
|
|
37
|
+
import {sortDiagnostics} from '../../foundation/doc-compiler/diagnostics.mjs';
|
|
23
38
|
import {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
} from '../../foundation/
|
|
39
|
+
linkBlocks,
|
|
40
|
+
parseLinkTarget,
|
|
41
|
+
} from '../../foundation/doc-compiler/links.mjs';
|
|
42
|
+
import {
|
|
43
|
+
createDocId,
|
|
44
|
+
normalizeProviderId,
|
|
45
|
+
} from '../../foundation/identity/provider-identity.mjs';
|
|
46
|
+
import {
|
|
47
|
+
cliDocIndex,
|
|
48
|
+
cliDocSection,
|
|
49
|
+
} from '../../foundation/discovery/cli-self-docs.mjs';
|
|
27
50
|
import {AstryxError} from '../error.mjs';
|
|
28
51
|
import {ERROR_CODES} from '../../foundation/response/error-codes.mjs';
|
|
29
52
|
|
|
53
|
+
export {OVERLAY_LANGUAGES, overlayLanguages};
|
|
54
|
+
|
|
30
55
|
/**
|
|
31
56
|
* The project's topics: the built-in ones plus whatever the configured
|
|
32
57
|
* integrations contribute.
|
|
@@ -50,121 +75,722 @@ export async function loadDocsCatalog(cwd = process.cwd()) {
|
|
|
50
75
|
}
|
|
51
76
|
|
|
52
77
|
/**
|
|
53
|
-
*
|
|
54
|
-
* @param {
|
|
55
|
-
* @returns {
|
|
78
|
+
* The overlay a read applies: none for the authored language.
|
|
79
|
+
* @param {string | null | undefined} lang
|
|
80
|
+
* @returns {string | null}
|
|
81
|
+
*/
|
|
82
|
+
function overlayLanguage(lang) {
|
|
83
|
+
return lang && lang !== 'en' ? lang : null;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** @type {WeakMap<DocsCatalog, Map<string, Promise<import('../../foundation/doc-compiler/compile.mjs').CompiledReferenceNode>>>} */
|
|
87
|
+
const loweredByCatalog = new WeakMap();
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* One topic, lowered for `lang` with its links as written: overlaid,
|
|
91
|
+
* extensions merged, keys stamped. Memoized per catalog, so a read that
|
|
92
|
+
* references a topic twice loads it once. Every read of the catalog shares the
|
|
93
|
+
* memoized node, so it is frozen; the lenses hand readers copies.
|
|
94
|
+
* @param {DocsCatalog} catalog
|
|
95
|
+
* @param {import('../../foundation/discovery/docs-discovery.mjs').DocsTopicEntry} entry
|
|
96
|
+
* @param {string | null} [lang]
|
|
97
|
+
* @returns {Promise<import('../../foundation/doc-compiler/compile.mjs').CompiledReferenceNode>}
|
|
98
|
+
*/
|
|
99
|
+
function lowerRawTopic(catalog, entry, lang = null) {
|
|
100
|
+
const overlay = overlayLanguage(lang);
|
|
101
|
+
let cache = loweredByCatalog.get(catalog);
|
|
102
|
+
if (!cache) {
|
|
103
|
+
cache = new Map();
|
|
104
|
+
loweredByCatalog.set(catalog, cache);
|
|
105
|
+
}
|
|
106
|
+
const key = `${entry.name.toLowerCase()}\u0000${overlay ?? ''}`;
|
|
107
|
+
let lowered = cache.get(key);
|
|
108
|
+
if (!lowered) {
|
|
109
|
+
lowered = loadTopicInput(entry, overlay).then(input =>
|
|
110
|
+
deepFreeze(lowerReferenceTopic(input)),
|
|
111
|
+
);
|
|
112
|
+
cache.set(key, lowered);
|
|
113
|
+
}
|
|
114
|
+
return lowered;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* @typedef {import('../../foundation/doc-compiler/tree.mjs').DocsTree} DocsTree
|
|
119
|
+
* @typedef {import('../../foundation/doc-compiler/tree.mjs').TreeNode} TreeNode
|
|
120
|
+
* @typedef {import('../../foundation/doc-compiler/links.mjs').LinkProblem} LinkProblem
|
|
121
|
+
* @typedef {import('../../foundation/doc-compiler/links.mjs').LinkResolver} LinkResolver
|
|
122
|
+
* @typedef {import('../../foundation/discovery/docs-discovery.mjs').DocsTopicEntry} DocsTopicEntry
|
|
123
|
+
*/
|
|
124
|
+
|
|
125
|
+
/** @type {WeakMap<DocsCatalog, Map<string, Promise<{node: import('../../foundation/doc-compiler/compile.mjs').CompiledReferenceNode, problems: LinkProblem[]}>>>} */
|
|
126
|
+
const linkedByCatalog = new WeakMap();
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* The CLI's own topics alone, for a check that runs without a project.
|
|
130
|
+
* @returns {DocsCatalog}
|
|
131
|
+
*/
|
|
132
|
+
export function builtinCatalog() {
|
|
133
|
+
return DocsCatalog.fromBuiltins();
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* The provider id a topic's (or an extension's) links resolve against: its
|
|
138
|
+
* owner's.
|
|
139
|
+
* @param {{providerId?: string, package: string}} entry
|
|
140
|
+
* @returns {string}
|
|
141
|
+
*/
|
|
142
|
+
function providerOf(entry) {
|
|
143
|
+
return normalizeProviderId(entry.providerId ?? entry.package);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* One topic, lowered for `lang` with every link between docs resolved
|
|
148
|
+
* (spec:AST-047 FR9): an inline `{@link <target>}` reads as the command that
|
|
149
|
+
* opens its doc, and a `reference` or `workflow` block carries the doc it
|
|
150
|
+
* names. Memoized per catalog and frozen, like the lowered node.
|
|
151
|
+
* @param {DocsCatalog} catalog
|
|
152
|
+
* @param {DocsTopicEntry} entry
|
|
153
|
+
* @param {string | null} [lang]
|
|
154
|
+
* @returns {Promise<import('../../foundation/doc-compiler/compile.mjs').CompiledReferenceNode>}
|
|
155
|
+
*/
|
|
156
|
+
export async function lowerTopic(catalog, entry, lang = null) {
|
|
157
|
+
return (await linkTopic(catalog, entry, lang)).node;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Each link in a topic that names no doc.
|
|
162
|
+
* @param {DocsCatalog} catalog
|
|
163
|
+
* @param {DocsTopicEntry} entry
|
|
164
|
+
* @returns {Promise<LinkProblem[]>}
|
|
165
|
+
*/
|
|
166
|
+
export async function topicLinkProblems(catalog, entry) {
|
|
167
|
+
return (await linkTopic(catalog, entry, null)).problems;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* @param {DocsCatalog} catalog
|
|
172
|
+
* @param {DocsTopicEntry} entry
|
|
173
|
+
* @param {string | null} lang
|
|
56
174
|
*/
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
175
|
+
function linkTopic(catalog, entry, lang) {
|
|
176
|
+
let cache = linkedByCatalog.get(catalog);
|
|
177
|
+
if (!cache) {
|
|
178
|
+
cache = new Map();
|
|
179
|
+
linkedByCatalog.set(catalog, cache);
|
|
180
|
+
}
|
|
181
|
+
const key = `${entry.name.toLowerCase()}\u0000${overlayLanguage(lang) ?? ''}`;
|
|
182
|
+
let linked = cache.get(key);
|
|
183
|
+
if (!linked) {
|
|
184
|
+
linked = (async () => {
|
|
185
|
+
const raw = await lowerRawTopic(catalog, entry, lang);
|
|
186
|
+
/** @type {Map<string, LinkResolver>} */
|
|
187
|
+
const resolvers = new Map();
|
|
188
|
+
/** @param {string} provider */
|
|
189
|
+
const resolverFor = async provider => {
|
|
190
|
+
let resolve = resolvers.get(provider);
|
|
191
|
+
if (!resolve) {
|
|
192
|
+
resolve = await linkResolver(catalog, provider);
|
|
193
|
+
resolvers.set(provider, resolve);
|
|
194
|
+
}
|
|
195
|
+
return resolve;
|
|
196
|
+
};
|
|
197
|
+
/** @type {LinkProblem[]} */
|
|
198
|
+
const problems = [];
|
|
199
|
+
const sections = [];
|
|
200
|
+
// Each section resolves its links against the provider that wrote it:
|
|
201
|
+
// an extension's sections against the extension's provider, never the
|
|
202
|
+
// base topic's.
|
|
203
|
+
for (const section of raw.doc.sections) {
|
|
204
|
+
const provider = raw.sectionProviders?.[section.id];
|
|
205
|
+
const linked = await linkBlocks(
|
|
206
|
+
section.content,
|
|
207
|
+
await resolverFor(
|
|
208
|
+
provider == null ? providerOf(entry) : normalizeProviderId(provider),
|
|
209
|
+
),
|
|
210
|
+
{section: section.id ?? section.title},
|
|
211
|
+
);
|
|
212
|
+
problems.push(...linked.problems);
|
|
213
|
+
sections.push({...section, content: linked.content});
|
|
214
|
+
}
|
|
215
|
+
return {
|
|
216
|
+
node: deepFreeze({...raw, doc: {...raw.doc, sections}}),
|
|
217
|
+
problems,
|
|
218
|
+
};
|
|
219
|
+
})();
|
|
220
|
+
cache.set(key, linked);
|
|
221
|
+
}
|
|
222
|
+
return linked;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/** @type {WeakMap<DocsCatalog, Promise<DocsTree>>} */
|
|
226
|
+
const treesByCatalog = new WeakMap();
|
|
61
227
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
228
|
+
/**
|
|
229
|
+
* The project's docs tree: the CLI's own docs plus the namespace docs and
|
|
230
|
+
* placed guides the configured integrations ship (spec:AST-046), built once
|
|
231
|
+
* per catalog. Without integration docs it is the CLI's tree, built once per
|
|
232
|
+
* process.
|
|
233
|
+
* @param {DocsCatalog} catalog
|
|
234
|
+
* @param {{fresh?: boolean}} [options] `fresh`: reread the CLI's tree files
|
|
235
|
+
* @returns {Promise<DocsTree>}
|
|
236
|
+
*/
|
|
237
|
+
export function projectTree(catalog, {fresh = false} = {}) {
|
|
238
|
+
let tree = treesByCatalog.get(catalog);
|
|
239
|
+
if (!tree || fresh) {
|
|
240
|
+
tree = buildProjectTree(catalog, fresh);
|
|
241
|
+
treesByCatalog.set(catalog, tree);
|
|
242
|
+
}
|
|
243
|
+
return tree;
|
|
244
|
+
}
|
|
67
245
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
if (!translation) return docs;
|
|
246
|
+
/** @type {ReturnType<typeof loadTreeInputs> | undefined} */
|
|
247
|
+
let cliTreeInputs;
|
|
71
248
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
249
|
+
/**
|
|
250
|
+
* Every flat topic in the catalog, as the tree's Unorganized level reads it.
|
|
251
|
+
* @param {DocsCatalog} catalog
|
|
252
|
+
* @returns {Promise<import('../../foundation/doc-compiler/tree.mjs').TreeTopicInput[]>}
|
|
253
|
+
*/
|
|
254
|
+
async function flatTopicInputs(catalog) {
|
|
255
|
+
/** @type {import('../../foundation/doc-compiler/tree.mjs').TreeTopicInput[]} */
|
|
256
|
+
const topics = [];
|
|
257
|
+
for (const entry of catalog.entries()) {
|
|
258
|
+
const aliases = catalog.aliasesOf(entry);
|
|
259
|
+
let {title, description} = entry;
|
|
260
|
+
if (title == null || description == null) {
|
|
261
|
+
try {
|
|
262
|
+
const file = await loadTopicFile(entry.path, null);
|
|
263
|
+
title ??= file.doc?.title;
|
|
264
|
+
description ??= file.doc?.description;
|
|
265
|
+
} catch {
|
|
266
|
+
// A topic that does not load is reported where it is read.
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
topics.push({
|
|
270
|
+
provider: entry.package,
|
|
271
|
+
providerId: entry.providerId ?? entry.package,
|
|
272
|
+
name: entry.name,
|
|
273
|
+
title: title ?? entry.name,
|
|
274
|
+
summary: description ?? '',
|
|
275
|
+
source: `${entry.package}:${entry.name}`,
|
|
276
|
+
...(aliases.length > 0 ? {aliases} : {}),
|
|
277
|
+
});
|
|
83
278
|
}
|
|
279
|
+
return topics;
|
|
280
|
+
}
|
|
84
281
|
|
|
282
|
+
/**
|
|
283
|
+
* The CLI's tree, each configured integration's namespaces and guides, and
|
|
284
|
+
* every flat topic in the generated Unorganized level.
|
|
285
|
+
* @param {DocsCatalog} catalog
|
|
286
|
+
* @param {boolean} fresh
|
|
287
|
+
* @returns {Promise<DocsTree>}
|
|
288
|
+
*/
|
|
289
|
+
async function buildProjectTree(catalog, fresh) {
|
|
290
|
+
const added = catalog.treeInputs;
|
|
291
|
+
if (fresh || !cliTreeInputs) cliTreeInputs = loadTreeInputs();
|
|
292
|
+
const cli = await cliTreeInputs;
|
|
293
|
+
const result = buildDocsTree({
|
|
294
|
+
namespaces: [...cli.namespaces, ...added.flatMap(each => each.namespaces)],
|
|
295
|
+
docs: [...cli.docs, ...added.flatMap(each => each.guides)],
|
|
296
|
+
topics: await flatTopicInputs(catalog),
|
|
297
|
+
});
|
|
85
298
|
return {
|
|
86
|
-
...
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
299
|
+
...result,
|
|
300
|
+
diagnostics: sortDiagnostics([...cli.diagnostics, ...result.diagnostics]),
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/** @type {WeakMap<DocsTree, Map<string, TreeNode>>} */
|
|
305
|
+
const identitiesByTree = new WeakMap();
|
|
306
|
+
|
|
307
|
+
/** @param {string} provider @param {string} kind @param {string} name */
|
|
308
|
+
function identityKey(provider, kind, name) {
|
|
309
|
+
return `${provider}\u0000${kind}\u0000${kind === 'generic' ? name.toLowerCase() : name}`;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Every tree node with an identity, by provider id, kind, and name.
|
|
314
|
+
* @param {DocsTree} tree
|
|
315
|
+
*/
|
|
316
|
+
function identitiesOf(tree) {
|
|
317
|
+
let index = identitiesByTree.get(tree);
|
|
318
|
+
if (!index) {
|
|
319
|
+
index = new Map();
|
|
320
|
+
for (const node of tree.nodes.values()) {
|
|
321
|
+
if (node.id == null) continue;
|
|
322
|
+
let provider = node.providerId;
|
|
323
|
+
try {
|
|
324
|
+
provider = normalizeProviderId(node.providerId);
|
|
325
|
+
} catch {
|
|
326
|
+
// Kept as given; a link names it the same way.
|
|
327
|
+
}
|
|
328
|
+
index.set(identityKey(provider, node.kind, node.name), node);
|
|
329
|
+
}
|
|
330
|
+
identitiesByTree.set(tree, index);
|
|
331
|
+
}
|
|
332
|
+
return index;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* How a doc's links find their targets (spec:AST-047 FR9): a doc in the
|
|
337
|
+
* project's docs tree by its identity, or a flat topic by its provider and
|
|
338
|
+
* name. A target that matches neither is a problem, never a guess.
|
|
339
|
+
* @param {DocsCatalog} catalog
|
|
340
|
+
* @param {string} fromProvider the provider id of the doc the links sit in
|
|
341
|
+
* @returns {Promise<LinkResolver>}
|
|
342
|
+
*/
|
|
343
|
+
export async function linkResolver(catalog, fromProvider) {
|
|
344
|
+
const identities = identitiesOf(await projectTree(catalog));
|
|
345
|
+
return async target => {
|
|
346
|
+
const parsed = parseLinkTarget(target);
|
|
347
|
+
if ('error' in parsed) return {problem: parsed.error};
|
|
348
|
+
let provider;
|
|
349
|
+
try {
|
|
350
|
+
provider = normalizeProviderId(parsed.provider ?? fromProvider);
|
|
351
|
+
} catch {
|
|
352
|
+
return {
|
|
353
|
+
problem: `"${target}" names "${parsed.provider}", which is not a provider id: an npm package name, or the \`providerId\` its manifest declares`,
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
const node = identities.get(identityKey(provider, parsed.kind, parsed.name));
|
|
357
|
+
if (node) {
|
|
358
|
+
return {
|
|
359
|
+
target,
|
|
360
|
+
id: /** @type {string} */ (node.id),
|
|
361
|
+
route: node.route,
|
|
362
|
+
title: node.title,
|
|
363
|
+
summary: node.summary,
|
|
364
|
+
command: `astryx docs ${node.route}`,
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
if (parsed.kind === 'generic') {
|
|
368
|
+
const entry = catalog.resolve(parsed.name);
|
|
369
|
+
if (
|
|
370
|
+
entry &&
|
|
371
|
+
!entry.tree &&
|
|
372
|
+
(providerOf(entry) === provider ||
|
|
373
|
+
catalog.aliasesOf(entry).includes(parsed.name.toLowerCase()))
|
|
374
|
+
) {
|
|
375
|
+
let title = entry.title ?? entry.name;
|
|
376
|
+
let summary = entry.description ?? '';
|
|
377
|
+
try {
|
|
378
|
+
const raw = await lowerRawTopic(catalog, entry);
|
|
379
|
+
title = raw.doc.title ?? title;
|
|
380
|
+
summary = raw.doc.description ?? summary;
|
|
381
|
+
} catch {
|
|
382
|
+
// The topic budget check reports a topic that does not load; the
|
|
383
|
+
// link still opens it.
|
|
384
|
+
}
|
|
92
385
|
return {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
) => {
|
|
100
|
-
const tb = ts.content?.[bi];
|
|
101
|
-
if (!tb) return block;
|
|
102
|
-
if (tb.type === 'prose' && block.type === 'prose') return {...block, text: tb.text};
|
|
103
|
-
if (tb.type === 'list' && block.type === 'list') return {...block, items: tb.items};
|
|
104
|
-
return block;
|
|
105
|
-
},
|
|
106
|
-
),
|
|
386
|
+
target,
|
|
387
|
+
id: createDocId(provider, 'generic', parsed.name),
|
|
388
|
+
route: entry.name,
|
|
389
|
+
title,
|
|
390
|
+
summary,
|
|
391
|
+
command: `astryx docs ${entry.name}`,
|
|
107
392
|
};
|
|
108
|
-
}
|
|
109
|
-
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
return {
|
|
396
|
+
problem: `"${target}" names no doc. Find it with \`astryx search ${parsed.name} --type doc\`, then name it as \`[<provider>:]<kind>:<name>\`.`,
|
|
397
|
+
};
|
|
110
398
|
};
|
|
111
399
|
}
|
|
112
400
|
|
|
113
401
|
/**
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
|
|
121
|
-
|
|
402
|
+
* Every link in the project's docs that names no doc: in each topic, each
|
|
403
|
+
* guide the tree places, and each typed doc.
|
|
404
|
+
* @param {DocsCatalog} catalog
|
|
405
|
+
* @param {DocsTree} tree
|
|
406
|
+
* @param {{owner?: string}} [options] `owner`: only the docs this package owns
|
|
407
|
+
* @returns {Promise<string[]>}
|
|
408
|
+
*/
|
|
409
|
+
export async function docsLinkProblems(catalog, tree, {owner} = {}) {
|
|
410
|
+
/** @type {string[]} */
|
|
411
|
+
const problems = [];
|
|
412
|
+
/** @param {string} where @param {LinkProblem[]} found */
|
|
413
|
+
const note = (where, found) => {
|
|
414
|
+
for (const problem of found) {
|
|
415
|
+
problems.push(
|
|
416
|
+
`${where}${problem.section ? ` \u00a7 ${problem.section}` : ''}: ${problem.message}`,
|
|
417
|
+
);
|
|
418
|
+
}
|
|
419
|
+
};
|
|
420
|
+
for (const entry of catalog.entries()) {
|
|
421
|
+
// A package owns a topic it wrote, and the sections it adds to another
|
|
422
|
+
// package's topic.
|
|
423
|
+
if (
|
|
424
|
+
owner != null &&
|
|
425
|
+
entry.package !== owner &&
|
|
426
|
+
!entry.extensions.some(extension => extension.package === owner)
|
|
427
|
+
) {
|
|
428
|
+
continue;
|
|
429
|
+
}
|
|
430
|
+
try {
|
|
431
|
+
note(entry.name, await topicLinkProblems(catalog, entry));
|
|
432
|
+
} catch {
|
|
433
|
+
// The topic budget check reports a topic that does not load.
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
for (const node of tree.nodes.values()) {
|
|
437
|
+
if (owner != null && node.provider !== owner) continue;
|
|
438
|
+
if (node.kind === 'generic' && node.ref?.topicFile) {
|
|
439
|
+
try {
|
|
440
|
+
note(node.route, await topicLinkProblems(catalog, guideEntry(node)));
|
|
441
|
+
} catch {
|
|
442
|
+
// As above.
|
|
443
|
+
}
|
|
444
|
+
} else if (node.ref?.selfDoc) {
|
|
445
|
+
note(node.route, (await nodeContent(catalog, tree, node)).problems);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
return problems;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* What \`astryx doctor integration docs\` checks in one integration's docs: the
|
|
453
|
+
* docs tree they build beside the CLI's (namespaces, placements, routes) and
|
|
454
|
+
* every link in them (spec:AST-046, spec:AST-047).
|
|
455
|
+
* @param {{name: string}} integration
|
|
456
|
+
* @param {{records: import('../../foundation/discovery/docs-discovery.mjs').DocsTopicRecord[], namespaces: import('../../foundation/doc-compiler/tree.mjs').TreeNamespaceInput[], guides: import('../../foundation/doc-compiler/tree.mjs').TreeDocInput[]}} discovered
|
|
457
|
+
* @returns {Promise<string[]>}
|
|
458
|
+
*/
|
|
459
|
+
export async function packageDocsProblems(integration, discovered) {
|
|
460
|
+
const catalog = DocsCatalog.fromBuiltins();
|
|
461
|
+
for (const record of discovered.records) catalog.add(record);
|
|
462
|
+
catalog.addTreeInputs({
|
|
463
|
+
namespaces: discovered.namespaces.map(input => ({...input, rank: 1})),
|
|
464
|
+
guides: discovered.guides.map(input => ({...input, rank: 1})),
|
|
465
|
+
});
|
|
466
|
+
const tree = await projectTree(catalog);
|
|
467
|
+
const problems = tree.diagnostics
|
|
468
|
+
.filter(d => d.severity === 'error' && d.provider === integration.name)
|
|
469
|
+
.map(d => `${d.source ?? integration.name}: ${d.message}`);
|
|
470
|
+
problems.push(
|
|
471
|
+
...(await docsLinkProblems(catalog, tree, {owner: integration.name})),
|
|
472
|
+
);
|
|
473
|
+
return problems;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* How a token reference finds its target: the topic it names in `catalog`,
|
|
478
|
+
* lowered for the same language.
|
|
479
|
+
* @param {DocsCatalog} catalog
|
|
480
|
+
* @param {string | null} lang
|
|
481
|
+
* @returns {(topic: string) => Promise<import('../../foundation/doc-compiler/compile.mjs').CompiledReferenceNode | null>}
|
|
482
|
+
*/
|
|
483
|
+
export function referenceTargets(catalog, lang) {
|
|
484
|
+
return async topic => {
|
|
485
|
+
const target = catalog.resolve(topic);
|
|
486
|
+
return target ? lowerTopic(catalog, target, lang) : null;
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* One topic, compiled for `lang`: lowered, then every token reference linked.
|
|
492
|
+
* @param {DocsCatalog} catalog
|
|
122
493
|
* @param {import('../../foundation/discovery/docs-discovery.mjs').DocsTopicEntry} entry
|
|
123
|
-
* @param {
|
|
124
|
-
* @returns {Promise<import('
|
|
494
|
+
* @param {string | null} [lang]
|
|
495
|
+
* @returns {Promise<import('../../foundation/doc-compiler/compile.mjs').CompiledReferenceNode>}
|
|
496
|
+
*/
|
|
497
|
+
export async function compileTopic(catalog, entry, lang = null) {
|
|
498
|
+
return linkReferenceTopic(
|
|
499
|
+
await lowerTopic(catalog, entry, lang),
|
|
500
|
+
referenceTargets(catalog, lang),
|
|
501
|
+
);
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
/**
|
|
505
|
+
* A guide the docs tree places, as a topic entry the topic readers open by its
|
|
506
|
+
* route. It is never a flat topic: `astryx docs <route>` is its only name.
|
|
507
|
+
* @param {import('../../foundation/doc-compiler/tree.mjs').TreeNode} node
|
|
508
|
+
* @returns {import('../../foundation/discovery/docs-discovery.mjs').DocsTopicEntry}
|
|
509
|
+
*/
|
|
510
|
+
export function guideEntry(node) {
|
|
511
|
+
return {
|
|
512
|
+
name: node.route,
|
|
513
|
+
route: node.route,
|
|
514
|
+
package: node.provider,
|
|
515
|
+
providerId: node.providerId,
|
|
516
|
+
path: node.ref.topicFile,
|
|
517
|
+
extensions: [],
|
|
518
|
+
tree: true,
|
|
519
|
+
parent: node.parent ?? undefined,
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
/** @type {WeakMap<DocsTree, ReturnType<typeof cliDocIndex>>} */
|
|
524
|
+
const typedDocIndexes = new WeakMap();
|
|
525
|
+
|
|
526
|
+
/**
|
|
527
|
+
* What a typed doc in the docs tree prints: its content, with every link to
|
|
528
|
+
* another doc resolved (spec:AST-047 FR9). A namespace has no content. The
|
|
529
|
+
* CLI's doc modules are discovery, so this lives in the adapter
|
|
530
|
+
* (architecture:cli-surface INV21).
|
|
531
|
+
* @param {DocsCatalog} catalog
|
|
532
|
+
* @param {DocsTree} tree
|
|
533
|
+
* @param {TreeNode} node
|
|
534
|
+
* @returns {Promise<{content: any[], problems: LinkProblem[]}>}
|
|
125
535
|
*/
|
|
126
|
-
export async function
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
536
|
+
export async function nodeContent(catalog, tree, node) {
|
|
537
|
+
if (!node.ref?.selfDoc) return {content: [], problems: []};
|
|
538
|
+
let index = typedDocIndexes.get(tree);
|
|
539
|
+
if (!index) {
|
|
540
|
+
index = cliDocIndex(
|
|
541
|
+
[...tree.nodes.values()].flatMap(each =>
|
|
542
|
+
each.ref?.selfDoc ? [each.ref.selfDoc] : [],
|
|
543
|
+
),
|
|
544
|
+
);
|
|
545
|
+
typedDocIndexes.set(tree, index);
|
|
130
546
|
}
|
|
131
|
-
|
|
547
|
+
const resolve = await linkResolver(catalog, node.providerId);
|
|
548
|
+
return linkBlocks(cliDocSection(node.ref.selfDoc, index).content, resolve);
|
|
132
549
|
}
|
|
133
550
|
|
|
134
551
|
/**
|
|
135
|
-
*
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
* @param {string} topic
|
|
141
|
-
* @param {object} [options]
|
|
142
|
-
* @param {string} [options.lang]
|
|
143
|
-
* @param {boolean} [options.zh]
|
|
144
|
-
* @param {boolean} [options.dense]
|
|
145
|
-
* @param {string} [options.cwd]
|
|
146
|
-
* @returns {Promise<{
|
|
147
|
-
* catalog: DocsCatalog,
|
|
148
|
-
* docsData: import('./docs.type.mjs').DocsDetailResponse['data'],
|
|
149
|
-
* }>}
|
|
552
|
+
* The command that opens the level a topic sits in when the tree cannot say:
|
|
553
|
+
* a guide's parent namespace, or the topic list.
|
|
554
|
+
* @param {import('../../foundation/discovery/docs-discovery.mjs').DocsTopicEntry} entry
|
|
555
|
+
* @returns {import('./docs.type.mjs').DocsCommand}
|
|
150
556
|
*/
|
|
151
|
-
export
|
|
152
|
-
|
|
153
|
-
|
|
557
|
+
export function topicUp(entry) {
|
|
558
|
+
return entry.tree && entry.parent
|
|
559
|
+
? `astryx docs ${entry.parent}`
|
|
560
|
+
: 'astryx docs';
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
/**
|
|
564
|
+
* The moves from a node's place in the tree (spec:AST-047 FR2, FR4): up to its
|
|
565
|
+
* parent (the topic list, at the top), and across to the nodes before and
|
|
566
|
+
* after it in its parent's slot.
|
|
567
|
+
* @param {DocsTree} tree
|
|
568
|
+
* @param {TreeNode} node
|
|
569
|
+
* @returns {import('./docs.type.mjs').DocsLinks}
|
|
570
|
+
*/
|
|
571
|
+
export function placeLinks(tree, node) {
|
|
572
|
+
/** @type {import('./docs.type.mjs').DocsLinks} */
|
|
573
|
+
const links = {
|
|
574
|
+
up: node.parent == null ? 'astryx docs' : `astryx docs ${node.parent}`,
|
|
575
|
+
};
|
|
576
|
+
const parent = node.parent == null ? undefined : tree.get(node.parent);
|
|
577
|
+
const siblings =
|
|
578
|
+
parent?.slots.find(slot => slot.children.includes(node.route))?.children ??
|
|
579
|
+
[];
|
|
580
|
+
const at = siblings.indexOf(node.route);
|
|
581
|
+
if (at > 0) links.previous = `astryx docs ${siblings[at - 1]}`;
|
|
582
|
+
if (at !== -1 && at < siblings.length - 1) {
|
|
583
|
+
links.next = `astryx docs ${siblings[at + 1]}`;
|
|
584
|
+
}
|
|
585
|
+
return links;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
/**
|
|
589
|
+
* The moves a topic read offers: from its place in the tree, where a guide
|
|
590
|
+
* sits in its namespace and a flat topic in the Unorganized level.
|
|
591
|
+
* @param {DocsCatalog} catalog
|
|
592
|
+
* @param {import('../../foundation/discovery/docs-discovery.mjs').DocsTopicEntry} entry
|
|
593
|
+
* @returns {Promise<import('./docs.type.mjs').DocsLinks>}
|
|
594
|
+
*/
|
|
595
|
+
export async function topicLinks(catalog, entry) {
|
|
596
|
+
const tree = await projectTree(catalog);
|
|
597
|
+
const node = tree.get(entry.tree ? (entry.route ?? entry.name) : entry.name);
|
|
598
|
+
const placed =
|
|
599
|
+
node && (entry.tree ? node.kind === 'generic' : node.ref?.flatTopic === entry.name);
|
|
600
|
+
return placed ? placeLinks(tree, node) : {up: topicUp(entry)};
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
/**
|
|
604
|
+
* What a docs argument names: a topic (a flat one, or a guide the docs tree
|
|
605
|
+
* places), a namespace or typed doc in the tree, or nothing, as nameOwner
|
|
606
|
+
* decides.
|
|
607
|
+
* @param {unknown} topic
|
|
608
|
+
* @param {{cwd?: string}} [options]
|
|
609
|
+
* @returns {Promise<
|
|
610
|
+
* | {kind: 'topic', catalog: DocsCatalog, entry: import('../../foundation/discovery/docs-discovery.mjs').DocsTopicEntry}
|
|
611
|
+
* | {kind: 'node', catalog: DocsCatalog, tree: import('../../foundation/doc-compiler/tree.mjs').DocsTree, node: import('../../foundation/doc-compiler/tree.mjs').TreeNode}
|
|
612
|
+
* | {kind: 'unknown', catalog: DocsCatalog}
|
|
613
|
+
* >}
|
|
614
|
+
*/
|
|
615
|
+
export async function resolveDocsArgument(topic, {cwd} = {}) {
|
|
154
616
|
const catalog = await loadDocsCatalog(cwd);
|
|
617
|
+
if (typeof topic !== 'string' || topic === '')
|
|
618
|
+
return {kind: 'unknown', catalog};
|
|
619
|
+
const tree = await projectTree(catalog);
|
|
620
|
+
const owner = nameOwner(tree, catalog, topic);
|
|
621
|
+
if (owner == null) return {kind: 'unknown', catalog};
|
|
622
|
+
if (owner.kind === 'topic') return {kind: 'topic', catalog, entry: owner.entry};
|
|
623
|
+
return treeArgument(catalog, tree, owner.node);
|
|
624
|
+
}
|
|
155
625
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
626
|
+
/**
|
|
627
|
+
* Who answers to a name a reader types (spec:AST-046 FR5, FR11). The tree
|
|
628
|
+
* decides first: the node at that route, compared without case, holds it. A
|
|
629
|
+
* name with no node of its own is a topic's other name (its `replaces`
|
|
630
|
+
* alias), and that topic answers, unless the tree gave the topic's own route
|
|
631
|
+
* to another doc. Reads, the topic list, and search all ask this, so they
|
|
632
|
+
* agree on every name.
|
|
633
|
+
* @param {DocsTree} tree
|
|
634
|
+
* @param {DocsCatalog} catalog
|
|
635
|
+
* @param {string} name
|
|
636
|
+
* @returns {{kind: 'topic', entry: import('../../foundation/discovery/docs-discovery.mjs').DocsTopicEntry} | {kind: 'node', node: TreeNode} | null}
|
|
637
|
+
*/
|
|
638
|
+
export function nameOwner(tree, catalog, name) {
|
|
639
|
+
const node = tree.get(name) ?? tree.getFolded?.(name);
|
|
640
|
+
if (node != null) {
|
|
641
|
+
if (node.ref?.flatTopic == null) return {kind: 'node', node};
|
|
642
|
+
const entry = catalog.resolve(node.ref.flatTopic);
|
|
643
|
+
return entry == null ? null : {kind: 'topic', entry};
|
|
644
|
+
}
|
|
645
|
+
const entry = catalog.resolve(name);
|
|
646
|
+
if (entry == null) return null;
|
|
647
|
+
const owner = routeOwner(tree, entry);
|
|
648
|
+
return owner == null ? {kind: 'topic', entry} : {kind: 'node', node: owner};
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
/**
|
|
652
|
+
* Whether a topic answers to its own name: what the topic list and search
|
|
653
|
+
* offer must open that topic.
|
|
654
|
+
* @param {DocsTree} tree
|
|
655
|
+
* @param {DocsCatalog} catalog
|
|
656
|
+
* @param {import('../../foundation/discovery/docs-discovery.mjs').DocsTopicEntry} entry
|
|
657
|
+
* @returns {boolean}
|
|
658
|
+
*/
|
|
659
|
+
export function holdsOwnName(tree, catalog, entry) {
|
|
660
|
+
const owner = nameOwner(tree, catalog, entry.name);
|
|
661
|
+
return (
|
|
662
|
+
owner?.kind === 'topic' &&
|
|
663
|
+
owner.entry.name === entry.name &&
|
|
664
|
+
owner.entry.package === entry.package
|
|
665
|
+
);
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
/**
|
|
669
|
+
* What a tree node opens as: a guide the tree places reads like a topic; a
|
|
670
|
+
* namespace or a typed doc is a node.
|
|
671
|
+
* @param {DocsCatalog} catalog
|
|
672
|
+
* @param {DocsTree} tree
|
|
673
|
+
* @param {TreeNode} node
|
|
674
|
+
* @returns {{kind: 'topic', catalog: DocsCatalog, entry: import('../../foundation/discovery/docs-discovery.mjs').DocsTopicEntry} | {kind: 'node', catalog: DocsCatalog, tree: DocsTree, node: TreeNode}}
|
|
675
|
+
*/
|
|
676
|
+
function treeArgument(catalog, tree, node) {
|
|
677
|
+
if (node.kind === 'generic') {
|
|
678
|
+
return {kind: 'topic', catalog, entry: guideEntry(node)};
|
|
166
679
|
}
|
|
680
|
+
return {kind: 'node', catalog, tree, node};
|
|
681
|
+
}
|
|
167
682
|
|
|
168
|
-
|
|
169
|
-
|
|
683
|
+
/**
|
|
684
|
+
* The doc that took a flat topic's route in the docs tree, when it is not
|
|
685
|
+
* that topic (spec:AST-046 FR11): the CLI keeps its routes, such as `cli`
|
|
686
|
+
* and `unorganized`, and a namespace keeps its route over a topic of the same
|
|
687
|
+
* name. Null when the topic owns its route, or the tree has no node there.
|
|
688
|
+
* @param {DocsTree} tree
|
|
689
|
+
* @param {import('../../foundation/discovery/docs-discovery.mjs').DocsTopicEntry} entry
|
|
690
|
+
* @returns {TreeNode | null}
|
|
691
|
+
*/
|
|
692
|
+
export function routeOwner(tree, entry) {
|
|
693
|
+
const node = tree.get(entry.name) ?? tree.getFolded?.(entry.name);
|
|
694
|
+
if (node == null) return null;
|
|
695
|
+
return node.ref?.flatTopic === entry.name && node.provider === entry.package
|
|
696
|
+
? null
|
|
697
|
+
: node;
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
/**
|
|
701
|
+
* The error for a docs argument that names nothing. For a route, it suggests
|
|
702
|
+
* the children of the deepest namespace the route reaches; otherwise, every
|
|
703
|
+
* topic and every top-level namespace.
|
|
704
|
+
* @param {unknown} topic
|
|
705
|
+
* @param {DocsCatalog} catalog
|
|
706
|
+
* @returns {Promise<AstryxError>}
|
|
707
|
+
*/
|
|
708
|
+
export async function unknownTopicError(topic, catalog) {
|
|
709
|
+
const tree = await projectTree(catalog);
|
|
710
|
+
/** @type {Array<{name: string, reason: string}>} */
|
|
711
|
+
let suggestions = [];
|
|
712
|
+
if (typeof topic === 'string' && topic.includes('/')) {
|
|
713
|
+
const parts = topic.split('/');
|
|
714
|
+
for (
|
|
715
|
+
let depth = parts.length - 1;
|
|
716
|
+
depth > 0 && suggestions.length === 0;
|
|
717
|
+
depth--
|
|
718
|
+
) {
|
|
719
|
+
const near = tree.get(parts.slice(0, depth).join('/'));
|
|
720
|
+
if (near) {
|
|
721
|
+
suggestions = near.slots.flatMap(slot =>
|
|
722
|
+
slot.children.map(route => ({
|
|
723
|
+
name: route,
|
|
724
|
+
reason: tree.get(route)?.summary ?? '',
|
|
725
|
+
})),
|
|
726
|
+
);
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
if (suggestions.length === 0 && typeof topic === 'string') {
|
|
731
|
+
// The docs whose own name it is (`doctor` is cli/commands/doctor), or whose
|
|
732
|
+
// route it spells with hyphens (`cli-integrations`, the guide's name before
|
|
733
|
+
// it moved to cli/integrations).
|
|
734
|
+
const wanted = topic.toLowerCase();
|
|
735
|
+
suggestions = [...tree.nodes.values()]
|
|
736
|
+
.filter(
|
|
737
|
+
node =>
|
|
738
|
+
!node.ref?.flatTopic &&
|
|
739
|
+
(node.name.toLowerCase() === wanted ||
|
|
740
|
+
node.route.replaceAll('/', '-').toLowerCase() === wanted),
|
|
741
|
+
)
|
|
742
|
+
.map(node => ({name: node.route, reason: node.summary}));
|
|
743
|
+
}
|
|
744
|
+
if (suggestions.length === 0) {
|
|
745
|
+
suggestions = [
|
|
746
|
+
...tree
|
|
747
|
+
.roots()
|
|
748
|
+
.map(root => ({name: root.route, reason: 'docs namespace'})),
|
|
749
|
+
...catalog.names().map(name => ({name, reason: 'available topic'})),
|
|
750
|
+
];
|
|
751
|
+
}
|
|
752
|
+
return new AstryxError(
|
|
753
|
+
`Unknown topic "${String(topic)}"${notLoaded(catalog)}`,
|
|
754
|
+
suggestions,
|
|
755
|
+
ERROR_CODES.ERR_UNKNOWN_TOPIC,
|
|
756
|
+
);
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
/**
|
|
760
|
+
* A sentence naming the packages whose docs did not load, or nothing: a doc
|
|
761
|
+
* that fails to load withdraws its package's docs, so a reader who cannot
|
|
762
|
+
* find one learns where to look.
|
|
763
|
+
* @param {DocsCatalog} catalog
|
|
764
|
+
* @returns {string}
|
|
765
|
+
*/
|
|
766
|
+
export function notLoaded(catalog) {
|
|
767
|
+
const packages = [...new Set(catalog.issues.map(issue => issue.package))];
|
|
768
|
+
if (packages.length === 0) return '';
|
|
769
|
+
return `. The docs of ${packages.join(', ')} did not load; run \`astryx doctor integration docs\` in that package to see why.`;
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
/**
|
|
773
|
+
* Resolve a topic (a flat one, or a guide the docs tree places by its route)
|
|
774
|
+
* and lower it for the topic readers.
|
|
775
|
+
* @param {unknown} topic
|
|
776
|
+
* @param {{lang?: string | null, zh?: boolean, dense?: boolean, cwd?: string}} [options]
|
|
777
|
+
*/
|
|
778
|
+
export async function resolveTopicDocs(topic, options = {}) {
|
|
779
|
+
const {lang = null, zh = false, dense = false, cwd} = options;
|
|
780
|
+
const effectiveLang = lang || (dense ? 'dense' : zh ? 'zh' : null);
|
|
781
|
+
// A public API caller could pass a non-string topic; it lands on the same
|
|
782
|
+
// stable code as an unknown name rather than a raw TypeError.
|
|
783
|
+
const found = await resolveDocsArgument(topic, {cwd});
|
|
784
|
+
if (found.kind !== 'topic') {
|
|
785
|
+
throw found.kind === 'node'
|
|
786
|
+
? new AstryxError(
|
|
787
|
+
`"${found.node.route}" is a ${found.node.kind === 'namespace' ? 'namespace' : `${found.node.kind} doc`} in the docs tree, not a topic. Read it with \`astryx docs ${found.node.route}\`.`,
|
|
788
|
+
undefined,
|
|
789
|
+
ERROR_CODES.ERR_UNKNOWN_TOPIC,
|
|
790
|
+
)
|
|
791
|
+
: await unknownTopicError(topic, found.catalog);
|
|
792
|
+
}
|
|
793
|
+
const {catalog, entry} = found;
|
|
794
|
+
const node = await lowerTopic(catalog, entry, effectiveLang);
|
|
795
|
+
return {catalog, node, lang: effectiveLang, entry};
|
|
170
796
|
}
|