@astryxdesign/cli 0.6.3-canary.ea2f048 → 0.6.3-canary.f04b501
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +106 -72
- package/api/blog/blog.doc.mjs +1 -0
- package/api/build/build.doc.mjs +4 -3
- package/api/build/build.test.mjs +14 -3
- package/api/build/build.type.d.mts +36 -2
- package/api/build/build.type.mjs +25 -4
- package/api/build/help/help.d.mts +8 -5
- package/api/build/help/help.mjs +56 -6
- package/api/component/component.doc.mjs +13 -3
- package/api/component/component.mjs +31 -2
- 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 +37 -9
- package/api/discover/discover.doc.mjs +2 -1
- package/api/discover/discover.type.d.mts +4 -4
- package/api/discover/discover.type.mjs +10 -10
- package/api/docs/_adapter.d.mts +32 -24
- package/api/docs/_adapter.mjs +81 -87
- package/api/docs/compiled-topics.test.mjs +78 -0
- package/api/docs/detail/detail.mjs +14 -63
- package/api/docs/detail/section/section.d.mts +1 -1
- package/api/docs/detail/section/section.mjs +44 -20
- package/api/docs/detail/section/section.test.mjs +41 -0
- package/api/docs/docs.d.mts +7 -2
- package/api/docs/docs.doc.mjs +28 -10
- package/api/docs/docs.mjs +16 -9
- package/api/docs/docs.test.mjs +6 -0
- package/api/docs/docs.type.d.mts +40 -3
- package/api/docs/docs.type.mjs +36 -8
- package/api/docs/index/index.d.mts +18 -0
- package/api/docs/index/index.mjs +32 -0
- package/api/docs/index/index.test.mjs +62 -0
- package/api/docs/integrationDocs.test.mjs +106 -0
- package/api/docs/list/list.mjs +3 -7
- package/api/doctor/doctor.d.mts +70 -0
- package/api/doctor/doctor.doc.mjs +1 -0
- package/api/doctor/doctor.mjs +404 -0
- package/api/doctor/doctor.test.mjs +522 -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/init/init.doc.mjs +5 -0
- 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.mjs +23 -10
- package/api/integration/add-contribution.test.mjs +121 -7
- package/api/integration/add-theme.mjs +34 -64
- package/api/integration/add-theme.test.mjs +105 -21
- package/api/integration/authoring-checks.test.mjs +8 -4
- package/api/integration/integration-authoring.type.d.mts +1 -1
- package/api/integration/integration-block-exports.test.mjs +10 -6
- package/api/integration/integrationAdd.doc.mjs +8 -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 +1 -0
- 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 +1 -0
- package/api/integration/integrationPackCheck.doc.mjs +1 -0
- package/api/integration/integrationTemplateConflicts.doc.mjs +1 -0
- package/api/integration/pack-check.mjs +49 -7
- package/api/integration/pack-check.test.mjs +266 -47
- package/api/integration/summarizeIssues.doc.mjs +1 -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 +176 -23
- package/api/integration/validate-unread-theme-folders.test.mjs +110 -0
- package/api/integration/validateIntegration.doc.mjs +2 -1
- package/api/json/assertResponse.doc.mjs +1 -0
- package/api/json/envelope-types.test.mjs +76 -0
- package/api/json/isError.doc.mjs +1 -0
- package/api/json/parseResponse.doc.mjs +3 -2
- 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 +3 -10
- package/api/search/search.doc.mjs +6 -1
- package/api/search/search.mjs +31 -14
- package/api/search/search.test.mjs +34 -0
- package/api/search/search.type.d.mts +2 -2
- package/api/search/search.type.mjs +1 -1
- 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/template-suffix.test.mjs +41 -21
- package/api/template/template.d.mts +1 -1
- package/api/template/template.doc.mjs +3 -1
- package/api/template/template.type.d.mts +6 -6
- package/api/template/template.type.mjs +12 -12
- 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 +20 -3
- package/api/theme/add/add.staging.test.mjs +66 -0
- package/api/theme/add/add.test.mjs +14 -1
- package/api/theme/build/build.mjs +133 -42
- 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.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 +15 -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 +5 -1
- package/api/upgrade/_adapter.d.mts +12 -3
- package/api/upgrade/_adapter.mjs +123 -19
- 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 +1 -0
- package/api/upgrade/status/status.mjs +2 -2
- package/api/upgrade/upgrade.doc.mjs +7 -4
- package/api/upgrade/upgrade.type.d.mts +9 -5
- package/api/upgrade/upgrade.type.mjs +12 -11
- package/assets/codemods/integration-discovery.mjs +48 -4
- package/assets/codemods/integration-discovery.test.mjs +73 -0
- package/assets/codemods/runner.mjs +115 -5
- package/assets/codemods/term-log.mjs +32 -8
- package/assets/codemods/term-log.test.mjs +19 -1
- package/assets/codemods/transform-prop.mjs +109 -0
- package/assets/codemods/transform-prop.test.mjs +95 -0
- package/assets/codemods/transforms/next/__tests__/migrate-theme-catalog-to-descriptors.test.mjs +216 -0
- package/assets/codemods/transforms/next/index.mjs +11 -1
- package/assets/codemods/transforms/next/migrate-theme-catalog-to-descriptors.mjs +141 -0
- package/assets/codemods/transforms/v0.0.14/__tests__/rename-status-variants.test.mjs +86 -165
- package/assets/codemods/transforms/v0.0.14/rename-status-variants.mjs +72 -210
- package/assets/codemods/transforms/v0.1.8/__tests__/rename-avatar-size-scale.test.mjs +83 -115
- package/assets/codemods/transforms/v0.1.8/rename-avatar-size-scale.mjs +57 -186
- package/assets/codemods/transforms/v0.3.0/__tests__/unwrap-authoring-factories.test.mjs +27 -5
- package/assets/codemods/transforms/v0.3.0/unwrap-authoring-factories.mjs +20 -5
- package/assets/codemods/transforms/v0.6.0/__tests__/next-codemods.test.mjs +47 -0
- package/assets/codemods/transforms/v0.6.0/rename-resizable-pixel-bounds.mjs +57 -10
- package/assets/docs/README.md +9 -0
- package/assets/docs/authoring.doc.mjs +14 -0
- package/assets/docs/cli-integrations.doc.mjs +78 -20
- package/assets/docs/cli.doc.mjs +15 -0
- package/assets/docs/styling-libraries.doc.mjs +1 -1
- package/assets/docs/theme.doc.mjs +1 -1
- package/assets/docs/working-with-ai.doc.mjs +1 -1
- 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/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/config/config.doc.mjs +2 -2
- package/authoring/config/debug-composition.test.mjs +92 -0
- package/authoring/config/parse.d.mts +13 -13
- package/authoring/config/parse.mjs +8 -8
- package/authoring/config/type.ts +18 -6
- package/authoring/debug/debug.doc.d.mts +11 -0
- package/authoring/debug/debug.doc.mjs +182 -0
- package/authoring/debug/parse.d.mts +5 -5
- package/authoring/debug/parse.mjs +3 -3
- package/authoring/doctypes/_schema.d.mts +788 -23
- package/authoring/doctypes/_schema.mjs +492 -39
- package/authoring/doctypes/base/graph-fields.doc.d.mts +9 -0
- package/authoring/doctypes/base/graph-fields.doc.mjs +62 -0
- package/authoring/doctypes/base/type.ts +40 -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 +4 -3
- 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 +5 -1
- package/authoring/doctypes/function/parse.d.mts +2 -2
- package/authoring/doctypes/function/parse.mjs +1 -1
- package/authoring/doctypes/function/type.ts +7 -3
- package/authoring/doctypes/hook/hook.doc.mjs +4 -0
- package/authoring/doctypes/hook/parse.d.mts +2 -2
- package/authoring/doctypes/hook/parse.mjs +1 -1
- package/authoring/doctypes/hook/type.ts +5 -4
- package/authoring/doctypes/legacy.d.mts +8 -6
- package/authoring/doctypes/legacy.mjs +5 -4
- package/authoring/doctypes/load-contract.test.mjs +208 -0
- package/authoring/doctypes/namespace/namespace.doc.d.mts +9 -0
- package/authoring/doctypes/namespace/namespace.doc.mjs +132 -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 +165 -0
- package/authoring/doctypes/namespace/type.ts +71 -0
- package/authoring/doctypes/parse.d.mts +22 -18
- package/authoring/doctypes/parse.mjs +22 -12
- 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 +18 -5
- package/authoring/doctypes/reference/type.ts +53 -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 +92 -1
- package/authoring/doctypes/template/parse.mjs +36 -2
- package/authoring/doctypes/template/parse.test.mjs +8 -2
- package/authoring/doctypes/template/template.doc.mjs +7 -3
- package/authoring/doctypes/template/type.ts +5 -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 +2 -0
- package/authoring/index.d.ts +51 -17
- package/authoring/index.mjs +3 -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 +18 -7
- 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.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 +5 -5
- 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 +5 -2
- package/clients/cli/commands/build.exit-codes-doc.test.mjs +50 -0
- package/clients/cli/commands/build.mjs +32 -47
- package/clients/cli/commands/build.playbook.test.mjs +75 -0
- package/clients/cli/commands/build.text-fields.test.mjs +40 -0
- package/clients/cli/commands/component/index.mjs +2 -7
- 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 +48 -0
- package/clients/cli/commands/discover.components-flag.test.mjs +97 -0
- package/clients/cli/commands/discover.doc.mjs +5 -3
- package/clients/cli/commands/discover.mjs +3 -3
- package/clients/cli/commands/discover.text-projection.test.mjs +103 -0
- package/clients/cli/commands/docs.doc.mjs +14 -4
- package/clients/cli/commands/docs.mjs +121 -21
- package/clients/cli/commands/docs.test.mjs +88 -0
- package/clients/cli/commands/doctor-integration-components.doc.mjs +1 -1
- package/clients/cli/commands/doctor-integration-docs.doc.mjs +1 -1
- package/clients/cli/commands/doctor-integration-templates.doc.mjs +1 -1
- 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 +15 -7
- package/clients/cli/commands/doctor.doc.mjs +1 -1
- package/clients/cli/commands/doctor.mjs +6 -16
- 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 +22 -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/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 +17 -7
- package/clients/cli/commands/search.test.mjs +75 -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 +29 -7
- package/clients/cli/commands/template.flag-help.test.mjs +117 -0
- package/clients/cli/commands/template.path-help.test.mjs +40 -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.doc.mjs +1 -1
- package/clients/cli/commands/theme-template.behavior.test.mjs +12 -0
- package/clients/cli/commands/theme-template.doc.mjs +2 -2
- package/clients/cli/commands/theme.doc.mjs +1 -1
- package/clients/cli/commands/upgrade.ascii-output.test.mjs +87 -0
- package/clients/cli/commands/upgrade.doc.mjs +20 -9
- 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/formatters/index.mjs +162 -1
- package/clients/cli/formatters/index.test.mjs +91 -0
- package/clients/cli/index.mjs +13 -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 +29 -2
- package/clients/cli/lib/manifest.test.mjs +17 -0
- package/foundation/agent-docs/agent-docs.d.mts +4 -0
- package/foundation/agent-docs/agent-docs.mjs +69 -3
- package/foundation/agent-docs/agent-docs.path-safety.test.mjs +266 -4
- package/foundation/config/integration-debug.test.mjs +28 -3
- package/foundation/config/project-themes.test.mjs +11 -19
- package/foundation/config/project.d.mts +8 -0
- package/foundation/config/project.mjs +190 -32
- package/foundation/config/project.test.mjs +129 -16
- package/foundation/discovery/authoring-self-docs.d.mts +75 -0
- package/foundation/discovery/authoring-self-docs.mjs +224 -0
- package/foundation/discovery/authoring-self-docs.test.mjs +154 -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 +113 -0
- package/foundation/discovery/cli-self-docs.mjs +514 -0
- package/foundation/discovery/cli-self-docs.test.mjs +437 -0
- package/foundation/discovery/component-discovery.d.mts +1 -1
- package/foundation/discovery/component-discovery.mjs +2 -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 +12 -4
- package/foundation/discovery/docs-discovery.mjs +214 -98
- package/foundation/discovery/docs-discovery.test.mjs +284 -15
- 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 +98 -0
- package/foundation/discovery/docs-section-key.mjs +221 -0
- package/foundation/discovery/docs-section-key.test.mjs +224 -0
- package/foundation/discovery/template-adapter.d.mts +21 -5
- 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 +321 -66
- package/foundation/discovery/template-adapter.test.mjs +15 -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 +218 -0
- package/foundation/doc-compiler/bundle.test.mjs +255 -0
- package/foundation/doc-compiler/compile.d.mts +362 -0
- package/foundation/doc-compiler/compile.mjs +511 -0
- package/foundation/doc-compiler/diagnostics.d.mts +126 -0
- package/foundation/doc-compiler/diagnostics.mjs +277 -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 +286 -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 +464 -0
- package/foundation/doc-compiler/lenses.d.mts +33 -0
- package/foundation/doc-compiler/lenses.mjs +127 -0
- package/foundation/doc-compiler/lower-doc.test.mjs +492 -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 +126 -0
- package/foundation/doc-compiler/read.mjs +320 -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/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/contribution-fixes.d.mts +145 -0
- package/foundation/integrations/contribution-fixes.mjs +1284 -0
- package/foundation/integrations/contribution-inventory.d.mts +1 -1
- package/foundation/integrations/contribution-inventory.mjs +17 -20
- package/foundation/integrations/contribution-inventory.test.mjs +67 -27
- package/foundation/integrations/integration-warnings.mjs +6 -0
- package/foundation/integrations/integrations.d.mts +49 -2
- package/foundation/integrations/integrations.mjs +81 -8
- package/foundation/integrations/integrations.test.mjs +384 -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 +114 -10
- package/foundation/response/base.d.ts +8 -4
- package/foundation/response/error-codes.doc.mjs +3 -4
- package/foundation/response/error-codes.mjs +2 -2
- package/foundation/response/error-codes.test.mjs +83 -0
- 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.mjs +16 -11
- package/foundation/response/response-types.doc.test.mjs +158 -0
- package/foundation/response/response.doc.mjs +1 -1
- package/foundation/text/string-utils.mjs +22 -10
- package/foundation/xle/expand.d.mts +2 -0
- package/foundation/xle/expand.mjs +3 -2
- package/foundation/xle/expand.test.mjs +54 -0
- package/package.json +9 -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
package/api/hook/hook.type.mjs
CHANGED
|
@@ -11,14 +11,14 @@
|
|
|
11
11
|
*
|
|
12
12
|
* Invocation -> type discriminator
|
|
13
13
|
* ------------------------------------------------------------------
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* (not found)
|
|
14
|
+
* astryx --json hook -> hook.list (data.detail='names')
|
|
15
|
+
* astryx --json hook --list -> hook.list (data.detail='names')
|
|
16
|
+
* astryx --json hook --category State -> hook.list (filtered)
|
|
17
|
+
* astryx --json hook --list --detail compact -> hook.list (data.detail='compact')
|
|
18
|
+
* astryx --json hook --list --detail full -> hook.list (data.detail='full')
|
|
19
|
+
* astryx --json hook useMediaQuery -> hook.detail
|
|
20
|
+
* astryx --json hook useMediaQuery --params -> hook.detail.params
|
|
21
|
+
* (not found) -> CLIError
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
24
|
// Re-export the authored-doc types from core so the hook leaves reference these
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
/** @typedef {import('@astryxdesign/cli/authoring').HookParamDoc} HookParamDoc */
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
|
-
*
|
|
31
|
+
* astryx --json hook [--list] [--category X] [--detail names|compact|full]
|
|
32
32
|
*
|
|
33
33
|
* The list view emits ONE `hook.list` type across all three detail levels; the
|
|
34
34
|
* depth is carried in `data.detail` and `data.components` holds the grouped map
|
|
@@ -56,14 +56,14 @@
|
|
|
56
56
|
*/
|
|
57
57
|
|
|
58
58
|
/**
|
|
59
|
-
*
|
|
59
|
+
* astryx --json hook <name>
|
|
60
60
|
* @typedef {object} HookDetailResponse
|
|
61
61
|
* @property {'hook.detail'} type
|
|
62
62
|
* @property {HookDoc} data
|
|
63
63
|
*/
|
|
64
64
|
|
|
65
65
|
/**
|
|
66
|
-
*
|
|
66
|
+
* astryx --json hook <name> --params
|
|
67
67
|
* @typedef {object} HookDetailParamsResponse
|
|
68
68
|
* @property {'hook.detail.params'} type
|
|
69
69
|
* @property {HookParamDoc[]} data
|
package/api/hook/list/list.d.mts
CHANGED
|
@@ -10,10 +10,10 @@
|
|
|
10
10
|
* @param {string|null} [options.lang]
|
|
11
11
|
* @returns {Promise<import('../hook.type.mjs').HookListResponse>}
|
|
12
12
|
*/
|
|
13
|
-
export function list({ cwd, category, detail, zh, lang }?: {
|
|
13
|
+
export function list({ cwd, category, detail, zh, lang, }?: {
|
|
14
14
|
cwd?: string | undefined;
|
|
15
15
|
category?: string | undefined;
|
|
16
|
-
detail?: "
|
|
16
|
+
detail?: "compact" | "full" | "names" | "brief" | undefined;
|
|
17
17
|
zh?: boolean | undefined;
|
|
18
18
|
lang?: string | null | undefined;
|
|
19
19
|
}): Promise<import("../hook.type.mjs").HookListResponse>;
|
package/api/hook/list/list.mjs
CHANGED
|
@@ -13,7 +13,10 @@
|
|
|
13
13
|
* @position api/hook/list/list.mjs — dispatched from ../hook.mjs
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
discoverHooks,
|
|
18
|
+
findHookDoc,
|
|
19
|
+
} from '../../../foundation/discovery/hook-discovery.mjs';
|
|
17
20
|
import {loadDocs} from '../../../foundation/discovery/component-loader.mjs';
|
|
18
21
|
import {AstryxError} from '../../error.mjs';
|
|
19
22
|
import {ERROR_CODES} from '../../../foundation/response/error-codes.mjs';
|
|
@@ -28,7 +31,13 @@ import {resolveCoreDir} from '../_adapter.mjs';
|
|
|
28
31
|
* @param {string|null} [options.lang]
|
|
29
32
|
* @returns {Promise<import('../hook.type.mjs').HookListResponse>}
|
|
30
33
|
*/
|
|
31
|
-
export async function list({
|
|
34
|
+
export async function list({
|
|
35
|
+
cwd = process.cwd(),
|
|
36
|
+
category,
|
|
37
|
+
detail = 'names',
|
|
38
|
+
zh = false,
|
|
39
|
+
lang = null,
|
|
40
|
+
} = {}) {
|
|
32
41
|
const coreDir = resolveCoreDir(cwd);
|
|
33
42
|
const hooks = discoverHooks(coreDir);
|
|
34
43
|
|
|
@@ -51,20 +60,31 @@ export async function list({cwd = process.cwd(), category, detail = 'names', zh
|
|
|
51
60
|
const docPath = findHookDoc(coreDir, hookName);
|
|
52
61
|
if (docPath) {
|
|
53
62
|
try {
|
|
54
|
-
const docs = await loadDocs(docPath,
|
|
63
|
+
const docs = await loadDocs(docPath, {zh, lang, root: 'hooks'});
|
|
55
64
|
entries.push({
|
|
56
65
|
name: hookName,
|
|
57
66
|
description: docs.usage?.description || '',
|
|
58
67
|
import: docs.importPath || '@astryxdesign/core/hooks',
|
|
59
68
|
});
|
|
60
69
|
} catch {
|
|
61
|
-
entries.push({
|
|
70
|
+
entries.push({
|
|
71
|
+
name: hookName,
|
|
72
|
+
description: '',
|
|
73
|
+
import: '@astryxdesign/core/hooks',
|
|
74
|
+
});
|
|
62
75
|
}
|
|
63
76
|
} else {
|
|
64
|
-
entries.push({
|
|
77
|
+
entries.push({
|
|
78
|
+
name: hookName,
|
|
79
|
+
description: '',
|
|
80
|
+
import: '@astryxdesign/core/hooks',
|
|
81
|
+
});
|
|
65
82
|
}
|
|
66
83
|
}
|
|
67
|
-
return {
|
|
84
|
+
return {
|
|
85
|
+
type: 'hook.list',
|
|
86
|
+
data: {detail: 'compact', components: {[match[0]]: entries}},
|
|
87
|
+
};
|
|
68
88
|
}
|
|
69
89
|
|
|
70
90
|
if (detail === 'full') {
|
|
@@ -74,19 +94,33 @@ export async function list({cwd = process.cwd(), category, detail = 'names', zh
|
|
|
74
94
|
const docPath = findHookDoc(coreDir, hookName);
|
|
75
95
|
if (docPath) {
|
|
76
96
|
try {
|
|
77
|
-
entries.push(await loadDocs(docPath,
|
|
97
|
+
entries.push(await loadDocs(docPath, {zh, lang, root: 'hooks'}));
|
|
78
98
|
} catch {
|
|
79
|
-
entries.push(
|
|
99
|
+
entries.push(
|
|
100
|
+
/** @type {import('../hook.type.mjs').HookDoc} */ ({
|
|
101
|
+
name: hookName,
|
|
102
|
+
}),
|
|
103
|
+
);
|
|
80
104
|
}
|
|
81
105
|
} else {
|
|
82
|
-
entries.push(
|
|
106
|
+
entries.push(
|
|
107
|
+
/** @type {import('../hook.type.mjs').HookDoc} */ ({
|
|
108
|
+
name: hookName,
|
|
109
|
+
}),
|
|
110
|
+
);
|
|
83
111
|
}
|
|
84
112
|
}
|
|
85
|
-
return {
|
|
113
|
+
return {
|
|
114
|
+
type: 'hook.list',
|
|
115
|
+
data: {detail: 'full', components: {[match[0]]: entries}},
|
|
116
|
+
};
|
|
86
117
|
}
|
|
87
118
|
|
|
88
119
|
// Default: names only
|
|
89
|
-
return {
|
|
120
|
+
return {
|
|
121
|
+
type: 'hook.list',
|
|
122
|
+
data: {detail: 'names', components: {[match[0]]: match[1]}},
|
|
123
|
+
};
|
|
90
124
|
}
|
|
91
125
|
|
|
92
126
|
// All hooks
|
|
@@ -99,17 +133,25 @@ export async function list({cwd = process.cwd(), category, detail = 'names', zh
|
|
|
99
133
|
const docPath = findHookDoc(coreDir, hookName);
|
|
100
134
|
if (docPath) {
|
|
101
135
|
try {
|
|
102
|
-
const docs = await loadDocs(docPath,
|
|
136
|
+
const docs = await loadDocs(docPath, {zh, lang, root: 'hooks'});
|
|
103
137
|
result[cat].push({
|
|
104
138
|
name: hookName,
|
|
105
139
|
description: docs.usage?.description || '',
|
|
106
140
|
import: docs.importPath || '@astryxdesign/core/hooks',
|
|
107
141
|
});
|
|
108
142
|
} catch {
|
|
109
|
-
result[cat].push({
|
|
143
|
+
result[cat].push({
|
|
144
|
+
name: hookName,
|
|
145
|
+
description: '',
|
|
146
|
+
import: '@astryxdesign/core/hooks',
|
|
147
|
+
});
|
|
110
148
|
}
|
|
111
149
|
} else {
|
|
112
|
-
result[cat].push({
|
|
150
|
+
result[cat].push({
|
|
151
|
+
name: hookName,
|
|
152
|
+
description: '',
|
|
153
|
+
import: '@astryxdesign/core/hooks',
|
|
154
|
+
});
|
|
113
155
|
}
|
|
114
156
|
}
|
|
115
157
|
}
|
|
@@ -125,12 +167,22 @@ export async function list({cwd = process.cwd(), category, detail = 'names', zh
|
|
|
125
167
|
const docPath = findHookDoc(coreDir, hookName);
|
|
126
168
|
if (docPath) {
|
|
127
169
|
try {
|
|
128
|
-
result[cat].push(
|
|
170
|
+
result[cat].push(
|
|
171
|
+
await loadDocs(docPath, {zh, lang, root: 'hooks'}),
|
|
172
|
+
);
|
|
129
173
|
} catch {
|
|
130
|
-
result[cat].push(
|
|
174
|
+
result[cat].push(
|
|
175
|
+
/** @type {import('../hook.type.mjs').HookDoc} */ ({
|
|
176
|
+
name: hookName,
|
|
177
|
+
}),
|
|
178
|
+
);
|
|
131
179
|
}
|
|
132
180
|
} else {
|
|
133
|
-
result[cat].push(
|
|
181
|
+
result[cat].push(
|
|
182
|
+
/** @type {import('../hook.type.mjs').HookDoc} */ ({
|
|
183
|
+
name: hookName,
|
|
184
|
+
}),
|
|
185
|
+
);
|
|
134
186
|
}
|
|
135
187
|
}
|
|
136
188
|
}
|
package/api/init/init.doc.mjs
CHANGED
|
@@ -11,6 +11,7 @@ export const doc = {
|
|
|
11
11
|
type: 'function',
|
|
12
12
|
kind: 'api',
|
|
13
13
|
name: 'init',
|
|
14
|
+
namespace: 'cli/api',
|
|
14
15
|
displayName: 'init()',
|
|
15
16
|
summary:
|
|
16
17
|
'Non-interactive project setup: install agent docs and point at the theme + build workflows.',
|
|
@@ -90,6 +91,10 @@ export const doc = {
|
|
|
90
91
|
code: 'ERR_FILE_EXISTS',
|
|
91
92
|
when: 'scaffolding a template would overwrite an existing page.tsx',
|
|
92
93
|
},
|
|
94
|
+
{
|
|
95
|
+
code: 'ERR_PATH_TRAVERSAL',
|
|
96
|
+
when: 'the template output path resolves outside cwd, for example through a symlinked src directory',
|
|
97
|
+
},
|
|
93
98
|
],
|
|
94
99
|
examples: [
|
|
95
100
|
{label: 'Default setup', code: 'const r = await init();'},
|
package/api/init/init.test.mjs
CHANGED
|
@@ -230,13 +230,40 @@ describe('init() — logger', () => {
|
|
|
230
230
|
errSpy.mockRestore();
|
|
231
231
|
}
|
|
232
232
|
const text = lines.join('\n');
|
|
233
|
-
expect(text).toContain('
|
|
233
|
+
expect(text).toContain('[ok] AI agent docs installed -> AGENTS.md');
|
|
234
234
|
expect(text).toContain(' Next steps:');
|
|
235
235
|
// The exact next-steps block the CLI prints comes from getNextSteps().
|
|
236
236
|
expect(text).toContain(getNextSteps('npx astryx')[2].slice(0, 20));
|
|
237
237
|
});
|
|
238
238
|
});
|
|
239
239
|
|
|
240
|
+
describe('init() — ASCII output', () => {
|
|
241
|
+
it('prints only ASCII on the default, all-features, re-run, template, and remove paths', async () => {
|
|
242
|
+
/** @type {string[]} */
|
|
243
|
+
const lines = [];
|
|
244
|
+
const logSpy = vi.spyOn(console, 'log').mockImplementation((...a) => lines.push(a.join(' ')));
|
|
245
|
+
const errSpy = vi.spyOn(console, 'error').mockImplementation((...a) => lines.push(a.join(' ')));
|
|
246
|
+
const empty = fs.mkdtempSync(path.join(process.cwd(), '.astryx-init-remove-'));
|
|
247
|
+
logger.setSilent(false);
|
|
248
|
+
try {
|
|
249
|
+
await init({}, {cwd: tmpDir});
|
|
250
|
+
await init({all: true}, {cwd: tmpDir});
|
|
251
|
+
await init({all: true}, {cwd: tmpDir});
|
|
252
|
+
await init({features: 'template', templateName: 'blank'}, {cwd: tmpDir});
|
|
253
|
+
await init({removeAgents: true}, {cwd: tmpDir});
|
|
254
|
+
await init({removeAgents: true}, {cwd: empty});
|
|
255
|
+
} finally {
|
|
256
|
+
logger.setSilent(true);
|
|
257
|
+
logSpy.mockRestore();
|
|
258
|
+
errSpy.mockRestore();
|
|
259
|
+
fs.rmSync(empty, {recursive: true, force: true});
|
|
260
|
+
}
|
|
261
|
+
expect(lines.length).toBeGreaterThan(0);
|
|
262
|
+
expect(lines.some(line => line.startsWith('[ok] Removed'))).toBe(true);
|
|
263
|
+
expect(lines.filter(line => /[\u0080-\uFFFF]/.test(line))).toEqual([]);
|
|
264
|
+
});
|
|
265
|
+
});
|
|
266
|
+
|
|
240
267
|
describe('init() — write-path safety', () => {
|
|
241
268
|
it('template scaffold refuses to clobber an existing page.tsx', async () => {
|
|
242
269
|
const dest = path.join(tmpDir, 'src', 'pages', 'blank');
|
|
@@ -260,4 +287,17 @@ describe('init() — write-path safety', () => {
|
|
|
260
287
|
init({features: 'template', templateName: '../../etc/evil'}, {cwd: tmpDir}),
|
|
261
288
|
).rejects.toMatchObject({code: ERROR_CODES.ERR_UNKNOWN_TEMPLATE});
|
|
262
289
|
});
|
|
290
|
+
|
|
291
|
+
it('refuses a template write that a symlinked src would carry outside cwd (ERR_PATH_TRAVERSAL)', async () => {
|
|
292
|
+
const outside = fs.mkdtempSync(path.join(process.cwd(), '.astryx-init-outside-'));
|
|
293
|
+
try {
|
|
294
|
+
fs.symlinkSync(outside, path.join(tmpDir, 'src'), 'dir');
|
|
295
|
+
await expect(
|
|
296
|
+
init({features: 'template', templateName: 'blank'}, {cwd: tmpDir}),
|
|
297
|
+
).rejects.toMatchObject({code: ERROR_CODES.ERR_PATH_TRAVERSAL});
|
|
298
|
+
expect(fs.readdirSync(outside)).toEqual([]);
|
|
299
|
+
} finally {
|
|
300
|
+
fs.rmSync(outside, {recursive: true, force: true});
|
|
301
|
+
}
|
|
302
|
+
});
|
|
263
303
|
});
|
|
@@ -24,6 +24,6 @@ import {logger} from '../../logger.mjs';
|
|
|
24
24
|
*/
|
|
25
25
|
export async function remove({cwd = process.cwd()} = {}) {
|
|
26
26
|
removeAgentDocs(cwd);
|
|
27
|
-
logger.log('
|
|
27
|
+
logger.log('[ok] AI agent docs removed.');
|
|
28
28
|
return {type: 'init.remove', data: {removed: true}};
|
|
29
29
|
}
|
package/api/init/run/run.mjs
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
import * as path from 'node:path';
|
|
18
18
|
import * as fs from 'node:fs';
|
|
19
19
|
import {CLI_ROOT} from '../../../foundation/fs/paths.mjs';
|
|
20
|
-
import {PathSafetyError} from '../../../foundation/fs/path-safety.mjs';
|
|
20
|
+
import {PathSafetyError, assertWithin} from '../../../foundation/fs/path-safety.mjs';
|
|
21
21
|
import {getCliInvocation} from '../../../foundation/env/package-manager.mjs';
|
|
22
22
|
import {
|
|
23
23
|
installAgentDocs,
|
|
@@ -98,7 +98,7 @@ async function applyAgents(cwd, options, invocation, data) {
|
|
|
98
98
|
renderedBlock,
|
|
99
99
|
});
|
|
100
100
|
data.docsWritten = written;
|
|
101
|
-
logger.log(
|
|
101
|
+
logger.log(`[ok] AI agent docs installed -> ${written.join(', ')}`);
|
|
102
102
|
} catch (err) {
|
|
103
103
|
// PathSafetyError carries a precise, user-actionable message — surface it
|
|
104
104
|
// (and flag exit 1) instead of the generic "could not install" warning so
|
|
@@ -132,8 +132,8 @@ function applyTheme(cwd, invocation, data) {
|
|
|
132
132
|
data.themeTemplatePath = didWrite ? written : null;
|
|
133
133
|
logger.log(
|
|
134
134
|
didWrite
|
|
135
|
-
?
|
|
136
|
-
:
|
|
135
|
+
? `[ok] Theme template written -> ${written}`
|
|
136
|
+
: `- ${written} already exists - left as is.`,
|
|
137
137
|
);
|
|
138
138
|
} catch {
|
|
139
139
|
// Soft failure, like agent docs: the guidance below is still useful.
|
|
@@ -166,16 +166,16 @@ function applyTemplate(cwd, {templateName}, invocation, data) {
|
|
|
166
166
|
// Point agents at the build workflow rather than dumping page-template
|
|
167
167
|
// names — `build` surfaces pages AND blocks AND components for an idea,
|
|
168
168
|
// and `build` with no args is the full how-to-build playbook.
|
|
169
|
-
logger.log('
|
|
169
|
+
logger.log('[ok] To build UI, use these commands:');
|
|
170
170
|
logger.log('');
|
|
171
171
|
logger.log(
|
|
172
|
-
` ${invocation} build "<what you're building>" build a page
|
|
172
|
+
` ${invocation} build "<what you're building>" build a page - kit: closest template + blocks + components`,
|
|
173
173
|
);
|
|
174
174
|
logger.log(
|
|
175
175
|
` ${invocation} build the how-to-build workflow (read this first)`,
|
|
176
176
|
);
|
|
177
177
|
logger.log(
|
|
178
|
-
` ${invocation} search <query> find anything
|
|
178
|
+
` ${invocation} search <query> find anything - components, docs, templates, blocks`,
|
|
179
179
|
);
|
|
180
180
|
logger.log('');
|
|
181
181
|
data.template = 'workflow';
|
|
@@ -190,9 +190,19 @@ function applyTemplate(cwd, {templateName}, invocation, data) {
|
|
|
190
190
|
);
|
|
191
191
|
}
|
|
192
192
|
|
|
193
|
-
|
|
193
|
+
let destFile;
|
|
194
|
+
try {
|
|
195
|
+
destFile = assertWithin(path.join('src', 'pages', templateName, 'page.tsx'), cwd, {
|
|
196
|
+
label: 'template output path',
|
|
197
|
+
});
|
|
198
|
+
} catch (err) {
|
|
199
|
+
if (err instanceof PathSafetyError) {
|
|
200
|
+
throw new AstryxError(err.message, undefined, ERROR_CODES.ERR_PATH_TRAVERSAL);
|
|
201
|
+
}
|
|
202
|
+
throw err;
|
|
203
|
+
}
|
|
204
|
+
const outputDir = path.dirname(destFile);
|
|
194
205
|
const srcPath = path.join(CLI_ROOT, 'assets', 'templates', 'pages', templateName, 'page.tsx');
|
|
195
|
-
const destFile = path.join(outputDir, 'page.tsx');
|
|
196
206
|
// Don't clobber a user's existing page — same guard the peer template/copy and
|
|
197
207
|
// theme/add write-leaves apply (init is a public API surface too).
|
|
198
208
|
if (fs.existsSync(destFile)) {
|
|
@@ -206,7 +216,7 @@ function applyTemplate(cwd, {templateName}, invocation, data) {
|
|
|
206
216
|
fs.mkdirSync(outputDir, {recursive: true});
|
|
207
217
|
fs.copyFileSync(srcPath, destFile);
|
|
208
218
|
const rel = path.relative(cwd, outputDir);
|
|
209
|
-
logger.log(
|
|
219
|
+
logger.log(`[ok] Template created at ${rel}/page.tsx`);
|
|
210
220
|
data.template = 'created';
|
|
211
221
|
data.templatePath = rel;
|
|
212
222
|
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
import {afterEach, beforeEach, describe, expect, it} from 'vitest';
|
|
4
|
+
import * as fs from 'node:fs';
|
|
5
|
+
import * as path from 'node:path';
|
|
6
|
+
import {integrationAdd, integrationAddComponent} from './add-contribution.mjs';
|
|
7
|
+
import {discoverIntegrationComponents} from '../../foundation/discovery/component-discovery.mjs';
|
|
8
|
+
|
|
9
|
+
let tmpDir;
|
|
10
|
+
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
tmpDir = fs.mkdtempSync(path.join(process.cwd(), '.astryx-add-component-'));
|
|
13
|
+
fs.writeFileSync(
|
|
14
|
+
path.join(tmpDir, 'package.json'),
|
|
15
|
+
`${JSON.stringify({name: '@acme/widgets', version: '1.0.0', files: ['dist']}, null, 2)}\n`,
|
|
16
|
+
);
|
|
17
|
+
fs.writeFileSync(
|
|
18
|
+
path.join(tmpDir, 'astryx.integration.mjs'),
|
|
19
|
+
"export default {\n components: './components',\n};\n",
|
|
20
|
+
);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
afterEach(() => {
|
|
24
|
+
fs.rmSync(tmpDir, {recursive: true, force: true});
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
/** @param {string} relativeDoc */
|
|
28
|
+
function writeAuthoredComponent(relativeDoc) {
|
|
29
|
+
const doc = path.join(tmpDir, relativeDoc);
|
|
30
|
+
fs.mkdirSync(path.dirname(doc), {recursive: true});
|
|
31
|
+
fs.writeFileSync(
|
|
32
|
+
doc,
|
|
33
|
+
"export default {\n type: 'component',\n name: 'AcmeWidget',\n description: 'The authored AcmeWidget.',\n props: [],\n};\n",
|
|
34
|
+
);
|
|
35
|
+
fs.writeFileSync(
|
|
36
|
+
doc.replace(/\.doc\.(?:ts|mjs|js)$/u, '.tsx'),
|
|
37
|
+
'export function AcmeWidget() {\n return <div>Authored</div>;\n}\n',
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Every file under the package, with its bytes. */
|
|
42
|
+
function snapshot() {
|
|
43
|
+
/** @type {Record<string, string>} */
|
|
44
|
+
const files = {};
|
|
45
|
+
/** @param {string} dir */
|
|
46
|
+
const walk = dir => {
|
|
47
|
+
for (const entry of fs.readdirSync(dir, {withFileTypes: true})) {
|
|
48
|
+
const full = path.join(dir, entry.name);
|
|
49
|
+
if (entry.isDirectory()) walk(full);
|
|
50
|
+
else files[path.relative(tmpDir, full)] = fs.readFileSync(full, 'utf-8');
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
walk(tmpDir);
|
|
54
|
+
return files;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
describe('integrationAddComponent name collisions', () => {
|
|
58
|
+
it('refuses a name a nested component doc already defines', async () => {
|
|
59
|
+
writeAuthoredComponent('components/AcmeWidget/AcmeWidget.doc.mjs');
|
|
60
|
+
const before = snapshot();
|
|
61
|
+
|
|
62
|
+
await expect(
|
|
63
|
+
integrationAddComponent('AcmeWidget', {cwd: tmpDir}),
|
|
64
|
+
).rejects.toMatchObject({
|
|
65
|
+
code: 'ERR_FILE_EXISTS',
|
|
66
|
+
message: expect.stringContaining(
|
|
67
|
+
'components/AcmeWidget/AcmeWidget.doc.mjs',
|
|
68
|
+
),
|
|
69
|
+
});
|
|
70
|
+
expect(snapshot()).toEqual(before);
|
|
71
|
+
expect(
|
|
72
|
+
discoverIntegrationComponents({
|
|
73
|
+
name: '@acme/widgets',
|
|
74
|
+
components: path.join(tmpDir, 'components'),
|
|
75
|
+
}).map(component => path.relative(tmpDir, component.docPath)),
|
|
76
|
+
).toEqual([path.join('components', 'AcmeWidget', 'AcmeWidget.doc.mjs')]);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('refuses the same collision under --dry-run', async () => {
|
|
80
|
+
writeAuthoredComponent('components/widgets/AcmeWidget.doc.mjs');
|
|
81
|
+
|
|
82
|
+
await expect(
|
|
83
|
+
integrationAdd('component', 'AcmeWidget', {cwd: tmpDir, dryRun: true}),
|
|
84
|
+
).rejects.toMatchObject({code: 'ERR_FILE_EXISTS'});
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('refuses a same-stem doc with another extension in the root', async () => {
|
|
88
|
+
fs.mkdirSync(path.join(tmpDir, 'components'));
|
|
89
|
+
fs.writeFileSync(
|
|
90
|
+
path.join(tmpDir, 'components', 'AcmeWidget.doc.ts'),
|
|
91
|
+
"export default {type: 'component', name: 'AcmeWidget', props: []};\n",
|
|
92
|
+
);
|
|
93
|
+
const before = snapshot();
|
|
94
|
+
|
|
95
|
+
await expect(
|
|
96
|
+
integrationAddComponent('AcmeWidget', {cwd: tmpDir}),
|
|
97
|
+
).rejects.toMatchObject({code: 'ERR_FILE_EXISTS'});
|
|
98
|
+
expect(snapshot()).toEqual(before);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('still adds a component whose name is free', async () => {
|
|
102
|
+
writeAuthoredComponent('components/AcmeWidget/AcmeWidget.doc.mjs');
|
|
103
|
+
|
|
104
|
+
const result = await integrationAddComponent('AcmeBadge', {cwd: tmpDir});
|
|
105
|
+
|
|
106
|
+
expect(result.data.files).toEqual([
|
|
107
|
+
'components/AcmeBadge.doc.mjs',
|
|
108
|
+
'components/AcmeBadge.tsx',
|
|
109
|
+
'package.json',
|
|
110
|
+
]);
|
|
111
|
+
expect(
|
|
112
|
+
discoverIntegrationComponents({
|
|
113
|
+
name: '@acme/widgets',
|
|
114
|
+
components: path.join(tmpDir, 'components'),
|
|
115
|
+
})
|
|
116
|
+
.map(component => component.name)
|
|
117
|
+
.sort(),
|
|
118
|
+
).toEqual(['AcmeBadge', 'AcmeWidget']);
|
|
119
|
+
});
|
|
120
|
+
});
|
|
@@ -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,7 @@ 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 {findIntegrationComponentDoc} from '../../foundation/discovery/component-discovery.mjs';
|
|
38
38
|
import {parseAgentDocsField} from '../../authoring/integration/schema.mjs';
|
|
39
39
|
import {integrationAddTheme} from './add-theme.mjs';
|
|
40
40
|
import {
|
|
@@ -248,10 +248,21 @@ async function addComponent(name, options) {
|
|
|
248
248
|
ERROR_CODES.ERR_FILE_EXISTS,
|
|
249
249
|
);
|
|
250
250
|
}
|
|
251
|
+
// Discovery keys components by doc stem anywhere under the root, so a second
|
|
252
|
+
// doc with this name would shadow one of the two.
|
|
253
|
+
const existingDoc = findIntegrationComponentDoc({components: root}, name);
|
|
254
|
+
if (existingDoc != null) {
|
|
255
|
+
throw new AstryxError(
|
|
256
|
+
`Refusing to add component "${name}": ${projectPath(path.relative(packageDir, existingDoc))} already defines it.`,
|
|
257
|
+
undefined,
|
|
258
|
+
ERROR_CODES.ERR_FILE_EXISTS,
|
|
259
|
+
);
|
|
260
|
+
}
|
|
251
261
|
|
|
252
262
|
const sourcePath = projectPath(path.relative(packageDir, sourceFile));
|
|
253
|
-
const
|
|
254
|
-
const
|
|
263
|
+
const extensionlessPath = sourcePath.replace(/\.tsx?$/u, '');
|
|
264
|
+
const importSpecifier = `${owner}/${extensionlessPath}`;
|
|
265
|
+
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
266
|
const sourceContents = `export function ${name}() {\n return <div>${name}</div>;\n}\n`;
|
|
256
267
|
|
|
257
268
|
/** @type {import('./add-helpers.mjs').WritePlan[]} */
|
|
@@ -263,7 +274,7 @@ async function addComponent(name, options) {
|
|
|
263
274
|
packageFile,
|
|
264
275
|
rootPath,
|
|
265
276
|
path.basename(manifestFile),
|
|
266
|
-
[{subpath:
|
|
277
|
+
[{subpath: extensionlessPath, target: sourcePath}],
|
|
267
278
|
);
|
|
268
279
|
if (pkgUpdate != null) {
|
|
269
280
|
plans.push({
|
|
@@ -426,7 +437,7 @@ async function addDoc(name, options) {
|
|
|
426
437
|
: options.extends
|
|
427
438
|
? `\n extends: '${options.extends}',`
|
|
428
439
|
: '';
|
|
429
|
-
const docContents =
|
|
440
|
+
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
441
|
|
|
431
442
|
/** @type {import('./add-helpers.mjs').WritePlan[]} */
|
|
432
443
|
const plans = [{path: docFile, contents: docContents, createOnly: true}];
|
|
@@ -553,8 +564,8 @@ async function addTemplate(name, options) {
|
|
|
553
564
|
throw error;
|
|
554
565
|
}
|
|
555
566
|
|
|
556
|
-
const specFile = assertWithin(`${name}.
|
|
557
|
-
label: 'template
|
|
567
|
+
const specFile = assertWithin(`${name}.doc.mjs`, root, {
|
|
568
|
+
label: 'template descriptor',
|
|
558
569
|
});
|
|
559
570
|
const sourceFile = assertWithin(`${name}.tsx`, root, {
|
|
560
571
|
label: 'template source',
|
|
@@ -576,7 +587,9 @@ async function addTemplate(name, options) {
|
|
|
576
587
|
|
|
577
588
|
const pascalName = kebabToPascal(name);
|
|
578
589
|
const sourcePath = projectPath(path.relative(packageDir, sourceFile));
|
|
579
|
-
const
|
|
590
|
+
const extensionlessPath = sourcePath.replace(/\.tsx?$/u, '');
|
|
591
|
+
const blockFields = templateType === 'block' ? '\n aspectRatio: 1,' : '';
|
|
592
|
+
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
593
|
const sourceContents = `export default function ${pascalName}() {\n return <div>${kebabToTitle(name)}</div>;\n}\n`;
|
|
581
594
|
|
|
582
595
|
/** @type {import('./add-helpers.mjs').WritePlan[]} */
|
|
@@ -588,7 +601,7 @@ async function addTemplate(name, options) {
|
|
|
588
601
|
packageFile,
|
|
589
602
|
rootPath,
|
|
590
603
|
path.basename(manifestFile),
|
|
591
|
-
[{subpath:
|
|
604
|
+
[{subpath: extensionlessPath, target: sourcePath}],
|
|
592
605
|
);
|
|
593
606
|
if (pkgUpdate != null) {
|
|
594
607
|
plans.push({
|