@astryxdesign/cli 0.6.3-canary.db4e378 → 0.6.3-canary.db52d98
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 +38 -15
- package/api/blog/blog.doc.mjs +1 -0
- package/api/build/_adapter.d.mts +50 -0
- package/api/build/_adapter.mjs +60 -0
- package/api/build/build.doc.mjs +14 -7
- package/api/build/build.test.mjs +184 -6
- package/api/build/build.type.d.mts +57 -2
- package/api/build/build.type.mjs +30 -7
- package/api/build/help/help.d.mts +4 -0
- package/api/build/help/help.mjs +24 -11
- package/api/build/kit/kit.d.mts +4 -1
- package/api/build/kit/kit.mjs +165 -49
- package/api/build/kit/rank.d.mts +44 -0
- package/api/build/kit/rank.mjs +432 -0
- package/api/build/kit/rank.test.mjs +196 -0
- package/api/component/_adapter.d.mts +6 -12
- package/api/component/_adapter.mjs +20 -10
- package/api/component/component.doc.mjs +1 -0
- package/api/component/component.mjs +60 -12
- package/api/component/list/list.mjs +3 -2
- package/api/discover/discover.doc.mjs +1 -0
- package/api/docs/_adapter.d.mts +252 -34
- package/api/docs/_adapter.mjs +923 -132
- package/api/docs/detail/detail.mjs +11 -3
- package/api/docs/detail/section/section.mjs +24 -13
- package/api/docs/detail/section/section.test.mjs +15 -6
- package/api/docs/docs.d.mts +5 -3
- package/api/docs/docs.doc.mjs +39 -17
- package/api/docs/docs.mjs +44 -8
- package/api/docs/docs.test.mjs +158 -4
- package/api/docs/docs.type.d.mts +181 -2
- package/api/docs/docs.type.mjs +117 -3
- package/api/docs/index/index.mjs +11 -3
- package/api/docs/index/index.test.mjs +1 -1
- package/api/docs/integration-tree.test.mjs +555 -0
- package/api/docs/integrationDocs.test.mjs +14 -14
- 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/docs/reference-blocks.test.mjs +406 -0
- package/api/doctor/doctor.d.mts +54 -4
- package/api/doctor/doctor.doc.mjs +1 -0
- package/api/doctor/doctor.mjs +331 -16
- package/api/doctor/doctor.test.mjs +420 -7
- package/api/gap-report/gap-report.doc.mjs +1 -0
- package/api/hook/_adapter.mjs +19 -5
- package/api/hook/hook.doc.mjs +1 -0
- package/api/hook/list/list.d.mts +1 -1
- 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 +2 -1
- package/api/integration/add-contribution.d.mts +2 -1
- package/api/integration/add-contribution.mjs +114 -12
- package/api/integration/add-contribution.test.mjs +174 -3
- package/api/integration/add-theme.mjs +34 -64
- package/api/integration/add-theme.test.mjs +105 -21
- package/api/integration/authoring-checks.mjs +138 -28
- package/api/integration/authoring-checks.test.mjs +179 -7
- package/api/integration/authoring-checks.type.mjs +6 -1
- package/api/integration/integration-authoring.type.d.mts +2 -0
- 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 +7 -0
- package/api/integration/integrationAddAgentDoc.doc.mjs +1 -0
- package/api/integration/integrationAddCodemod.doc.mjs +1 -0
- package/api/integration/integrationAddComponent.doc.mjs +1 -0
- 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.d.mts +3 -0
- package/api/integration/integrationTemplateConflicts.doc.mjs +4 -0
- package/api/integration/pack-check.mjs +34 -0
- package/api/integration/pack-check.test.mjs +138 -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/template-conflict-compatibility.test.mjs +73 -0
- package/api/integration/validate-integration-fixes.test.mjs +1389 -0
- package/api/integration/validate-integration.mjs +50 -102
- package/api/integration/validate-integration.test.mjs +88 -26
- package/api/integration/validate-unread-theme-folders.test.mjs +110 -0
- package/api/integration/validateIntegration.doc.mjs +2 -1
- package/api/json/assertResponse.doc.mjs +1 -0
- package/api/json/index.ts +2 -0
- package/api/json/isError.doc.mjs +1 -0
- package/api/json/parseResponse.doc.mjs +1 -0
- package/api/layout/_adapter.mjs +20 -5
- package/api/layout/layoutCheck.doc.mjs +1 -0
- package/api/layout/layoutExpand.doc.mjs +1 -0
- package/api/layout/layoutGrammar.doc.mjs +1 -0
- package/api/search/search.d.mts +59 -1
- package/api/search/search.doc.mjs +5 -3
- package/api/search/search.mjs +458 -77
- package/api/search/search.test.mjs +91 -2
- package/api/search/search.type.d.mts +13 -1
- package/api/search/search.type.mjs +4 -1
- package/api/swizzle/swizzle.doc.mjs +1 -0
- package/api/template/list/list.mjs +1 -0
- package/api/template/table-floating-bulk-actions.test.mjs +66 -0
- package/api/template/template-integration.test.mjs +1072 -3
- package/api/template/template-suffix.test.mjs +41 -21
- package/api/template/template.doc.mjs +28 -7
- package/api/template/template.mjs +45 -8
- package/api/template/template.type.d.mts +6 -8
- package/api/template/template.type.mjs +3 -2
- package/api/theme/_adapter.d.mts +2 -3
- package/api/theme/_adapter.mjs +4 -5
- package/api/theme/add/add.binary.test.mjs +10 -17
- package/api/theme/add/add.test.mjs +14 -1
- 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/template/template.test.mjs +5 -0
- package/api/theme/themeAdd.doc.mjs +4 -3
- package/api/theme/themeBuild.doc.mjs +1 -0
- 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 +2 -1
- package/api/upgrade/_adapter.d.mts +32 -5
- package/api/upgrade/_adapter.mjs +97 -69
- package/api/upgrade/provider-agreement.test.mjs +152 -0
- package/api/upgrade/run/run.mjs +356 -59
- package/api/upgrade/upgrade.doc.mjs +6 -1
- package/api/upgrade/upgrade.type.d.mts +34 -0
- package/api/upgrade/upgrade.type.mjs +15 -0
- package/assets/codemods/__tests__/runner.test.mjs +330 -8
- package/assets/codemods/integration-discovery.mjs +8 -2
- package/assets/codemods/integration-discovery.test.mjs +15 -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/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/docs/getting-started.doc.mjs +2 -2
- package/assets/docs/layout.doc.dense.mjs +2 -2
- package/assets/docs/layout.doc.mjs +1 -1
- 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 +5 -5
- 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} +66 -38
- 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 +3 -3
- package/assets/templates/blocks/components/CheckboxList/CheckboxListSelectAllPattern.doc.mjs +1 -1
- package/assets/templates/blocks/components/CheckboxList/CheckboxListSelectAllPattern.tsx +1 -3
- 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/Table/TableBulkActionsTable.doc.mjs +14 -0
- package/assets/templates/blocks/components/Table/TableBulkActionsTable.tsx +71 -0
- package/assets/templates/blocks/components/Table/TableFloatingBulkActionsTable.doc.mjs +19 -0
- package/assets/templates/blocks/components/Table/TableFloatingBulkActionsTable.tsx +139 -0
- package/assets/templates/blocks/components/TimeInput/TimeInputConstrained.tsx +1 -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/codemod/codemod.doc.mjs +1 -1
- package/authoring/codemod/type.ts +12 -0
- package/authoring/config/config.doc.mjs +1 -1
- package/authoring/debug/debug.doc.d.mts +11 -0
- package/authoring/debug/debug.doc.mjs +182 -0
- package/authoring/debug/parse.d.mts +3 -3
- package/authoring/doctypes/_schema.d.mts +119 -117
- package/authoring/doctypes/_schema.mjs +54 -3
- package/authoring/doctypes/base/graph-fields.doc.mjs +8 -6
- package/authoring/doctypes/base/type.ts +6 -5
- package/authoring/doctypes/command/command.doc.mjs +1 -1
- package/authoring/doctypes/command/type.ts +2 -2
- package/authoring/doctypes/component/type.ts +2 -2
- package/authoring/doctypes/doctypes-new.test.mjs +48 -6
- package/authoring/doctypes/enum/enum.doc.mjs +1 -1
- package/authoring/doctypes/enum/type.ts +1 -1
- package/authoring/doctypes/function/function.doc.mjs +3 -2
- package/authoring/doctypes/function/type.ts +3 -2
- package/authoring/doctypes/hook/type.ts +2 -2
- package/authoring/doctypes/load-contract.test.mjs +28 -2
- package/authoring/doctypes/namespace/namespace.doc.mjs +6 -10
- package/authoring/doctypes/namespace/parse.test.mjs +23 -25
- package/authoring/doctypes/namespace/type.ts +5 -2
- package/authoring/doctypes/parse.d.mts +4 -2
- package/authoring/doctypes/parse.mjs +10 -5
- package/authoring/doctypes/reference/reference.doc.mjs +35 -6
- package/authoring/doctypes/reference/type.ts +30 -13
- package/authoring/doctypes/schema/schema.doc.mjs +1 -1
- package/authoring/doctypes/schema/type.ts +1 -2
- package/authoring/doctypes/template/parse.d.mts +2 -0
- package/authoring/doctypes/template/parse.mjs +4 -0
- package/authoring/doctypes/template/parse.test.mjs +18 -0
- package/authoring/doctypes/template/template.doc.mjs +9 -3
- package/authoring/doctypes/template/type.ts +8 -0
- 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 +2 -1
- package/authoring/gap-report/gap-report.doc.d.mts +12 -0
- package/authoring/gap-report/gap-report.doc.mjs +183 -0
- package/authoring/identity/identity.doc.mjs +2 -2
- package/authoring/index.d.mts +1 -0
- package/authoring/index.d.ts +7 -4
- package/authoring/index.mjs +2 -1
- package/authoring/integration/integration.doc.mjs +2 -2
- package/authoring/integration/type.ts +4 -10
- package/clients/cli/__tests__/cliManifest.test.ts +27 -29
- package/clients/cli/commands/blog.doc.mjs +1 -1
- package/clients/cli/commands/build-theme.adaptations.test.mjs +100 -1
- package/clients/cli/commands/build-theme.mjs +11 -45
- package/clients/cli/commands/build.doc.mjs +12 -7
- package/clients/cli/commands/build.mjs +105 -67
- package/clients/cli/commands/build.text-fields.test.mjs +41 -0
- package/clients/cli/commands/component/index.mjs +1 -1
- package/clients/cli/commands/component-ownership.test.mjs +3 -3
- package/clients/cli/commands/component.doc.mjs +1 -1
- package/clients/cli/commands/discover.broken-integration.test.mjs +7 -8
- package/clients/cli/commands/discover.doc.mjs +1 -1
- package/clients/cli/commands/discover.mjs +1 -1
- package/clients/cli/commands/docs.doc.mjs +21 -9
- package/clients/cli/commands/docs.mjs +184 -70
- package/clients/cli/commands/docs.test.mjs +120 -16
- 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.test.mjs +90 -8
- package/clients/cli/commands/doctor.doc.mjs +1 -1
- package/clients/cli/commands/doctor.mjs +53 -16
- package/clients/cli/commands/gap-report.doc.mjs +1 -1
- package/clients/cli/commands/hook.doc.mjs +1 -1
- package/clients/cli/commands/init.doc.mjs +1 -1
- package/clients/cli/commands/integration-add.controls.test.mjs +1 -1
- package/clients/cli/commands/integration-add.doc.mjs +11 -1
- 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/layout-check.doc.mjs +1 -1
- package/clients/cli/commands/layout-expand.doc.mjs +1 -1
- package/clients/cli/commands/layout-grammar.doc.mjs +1 -1
- package/clients/cli/commands/layout.doc.mjs +1 -1
- package/clients/cli/commands/manifest.doc.mjs +1 -1
- package/clients/cli/commands/search.doc.mjs +1 -1
- package/clients/cli/commands/search.mjs +11 -2
- package/clients/cli/commands/setup-nudge.test.mjs +6 -0
- package/clients/cli/commands/swizzle.doc.mjs +1 -1
- package/clients/cli/commands/template.doc.mjs +24 -7
- package/clients/cli/commands/template.mjs +4 -91
- package/clients/cli/commands/text-json-parity.test.mjs +719 -0
- package/clients/cli/commands/theme-add.doc.mjs +2 -2
- package/clients/cli/commands/theme-build.doc.mjs +1 -1
- package/clients/cli/commands/theme-list.doc.mjs +2 -2
- package/clients/cli/commands/theme-palette-generate.doc.mjs +3 -3
- 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.doc.mjs +1 -1
- package/clients/cli/commands/theme.doc.mjs +1 -1
- package/clients/cli/commands/upgrade.doc.mjs +3 -2
- package/clients/cli/commands/upgrade.file-protection.test.mjs +228 -0
- package/clients/cli/commands/upgrade.mjs +29 -7
- package/clients/cli/formatters/index.mjs +2 -0
- package/clients/cli/formatters/index.test.mjs +6 -0
- package/clients/cli/index.mjs +8 -0
- package/clients/cli/lib/hook-format.mjs +14 -5
- package/clients/cli/lib/manifest.mjs +9 -2
- package/foundation/agent-docs/agent-docs.d.mts +3 -2
- package/foundation/agent-docs/agent-docs.mjs +13 -9
- package/foundation/agent-docs/agent-docs.test.mjs +19 -1
- package/foundation/config/project-themes.test.mjs +11 -19
- package/foundation/config/project.d.mts +20 -11
- package/foundation/config/project.mjs +123 -80
- package/foundation/config/project.test.mjs +144 -21
- package/foundation/discovery/authoring-self-docs.d.mts +18 -0
- package/foundation/discovery/authoring-self-docs.mjs +37 -15
- package/foundation/discovery/authoring-self-docs.test.mjs +25 -9
- 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 +38 -0
- package/foundation/discovery/component-discovery.mjs +48 -0
- package/foundation/discovery/component-loader.d.mts +35 -38
- package/foundation/discovery/component-loader.mjs +53 -222
- package/foundation/discovery/docs-discovery.d.mts +112 -11
- package/foundation/discovery/docs-discovery.mjs +231 -36
- package/foundation/discovery/docs-discovery.test.mjs +111 -32
- package/foundation/discovery/docs-output-budget.d.mts +2 -2
- package/foundation/discovery/docs-output-budget.mjs +1 -1
- package/foundation/discovery/docs-section-key.d.mts +28 -10
- package/foundation/discovery/docs-section-key.mjs +134 -33
- package/foundation/discovery/docs-section-key.test.mjs +41 -19
- package/foundation/discovery/template-adapter.d.mts +99 -6
- package/foundation/discovery/template-adapter.mjs +480 -57
- package/foundation/discovery/template-adapter.test.mjs +57 -0
- package/foundation/discovery/template-conflict-release.d.mts +13 -0
- package/foundation/discovery/template-conflict-release.mjs +40 -0
- package/foundation/discovery/template-conflict-release.test.mjs +40 -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/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 +220 -39
- package/foundation/doc-compiler/compile.mjs +311 -15
- 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 +28 -1
- 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 +13 -0
- package/foundation/doc-compiler/ir.mjs +196 -12
- package/foundation/doc-compiler/lenses.d.mts +8 -5
- package/foundation/doc-compiler/lenses.mjs +50 -4
- package/foundation/doc-compiler/links.d.mts +162 -0
- package/foundation/doc-compiler/links.mjs +294 -0
- package/foundation/doc-compiler/links.test.mjs +192 -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/integrations/autolink.d.mts +58 -1
- package/foundation/integrations/autolink.mjs +143 -57
- 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 +84 -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 +51 -26
- package/foundation/integrations/integration-warnings.test.mjs +74 -1
- package/foundation/integrations/integrations.d.mts +3 -0
- package/foundation/integrations/integrations.mjs +11 -97
- 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.mjs +121 -29
- 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 +12 -2
- package/foundation/response/error-codes.mjs +7 -1
- package/foundation/response/error-codes.test.mjs +55 -11
- package/foundation/response/response-types.doc.d.mts +5 -1
- package/foundation/response/response-types.doc.mjs +20 -11
- package/foundation/response/response.doc.mjs +1 -1
- package/foundation/text/string-utils.d.mts +8 -0
- package/foundation/text/string-utils.mjs +40 -10
- package/foundation/xle/expand.mjs +1 -1
- package/foundation/xle/xle.test.mjs +13 -0
- package/package.json +10 -9
- package/assets/templates/themes/manifest.json +0 -95
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
*/
|
|
16
16
|
/**
|
|
17
17
|
* Compute the files the tarball must contain for an integration's
|
|
18
|
-
* contributions to be visible.
|
|
18
|
+
* contributions to be visible. Walks descriptor-owned directories;
|
|
19
19
|
* never imports or executes authored modules.
|
|
20
20
|
*
|
|
21
21
|
* @param {import('./integrations.mjs').LoadedIntegration} loaded
|
|
@@ -26,7 +26,7 @@ export function computeRequiredFiles(loaded: import("./integrations.mjs").Loaded
|
|
|
26
26
|
* @typedef {object} ContributionIdentities
|
|
27
27
|
* @property {{slug: string, exportName: string}[]} themes
|
|
28
28
|
* @property {string[]} components
|
|
29
|
-
* @property {{id: string, type: string, name: string}[]} templates
|
|
29
|
+
* @property {{id: string, type: string, name: string, replaces?: string}[]} templates
|
|
30
30
|
* @property {{version: string, id: string}[]} codemods
|
|
31
31
|
* @property {string[]} docs
|
|
32
32
|
* @property {string[]} agentDocsAppend
|
|
@@ -127,6 +127,7 @@ export type ContributionIdentities = {
|
|
|
127
127
|
id: string;
|
|
128
128
|
type: string;
|
|
129
129
|
name: string;
|
|
130
|
+
replaces?: string;
|
|
130
131
|
}[];
|
|
131
132
|
codemods: {
|
|
132
133
|
version: string;
|
|
@@ -14,8 +14,11 @@
|
|
|
14
14
|
import * as fs from 'node:fs';
|
|
15
15
|
import * as path from 'node:path';
|
|
16
16
|
import {isDeepStrictEqual} from 'node:util';
|
|
17
|
-
import {
|
|
18
|
-
|
|
17
|
+
import {
|
|
18
|
+
discoverIntegrationThemes,
|
|
19
|
+
isThemeFolder,
|
|
20
|
+
listThemeFiles,
|
|
21
|
+
} from '../discovery/theme-discovery.mjs';
|
|
19
22
|
import {discoverIntegrationComponents} from '../discovery/component-discovery.mjs';
|
|
20
23
|
import {loadComponentDoc} from '../discovery/component-loader.mjs';
|
|
21
24
|
import {discoverIntegrationTemplatesForOne} from '../discovery/template-adapter.mjs';
|
|
@@ -65,27 +68,21 @@ function rel(packageDir, file) {
|
|
|
65
68
|
|
|
66
69
|
/** @param {string} root @param {string} pkgDir */
|
|
67
70
|
function enumerateThemeFiles(root, pkgDir) {
|
|
71
|
+
if (!root || !fs.existsSync(root) || !fs.statSync(root).isDirectory()) {
|
|
72
|
+
return [];
|
|
73
|
+
}
|
|
74
|
+
// Exactly what `theme add` copies: each theme folder's files, including
|
|
75
|
+
// tests and fixtures, but no dot entry or file npm never publishes. Files
|
|
76
|
+
// beside the theme folders belong to no theme.
|
|
68
77
|
/** @type {string[]} */
|
|
69
78
|
const files = [];
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
const data = JSON.parse(fs.readFileSync(catalog, 'utf-8'));
|
|
75
|
-
if (data?.version !== 1 || !Array.isArray(data.themes)) return files;
|
|
76
|
-
for (const theme of data.themes) {
|
|
77
|
-
if (typeof theme.slug !== 'string' || !Array.isArray(theme.files))
|
|
78
|
-
continue;
|
|
79
|
-
for (const f of theme.files) {
|
|
80
|
-
if (typeof f === 'string') {
|
|
81
|
-
files.push(rel(pkgDir, path.join(root, theme.slug, f)));
|
|
82
|
-
}
|
|
83
|
-
}
|
|
79
|
+
for (const entry of fs.readdirSync(root, {withFileTypes: true})) {
|
|
80
|
+
const full = path.join(root, entry.name);
|
|
81
|
+
if (entry.isDirectory() && isThemeFolder(full)) {
|
|
82
|
+
files.push(...listThemeFiles(full).map(file => path.join(full, file)));
|
|
84
83
|
}
|
|
85
|
-
} catch {
|
|
86
|
-
/* Phase 1 catches structural issues */
|
|
87
84
|
}
|
|
88
|
-
return files;
|
|
85
|
+
return files.sort().map(file => rel(pkgDir, file));
|
|
89
86
|
}
|
|
90
87
|
|
|
91
88
|
/** @param {string} root @param {string} pkgDir */
|
|
@@ -158,7 +155,7 @@ const ROOT_KINDS = /** @type {const} */ ([
|
|
|
158
155
|
|
|
159
156
|
/**
|
|
160
157
|
* Compute the files the tarball must contain for an integration's
|
|
161
|
-
* contributions to be visible.
|
|
158
|
+
* contributions to be visible. Walks descriptor-owned directories;
|
|
162
159
|
* never imports or executes authored modules.
|
|
163
160
|
*
|
|
164
161
|
* @param {import('./integrations.mjs').LoadedIntegration} loaded
|
|
@@ -192,7 +189,7 @@ export function computeRequiredFiles(loaded) {
|
|
|
192
189
|
* @typedef {object} ContributionIdentities
|
|
193
190
|
* @property {{slug: string, exportName: string}[]} themes
|
|
194
191
|
* @property {string[]} components
|
|
195
|
-
* @property {{id: string, type: string, name: string}[]} templates
|
|
192
|
+
* @property {{id: string, type: string, name: string, replaces?: string}[]} templates
|
|
196
193
|
* @property {{version: string, id: string}[]} codemods
|
|
197
194
|
* @property {string[]} docs
|
|
198
195
|
* @property {string[]} agentDocsAppend
|
|
@@ -281,7 +278,12 @@ export async function collectIdentities(loaded) {
|
|
|
281
278
|
errors.push({kind: 'templates', message: templateError.message});
|
|
282
279
|
}
|
|
283
280
|
identities.templates = templates
|
|
284
|
-
.map(t => ({
|
|
281
|
+
.map(t => ({
|
|
282
|
+
id: t.dirName,
|
|
283
|
+
type: t.type,
|
|
284
|
+
name: t.name,
|
|
285
|
+
...(t.replaces == null ? {} : {replaces: t.replaces}),
|
|
286
|
+
}))
|
|
285
287
|
.sort((a, b) => a.id.localeCompare(b.id));
|
|
286
288
|
} catch (err) {
|
|
287
289
|
errors.push({
|
|
@@ -312,12 +314,13 @@ export async function collectIdentities(loaded) {
|
|
|
312
314
|
|
|
313
315
|
if (loaded.docs && fs.existsSync(loaded.docs)) {
|
|
314
316
|
try {
|
|
315
|
-
const {records, errors: docErrors} =
|
|
317
|
+
const {records, guides, errors: docErrors} =
|
|
316
318
|
await discoverIntegrationDocs(loaded);
|
|
317
319
|
for (const docError of docErrors) {
|
|
318
320
|
errors.push({kind: 'docs', message: docError.message});
|
|
319
321
|
}
|
|
320
|
-
|
|
322
|
+
// A guide placed in the docs tree is a doc contribution too.
|
|
323
|
+
identities.docs = [...records, ...guides].map(r => r.name).sort();
|
|
321
324
|
} catch (err) {
|
|
322
325
|
errors.push({kind: 'docs', message: /** @type {Error} */ (err).message});
|
|
323
326
|
}
|
|
@@ -37,30 +37,37 @@ function loaded(overrides = {}) {
|
|
|
37
37
|
|
|
38
38
|
function writeTheme(slug, files = [`${slug}Theme.ts`]) {
|
|
39
39
|
const root = path.join(tmpDir, 'themes');
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
const themeDir = path.join(root, slug);
|
|
41
|
+
fs.mkdirSync(themeDir, {recursive: true});
|
|
42
|
+
for (const file of files) {
|
|
43
|
+
const target = path.join(themeDir, file);
|
|
44
|
+
fs.mkdirSync(path.dirname(target), {recursive: true});
|
|
45
|
+
fs.writeFileSync(target, `// ${file}\n`);
|
|
43
46
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
catalog.themes.push({
|
|
50
|
-
slug,
|
|
51
|
-
displayName: slug,
|
|
52
|
-
description: `${slug} theme.`,
|
|
53
|
-
maintained: true,
|
|
54
|
-
entry: files[0],
|
|
55
|
-
exportName: `${slug}Theme`,
|
|
56
|
-
files,
|
|
57
|
-
});
|
|
58
|
-
fs.writeFileSync(catalogPath, JSON.stringify(catalog, null, 2) + '\n');
|
|
47
|
+
fs.writeFileSync(
|
|
48
|
+
path.join(themeDir, `${slug}Theme.doc.mjs`),
|
|
49
|
+
`/** @type {import('@astryxdesign/cli/authoring').ThemeDoc} */\nexport default {type: 'theme', name: '${slug}', displayName: '${slug}', description: '${slug} theme.', maintained: true};\n`,
|
|
50
|
+
);
|
|
59
51
|
return root;
|
|
60
52
|
}
|
|
61
53
|
|
|
54
|
+
const UNPUBLISHED = [
|
|
55
|
+
'.DS_Store',
|
|
56
|
+
'._oceanTheme.ts',
|
|
57
|
+
'.gitignore',
|
|
58
|
+
'.npmignore',
|
|
59
|
+
'.npmrc',
|
|
60
|
+
'oceanTheme.ts.orig',
|
|
61
|
+
'npm-debug.log',
|
|
62
|
+
'palette/.DS_Store',
|
|
63
|
+
'palette/npm-debug.log',
|
|
64
|
+
'.git/HEAD',
|
|
65
|
+
'CVS/Entries',
|
|
66
|
+
'node_modules/dep/index.js',
|
|
67
|
+
];
|
|
68
|
+
|
|
62
69
|
describe('computeRequiredFiles', () => {
|
|
63
|
-
it('enumerates
|
|
70
|
+
it('enumerates each complete descriptor-owned theme directory', () => {
|
|
64
71
|
const root = writeTheme('ocean', ['oceanTheme.ts', 'tokens.ts']);
|
|
65
72
|
const inv = computeRequiredFiles(loaded({themes: root}));
|
|
66
73
|
|
|
@@ -69,13 +76,46 @@ describe('computeRequiredFiles', () => {
|
|
|
69
76
|
expect(inv.roots[0].kind).toBe('themes');
|
|
70
77
|
expect(inv.roots[0].files).toEqual(
|
|
71
78
|
expect.arrayContaining([
|
|
72
|
-
'themes/
|
|
79
|
+
'themes/ocean/oceanTheme.doc.mjs',
|
|
73
80
|
'themes/ocean/oceanTheme.ts',
|
|
74
81
|
'themes/ocean/tokens.ts',
|
|
75
82
|
]),
|
|
76
83
|
);
|
|
77
84
|
expect(inv.allFiles).toContain('astryx.integration.mjs');
|
|
78
|
-
expect(inv.allFiles).toContain('themes/
|
|
85
|
+
expect(inv.allFiles).toContain('themes/ocean/oceanTheme.doc.mjs');
|
|
86
|
+
expect(inv.allFiles).not.toContain('themes/manifest.json');
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('requires no file npm leaves out, at any depth, and none beside the themes', () => {
|
|
90
|
+
const root = writeTheme('ocean', ['oceanTheme.ts', 'palette/tokens.ts']);
|
|
91
|
+
for (const file of [
|
|
92
|
+
...UNPUBLISHED.map(name => `ocean/${name}`),
|
|
93
|
+
'README.md',
|
|
94
|
+
'npm-debug.log',
|
|
95
|
+
]) {
|
|
96
|
+
fs.mkdirSync(path.dirname(path.join(root, file)), {recursive: true});
|
|
97
|
+
fs.writeFileSync(path.join(root, file), 'x\n');
|
|
98
|
+
}
|
|
99
|
+
expect(computeRequiredFiles(loaded({themes: root})).roots[0].files).toEqual(
|
|
100
|
+
[
|
|
101
|
+
'themes/ocean/oceanTheme.doc.mjs',
|
|
102
|
+
'themes/ocean/oceanTheme.ts',
|
|
103
|
+
'themes/ocean/palette/tokens.ts',
|
|
104
|
+
],
|
|
105
|
+
);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('requires only the folders theme discovery reads', () => {
|
|
109
|
+
const root = writeTheme('ocean');
|
|
110
|
+
for (const file of ['shared/palette.ts', '.cache/state.json']) {
|
|
111
|
+
fs.mkdirSync(path.dirname(path.join(root, file)), {recursive: true});
|
|
112
|
+
fs.writeFileSync(path.join(root, file), '{}\n');
|
|
113
|
+
}
|
|
114
|
+
const inv = computeRequiredFiles(loaded({themes: root}));
|
|
115
|
+
expect(inv.roots[0].files).toEqual([
|
|
116
|
+
'themes/ocean/oceanTheme.doc.mjs',
|
|
117
|
+
'themes/ocean/oceanTheme.ts',
|
|
118
|
+
]);
|
|
79
119
|
});
|
|
80
120
|
|
|
81
121
|
it('enumerates paired component metadata and source files', () => {
|
|
@@ -139,31 +179,31 @@ describe('computeRequiredFiles', () => {
|
|
|
139
179
|
const root = path.join(tmpDir, 'templates');
|
|
140
180
|
fs.mkdirSync(path.join(root, 'dashboard'), {recursive: true});
|
|
141
181
|
fs.writeFileSync(
|
|
142
|
-
path.join(root, 'dashboard', 'dashboard.
|
|
182
|
+
path.join(root, 'dashboard', 'dashboard.doc.mjs'),
|
|
143
183
|
'// tmpl\n',
|
|
144
184
|
);
|
|
145
185
|
fs.writeFileSync(path.join(root, 'dashboard', 'dashboard.tsx'), '// src\n');
|
|
146
186
|
const inv = computeRequiredFiles(loaded({templates: root}));
|
|
147
187
|
|
|
148
188
|
expect(inv.roots[0].files).toContain(
|
|
149
|
-
'templates/dashboard/dashboard.
|
|
189
|
+
'templates/dashboard/dashboard.doc.mjs',
|
|
150
190
|
);
|
|
151
191
|
expect(inv.roots[0].files).toContain('templates/dashboard/dashboard.tsx');
|
|
152
192
|
});
|
|
153
193
|
|
|
154
|
-
it('enumerates
|
|
194
|
+
it('enumerates released .template compatibility metadata with paired sources', () => {
|
|
155
195
|
const root = path.join(tmpDir, 'templates');
|
|
156
196
|
fs.mkdirSync(path.join(root, 'dashboard'), {recursive: true});
|
|
157
197
|
fs.writeFileSync(
|
|
158
|
-
path.join(root, 'dashboard', 'dashboard.
|
|
159
|
-
'//
|
|
198
|
+
path.join(root, 'dashboard', 'dashboard.template.mjs'),
|
|
199
|
+
'// released compatibility template\n',
|
|
160
200
|
);
|
|
161
201
|
fs.writeFileSync(path.join(root, 'dashboard', 'dashboard.tsx'), '// src\n');
|
|
162
202
|
|
|
163
203
|
const inv = computeRequiredFiles(loaded({templates: root}));
|
|
164
204
|
|
|
165
205
|
expect(inv.roots[0].files).toEqual([
|
|
166
|
-
'templates/dashboard/dashboard.
|
|
206
|
+
'templates/dashboard/dashboard.template.mjs',
|
|
167
207
|
'templates/dashboard/dashboard.tsx',
|
|
168
208
|
]);
|
|
169
209
|
});
|
|
@@ -264,6 +304,25 @@ describe('compareIdentities', () => {
|
|
|
264
304
|
expect(issues[0].message).toContain('dash');
|
|
265
305
|
});
|
|
266
306
|
|
|
307
|
+
it('errors when a packed template replaces a different target', () => {
|
|
308
|
+
const template = {id: 'acme-shell', type: 'page', name: 'Acme shell'};
|
|
309
|
+
const local = {
|
|
310
|
+
...base(),
|
|
311
|
+
templates: [{...template, replaces: 'shell-side-nav'}],
|
|
312
|
+
};
|
|
313
|
+
const packed = {
|
|
314
|
+
...base(),
|
|
315
|
+
templates: [{...template, replaces: 'shell-top-nav'}],
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
expect(compareIdentities(local, packed)).toEqual([
|
|
319
|
+
expect.objectContaining({
|
|
320
|
+
code: 'identity_mismatch',
|
|
321
|
+
message: expect.stringContaining('acme-shell'),
|
|
322
|
+
}),
|
|
323
|
+
]);
|
|
324
|
+
});
|
|
325
|
+
|
|
267
326
|
it('errors when a codemod is missing from packed', () => {
|
|
268
327
|
const local = {
|
|
269
328
|
...base(),
|
|
@@ -8,10 +8,17 @@
|
|
|
8
8
|
*
|
|
9
9
|
* Warning: <pkg> has N integration issue(s). Run: astryx doctor integration validate <pkg>
|
|
10
10
|
*
|
|
11
|
-
* @param {Array<import('./integrations.mjs').LoadedIntegration>
|
|
11
|
+
* @param {Array<import('./integrations.mjs').LoadedIntegration> | {issues: () => Promise<Array<{package: string, code: string, severity: string, message: string}>>}} source loaded integrations or their Project owner
|
|
12
12
|
* @param {{json?: boolean}} [options]
|
|
13
13
|
* @returns {Promise<void>}
|
|
14
14
|
*/
|
|
15
|
-
export function warnOnIntegrationIssues(
|
|
15
|
+
export function warnOnIntegrationIssues(source: Array<import("./integrations.mjs").LoadedIntegration> | {
|
|
16
|
+
issues: () => Promise<Array<{
|
|
17
|
+
package: string;
|
|
18
|
+
code: string;
|
|
19
|
+
severity: string;
|
|
20
|
+
message: string;
|
|
21
|
+
}>>;
|
|
22
|
+
}, { json }?: {
|
|
16
23
|
json?: boolean;
|
|
17
24
|
}): Promise<void>;
|
|
@@ -10,8 +10,9 @@
|
|
|
10
10
|
* contributions or spamming per-contribution diagnostics.
|
|
11
11
|
*
|
|
12
12
|
* Design constraints (all enforced here):
|
|
13
|
-
* - Reuses
|
|
14
|
-
*
|
|
13
|
+
* - Reuses Project.issues() when a Project is available, so cross-package
|
|
14
|
+
* replacement warnings are visible; accepts loaded integrations for legacy
|
|
15
|
+
* internal callers and tests.
|
|
15
16
|
* - Writes to STDERR only, so it never corrupts a --json stdout envelope.
|
|
16
17
|
* - Suppressed entirely in --json mode.
|
|
17
18
|
* - Best-effort: never throws, never changes the exit code. Broken
|
|
@@ -28,38 +29,62 @@ import {validateLoadedIntegration} from './validate-contributions.mjs';
|
|
|
28
29
|
*
|
|
29
30
|
* Warning: <pkg> has N integration issue(s). Run: astryx doctor integration validate <pkg>
|
|
30
31
|
*
|
|
31
|
-
* @param {Array<import('./integrations.mjs').LoadedIntegration>
|
|
32
|
+
* @param {Array<import('./integrations.mjs').LoadedIntegration> | {issues: () => Promise<Array<{package: string, code: string, severity: string, message: string}>>}} source loaded integrations or their Project owner
|
|
32
33
|
* @param {{json?: boolean}} [options]
|
|
33
34
|
* @returns {Promise<void>}
|
|
34
35
|
*/
|
|
35
|
-
export async function warnOnIntegrationIssues(
|
|
36
|
+
export async function warnOnIntegrationIssues(source, {json = false} = {}) {
|
|
36
37
|
try {
|
|
37
|
-
// Cheap guard: only do work when integrations are actually configured.
|
|
38
38
|
if (json) return;
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
39
|
+
|
|
40
|
+
/** @type {Map<string, number>} */
|
|
41
|
+
const issueCounts = new Map();
|
|
42
|
+
const fromProject =
|
|
43
|
+
source != null &&
|
|
44
|
+
!Array.isArray(source) &&
|
|
45
|
+
typeof source.issues === 'function';
|
|
46
|
+
|
|
47
|
+
if (fromProject) {
|
|
48
|
+
const issues = await source.issues();
|
|
49
|
+
for (const issue of issues) {
|
|
50
|
+
// A provider-conflict issue carries the specific message that
|
|
51
|
+
// `doctor integration validate` would not explain. Print it directly.
|
|
52
|
+
if (issue.code === 'duplicate_provider') {
|
|
53
|
+
console.error(`Warning: ${issue.message}`);
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
issueCounts.set(
|
|
57
|
+
issue.package,
|
|
58
|
+
(issueCounts.get(issue.package) ?? 0) + 1,
|
|
59
|
+
);
|
|
49
60
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
//
|
|
55
|
-
|
|
61
|
+
} else if (Array.isArray(source)) {
|
|
62
|
+
for (const integration of source) {
|
|
63
|
+
if (!integration || typeof integration !== 'object') continue;
|
|
64
|
+
// A package set aside for a provider-ID conflict is fine in isolation,
|
|
65
|
+
// so `doctor integration validate` would not explain it. Say it here.
|
|
66
|
+
if (integration.__providerConflict) {
|
|
67
|
+
console.error(`Warning: ${integration.__providerConflict.message}`);
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
let issues;
|
|
71
|
+
try {
|
|
72
|
+
issues = await validateLoadedIntegration(integration);
|
|
73
|
+
} catch {
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
if (!Array.isArray(issues) || issues.length === 0) continue;
|
|
77
|
+
const pkg = integration.name ?? integration.__spec ?? '(integration)';
|
|
78
|
+
issueCounts.set(pkg, issues.length);
|
|
56
79
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
for (const [pkg, count] of issueCounts) {
|
|
83
|
+
const command = fromProject
|
|
84
|
+
? 'astryx doctor'
|
|
85
|
+
: `astryx doctor integration validate ${pkg}`;
|
|
60
86
|
console.error(
|
|
61
|
-
`Warning: ${pkg} has ${
|
|
62
|
-
`Run: astryx doctor integration validate ${pkg}`,
|
|
87
|
+
`Warning: ${pkg} has ${count} integration issue(s). Run: ${command}`,
|
|
63
88
|
);
|
|
64
89
|
}
|
|
65
90
|
} catch {
|
|
@@ -37,7 +37,12 @@ afterEach(() => {
|
|
|
37
37
|
* Build a loaded-integration-shaped object. Roots are absolute (mirrors
|
|
38
38
|
* loadIntegrations' resolveRoot).
|
|
39
39
|
*/
|
|
40
|
-
function loaded({
|
|
40
|
+
function loaded({
|
|
41
|
+
name = '@acme/widgets',
|
|
42
|
+
components,
|
|
43
|
+
templates,
|
|
44
|
+
codemods,
|
|
45
|
+
} = {}) {
|
|
41
46
|
return {
|
|
42
47
|
name,
|
|
43
48
|
version: '1.0.0',
|
|
@@ -62,6 +67,25 @@ describe('warnOnIntegrationIssues', () => {
|
|
|
62
67
|
);
|
|
63
68
|
});
|
|
64
69
|
|
|
70
|
+
it('surfaces cross-package issues collected by Project', async () => {
|
|
71
|
+
const project = {
|
|
72
|
+
issues: async () => [
|
|
73
|
+
{
|
|
74
|
+
package: '@acme/later',
|
|
75
|
+
code: 'ambiguous_template_replacement',
|
|
76
|
+
severity: 'warning',
|
|
77
|
+
message: 'Later configured replacement wins.',
|
|
78
|
+
},
|
|
79
|
+
],
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
await warnOnIntegrationIssues(project, {json: false});
|
|
83
|
+
|
|
84
|
+
expect(errLines).toEqual([
|
|
85
|
+
'Warning: @acme/later has 1 integration issue(s). Run: astryx doctor',
|
|
86
|
+
]);
|
|
87
|
+
});
|
|
88
|
+
|
|
65
89
|
it('emits nothing in --json mode (keeps stdout/JSON clean)', async () => {
|
|
66
90
|
const integration = loaded({components: 'does-not-exist'});
|
|
67
91
|
await warnOnIntegrationIssues([integration], {json: true});
|
|
@@ -116,4 +140,53 @@ describe('warnOnIntegrationIssues', () => {
|
|
|
116
140
|
).resolves.toBeUndefined();
|
|
117
141
|
expect(errLines).toHaveLength(0);
|
|
118
142
|
});
|
|
143
|
+
|
|
144
|
+
it('prints the specific provider-conflict message via the array path', async () => {
|
|
145
|
+
const conflict = {
|
|
146
|
+
name: '@acme/charts',
|
|
147
|
+
version: '2.0.0',
|
|
148
|
+
__spec: '@acme/charts',
|
|
149
|
+
__packageDir: tmpDir,
|
|
150
|
+
__providerConflict: {
|
|
151
|
+
providerId: '@acme/lab',
|
|
152
|
+
claimedBy: '@acme/lab',
|
|
153
|
+
message:
|
|
154
|
+
'@acme/charts@2.0.0 and @acme/lab@1.0.0 both claim provider ID ' +
|
|
155
|
+
'"@acme/lab". @acme/lab@1.0.0 loads first and is used; ' +
|
|
156
|
+
'@acme/charts@2.0.0 contributes nothing until one package changes ' +
|
|
157
|
+
'its providerId.',
|
|
158
|
+
},
|
|
159
|
+
};
|
|
160
|
+
await warnOnIntegrationIssues([conflict], {json: false});
|
|
161
|
+
|
|
162
|
+
expect(errLines).toHaveLength(1);
|
|
163
|
+
expect(errLines[0]).toBe(`Warning: ${conflict.__providerConflict.message}`);
|
|
164
|
+
// Must NOT print the generic validate pointer for a provider conflict.
|
|
165
|
+
expect(errLines[0]).not.toContain('integration issue(s)');
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it('prints the specific provider-conflict message via the Project path', async () => {
|
|
169
|
+
const conflictMessage =
|
|
170
|
+
'@acme/charts@2.0.0 and @acme/lab@1.0.0 both claim provider ID ' +
|
|
171
|
+
'"@acme/lab". @acme/lab@1.0.0 loads first and is used; ' +
|
|
172
|
+
'@acme/charts@2.0.0 contributes nothing until one package changes ' +
|
|
173
|
+
'its providerId.';
|
|
174
|
+
const project = {
|
|
175
|
+
issues: async () => [
|
|
176
|
+
{
|
|
177
|
+
package: '@acme/charts@2.0.0',
|
|
178
|
+
code: 'duplicate_provider',
|
|
179
|
+
severity: 'warning',
|
|
180
|
+
message: conflictMessage,
|
|
181
|
+
},
|
|
182
|
+
],
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
await warnOnIntegrationIssues(project, {json: false});
|
|
186
|
+
|
|
187
|
+
expect(errLines).toHaveLength(1);
|
|
188
|
+
expect(errLines[0]).toBe(`Warning: ${conflictMessage}`);
|
|
189
|
+
// Must NOT print the generic validate pointer for a provider conflict.
|
|
190
|
+
expect(errLines[0]).not.toContain('integration issue(s)');
|
|
191
|
+
});
|
|
119
192
|
});
|
|
@@ -14,6 +14,9 @@
|
|
|
14
14
|
* issues, Doctor, and the per-command warning name the one set aside instead of
|
|
15
15
|
* dropping it without a word.
|
|
16
16
|
*
|
|
17
|
+
* The conflict pass of {@link resolveProviders}, for a list that is already
|
|
18
|
+
* assembled.
|
|
19
|
+
*
|
|
17
20
|
* @param {LoadedIntegration[]} integrations in precedence order
|
|
18
21
|
* @returns {LoadedIntegration[]}
|
|
19
22
|
*/
|
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
} from '../../authoring/integration/schema.mjs';
|
|
30
30
|
import {importUserModule, findPresentFiles} from '../fs/module-loader.mjs';
|
|
31
31
|
import {parseGapReportHandler} from '../../authoring/gap-report/parse.mjs';
|
|
32
|
+
import {resolveProviders} from './provider-resolution.mjs';
|
|
32
33
|
|
|
33
34
|
/**
|
|
34
35
|
* A fully-resolved, loaded integration. Identity (`name`, `version`) comes from
|
|
@@ -116,107 +117,20 @@ function providerIdForPackage(name) {
|
|
|
116
117
|
* issues, Doctor, and the per-command warning name the one set aside instead of
|
|
117
118
|
* dropping it without a word.
|
|
118
119
|
*
|
|
120
|
+
* The conflict pass of {@link resolveProviders}, for a list that is already
|
|
121
|
+
* assembled.
|
|
122
|
+
*
|
|
119
123
|
* @param {LoadedIntegration[]} integrations in precedence order
|
|
120
124
|
* @returns {LoadedIntegration[]}
|
|
121
125
|
*/
|
|
122
126
|
export function markProviderConflicts(integrations) {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
}
|
|
131
|
-
/** @type {LoadedIntegration[]} */
|
|
132
|
-
const resolved = [];
|
|
133
|
-
for (const integration of integrations) {
|
|
134
|
-
if (!claimsProvider(integration)) {
|
|
135
|
-
resolved.push(integration);
|
|
136
|
-
continue;
|
|
137
|
-
}
|
|
138
|
-
const providerId = /** @type {string} */ (integration.providerId);
|
|
139
|
-
const claimant = claims.get(providerId);
|
|
140
|
-
if (claimant == null) {
|
|
141
|
-
claims.set(providerId, integration);
|
|
142
|
-
resolved.push(integration);
|
|
143
|
-
} else if (claimant === integration) {
|
|
144
|
-
resolved.push(integration);
|
|
145
|
-
} else if (
|
|
146
|
-
claimant.name !== integration.name ||
|
|
147
|
-
claimant.version !== integration.version
|
|
148
|
-
) {
|
|
149
|
-
resolved.push(providerConflict(integration, claimant));
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
return resolved;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* Whether an entry contributes under its provider ID: it has one, its manifest
|
|
157
|
-
* loaded, and it has not already been set aside.
|
|
158
|
-
* @param {LoadedIntegration | undefined} integration
|
|
159
|
-
* @returns {boolean}
|
|
160
|
-
*/
|
|
161
|
-
function claimsProvider(integration) {
|
|
162
|
-
return (
|
|
163
|
-
integration?.providerId != null &&
|
|
164
|
-
integration.__loadError == null &&
|
|
165
|
-
integration.__providerConflict == null
|
|
166
|
-
);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
* @param {LoadedIntegration} integration
|
|
171
|
-
* @returns {string}
|
|
172
|
-
*/
|
|
173
|
-
function describeIntegration(integration) {
|
|
174
|
-
const id = integration.version
|
|
175
|
-
? `${integration.name}@${integration.version}`
|
|
176
|
-
: integration.name;
|
|
177
|
-
return integration.__spec && integration.__spec !== integration.name
|
|
178
|
-
? `${id} (from "${integration.__spec}")`
|
|
179
|
-
: id;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
/**
|
|
183
|
-
* An inert record for a package whose provider ID is already claimed. It keeps
|
|
184
|
-
* the package's identity and location for reporting, and drops every
|
|
185
|
-
* contribution root and handler.
|
|
186
|
-
* @param {LoadedIntegration} integration
|
|
187
|
-
* @param {LoadedIntegration} claimant
|
|
188
|
-
* @returns {LoadedIntegration}
|
|
189
|
-
*/
|
|
190
|
-
function providerConflict(integration, claimant) {
|
|
191
|
-
const providerId =
|
|
192
|
-
/** @type {import('../../authoring/identity/type').ProviderId} */ (
|
|
193
|
-
integration.providerId
|
|
194
|
-
);
|
|
195
|
-
const winner = describeIntegration(claimant);
|
|
196
|
-
const setAside = describeIntegration(integration);
|
|
197
|
-
const reason = claimant.__local
|
|
198
|
-
? 'is the package being authored, so it is used'
|
|
199
|
-
: 'loads first and is used';
|
|
200
|
-
return {
|
|
201
|
-
name: integration.name,
|
|
202
|
-
providerId,
|
|
203
|
-
version: integration.version,
|
|
204
|
-
__spec: integration.__spec,
|
|
205
|
-
__packageDir: integration.__packageDir,
|
|
206
|
-
__manifestFile: integration.__manifestFile,
|
|
207
|
-
...(integration.__local ? {__local: true} : {}),
|
|
208
|
-
...(integration.__autolinked
|
|
209
|
-
? {__autolinked: true, __dependencyField: integration.__dependencyField}
|
|
210
|
-
: {}),
|
|
211
|
-
__providerConflict: {
|
|
212
|
-
providerId,
|
|
213
|
-
claimedBy: claimant.name,
|
|
214
|
-
message:
|
|
215
|
-
`${setAside} and ${winner} both claim provider ID "${providerId}". ` +
|
|
216
|
-
`${winner} ${reason}; ${setAside} contributes nothing ` +
|
|
217
|
-
'until one package changes its providerId.',
|
|
218
|
-
},
|
|
219
|
-
};
|
|
127
|
+
return resolveProviders(
|
|
128
|
+
integrations.map(integration => ({
|
|
129
|
+
source: /** @type {const} */ ('configured'),
|
|
130
|
+
integration,
|
|
131
|
+
spec: integration?.__spec,
|
|
132
|
+
})),
|
|
133
|
+
).integrations;
|
|
220
134
|
}
|
|
221
135
|
|
|
222
136
|
/**
|