@astryxdesign/cli 0.6.3 → 0.6.4-canary.06c8fa3
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/CHANGELOG.md +194 -0
- package/README.md +121 -85
- 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 +31 -12
- package/api/component/_adapter.mjs +79 -15
- package/api/component/component.d.mts +6 -3
- package/api/component/component.doc.mjs +36 -13
- package/api/component/component.mjs +339 -22
- package/api/component/component.test.mjs +38 -0
- package/api/component/component.type.d.mts +47 -11
- package/api/component/component.type.mjs +76 -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 +272 -41
- package/api/docs/_adapter.mjs +985 -108
- package/api/docs/compiled-topics.test.mjs +78 -0
- package/api/docs/detail/detail.mjs +22 -63
- package/api/docs/detail/section/section.d.mts +1 -1
- package/api/docs/detail/section/section.mjs +54 -19
- package/api/docs/detail/section/section.test.mjs +50 -0
- package/api/docs/docs.d.mts +10 -3
- package/api/docs/docs.doc.mjs +55 -16
- package/api/docs/docs.mjs +53 -10
- package/api/docs/docs.test.mjs +166 -4
- package/api/docs/docs.type.d.mts +221 -5
- package/api/docs/docs.type.mjs +153 -11
- package/api/docs/index/index.d.mts +18 -0
- package/api/docs/index/index.mjs +40 -0
- package/api/docs/index/index.test.mjs +62 -0
- package/api/docs/integration-tree.test.mjs +555 -0
- package/api/docs/integrationDocs.test.mjs +114 -8
- package/api/docs/list/list.mjs +28 -12
- package/api/docs/node/node.d.mts +43 -0
- package/api/docs/node/node.mjs +192 -0
- package/api/docs/reference-blocks.test.mjs +406 -0
- package/api/doctor/doctor.d.mts +104 -1
- package/api/doctor/doctor.doc.mjs +1 -0
- package/api/doctor/doctor.mjs +635 -7
- package/api/doctor/doctor.test.mjs +732 -11
- package/api/gap-report/gap-report.doc.mjs +8 -4
- package/api/hook/_adapter.mjs +19 -5
- package/api/hook/hook.doc.mjs +1 -0
- package/api/hook/hook.type.d.mts +3 -3
- package/api/hook/hook.type.mjs +11 -11
- package/api/hook/list/list.d.mts +2 -2
- package/api/hook/list/list.mjs +69 -17
- package/api/index.d.mts +2 -3
- package/api/index.mjs +5 -4
- 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 +3 -1
- package/api/integration/integration-authoring.type.mjs +2 -0
- package/api/integration/integration-block-exports.test.mjs +10 -6
- package/api/integration/integrationAdd.doc.mjs +14 -4
- package/api/integration/integrationAddAgentDoc.doc.mjs +1 -0
- package/api/integration/integrationAddCodemod.doc.mjs +1 -0
- package/api/integration/integrationAddComponent.doc.mjs +2 -1
- package/api/integration/integrationAddDoc.doc.mjs +8 -1
- package/api/integration/integrationAddTemplate.doc.mjs +1 -0
- package/api/integration/integrationAddTheme.doc.mjs +6 -5
- package/api/integration/integrationComponentConflicts.doc.mjs +1 -0
- package/api/integration/integrationDocConflicts.doc.mjs +2 -1
- package/api/integration/integrationPackCheck.doc.mjs +2 -1
- package/api/integration/integrationTemplateConflicts.doc.d.mts +3 -0
- package/api/integration/integrationTemplateConflicts.doc.mjs +4 -0
- package/api/integration/pack-check.lifecycle-output.test.mjs +105 -0
- package/api/integration/pack-check.mjs +111 -10
- 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 -1
- package/api/json/isError.doc.mjs +1 -0
- package/api/json/parseResponse.doc.mjs +3 -2
- package/api/search/search-return-type.test.mjs +54 -0
- package/api/search/search.d.mts +62 -11
- package/api/search/search.doc.mjs +8 -2
- package/api/search/search.mjs +471 -83
- package/api/search/search.test.mjs +142 -1
- package/api/search/search.type.d.mts +15 -3
- package/api/search/search.type.mjs +5 -2
- package/api/swizzle/copy/copy.mjs +28 -11
- package/api/swizzle/swizzle.doc.mjs +2 -1
- package/api/swizzle/swizzle.type.d.mts +2 -2
- package/api/swizzle/swizzle.type.mjs +2 -2
- package/api/template/copy/copy.mjs +17 -23
- package/api/template/copy/copy.test.mjs +17 -0
- package/api/template/list/list.mjs +1 -0
- package/api/template/table-floating-bulk-actions.test.mjs +66 -0
- package/api/template/template-integration.test.mjs +1008 -3
- package/api/template/template-suffix.test.mjs +41 -21
- package/api/template/template.d.mts +1 -1
- package/api/template/template.doc.mjs +30 -8
- package/api/template/template.mjs +46 -9
- package/api/template/template.type.d.mts +12 -14
- package/api/template/template.type.mjs +15 -14
- package/api/theme/_adapter.d.mts +2 -3
- package/api/theme/_adapter.mjs +4 -5
- package/api/theme/add/add.binary.test.mjs +84 -0
- package/api/theme/add/add.mjs +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 +139 -22
- package/api/upgrade/list/list.mjs +2 -1
- package/api/upgrade/list/list.test.mjs +73 -0
- package/api/upgrade/project-context.test.mjs +272 -0
- package/api/upgrade/provider-agreement.test.mjs +152 -0
- package/api/upgrade/run/files-changed.test.mjs +111 -0
- package/api/upgrade/run/run.mjs +359 -60
- package/api/upgrade/status/status.mjs +2 -2
- package/api/upgrade/upgrade.doc.mjs +12 -5
- package/api/upgrade/upgrade.type.d.mts +43 -5
- package/api/upgrade/upgrade.type.mjs +29 -13
- package/assets/codemods/__tests__/registry.test.mjs +1 -0
- package/assets/codemods/__tests__/runner.test.mjs +332 -8
- package/assets/codemods/file-count.test.mjs +163 -0
- package/assets/codemods/integration-discovery.mjs +48 -4
- package/assets/codemods/integration-discovery.test.mjs +73 -0
- package/assets/codemods/integration-runner.mjs +59 -7
- package/assets/codemods/integration-runner.protection.test.mjs +153 -0
- package/assets/codemods/registry.mjs +1 -0
- package/assets/codemods/run-codemod.mjs +177 -34
- package/assets/codemods/runner.mjs +353 -104
- 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/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/codemods/transforms/v0.6.4/__tests__/migrate-native-picker-to-presentation.test.mjs +63 -0
- package/assets/codemods/transforms/v0.6.4/__tests__/migrate-theme-catalog-to-descriptors.test.mjs +220 -0
- package/assets/codemods/transforms/v0.6.4/index.mjs +31 -0
- package/assets/codemods/transforms/v0.6.4/migrate-native-picker-to-presentation.mjs +148 -0
- package/assets/codemods/transforms/v0.6.4/migrate-theme-catalog-to-descriptors.mjs +141 -0
- package/assets/docs/README.md +9 -0
- package/assets/docs/authoring.doc.mjs +14 -0
- package/assets/docs/getting-started.doc.mjs +2 -2
- package/assets/docs/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/tree/component-lookups.doc.mjs +149 -0
- package/assets/docs/{cli-integrations.doc.mjs → tree/integrations.doc.mjs} +144 -26
- 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/blocks/components/Timer/TimerFormats.doc.mjs +14 -0
- package/assets/templates/blocks/components/Timer/TimerFormats.tsx +34 -0
- package/assets/templates/blocks/components/Timer/TimerInline.doc.mjs +14 -0
- package/assets/templates/blocks/components/Timer/TimerInline.tsx +14 -0
- package/assets/templates/blocks/components/Timer/TimerShowcase.doc.mjs +13 -0
- package/assets/templates/blocks/components/Timer/TimerShowcase.tsx +47 -0
- package/assets/templates/blocks/components/Timer/TimerTypography.doc.mjs +14 -0
- package/assets/templates/blocks/components/Timer/TimerTypography.tsx +31 -0
- package/assets/templates/blocks/components/Toolbar/ToolbarTableFilter.doc.mjs +19 -3
- package/assets/templates/blocks/components/Toolbar/ToolbarTableFilter.tsx +383 -65
- 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 +11 -3
- 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 +31 -8
- package/authoring/debug/debug.doc.d.mts +11 -0
- package/authoring/debug/debug.doc.mjs +182 -0
- package/authoring/debug/parse.d.mts +8 -8
- package/authoring/debug/parse.mjs +3 -3
- package/authoring/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 +790 -23
- package/authoring/doctypes/_schema.mjs +543 -39
- package/authoring/doctypes/base/graph-fields.doc.d.mts +9 -0
- package/authoring/doctypes/base/graph-fields.doc.mjs +64 -0
- package/authoring/doctypes/base/type.ts +41 -0
- package/authoring/doctypes/command/command.doc.mjs +5 -4
- package/authoring/doctypes/command/parse.d.mts +2 -2
- package/authoring/doctypes/command/parse.mjs +1 -1
- package/authoring/doctypes/command/type.ts +6 -5
- package/authoring/doctypes/component/component.doc.mjs +6 -3
- package/authoring/doctypes/component/parse.d.mts +2 -2
- package/authoring/doctypes/component/parse.mjs +1 -1
- package/authoring/doctypes/component/type.ts +6 -5
- package/authoring/doctypes/doctypes-new.test.mjs +48 -6
- package/authoring/doctypes/enum/enum.doc.mjs +1 -1
- package/authoring/doctypes/enum/parse.d.mts +2 -2
- package/authoring/doctypes/enum/parse.mjs +1 -1
- package/authoring/doctypes/enum/type.ts +4 -2
- package/authoring/doctypes/function/function.doc.mjs +7 -2
- package/authoring/doctypes/function/parse.d.mts +2 -2
- package/authoring/doctypes/function/parse.mjs +1 -1
- package/authoring/doctypes/function/type.ts +9 -4
- package/authoring/doctypes/hook/hook.doc.mjs +4 -0
- package/authoring/doctypes/hook/parse.d.mts +2 -2
- package/authoring/doctypes/hook/parse.mjs +1 -1
- package/authoring/doctypes/hook/type.ts +5 -4
- package/authoring/doctypes/legacy.d.mts +8 -6
- package/authoring/doctypes/legacy.mjs +5 -4
- package/authoring/doctypes/load-contract.test.mjs +233 -0
- package/authoring/doctypes/namespace/namespace.doc.d.mts +9 -0
- package/authoring/doctypes/namespace/namespace.doc.mjs +128 -0
- package/authoring/doctypes/namespace/parse.d.mts +12 -0
- package/authoring/doctypes/namespace/parse.mjs +25 -0
- package/authoring/doctypes/namespace/parse.test.mjs +163 -0
- package/authoring/doctypes/namespace/type.ts +74 -0
- package/authoring/doctypes/parse.d.mts +22 -18
- package/authoring/doctypes/parse.mjs +22 -11
- package/authoring/doctypes/parse.test.mjs +77 -3
- package/authoring/doctypes/reference/parse.d.mts +2 -2
- package/authoring/doctypes/reference/parse.mjs +8 -5
- package/authoring/doctypes/reference/reference.doc.mjs +48 -6
- package/authoring/doctypes/reference/type.ts +70 -7
- package/authoring/doctypes/schema/parse.d.mts +2 -2
- package/authoring/doctypes/schema/parse.mjs +1 -1
- package/authoring/doctypes/schema/schema.doc.mjs +1 -1
- package/authoring/doctypes/schema/type.ts +4 -4
- package/authoring/doctypes/template/parse.d.mts +94 -1
- package/authoring/doctypes/template/parse.mjs +40 -2
- package/authoring/doctypes/template/parse.test.mjs +26 -2
- package/authoring/doctypes/template/template.doc.mjs +13 -3
- package/authoring/doctypes/template/type.ts +13 -2
- package/authoring/doctypes/theme/parse.d.mts +35 -0
- package/authoring/doctypes/theme/parse.mjs +76 -0
- package/authoring/doctypes/theme/theme.doc.d.mts +9 -0
- package/authoring/doctypes/theme/theme.doc.mjs +79 -0
- package/authoring/doctypes/theme/type.ts +42 -0
- package/authoring/doctypes/types.ts +12 -10
- package/authoring/gap-report/gap-report.doc.d.mts +12 -0
- package/authoring/gap-report/gap-report.doc.mjs +183 -0
- package/authoring/gap-report/parse.d.mts +10 -10
- package/authoring/gap-report/parse.mjs +6 -6
- package/authoring/gap-report/type.ts +1 -1
- package/authoring/identity/identity.doc.d.mts +9 -0
- package/authoring/identity/identity.doc.mjs +61 -0
- package/authoring/identity/type.ts +132 -0
- package/authoring/index.d.mts +3 -0
- package/authoring/index.d.ts +62 -17
- package/authoring/index.mjs +4 -1
- package/authoring/integration/integration.doc.mjs +15 -8
- package/authoring/integration/parse.d.mts +2 -2
- package/authoring/integration/parse.mjs +1 -1
- package/authoring/integration/parse.test.mjs +10 -1
- package/authoring/integration/schema.d.mts +6 -4
- package/authoring/integration/schema.mjs +9 -3
- package/authoring/integration/type.ts +19 -8
- package/authoring/shadcn/receipt.d.mts +6 -6
- package/clients/cli/__tests__/cliManifest.test.ts +27 -29
- package/clients/cli/command-load-failure.test.mjs +83 -0
- package/clients/cli/command-result-coverage.test.mjs +7 -7
- 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 +153 -61
- package/clients/cli/commands/component-batch.test.mjs +341 -0
- package/clients/cli/commands/component-ownership.test.mjs +92 -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 +24 -7
- package/clients/cli/commands/component.test.mjs +19 -0
- package/clients/cli/commands/debug-result-summary.test.mjs +2 -2
- 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 +28 -6
- package/clients/cli/commands/docs.mjs +240 -26
- package/clients/cli/commands/docs.test.mjs +222 -1
- package/clients/cli/commands/doctor-integration-components.doc.mjs +1 -1
- package/clients/cli/commands/doctor-integration-docs.doc.mjs +3 -3
- package/clients/cli/commands/doctor-integration-templates.doc.mjs +15 -8
- package/clients/cli/commands/doctor-integration-validate.doc.mjs +1 -1
- package/clients/cli/commands/doctor-integration.doc.mjs +1 -1
- package/clients/cli/commands/doctor-integration.package-json.test.mjs +53 -0
- package/clients/cli/commands/doctor-integration.test.mjs +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/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 +702 -0
- package/clients/cli/commands/theme-add.doc.mjs +4 -3
- package/clients/cli/commands/theme-build.doc.mjs +8 -7
- package/clients/cli/commands/theme-list.doc.mjs +2 -2
- package/clients/cli/commands/theme-palette-generate.doc.mjs +9 -5
- package/clients/cli/commands/theme-palette-generate.test.mjs +19 -0
- package/clients/cli/commands/theme-palette.doc.mjs +1 -1
- package/clients/cli/commands/theme-targets.behavior.test.mjs +4 -3
- package/clients/cli/commands/theme-targets.doc.mjs +1 -1
- package/clients/cli/commands/theme-template.behavior.test.mjs +12 -0
- package/clients/cli/commands/theme-template.doc.mjs +2 -2
- package/clients/cli/commands/theme.doc.mjs +1 -1
- package/clients/cli/commands/upgrade.ascii-output.test.mjs +87 -0
- package/clients/cli/commands/upgrade.doc.mjs +22 -10
- package/clients/cli/commands/upgrade.file-protection.test.mjs +228 -0
- package/clients/cli/commands/upgrade.flag-help.test.mjs +188 -0
- package/clients/cli/commands/upgrade.hook-output.test.mjs +88 -0
- package/clients/cli/commands/upgrade.mjs +29 -7
- package/clients/cli/formatters/index.mjs +164 -1
- package/clients/cli/formatters/index.test.mjs +97 -0
- package/clients/cli/index.mjs +21 -34
- 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 +90 -0
- package/clients/cli/lib/hook-format.mjs +19 -10
- package/clients/cli/lib/json-shim.mjs +62 -16
- package/clients/cli/lib/json-shim.test.mjs +69 -0
- package/clients/cli/lib/manifest.d.ts +2 -0
- package/clients/cli/lib/manifest.mjs +39 -10
- package/clients/cli/lib/manifest.test.mjs +22 -2
- package/clients/cli/lib/parse-error-format.test.mjs +81 -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 +263 -91
- package/foundation/config/project.test.mjs +270 -21
- package/foundation/discovery/authoring-self-docs.d.mts +87 -0
- package/foundation/discovery/authoring-self-docs.mjs +237 -0
- package/foundation/discovery/authoring-self-docs.test.mjs +170 -0
- package/foundation/discovery/authoring-surface.d.mts +74 -0
- package/foundation/discovery/authoring-surface.mjs +525 -0
- package/foundation/discovery/authoring-surface.test.mjs +392 -0
- package/foundation/discovery/cli-self-docs.d.mts +119 -0
- package/foundation/discovery/cli-self-docs.mjs +490 -0
- package/foundation/discovery/cli-self-docs.test.mjs +375 -0
- package/foundation/discovery/component-discovery.d.mts +39 -1
- package/foundation/discovery/component-discovery.mjs +50 -1
- package/foundation/discovery/component-loader.d.mts +35 -38
- package/foundation/discovery/component-loader.mjs +53 -222
- package/foundation/discovery/docs-discovery.d.mts +119 -11
- package/foundation/discovery/docs-discovery.mjs +423 -108
- package/foundation/discovery/docs-discovery.test.mjs +365 -20
- package/foundation/discovery/docs-output-budget.d.mts +28 -0
- package/foundation/discovery/docs-output-budget.mjs +50 -0
- package/foundation/discovery/docs-section-key.d.mts +116 -0
- package/foundation/discovery/docs-section-key.mjs +322 -0
- package/foundation/discovery/docs-section-key.test.mjs +246 -0
- package/foundation/discovery/template-adapter.d.mts +113 -11
- package/foundation/discovery/template-adapter.fixture-refs.test.mjs +248 -0
- package/foundation/discovery/template-adapter.integration-isolation.test.mjs +94 -0
- package/foundation/discovery/template-adapter.mjs +775 -84
- 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 +1630 -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 +606 -0
- package/foundation/fs/file-protection.d.mts +33 -0
- package/foundation/fs/file-protection.mjs +825 -0
- package/foundation/fs/file-protection.test.mjs +250 -0
- package/foundation/fs/module-loader.d.mts +1 -0
- package/foundation/fs/module-loader.mjs +50 -1
- package/foundation/fs/module-loader.stdout.test.mjs +332 -0
- package/foundation/fs/path-safety.d.mts +3 -2
- package/foundation/fs/path-safety.mjs +49 -19
- package/foundation/fs/path-safety.test.mjs +50 -0
- package/foundation/fs/publish-file-hardlink-unavailable.test.mjs +129 -94
- package/foundation/identity/provider-identity.d.mts +90 -0
- package/foundation/identity/provider-identity.mjs +320 -0
- package/foundation/identity/provider-identity.test.mjs +254 -0
- package/foundation/identity/providers.d.mts +7 -0
- package/foundation/identity/providers.mjs +16 -0
- package/foundation/integrations/autolink.d.mts +58 -1
- package/foundation/integrations/autolink.mjs +143 -45
- package/foundation/integrations/autolink.test.mjs +1 -1
- package/foundation/integrations/cli-requirement.d.mts +45 -0
- package/foundation/integrations/cli-requirement.mjs +154 -0
- package/foundation/integrations/cli-requirement.test.mjs +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 +52 -21
- package/foundation/integrations/integration-warnings.test.mjs +74 -1
- package/foundation/integrations/integrations.d.mts +63 -3
- package/foundation/integrations/integrations.mjs +122 -9
- package/foundation/integrations/integrations.test.mjs +415 -1
- package/foundation/integrations/provider-conflicts.test.mjs +125 -0
- package/foundation/integrations/provider-ledger.test.mjs +275 -0
- package/foundation/integrations/provider-resolution.d.mts +152 -0
- package/foundation/integrations/provider-resolution.mjs +576 -0
- package/foundation/integrations/provider-resolution.test.mjs +369 -0
- package/foundation/integrations/theme-descriptor.d.mts +8 -0
- package/foundation/integrations/theme-descriptor.mjs +44 -0
- package/foundation/integrations/validate-contributions.d.mts +2 -0
- package/foundation/integrations/validate-contributions.mjs +131 -29
- package/foundation/response/base.d.ts +8 -4
- package/foundation/response/batch.type.d.mts +33 -0
- package/foundation/response/batch.type.mjs +34 -0
- package/foundation/response/error-codes.d.mts +3 -1
- package/foundation/response/error-codes.d.ts +2 -0
- package/foundation/response/error-codes.doc.mjs +13 -4
- package/foundation/response/error-codes.mjs +8 -2
- package/foundation/response/error-codes.test.mjs +137 -10
- package/foundation/response/json-contract.test.mjs +57 -17
- package/foundation/response/json.d.mts +4 -2
- package/foundation/response/json.mjs +8 -10
- package/foundation/response/response-types.doc.d.mts +5 -1
- package/foundation/response/response-types.doc.mjs +46 -38
- package/foundation/response/response-types.doc.test.mjs +181 -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/browser.d.mts +3 -3
- package/foundation/xle/browser.mjs +3 -3
- package/foundation/xle/expand.d.mts +2 -0
- package/foundation/xle/expand.mjs +6 -5
- package/foundation/xle/expand.test.mjs +54 -0
- package/foundation/xle/parse.mjs +1 -1
- package/foundation/xle/print.mjs +2 -2
- package/foundation/xle/splice.mjs +1 -1
- package/foundation/xle/xle.test.mjs +13 -0
- package/package.json +10 -11
- package/api/layout/_adapter.d.mts +0 -34
- package/api/layout/_adapter.mjs +0 -133
- package/api/layout/check/check.d.mts +0 -16
- package/api/layout/check/check.mjs +0 -40
- package/api/layout/expand/expand.d.mts +0 -22
- package/api/layout/expand/expand.mjs +0 -153
- package/api/layout/grammar/grammar.d.mts +0 -13
- package/api/layout/grammar/grammar.mjs +0 -86
- package/api/layout/layout.d.mts +0 -6
- package/api/layout/layout.mjs +0 -17
- package/api/layout/layout.test.mjs +0 -297
- package/api/layout/layout.type.d.mts +0 -89
- package/api/layout/layout.type.mjs +0 -103
- package/api/layout/layoutCheck.doc.d.mts +0 -11
- package/api/layout/layoutCheck.doc.mjs +0 -84
- package/api/layout/layoutExpand.doc.d.mts +0 -11
- package/api/layout/layoutExpand.doc.mjs +0 -106
- package/api/layout/layoutGrammar.doc.d.mts +0 -11
- package/api/layout/layoutGrammar.doc.mjs +0 -56
- package/assets/templates/themes/manifest.json +0 -95
- package/clients/cli/commands/layout-check.doc.mjs +0 -54
- package/clients/cli/commands/layout-expand.doc.mjs +0 -66
- package/clients/cli/commands/layout-grammar.doc.mjs +0 -30
- package/clients/cli/commands/layout.doc.mjs +0 -34
- package/clients/cli/commands/layout.error-codes.test.mjs +0 -66
- package/clients/cli/commands/layout.exit-parity.test.mjs +0 -41
- package/clients/cli/commands/layout.mjs +0 -263
- 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
|
@@ -29,11 +29,16 @@
|
|
|
29
29
|
* 4. Routing unknown-subcommand attempts through the same error
|
|
30
30
|
* envelope path (so `astryx bogus-cmd --json` gets exit 1 + envelope
|
|
31
31
|
* instead of exit 0 + help envelope).
|
|
32
|
+
* 5. Emitting an error envelope, not the help envelope, when Commander
|
|
33
|
+
* shows help because the invocation failed (`help <unknown>`, or a
|
|
34
|
+
* command group with no subcommand), which exits 1.
|
|
32
35
|
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
36
|
+
* Commander writes its own "error: ..." line via configureOutput.writeErr.
|
|
37
|
+
* The shim drops that line in both modes. Under --json the error envelope
|
|
38
|
+
* replaces it; in text mode `handleCommanderError` writes the Astryx line
|
|
39
|
+
* instead (`Error: <message>`, the same message the envelope carries), so
|
|
40
|
+
* a parse failure reads like every other CLI error. Other stderr output,
|
|
41
|
+
* such as help printed as the failure report, still passes through.
|
|
37
42
|
*/
|
|
38
43
|
|
|
39
44
|
import {API_VERSION, isJsonMode, toErrorEnvelope} from '../../../foundation/response/json.mjs';
|
|
@@ -117,6 +122,35 @@ export function buildHelpEnvelope(cmd) {
|
|
|
117
122
|
};
|
|
118
123
|
}
|
|
119
124
|
|
|
125
|
+
/**
|
|
126
|
+
* The error envelope for help Commander shows because the invocation failed
|
|
127
|
+
* (it then exits 1): `help <name>` for an unknown name on the root, or a
|
|
128
|
+
* command group run without a subcommand.
|
|
129
|
+
*
|
|
130
|
+
* @param {import('commander').Command} cmd the command whose help was shown
|
|
131
|
+
* @returns {ReturnType<typeof toErrorEnvelope>}
|
|
132
|
+
*/
|
|
133
|
+
export function buildHelpErrorEnvelope(cmd) {
|
|
134
|
+
const available = cmd.commands
|
|
135
|
+
.filter(s => !(/** @type {any} */ (s))._hidden && s.name() !== 'help')
|
|
136
|
+
.map(s => s.name());
|
|
137
|
+
if (!cmd.parent) {
|
|
138
|
+
// Commander dispatches `help <name>` with ['help', <name>, ...] in args.
|
|
139
|
+
const requested = cmd.args[1];
|
|
140
|
+
return toErrorEnvelope(
|
|
141
|
+
requested ? `unknown command '${requested}'` : 'unknown command',
|
|
142
|
+
available.map(name => ({name, reason: 'available command'})),
|
|
143
|
+
ERROR_CODES.ERR_UNKNOWN_COMMAND,
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
const group = fullNameOf(cmd);
|
|
147
|
+
return toErrorEnvelope(
|
|
148
|
+
`'${group}' needs a subcommand`,
|
|
149
|
+
available.map(name => ({name: `${group} ${name}`, reason: 'available subcommand'})),
|
|
150
|
+
ERROR_CODES.ERR_MISSING_ARGUMENT,
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
120
154
|
/**
|
|
121
155
|
* Emit a JSON error envelope to stdout (the JSON contract uses stdout
|
|
122
156
|
* for both success and error).
|
|
@@ -217,11 +251,20 @@ function applyShimRecursively(cmd) {
|
|
|
217
251
|
});
|
|
218
252
|
cmd.configureOutput({
|
|
219
253
|
writeOut: (str) => process.stdout.write(str),
|
|
254
|
+
// Commander's own "error: ..." line never reaches the user. Under --json a
|
|
255
|
+
// consumer parsing both streams must not see it alongside the envelope;
|
|
256
|
+
// in text mode it is Commander's format, not Astryx's, so an invalid
|
|
257
|
+
// global option (`--lang zh-Hans`) printed `error: option '--lang
|
|
258
|
+
// <locale>' argument 'zh-Hans' is invalid…` where every other CLI error
|
|
259
|
+
// prints `Error: …`. handleCommanderError writes the Astryx line below,
|
|
260
|
+
// for both modes, from the same message.
|
|
261
|
+
//
|
|
262
|
+
// ONLY that line. Commander also writes HELP through this channel when it
|
|
263
|
+
// shows help because the invocation failed (a command group with no
|
|
264
|
+
// subcommand), and that output is still wanted in text mode.
|
|
220
265
|
writeErr: (str) => {
|
|
221
|
-
// Suppress Commander's "error: ..." stderr line when --json is
|
|
222
|
-
// active, so a JSON consumer parsing both streams doesn't see
|
|
223
|
-
// it alongside the envelope. Non-JSON callers are unaffected.
|
|
224
266
|
if (jsonActive()) return;
|
|
267
|
+
if (/^error:\s/i.test(str)) return;
|
|
225
268
|
process.stderr.write(str);
|
|
226
269
|
},
|
|
227
270
|
});
|
|
@@ -310,7 +353,9 @@ function patchOutputHelp(cmd) {
|
|
|
310
353
|
if (jsonActive()) {
|
|
311
354
|
if (!process.__xdsJsonHandled) {
|
|
312
355
|
process.__xdsJsonHandled = true;
|
|
313
|
-
const env =
|
|
356
|
+
const env = contextOptions?.error
|
|
357
|
+
? buildHelpErrorEnvelope(cmd)
|
|
358
|
+
: buildHelpEnvelope(cmd);
|
|
314
359
|
process.stdout.write(`${JSON.stringify(env, null, 2)}\n`);
|
|
315
360
|
}
|
|
316
361
|
return;
|
|
@@ -334,7 +379,9 @@ function patchPrototype(CommandCtor) {
|
|
|
334
379
|
if (jsonActive()) {
|
|
335
380
|
if (!process.__xdsJsonHandled) {
|
|
336
381
|
process.__xdsJsonHandled = true;
|
|
337
|
-
const env =
|
|
382
|
+
const env = contextOptions?.error
|
|
383
|
+
? buildHelpErrorEnvelope(this)
|
|
384
|
+
: buildHelpEnvelope(this);
|
|
338
385
|
process.stdout.write(`${JSON.stringify(env, null, 2)}\n`);
|
|
339
386
|
}
|
|
340
387
|
return;
|
|
@@ -396,16 +443,15 @@ export function handleCommanderError(err) {
|
|
|
396
443
|
code: commanderCodeToErrorCode(code, message),
|
|
397
444
|
});
|
|
398
445
|
|
|
399
|
-
// Real error paths.
|
|
446
|
+
// Real error paths. Strip Commander's "error: " prefix once: in the envelope
|
|
447
|
+
// the key is already `error`, and in text mode the Astryx prefix replaces it.
|
|
448
|
+
const cleaned = message.replace(/^error:\s*/i, '');
|
|
400
449
|
if (jsonActive()) {
|
|
401
|
-
// Strip Commander's "error: " prefix — the envelope key is `error`
|
|
402
|
-
// already, doubled "error" is noise.
|
|
403
|
-
const cleaned = message.replace(/^error:\s*/i, '');
|
|
404
450
|
emitJsonError(cleaned, undefined, commanderCodeToErrorCode(code, cleaned));
|
|
405
451
|
} else {
|
|
406
|
-
//
|
|
407
|
-
//
|
|
408
|
-
|
|
452
|
+
// Commander's own line was suppressed above, so a parse failure reads the
|
|
453
|
+
// same as every other CLI error — the `Error: …` line cliError prints.
|
|
454
|
+
process.stderr.write(`Error: ${cleaned}\n`);
|
|
409
455
|
}
|
|
410
456
|
process.exit(exitCode || 1);
|
|
411
457
|
}
|
|
@@ -20,7 +20,12 @@
|
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
22
|
import {describe, it, expect} from 'vitest';
|
|
23
|
+
import {spawnSync} from 'node:child_process';
|
|
24
|
+
import {fileURLToPath} from 'node:url';
|
|
25
|
+
import {Command} from 'commander';
|
|
23
26
|
import {runCli} from '../../../test-utils/run-cli.mjs';
|
|
27
|
+
import {installJsonShim} from './json-shim.mjs';
|
|
28
|
+
import {setJsonMode} from '../../../foundation/response/json.mjs';
|
|
24
29
|
|
|
25
30
|
function parseJson(stdout) {
|
|
26
31
|
return JSON.parse(stdout);
|
|
@@ -207,3 +212,67 @@ describe('--json shim: stdout discipline under --json', () => {
|
|
|
207
212
|
}
|
|
208
213
|
});
|
|
209
214
|
});
|
|
215
|
+
|
|
216
|
+
describe('--json shim: help shown for a failed invocation is an error envelope', () => {
|
|
217
|
+
it('astryx help bogus --json emits ERR_UNKNOWN_COMMAND, exit 1', async () => {
|
|
218
|
+
const {status, stdout, stderr} = await runCli(['help', 'bogus', '--json']);
|
|
219
|
+
expect(status).toBe(1);
|
|
220
|
+
expect(stderr).toBe('');
|
|
221
|
+
const parsed = parseJson(stdout);
|
|
222
|
+
expect(parsed).not.toHaveProperty('type');
|
|
223
|
+
expect(parsed.apiVersion).toBe(1);
|
|
224
|
+
expect(parsed.code).toBe('ERR_UNKNOWN_COMMAND');
|
|
225
|
+
expect(parsed.error).toMatch(/bogus/);
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
it('the real binary emits the same envelope for help bogus --json', () => {
|
|
229
|
+
// One program per process, so the root's own outputHelp patch is used here.
|
|
230
|
+
const bin = fileURLToPath(new URL('../bin/astryx.mjs', import.meta.url));
|
|
231
|
+
const res = spawnSync(process.execPath, [bin, 'help', 'bogus', '--json'], {
|
|
232
|
+
encoding: 'utf-8',
|
|
233
|
+
timeout: 20_000,
|
|
234
|
+
});
|
|
235
|
+
expect(res.status).toBe(1);
|
|
236
|
+
expect(res.stderr).toBe('');
|
|
237
|
+
const parsed = parseJson(res.stdout);
|
|
238
|
+
expect(parsed).not.toHaveProperty('type');
|
|
239
|
+
expect(parsed.code).toBe('ERR_UNKNOWN_COMMAND');
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
it('a group added after install gets the same error envelope', () => {
|
|
243
|
+
// This is the only coverage of the no-subcommand path: every group the CLI
|
|
244
|
+
// ships has an action of its own (see command-result-coverage.test.mjs), so
|
|
245
|
+
// a group without one has to be built here.
|
|
246
|
+
const program = new Command('astryx');
|
|
247
|
+
installJsonShim(program);
|
|
248
|
+
// Added later, so only the prototype-level patch covers its outputHelp.
|
|
249
|
+
const late = new Command('late');
|
|
250
|
+
late.command('child');
|
|
251
|
+
program.addCommand(late);
|
|
252
|
+
/** @type {string[]} */
|
|
253
|
+
const writes = [];
|
|
254
|
+
const origWrite = process.stdout.write;
|
|
255
|
+
// @ts-expect-error - test-only capture
|
|
256
|
+
process.stdout.write = (chunk) => writes.push(String(chunk)) > 0;
|
|
257
|
+
setJsonMode(true);
|
|
258
|
+
delete process.__xdsJsonHandled;
|
|
259
|
+
try {
|
|
260
|
+
late.outputHelp({error: true});
|
|
261
|
+
} finally {
|
|
262
|
+
process.stdout.write = origWrite;
|
|
263
|
+
setJsonMode(false);
|
|
264
|
+
delete process.__xdsJsonHandled;
|
|
265
|
+
}
|
|
266
|
+
const parsed = parseJson(writes.join(''));
|
|
267
|
+
expect(parsed.code).toBe('ERR_MISSING_ARGUMENT');
|
|
268
|
+
expect(parsed.suggestions).toEqual([{name: 'late child', reason: 'available subcommand'}]);
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
it('astryx help theme --json still emits the help envelope, exit 0', async () => {
|
|
272
|
+
const {status, stdout} = await runCli(['help', 'theme', '--json']);
|
|
273
|
+
expect(status).toBe(0);
|
|
274
|
+
const parsed = parseJson(stdout);
|
|
275
|
+
expect(parsed.type).toBe('help');
|
|
276
|
+
expect(parsed.data.command).toBe('astryx theme');
|
|
277
|
+
});
|
|
278
|
+
});
|
|
@@ -48,6 +48,8 @@ export interface ManifestCommand {
|
|
|
48
48
|
responseTypes?: string[];
|
|
49
49
|
/** Example invocations. */
|
|
50
50
|
examples?: string[];
|
|
51
|
+
/** Documented exit codes: the process exit status and when it occurs. */
|
|
52
|
+
exitCodes?: {code: number; when: string}[];
|
|
51
53
|
/** Nested subcommands (e.g. `theme build` under `theme`). */
|
|
52
54
|
subcommands?: ManifestCommand[];
|
|
53
55
|
}
|
|
@@ -35,6 +35,8 @@
|
|
|
35
35
|
*/
|
|
36
36
|
|
|
37
37
|
import {API_VERSION} from '../../../foundation/response/json.mjs';
|
|
38
|
+
import {commandDocsOf} from './define-command.mjs';
|
|
39
|
+
import {doc as manifestDoc} from '../commands/manifest.doc.mjs';
|
|
38
40
|
|
|
39
41
|
/**
|
|
40
42
|
* Response `type` discriminators each fully-qualified command can emit in
|
|
@@ -49,18 +51,26 @@ export const RESPONSE_TYPES = {
|
|
|
49
51
|
init: ['init.run', 'init.remove'],
|
|
50
52
|
component: [
|
|
51
53
|
'component.list',
|
|
54
|
+
'component.batch',
|
|
52
55
|
'component.detail',
|
|
53
56
|
'component.detail.props',
|
|
54
57
|
'component.detail.source',
|
|
55
58
|
'component.detail.showcase',
|
|
56
59
|
'component.detail.blocks',
|
|
57
60
|
],
|
|
58
|
-
docs: [
|
|
61
|
+
docs: [
|
|
62
|
+
'docs.list',
|
|
63
|
+
'docs.index',
|
|
64
|
+
'docs.detail',
|
|
65
|
+
'docs.detail.section',
|
|
66
|
+
'docs.node',
|
|
67
|
+
],
|
|
59
68
|
blog: ['blog.list', 'blog.detail'],
|
|
60
69
|
discover: [
|
|
61
70
|
'discover.list',
|
|
62
71
|
'discover.detail',
|
|
63
72
|
'discover.detail.doc',
|
|
73
|
+
'discover.item',
|
|
64
74
|
'discover.search',
|
|
65
75
|
],
|
|
66
76
|
search: ['search'],
|
|
@@ -90,9 +100,6 @@ export const RESPONSE_TYPES = {
|
|
|
90
100
|
'doctor integration templates': ['integration.template-conflicts'],
|
|
91
101
|
'doctor integration components': ['integration.component-conflicts'],
|
|
92
102
|
'doctor integration docs': ['integration.doc-conflicts'],
|
|
93
|
-
'layout expand': ['layout.expand'],
|
|
94
|
-
'layout check': ['layout.check'],
|
|
95
|
-
'layout grammar': ['layout.grammar'],
|
|
96
103
|
};
|
|
97
104
|
|
|
98
105
|
/**
|
|
@@ -103,9 +110,16 @@ const EXAMPLES = {
|
|
|
103
110
|
component: [
|
|
104
111
|
'astryx component',
|
|
105
112
|
'astryx component XDSButton',
|
|
113
|
+
'astryx component Button Badge Text',
|
|
106
114
|
'astryx component XDSButton --props --json',
|
|
107
115
|
],
|
|
108
|
-
docs: [
|
|
116
|
+
docs: [
|
|
117
|
+
'astryx docs',
|
|
118
|
+
'astryx docs spacing --json',
|
|
119
|
+
'astryx docs theme',
|
|
120
|
+
'astryx docs theme quick-start',
|
|
121
|
+
'astryx docs cli/integrations --full',
|
|
122
|
+
],
|
|
109
123
|
discover: ['astryx discover --json'],
|
|
110
124
|
search: [
|
|
111
125
|
'astryx search modal --json',
|
|
@@ -166,11 +180,6 @@ const EXAMPLES = {
|
|
|
166
180
|
'astryx doctor integration docs @acme/widgets --json',
|
|
167
181
|
],
|
|
168
182
|
init: ['astryx init', 'astryx init --all --json'],
|
|
169
|
-
'layout expand': [
|
|
170
|
-
`astryx layout expand 'V[g6] > C{card-callout}*4' ./src/Page.tsx`,
|
|
171
|
-
],
|
|
172
|
-
'layout check': [`astryx layout check 'A[cp6] > L > LC > S[p6]' --json`],
|
|
173
|
-
'layout grammar': ['astryx layout grammar'],
|
|
174
183
|
};
|
|
175
184
|
|
|
176
185
|
/**
|
|
@@ -232,6 +241,18 @@ function fullName(cmd, root) {
|
|
|
232
241
|
return parts.join(' ');
|
|
233
242
|
}
|
|
234
243
|
|
|
244
|
+
/**
|
|
245
|
+
* The docs a command was built from. `manifest` is registered by hand in
|
|
246
|
+
* index.mjs, so its CommandDoc is read here.
|
|
247
|
+
* @param {import('commander').Command} cmd
|
|
248
|
+
* @param {string} name
|
|
249
|
+
*/
|
|
250
|
+
function docsOf(cmd, name) {
|
|
251
|
+
return (
|
|
252
|
+
commandDocsOf(cmd) ?? (name === 'manifest' ? {doc: manifestDoc} : undefined)
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
|
|
235
256
|
/**
|
|
236
257
|
* Recursively describe a Commander command and its subcommands.
|
|
237
258
|
*
|
|
@@ -247,6 +268,8 @@ function describeCommand(cmd, root, jsonSupported) {
|
|
|
247
268
|
// `_hidden` is a Commander internal not present on its public types.
|
|
248
269
|
if (!name || /** @type {any} */ (cmd)._hidden || name === 'help') return null;
|
|
249
270
|
|
|
271
|
+
const docs = docsOf(cmd, name);
|
|
272
|
+
|
|
250
273
|
const subcommands = /** @type {object[]} */ (
|
|
251
274
|
(cmd.commands || [])
|
|
252
275
|
.map(sub => describeCommand(sub, root, jsonSupported))
|
|
@@ -279,6 +302,12 @@ function describeCommand(cmd, root, jsonSupported) {
|
|
|
279
302
|
|
|
280
303
|
if (EXAMPLES[name]) entry.examples = [...EXAMPLES[name]];
|
|
281
304
|
|
|
305
|
+
const exitCodes = (docs?.doc.exitCodes ?? []).map(({code, when}) => ({
|
|
306
|
+
code,
|
|
307
|
+
when,
|
|
308
|
+
}));
|
|
309
|
+
if (exitCodes.length > 0) entry.exitCodes = exitCodes;
|
|
310
|
+
|
|
282
311
|
// Sort subcommands by name for a stable, agent-facing contract — the same
|
|
283
312
|
// guarantee the top-level command list makes. Otherwise Commander
|
|
284
313
|
// registration order leaks into the manifest and a pure reorder of
|
|
@@ -156,7 +156,10 @@ describe('manifest: shape', () => {
|
|
|
156
156
|
|
|
157
157
|
it('derives arguments from Commander metadata', () => {
|
|
158
158
|
const component = allEntries.find((c) => c.name === 'component');
|
|
159
|
-
|
|
159
|
+
const names = component.arguments.find((a) => a.name === 'names');
|
|
160
|
+
expect(names.required).toBe(false);
|
|
161
|
+
expect(names.variadic).toBe(true);
|
|
162
|
+
expect(names.description).toContain('Two or more return one ordered batch');
|
|
160
163
|
const themeBuild = allEntries.find((c) => c.name === 'theme build');
|
|
161
164
|
expect(themeBuild.arguments.map((a) => a.name)).toContain('files');
|
|
162
165
|
const files = themeBuild.arguments.find((a) => a.name === 'files');
|
|
@@ -193,6 +196,23 @@ describe('manifest: e2e', () => {
|
|
|
193
196
|
// Enriched: the full structured manifest is embedded.
|
|
194
197
|
expect(parsed.data.manifest).toBeDefined();
|
|
195
198
|
expect(parsed.data.manifest.commands.find((c) => c.name === 'component').responseTypes)
|
|
196
|
-
.
|
|
199
|
+
.toEqual(expect.arrayContaining(['component.list', 'component.batch']));
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
describe('manifest: text projection', () => {
|
|
204
|
+
it('astryx manifest (text) uses the JSON entry keys as its field names', async () => {
|
|
205
|
+
const text = await runCli(['manifest']);
|
|
206
|
+
expect(text.status).toBe(0);
|
|
207
|
+
const json = JSON.parse((await runCli(['manifest', '--json'])).stdout);
|
|
208
|
+
const jsonKeys = new Set(json.data.commands.flatMap((c) => Object.keys(c)));
|
|
209
|
+
const textKeys = new Set(
|
|
210
|
+
text.stdout
|
|
211
|
+
.split('\n')
|
|
212
|
+
.map((line) => /^([A-Za-z]+):\s/.exec(line)?.[1])
|
|
213
|
+
.filter(Boolean),
|
|
214
|
+
);
|
|
215
|
+
expect(textKeys).toContain('name');
|
|
216
|
+
for (const key of textKeys) expect(jsonKeys).toContain(key);
|
|
197
217
|
});
|
|
198
218
|
});
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file A parse failure reads like every other Astryx error in text mode.
|
|
5
|
+
*
|
|
6
|
+
* `astryx theme list --lang zh-Hans` printed Commander's own line —
|
|
7
|
+
* `error: option '--lang <locale>' argument 'zh-Hans' is invalid…` — while
|
|
8
|
+
* every other CLI error prints `Error: …`. `--json` was already correct
|
|
9
|
+
* (ERR_INVALID_LANG), so text and JSON disagreed on everything except the exit
|
|
10
|
+
* code. Commander writes that line before any Astryx code runs, so the shim is
|
|
11
|
+
* the only place that can speak for it.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import {describe, it, expect} from 'vitest';
|
|
15
|
+
import {Command} from 'commander';
|
|
16
|
+
import {runCli} from '../../../test-utils/run-cli.mjs';
|
|
17
|
+
import {installJsonShim} from './json-shim.mjs';
|
|
18
|
+
|
|
19
|
+
describe('a parse error prints the Astryx error format', () => {
|
|
20
|
+
it.each([
|
|
21
|
+
['invalid --lang value', ['theme', 'list', '--lang', 'zh-Hans'], 'ERR_INVALID_LANG'],
|
|
22
|
+
['invalid --detail value', ['theme', 'list', '--detail', 'nope'], 'ERR_INVALID_DETAIL'],
|
|
23
|
+
['unknown option', ['component', '--bogus-flag'], 'ERR_INVALID_OPTION'],
|
|
24
|
+
['missing argument', ['theme', 'build'], 'ERR_MISSING_ARGUMENT'],
|
|
25
|
+
])('%s', async (_label, args, code) => {
|
|
26
|
+
const human = await runCli(args);
|
|
27
|
+
|
|
28
|
+
expect(human.status).toBe(1);
|
|
29
|
+
expect(human.stderr).toContain('Error: ');
|
|
30
|
+
// Commander's own lowercase line must not reach the user.
|
|
31
|
+
expect(human.stderr).not.toMatch(/(^|\n)error: /);
|
|
32
|
+
|
|
33
|
+
// --json is unchanged, and the two modes agree on the exit code.
|
|
34
|
+
const json = await runCli(['--json', ...args]);
|
|
35
|
+
expect(json.status).toBe(human.status);
|
|
36
|
+
expect(JSON.parse(json.stdout).code).toBe(code);
|
|
37
|
+
expect(json.stderr).toBe('');
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('carries Commander\'s explanation, not just a generic line', async () => {
|
|
41
|
+
const {stderr} = await runCli(['theme', 'list', '--lang', 'zh-Hans']);
|
|
42
|
+
expect(stderr).toContain("'zh-Hans' is invalid");
|
|
43
|
+
expect(stderr).toContain('en, zh, dense');
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('leaves --help and --version at exit 0 with nothing on stderr', async () => {
|
|
47
|
+
for (const args of [['--help'], ['theme', '--help']]) {
|
|
48
|
+
const r = await runCli(args);
|
|
49
|
+
expect(r.status).toBe(0);
|
|
50
|
+
expect(r.stderr).toBe('');
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// Commander writes help through the same stderr channel when it shows help
|
|
55
|
+
// BECAUSE the invocation failed, so suppressing that channel wholesale would
|
|
56
|
+
// have taken the help with it. Driven on a throwaway program rather than a
|
|
57
|
+
// real command, so the guard outlives whichever command happens to have a
|
|
58
|
+
// subcommand group today.
|
|
59
|
+
it('still lets help reach stderr when help IS the failure report', () => {
|
|
60
|
+
const program = new Command('probe');
|
|
61
|
+
const group = program.command('group');
|
|
62
|
+
group.command('leaf').action(() => {});
|
|
63
|
+
installJsonShim(program);
|
|
64
|
+
|
|
65
|
+
/** @type {string[]} */
|
|
66
|
+
const written = [];
|
|
67
|
+
const original = process.stderr.write;
|
|
68
|
+
// @ts-expect-error test double for the write signature
|
|
69
|
+
process.stderr.write = str => {
|
|
70
|
+
written.push(String(str));
|
|
71
|
+
return true;
|
|
72
|
+
};
|
|
73
|
+
try {
|
|
74
|
+
group.outputHelp({error: true});
|
|
75
|
+
} finally {
|
|
76
|
+
process.stderr.write = original;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
expect(written.join('')).toMatch(/Usage: probe group/);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
@@ -78,8 +78,9 @@ export function detectStylingSystem(targetDir: string): "stylex" | "tailwind" |
|
|
|
78
78
|
* Generate the agent cheat sheet from live CLI metadata.
|
|
79
79
|
*
|
|
80
80
|
* Structured as: workflow (behavioral) → rules (error prevention) → CLI reference.
|
|
81
|
-
* Templates
|
|
82
|
-
*
|
|
81
|
+
* Templates lead the workflow: every page starts from a scaffolded template,
|
|
82
|
+
* because the template already carries the frame and spacing that an agent
|
|
83
|
+
* composing from components would have to re-derive, and usually gets wrong.
|
|
83
84
|
*
|
|
84
85
|
* `stylingSystem` tailors the custom-styling guidance to what the project has
|
|
85
86
|
* configured (see {@link detectStylingSystem}) so the agent never reaches for a
|
|
@@ -182,6 +183,8 @@ export function removeXdsBlock(filePath: string, { deleteIfEmpty }?: {
|
|
|
182
183
|
/**
|
|
183
184
|
* Remove Astryx section from all known agent doc files.
|
|
184
185
|
* @param {string} targetDir
|
|
186
|
+
* @throws {PathSafetyError} `ERR_PATH_TRAVERSAL` when a file it would change
|
|
187
|
+
* resolves outside `targetDir`; nothing is changed.
|
|
185
188
|
*/
|
|
186
189
|
export function removeAgentDocs(targetDir: string): void;
|
|
187
190
|
/**
|
|
@@ -208,6 +211,8 @@ export function removeAgentDocs(targetDir: string): void;
|
|
|
208
211
|
* @param {string} [options.renderedBlock] - Fully rendered expected block. Init
|
|
209
212
|
* and upgrade pass one shared block to every target.
|
|
210
213
|
* @returns {string[]} List of files written
|
|
214
|
+
* @throws {import('../fs/path-safety.mjs').PathSafetyError} when a file it would
|
|
215
|
+
* write resolves outside `targetDir`; nothing is written.
|
|
211
216
|
*/
|
|
212
217
|
export function installAgentDocs(targetDir: string, { zh, lang, agent, paths, onlyReplace, topics, renderedBlock, }?: {
|
|
213
218
|
zh?: boolean | undefined;
|
|
@@ -22,11 +22,12 @@
|
|
|
22
22
|
import * as fs from 'node:fs';
|
|
23
23
|
import * as path from 'node:path';
|
|
24
24
|
import {findCoreDir, CLI_ROOT} from '../fs/paths.mjs';
|
|
25
|
-
import {assertWithin} from '../fs/path-safety.mjs';
|
|
25
|
+
import {assertWithin, PathSafetyError} from '../fs/path-safety.mjs';
|
|
26
26
|
import {getCliInvocation} from '../env/package-manager.mjs';
|
|
27
27
|
import {discoverComponents} from '../discovery/component-discovery.mjs';
|
|
28
28
|
import {Project} from '../config/project.mjs';
|
|
29
29
|
import {humanLog} from '../response/json.mjs';
|
|
30
|
+
import {ERROR_CODES} from '../response/error-codes.mjs';
|
|
30
31
|
import {
|
|
31
32
|
AGENTS_MD,
|
|
32
33
|
CLAUDE_MD,
|
|
@@ -353,8 +354,9 @@ export function detectStylingSystem(targetDir) {
|
|
|
353
354
|
* Generate the agent cheat sheet from live CLI metadata.
|
|
354
355
|
*
|
|
355
356
|
* Structured as: workflow (behavioral) → rules (error prevention) → CLI reference.
|
|
356
|
-
* Templates
|
|
357
|
-
*
|
|
357
|
+
* Templates lead the workflow: every page starts from a scaffolded template,
|
|
358
|
+
* because the template already carries the frame and spacing that an agent
|
|
359
|
+
* composing from components would have to re-derive, and usually gets wrong.
|
|
358
360
|
*
|
|
359
361
|
* `stylingSystem` tailors the custom-styling guidance to what the project has
|
|
360
362
|
* configured (see {@link detectStylingSystem}) so the agent never reaches for a
|
|
@@ -427,17 +429,19 @@ export function generateCompressedIndex(
|
|
|
427
429
|
lines.push(' import "@astryxdesign/core/astryx.css";');
|
|
428
430
|
lines.push('');
|
|
429
431
|
|
|
430
|
-
// Workflow — `build` is the front door
|
|
431
|
-
|
|
432
|
-
lines.push('
|
|
433
|
-
lines.push('
|
|
434
|
-
lines.push('
|
|
432
|
+
// Workflow — `build` is the front door, and every page starts from the
|
|
433
|
+
// template it names.
|
|
434
|
+
lines.push('WORKFLOW — start every page from a template. Never lay out a page from scratch:');
|
|
435
|
+
lines.push('1. `astryx build "<idea>"` — START HERE: names the [page] template to start from (always one: the closest match, or the app shell), two other templates, and the [block]s + [component]s for parts it lacks. No args = full playbook.');
|
|
436
|
+
lines.push('2. `astryx template <name> <path>` — scaffold that template into your project. Keep its frame, gap and padding; replace its data, copy and sections; delete sections you do not need.');
|
|
437
|
+
lines.push('3. `astryx template <Block>` for a part the template lacks; `astryx component <Name>` for props + examples before you use or change a component.');
|
|
438
|
+
lines.push('Changing a page you already have? Keep it: skip step 2 and add blocks and components inside its sections.');
|
|
435
439
|
lines.push('');
|
|
436
440
|
|
|
437
441
|
// Rules — the top error-preventers.
|
|
438
442
|
lines.push('RULES:');
|
|
439
443
|
lines.push('- No <div> — components do all layout/spacing, page frame included.');
|
|
440
|
-
lines.push('- Frame first:
|
|
444
|
+
lines.push('- Frame first: the template you scaffold sets the page frame. Read `astryx docs layout` before you change it — region widths, breakpoint behavior.');
|
|
441
445
|
lines.push('- Dense data = rows (Table, List/Item), never Card-wrapped list items; Card is for standalone widgets. Status = StatusDot/Token; Badge = counts only.');
|
|
442
446
|
// Styling guidance tailored to the project's configured system — never
|
|
443
447
|
// recommend a path that isn't compiled here (xstyle needs the StyleX compiler;
|
|
@@ -462,7 +466,7 @@ export function generateCompressedIndex(
|
|
|
462
466
|
css: 'replace any raw <div>/<span> layout, imported .css/@apply, or hardcoded value (#hex, 16px) with the component or a token (var(--color-*|--spacing-*|…))',
|
|
463
467
|
};
|
|
464
468
|
lines.push(
|
|
465
|
-
`- SELF-CHECK before you finish: re-read the file and ${selfCheckFix[stylingSystem] ?? selfCheckFix.css}. If unsure a component/prop exists, run \`astryx component <Name>\` / \`astryx search "<thing>"\`; don't hand-roll CSS.`,
|
|
469
|
+
`- SELF-CHECK before you finish: re-read the file and ${selfCheckFix[stylingSystem] ?? selfCheckFix.css}. Confirm the page kept its template's frame, gap and padding. If unsure a component/prop exists, run \`astryx component <Name>\` / \`astryx search "<thing>"\`; don't hand-roll CSS.`,
|
|
466
470
|
);
|
|
467
471
|
lines.push('');
|
|
468
472
|
|
|
@@ -485,6 +489,7 @@ export function generateCompressedIndex(
|
|
|
485
489
|
if (resolvedTopics.length > 0) {
|
|
486
490
|
lines.push(` docs <topic> ${resolvedTopics.join(', ')}`);
|
|
487
491
|
}
|
|
492
|
+
lines.push(' docs cli commands, API reference, integration authoring (one level at a time)');
|
|
488
493
|
lines.push(' swizzle <Name> eject component source for deep customization');
|
|
489
494
|
lines.push(' upgrade --apply run after any Astryx or integration dependency bump');
|
|
490
495
|
const appendCount = agentDocs.reduce(
|
|
@@ -705,12 +710,65 @@ export function removeXdsBlock(filePath, {deleteIfEmpty = false} = {}) {
|
|
|
705
710
|
return true;
|
|
706
711
|
}
|
|
707
712
|
|
|
713
|
+
/**
|
|
714
|
+
* Whether an agent-doc file already carries a managed-block marker.
|
|
715
|
+
* @param {string} filePath
|
|
716
|
+
* @returns {boolean}
|
|
717
|
+
*/
|
|
718
|
+
function hasManagedMarker(filePath) {
|
|
719
|
+
try {
|
|
720
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
721
|
+
return content.includes(MARKER_START) || content.includes(LEGACY_MARKER_START);
|
|
722
|
+
} catch {
|
|
723
|
+
return false;
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
/**
|
|
728
|
+
* Whether `removeXdsBlock` would change `filePath`: it holds one well-formed
|
|
729
|
+
* managed block.
|
|
730
|
+
* @param {string} filePath
|
|
731
|
+
* @returns {boolean}
|
|
732
|
+
*/
|
|
733
|
+
function hasRemovableBlock(filePath) {
|
|
734
|
+
try {
|
|
735
|
+
return findManagedBlock(fs.readFileSync(filePath, 'utf-8')) != null;
|
|
736
|
+
} catch {
|
|
737
|
+
return false;
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
/**
|
|
742
|
+
* Every file a run writes must resolve inside `targetDir`, symlinks
|
|
743
|
+
* included. Checked for the whole write set before the first write, so an
|
|
744
|
+
* escape writes nothing.
|
|
745
|
+
* @param {string} targetDir
|
|
746
|
+
* @param {Iterable<string>} relPaths
|
|
747
|
+
*/
|
|
748
|
+
function assertTargetsWithin(targetDir, relPaths) {
|
|
749
|
+
for (const p of relPaths) {
|
|
750
|
+
assertWithin(p, targetDir, {label: 'agent docs path'});
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
|
|
708
754
|
/**
|
|
709
755
|
* Remove Astryx section from all known agent doc files.
|
|
710
756
|
* @param {string} targetDir
|
|
757
|
+
* @throws {PathSafetyError} `ERR_PATH_TRAVERSAL` when a file it would change
|
|
758
|
+
* resolves outside `targetDir`; nothing is changed.
|
|
711
759
|
*/
|
|
712
760
|
export function removeAgentDocs(targetDir) {
|
|
713
761
|
const allPaths = discoverAgentDocs(targetDir);
|
|
762
|
+
try {
|
|
763
|
+
assertTargetsWithin(
|
|
764
|
+
targetDir,
|
|
765
|
+
allPaths.filter(p => hasRemovableBlock(path.join(targetDir, p))),
|
|
766
|
+
);
|
|
767
|
+
} catch (err) {
|
|
768
|
+
// The code reaches the error envelope as is, so it must be registered.
|
|
769
|
+
if (!(err instanceof PathSafetyError)) throw err;
|
|
770
|
+
throw new PathSafetyError(err.message, ERROR_CODES.ERR_PATH_TRAVERSAL);
|
|
771
|
+
}
|
|
714
772
|
|
|
715
773
|
for (const p of allPaths) {
|
|
716
774
|
const filePath = path.join(targetDir, p);
|
|
@@ -718,9 +776,9 @@ export function removeAgentDocs(targetDir) {
|
|
|
718
776
|
const deleteIfEmpty = p === AGENTS_MD || p === CLAUDE_DIR_MD;
|
|
719
777
|
if (removeXdsBlock(filePath, {deleteIfEmpty})) {
|
|
720
778
|
if (!fs.existsSync(filePath)) {
|
|
721
|
-
humanLog(
|
|
779
|
+
humanLog(`[ok] Removed empty ${p}`);
|
|
722
780
|
} else {
|
|
723
|
-
humanLog(
|
|
781
|
+
humanLog(`[ok] Removed design system section from ${p}`);
|
|
724
782
|
}
|
|
725
783
|
}
|
|
726
784
|
}
|
|
@@ -750,6 +808,8 @@ export function removeAgentDocs(targetDir) {
|
|
|
750
808
|
* @param {string} [options.renderedBlock] - Fully rendered expected block. Init
|
|
751
809
|
* and upgrade pass one shared block to every target.
|
|
752
810
|
* @returns {string[]} List of files written
|
|
811
|
+
* @throws {import('../fs/path-safety.mjs').PathSafetyError} when a file it would
|
|
812
|
+
* write resolves outside `targetDir`; nothing is written.
|
|
753
813
|
*/
|
|
754
814
|
export function installAgentDocs(
|
|
755
815
|
targetDir,
|
|
@@ -806,6 +866,7 @@ export function installAgentDocs(
|
|
|
806
866
|
// Agent preset
|
|
807
867
|
if (agent) {
|
|
808
868
|
const {inject, create} = resolveAgentPaths(targetDir, agent);
|
|
869
|
+
assertTargetsWithin(targetDir, [...inject, ...create]);
|
|
809
870
|
for (const p of inject) {
|
|
810
871
|
injectXdsBlock(path.join(targetDir, p), compressedIndex);
|
|
811
872
|
written.push(p);
|
|
@@ -833,6 +894,14 @@ export function installAgentDocs(
|
|
|
833
894
|
if (existing.length > 0) {
|
|
834
895
|
const wrappers = discoverAgentDocWrappers(targetDir, existing);
|
|
835
896
|
const targets = existing.filter(p => !wrappers.has(p));
|
|
897
|
+
// A refresh skips unmarked files and a wrapper is only written when it
|
|
898
|
+
// carries a block, so only the files this run writes are checked.
|
|
899
|
+
/** @param {string} p */
|
|
900
|
+
const marked = p => hasManagedMarker(path.join(targetDir, p));
|
|
901
|
+
assertTargetsWithin(targetDir, [
|
|
902
|
+
...targets.filter(p => !onlyReplace || marked(p)),
|
|
903
|
+
...[...wrappers].filter(marked),
|
|
904
|
+
]);
|
|
836
905
|
|
|
837
906
|
for (const p of targets) {
|
|
838
907
|
const didWrite = injectXdsBlock(path.join(targetDir, p), compressedIndex, {onlyReplace});
|
|
@@ -860,6 +929,7 @@ export function installAgentDocs(
|
|
|
860
929
|
if (onlyReplace) return written;
|
|
861
930
|
|
|
862
931
|
const defaultPath = AGENTS_MD;
|
|
932
|
+
assertTargetsWithin(targetDir, [defaultPath]);
|
|
863
933
|
injectXdsBlock(path.join(targetDir, defaultPath), compressedIndex, {
|
|
864
934
|
createIfMissing: true,
|
|
865
935
|
header: `# AGENTS.md\n\nProject-specific guidance for AI coding agents.`,
|