@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
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* @file Ensures `astryx theme build` preserves AST-012 adaptation semantics.
|
|
5
5
|
* Runtime and static output share core's compiler; this suite guards the CLI
|
|
6
|
-
* loading, diagnostics, serialization, and extension boundaries around it
|
|
6
|
+
* loading, diagnostics, serialization, and extension boundaries around it,
|
|
7
|
+
* including root component overrides underneath adapted typography scales.
|
|
7
8
|
*/
|
|
8
9
|
|
|
9
10
|
import {afterEach, beforeAll, beforeEach, describe, expect, it} from 'vitest';
|
|
@@ -94,6 +95,104 @@ describe('theme build adaptations', () => {
|
|
|
94
95
|
);
|
|
95
96
|
});
|
|
96
97
|
|
|
98
|
+
it.each([
|
|
99
|
+
['defined', writeTheme],
|
|
100
|
+
['plain', writePlainTheme],
|
|
101
|
+
])(
|
|
102
|
+
'preserves component pins in %s themes and built extensions',
|
|
103
|
+
async (_kind, write) => {
|
|
104
|
+
const {defineTheme, generateAdaptationCSS, generateThemeCSS} =
|
|
105
|
+
await import('@astryxdesign/core/theme');
|
|
106
|
+
const project = path.join(tmpDir, 'project');
|
|
107
|
+
const themesDir = path.join(project, 'themes');
|
|
108
|
+
const displayFamily =
|
|
109
|
+
'Sarina, "Brush Script MT", "Snell Roundhand", cursive';
|
|
110
|
+
const input = {
|
|
111
|
+
name: 'adaptive-display',
|
|
112
|
+
typography: {
|
|
113
|
+
scale: {base: 16, ratio: 1.25},
|
|
114
|
+
body: {family: 'Outfit', fallbacks: 'sans-serif'},
|
|
115
|
+
},
|
|
116
|
+
components: {
|
|
117
|
+
text: Object.fromEntries(
|
|
118
|
+
['display-1', 'display-2', 'display-3'].map(type => [
|
|
119
|
+
`type:${type}`,
|
|
120
|
+
{fontFamily: displayFamily},
|
|
121
|
+
]),
|
|
122
|
+
),
|
|
123
|
+
button: {base: {borderRadius: '12px'}},
|
|
124
|
+
},
|
|
125
|
+
adaptations: {
|
|
126
|
+
rules: [
|
|
127
|
+
{
|
|
128
|
+
when: {width: {below: 'md'}, pointer: 'coarse'},
|
|
129
|
+
value: {typography: {scale: {base: 14, ratio: 1.2}}},
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
when: {contrast: 'more'},
|
|
133
|
+
value: {
|
|
134
|
+
typography: {scale: {base: 15}},
|
|
135
|
+
components: {
|
|
136
|
+
text: {'type:display-1': {fontFamily: 'monospace'}},
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
],
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
const themeFile = write(themesDir, input.name, JSON.stringify(input));
|
|
144
|
+
const result = await build(project, themeFile);
|
|
145
|
+
expect(result.code, result.stderr).toBe(0);
|
|
146
|
+
const css = fs.readFileSync(
|
|
147
|
+
path.join(themesDir, 'adaptive-display.css'),
|
|
148
|
+
'utf8',
|
|
149
|
+
);
|
|
150
|
+
const compact = value => value.replace(/\s+/g, ' ').trim();
|
|
151
|
+
const source = defineTheme(input);
|
|
152
|
+
const runtime = generateThemeCSS(source);
|
|
153
|
+
// The CLI wraps root, adaptation, and surface CSS in separate @layer
|
|
154
|
+
// blocks; their contents and order must still match runtime output.
|
|
155
|
+
const adaptationCSS = generateAdaptationCSS(source).component;
|
|
156
|
+
const [rootCSS, surfaceCSS] = runtime.component.split(adaptationCSS);
|
|
157
|
+
const blocks = [rootCSS, adaptationCSS, surfaceCSS].map(compact);
|
|
158
|
+
let previousIndex = -1;
|
|
159
|
+
for (const block of blocks) {
|
|
160
|
+
expect(compact(css)).toContain(block);
|
|
161
|
+
const index = compact(css).indexOf(block);
|
|
162
|
+
expect(index).toBeGreaterThan(previousIndex);
|
|
163
|
+
previousIndex = index;
|
|
164
|
+
}
|
|
165
|
+
expect(compact(css)).toContain(compact(runtime.prose));
|
|
166
|
+
const scaleBlock = css.slice(
|
|
167
|
+
css.indexOf('@media (width < 768px) and (pointer: coarse)'),
|
|
168
|
+
css.indexOf('@media (prefers-contrast: more)'),
|
|
169
|
+
);
|
|
170
|
+
expect(scaleBlock).toContain('--font-size-base: 0.875rem');
|
|
171
|
+
expect(scaleBlock).not.toContain('.astryx-text');
|
|
172
|
+
expect(scaleBlock).not.toContain('.astryx-heading');
|
|
173
|
+
expect(scaleBlock).not.toContain('.astryx-button');
|
|
174
|
+
expect(css).toContain(`font-family: ${displayFamily};`);
|
|
175
|
+
expect(css).toContain('font-family: monospace;');
|
|
176
|
+
|
|
177
|
+
const {adaptiveDisplayTheme: builtTheme} = await import(
|
|
178
|
+
pathToFileURL(path.join(themesDir, 'adaptive-display.js')).href
|
|
179
|
+
);
|
|
180
|
+
expect(builtTheme.__adaptationRules).toBeUndefined();
|
|
181
|
+
expect(generateThemeCSS(builtTheme)).toEqual(runtime);
|
|
182
|
+
const childInput = {
|
|
183
|
+
name: 'display-child',
|
|
184
|
+
components: {text: {'type:display-2': {fontFamily: 'serif'}}},
|
|
185
|
+
};
|
|
186
|
+
const fromSource = defineTheme({...childInput, extends: source});
|
|
187
|
+
const fromBuilt = defineTheme({...childInput, extends: builtTheme});
|
|
188
|
+
expect(generateThemeCSS(fromBuilt)).toEqual(generateThemeCSS(fromSource));
|
|
189
|
+
expect(fromBuilt.__adaptationRules[0].components).toBeUndefined();
|
|
190
|
+
expect(fromBuilt.components.text['type:display-2'].fontFamily).toBe(
|
|
191
|
+
'serif',
|
|
192
|
+
);
|
|
193
|
+
},
|
|
194
|
+
);
|
|
195
|
+
|
|
97
196
|
it('resolves a plain object whose only input-only field is adaptations', async () => {
|
|
98
197
|
const project = path.join(tmpDir, 'project');
|
|
99
198
|
const themesDir = path.join(project, 'themes');
|
|
@@ -33,7 +33,7 @@ import {fileURLToPath} from 'node:url';
|
|
|
33
33
|
import {spawn} from 'node:child_process';
|
|
34
34
|
import {getCliInvocation} from '../../../foundation/env/package-manager.mjs';
|
|
35
35
|
import {jsonOut} from '../../../foundation/response/json.mjs';
|
|
36
|
-
import {emit, section, text, list, code} from '../formatters/index.mjs';
|
|
36
|
+
import {emit, section, text, list, records, code} from '../formatters/index.mjs';
|
|
37
37
|
import {logger} from '../../../api/logger.mjs';
|
|
38
38
|
import {cliError} from '../lib/cli-error.mjs';
|
|
39
39
|
import {ERROR_CODES} from '../../../foundation/response/error-codes.mjs';
|
|
@@ -196,7 +196,7 @@ async function warnOnThemeIntegrationIssues(json) {
|
|
|
196
196
|
try {
|
|
197
197
|
const project = await Project.load(process.cwd());
|
|
198
198
|
await project.themes();
|
|
199
|
-
await warnOnIntegrationIssues(project
|
|
199
|
+
await warnOnIntegrationIssues(project, {json});
|
|
200
200
|
} catch {
|
|
201
201
|
// Never let the nudge break the command.
|
|
202
202
|
}
|
|
@@ -229,47 +229,6 @@ function printThemeList(themes) {
|
|
|
229
229
|
);
|
|
230
230
|
}
|
|
231
231
|
|
|
232
|
-
/**
|
|
233
|
-
* Render the targets as one greppable line each, under an aligned header. A
|
|
234
|
-
* `records()` block would be five lines per target — over a thousand for the
|
|
235
|
-
* full surface, which is the view this command exists to make readable.
|
|
236
|
-
* @param {import('../../../api/theme/theme.type.mjs').ThemeTargetEntry[]} targets
|
|
237
|
-
* @returns {string}
|
|
238
|
-
*/
|
|
239
|
-
function formatTargetsTable(targets) {
|
|
240
|
-
const rows = targets.map(t => ({
|
|
241
|
-
key: t.deprecatedFor
|
|
242
|
-
? `${t.key} [deprecated; use ${t.deprecatedFor}]`
|
|
243
|
-
: t.key,
|
|
244
|
-
component: t.component,
|
|
245
|
-
props: t.props.join(', ') || '-',
|
|
246
|
-
states: t.states.join(', ') || '-',
|
|
247
|
-
}));
|
|
248
|
-
const head = {
|
|
249
|
-
key: 'key',
|
|
250
|
-
component: 'component',
|
|
251
|
-
props: 'props',
|
|
252
|
-
states: 'states',
|
|
253
|
-
};
|
|
254
|
-
const width = (/** @type {'key'|'component'|'props'} */ field) =>
|
|
255
|
-
[head, ...rows].reduce((max, r) => Math.max(max, r[field].length), 0);
|
|
256
|
-
const w = {
|
|
257
|
-
key: width('key'),
|
|
258
|
-
component: width('component'),
|
|
259
|
-
props: width('props'),
|
|
260
|
-
};
|
|
261
|
-
const line = (/** @type {typeof head} */ r) =>
|
|
262
|
-
[
|
|
263
|
-
r.key.padEnd(w.key),
|
|
264
|
-
r.component.padEnd(w.component),
|
|
265
|
-
r.props.padEnd(w.props),
|
|
266
|
-
r.states,
|
|
267
|
-
]
|
|
268
|
-
.join(' ')
|
|
269
|
-
.trimEnd();
|
|
270
|
-
return [line(head), ...rows.map(line)].join('\n');
|
|
271
|
-
}
|
|
272
|
-
|
|
273
232
|
/**
|
|
274
233
|
* @param {import('commander').Command} program
|
|
275
234
|
*/
|
|
@@ -811,9 +770,16 @@ export function registerTheme(program) {
|
|
|
811
770
|
emit(
|
|
812
771
|
section(
|
|
813
772
|
'Theming targets',
|
|
814
|
-
`${targets.length} across ${componentCount} component${componentCount === 1 ? '' : 's'}`,
|
|
773
|
+
`${targets.length} across ${componentCount} component${componentCount === 1 ? '' : 's'}\n(key - component - props - states - className - deprecatedFor)`,
|
|
815
774
|
),
|
|
816
|
-
|
|
775
|
+
records(targets, {
|
|
776
|
+
fields: ['key', 'component', 'props', 'states', 'className', 'deprecatedFor'],
|
|
777
|
+
layout: 'inline',
|
|
778
|
+
format: {
|
|
779
|
+
deprecatedFor: (/** @type {string|null} */ v) =>
|
|
780
|
+
v ? `deprecated; use ${v}` : '',
|
|
781
|
+
},
|
|
782
|
+
}),
|
|
817
783
|
text(
|
|
818
784
|
[
|
|
819
785
|
`Each key goes under \`components\` in defineTheme; it paints \`.astryx-<key>\`.`,
|
|
@@ -12,13 +12,14 @@ export const doc = {
|
|
|
12
12
|
type: 'command',
|
|
13
13
|
name: 'build',
|
|
14
14
|
displayName: 'astryx build',
|
|
15
|
-
namespace: 'cli',
|
|
15
|
+
namespace: 'cli/commands',
|
|
16
16
|
summary:
|
|
17
|
-
'Build a page:
|
|
17
|
+
'Build a page: the template to start from, or the workflow playbook (no query)',
|
|
18
18
|
description:
|
|
19
|
-
'The
|
|
20
|
-
'playbook; with a query it
|
|
21
|
-
'
|
|
19
|
+
'The build-a-page entry point. With no query it returns the how-to-build-a-page ' +
|
|
20
|
+
'playbook; with a query it names the page template to start from (always one: the ' +
|
|
21
|
+
'closest page template, or the app shell when none matches), the next two templates, and the ' +
|
|
22
|
+
'drop-in blocks and idea-specific components and hooks around it.',
|
|
22
23
|
fn: 'build',
|
|
23
24
|
args: [{name: 'query', param: 'query', required: false}],
|
|
24
25
|
options: [
|
|
@@ -35,12 +36,16 @@ export const doc = {
|
|
|
35
36
|
},
|
|
36
37
|
{
|
|
37
38
|
flag: '--verbose',
|
|
38
|
-
description:
|
|
39
|
+
description:
|
|
40
|
+
'Verbose output (every block and component, full descriptions, import paths and match reason)',
|
|
39
41
|
},
|
|
40
42
|
],
|
|
41
43
|
examples: [
|
|
42
44
|
{label: 'Get the playbook', cli: 'astryx build'},
|
|
43
|
-
{
|
|
45
|
+
{
|
|
46
|
+
label: 'Find the template to start from',
|
|
47
|
+
cli: 'astryx build "analytics dashboard" --json',
|
|
48
|
+
},
|
|
44
49
|
],
|
|
45
50
|
exitCodes: [
|
|
46
51
|
{code: 0, when: 'success (including zero matches)'},
|
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
* @file build command — thin wrapper with a stable result summary.
|
|
5
5
|
*
|
|
6
6
|
* astryx build → the PLAYBOOK (how to build a page)
|
|
7
|
-
* astryx build "<what>" →
|
|
8
|
-
*
|
|
7
|
+
* astryx build "<what>" → the TEMPLATE to start from (always one: the
|
|
8
|
+
* closest page, or the app shell), other
|
|
9
|
+
* templates, then blocks and components.
|
|
9
10
|
*
|
|
10
11
|
* All grouping/scoring lives in api/build; this file only parses flags and
|
|
11
12
|
* renders. Command strings are prefixed for the caller's package manager here
|
|
@@ -27,6 +28,7 @@ import {
|
|
|
27
28
|
records,
|
|
28
29
|
} from '../formatters/index.mjs';
|
|
29
30
|
import {cliError} from '../lib/cli-error.mjs';
|
|
31
|
+
import {firstSentence} from '../../../foundation/text/string-utils.mjs';
|
|
30
32
|
import {defineCommand} from '../lib/define-command.mjs';
|
|
31
33
|
import {build as buildApi} from '../../../api/build/build.mjs';
|
|
32
34
|
import {doc as buildCommand} from './build.doc.mjs';
|
|
@@ -126,6 +128,7 @@ export function registerBuild(program) {
|
|
|
126
128
|
hasResults,
|
|
127
129
|
matchCount,
|
|
128
130
|
directMatch,
|
|
131
|
+
start,
|
|
129
132
|
pages,
|
|
130
133
|
blocks,
|
|
131
134
|
domain,
|
|
@@ -134,8 +137,8 @@ export function registerBuild(program) {
|
|
|
134
137
|
hint,
|
|
135
138
|
} = result.data;
|
|
136
139
|
// The kit spans domains, so its kind comes from the pieces themselves.
|
|
137
|
-
// `
|
|
138
|
-
// are not what the query matched.
|
|
140
|
+
// `start` (which may be the fallback shell), `frame` and `foundation`
|
|
141
|
+
// are deliberately excluded: they are not what the query matched.
|
|
139
142
|
const answered = resultSetOf([...pages, ...blocks, ...domain], {
|
|
140
143
|
count: matchCount,
|
|
141
144
|
empty: !hasResults,
|
|
@@ -148,7 +151,7 @@ export function registerBuild(program) {
|
|
|
148
151
|
return answered;
|
|
149
152
|
}
|
|
150
153
|
|
|
151
|
-
if (!hasResults) {
|
|
154
|
+
if (!hasResults && !start) {
|
|
152
155
|
emit(
|
|
153
156
|
text(`No matches for "${q}".`),
|
|
154
157
|
text(`Try a broader term, or browse: ${run} component --list`),
|
|
@@ -156,91 +159,126 @@ export function registerBuild(program) {
|
|
|
156
159
|
return answered;
|
|
157
160
|
}
|
|
158
161
|
|
|
159
|
-
//
|
|
160
|
-
//
|
|
161
|
-
//
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
'domain',
|
|
166
|
-
'displayName',
|
|
167
|
-
'score',
|
|
168
|
-
'reason',
|
|
169
|
-
'import',
|
|
170
|
-
'description',
|
|
171
|
-
'command',
|
|
172
|
-
]
|
|
173
|
-
: ['name', 'displayName', 'description', 'command'];
|
|
162
|
+
// Four sections, one job each: the TEMPLATE to scaffold, OTHER
|
|
163
|
+
// TEMPLATES if its layout is wrong, BLOCKS for parts it lacks, and
|
|
164
|
+
// COMPONENTS for the rest. Descriptions stop at their first sentence and
|
|
165
|
+
// blocks and components share one command line in their heading; the
|
|
166
|
+
// JSON and --verbose carry everything.
|
|
167
|
+
const verbose = Boolean(options.verbose);
|
|
174
168
|
/** @type {import('../formatters/index.mjs').RecordOptions} */
|
|
175
|
-
const
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
//
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
169
|
+
const full = {
|
|
170
|
+
fields: [
|
|
171
|
+
'name',
|
|
172
|
+
'domain',
|
|
173
|
+
'displayName',
|
|
174
|
+
'score',
|
|
175
|
+
'reason',
|
|
176
|
+
'import',
|
|
177
|
+
'description',
|
|
178
|
+
'command',
|
|
179
|
+
],
|
|
180
|
+
format: {command: formatCliCommand},
|
|
181
|
+
};
|
|
182
|
+
/** @param {string[]} fields */
|
|
183
|
+
const brief = fields => ({
|
|
184
|
+
fields,
|
|
185
|
+
format: {command: formatCliCommand, description: firstSentence},
|
|
186
|
+
});
|
|
187
|
+
// Blocks and components are extras: the text names the top few, and
|
|
188
|
+
// says how many more the JSON and --verbose carry.
|
|
189
|
+
const TOP = 3;
|
|
190
|
+
/** @param {unknown[]} items */
|
|
191
|
+
const shown = items => (verbose ? items : items.slice(0, TOP));
|
|
192
|
+
/** @param {unknown[]} items */
|
|
193
|
+
const more = items =>
|
|
194
|
+
!verbose && items.length > TOP
|
|
195
|
+
? ` (top ${TOP} of ${items.length}; --verbose for all)`
|
|
196
|
+
: '';
|
|
202
197
|
|
|
203
198
|
/** @type {import('../formatters/index.mjs').Block[]} */
|
|
204
199
|
const out = [
|
|
205
200
|
section(`Build kit for "${q}"`),
|
|
206
201
|
text(
|
|
207
|
-
|
|
208
|
-
'
|
|
209
|
-
|
|
210
|
-
|
|
202
|
+
start
|
|
203
|
+
? 'Start from the TEMPLATE, fill it with BLOCKS, and use COMPONENTS only for what is left.\n' +
|
|
204
|
+
'Changing a page you already have? Keep it, and use only the blocks and components.'
|
|
205
|
+
: 'This kit is narrowed by --type, so it names no template.',
|
|
211
206
|
),
|
|
212
|
-
section('RECOMMENDED START', `${startNote}\n${startCmd}`),
|
|
213
207
|
];
|
|
214
208
|
|
|
215
|
-
if (
|
|
209
|
+
if (start) {
|
|
216
210
|
out.push(
|
|
217
211
|
section(
|
|
218
|
-
'
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
212
|
+
'TEMPLATE',
|
|
213
|
+
`${start.reason} ${
|
|
214
|
+
start.basis === 'fallback'
|
|
215
|
+
? 'Scaffold it, then put blocks inside it.'
|
|
216
|
+
: 'Scaffold it, then replace its content. Keep its layout and spacing.'
|
|
217
|
+
}`,
|
|
218
|
+
),
|
|
219
|
+
record(
|
|
220
|
+
start,
|
|
221
|
+
verbose
|
|
222
|
+
? {
|
|
223
|
+
fields: ['name', 'displayName', 'description', 'command'],
|
|
224
|
+
format: {command: formatCliCommand},
|
|
225
|
+
}
|
|
226
|
+
: brief(['name', 'description', 'command']),
|
|
222
227
|
),
|
|
223
|
-
records(pages, recordOpts),
|
|
224
228
|
);
|
|
229
|
+
if (start.alternatives.length) {
|
|
230
|
+
out.push(
|
|
231
|
+
section(
|
|
232
|
+
'OTHER TEMPLATES',
|
|
233
|
+
`If the layout is wrong, scaffold one of these instead. All page templates: ${formatCliCommand('template --list --type page')}`,
|
|
234
|
+
),
|
|
235
|
+
records(
|
|
236
|
+
start.alternatives,
|
|
237
|
+
verbose ? full : brief(['name', 'description', 'command']),
|
|
238
|
+
),
|
|
239
|
+
);
|
|
240
|
+
}
|
|
225
241
|
}
|
|
226
|
-
|
|
242
|
+
// Search's own page matches, so the text carries every field the JSON
|
|
243
|
+
// does: one line by default, the full entries under --verbose.
|
|
244
|
+
if (pages.length) {
|
|
227
245
|
out.push(
|
|
228
|
-
|
|
229
|
-
|
|
246
|
+
verbose
|
|
247
|
+
? section(
|
|
248
|
+
'SEARCH MATCHES',
|
|
249
|
+
'Page templates keyword search matched, best first.',
|
|
250
|
+
)
|
|
251
|
+
: text(
|
|
252
|
+
`Keyword search matched these page templates: ${pages.map(p => p.name).join(', ')}.`,
|
|
253
|
+
),
|
|
230
254
|
);
|
|
255
|
+
if (verbose) out.push(records(pages, full));
|
|
231
256
|
}
|
|
232
|
-
if (
|
|
257
|
+
if (blocks.length) {
|
|
233
258
|
out.push(
|
|
234
|
-
section(
|
|
235
|
-
|
|
259
|
+
section(
|
|
260
|
+
'BLOCKS',
|
|
261
|
+
`Ready-made sections for parts the template lacks${more(blocks)}. Print one: ${formatCliCommand('template <name>')}`,
|
|
262
|
+
),
|
|
263
|
+
records(
|
|
264
|
+
shown(blocks),
|
|
265
|
+
verbose ? full : brief(['name', 'description']),
|
|
266
|
+
),
|
|
236
267
|
);
|
|
237
268
|
}
|
|
238
|
-
|
|
239
269
|
out.push(
|
|
240
270
|
section(
|
|
241
|
-
'
|
|
242
|
-
|
|
271
|
+
'COMPONENTS',
|
|
272
|
+
`For what the template and blocks do not cover${more(domain)}. Read one: ${formatCliCommand('component <name>')}`,
|
|
243
273
|
),
|
|
274
|
+
...(domain.length
|
|
275
|
+
? [
|
|
276
|
+
records(
|
|
277
|
+
shown(domain),
|
|
278
|
+
verbose ? full : brief(['name', 'description']),
|
|
279
|
+
),
|
|
280
|
+
]
|
|
281
|
+
: []),
|
|
244
282
|
record({frame, foundation}),
|
|
245
283
|
);
|
|
246
284
|
|
|
@@ -21,6 +21,8 @@ describe('build kit text fields mirror the JSON keys', () => {
|
|
|
21
21
|
const {data} = JSON.parse(json.stdout);
|
|
22
22
|
const keys = new Set([
|
|
23
23
|
...Object.keys(data),
|
|
24
|
+
...Object.keys(data.start ?? {}),
|
|
25
|
+
...(data.start?.alternatives ?? []).flatMap(a => Object.keys(a)),
|
|
24
26
|
...[...data.pages, ...data.blocks, ...data.domain].flatMap(e => Object.keys(e)),
|
|
25
27
|
]);
|
|
26
28
|
|
|
@@ -35,6 +37,45 @@ describe('build kit text fields mirror the JSON keys', () => {
|
|
|
35
37
|
),
|
|
36
38
|
];
|
|
37
39
|
expect(fields).toContain('frame');
|
|
40
|
+
// The start is printed as a record, so its fields are checked too.
|
|
41
|
+
expect(fields).toContain('command');
|
|
42
|
+
expect(fields).toContain('displayName');
|
|
38
43
|
for (const field of fields) expect(keys).toContain(field);
|
|
39
44
|
}, SLOW);
|
|
45
|
+
|
|
46
|
+
it('leads with the start, then the alternatives, blocks and components', async () => {
|
|
47
|
+
const human = await runCli(['build', 'analytics dashboard'], REPO);
|
|
48
|
+
expect(human.status).toBe(0);
|
|
49
|
+
const headings = human.stdout
|
|
50
|
+
.split('\n')
|
|
51
|
+
.filter(line => /^(TEMPLATE|OTHER TEMPLATES|BLOCKS|COMPONENTS)$/.test(line));
|
|
52
|
+
expect(headings).toEqual(['TEMPLATE', 'OTHER TEMPLATES', 'BLOCKS', 'COMPONENTS']);
|
|
53
|
+
// A builder changing a page they already have keeps it.
|
|
54
|
+
expect(human.stdout).toContain(
|
|
55
|
+
'Changing a page you already have? Keep it, and use only the blocks and components.',
|
|
56
|
+
);
|
|
57
|
+
}, SLOW);
|
|
58
|
+
|
|
59
|
+
it("shortens the start's description by default and prints it whole under --verbose", async () => {
|
|
60
|
+
const json = await runCli(['build', 'quarterly revenue dashboard', '--json'], REPO);
|
|
61
|
+
const {start} = JSON.parse(json.stdout).data;
|
|
62
|
+
const first = start.description.slice(0, start.description.indexOf('. ') + 1);
|
|
63
|
+
expect(first.length).toBeGreaterThan(0);
|
|
64
|
+
expect(first.length).toBeLessThan(start.description.length);
|
|
65
|
+
const line = out => out.split('\n').find(l => l.startsWith('description:'));
|
|
66
|
+
const brief = await runCli(['build', 'quarterly revenue dashboard'], REPO);
|
|
67
|
+
expect(line(brief.stdout)).toBe(`description: ${first}`);
|
|
68
|
+
const whole = await runCli(['build', 'quarterly revenue dashboard', '--verbose'], REPO);
|
|
69
|
+
expect(whole.stdout).toContain(start.description);
|
|
70
|
+
}, SLOW);
|
|
71
|
+
|
|
72
|
+
it("names search's page matches in the default text", async () => {
|
|
73
|
+
const json = await runCli(['build', 'contact form', '--json'], REPO);
|
|
74
|
+
const {data} = JSON.parse(json.stdout);
|
|
75
|
+
expect(data.pages.length).toBeGreaterThan(0);
|
|
76
|
+
const human = await runCli(['build', 'contact form'], REPO);
|
|
77
|
+
expect(human.stdout).toContain(
|
|
78
|
+
`Keyword search matched these page templates: ${data.pages.map(p => p.name).join(', ')}.`,
|
|
79
|
+
);
|
|
80
|
+
}, SLOW);
|
|
40
81
|
});
|
|
@@ -111,7 +111,7 @@ export function registerComponent(program) {
|
|
|
111
111
|
// doctor integration validate. Best-effort; suppressed in --json mode.
|
|
112
112
|
try {
|
|
113
113
|
const project = await Project.load(process.cwd());
|
|
114
|
-
await warnOnIntegrationIssues(project
|
|
114
|
+
await warnOnIntegrationIssues(project, {json});
|
|
115
115
|
} catch {
|
|
116
116
|
// Never let the nudge break the command.
|
|
117
117
|
}
|
|
@@ -71,7 +71,7 @@ function createFixture({
|
|
|
71
71
|
);
|
|
72
72
|
fs.writeFileSync(
|
|
73
73
|
path.join(compDir, 'MetaAppShell.doc.mjs'),
|
|
74
|
-
`export
|
|
74
|
+
`export default {\n type: 'component',\n name: 'MetaAppShell',\n usage: { description: 'Meta-flavored app shell.' },\n props: [{ name: 'title', type: 'string', description: 'Header title' }],\n};\n`,
|
|
75
75
|
);
|
|
76
76
|
if (withSource) {
|
|
77
77
|
fs.writeFileSync(
|
|
@@ -82,7 +82,7 @@ function createFixture({
|
|
|
82
82
|
if (extraComponent) {
|
|
83
83
|
fs.writeFileSync(
|
|
84
84
|
path.join(compDir, `${extraComponent}.doc.mjs`),
|
|
85
|
-
`export
|
|
85
|
+
`export default {\n type: 'component',\n name: '${extraComponent}',\n usage: { description: '${extraComponent} from meta.' },\n props: [],\n};\n`,
|
|
86
86
|
);
|
|
87
87
|
fs.writeFileSync(
|
|
88
88
|
path.join(compDir, `${extraComponent}.tsx`),
|
|
@@ -100,7 +100,7 @@ function createFixture({
|
|
|
100
100
|
: '';
|
|
101
101
|
fs.writeFileSync(
|
|
102
102
|
path.join(entryDir, `${entryPoint.component}.doc.mjs`),
|
|
103
|
-
`export
|
|
103
|
+
`export default {\n type: 'component',\n name: '${entryPoint.component}',${ownSpecifier}\n usage: { description: '${entryPoint.component} from an entry point.' },\n props: [],\n};\n`,
|
|
104
104
|
);
|
|
105
105
|
}
|
|
106
106
|
|
|
@@ -13,7 +13,7 @@ export const doc = {
|
|
|
13
13
|
type: 'command',
|
|
14
14
|
name: 'component',
|
|
15
15
|
displayName: 'astryx component',
|
|
16
|
-
namespace: 'cli',
|
|
16
|
+
namespace: 'cli/commands',
|
|
17
17
|
summary: 'List components or print component docs',
|
|
18
18
|
description:
|
|
19
19
|
'Resolves a component by name across core and integration packages and prints ' +
|
|
@@ -69,11 +69,12 @@ describe('astryx discover with a manifest that fails to load', () => {
|
|
|
69
69
|
|
|
70
70
|
expect(status).toBe(0);
|
|
71
71
|
expect(stderr).toContain(
|
|
72
|
-
'Warning: @test/broken has 1 integration issue(s). '
|
|
73
|
-
'Run: astryx doctor integration validate @test/broken',
|
|
72
|
+
'Warning: @test/broken has 1 integration issue(s). Run: astryx doctor',
|
|
74
73
|
);
|
|
75
74
|
expect(stdout).not.toContain('No integrations configured.');
|
|
76
|
-
expect(stdout).toContain(
|
|
75
|
+
expect(stdout).toContain(
|
|
76
|
+
'No external components found in configured integrations.',
|
|
77
|
+
);
|
|
77
78
|
});
|
|
78
79
|
|
|
79
80
|
it('reports meta.configured=true in --json, with the nudge suppressed', async () => {
|
|
@@ -101,7 +102,7 @@ describe('astryx discover with a configured package that is not installed', () =
|
|
|
101
102
|
);
|
|
102
103
|
fs.writeFileSync(
|
|
103
104
|
path.join(healthy, 'components', 'Widget.doc.mjs'),
|
|
104
|
-
`export const docs = {name: 'Widget', usage: {description: 'A widget.'}};\n`,
|
|
105
|
+
`export const docs = {name: 'Widget', usage: {description: 'A widget.'}, props: []};\n`,
|
|
105
106
|
);
|
|
106
107
|
fs.writeFileSync(
|
|
107
108
|
path.join(healthy, 'components', 'Widget.tsx'),
|
|
@@ -129,8 +130,7 @@ describe('astryx discover with a configured package that is not installed', () =
|
|
|
129
130
|
|
|
130
131
|
expect(status).toBe(0);
|
|
131
132
|
expect(stderr).toContain(
|
|
132
|
-
'Warning: @test/missing has 1 integration issue(s). '
|
|
133
|
-
'Run: astryx doctor integration validate @test/missing',
|
|
133
|
+
'Warning: @test/missing has 1 integration issue(s). Run: astryx doctor\n',
|
|
134
134
|
);
|
|
135
135
|
});
|
|
136
136
|
});
|
|
@@ -149,8 +149,7 @@ describe('astryx search with a manifest that fails to load', () => {
|
|
|
149
149
|
|
|
150
150
|
expect(status).toBe(0);
|
|
151
151
|
expect(stderr).toContain(
|
|
152
|
-
'Warning: @test/broken has 1 integration issue(s). '
|
|
153
|
-
'Run: astryx doctor integration validate @test/broken',
|
|
152
|
+
'Warning: @test/broken has 1 integration issue(s). Run: astryx doctor',
|
|
154
153
|
);
|
|
155
154
|
|
|
156
155
|
const asJson = await runCli(['search', 'button', '--json'], {cwd: project});
|
|
@@ -13,7 +13,7 @@ export const doc = {
|
|
|
13
13
|
type: 'command',
|
|
14
14
|
name: 'discover',
|
|
15
15
|
displayName: 'astryx discover',
|
|
16
|
-
namespace: 'cli',
|
|
16
|
+
namespace: 'cli/commands',
|
|
17
17
|
summary: 'Discover external packages and components',
|
|
18
18
|
description:
|
|
19
19
|
'Explores components contributed by configured external packages and integrations. ' +
|
|
@@ -83,7 +83,7 @@ export function registerDiscover(program) {
|
|
|
83
83
|
// doctor integration validate. Best-effort; suppressed in --json mode.
|
|
84
84
|
try {
|
|
85
85
|
const project = await Project.load(process.cwd());
|
|
86
|
-
await warnOnIntegrationIssues(project
|
|
86
|
+
await warnOnIntegrationIssues(project, {json});
|
|
87
87
|
} catch {
|
|
88
88
|
// Never let the nudge break the command.
|
|
89
89
|
}
|