@astryxdesign/cli 0.6.3-canary.98a2e4e → 0.6.3-canary.9c4d44d
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 +117 -79
- 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 +16 -9
- package/api/build/build.test.mjs +197 -8
- package/api/build/build.type.d.mts +91 -2
- package/api/build/build.type.mjs +52 -8
- package/api/build/help/help.d.mts +12 -5
- package/api/build/help/help.mjs +69 -6
- 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 +13 -3
- package/api/component/component.mjs +91 -14
- package/api/component/component.test.mjs +38 -0
- package/api/component/component.type.d.mts +22 -11
- package/api/component/component.type.mjs +32 -24
- package/api/component/detail/blocks/blocks.d.mts +2 -1
- package/api/component/detail/blocks/blocks.mjs +4 -3
- package/api/component/list/list.d.mts +0 -5
- package/api/component/list/list.mjs +40 -11
- package/api/discover/_adapter.d.mts +114 -6
- package/api/discover/_adapter.mjs +372 -17
- package/api/discover/_adapter.test.mjs +215 -0
- package/api/discover/_catalog-view.d.mts +115 -0
- package/api/discover/_catalog-view.mjs +203 -0
- package/api/discover/_catalog-view.test.mjs +128 -0
- package/api/discover/detail/detail.d.mts +18 -6
- package/api/discover/detail/detail.mjs +67 -13
- package/api/discover/detail/detail.test.mjs +85 -0
- package/api/discover/detail/item/item.d.mts +26 -0
- package/api/discover/detail/item/item.mjs +78 -0
- package/api/discover/detail/item/item.test.mjs +73 -0
- package/api/discover/discover.d.mts +3 -9
- package/api/discover/discover.doc.mjs +62 -18
- package/api/discover/discover.mjs +220 -36
- package/api/discover/discover.test.mjs +11 -2
- package/api/discover/discover.type.d.mts +150 -11
- package/api/discover/discover.type.mjs +107 -17
- package/api/discover/list/list.d.mts +20 -6
- package/api/discover/list/list.mjs +45 -12
- package/api/discover/list/list.test.mjs +46 -0
- package/api/discover/search/search.d.mts +18 -16
- package/api/discover/search/search.mjs +102 -56
- package/api/discover/search/search.test.mjs +144 -10
- package/api/docs/_adapter.d.mts +268 -47
- package/api/docs/_adapter.mjs +970 -149
- package/api/docs/compiled-topics.test.mjs +78 -0
- package/api/docs/detail/detail.d.mts +0 -15
- package/api/docs/detail/detail.mjs +22 -78
- package/api/docs/detail/section/section.mjs +39 -24
- package/api/docs/detail/section/section.test.mjs +19 -9
- 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 +185 -6
- package/api/docs/docs.type.mjs +127 -13
- package/api/docs/index/index.mjs +15 -6
- 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 +332 -21
- package/api/doctor/doctor.test.mjs +420 -7
- package/api/gap-report/gap-report.doc.mjs +8 -4
- package/api/hook/_adapter.mjs +19 -5
- package/api/hook/hook.doc.mjs +1 -0
- package/api/hook/hook.type.d.mts +3 -3
- package/api/hook/hook.type.mjs +11 -11
- package/api/hook/list/list.d.mts +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 +6 -1
- package/api/init/init.test.mjs +41 -1
- package/api/init/remove/remove.mjs +1 -1
- package/api/init/run/run.mjs +20 -10
- package/api/integration/add-contribution.component-names.test.mjs +120 -0
- package/api/integration/add-contribution.d.mts +2 -1
- package/api/integration/add-contribution.mjs +130 -15
- package/api/integration/add-contribution.test.mjs +258 -7
- package/api/integration/add-helpers.d.mts +5 -2
- package/api/integration/add-helpers.mjs +36 -9
- 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 +14 -4
- package/api/integration/integrationAddAgentDoc.doc.mjs +1 -0
- package/api/integration/integrationAddCodemod.doc.mjs +1 -0
- package/api/integration/integrationAddComponent.doc.mjs +2 -1
- package/api/integration/integrationAddDoc.doc.mjs +8 -1
- package/api/integration/integrationAddTemplate.doc.mjs +1 -0
- package/api/integration/integrationAddTheme.doc.mjs +6 -5
- package/api/integration/integrationComponentConflicts.doc.mjs +1 -0
- package/api/integration/integrationDocConflicts.doc.mjs +2 -1
- package/api/integration/integrationPackCheck.doc.mjs +2 -1
- package/api/integration/integrationTemplateConflicts.doc.d.mts +3 -0
- package/api/integration/integrationTemplateConflicts.doc.mjs +4 -0
- package/api/integration/pack-check.mjs +83 -7
- package/api/integration/pack-check.test.mjs +387 -47
- package/api/integration/pack-check.type.d.mts +26 -2
- package/api/integration/pack-check.type.mjs +14 -1
- package/api/integration/summarizeIssues.doc.mjs +1 -0
- package/api/integration/template-conflict-compatibility.test.mjs +73 -0
- package/api/integration/validate-integration-fixes.test.mjs +1389 -0
- package/api/integration/validate-integration.mjs +52 -102
- package/api/integration/validate-integration.test.mjs +179 -26
- package/api/integration/validate-unread-theme-folders.test.mjs +110 -0
- package/api/integration/validateIntegration.doc.mjs +3 -2
- package/api/json/assertResponse.doc.mjs +1 -0
- package/api/json/envelope-types.test.mjs +76 -0
- package/api/json/index.ts +2 -0
- package/api/json/isError.doc.mjs +1 -0
- package/api/json/parseResponse.doc.mjs +3 -2
- package/api/layout/_adapter.mjs +20 -5
- package/api/layout/expand/expand.mjs +7 -5
- package/api/layout/expand/expand.path-safety.test.mjs +53 -0
- package/api/layout/grammar/grammar.mjs +2 -1
- package/api/layout/layoutCheck.doc.mjs +1 -0
- package/api/layout/layoutExpand.doc.mjs +2 -1
- package/api/layout/layoutGrammar.doc.mjs +1 -0
- package/api/search/search-return-type.test.mjs +54 -0
- package/api/search/search.d.mts +61 -10
- package/api/search/search.doc.mjs +8 -2
- package/api/search/search.mjs +471 -83
- package/api/search/search.test.mjs +124 -1
- package/api/search/search.type.d.mts +14 -2
- package/api/search/search.type.mjs +5 -2
- package/api/swizzle/copy/copy.mjs +28 -11
- package/api/swizzle/swizzle.doc.mjs +2 -1
- package/api/swizzle/swizzle.type.d.mts +2 -2
- package/api/swizzle/swizzle.type.mjs +2 -2
- package/api/template/copy/copy.mjs +17 -23
- package/api/template/copy/copy.test.mjs +17 -0
- package/api/template/list/list.mjs +1 -0
- package/api/template/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 +30 -8
- package/api/template/template.mjs +45 -8
- package/api/template/template.type.d.mts +11 -13
- package/api/template/template.type.mjs +15 -14
- package/api/theme/_adapter.d.mts +2 -3
- package/api/theme/_adapter.mjs +4 -5
- package/api/theme/add/add.binary.test.mjs +84 -0
- package/api/theme/add/add.mjs +31 -22
- package/api/theme/add/add.rollback.test.mjs +158 -0
- package/api/theme/add/add.staging.test.mjs +83 -0
- package/api/theme/add/add.test.mjs +14 -1
- package/api/theme/build/build.family.test.mjs +7 -12
- package/api/theme/build/build.mjs +140 -59
- package/api/theme/build/build.public-component-vars.test.mjs +1 -1
- package/api/theme/build/build.receipt-doc.test.mjs +111 -0
- package/api/theme/build/build.rollback.test.mjs +148 -0
- package/api/theme/build/build.test.mjs +127 -0
- package/api/theme/build/font-warning.mjs +3 -3
- package/api/theme/build/font-warning.test.mjs +5 -2
- package/api/theme/generateTonalPalette.doc.mjs +1 -0
- package/api/theme/integration-themes.test.mjs +39 -28
- package/api/theme/list/list.test.mjs +19 -20
- package/api/theme/listThemes.doc.mjs +6 -5
- package/api/theme/palette/generate/generate.mjs +8 -3
- package/api/theme/palette/generate/generate.test.mjs +96 -0
- package/api/theme/palette/generate/generator.d.mts +10 -13
- package/api/theme/palette/generate/generator.mjs +15 -4
- package/api/theme/palette/generate/generator.test.mjs +10 -0
- package/api/theme/template/template.mjs +11 -2
- package/api/theme/template/template.test.mjs +20 -0
- package/api/theme/theme.type.d.mts +170 -11
- package/api/theme/theme.type.mjs +94 -27
- package/api/theme/themeAdd.doc.mjs +4 -3
- package/api/theme/themeBuild.doc.mjs +8 -4
- package/api/theme/themeList.doc.mjs +6 -3
- package/api/theme/themeListAvailable.doc.mjs +5 -3
- package/api/theme/themePaletteGenerate.doc.mjs +1 -0
- package/api/theme/themeTargets.doc.mjs +1 -0
- package/api/theme/themeTemplate.doc.mjs +6 -2
- package/api/upgrade/_adapter.d.mts +32 -5
- package/api/upgrade/_adapter.mjs +124 -73
- package/api/upgrade/list/list.mjs +2 -1
- package/api/upgrade/list/list.test.mjs +73 -0
- package/api/upgrade/provider-agreement.test.mjs +152 -0
- package/api/upgrade/run/run.mjs +356 -59
- package/api/upgrade/status/status.mjs +2 -2
- package/api/upgrade/upgrade.doc.mjs +8 -2
- package/api/upgrade/upgrade.type.d.mts +42 -4
- package/api/upgrade/upgrade.type.mjs +26 -10
- package/assets/codemods/__tests__/runner.test.mjs +330 -8
- package/assets/codemods/integration-discovery.mjs +48 -4
- package/assets/codemods/integration-discovery.test.mjs +73 -0
- package/assets/codemods/integration-runner.mjs +56 -4
- package/assets/codemods/integration-runner.protection.test.mjs +153 -0
- package/assets/codemods/run-codemod.mjs +177 -34
- package/assets/codemods/runner.mjs +350 -102
- package/assets/codemods/term-log.mjs +32 -8
- package/assets/codemods/term-log.test.mjs +19 -1
- package/assets/codemods/transform-prop.mjs +109 -0
- package/assets/codemods/transform-prop.test.mjs +95 -0
- package/assets/codemods/transforms/next/__tests__/migrate-native-picker-to-presentation.test.mjs +63 -0
- package/assets/codemods/transforms/next/__tests__/migrate-theme-catalog-to-descriptors.test.mjs +220 -0
- package/assets/codemods/transforms/next/index.mjs +19 -1
- package/assets/codemods/transforms/next/migrate-native-picker-to-presentation.mjs +148 -0
- package/assets/codemods/transforms/next/migrate-theme-catalog-to-descriptors.mjs +141 -0
- package/assets/codemods/transforms/v0.0.14/__tests__/rename-status-variants.test.mjs +86 -165
- package/assets/codemods/transforms/v0.0.14/rename-status-variants.mjs +72 -210
- package/assets/codemods/transforms/v0.1.8/__tests__/rename-avatar-size-scale.test.mjs +83 -115
- package/assets/codemods/transforms/v0.1.8/rename-avatar-size-scale.mjs +57 -186
- package/assets/codemods/transforms/v0.3.0/__tests__/unwrap-authoring-factories.test.mjs +27 -5
- package/assets/codemods/transforms/v0.3.0/unwrap-authoring-factories.mjs +20 -5
- package/assets/codemods/transforms/v0.6.0/__tests__/next-codemods.test.mjs +47 -0
- package/assets/codemods/transforms/v0.6.0/rename-resizable-pixel-bounds.mjs +57 -10
- package/assets/docs/getting-started.doc.mjs +2 -2
- package/assets/docs/internationalization.doc.mjs +7 -5
- 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 +4 -4
- 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} +95 -39
- 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 +4 -4
- 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/InternationalizationProvider/InternationalizationProvider01ShippedLocale.tsx +1 -1
- package/assets/templates/blocks/components/Item/ItemDocumentTabs.doc.mjs +14 -0
- package/assets/templates/blocks/components/Item/ItemDocumentTabs.tsx +100 -0
- package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaInlineRail.doc.mjs +14 -0
- package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaInlineRail.tsx +61 -0
- package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaOverscrollChaining.doc.mjs +14 -0
- package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaOverscrollChaining.tsx +126 -0
- package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaShowcase.doc.mjs +15 -0
- package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaShowcase.tsx +86 -0
- package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyGroupHeaders.doc.mjs +14 -0
- package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyGroupHeaders.tsx +99 -0
- package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyPassthrough.doc.mjs +14 -0
- package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyPassthrough.tsx +122 -0
- package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaTwoAxisBoard.doc.mjs +14 -0
- package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaTwoAxisBoard.tsx +95 -0
- package/assets/templates/blocks/components/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/pages/table-tree/page.tsx +1704 -0
- package/assets/templates/pages/table-tree/template.doc.mjs +12 -0
- package/assets/templates/themes/butter/butterTheme.doc.mjs +11 -0
- package/assets/templates/themes/chocolate/chocolateTheme.doc.mjs +11 -0
- package/assets/templates/themes/gothic/gothicTheme.doc.mjs +11 -0
- package/assets/templates/themes/matcha/matchaTheme.doc.mjs +11 -0
- package/assets/templates/themes/neutral/neutralTheme.doc.mjs +11 -0
- package/assets/templates/themes/stone/stoneTheme.doc.mjs +11 -0
- package/assets/templates/themes/y2k/y2kTheme.doc.mjs +11 -0
- package/authoring/_shared/contract.ts +22 -0
- package/authoring/codemod/codemod.doc.mjs +7 -2
- package/authoring/codemod/parse.d.mts +8 -8
- package/authoring/codemod/parse.mjs +8 -6
- package/authoring/codemod/type.ts +12 -0
- package/authoring/config/config.doc.mjs +10 -2
- package/authoring/config/debug-composition.test.mjs +92 -0
- package/authoring/config/parse.d.mts +15 -13
- package/authoring/config/parse.mjs +27 -8
- package/authoring/config/parse.test.mjs +8 -0
- package/authoring/config/type.ts +29 -6
- package/authoring/debug/debug.doc.d.mts +11 -0
- package/authoring/debug/debug.doc.mjs +182 -0
- package/authoring/debug/parse.d.mts +7 -7
- package/authoring/debug/parse.mjs +3 -3
- package/authoring/discover/discover.doc.d.mts +13 -0
- package/authoring/discover/discover.doc.mjs +138 -0
- package/authoring/discover/parse.d.mts +24 -0
- package/authoring/discover/parse.mjs +128 -0
- package/authoring/discover/parse.test.mjs +124 -0
- package/authoring/discover/type.ts +87 -0
- package/authoring/doctypes/_schema.d.mts +240 -128
- package/authoring/doctypes/_schema.mjs +198 -16
- package/authoring/doctypes/base/graph-fields.doc.mjs +15 -6
- package/authoring/doctypes/base/type.ts +9 -4
- package/authoring/doctypes/command/command.doc.mjs +4 -3
- package/authoring/doctypes/command/parse.d.mts +2 -2
- package/authoring/doctypes/command/parse.mjs +1 -1
- package/authoring/doctypes/command/type.ts +4 -4
- package/authoring/doctypes/component/component.doc.mjs +5 -2
- package/authoring/doctypes/component/parse.d.mts +2 -2
- package/authoring/doctypes/component/parse.mjs +1 -1
- package/authoring/doctypes/component/type.ts +3 -3
- package/authoring/doctypes/doctypes-new.test.mjs +48 -6
- package/authoring/doctypes/enum/enum.doc.mjs +1 -1
- package/authoring/doctypes/enum/parse.d.mts +2 -2
- package/authoring/doctypes/enum/parse.mjs +1 -1
- package/authoring/doctypes/enum/type.ts +2 -2
- package/authoring/doctypes/function/function.doc.mjs +7 -2
- package/authoring/doctypes/function/parse.d.mts +2 -2
- package/authoring/doctypes/function/parse.mjs +1 -1
- package/authoring/doctypes/function/type.ts +4 -3
- package/authoring/doctypes/hook/hook.doc.mjs +4 -0
- package/authoring/doctypes/hook/parse.d.mts +2 -2
- package/authoring/doctypes/hook/parse.mjs +1 -1
- package/authoring/doctypes/hook/type.ts +3 -3
- package/authoring/doctypes/legacy.d.mts +6 -6
- package/authoring/doctypes/legacy.mjs +3 -3
- package/authoring/doctypes/load-contract.test.mjs +233 -0
- package/authoring/doctypes/namespace/namespace.doc.mjs +9 -9
- package/authoring/doctypes/namespace/parse.d.mts +2 -2
- package/authoring/doctypes/namespace/parse.mjs +1 -1
- package/authoring/doctypes/namespace/parse.test.mjs +23 -25
- package/authoring/doctypes/namespace/type.ts +6 -3
- package/authoring/doctypes/parse.d.mts +22 -20
- package/authoring/doctypes/parse.mjs +19 -14
- package/authoring/doctypes/reference/parse.d.mts +2 -2
- package/authoring/doctypes/reference/parse.mjs +1 -1
- package/authoring/doctypes/reference/reference.doc.mjs +39 -6
- package/authoring/doctypes/reference/type.ts +31 -14
- package/authoring/doctypes/schema/parse.d.mts +2 -2
- package/authoring/doctypes/schema/parse.mjs +1 -1
- package/authoring/doctypes/schema/schema.doc.mjs +1 -1
- package/authoring/doctypes/schema/type.ts +3 -4
- package/authoring/doctypes/template/parse.d.mts +94 -1
- package/authoring/doctypes/template/parse.mjs +37 -1
- package/authoring/doctypes/template/parse.test.mjs +18 -0
- package/authoring/doctypes/template/template.doc.mjs +13 -3
- package/authoring/doctypes/template/type.ts +12 -1
- package/authoring/doctypes/theme/parse.d.mts +35 -0
- package/authoring/doctypes/theme/parse.mjs +76 -0
- package/authoring/doctypes/theme/theme.doc.d.mts +9 -0
- package/authoring/doctypes/theme/theme.doc.mjs +79 -0
- package/authoring/doctypes/theme/type.ts +42 -0
- package/authoring/doctypes/types.ts +12 -11
- package/authoring/gap-report/gap-report.doc.d.mts +12 -0
- package/authoring/gap-report/gap-report.doc.mjs +183 -0
- package/authoring/gap-report/parse.d.mts +9 -9
- package/authoring/gap-report/parse.mjs +6 -6
- package/authoring/gap-report/type.ts +1 -1
- package/authoring/identity/identity.doc.mjs +3 -2
- package/authoring/identity/type.ts +10 -10
- package/authoring/index.d.mts +2 -0
- package/authoring/index.d.ts +32 -19
- package/authoring/index.mjs +3 -1
- package/authoring/integration/integration.doc.mjs +2 -2
- package/authoring/integration/parse.d.mts +2 -2
- package/authoring/integration/parse.mjs +1 -1
- package/authoring/integration/schema.d.mts +4 -4
- package/authoring/integration/schema.mjs +3 -3
- package/authoring/integration/type.ts +5 -11
- package/clients/cli/__tests__/cliManifest.test.ts +27 -29
- package/clients/cli/command-load-failure.test.mjs +83 -0
- package/clients/cli/commands/blog.doc.mjs +1 -1
- package/clients/cli/commands/blog.mjs +23 -8
- package/clients/cli/commands/blog.test.mjs +42 -1
- package/clients/cli/commands/build-theme.adaptations.test.mjs +100 -1
- package/clients/cli/commands/build-theme.ascii-output.test.mjs +161 -0
- package/clients/cli/commands/build-theme.flag-docs.test.mjs +110 -0
- package/clients/cli/commands/build-theme.mjs +16 -50
- package/clients/cli/commands/build-theme.path-safety.test.mjs +86 -1
- package/clients/cli/commands/build-theme.variants.test.mjs +76 -0
- package/clients/cli/commands/build.doc.mjs +16 -8
- package/clients/cli/commands/build.exit-codes-doc.test.mjs +50 -0
- package/clients/cli/commands/build.mjs +137 -114
- package/clients/cli/commands/build.playbook.test.mjs +75 -0
- package/clients/cli/commands/build.text-fields.test.mjs +81 -0
- package/clients/cli/commands/component/index.mjs +3 -8
- package/clients/cli/commands/component-ownership.test.mjs +3 -3
- package/clients/cli/commands/component-package.test.mjs +46 -0
- package/clients/cli/commands/component-resolution.test.mjs +21 -0
- package/clients/cli/commands/component.doc.mjs +1 -1
- package/clients/cli/commands/component.test.mjs +19 -0
- package/clients/cli/commands/detail-levels.test.mjs +2 -2
- package/clients/cli/commands/discover.broken-integration.test.mjs +52 -5
- package/clients/cli/commands/discover.components-flag.test.mjs +97 -0
- package/clients/cli/commands/discover.doc.mjs +55 -9
- package/clients/cli/commands/discover.mjs +393 -118
- package/clients/cli/commands/discover.sources.test.mjs +267 -0
- package/clients/cli/commands/discover.text-projection.test.mjs +103 -0
- 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.package-json.test.mjs +53 -0
- 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 +59 -32
- package/clients/cli/commands/doctor.test.mjs +42 -0
- package/clients/cli/commands/gap-report.doc.mjs +17 -6
- package/clients/cli/commands/gap-report.test.mjs +72 -0
- package/clients/cli/commands/hook/index.mjs +7 -17
- package/clients/cli/commands/hook.doc.mjs +1 -1
- package/clients/cli/commands/hook.text-projection.test.mjs +45 -0
- package/clients/cli/commands/init.doc.mjs +20 -9
- package/clients/cli/commands/init.flag-help.test.mjs +153 -0
- package/clients/cli/commands/integration-add.controls.test.mjs +132 -0
- package/clients/cli/commands/integration-add.doc.mjs +32 -6
- package/clients/cli/commands/integration-authoring.test.mjs +13 -9
- package/clients/cli/commands/integration-pack.doc.mjs +1 -1
- package/clients/cli/commands/integration-real-world.test.mjs +3 -9
- package/clients/cli/commands/integration.doc.mjs +1 -1
- package/clients/cli/commands/integration.mjs +1 -0
- package/clients/cli/commands/interactive-guard.test.mjs +101 -24
- package/clients/cli/commands/json-contract.test.mjs +33 -0
- package/clients/cli/commands/layout-check.doc.mjs +15 -4
- package/clients/cli/commands/layout-expand.doc.mjs +22 -5
- package/clients/cli/commands/layout-grammar.doc.mjs +1 -1
- package/clients/cli/commands/layout.doc.mjs +3 -3
- package/clients/cli/commands/layout.mjs +21 -9
- package/clients/cli/commands/layout.path-help.test.mjs +33 -0
- package/clients/cli/commands/layout.stdin-cap.test.mjs +47 -0
- package/clients/cli/commands/layout.text-fields.test.mjs +39 -0
- package/clients/cli/commands/manifest.doc.mjs +1 -1
- package/clients/cli/commands/no-prompt-wording.test.mjs +94 -0
- package/clients/cli/commands/search.doc.mjs +7 -4
- package/clients/cli/commands/search.mjs +28 -9
- package/clients/cli/commands/search.test.mjs +75 -0
- package/clients/cli/commands/setup-nudge.test.mjs +6 -0
- package/clients/cli/commands/swizzle.doc.mjs +3 -2
- package/clients/cli/commands/swizzle.path-safety.test.mjs +42 -0
- package/clients/cli/commands/template.doc.mjs +52 -13
- package/clients/cli/commands/template.flag-help.test.mjs +117 -0
- package/clients/cli/commands/template.mjs +4 -91
- package/clients/cli/commands/template.path-help.test.mjs +40 -0
- package/clients/cli/commands/text-json-parity.test.mjs +719 -0
- package/clients/cli/commands/theme-add.doc.mjs +4 -3
- package/clients/cli/commands/theme-build.doc.mjs +8 -7
- package/clients/cli/commands/theme-list.doc.mjs +2 -2
- package/clients/cli/commands/theme-palette-generate.doc.mjs +3 -3
- package/clients/cli/commands/theme-palette-generate.test.mjs +19 -0
- package/clients/cli/commands/theme-palette.doc.mjs +1 -1
- package/clients/cli/commands/theme-targets.behavior.test.mjs +4 -3
- package/clients/cli/commands/theme-targets.doc.mjs +1 -1
- package/clients/cli/commands/theme-template.behavior.test.mjs +12 -0
- package/clients/cli/commands/theme-template.doc.mjs +2 -2
- package/clients/cli/commands/theme.doc.mjs +1 -1
- package/clients/cli/commands/upgrade.ascii-output.test.mjs +87 -0
- package/clients/cli/commands/upgrade.doc.mjs +20 -8
- package/clients/cli/commands/upgrade.file-protection.test.mjs +228 -0
- package/clients/cli/commands/upgrade.flag-help.test.mjs +188 -0
- package/clients/cli/commands/upgrade.hook-output.test.mjs +88 -0
- package/clients/cli/commands/upgrade.mjs +29 -7
- package/clients/cli/formatters/index.mjs +2 -0
- package/clients/cli/formatters/index.test.mjs +6 -0
- package/clients/cli/index.mjs +21 -30
- package/clients/cli/latest-version-env.test.mjs +50 -0
- package/clients/cli/lib/cli-error.test.mjs +7 -0
- package/clients/cli/lib/component-format.mjs +9 -9
- package/clients/cli/lib/component-format.test.mjs +1 -1
- package/clients/cli/lib/define-command.mjs +32 -6
- package/clients/cli/lib/doc-text-ascii.test.mjs +82 -0
- package/clients/cli/lib/exit-codes.test.mjs +97 -0
- package/clients/cli/lib/hook-format.mjs +19 -10
- package/clients/cli/lib/json-shim.mjs +38 -2
- package/clients/cli/lib/json-shim.test.mjs +83 -0
- package/clients/cli/lib/manifest.d.ts +2 -0
- package/clients/cli/lib/manifest.mjs +32 -2
- package/clients/cli/lib/manifest.test.mjs +17 -0
- package/foundation/agent-docs/agent-docs.d.mts +7 -2
- package/foundation/agent-docs/agent-docs.mjs +82 -12
- package/foundation/agent-docs/agent-docs.path-safety.test.mjs +266 -4
- package/foundation/agent-docs/agent-docs.test.mjs +19 -1
- package/foundation/config/integration-debug.test.mjs +28 -3
- package/foundation/config/project-themes.test.mjs +11 -19
- package/foundation/config/project.d.mts +20 -11
- package/foundation/config/project.mjs +246 -89
- package/foundation/config/project.test.mjs +270 -21
- package/foundation/discovery/authoring-self-docs.d.mts +18 -0
- package/foundation/discovery/authoring-self-docs.mjs +38 -15
- package/foundation/discovery/authoring-self-docs.test.mjs +87 -12
- 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 +114 -9
- package/foundation/discovery/docs-discovery.mjs +239 -30
- package/foundation/discovery/docs-discovery.test.mjs +150 -35
- 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 +113 -11
- package/foundation/discovery/template-adapter.fixture-refs.test.mjs +248 -0
- package/foundation/discovery/template-adapter.integration-isolation.test.mjs +94 -0
- package/foundation/discovery/template-adapter.mjs +772 -82
- 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/discovery/theming-targets.test.mjs +4 -0
- package/foundation/doc-compiler/bundle.d.mts +47 -0
- package/foundation/doc-compiler/bundle.mjs +278 -0
- package/foundation/doc-compiler/bundle.test.mjs +266 -0
- package/foundation/doc-compiler/compile.d.mts +343 -0
- package/foundation/doc-compiler/compile.mjs +558 -0
- package/foundation/doc-compiler/diagnostics.d.mts +126 -0
- package/foundation/doc-compiler/diagnostics.mjs +305 -0
- package/foundation/doc-compiler/doc-compiler.test.mjs +714 -0
- package/foundation/doc-compiler/doc-loads.test.mjs +1642 -0
- package/foundation/doc-compiler/import.d.mts +24 -0
- package/foundation/doc-compiler/import.mjs +59 -0
- package/foundation/doc-compiler/inputs.d.mts +102 -0
- package/foundation/doc-compiler/inputs.mjs +291 -0
- package/foundation/doc-compiler/inputs.test.mjs +299 -0
- package/foundation/doc-compiler/ir.d.mts +22 -0
- package/foundation/doc-compiler/ir.mjs +471 -0
- package/foundation/doc-compiler/lenses.d.mts +36 -0
- package/foundation/doc-compiler/lenses.mjs +173 -0
- 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/fs/module-loader.d.mts +1 -0
- package/foundation/fs/module-loader.mjs +50 -1
- package/foundation/fs/module-loader.stdout.test.mjs +332 -0
- package/foundation/fs/path-safety.d.mts +3 -2
- package/foundation/fs/path-safety.mjs +49 -19
- package/foundation/fs/path-safety.test.mjs +50 -0
- package/foundation/fs/publish-file-hardlink-unavailable.test.mjs +129 -94
- package/foundation/integrations/autolink.d.mts +58 -1
- package/foundation/integrations/autolink.mjs +143 -52
- 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 +17 -1
- package/foundation/integrations/integrations.mjs +52 -98
- package/foundation/integrations/integrations.test.mjs +31 -0
- package/foundation/integrations/provider-ledger.test.mjs +275 -0
- package/foundation/integrations/provider-resolution.d.mts +152 -0
- package/foundation/integrations/provider-resolution.mjs +576 -0
- package/foundation/integrations/provider-resolution.test.mjs +369 -0
- package/foundation/integrations/theme-descriptor.d.mts +8 -0
- package/foundation/integrations/theme-descriptor.mjs +44 -0
- package/foundation/integrations/validate-contributions.mjs +121 -29
- package/foundation/response/base.d.ts +8 -4
- package/foundation/response/error-codes.d.mts +3 -1
- package/foundation/response/error-codes.d.ts +2 -0
- package/foundation/response/error-codes.doc.mjs +13 -4
- package/foundation/response/error-codes.mjs +8 -2
- package/foundation/response/error-codes.test.mjs +137 -10
- package/foundation/response/json-contract.test.mjs +11 -0
- package/foundation/response/json.d.mts +4 -2
- package/foundation/response/json.mjs +8 -10
- package/foundation/response/response-types.doc.d.mts +5 -1
- package/foundation/response/response-types.doc.mjs +37 -22
- package/foundation/response/response-types.doc.test.mjs +158 -0
- 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.d.mts +2 -0
- package/foundation/xle/expand.mjs +4 -3
- package/foundation/xle/expand.test.mjs +54 -0
- package/foundation/xle/xle.test.mjs +13 -0
- package/package.json +10 -11
- package/assets/templates/themes/manifest.json +0 -95
- package/clients/cli/lib/update-check.mjs +0 -83
- package/clients/cli/lib/update-check.test.mjs +0 -137
- package/clients/cli/update-hint-commands.test.mjs +0 -54
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file Human output of the `theme` command group stays plain ASCII.
|
|
5
|
+
*
|
|
6
|
+
* Covers every theme-build line family that carried a glyph or typographic
|
|
7
|
+
* punctuation: success, warning, error, notice, and font-help lines of a
|
|
8
|
+
* standalone build; `--check` in both states; a batch build and check; a
|
|
9
|
+
* family build and check; the quoted-glob suggestion; and a palette preview.
|
|
10
|
+
* Each case also asserts its ASCII marker, so a line that stops printing
|
|
11
|
+
* cannot pass the ASCII check vacuously.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import {describe, it, expect, beforeAll, beforeEach, afterEach} from 'vitest';
|
|
15
|
+
import * as fs from 'node:fs';
|
|
16
|
+
import * as path from 'node:path';
|
|
17
|
+
import {ensureCoreBuilt} from './ensure-core-built.mjs';
|
|
18
|
+
import {runCli} from '../../../test-utils/run-cli.mjs';
|
|
19
|
+
|
|
20
|
+
// Under the CLI package so fixtures resolve `@astryxdesign/core/theme`.
|
|
21
|
+
const CLI_ROOT = path.resolve(import.meta.dirname, '../../..');
|
|
22
|
+
|
|
23
|
+
const OCEAN = `import {defineTheme} from '@astryxdesign/core/theme';
|
|
24
|
+
export const oceanTheme = defineTheme({
|
|
25
|
+
name: 'ocean',
|
|
26
|
+
typography: {body: {family: 'Inter'}},
|
|
27
|
+
tokens: {'--color-background-body': '#ffffff'},
|
|
28
|
+
components: {
|
|
29
|
+
progressbar: {base: {color: 'red'}},
|
|
30
|
+
button: {base: {'--_button-radius': '2px'}},
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
`;
|
|
34
|
+
const CALM = `import {defineTheme} from '@astryxdesign/core/theme';
|
|
35
|
+
import {oceanTheme} from './ocean.mjs';
|
|
36
|
+
export const oceanCalmTheme = defineTheme({
|
|
37
|
+
name: 'ocean-calm',
|
|
38
|
+
extends: oceanTheme,
|
|
39
|
+
tokens: {'--color-background-body': '#eeeeee'},
|
|
40
|
+
});
|
|
41
|
+
`;
|
|
42
|
+
|
|
43
|
+
/** @type {string} */
|
|
44
|
+
let dir;
|
|
45
|
+
|
|
46
|
+
beforeAll(() => {
|
|
47
|
+
ensureCoreBuilt();
|
|
48
|
+
}, 200_000);
|
|
49
|
+
|
|
50
|
+
beforeEach(() => {
|
|
51
|
+
dir = fs.mkdtempSync(path.join(CLI_ROOT, '.tmp-theme-ascii-'));
|
|
52
|
+
fs.writeFileSync(path.join(dir, 'package.json'), '{"type":"module"}\n');
|
|
53
|
+
fs.writeFileSync(path.join(dir, 'ocean.mjs'), OCEAN);
|
|
54
|
+
fs.writeFileSync(path.join(dir, 'ocean-calm.mjs'), CALM);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
afterEach(() => {
|
|
58
|
+
fs.rmSync(dir, {recursive: true, force: true});
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
/** @param {{stdout: string, stderr: string}} result */
|
|
62
|
+
function nonAscii(result) {
|
|
63
|
+
return [
|
|
64
|
+
...new Set(`${result.stdout}${result.stderr}`.match(/[\u0080-\uffff]/g)),
|
|
65
|
+
];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** @param {string[]} args */
|
|
69
|
+
function run(args) {
|
|
70
|
+
return runCli(['theme', ...args], dir);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
describe('theme command human output is plain ASCII', () => {
|
|
74
|
+
it('a standalone build: ok, warning, error, notice, and font help lines', async () => {
|
|
75
|
+
const result = await run(['build', 'ocean.mjs']);
|
|
76
|
+
|
|
77
|
+
expect(result.code).toBe(0);
|
|
78
|
+
expect(result.stdout).toContain('[ok] ocean.css');
|
|
79
|
+
expect(result.stderr).toContain('[warn] Deprecated component target');
|
|
80
|
+
expect(result.stderr).toContain('[error] Component "button"');
|
|
81
|
+
expect(result.stdout).toContain('note: Font "Inter"');
|
|
82
|
+
expect(result.stdout).toContain('[note] Theme "ocean" names fonts');
|
|
83
|
+
expect(nonAscii(result)).toEqual([]);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('--check, up to date and stale', async () => {
|
|
87
|
+
await run(['build', 'ocean.mjs']);
|
|
88
|
+
const upToDate = await run(['build', 'ocean.mjs', '--check']);
|
|
89
|
+
expect(upToDate.code).toBe(0);
|
|
90
|
+
expect(upToDate.stdout).toContain('[ok] Theme outputs are up to date');
|
|
91
|
+
expect(nonAscii(upToDate)).toEqual([]);
|
|
92
|
+
|
|
93
|
+
fs.appendFileSync(path.join(dir, 'ocean.css'), '/* drift */\n');
|
|
94
|
+
const stale = await run(['build', 'ocean.mjs', '--check']);
|
|
95
|
+
expect(stale.code).toBe(1);
|
|
96
|
+
expect(stale.stderr).toContain('[fail] 1 theme output(s) are out of date');
|
|
97
|
+
expect(nonAscii(stale)).toEqual([]);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('a batch build and check', async () => {
|
|
101
|
+
const built = await run(['build', 'ocean.mjs', 'ocean-calm.mjs']);
|
|
102
|
+
expect(built.code).toBe(0);
|
|
103
|
+
expect(built.stdout).toContain('[ok] Built 2 themes.');
|
|
104
|
+
expect(nonAscii(built)).toEqual([]);
|
|
105
|
+
|
|
106
|
+
const checked = await run([
|
|
107
|
+
'build',
|
|
108
|
+
'ocean.mjs',
|
|
109
|
+
'ocean-calm.mjs',
|
|
110
|
+
'--check',
|
|
111
|
+
]);
|
|
112
|
+
expect(checked.code).toBe(0);
|
|
113
|
+
expect(checked.stdout).toContain('[ok] Checked 2 themes.');
|
|
114
|
+
expect(nonAscii(checked)).toEqual([]);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it('a family build and a stale family check', async () => {
|
|
118
|
+
const familyArgs = [
|
|
119
|
+
'build',
|
|
120
|
+
'--family',
|
|
121
|
+
'ocean.mjs',
|
|
122
|
+
'ocean-calm.mjs',
|
|
123
|
+
'--family-key',
|
|
124
|
+
'ocean-family',
|
|
125
|
+
];
|
|
126
|
+
const built = await run(familyArgs);
|
|
127
|
+
expect(built.code).toBe(0);
|
|
128
|
+
expect(built.stdout).toContain('[ok] ocean-family.css');
|
|
129
|
+
expect(nonAscii(built)).toEqual([]);
|
|
130
|
+
|
|
131
|
+
fs.rmSync(path.join(dir, 'ocean-family.js'));
|
|
132
|
+
const stale = await run([...familyArgs, '--check']);
|
|
133
|
+
expect(stale.code).toBe(1);
|
|
134
|
+
expect(stale.stderr).toContain('[fail] 1 theme family output(s)');
|
|
135
|
+
expect(nonAscii(stale)).toEqual([]);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it('the suggestion for a quoted glob', async () => {
|
|
139
|
+
const result = await run(['build', 'themes/*.mjs']);
|
|
140
|
+
|
|
141
|
+
expect(result.code).toBe(1);
|
|
142
|
+
expect(result.stderr).toContain('globs are expanded by your shell');
|
|
143
|
+
expect(nonAscii(result)).toEqual([]);
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it('a palette candidate preview', async () => {
|
|
147
|
+
fs.writeFileSync(
|
|
148
|
+
path.join(dir, 'palette.config.json'),
|
|
149
|
+
JSON.stringify({
|
|
150
|
+
modeStrategy: 'dark-only',
|
|
151
|
+
stops: [10, 50, 90],
|
|
152
|
+
families: [{id: 'blue', seed: '#0074e2'}],
|
|
153
|
+
}),
|
|
154
|
+
);
|
|
155
|
+
const result = await run(['palette', 'generate', 'palette.config.json']);
|
|
156
|
+
|
|
157
|
+
expect(result.code).toBe(0);
|
|
158
|
+
expect(result.stdout).toContain('1 families, 3 stops, dark');
|
|
159
|
+
expect(nonAscii(result)).toEqual([]);
|
|
160
|
+
});
|
|
161
|
+
});
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file Every `theme build` flag interaction is discoverable.
|
|
5
|
+
*
|
|
6
|
+
* Each combination the command refuses is refused before any work, and the
|
|
7
|
+
* refusal is named in the machine-readable manifest's description of at least
|
|
8
|
+
* one of the flags involved. Flags that fill in a value when omitted state
|
|
9
|
+
* their default there too.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import {describe, it, expect, beforeAll, afterAll} from 'vitest';
|
|
13
|
+
import * as fs from 'node:fs';
|
|
14
|
+
import * as os from 'node:os';
|
|
15
|
+
import * as path from 'node:path';
|
|
16
|
+
import {runCli} from '../../../test-utils/run-cli.mjs';
|
|
17
|
+
import {ERROR_CODES} from '../../../foundation/response/error-codes.mjs';
|
|
18
|
+
|
|
19
|
+
/** @type {string} */
|
|
20
|
+
let dir;
|
|
21
|
+
/** @type {Map<string, string>} flag token -> manifest description */
|
|
22
|
+
let descriptions;
|
|
23
|
+
|
|
24
|
+
beforeAll(async () => {
|
|
25
|
+
dir = fs.mkdtempSync(path.join(os.tmpdir(), 'astryx-theme-flag-docs-'));
|
|
26
|
+
// Refusals happen before a theme loads; the files only need to exist.
|
|
27
|
+
for (const name of ['a.mjs', 'b.mjs']) {
|
|
28
|
+
fs.writeFileSync(path.join(dir, name), 'export default {};\n');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const manifest = JSON.parse(
|
|
32
|
+
(await runCli(['--json', 'manifest'], dir)).stdout,
|
|
33
|
+
).data;
|
|
34
|
+
const theme = manifest.commands.find(command => command.name === 'theme');
|
|
35
|
+
const build = theme.subcommands.find(
|
|
36
|
+
command => command.name === 'theme build',
|
|
37
|
+
);
|
|
38
|
+
descriptions = new Map(
|
|
39
|
+
build.options.map(option => [
|
|
40
|
+
/** @type {string} */ (option.flag.match(/--[a-z-]+/)?.[0]),
|
|
41
|
+
option.description,
|
|
42
|
+
]),
|
|
43
|
+
);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
afterAll(() => {
|
|
47
|
+
fs.rmSync(dir, {recursive: true, force: true});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
/** @param {string} flag */
|
|
51
|
+
function description(flag) {
|
|
52
|
+
const text = descriptions.get(flag);
|
|
53
|
+
expect(text, `manifest has no ${flag} option`).toBeDefined();
|
|
54
|
+
return /** @type {string} */ (text);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Whether `a`'s description names `b`, or `b`'s names `a`. `b` may also be a
|
|
59
|
+
* pattern for a condition that is not a flag.
|
|
60
|
+
* @param {string} a
|
|
61
|
+
* @param {string | RegExp} b
|
|
62
|
+
*/
|
|
63
|
+
function documented(a, b) {
|
|
64
|
+
const partner = typeof b === 'string' ? new RegExp(`${b}\\b`) : b;
|
|
65
|
+
if (partner.test(description(a))) return true;
|
|
66
|
+
return (
|
|
67
|
+
typeof b === 'string' &&
|
|
68
|
+
descriptions.has(b) &&
|
|
69
|
+
new RegExp(`${a}\\b`).test(description(b))
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const REFUSED = [
|
|
74
|
+
{
|
|
75
|
+
pair: ['--family', '--out'],
|
|
76
|
+
args: ['--family', 'a.mjs', 'b.mjs', '--family-key', 'k', '--out', 'x.css'],
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
pair: ['--family', '--watch'],
|
|
80
|
+
args: ['--family', 'a.mjs', 'b.mjs', '--family-key', 'k', '--watch'],
|
|
81
|
+
},
|
|
82
|
+
{pair: ['--family', '--family-key'], args: ['--family', 'a.mjs', 'b.mjs']},
|
|
83
|
+
{pair: ['--family-key', '--family'], args: ['a.mjs', '--family-key', 'k']},
|
|
84
|
+
{pair: ['--check', '--watch'], args: ['a.mjs', '--check', '--watch']},
|
|
85
|
+
{
|
|
86
|
+
pair: ['--out', /several|more than one|single theme|one theme/i],
|
|
87
|
+
args: ['a.mjs', 'b.mjs', '--out', 'x.css'],
|
|
88
|
+
},
|
|
89
|
+
{pair: ['--watch', '--json'], args: ['a.mjs', '--watch']},
|
|
90
|
+
];
|
|
91
|
+
|
|
92
|
+
describe('theme build flag interactions are documented', () => {
|
|
93
|
+
for (const {pair, args} of REFUSED) {
|
|
94
|
+
const [a, b] = pair;
|
|
95
|
+
it(`${a} with ${String(b)} is refused and documented`, async () => {
|
|
96
|
+
const result = await runCli(['--json', 'theme', 'build', ...args], dir);
|
|
97
|
+
|
|
98
|
+
expect(result.code).toBe(1);
|
|
99
|
+
expect(JSON.parse(result.stdout).code).toBe(
|
|
100
|
+
ERROR_CODES.ERR_THEME_INVALID,
|
|
101
|
+
);
|
|
102
|
+
expect(documented(a, b)).toBe(true);
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
it('flags that fill in an omitted value state their default', () => {
|
|
107
|
+
expect(description('--out')).toMatch(/default/i);
|
|
108
|
+
expect(description('--icons-specifier')).toMatch(/default/i);
|
|
109
|
+
});
|
|
110
|
+
});
|
|
@@ -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
|
*/
|
|
@@ -369,7 +328,7 @@ export function registerTheme(program) {
|
|
|
369
328
|
emit(
|
|
370
329
|
section(
|
|
371
330
|
'Palette candidate',
|
|
372
|
-
`${result.data.familyCount} families
|
|
331
|
+
`${result.data.familyCount} families, ${result.data.stopCount} stops, ${result.data.modes.join(', ')}`,
|
|
373
332
|
),
|
|
374
333
|
code(serializePaletteCandidate(result.data.candidate).trimEnd()),
|
|
375
334
|
);
|
|
@@ -426,7 +385,7 @@ export function registerTheme(program) {
|
|
|
426
385
|
{
|
|
427
386
|
name: `astryx theme build ${entry.file.replace(/['"]/g, '')}`,
|
|
428
387
|
reason:
|
|
429
|
-
'globs are expanded by your shell
|
|
388
|
+
'globs are expanded by your shell; pass the pattern unquoted, or list the files',
|
|
430
389
|
},
|
|
431
390
|
]
|
|
432
391
|
: undefined,
|
|
@@ -491,7 +450,7 @@ export function registerTheme(program) {
|
|
|
491
450
|
// Non-watch: delegate to the API compiler, once per theme, in argument
|
|
492
451
|
// order. Enable human output unless in --json mode (log → stdout via
|
|
493
452
|
// humanLog, warn/error → stderr). The "Building theme from" line, the
|
|
494
|
-
//
|
|
453
|
+
// [ok]/[warn] lines, and the install instructions are all emitted from
|
|
495
454
|
// inside themeBuild via the shared logger.
|
|
496
455
|
logger.setSilent(json);
|
|
497
456
|
|
|
@@ -574,8 +533,8 @@ export function registerTheme(program) {
|
|
|
574
533
|
emit(
|
|
575
534
|
text(
|
|
576
535
|
options.check
|
|
577
|
-
? `\n${stale ? '
|
|
578
|
-
: `\n
|
|
536
|
+
? `\n${stale ? '[fail]' : '[ok]'} Checked ${entries.length} themes.`
|
|
537
|
+
: `\n[ok] Built ${entries.length} themes.`,
|
|
579
538
|
),
|
|
580
539
|
);
|
|
581
540
|
}
|
|
@@ -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>\`.`,
|
|
@@ -7,15 +7,21 @@
|
|
|
7
7
|
* - Theme name with `..` segments cannot escape the output directory.
|
|
8
8
|
* - Theme name with `/` is rejected with a clear error (vs. ENOENT).
|
|
9
9
|
* - Multi-file write is atomic: if one file fails, none are left behind.
|
|
10
|
+
* - An `--out` escape, or an output directory that cannot be created, fails
|
|
11
|
+
* with a registered error code.
|
|
10
12
|
*
|
|
11
13
|
* Runs the CLI in-process (shared runCli harness) against a tiny synthetic theme file.
|
|
12
14
|
*/
|
|
13
15
|
|
|
14
|
-
import {describe, it, expect, beforeEach, afterEach} from 'vitest';
|
|
16
|
+
import {describe, it, expect, beforeAll, beforeEach, afterEach} from 'vitest';
|
|
15
17
|
import * as fs from 'node:fs';
|
|
16
18
|
import * as path from 'node:path';
|
|
17
19
|
import * as os from 'node:os';
|
|
20
|
+
import {ensureCoreBuilt} from './ensure-core-built.mjs';
|
|
18
21
|
import {runCli} from '../../../test-utils/run-cli.mjs';
|
|
22
|
+
import {themeBuild} from '../../../api/theme/build/build.mjs';
|
|
23
|
+
import {AstryxError} from '../../../api/error.mjs';
|
|
24
|
+
import {ERROR_CODES} from '../../../foundation/response/error-codes.mjs';
|
|
19
25
|
|
|
20
26
|
function writeTheme(dir, name) {
|
|
21
27
|
fs.mkdirSync(dir, {recursive: true});
|
|
@@ -93,3 +99,82 @@ describe('theme build path safety', () => {
|
|
|
93
99
|
expect(entries).toEqual(['theme.mjs']);
|
|
94
100
|
});
|
|
95
101
|
});
|
|
102
|
+
|
|
103
|
+
describe('theme build output-path failures carry registered codes', () => {
|
|
104
|
+
// These reach the output-path step, which runs after CSS generation.
|
|
105
|
+
beforeAll(() => {
|
|
106
|
+
ensureCoreBuilt();
|
|
107
|
+
}, 200_000);
|
|
108
|
+
|
|
109
|
+
const registered = new Set(Object.values(ERROR_CODES));
|
|
110
|
+
|
|
111
|
+
/** @param {string[]} args @param {string} cwd */
|
|
112
|
+
async function buildJson(args, cwd) {
|
|
113
|
+
const result = await runCli(['--json', 'theme', 'build', ...args], cwd);
|
|
114
|
+
return {result, envelope: JSON.parse(result.stdout)};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
it('reports an --out path outside the project as ERR_PATH_TRAVERSAL', async () => {
|
|
118
|
+
const project = path.join(tmpDir, 'project');
|
|
119
|
+
const themeFile = writeTheme(path.join(project, 'themes'), 'ocean');
|
|
120
|
+
|
|
121
|
+
const {result, envelope} = await buildJson(
|
|
122
|
+
[path.relative(project, themeFile), '--out', '../escaped.css'],
|
|
123
|
+
project,
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
expect(result.code).toBe(1);
|
|
127
|
+
expect(envelope.code).toBe(ERROR_CODES.ERR_PATH_TRAVERSAL);
|
|
128
|
+
expect(registered.has(envelope.code)).toBe(true);
|
|
129
|
+
expect(fs.existsSync(path.join(tmpDir, 'escaped.css'))).toBe(false);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('reports an --out path that escapes through a symlink as ERR_PATH_TRAVERSAL', async () => {
|
|
133
|
+
const project = path.join(tmpDir, 'project');
|
|
134
|
+
const outside = path.join(tmpDir, 'outside');
|
|
135
|
+
fs.mkdirSync(outside, {recursive: true});
|
|
136
|
+
const themeFile = writeTheme(path.join(project, 'themes'), 'ocean');
|
|
137
|
+
fs.symlinkSync(outside, path.join(project, 'link'), 'dir');
|
|
138
|
+
|
|
139
|
+
const {result, envelope} = await buildJson(
|
|
140
|
+
[path.relative(project, themeFile), '--out', 'link/escaped.css'],
|
|
141
|
+
project,
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
expect(result.code).toBe(1);
|
|
145
|
+
expect(envelope.code).toBe(ERROR_CODES.ERR_PATH_TRAVERSAL);
|
|
146
|
+
expect(fs.readdirSync(outside)).toEqual([]);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it('reports an output directory that cannot be created as ERR_WRITE_FAILED', async () => {
|
|
150
|
+
const project = path.join(tmpDir, 'project');
|
|
151
|
+
const themeFile = writeTheme(path.join(project, 'themes'), 'ocean');
|
|
152
|
+
// A regular file where the output directory would have to be created.
|
|
153
|
+
fs.writeFileSync(path.join(project, 'blocker'), '');
|
|
154
|
+
|
|
155
|
+
const {result, envelope} = await buildJson(
|
|
156
|
+
[path.relative(project, themeFile), '--out', 'blocker/ocean.css'],
|
|
157
|
+
project,
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
expect(result.code).toBe(1);
|
|
161
|
+
expect(envelope.code).toBe(ERROR_CODES.ERR_WRITE_FAILED);
|
|
162
|
+
expect(registered.has(envelope.code)).toBe(true);
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it('themeBuild() rejects an escaping out path with an AstryxError', async () => {
|
|
166
|
+
const project = path.join(tmpDir, 'project');
|
|
167
|
+
const themeFile = writeTheme(path.join(project, 'themes'), 'ocean');
|
|
168
|
+
|
|
169
|
+
const build = themeBuild(
|
|
170
|
+
path.relative(project, themeFile),
|
|
171
|
+
{out: '../escaped.css'},
|
|
172
|
+
{cwd: project},
|
|
173
|
+
);
|
|
174
|
+
|
|
175
|
+
await expect(build).rejects.toBeInstanceOf(AstryxError);
|
|
176
|
+
await expect(build).rejects.toMatchObject({
|
|
177
|
+
code: ERROR_CODES.ERR_PATH_TRAVERSAL,
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
});
|
|
@@ -324,6 +324,82 @@ describe('theme build custom-variant augmentations', () => {
|
|
|
324
324
|
);
|
|
325
325
|
});
|
|
326
326
|
|
|
327
|
+
it('rejects a custom Heading type whose only declaration is blank', async () => {
|
|
328
|
+
const themeFile = writeTheme(
|
|
329
|
+
tmpDir,
|
|
330
|
+
`export default {
|
|
331
|
+
name: 'variants-theme',
|
|
332
|
+
tokens: { '--color-bg': '#fff' },
|
|
333
|
+
components: { heading: { 'type:hero': { fontSize: '' } } },
|
|
334
|
+
};\n`,
|
|
335
|
+
);
|
|
336
|
+
|
|
337
|
+
const result = await runCli(
|
|
338
|
+
['theme', 'build', path.relative(tmpDir, themeFile)],
|
|
339
|
+
tmpDir,
|
|
340
|
+
);
|
|
341
|
+
|
|
342
|
+
expect(result.code).toBe(1);
|
|
343
|
+
expect(result.stderr).toContain(
|
|
344
|
+
'Custom Heading type "hero" needs a non-empty standalone',
|
|
345
|
+
);
|
|
346
|
+
expect(fs.existsSync(path.join(tmpDir, 'variants-theme.css'))).toBe(false);
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
it('rejects a custom Heading type whose every declaration the compiler drops', async () => {
|
|
350
|
+
const themeFile = writeTheme(
|
|
351
|
+
tmpDir,
|
|
352
|
+
`export default {
|
|
353
|
+
name: 'variants-theme',
|
|
354
|
+
tokens: { '--color-bg': '#fff' },
|
|
355
|
+
components: {
|
|
356
|
+
heading: { 'type:hero': { color: 'red; } body { color: blue' } },
|
|
357
|
+
},
|
|
358
|
+
};\n`,
|
|
359
|
+
);
|
|
360
|
+
|
|
361
|
+
const result = await runCli(
|
|
362
|
+
['--json', 'theme', 'build', path.relative(tmpDir, themeFile)],
|
|
363
|
+
tmpDir,
|
|
364
|
+
);
|
|
365
|
+
|
|
366
|
+
expect(result.code).toBe(1);
|
|
367
|
+
const envelope = JSON.parse(result.stdout);
|
|
368
|
+
expect(envelope.code).toBe('ERR_THEME_INVALID');
|
|
369
|
+
expect(envelope.error).toContain('Custom Heading type "hero"');
|
|
370
|
+
expect(fs.existsSync(path.join(tmpDir, 'variants-theme.css'))).toBe(false);
|
|
371
|
+
expect(
|
|
372
|
+
fs.existsSync(path.join(tmpDir, 'variants-theme.variants.d.ts')),
|
|
373
|
+
).toBe(false);
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
it('builds a custom Heading type that keeps one valid declaration', async () => {
|
|
377
|
+
const themeFile = writeTheme(
|
|
378
|
+
tmpDir,
|
|
379
|
+
`export default {
|
|
380
|
+
name: 'variants-theme',
|
|
381
|
+
tokens: { '--color-bg': '#fff' },
|
|
382
|
+
components: {
|
|
383
|
+
heading: {
|
|
384
|
+
'type:hero': { fontSize: '80px', color: 'red; } body { color: blue' },
|
|
385
|
+
},
|
|
386
|
+
},
|
|
387
|
+
};\n`,
|
|
388
|
+
);
|
|
389
|
+
|
|
390
|
+
const result = await runCli(
|
|
391
|
+
['--json', 'theme', 'build', path.relative(tmpDir, themeFile)],
|
|
392
|
+
tmpDir,
|
|
393
|
+
);
|
|
394
|
+
|
|
395
|
+
expect(result.code).toBe(0);
|
|
396
|
+
const envelope = JSON.parse(result.stdout);
|
|
397
|
+
expect(envelope.data.outputs.variantsDts).toBe(
|
|
398
|
+
'variants-theme.variants.d.ts',
|
|
399
|
+
);
|
|
400
|
+
expect(envelope.data.warnings.join('\n')).toContain('Declaration dropped');
|
|
401
|
+
});
|
|
402
|
+
|
|
327
403
|
it('makes generated custom component prop values type-check through public subpaths', async () => {
|
|
328
404
|
const themeFile = writeTheme(
|
|
329
405
|
tmpDir,
|
|
@@ -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,16 +36,23 @@ 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)'},
|
|
47
|
-
{
|
|
52
|
+
{
|
|
53
|
+
code: 1,
|
|
54
|
+
when: 'invalid --type, a non-positive --limit, or a query when @astryxdesign/core cannot be found (the playbook needs no core)',
|
|
55
|
+
},
|
|
48
56
|
],
|
|
49
57
|
related: ['search', 'template', 'component', 'hook', 'init'],
|
|
50
58
|
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file `astryx build` documents that a query needs @astryxdesign/core while
|
|
5
|
+
* the playbook does not, and exits as documented without it.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {describe, it, expect, beforeEach, afterEach} from 'vitest';
|
|
9
|
+
import * as fs from 'node:fs';
|
|
10
|
+
import * as os from 'node:os';
|
|
11
|
+
import * as path from 'node:path';
|
|
12
|
+
import {runCli} from '../../../test-utils/run-cli.mjs';
|
|
13
|
+
import {doc as buildDoc} from './build.doc.mjs';
|
|
14
|
+
|
|
15
|
+
const SLOW = 30_000;
|
|
16
|
+
|
|
17
|
+
/** @type {string} */
|
|
18
|
+
let tmpDir;
|
|
19
|
+
|
|
20
|
+
beforeEach(() => {
|
|
21
|
+
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'astryx-build-no-core-'));
|
|
22
|
+
fs.writeFileSync(path.join(tmpDir, 'package.json'), JSON.stringify({name: 'consumer'}));
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
afterEach(() => {
|
|
26
|
+
fs.rmSync(tmpDir, {recursive: true, force: true});
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
/** @param {number} code */
|
|
30
|
+
const exitWhen = code => buildDoc.exitCodes?.find(e => e.code === code)?.when ?? '';
|
|
31
|
+
|
|
32
|
+
describe('astryx build without @astryxdesign/core', () => {
|
|
33
|
+
it('the CommandDoc lists a query without core under exit 1, and both modes exit 1', async () => {
|
|
34
|
+
expect(exitWhen(1)).toMatch(/a query when @astryxdesign\/core cannot be found/);
|
|
35
|
+
|
|
36
|
+
const text = await runCli(['build', 'dashboard'], tmpDir);
|
|
37
|
+
const json = await runCli(['--json', 'build', 'dashboard'], tmpDir);
|
|
38
|
+
expect(text.status).toBe(1);
|
|
39
|
+
expect(json.status).toBe(1);
|
|
40
|
+
expect(JSON.parse(json.stdout).error).toMatch(/@astryxdesign\/core/);
|
|
41
|
+
}, SLOW);
|
|
42
|
+
|
|
43
|
+
it('the CommandDoc says the playbook needs no core, and it exits 0', async () => {
|
|
44
|
+
expect(exitWhen(1)).toMatch(/the playbook needs no core/);
|
|
45
|
+
|
|
46
|
+
const {status, stdout} = await runCli(['--json', 'build'], tmpDir);
|
|
47
|
+
expect(status).toBe(0);
|
|
48
|
+
expect(JSON.parse(stdout).type).toBe('build.help');
|
|
49
|
+
}, SLOW);
|
|
50
|
+
});
|