@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
package/README.md
CHANGED
|
@@ -15,6 +15,25 @@ npx @astryxdesign/cli template --list
|
|
|
15
15
|
|
|
16
16
|
Once it's a project dependency (`npm install -D @astryxdesign/cli`), drop the scope and use the shorter `astryx` — e.g. `npx astryx component Button` or `pnpm exec astryx component Button`. Bare `astryx` resolves to an unrelated npm package until the CLI is installed, so prefer the scoped form above for first-run/one-off use.
|
|
17
17
|
|
|
18
|
+
## Reading the CLI's own docs
|
|
19
|
+
|
|
20
|
+
The CLI documents itself, so these commands print what the installed version does:
|
|
21
|
+
|
|
22
|
+
- `astryx <command> --help`: one command's arguments and options.
|
|
23
|
+
- `astryx manifest --json`: every command, option, and response type, as JSON.
|
|
24
|
+
- `astryx docs cli`: the CLI's docs tree, one level at a time.
|
|
25
|
+
`astryx docs cli/commands` lists every command, `astryx docs cli/api` lists
|
|
26
|
+
the API's functions, schemas, and enums, and a route such as
|
|
27
|
+
`astryx docs cli/api/functions/search` prints one.
|
|
28
|
+
- `astryx docs authoring --index`: the authoring reference, with one section for
|
|
29
|
+
each file an author writes: the `astryx.config.*` file, the
|
|
30
|
+
`astryx.integration.*` manifest, codemods, and every doc type (`ComponentDoc`,
|
|
31
|
+
`TemplateDoc`, `ThemeDoc`, and the rest). Read one section with
|
|
32
|
+
`astryx docs authoring <section>`, for example `astryx docs authoring config`.
|
|
33
|
+
- `astryx docs cli/integrations`: the guide to building an integration package.
|
|
34
|
+
- `astryx docs`: every docs topic, including the design-system guides (for
|
|
35
|
+
example `tokens`, `theme`, and `layout`).
|
|
36
|
+
|
|
18
37
|
## Finding things: `astryx search`
|
|
19
38
|
|
|
20
39
|
When you don't know whether what you need is a component, a hook, a docs topic,
|
|
@@ -61,7 +80,7 @@ Options:
|
|
|
61
80
|
| Command | Description |
|
|
62
81
|
| ------------- | ----------------------------------------------------------------------------- |
|
|
63
82
|
| `blog` | Read the Astryx blog from the published feed |
|
|
64
|
-
| `build` | Build a page:
|
|
83
|
+
| `build` | Build a page: the template to start from, or the workflow playbook (no query) |
|
|
65
84
|
| `component` | List components or print component docs |
|
|
66
85
|
| `discover` | Discover external packages and components |
|
|
67
86
|
| `docs` | Print reference docs |
|
|
@@ -170,6 +189,8 @@ if (isError(result)) {
|
|
|
170
189
|
| `ERR_UNKNOWN_FEATURE` | An unrecognized `--features` value was passed to init. |
|
|
171
190
|
| `ERR_UNKNOWN_CODEMOD` | A `--codemod` value did not match any registered codemod (upgrade). |
|
|
172
191
|
| `ERR_CODEMOD_FAILED` | One or more codemods failed during an upgrade run. |
|
|
192
|
+
| `ERR_CODEMOD_PROTECTED` | A required codemod change remains blocked by a protected consumer file. |
|
|
193
|
+
| `ERR_CODEMOD_PROTECTION_SOURCE` | A working-tree protection declaration could not be read or parsed. |
|
|
173
194
|
| `ERR_NOT_FOUND` | A generic discover/lookup query matched nothing in any package. |
|
|
174
195
|
| `ERR_NO_DOC` | A component exists but has no typed `.doc.mjs` file. |
|
|
175
196
|
| `ERR_NO_SHOWCASE` | No showcase exists for the requested component. |
|
|
@@ -179,7 +200,7 @@ if (isError(result)) {
|
|
|
179
200
|
| `ERR_FILE_EXISTS` | Refused to overwrite an existing file. |
|
|
180
201
|
| `ERR_PATH_TRAVERSAL` | A path escaped its allowed root, or a name contained traversal markers. |
|
|
181
202
|
| `ERR_WRITE_FAILED` | Writing output files failed (and was rolled back). |
|
|
182
|
-
| `ERR_THEME_INVALID` | A theme definition or contributed theme
|
|
203
|
+
| `ERR_THEME_INVALID` | A theme definition or contributed theme descriptor is invalid. |
|
|
183
204
|
| `ERR_THEME_LOAD` | A theme file could not be loaded / parsed into a defineTheme result. |
|
|
184
205
|
| `ERR_PALETTE_GENERATION` | A palette generation request or one of its constraints was invalid. |
|
|
185
206
|
| `ERR_VERSION_DETECT` | The current `@astryxdesign/core` version could not be detected. |
|
|
@@ -407,24 +428,25 @@ Every response has a `type` discriminant. The full set is below (generated from
|
|
|
407
428
|
| `component.detail.source` | One component's source file, as {component, source}. |
|
|
408
429
|
| `component.detail.showcase` | One component's showcase example, as {component, aspectRatio, source}. |
|
|
409
430
|
| `component.detail.blocks` | One component's example blocks, as {component, showcase, examples, related} of BlockEntry. |
|
|
410
|
-
| `docs.list` | All reference-doc topics as DocsListEntry[] ({topic, description}), in
|
|
411
|
-
| `docs.detail` | One topic's full ReferenceDoc, with token-ref blocks inlined.
|
|
412
|
-
| `docs.index` | One topic's section index (--index): the topic's name, title, and description, plus sections, each {id, title, summary} (pass the id as the section argument; summary is the section's one-line summary).
|
|
413
|
-
| `docs.detail.section` | One ReferenceSection of a topic, found by key or title, with token-ref blocks inlined.
|
|
431
|
+
| `docs.list` | All reference-doc topics as DocsListEntry[] ({topic, description, package, replaces?}), in read order; meta.namespaces lists the docs tree's top-level namespaces, and meta.notLoaded each package whose docs did not load. |
|
|
432
|
+
| `docs.detail` | One topic's full ReferenceDoc (the JSON read of a topic, --full, --dense, or a topic with one section), with token-ref blocks inlined, plus links ({up, previous, next}: the commands that open the level it sits in and its neighbors there). |
|
|
433
|
+
| `docs.index` | One topic's section index, the text read of a topic with more than one section (and --index): the topic's name, title, and description, plus sections, each {id, title, summary} (pass the id as the section argument; summary is the section's one-line summary), and links ({up, previous, next}: the commands that open the level it sits in and its neighbors there). |
|
|
434
|
+
| `docs.detail.section` | One ReferenceSection of a topic, found by key or title, with token-ref blocks inlined, plus links ({up, previous, next}: the commands that open its topic index and the sections before and after it). |
|
|
435
|
+
| `docs.node` | One node of the docs tree, read by its route: its id, kind, package, title, summary, and breadcrumb, plus a namespace's slots with their children (one level down) or a typed doc's content, and links ({up, previous, next, related}: the commands that open its parent, its neighbors, and the docs it names). |
|
|
414
436
|
| `blog.list` | The feed URL plus every post parsed from the RSS feed, each with slug, title, description, date, type, authors, link, and plaintext URL. |
|
|
415
437
|
| `blog.detail` | One post's metadata plus the feed URL and the post's full plaintext body. |
|
|
416
438
|
| `discover.list` | The configured external packages (name, category, components, version, description); when empty it carries meta.configured to tell "nothing configured" from "nothing discovered". |
|
|
417
439
|
| `discover.detail` | A single external package entry, for an @scope/name query. |
|
|
418
440
|
| `discover.detail.doc` | The validated ComponentDoc for one external component: an @scope/name/Component query, or a free-text term resolving to exactly one component. |
|
|
419
441
|
| `discover.search` | The echoed query plus the matching {package, component} pairs, when a free-text term matches several components. |
|
|
420
|
-
| `search` | The echoed query, `matchCount` (total matches, before `limit`), and results, a ranked SearchResultEntry[] bounded by `limit`: each {domain, name, score, reason, description, command}, plus import (components, hooks), title (docs), or displayName and kind (templates).
|
|
442
|
+
| `search` | The echoed query, `matchCount` (total matches, before `limit`), and results, a ranked SearchResultEntry[] bounded by `limit`: each {domain, name, score, reason, description, command}, plus import (components, hooks), title, parent (the command that opens the level above), package (for a docs-tree hit), and, for a hit on one section, section (docs), or displayName and kind (templates). |
|
|
421
443
|
| `build.help` | The how-to-build-a-page playbook, emitted when no query is given: `playbook: true`, a title, the ordered steps (title, commands, optional returns), the on-system rules, and related lookups. Commands are bare subcommands for the caller to render with its own invocation. |
|
|
422
|
-
| `build.kit` | The
|
|
444
|
+
| `build.kit` | The template to start from and its kit: query, hasResults, matchCount (never a cap), directMatch, start {name, command, basis, reason, alternatives, ...}, pages (search's closest templates), blocks and domain as SearchResultEntry[], frame, foundation, and hint {reason, commands} when thin. |
|
|
423
445
|
| `swizzle.list` | The names of swizzlable components discoverable from cwd's @astryxdesign/core. |
|
|
424
446
|
| `swizzle.copy` | An eject receipt: component name, owning package, output directory, files-copied count, the written file names, whether any file uses StyleX, and an optional maintainer note. |
|
|
425
447
|
| `gap-report.categories` | The fixed gap category values and human-readable labels. |
|
|
426
448
|
| `gap-report.file` | An aggregate receipt: overall status, the selected package, issuesUrl (or null), deliveries in handler order, each {handlerType: project \| integration \| fallback, handler, audience, status, url, message}, and filedCount/routedOnlyCount totals. |
|
|
427
|
-
| `template.list` |
|
|
449
|
+
| `template.list` | The effective discovered TemplateListEntry[] for pages and blocks. A winning replacement entry includes optional `replaces`, naming the Core id omitted from the default list. |
|
|
428
450
|
| `template.show` | The resolved template's raw source plus its description, kind, and the component names it composes. |
|
|
429
451
|
| `template.skeleton` | A layout skeleton (structural tags with spatial annotations) plus the template's description and the components it composes. |
|
|
430
452
|
| `template.copy` | A scaffold receipt: template id, output directory, written file name, and file count. |
|
|
@@ -448,9 +470,9 @@ Every response has a `type` discriminant. The full set is below (generated from
|
|
|
448
470
|
| `integration.add` | A contribution-writer receipt: kind, name, optional root {path, created}, integration-manifest path, every affected project-relative path, written, and dryRun. |
|
|
449
471
|
| `integration.pack-check` | The packed-package check: name, version, packable, tarball {filename, fileCount, size, unpackedSize} or null, inventory {manifest, roots [{kind, path, expectedFiles, missingFiles, complete}], expectedFiles, packedFiles}, contributions {local, packed}, each null or {themes [{slug, exportName}], components, templates [{id, type, name}], codemods [{version, id}], docs, agentDocsAppend}, and issues [{code, severity, message}]. |
|
|
450
472
|
| `integration.validate` | The validation result: the package name and version (both null when no local manifest is found) plus issues, an AstryxIntegrationIssue[] of {code, severity: warning \| error, message}. |
|
|
451
|
-
| `integration.template-conflicts` | The integration identity, structural issues, and non-blocking
|
|
473
|
+
| `integration.template-conflicts` | The integration identity, structural issues, and non-blocking Core template-id conflicts as {id, severity: warning, integrationPackage, integrationType, integrationName, coreMatches, message, command}. |
|
|
452
474
|
| `integration.component-conflicts` | The integration identity, structural issues, and non-blocking conflicts where an integration component name is also owned by Core; each conflict includes the exact package-qualified command. |
|
|
453
|
-
| `integration.doc-conflicts` | The integration identity, structural issues, and Core doc overlaps
|
|
475
|
+
| `integration.doc-conflicts` | The integration identity, structural issues, and Core doc overlaps. Each finding includes `severity` (`info` \| `error`) and `relationship` (`replaces` \| `extends` \| `accidental`). |
|
|
454
476
|
| `layout.expand` | The expansion: parsed form, generated TSX code, componentsUsed, states (count of useState hooks scaffolded), todos, blocksReferenced (each {name, mode}), warnings, and written (the output path, or null when nothing was written). |
|
|
455
477
|
| `layout.check` | The validation result: a valid flag, the detected form, errors (each with line/col, message, formatted text, and suggestions), warnings, and the expression re-printed in both canonical surfaces (compact and outline). |
|
|
456
478
|
| `layout.grammar` | The XLE/XLO grammar cheatsheet: a text field with the full reference plus an aliases map (short name → canonical component) generated from this install's registry. |
|
|
@@ -646,9 +668,10 @@ wrong type fails there; a field this CLI does not know is ignored with a
|
|
|
646
668
|
warning naming it, so a manifest written against a newer CLI still contributes
|
|
647
669
|
everything this one understands.
|
|
648
670
|
|
|
649
|
-
Discovery is resilient
|
|
650
|
-
|
|
651
|
-
|
|
671
|
+
Discovery is resilient. A manifest load failure skips that package with a warning.
|
|
672
|
+
An invalid contribution kind remains reportable without hiding other valid kinds,
|
|
673
|
+
and invalid template or component metadata is omitted without hiding valid siblings.
|
|
674
|
+
Warnings go to stderr and never corrupt a `--json` envelope. To inspect problems, run
|
|
652
675
|
`astryx doctor integration validate <package>` for structure, then use `templates`,
|
|
653
676
|
`components`, or `docs` under the same `astryx doctor integration` group to check
|
|
654
677
|
Core identity overlaps before publishing. Bare `astryx doctor` checks overall
|
|
@@ -658,5 +681,5 @@ For the full authoring walkthrough (component doc format, template packaging
|
|
|
658
681
|
and `exports` requirements, and codemod authoring), see the guide:
|
|
659
682
|
|
|
660
683
|
```bash
|
|
661
|
-
astryx docs cli
|
|
684
|
+
astryx docs cli/integrations
|
|
662
685
|
```
|
package/api/blog/blog.doc.mjs
CHANGED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// @generated by scripts/sync-api-types.mjs from the JSDoc in api/**/*.mjs.
|
|
2
|
+
// DO NOT EDIT — run `pnpm sync:api-types` to regenerate.
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A page template the kit can recommend starting from.
|
|
6
|
+
* @typedef {object} PageTemplate
|
|
7
|
+
* @property {string} name The template's own id, as search reports it.
|
|
8
|
+
* @property {string} command `astryx template <id> --type page`, the command that selects exactly this template: an integration replacement is selected by the Core id it replaces, and `--type page` keeps a block with the same id from making it ambiguous. Search prints template commands the same way.
|
|
9
|
+
* @property {string} displayName Human-facing name.
|
|
10
|
+
* @property {string} description What the page is: its layout and the ideas it serves.
|
|
11
|
+
* @property {string} category The template's own `Family - Variant` label; empty when it declares none.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Every ready page template the project can scaffold, in discovery order. This
|
|
15
|
+
* is the default discovery view: an active integration replacement stands in
|
|
16
|
+
* for the Core template it replaces, as it does for `astryx template <id>`.
|
|
17
|
+
*
|
|
18
|
+
* Discovery failures leave the kit without a start rather than failing the
|
|
19
|
+
* command: the kit still carries its search matches, and `template --list`
|
|
20
|
+
* reports what went wrong.
|
|
21
|
+
*
|
|
22
|
+
* @param {string} cwd
|
|
23
|
+
* @returns {Promise<PageTemplate[]>}
|
|
24
|
+
*/
|
|
25
|
+
export function loadPageTemplates(cwd: string): Promise<PageTemplate[]>;
|
|
26
|
+
/**
|
|
27
|
+
* A page template the kit can recommend starting from.
|
|
28
|
+
*/
|
|
29
|
+
export type PageTemplate = {
|
|
30
|
+
/**
|
|
31
|
+
* The template's own id, as search reports it.
|
|
32
|
+
*/
|
|
33
|
+
name: string;
|
|
34
|
+
/**
|
|
35
|
+
* `astryx template <id> --type page`, the command that selects exactly this template: an integration replacement is selected by the Core id it replaces, and `--type page` keeps a block with the same id from making it ambiguous. Search prints template commands the same way.
|
|
36
|
+
*/
|
|
37
|
+
command: string;
|
|
38
|
+
/**
|
|
39
|
+
* Human-facing name.
|
|
40
|
+
*/
|
|
41
|
+
displayName: string;
|
|
42
|
+
/**
|
|
43
|
+
* What the page is: its layout and the ideas it serves.
|
|
44
|
+
*/
|
|
45
|
+
description: string;
|
|
46
|
+
/**
|
|
47
|
+
* The template's own `Family - Variant` label; empty when it declares none.
|
|
48
|
+
*/
|
|
49
|
+
category: string;
|
|
50
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file The build subject's environment access: the page templates a project
|
|
5
|
+
* can scaffold.
|
|
6
|
+
*
|
|
7
|
+
* @input Template discovery for `cwd` — the CLI's own templates plus any that
|
|
8
|
+
* the project's configured integrations contribute.
|
|
9
|
+
* @output Ready page templates as `{name, displayName, description, category,
|
|
10
|
+
* command}`, where `command` is the `astryx template` command that selects
|
|
11
|
+
* exactly that template.
|
|
12
|
+
* @position Beside build.mjs (api/build/). The kit leaf reads templates only
|
|
13
|
+
* through here, because a subject's `_adapter.mjs` is its only environment
|
|
14
|
+
* access. Search keeps its own discovery; this adds none of its own, it
|
|
15
|
+
* reuses the template subject's.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import {discoverTemplates} from '../template/template.mjs';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* A page template the kit can recommend starting from.
|
|
22
|
+
* @typedef {object} PageTemplate
|
|
23
|
+
* @property {string} name The template's own id, as search reports it.
|
|
24
|
+
* @property {string} command `astryx template <id> --type page`, the command that selects exactly this template: an integration replacement is selected by the Core id it replaces, and `--type page` keeps a block with the same id from making it ambiguous. Search prints template commands the same way.
|
|
25
|
+
* @property {string} displayName Human-facing name.
|
|
26
|
+
* @property {string} description What the page is: its layout and the ideas it serves.
|
|
27
|
+
* @property {string} category The template's own `Family - Variant` label; empty when it declares none.
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Every ready page template the project can scaffold, in discovery order. This
|
|
32
|
+
* is the default discovery view: an active integration replacement stands in
|
|
33
|
+
* for the Core template it replaces, as it does for `astryx template <id>`.
|
|
34
|
+
*
|
|
35
|
+
* Discovery failures leave the kit without a start rather than failing the
|
|
36
|
+
* command: the kit still carries its search matches, and `template --list`
|
|
37
|
+
* reports what went wrong.
|
|
38
|
+
*
|
|
39
|
+
* @param {string} cwd
|
|
40
|
+
* @returns {Promise<PageTemplate[]>}
|
|
41
|
+
*/
|
|
42
|
+
export async function loadPageTemplates(cwd) {
|
|
43
|
+
let templates;
|
|
44
|
+
try {
|
|
45
|
+
templates = await discoverTemplates(cwd);
|
|
46
|
+
} catch {
|
|
47
|
+
return [];
|
|
48
|
+
}
|
|
49
|
+
return templates
|
|
50
|
+
.filter(t => t.type === 'page' && t.isReady !== false)
|
|
51
|
+
.map(t => ({
|
|
52
|
+
name: t.dirName,
|
|
53
|
+
displayName: t.displayName || t.name,
|
|
54
|
+
description: t.description || '',
|
|
55
|
+
category: t.category || '',
|
|
56
|
+
// The id `template()` resolves back to this entry: an active replacement
|
|
57
|
+
// owns the Core id it names, so that id selects it, not its own.
|
|
58
|
+
command: `astryx template ${t.replaces ?? t.dirName} --type page`,
|
|
59
|
+
}));
|
|
60
|
+
}
|
package/api/build/build.doc.mjs
CHANGED
|
@@ -11,15 +11,19 @@ export const doc = {
|
|
|
11
11
|
type: 'function',
|
|
12
12
|
kind: 'api',
|
|
13
13
|
name: 'build',
|
|
14
|
+
namespace: 'cli/api',
|
|
14
15
|
displayName: 'build()',
|
|
15
16
|
summary:
|
|
16
|
-
'Page-building assistant: the how-to-build playbook, or
|
|
17
|
+
'Page-building assistant: the how-to-build playbook, or the page template to start from for an idea.',
|
|
17
18
|
description:
|
|
18
|
-
'The "
|
|
19
|
+
'The "build a page" entry point. Called with no query it returns the ' +
|
|
19
20
|
'how-to-build-a-page playbook as data: the workflow steps with their ' +
|
|
20
|
-
'commands, the on-system rules, and related lookups. Called with a query it
|
|
21
|
-
'
|
|
22
|
-
'and
|
|
21
|
+
'commands, the on-system rules, and related lookups. Called with a query it names the page template to ' +
|
|
22
|
+
'START from (always one: the page template a ranker built for long descriptions puts first, else the app ' +
|
|
23
|
+
'shell) and the next two templates, ' +
|
|
24
|
+
'and the unified search grouped around it: the other close page templates, drop-in blocks, and ' +
|
|
25
|
+
'idea-specific components/hooks, plus the always-on frame + foundation. A template carries the page ' +
|
|
26
|
+
'frame and spacing, so the kit never recommends composing a page from components.',
|
|
23
27
|
importPath: '@astryxdesign/cli/api',
|
|
24
28
|
signature:
|
|
25
29
|
'build(query?: string, options?: BuildOptions): Promise<BuildHelpResponse | BuildKitResponse>',
|
|
@@ -59,7 +63,7 @@ export const doc = {
|
|
|
59
63
|
{
|
|
60
64
|
type: 'build.kit',
|
|
61
65
|
description:
|
|
62
|
-
|
|
66
|
+
"The page template to start from and the kit around it: the echoed query, hasResults/matchCount/directMatch fields, `start` (the template to scaffold, the `template <id> --type page <path>` command that selects it, whether the page ranker's pick is also search's direct match, the closest page, or the fallback app shell, and the ranker's next two `alternatives`), search's closest page templates (≤3), drop-in block patterns (≤5), idea-specific components/hooks (≤6), and the always-on frame + foundation component-name arrays. Carries `hint` only when the kit came back thin — what to try instead, so a caller does not read a near-empty kit as \"the package has nothing\".",
|
|
63
67
|
},
|
|
64
68
|
],
|
|
65
69
|
throws: [
|
|
@@ -70,7 +74,10 @@ export const doc = {
|
|
|
70
74
|
],
|
|
71
75
|
examples: [
|
|
72
76
|
{label: 'Get the playbook', code: 'const r = await build();'},
|
|
73
|
-
{
|
|
77
|
+
{
|
|
78
|
+
label: 'Find the template to start from',
|
|
79
|
+
code: "const {data} = await build('analytics dashboard');\n// data.start.command: 'astryx template dashboard --type page <path>'",
|
|
80
|
+
},
|
|
74
81
|
{
|
|
75
82
|
label: 'Restrict + limit',
|
|
76
83
|
code: "await build('pricing', {type: 'template', limit: 10});",
|
package/api/build/build.test.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* @file Tests for the build API (playbook +
|
|
4
|
+
* @file Tests for the build API (playbook + the template-first kit).
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import {describe, it, expect, vi} from 'vitest';
|
|
@@ -37,6 +37,15 @@ describe('build API', () => {
|
|
|
37
37
|
for (const {command} of commands) expect(command).not.toMatch(/^(astryx|npx|pnpm|yarn|bunx?)\b/);
|
|
38
38
|
});
|
|
39
39
|
|
|
40
|
+
it('the playbook scaffolds the named template before composing', async () => {
|
|
41
|
+
const r = await build();
|
|
42
|
+
if (r.type !== 'build.help') throw new Error(r.type);
|
|
43
|
+
const commands = r.data.steps.map(s => s.commands.map(c => c.command));
|
|
44
|
+
expect(commands[0][0]).toMatch(/^build /);
|
|
45
|
+
expect(commands[1]).toContain('template <name> <path>');
|
|
46
|
+
expect(JSON.stringify(r.data)).not.toMatch(/--skeleton|reference code/);
|
|
47
|
+
});
|
|
48
|
+
|
|
40
49
|
it('query → build.kit with raw entries + static frame/foundation', async () => {
|
|
41
50
|
const r = await build('dashboard', {cwd: REPO});
|
|
42
51
|
expect(r.type).toBe('build.kit');
|
|
@@ -76,10 +85,10 @@ describe('build API', () => {
|
|
|
76
85
|
expect(blocks.length).toBeLessThanOrEqual(5);
|
|
77
86
|
expect(domain.length).toBeLessThanOrEqual(6);
|
|
78
87
|
|
|
79
|
-
// Score floors: pages ≥ PAGE_FLOOR(50); blocks/domain ≥ DOMAIN_FLOOR(
|
|
88
|
+
// Score floors: pages ≥ PAGE_FLOOR(50); blocks/domain ≥ DOMAIN_FLOOR(60).
|
|
80
89
|
for (const p of pages) expect(p.score).toBeGreaterThanOrEqual(50);
|
|
81
|
-
for (const b of blocks) expect(b.score).toBeGreaterThanOrEqual(
|
|
82
|
-
for (const d of domain) expect(d.score).toBeGreaterThanOrEqual(
|
|
90
|
+
for (const b of blocks) expect(b.score).toBeGreaterThanOrEqual(60);
|
|
91
|
+
for (const d of domain) expect(d.score).toBeGreaterThanOrEqual(60);
|
|
83
92
|
|
|
84
93
|
// directMatch iff the top page is a confident match (PAGE_DIRECT = 95).
|
|
85
94
|
expect(directMatch).toBe(pages.length > 0 && pages[0].score >= 95);
|
|
@@ -201,7 +210,7 @@ describe('build kit — a thin kit says what to try next', () => {
|
|
|
201
210
|
it('hints for a matched-then-filtered query: hasResults true, nothing offerable', async () => {
|
|
202
211
|
// The case most likely to be misread, and the reason the threshold counts
|
|
203
212
|
// what SURVIVED the floors rather than what search returned.
|
|
204
|
-
const r = await build('
|
|
213
|
+
const r = await build('hydration', {cwd: REPO});
|
|
205
214
|
expect(r.type).toBe('build.kit');
|
|
206
215
|
if (r.type !== 'build.kit') return;
|
|
207
216
|
expect(r.data.hasResults).toBe(true);
|
|
@@ -224,12 +233,28 @@ describe('build kit — a thin kit says what to try next', () => {
|
|
|
224
233
|
}
|
|
225
234
|
});
|
|
226
235
|
|
|
236
|
+
it('still starts from the closest page on a loose match, and scaffolds it', async () => {
|
|
237
|
+
// A skeleton is a 35-line excerpt: a reader who studies it and composes
|
|
238
|
+
// the rest loses the spacing the template exists to carry. A loose match
|
|
239
|
+
// is still the best start there is, so `start` scaffolds it.
|
|
240
|
+
const r = await build('executive summary', {cwd: REPO});
|
|
241
|
+
expect(r.type).toBe('build.kit');
|
|
242
|
+
if (r.type !== 'build.kit') return;
|
|
243
|
+
expect(r.data.directMatch).toBe(false);
|
|
244
|
+
expect(r.data.start).toMatchObject({
|
|
245
|
+
name: 'dashboard-scorecard',
|
|
246
|
+
basis: 'closest',
|
|
247
|
+
command: 'astryx template dashboard-scorecard --type page <path>',
|
|
248
|
+
});
|
|
249
|
+
});
|
|
250
|
+
|
|
227
251
|
it('recommends scaffolding on a direct match', async () => {
|
|
228
252
|
const r = await build('contact form', {cwd: REPO});
|
|
229
253
|
expect(r.type).toBe('build.kit');
|
|
230
254
|
if (r.type !== 'build.kit') return;
|
|
231
255
|
expect(r.data.directMatch).toBe(true);
|
|
232
256
|
expect(r.data.pages.length).toBeGreaterThan(0);
|
|
257
|
+
expect(r.data.start).toMatchObject({name: r.data.pages[0].name, basis: 'direct'});
|
|
233
258
|
for (const page of r.data.pages) {
|
|
234
259
|
expect(page.command).not.toMatch(/--skeleton/);
|
|
235
260
|
}
|
|
@@ -238,12 +263,13 @@ describe('build kit — a thin kit says what to try next', () => {
|
|
|
238
263
|
it('keeps the recommendation package-manager-agnostic', async () => {
|
|
239
264
|
// Appending a flag must not turn into prefixing an invocation; that stays
|
|
240
265
|
// the renderer's job.
|
|
241
|
-
const r = await build('
|
|
266
|
+
const r = await build('executive summary', {cwd: REPO});
|
|
242
267
|
expect(r.type).toBe('build.kit');
|
|
243
268
|
if (r.type !== 'build.kit') return;
|
|
244
269
|
for (const page of r.data.pages) {
|
|
245
270
|
expect(page.command).not.toMatch(/^(pnpm|npm|yarn|bun|npx)\b/);
|
|
246
271
|
}
|
|
272
|
+
expect(r.data.start?.command).not.toMatch(/^(pnpm|npm|yarn|bun|npx)\b/);
|
|
247
273
|
});
|
|
248
274
|
|
|
249
275
|
it('keeps recovery commands bare, for the caller to render', async () => {
|
|
@@ -258,3 +284,155 @@ describe('build kit — a thin kit says what to try next', () => {
|
|
|
258
284
|
}
|
|
259
285
|
});
|
|
260
286
|
});
|
|
287
|
+
|
|
288
|
+
describe('build kit — every page starts from a template', () => {
|
|
289
|
+
it('falls back to the app shell when no page template matches', async () => {
|
|
290
|
+
// Before, an unmatched idea got "compose from AppShell": the one path
|
|
291
|
+
// with no frame, no spacing, and no section rhythm.
|
|
292
|
+
const r = await build('zzznomatch99', {cwd: REPO});
|
|
293
|
+
expect(r.type).toBe('build.kit');
|
|
294
|
+
if (r.type !== 'build.kit') return;
|
|
295
|
+
expect(r.data.hasResults).toBe(false);
|
|
296
|
+
expect(r.data.start).toMatchObject({
|
|
297
|
+
name: 'shell-top-nav',
|
|
298
|
+
basis: 'fallback',
|
|
299
|
+
command: 'astryx template shell-top-nav --type page <path>',
|
|
300
|
+
});
|
|
301
|
+
expect(r.data.start?.description).toBeTruthy();
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
it('starts a long idea from the family its words name', async () => {
|
|
305
|
+
// The coverage gate cannot tell layout words from subject matter: every
|
|
306
|
+
// dashboard covers one term of three, so search offers no page at all.
|
|
307
|
+
// The ranker still starts the page from the dashboard.
|
|
308
|
+
const r = await build('quarterly revenue dashboard', {cwd: REPO});
|
|
309
|
+
expect(r.type).toBe('build.kit');
|
|
310
|
+
if (r.type !== 'build.kit') return;
|
|
311
|
+
expect(r.data.start).toMatchObject({name: 'dashboard', basis: 'closest'});
|
|
312
|
+
expect(r.data.directMatch).toBe(false);
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
it('does not start from a direct match that is not ready yet, and says so', async () => {
|
|
316
|
+
const r = await build('incident console', {cwd: REPO});
|
|
317
|
+
expect(r.type).toBe('build.kit');
|
|
318
|
+
if (r.type !== 'build.kit') return;
|
|
319
|
+
expect(r.data.directMatch).toBe(true);
|
|
320
|
+
expect(r.data.pages[0].name).toBe('incident-console');
|
|
321
|
+
expect(r.data.start?.name).not.toBe('incident-console');
|
|
322
|
+
expect(r.data.start?.reason).toMatch(/`incident-console` matches but is not ready yet/);
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
it('does not start from a page that matched one incidental word', async () => {
|
|
326
|
+
// A work-item detail page mentions a feed in its description. That is a
|
|
327
|
+
// worse start for a news feed than the app shell.
|
|
328
|
+
const r = await build('news feed', {cwd: REPO});
|
|
329
|
+
expect(r.type).toBe('build.kit');
|
|
330
|
+
if (r.type !== 'build.kit') return;
|
|
331
|
+
expect(r.data.start?.basis).toBe('fallback');
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
it('starts a part from the page it is placed in, else from the app shell', async () => {
|
|
335
|
+
const placed = await build('an empty state for a settings page', {cwd: REPO});
|
|
336
|
+
if (placed.type !== 'build.kit') throw new Error(placed.type);
|
|
337
|
+
expect(placed.data.start).toMatchObject({name: 'settings', basis: 'closest'});
|
|
338
|
+
const loose = await build('a date range picker', {cwd: REPO});
|
|
339
|
+
if (loose.type !== 'build.kit') throw new Error(loose.type);
|
|
340
|
+
expect(loose.data.start).toMatchObject({name: 'shell-top-nav', basis: 'fallback'});
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
it('names a direct match the ranker outweighed in the reason', async () => {
|
|
344
|
+
const r = await build('dashboard with a login form', {cwd: REPO});
|
|
345
|
+
if (r.type !== 'build.kit') throw new Error(r.type);
|
|
346
|
+
expect(r.data.directMatch).toBe(true);
|
|
347
|
+
expect(r.data.pages[0].name).toBe('login');
|
|
348
|
+
expect(r.data.start).toMatchObject({name: 'dashboard', basis: 'closest'});
|
|
349
|
+
expect(r.data.start?.reason).toContain('`login`');
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
it('names the loose page matches when it falls back to the shell', async () => {
|
|
353
|
+
const r = await build('news feed', {cwd: REPO});
|
|
354
|
+
if (r.type !== 'build.kit') throw new Error(r.type);
|
|
355
|
+
expect(r.data.pages.length).toBeGreaterThan(0);
|
|
356
|
+
expect(r.data.start?.basis).toBe('fallback');
|
|
357
|
+
for (const page of r.data.pages) expect(r.data.start?.reason).toContain(`\`${page.name}\``);
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
it('never gives a reason that denies a match the response reports', async () => {
|
|
361
|
+
for (const q of ['news feed', 'dashboard with a login form', 'user profile', 'incident console']) {
|
|
362
|
+
const r = await build(q, {cwd: REPO});
|
|
363
|
+
if (r.type !== 'build.kit') throw new Error(r.type);
|
|
364
|
+
if (r.data.pages.length) expect(r.data.start?.reason).not.toMatch(/No template matched/);
|
|
365
|
+
if (r.data.directMatch) expect(r.data.start?.reason).not.toMatch(/none is exactly this page/);
|
|
366
|
+
}
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
it('names no start when the kit is narrowed to components', async () => {
|
|
370
|
+
const r = await build('dashboard', {cwd: REPO, type: 'component'});
|
|
371
|
+
expect(r.type).toBe('build.kit');
|
|
372
|
+
if (r.type !== 'build.kit') return;
|
|
373
|
+
expect(r.data.start).toBeNull();
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
it('keeps incidental description matches out of blocks and components', async () => {
|
|
379
|
+
// Toast, Popover and TextInput all say "brief" somewhere in their
|
|
380
|
+
// descriptions; none of them is part of a brief.
|
|
381
|
+
const r = await build('weekly brief', {cwd: REPO});
|
|
382
|
+
expect(r.type).toBe('build.kit');
|
|
383
|
+
if (r.type !== 'build.kit') return;
|
|
384
|
+
const names = [...r.data.blocks, ...r.data.domain].map(e => e.name);
|
|
385
|
+
for (const noise of ['Toast', 'Popover', 'TextInput']) expect(names).not.toContain(noise);
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
it('names the ranker\'s next two templates beside every start', async () => {
|
|
389
|
+
for (const idea of ['quarterly revenue dashboard', 'contact form']) {
|
|
390
|
+
const r = await build(idea, {cwd: REPO});
|
|
391
|
+
expect(r.type).toBe('build.kit');
|
|
392
|
+
if (r.type !== 'build.kit') return;
|
|
393
|
+
const alternatives = r.data.start?.alternatives ?? [];
|
|
394
|
+
expect(alternatives.length).toBeGreaterThan(0);
|
|
395
|
+
expect(alternatives.length).toBeLessThanOrEqual(2);
|
|
396
|
+
for (const alt of alternatives) {
|
|
397
|
+
expect(alt.name).not.toBe(r.data.start?.name);
|
|
398
|
+
expect(alt.description).toBeTruthy();
|
|
399
|
+
expect(alt.command).toBe(`astryx template ${alt.name} --type page <path>`);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
it('calls a start direct only when search and the ranker agree', async () => {
|
|
405
|
+
const r = await build('contact form', {cwd: REPO});
|
|
406
|
+
expect(r.type).toBe('build.kit');
|
|
407
|
+
if (r.type !== 'build.kit') return;
|
|
408
|
+
expect(r.data.directMatch).toBe(true);
|
|
409
|
+
expect(r.data.start).toMatchObject({name: r.data.pages[0].name, basis: 'direct'});
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
it('never lets a noisy search match pick the start', async () => {
|
|
413
|
+
// Search once matched "site" to the gallery's "side" and started a
|
|
414
|
+
// navigation bar from a gallery. The ranker alone picks the start now.
|
|
415
|
+
const r = await build('horizontal site navigation with a current section indicator', {cwd: REPO});
|
|
416
|
+
expect(r.type).toBe('build.kit');
|
|
417
|
+
if (r.type !== 'build.kit') return;
|
|
418
|
+
expect(r.data.start?.name).toBe('shell-top-nav');
|
|
419
|
+
expect(r.data.pages.map(p => p.name)).not.toContain('side-gallery');
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
it('starts a component in a container from a template with that frame', async () => {
|
|
423
|
+
// "in a modal": the modal is the frame, so the dialog template leads
|
|
424
|
+
// instead of the app shell.
|
|
425
|
+
const r = await build('saved drafts in a modal with resume and delete row actions', {cwd: REPO});
|
|
426
|
+
expect(r.type).toBe('build.kit');
|
|
427
|
+
if (r.type !== 'build.kit') return;
|
|
428
|
+
expect(r.data.start?.name).toBe('settings-dialog');
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
it('does not start from a template named only by a word that modifies another', async () => {
|
|
432
|
+
// "product" describes the response; it is not a product page.
|
|
433
|
+
const r = await build('an interactive command catalog with side-by-side product response and trace', {cwd: REPO});
|
|
434
|
+
expect(r.type).toBe('build.kit');
|
|
435
|
+
if (r.type !== 'build.kit') return;
|
|
436
|
+
expect(r.data.start?.name).not.toMatch(/^product-/);
|
|
437
|
+
});
|
|
438
|
+
});
|