@astryxdesign/cli 0.6.3 → 0.6.4-canary.10dd683
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 +117 -78
- 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 +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 +164 -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 +99 -1
- package/api/doctor/doctor.doc.mjs +1 -0
- package/api/doctor/doctor.mjs +548 -1
- package/api/doctor/doctor.test.mjs +610 -1
- 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 +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 +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.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 +62 -11
- 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 +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 +1072 -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 +45 -8
- 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/run.mjs +356 -59
- 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 +27 -11
- package/assets/codemods/__tests__/registry.test.mjs +1 -0
- 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/registry.mjs +1 -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/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/{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 +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 +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 +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 +5 -4
- 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/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 +28 -6
- package/clients/cli/commands/docs.mjs +240 -26
- package/clients/cli/commands/docs.test.mjs +193 -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/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 +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 -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 +37 -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 +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 +774 -83
- 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/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/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 +41 -21
- 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
|
@@ -5,8 +5,7 @@
|
|
|
5
5
|
* contribution into an integration package.
|
|
6
6
|
*
|
|
7
7
|
* Dispatches component, doc, template, codemod, and agent-doc. Theme
|
|
8
|
-
* delegates to the
|
|
9
|
-
* Every root-based kind shares: first add creates the manifest; one shared
|
|
8
|
+
* delegates to the dedicated same-stem descriptor writer. Every root-based kind shares: first add creates the manifest; one shared
|
|
10
9
|
* writer; never creates `files`/`exports`; atomic staged writes; no clobber;
|
|
11
10
|
* dry-run receipt predicts real run; post-write verify through the real
|
|
12
11
|
* discovery/parser seam.
|
|
@@ -35,6 +34,12 @@ import {
|
|
|
35
34
|
} from '../../foundation/integrations/integrations.mjs';
|
|
36
35
|
import {isValidSemver} from '../../foundation/env/semver.mjs';
|
|
37
36
|
import {assertContributionVisible} from '../../foundation/integrations/contribution-inventory.mjs';
|
|
37
|
+
import {
|
|
38
|
+
docsTreeCliProblem,
|
|
39
|
+
withDocsTreeCli,
|
|
40
|
+
} from '../../foundation/integrations/cli-requirement.mjs';
|
|
41
|
+
import {discoverIntegrationDocs} from '../../foundation/discovery/docs-discovery.mjs';
|
|
42
|
+
import {findIntegrationComponentDoc} from '../../foundation/discovery/component-discovery.mjs';
|
|
38
43
|
import {parseAgentDocsField} from '../../authoring/integration/schema.mjs';
|
|
39
44
|
import {integrationAddTheme} from './add-theme.mjs';
|
|
40
45
|
import {
|
|
@@ -83,6 +88,17 @@ function resolvePackage(cwd) {
|
|
|
83
88
|
}
|
|
84
89
|
const owner = typeof pkg.name === 'string' ? pkg.name : '(local integration)';
|
|
85
90
|
const existingManifest = findLocalIntegrationManifestOrNull(packageDir);
|
|
91
|
+
// The nearest package.json above the cwd may belong to another package (an
|
|
92
|
+
// app that contains the folder). Only a package that is already an
|
|
93
|
+
// integration is found from a subfolder; the first add runs in the package.
|
|
94
|
+
const here = path.resolve(cwd ?? process.cwd());
|
|
95
|
+
if (existingManifest == null && path.resolve(packageDir) !== here) {
|
|
96
|
+
throw new AstryxError(
|
|
97
|
+
`${here} has no package.json. The nearest is ${packageFile} (${owner}), which is not an Astryx integration yet. Run this in your integration package's own directory, next to its package.json.`,
|
|
98
|
+
undefined,
|
|
99
|
+
ERROR_CODES.ERR_INVALID_ARGUMENT,
|
|
100
|
+
);
|
|
101
|
+
}
|
|
86
102
|
const manifestFile =
|
|
87
103
|
existingManifest ?? path.join(packageDir, 'astryx.integration.mjs');
|
|
88
104
|
return {
|
|
@@ -248,10 +264,21 @@ async function addComponent(name, options) {
|
|
|
248
264
|
ERROR_CODES.ERR_FILE_EXISTS,
|
|
249
265
|
);
|
|
250
266
|
}
|
|
267
|
+
// Discovery keys components by doc stem anywhere under the root, so a second
|
|
268
|
+
// doc with this name would shadow one of the two.
|
|
269
|
+
const existingDoc = findIntegrationComponentDoc({components: root}, name);
|
|
270
|
+
if (existingDoc != null) {
|
|
271
|
+
throw new AstryxError(
|
|
272
|
+
`Refusing to add component "${name}": ${projectPath(path.relative(packageDir, existingDoc))} already defines it.`,
|
|
273
|
+
undefined,
|
|
274
|
+
ERROR_CODES.ERR_FILE_EXISTS,
|
|
275
|
+
);
|
|
276
|
+
}
|
|
251
277
|
|
|
252
278
|
const sourcePath = projectPath(path.relative(packageDir, sourceFile));
|
|
253
|
-
const
|
|
254
|
-
const
|
|
279
|
+
const extensionlessPath = sourcePath.replace(/\.tsx?$/u, '');
|
|
280
|
+
const importSpecifier = `${owner}/${extensionlessPath}`;
|
|
281
|
+
const docContents = `/** @type {import('@astryxdesign/cli/authoring').ComponentDoc} */\nexport default {\n type: 'component',\n name: '${name}',\n displayName: '${name}',\n import: ${JSON.stringify(importSpecifier)},\n usage: {description: '${name} component.'},\n props: [],\n};\n`;
|
|
255
282
|
const sourceContents = `export function ${name}() {\n return <div>${name}</div>;\n}\n`;
|
|
256
283
|
|
|
257
284
|
/** @type {import('./add-helpers.mjs').WritePlan[]} */
|
|
@@ -263,7 +290,7 @@ async function addComponent(name, options) {
|
|
|
263
290
|
packageFile,
|
|
264
291
|
rootPath,
|
|
265
292
|
path.basename(manifestFile),
|
|
266
|
-
[{subpath:
|
|
293
|
+
[{subpath: extensionlessPath, target: sourcePath}],
|
|
267
294
|
);
|
|
268
295
|
if (pkgUpdate != null) {
|
|
269
296
|
plans.push({
|
|
@@ -342,7 +369,7 @@ async function addComponent(name, options) {
|
|
|
342
369
|
|
|
343
370
|
/**
|
|
344
371
|
* @param {string} name topic name (must match [\w-]+)
|
|
345
|
-
* @param {{cwd?: string, dryRun?: boolean, replaces?: string, extends?: string}} options
|
|
372
|
+
* @param {{cwd?: string, dryRun?: boolean, replaces?: string, extends?: string, parent?: string}} options
|
|
346
373
|
* @returns {Promise<import('./integration-authoring.type.mjs').IntegrationAddResponse>}
|
|
347
374
|
*/
|
|
348
375
|
async function addDoc(name, options) {
|
|
@@ -361,6 +388,20 @@ async function addDoc(name, options) {
|
|
|
361
388
|
ERROR_CODES.ERR_INVALID_ARGUMENT,
|
|
362
389
|
);
|
|
363
390
|
}
|
|
391
|
+
if (options.parent != null && (options.replaces != null || options.extends != null)) {
|
|
392
|
+
throw new AstryxError(
|
|
393
|
+
'A guide placed in a namespace has its own route: it cannot also replace or extend a topic.',
|
|
394
|
+
undefined,
|
|
395
|
+
ERROR_CODES.ERR_INVALID_ARGUMENT,
|
|
396
|
+
);
|
|
397
|
+
}
|
|
398
|
+
if (options.parent != null && !/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(options.parent)) {
|
|
399
|
+
throw new AstryxError(
|
|
400
|
+
'--parent must name a namespace in lowercase letters and digits joined by single hyphens, such as "acme".',
|
|
401
|
+
undefined,
|
|
402
|
+
ERROR_CODES.ERR_INVALID_ARGUMENT,
|
|
403
|
+
);
|
|
404
|
+
}
|
|
364
405
|
for (const [option, value] of [
|
|
365
406
|
['--replaces', options.replaces],
|
|
366
407
|
['--extends', options.extends],
|
|
@@ -421,20 +462,92 @@ async function addDoc(name, options) {
|
|
|
421
462
|
}
|
|
422
463
|
|
|
423
464
|
const title = kebabToTitle(name);
|
|
465
|
+
// --parent names a namespace of this package by its name, wherever its file
|
|
466
|
+
// is. An existing one is used as it is: its `guides` slot, or else its only
|
|
467
|
+
// slot that takes a guide. Otherwise the namespace doc is written, unless a
|
|
468
|
+
// file of that name is already something else (spec:AST-046 FR11).
|
|
469
|
+
const namespaceFile =
|
|
470
|
+
options.parent == null
|
|
471
|
+
? null
|
|
472
|
+
: assertWithin(`${options.parent}.doc.mjs`, root, {
|
|
473
|
+
label: 'namespace doc file',
|
|
474
|
+
});
|
|
475
|
+
let parentSlot = 'guides';
|
|
476
|
+
let writeNamespace = false;
|
|
477
|
+
if (options.parent != null && namespaceFile != null) {
|
|
478
|
+
const {namespaces} = await discoverIntegrationDocs({
|
|
479
|
+
name: owner,
|
|
480
|
+
docs: root,
|
|
481
|
+
});
|
|
482
|
+
const existing = namespaces.find(ns => ns.doc.name === options.parent);
|
|
483
|
+
if (existing != null) {
|
|
484
|
+
const takesGuides = Object.entries(existing.doc.slots ?? {})
|
|
485
|
+
.filter(([, slot]) => slot?.accepts?.kinds?.includes('generic'))
|
|
486
|
+
.map(([slotName]) => slotName);
|
|
487
|
+
const slot = takesGuides.includes('guides')
|
|
488
|
+
? 'guides'
|
|
489
|
+
: takesGuides.length === 1
|
|
490
|
+
? takesGuides[0]
|
|
491
|
+
: null;
|
|
492
|
+
if (slot == null) {
|
|
493
|
+
throw new AstryxError(
|
|
494
|
+
takesGuides.length === 0
|
|
495
|
+
? `Namespace "${options.parent}" (${existing.source}) has no slot that takes a guide. Add one, such as guides: {title: 'Guides', accepts: {kinds: ['generic']}}.`
|
|
496
|
+
: `Namespace "${options.parent}" (${existing.source}) has more than one slot that takes a guide (${takesGuides.join(', ')}). Write the guide yourself, and name its slot in its placement.`,
|
|
497
|
+
undefined,
|
|
498
|
+
ERROR_CODES.ERR_INVALID_ARGUMENT,
|
|
499
|
+
);
|
|
500
|
+
}
|
|
501
|
+
parentSlot = slot;
|
|
502
|
+
} else if (fs.existsSync(namespaceFile)) {
|
|
503
|
+
throw new AstryxError(
|
|
504
|
+
`${projectPath(path.relative(packageDir, namespaceFile))} exists but does not load as the namespace "${options.parent}". Fix or rename that file, or pass another --parent.`,
|
|
505
|
+
undefined,
|
|
506
|
+
ERROR_CODES.ERR_FILE_EXISTS,
|
|
507
|
+
);
|
|
508
|
+
} else {
|
|
509
|
+
writeNamespace = true;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
424
512
|
const relationship = options.replaces
|
|
425
513
|
? `\n replaces: '${options.replaces}',`
|
|
426
514
|
: options.extends
|
|
427
515
|
? `\n extends: '${options.extends}',`
|
|
428
|
-
:
|
|
429
|
-
|
|
516
|
+
: options.parent
|
|
517
|
+
? `\n placement: {parent: 'namespace:${options.parent}', slot: '${parentSlot}'},`
|
|
518
|
+
: '';
|
|
519
|
+
const namespaceTitle =
|
|
520
|
+
options.parent == null ? '' : kebabToTitle(options.parent);
|
|
521
|
+
const namespaceContents = `/** @type {import('@astryxdesign/cli/authoring').NamespaceDoc} */\nexport default {\n type: 'namespace',\n name: '${options.parent}',\n title: '${namespaceTitle}',\n summary: 'Guides for ${namespaceTitle}.',\n slots: {\n guides: {title: 'Guides', accepts: {kinds: ['generic']}},\n },\n};\n`;
|
|
522
|
+
const docContents = `/** @type {import('@astryxdesign/cli/authoring').ReferenceDoc} */\nexport default {\n type: 'generic',\n name: '${name}',\n title: '${title}',\n description: '${title} documentation.',${relationship}\n sections: [\n {\n title: 'Overview',\n content: [\n { type: 'prose', text: '${title} documentation.' },\n ],\n },\n ],\n};\n`;
|
|
430
523
|
|
|
431
524
|
/** @type {import('./add-helpers.mjs').WritePlan[]} */
|
|
432
525
|
const plans = [{path: docFile, contents: docContents, createOnly: true}];
|
|
433
|
-
|
|
526
|
+
if (namespaceFile != null && writeNamespace) {
|
|
527
|
+
plans.push({path: namespaceFile, contents: namespaceContents, createOnly: true});
|
|
528
|
+
}
|
|
529
|
+
let pkgUpdate = packageJsonUpdate(
|
|
434
530
|
packageFile,
|
|
435
531
|
rootPath,
|
|
436
532
|
path.basename(manifestFile),
|
|
437
533
|
);
|
|
534
|
+
// A namespace doc needs a CLI that reads it: an older one hides every doc
|
|
535
|
+
// topic the package ships. Declare that CLI as a peer, so an older one fails
|
|
536
|
+
// at install instead (spec:AST-046 FR11).
|
|
537
|
+
if (options.parent != null) {
|
|
538
|
+
const expectedOriginal =
|
|
539
|
+
pkgUpdate?.expectedOriginal ?? fs.readFileSync(packageFile);
|
|
540
|
+
const text = pkgUpdate?.contents ?? expectedOriginal.toString('utf-8');
|
|
541
|
+
const current = JSON.parse(text);
|
|
542
|
+
if (docsTreeCliProblem(current) != null) {
|
|
543
|
+
pkgUpdate = {
|
|
544
|
+
contents:
|
|
545
|
+
JSON.stringify(withDocsTreeCli(current), null, 2) +
|
|
546
|
+
(text.endsWith('\n') ? '\n' : ''),
|
|
547
|
+
expectedOriginal,
|
|
548
|
+
};
|
|
549
|
+
}
|
|
550
|
+
}
|
|
438
551
|
if (pkgUpdate != null) {
|
|
439
552
|
plans.push({
|
|
440
553
|
path: packageFile,
|
|
@@ -553,8 +666,8 @@ async function addTemplate(name, options) {
|
|
|
553
666
|
throw error;
|
|
554
667
|
}
|
|
555
668
|
|
|
556
|
-
const specFile = assertWithin(`${name}.
|
|
557
|
-
label: 'template
|
|
669
|
+
const specFile = assertWithin(`${name}.doc.mjs`, root, {
|
|
670
|
+
label: 'template descriptor',
|
|
558
671
|
});
|
|
559
672
|
const sourceFile = assertWithin(`${name}.tsx`, root, {
|
|
560
673
|
label: 'template source',
|
|
@@ -576,7 +689,9 @@ async function addTemplate(name, options) {
|
|
|
576
689
|
|
|
577
690
|
const pascalName = kebabToPascal(name);
|
|
578
691
|
const sourcePath = projectPath(path.relative(packageDir, sourceFile));
|
|
579
|
-
const
|
|
692
|
+
const extensionlessPath = sourcePath.replace(/\.tsx?$/u, '');
|
|
693
|
+
const blockFields = templateType === 'block' ? '\n aspectRatio: 1,' : '';
|
|
694
|
+
const specContents = `/** @type {import('@astryxdesign/cli/authoring').TemplateDoc} */\nexport default {\n type: '${templateType}',\n name: '${name}',\n displayName: '${kebabToTitle(name)}',\n description: '${kebabToTitle(name)} template.',${blockFields}\n};\n`;
|
|
580
695
|
const sourceContents = `export default function ${pascalName}() {\n return <div>${kebabToTitle(name)}</div>;\n}\n`;
|
|
581
696
|
|
|
582
697
|
/** @type {import('./add-helpers.mjs').WritePlan[]} */
|
|
@@ -588,7 +703,7 @@ async function addTemplate(name, options) {
|
|
|
588
703
|
packageFile,
|
|
589
704
|
rootPath,
|
|
590
705
|
path.basename(manifestFile),
|
|
591
|
-
[{subpath:
|
|
706
|
+
[{subpath: extensionlessPath, target: sourcePath}],
|
|
592
707
|
);
|
|
593
708
|
if (pkgUpdate != null) {
|
|
594
709
|
plans.push({
|
|
@@ -1092,7 +1207,7 @@ export function integrationAddAgentDoc(line, options = {}) {
|
|
|
1092
1207
|
|
|
1093
1208
|
const KIND_OPTIONS = {
|
|
1094
1209
|
component: new Set(['cwd', 'dryRun']),
|
|
1095
|
-
doc: new Set(['cwd', 'dryRun', 'replaces', 'extends']),
|
|
1210
|
+
doc: new Set(['cwd', 'dryRun', 'replaces', 'extends', 'parent']),
|
|
1096
1211
|
template: new Set(['cwd', 'dryRun', 'templateType']),
|
|
1097
1212
|
codemod: new Set(['cwd', 'dryRun', 'to']),
|
|
1098
1213
|
'agent-doc': new Set(['cwd', 'dryRun']),
|
|
@@ -1123,7 +1238,7 @@ function validateKindOptions(kind, options) {
|
|
|
1123
1238
|
*
|
|
1124
1239
|
* @param {'component'|'doc'|'template'|'codemod'|'agent-doc'|'theme'} kind
|
|
1125
1240
|
* @param {string} name
|
|
1126
|
-
* @param {{cwd?: string, dryRun?: boolean, templateType?: 'page'|'block', to?: string, replaces?: string, extends?: string}} [options]
|
|
1241
|
+
* @param {{cwd?: string, dryRun?: boolean, templateType?: 'page'|'block', to?: string, replaces?: string, extends?: string, parent?: string}} [options]
|
|
1127
1242
|
* @returns {Promise<import('./integration-authoring.type.mjs').IntegrationAddResponse>}
|
|
1128
1243
|
*/
|
|
1129
1244
|
export async function integrationAdd(kind, name, options = {}) {
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
integrationAddTemplate,
|
|
13
13
|
} from './add-contribution.mjs';
|
|
14
14
|
import {validateLocalIntegration} from './validate-integration.mjs';
|
|
15
|
+
import {DOCS_TREE_CLI} from '../../foundation/integrations/cli-requirement.mjs';
|
|
15
16
|
|
|
16
17
|
let tmpDir;
|
|
17
18
|
|
|
@@ -77,6 +78,7 @@ describe('integrationAdd component', () => {
|
|
|
77
78
|
path.join(tmpDir, 'components/MyWidget.doc.mjs'),
|
|
78
79
|
'utf-8',
|
|
79
80
|
);
|
|
81
|
+
expect(doc).toContain("@astryxdesign/cli/authoring').ComponentDoc");
|
|
80
82
|
expect(doc).toContain("type: 'component'");
|
|
81
83
|
expect(doc).toContain("name: 'MyWidget'");
|
|
82
84
|
expect(doc).toContain('props: []');
|
|
@@ -118,14 +120,14 @@ describe('integrationAdd component', () => {
|
|
|
118
120
|
);
|
|
119
121
|
expect(pkg.exports).toEqual({
|
|
120
122
|
'.': './index.mjs',
|
|
121
|
-
'./components/MyWidget
|
|
123
|
+
'./components/MyWidget': './components/MyWidget.tsx',
|
|
122
124
|
});
|
|
123
125
|
expect(
|
|
124
126
|
fs.readFileSync(
|
|
125
127
|
path.join(tmpDir, 'components/MyWidget.doc.mjs'),
|
|
126
128
|
'utf-8',
|
|
127
129
|
),
|
|
128
|
-
).toContain('import: "@acme/integration/components/MyWidget
|
|
130
|
+
).toContain('import: "@acme/integration/components/MyWidget"');
|
|
129
131
|
});
|
|
130
132
|
|
|
131
133
|
it('does not create exports when the package has no exports map', async () => {
|
|
@@ -143,7 +145,7 @@ describe('integrationAdd component', () => {
|
|
|
143
145
|
setup({
|
|
144
146
|
exports: {
|
|
145
147
|
'.': './index.mjs',
|
|
146
|
-
'./components/MyWidget
|
|
148
|
+
'./components/MyWidget': './different.tsx',
|
|
147
149
|
},
|
|
148
150
|
});
|
|
149
151
|
|
|
@@ -304,6 +306,7 @@ describe('integrationAdd doc', () => {
|
|
|
304
306
|
path.join(tmpDir, 'docs/my-guide.doc.mjs'),
|
|
305
307
|
'utf-8',
|
|
306
308
|
);
|
|
309
|
+
expect(doc).toContain("@astryxdesign/cli/authoring').ReferenceDoc");
|
|
307
310
|
expect(doc).toContain("type: 'generic'");
|
|
308
311
|
expect(doc).toContain("name: 'my-guide'");
|
|
309
312
|
|
|
@@ -312,6 +315,142 @@ describe('integrationAdd doc', () => {
|
|
|
312
315
|
expect(docErrors).toEqual([]);
|
|
313
316
|
});
|
|
314
317
|
|
|
318
|
+
it('refuses to write from a folder with no package.json into the package above it', async () => {
|
|
319
|
+
setupBare();
|
|
320
|
+
const inside = path.join(tmpDir, 'kit');
|
|
321
|
+
fs.mkdirSync(inside);
|
|
322
|
+
await expect(
|
|
323
|
+
integrationAdd('doc', 'my-guide', {cwd: inside, parent: 'acme'}),
|
|
324
|
+
).rejects.toMatchObject({
|
|
325
|
+
code: 'ERR_INVALID_ARGUMENT',
|
|
326
|
+
message: expect.stringContaining('has no package.json'),
|
|
327
|
+
});
|
|
328
|
+
expect(fs.existsSync(path.join(tmpDir, 'docs'))).toBe(false);
|
|
329
|
+
expect(fs.existsSync(path.join(tmpDir, 'astryx.integration.mjs'))).toBe(false);
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
it('finds an integration from a folder inside it', async () => {
|
|
333
|
+
setup();
|
|
334
|
+
const inside = path.join(tmpDir, 'src');
|
|
335
|
+
fs.mkdirSync(inside);
|
|
336
|
+
const result = await integrationAdd('doc', 'my-guide', {cwd: inside});
|
|
337
|
+
expect(result.data.files).toContain('docs/my-guide.doc.mjs');
|
|
338
|
+
expect(fs.existsSync(path.join(tmpDir, 'docs/my-guide.doc.mjs'))).toBe(true);
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
it('places a guide in a namespace of the package, writing the namespace once', async () => {
|
|
342
|
+
setup();
|
|
343
|
+
const first = await integrationAdd('doc', 'deploying', {
|
|
344
|
+
cwd: tmpDir,
|
|
345
|
+
parent: 'acme',
|
|
346
|
+
});
|
|
347
|
+
expect(first.data.files).toEqual(
|
|
348
|
+
expect.arrayContaining(['docs/deploying.doc.mjs', 'docs/acme.doc.mjs']),
|
|
349
|
+
);
|
|
350
|
+
const guide = fs.readFileSync(path.join(tmpDir, 'docs/deploying.doc.mjs'), 'utf-8');
|
|
351
|
+
expect(guide).toContain("placement: {parent: 'namespace:acme', slot: 'guides'}");
|
|
352
|
+
const namespace = fs.readFileSync(path.join(tmpDir, 'docs/acme.doc.mjs'), 'utf-8');
|
|
353
|
+
expect(namespace).toContain("type: 'namespace'");
|
|
354
|
+
expect(namespace).toContain("guides: {title: 'Guides', accepts: {kinds: ['generic']}}");
|
|
355
|
+
|
|
356
|
+
// The namespace doc needs a CLI that reads it, declared as an optional peer.
|
|
357
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(tmpDir, 'package.json'), 'utf-8'));
|
|
358
|
+
expect(pkg.peerDependencies).toEqual({'@astryxdesign/cli': `>=${DOCS_TREE_CLI}`});
|
|
359
|
+
expect(pkg.peerDependenciesMeta).toEqual({'@astryxdesign/cli': {optional: true}});
|
|
360
|
+
|
|
361
|
+
const second = await integrationAdd('doc', 'upgrading', {
|
|
362
|
+
cwd: tmpDir,
|
|
363
|
+
parent: 'acme',
|
|
364
|
+
});
|
|
365
|
+
expect(second.data.files).not.toContain('docs/acme.doc.mjs');
|
|
366
|
+
|
|
367
|
+
const validation = await validateLocalIntegration(tmpDir);
|
|
368
|
+
expect(validation.issues.filter(i => i.code === 'invalid_doc')).toEqual([]);
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
it('finds the --parent namespace by its name, wherever its file is, and uses its slot', async () => {
|
|
372
|
+
setup({manifest: "export default {docs: './docs'};\n"});
|
|
373
|
+
fs.mkdirSync(path.join(tmpDir, 'docs', 'ns'), {recursive: true});
|
|
374
|
+
fs.writeFileSync(
|
|
375
|
+
path.join(tmpDir, 'docs', 'ns', 'acme.doc.mjs'),
|
|
376
|
+
"export default {type: 'namespace', name: 'acme', title: 'Acme', summary: 'Acme.', slots: {items: {title: 'Items', accepts: {kinds: ['generic']}}}};\n",
|
|
377
|
+
);
|
|
378
|
+
const result = await integrationAdd('doc', 'deploying', {cwd: tmpDir, parent: 'acme'});
|
|
379
|
+
expect(result.data.files).not.toContain('docs/acme.doc.mjs');
|
|
380
|
+
expect(fs.existsSync(path.join(tmpDir, 'docs', 'acme.doc.mjs'))).toBe(false);
|
|
381
|
+
expect(fs.readFileSync(path.join(tmpDir, 'docs', 'deploying.doc.mjs'), 'utf-8')).toContain(
|
|
382
|
+
"placement: {parent: 'namespace:acme', slot: 'items'}",
|
|
383
|
+
);
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
it('refuses --parent when its file is not that namespace, or the namespace has no slot for a guide', async () => {
|
|
387
|
+
setup({manifest: "export default {docs: './docs'};\n"});
|
|
388
|
+
fs.mkdirSync(path.join(tmpDir, 'docs'), {recursive: true});
|
|
389
|
+
const nsFile = path.join(tmpDir, 'docs', 'acme.doc.mjs');
|
|
390
|
+
fs.writeFileSync(
|
|
391
|
+
nsFile,
|
|
392
|
+
"export default {type: 'generic', name: 'acme', title: 'Acme', description: 'A topic.', sections: [{title: 'Only', content: [{type: 'prose', text: 'x'}]}]};\n",
|
|
393
|
+
);
|
|
394
|
+
await expect(
|
|
395
|
+
integrationAdd('doc', 'deploying', {cwd: tmpDir, parent: 'acme'}),
|
|
396
|
+
).rejects.toMatchObject({code: 'ERR_FILE_EXISTS'});
|
|
397
|
+
// A fresh file: the module loader keeps the first import of a path.
|
|
398
|
+
fs.writeFileSync(
|
|
399
|
+
path.join(tmpDir, 'docs', 'beta.doc.mjs'),
|
|
400
|
+
"export default {type: 'namespace', name: 'beta', title: 'Beta', summary: 'Beta.', slots: {items: {title: 'Items', accepts: {kinds: ['function']}}}};\n",
|
|
401
|
+
);
|
|
402
|
+
await expect(
|
|
403
|
+
integrationAdd('doc', 'deploying', {cwd: tmpDir, parent: 'beta'}),
|
|
404
|
+
).rejects.toMatchObject({
|
|
405
|
+
code: 'ERR_INVALID_ARGUMENT',
|
|
406
|
+
message: expect.stringContaining('no slot that takes a guide'),
|
|
407
|
+
});
|
|
408
|
+
fs.writeFileSync(
|
|
409
|
+
path.join(tmpDir, 'docs', 'gamma.doc.mjs'),
|
|
410
|
+
"export default {type: 'namespace', name: 'gamma', title: 'Gamma', summary: 'Gamma.', slots: {guides: {title: 'Guides', accepts: {kinds: ['function']}}, more: {title: 'More', accepts: {kinds: ['generic']}}, extra: {title: 'Extra', accepts: {kinds: ['generic']}}}};\n",
|
|
411
|
+
);
|
|
412
|
+
await expect(
|
|
413
|
+
integrationAdd('doc', 'deploying', {cwd: tmpDir, parent: 'gamma'}),
|
|
414
|
+
).rejects.toMatchObject({
|
|
415
|
+
code: 'ERR_INVALID_ARGUMENT',
|
|
416
|
+
message: expect.stringContaining('more than one slot that takes a guide (more, extra)'),
|
|
417
|
+
});
|
|
418
|
+
expect(fs.existsSync(path.join(tmpDir, 'docs', 'deploying.doc.mjs'))).toBe(false);
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
it('raises a CLI peer that admits a CLI too old for namespace docs, and keeps one that does not', async () => {
|
|
422
|
+
setup();
|
|
423
|
+
const file = path.join(tmpDir, 'package.json');
|
|
424
|
+
const write = (/** @type {string} */ range) => {
|
|
425
|
+
const pkg = JSON.parse(fs.readFileSync(file, 'utf-8'));
|
|
426
|
+
pkg.peerDependencies = {'@astryxdesign/cli': range};
|
|
427
|
+
fs.writeFileSync(file, `${JSON.stringify(pkg, null, 2)}\n`);
|
|
428
|
+
};
|
|
429
|
+
write('^0.6.0');
|
|
430
|
+
await integrationAdd('doc', 'deploying', {cwd: tmpDir, parent: 'acme'});
|
|
431
|
+
expect(JSON.parse(fs.readFileSync(file, 'utf-8')).peerDependencies).toEqual({
|
|
432
|
+
'@astryxdesign/cli': `>=${DOCS_TREE_CLI}`,
|
|
433
|
+
});
|
|
434
|
+
write('^9.1.0');
|
|
435
|
+
await integrationAdd('doc', 'upgrading', {cwd: tmpDir, parent: 'acme'});
|
|
436
|
+
expect(JSON.parse(fs.readFileSync(file, 'utf-8')).peerDependencies).toEqual({
|
|
437
|
+
'@astryxdesign/cli': '^9.1.0',
|
|
438
|
+
});
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
it('refuses --parent with a relationship, or a namespace name that is not a route segment', async () => {
|
|
442
|
+
setup();
|
|
443
|
+
await expect(
|
|
444
|
+
integrationAdd('doc', 'x', {cwd: tmpDir, parent: 'acme', replaces: 'getting-started'}),
|
|
445
|
+
).rejects.toMatchObject({code: 'ERR_INVALID_ARGUMENT'});
|
|
446
|
+
await expect(
|
|
447
|
+
integrationAdd('doc', 'x', {cwd: tmpDir, parent: 'Acme Kit'}),
|
|
448
|
+
).rejects.toMatchObject({code: 'ERR_INVALID_ARGUMENT'});
|
|
449
|
+
await expect(
|
|
450
|
+
integrationAdd('template', 'x', {cwd: tmpDir, parent: 'acme'}),
|
|
451
|
+
).rejects.toMatchObject({code: 'ERR_INVALID_ARGUMENT'});
|
|
452
|
+
});
|
|
453
|
+
|
|
315
454
|
it('includes replaces in the generated doc', async () => {
|
|
316
455
|
setup();
|
|
317
456
|
const result = await integrationAdd('doc', 'my-tokens', {
|
|
@@ -390,13 +529,14 @@ describe('integrationAdd template', () => {
|
|
|
390
529
|
expect(result.data.kind).toBe('template');
|
|
391
530
|
expect(result.data.name).toBe('my-widget');
|
|
392
531
|
expect(result.data.root).toEqual({path: './templates', created: true});
|
|
393
|
-
expect(result.data.files).toContain('templates/my-widget.
|
|
532
|
+
expect(result.data.files).toContain('templates/my-widget.doc.mjs');
|
|
394
533
|
expect(result.data.files).toContain('templates/my-widget.tsx');
|
|
395
534
|
|
|
396
535
|
const spec = fs.readFileSync(
|
|
397
|
-
path.join(tmpDir, 'templates/my-widget.
|
|
536
|
+
path.join(tmpDir, 'templates/my-widget.doc.mjs'),
|
|
398
537
|
'utf-8',
|
|
399
538
|
);
|
|
539
|
+
expect(spec).toContain("@astryxdesign/cli/authoring').TemplateDoc");
|
|
400
540
|
expect(spec).toContain("type: 'page'");
|
|
401
541
|
expect(spec).toContain("name: 'my-widget'");
|
|
402
542
|
|
|
@@ -421,7 +561,7 @@ describe('integrationAdd template', () => {
|
|
|
421
561
|
);
|
|
422
562
|
expect(pkg.exports).toEqual({
|
|
423
563
|
'.': './index.mjs',
|
|
424
|
-
'./templates/my-widget
|
|
564
|
+
'./templates/my-widget': './templates/my-widget.tsx',
|
|
425
565
|
});
|
|
426
566
|
});
|
|
427
567
|
|
|
@@ -432,10 +572,11 @@ describe('integrationAdd template', () => {
|
|
|
432
572
|
templateType: 'block',
|
|
433
573
|
});
|
|
434
574
|
const spec = fs.readFileSync(
|
|
435
|
-
path.join(tmpDir, 'templates/my-card.
|
|
575
|
+
path.join(tmpDir, 'templates/my-card.doc.mjs'),
|
|
436
576
|
'utf-8',
|
|
437
577
|
);
|
|
438
578
|
expect(spec).toContain("type: 'block'");
|
|
579
|
+
expect(spec).toContain('aspectRatio: 1');
|
|
439
580
|
});
|
|
440
581
|
|
|
441
582
|
it('rejects an invalid template type', async () => {
|
|
@@ -676,6 +817,35 @@ describe('custom root preservation', () => {
|
|
|
676
817
|
});
|
|
677
818
|
});
|
|
678
819
|
|
|
820
|
+
describe('typed descriptor conformance', () => {
|
|
821
|
+
it('emits a strongly typed .doc.mjs for every canonical item writer', async () => {
|
|
822
|
+
setup();
|
|
823
|
+
await integrationAdd('component', 'MyWidget', {cwd: tmpDir});
|
|
824
|
+
await integrationAdd('doc', 'my-guide', {cwd: tmpDir});
|
|
825
|
+
await integrationAdd('template', 'my-page', {cwd: tmpDir});
|
|
826
|
+
await integrationAdd('theme', 'ocean', {cwd: tmpDir});
|
|
827
|
+
|
|
828
|
+
// Codemod and agent-doc keep their released formats for compatibility;
|
|
829
|
+
// no new kind may copy those exceptions.
|
|
830
|
+
for (const [relativePath, type] of [
|
|
831
|
+
['components/MyWidget.doc.mjs', 'ComponentDoc'],
|
|
832
|
+
['docs/my-guide.doc.mjs', 'ReferenceDoc'],
|
|
833
|
+
['templates/my-page.doc.mjs', 'TemplateDoc'],
|
|
834
|
+
['themes/ocean/oceanTheme.doc.mjs', 'ThemeDoc'],
|
|
835
|
+
]) {
|
|
836
|
+
const source = fs.readFileSync(path.join(tmpDir, relativePath), 'utf-8');
|
|
837
|
+
expect(source).toContain(`@astryxdesign/cli/authoring').${type}`);
|
|
838
|
+
expect(source).toContain('export default {');
|
|
839
|
+
}
|
|
840
|
+
expect(
|
|
841
|
+
fs.existsSync(path.join(tmpDir, 'templates/my-page.template.mjs')),
|
|
842
|
+
).toBe(false);
|
|
843
|
+
expect(fs.existsSync(path.join(tmpDir, 'themes/manifest.json'))).toBe(
|
|
844
|
+
false,
|
|
845
|
+
);
|
|
846
|
+
});
|
|
847
|
+
});
|
|
848
|
+
|
|
679
849
|
describe('public per-kind APIs', () => {
|
|
680
850
|
it('exposes narrow functions for every non-theme contribution kind', async () => {
|
|
681
851
|
setup();
|
|
@@ -711,6 +881,7 @@ describe('public dispatcher', () => {
|
|
|
711
881
|
const result = await integrationAdd('theme', 'ocean', {cwd: tmpDir});
|
|
712
882
|
expect(result.data).toMatchObject({kind: 'theme', name: 'ocean'});
|
|
713
883
|
expect(result.data.files).toContain('themes/ocean/oceanTheme.ts');
|
|
884
|
+
expect(result.data.files).toContain('themes/ocean/oceanTheme.doc.mjs');
|
|
714
885
|
});
|
|
715
886
|
|
|
716
887
|
it('refuses a kind-specific option on the wrong kind', async () => {
|
|
@@ -731,3 +902,83 @@ describe('public dispatcher', () => {
|
|
|
731
902
|
).rejects.toThrow(/component, doc, template, codemod, agent-doc, or theme/);
|
|
732
903
|
});
|
|
733
904
|
});
|
|
905
|
+
|
|
906
|
+
describe('dry-run receipts match the real write', () => {
|
|
907
|
+
/** Package states each writer has to plan for. */
|
|
908
|
+
const STATES = {
|
|
909
|
+
'no manifest': {pkg: {files: ['dist']}},
|
|
910
|
+
'an empty manifest': {pkg: {}, manifest: 'export default {};\n'},
|
|
911
|
+
'declared roots and an exports map': {
|
|
912
|
+
pkg: {files: ['dist'], exports: {'.': './dist/index.js'}},
|
|
913
|
+
manifest:
|
|
914
|
+
"export default {\n components: './components',\n docs: './docs',\n templates: './templates',\n codemods: './codemods',\n themes: './themes',\n};\n",
|
|
915
|
+
},
|
|
916
|
+
};
|
|
917
|
+
/** @type {Array<[any, string, Record<string, unknown>]>} */
|
|
918
|
+
const KINDS = [
|
|
919
|
+
['component', 'AcmeWidget', {}],
|
|
920
|
+
['doc', 'deploying', {}],
|
|
921
|
+
['template', 'account-page', {}],
|
|
922
|
+
['template', 'account-card', {templateType: 'block'}],
|
|
923
|
+
['codemod', 'rename-widget', {to: '1.2.0'}],
|
|
924
|
+
['agent-doc', 'Run acme verify before finishing.', {}],
|
|
925
|
+
['theme', 'ocean', {}],
|
|
926
|
+
];
|
|
927
|
+
|
|
928
|
+
/** Every file under the package, keyed by project path, with its bytes. */
|
|
929
|
+
function snapshot() {
|
|
930
|
+
/** @type {Record<string, string>} */
|
|
931
|
+
const files = {};
|
|
932
|
+
/** @param {string} dir */
|
|
933
|
+
const walk = dir => {
|
|
934
|
+
for (const entry of fs.readdirSync(dir, {withFileTypes: true})) {
|
|
935
|
+
const full = path.join(dir, entry.name);
|
|
936
|
+
if (entry.isDirectory()) walk(full);
|
|
937
|
+
else {
|
|
938
|
+
files[path.relative(tmpDir, full).split(path.sep).join('/')] =
|
|
939
|
+
fs.readFileSync(full, 'base64');
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
};
|
|
943
|
+
walk(tmpDir);
|
|
944
|
+
return files;
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
for (const [stateName, state] of Object.entries(STATES)) {
|
|
948
|
+
for (const [kind, name, options] of KINDS) {
|
|
949
|
+
it(`${kind} ${name} in a package with ${stateName}`, async () => {
|
|
950
|
+
fs.writeFileSync(
|
|
951
|
+
path.join(tmpDir, 'package.json'),
|
|
952
|
+
`${JSON.stringify({name: '@acme/integration', version: '1.0.0', ...state.pkg}, null, 2)}\n`,
|
|
953
|
+
);
|
|
954
|
+
if (state.manifest != null) {
|
|
955
|
+
fs.writeFileSync(
|
|
956
|
+
path.join(tmpDir, 'astryx.integration.mjs'),
|
|
957
|
+
state.manifest,
|
|
958
|
+
);
|
|
959
|
+
}
|
|
960
|
+
const before = snapshot();
|
|
961
|
+
|
|
962
|
+
const plan = await integrationAdd(kind, name, {
|
|
963
|
+
cwd: tmpDir,
|
|
964
|
+
dryRun: true,
|
|
965
|
+
...options,
|
|
966
|
+
});
|
|
967
|
+
expect(snapshot()).toEqual(before);
|
|
968
|
+
|
|
969
|
+
const written = await integrationAdd(kind, name, {
|
|
970
|
+
cwd: tmpDir,
|
|
971
|
+
...options,
|
|
972
|
+
});
|
|
973
|
+
const after = snapshot();
|
|
974
|
+
const changed = Object.keys(after)
|
|
975
|
+
.filter(file => after[file] !== before[file])
|
|
976
|
+
.sort();
|
|
977
|
+
|
|
978
|
+
expect(written.data.root).toEqual(plan.data.root);
|
|
979
|
+
expect(written.data.files).toEqual(plan.data.files);
|
|
980
|
+
expect([...written.data.files].sort()).toEqual(changed);
|
|
981
|
+
});
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
});
|
|
@@ -8,7 +8,7 @@ export function findPackageDir(startDir: string): string;
|
|
|
8
8
|
/**
|
|
9
9
|
* @typedef {object} WritePlan
|
|
10
10
|
* @property {string} path
|
|
11
|
-
* @property {string} contents
|
|
11
|
+
* @property {string | Buffer} contents a Buffer is written byte for byte
|
|
12
12
|
* @property {boolean} createOnly
|
|
13
13
|
* @property {Buffer} [expectedOriginal] bytes captured before validation;
|
|
14
14
|
* a different current file is a concurrent edit and must never be overwritten
|
|
@@ -56,7 +56,10 @@ export function packageJsonUpdate(packageFile: string, rootPath: string, manifes
|
|
|
56
56
|
export function applyWrites(plans: WritePlan[]): () => void;
|
|
57
57
|
export type WritePlan = {
|
|
58
58
|
path: string;
|
|
59
|
-
|
|
59
|
+
/**
|
|
60
|
+
* a Buffer is written byte for byte
|
|
61
|
+
*/
|
|
62
|
+
contents: string | Buffer;
|
|
60
63
|
createOnly: boolean;
|
|
61
64
|
/**
|
|
62
65
|
* bytes captured before validation;
|