@astryxdesign/cli 0.7.2-canary.fe2c655 → 0.7.2
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 +119 -0
- package/README.md +175 -154
- package/api/build/_adapter.d.mts +8 -0
- package/api/build/_adapter.mjs +12 -1
- package/api/build/build.doc.mjs +4 -0
- package/api/build/help/help.mjs +1 -1
- package/api/build/kit/kit.mjs +3 -11
- package/api/component/_adapter.d.mts +72 -1
- package/api/component/_adapter.mjs +212 -18
- package/api/component/component.doc.mjs +6 -1
- package/api/component/component.mjs +82 -15
- package/api/component/component.test.mjs +80 -0
- package/api/component/doc-links.test.mjs +386 -0
- package/api/component/integration-export-name.test.mjs +644 -0
- package/api/component/list/list.mjs +42 -4
- package/api/discover/_adapter.d.mts +132 -12
- package/api/discover/_adapter.mjs +488 -27
- package/api/discover/_adapter.test.mjs +599 -17
- package/api/discover/_catalog-view.d.mts +16 -5
- package/api/discover/_catalog-view.mjs +32 -8
- package/api/discover/detail/doc/doc.mjs +9 -1
- package/api/discover/discover.d.mts +11 -0
- package/api/discover/discover.doc.mjs +9 -7
- package/api/discover/discover.mjs +121 -19
- package/api/discover/discover.type.d.mts +20 -7
- package/api/discover/discover.type.mjs +17 -7
- package/api/discover/list/list.d.mts +4 -3
- package/api/discover/list/list.mjs +17 -10
- package/api/docs/_adapter.d.mts +74 -0
- package/api/docs/_adapter.mjs +553 -16
- package/api/docs/docs.doc.mjs +2 -1
- package/api/docs/docs.mjs +2 -1
- package/api/docs/docs.test.mjs +5 -2
- package/api/docs/integration-tree.test.mjs +22 -0
- package/api/docs/integrationDocs.test.mjs +124 -0
- package/api/docs/list/list.mjs +12 -2
- package/api/docs/reference-blocks.test.mjs +1 -3
- package/api/doctor/_adapter.d.mts +108 -0
- package/api/doctor/_adapter.mjs +223 -4
- package/api/doctor/doctor.d.mts +199 -0
- package/api/doctor/doctor.doc.mjs +3 -2
- package/api/doctor/doctor.mjs +530 -34
- package/api/doctor/doctor.test.mjs +180 -14
- package/api/doctor/release-checks.test.mjs +156 -0
- package/api/doctor/theme-checks.mjs +17 -4
- package/api/doctor/theme-checks.test.mjs +223 -7
- package/api/error.d.mts +10 -0
- package/api/error.mjs +25 -0
- package/api/gap-report/gap-report.d.mts +3 -0
- package/api/gap-report/gap-report.doc.mjs +11 -3
- package/api/gap-report/gap-report.mjs +219 -52
- package/api/gap-report/gap-report.test.mjs +233 -0
- package/api/gap-report/gap-report.type.d.mts +41 -0
- package/api/gap-report/gap-report.type.mjs +18 -0
- package/api/hook/_adapter.mjs +3 -11
- package/api/hook/hook.doc.mjs +4 -0
- package/api/hook/list/list.d.mts +1 -1
- package/api/index.d.mts +2 -0
- package/api/index.mjs +2 -0
- package/api/init/_adapter.d.mts +22 -0
- package/api/init/_adapter.mjs +59 -0
- package/api/init/init.d.mts +7 -5
- package/api/init/init.doc.mjs +28 -7
- package/api/init/init.mjs +28 -4
- package/api/init/init.type.d.mts +48 -3
- package/api/init/init.type.mjs +37 -3
- package/api/init/run/run.d.mts +1 -1
- package/api/init/run/run.mjs +17 -6
- package/api/init/user/user.d.mts +14 -0
- package/api/init/user/user.mjs +87 -0
- package/api/init/user/user.test.mjs +232 -0
- package/api/integration/_adapter.d.mts +45 -0
- package/api/integration/_adapter.mjs +112 -0
- package/api/integration/add-contribution.component-names.test.mjs +66 -0
- package/api/integration/add-contribution.mjs +8 -4
- package/api/integration/add-contribution.test.mjs +4 -2
- package/api/integration/authoring-checks.mjs +110 -6
- package/api/integration/authoring-checks.test.mjs +808 -0
- package/api/integration/authoring-checks.type.d.mts +143 -0
- package/api/integration/authoring-checks.type.mjs +74 -2
- package/api/integration/check/check.d.mts +96 -0
- package/api/integration/check/check.mjs +357 -0
- package/api/integration/check/check.test.mjs +489 -0
- package/api/integration/integration-check.type.d.mts +118 -0
- package/api/integration/integration-check.type.mjs +84 -0
- package/api/integration/integrationCheck.doc.d.mts +10 -0
- package/api/integration/integrationCheck.doc.mjs +73 -0
- package/api/integration/integrationComponentConflicts.doc.mjs +45 -6
- package/api/integration/integrationDocConflicts.doc.mjs +22 -5
- package/api/integration/pack-check.mjs +364 -120
- package/api/integration/pack-check.test.mjs +730 -10
- package/api/integration/validate-integration-fixes.test.mjs +67 -0
- package/api/integration/validate-integration.d.mts +8 -0
- package/api/integration/validate-integration.mjs +63 -9
- package/api/integration/validate-integration.test.mjs +88 -8
- package/api/integration/validate-integration.type.d.mts +16 -0
- package/api/integration/validate-integration.type.mjs +14 -1
- package/api/integration/validate-unread-theme-folders.test.mjs +3 -2
- package/api/integration/validateIntegration.doc.mjs +19 -3
- package/api/search/_adapter.d.mts +11 -0
- package/api/search/_adapter.mjs +25 -0
- package/api/search/search.d.mts +82 -13
- package/api/search/search.doc.mjs +8 -3
- package/api/search/search.domain-priority.test.mjs +108 -18
- package/api/search/search.integration-check.test.mjs +24 -0
- package/api/search/search.mjs +645 -64
- package/api/search/search.test.mjs +179 -1
- package/api/search/search.type.d.mts +14 -1
- package/api/search/search.type.mjs +6 -1
- package/api/swizzle/_adapter.mjs +2 -2
- package/api/swizzle/copy/copy.mjs +29 -15
- package/api/template/template-integration.test.mjs +1 -1
- package/api/template/template.test.mjs +120 -3
- package/api/theme/_adapter.d.mts +16 -0
- package/api/theme/_adapter.mjs +32 -5
- package/api/theme/build/build.d.mts +2 -1
- package/api/theme/build/build.family.test.mjs +64 -0
- package/api/theme/build/build.mjs +250 -38
- package/api/theme/build/build.packed-old-core.test.mjs +20 -3
- package/api/theme/build/font-warning.mjs +5 -3
- package/api/theme/build/font-warning.test.mjs +2 -1
- package/api/theme/remove/remove.test.mjs +2 -2
- package/api/theme/targets/targets.mjs +3 -10
- package/api/theme/themeBuild.doc.mjs +4 -4
- package/api/theme/themeTargets.doc.mjs +4 -0
- package/api/theme/use/use.test.mjs +1 -1
- package/api/upgrade/_adapter.d.mts +40 -2
- package/api/upgrade/_adapter.mjs +118 -5
- package/api/upgrade/run/cli-behind-core.test.mjs +438 -0
- package/api/upgrade/run/run.mjs +35 -2
- package/api/upgrade/status/status.d.mts +21 -5
- package/api/upgrade/status/status.mjs +45 -8
- package/api/upgrade/upgrade.doc.mjs +6 -3
- package/api/upgrade/upgrade.mjs +5 -1
- package/api/upgrade/upgrade.type.d.mts +23 -0
- package/api/upgrade/upgrade.type.mjs +16 -1
- package/assets/codemods/__tests__/registry.test.mjs +1 -0
- package/assets/codemods/registry.mjs +1 -0
- package/assets/codemods/runner.mjs +7 -1
- package/assets/codemods/transforms/v0.7.2/__tests__/migrate-list-edge-compensation-to-edge.test.mjs +120 -0
- package/assets/codemods/transforms/v0.7.2/index.mjs +20 -0
- package/assets/codemods/transforms/v0.7.2/migrate-list-edge-compensation-to-edge.mjs +198 -0
- package/assets/discover/official-packages.json +367 -0
- package/assets/docs/README.md +10 -0
- package/assets/docs/author-a-theme.doc.mjs +3 -3
- package/assets/docs/browser-support.doc.mjs +1 -1
- package/assets/docs/getting-started.doc.mjs +26 -6
- package/assets/docs/styling-overview.doc.mjs +1 -1
- package/assets/docs/theme.doc.dense.mjs +1 -1
- package/assets/docs/theme.doc.mjs +2 -2
- package/assets/docs/theme.doc.zh.mjs +1 -1
- package/assets/docs/tree/add-a-component.doc.mjs +22 -2
- package/assets/docs/tree/add-a-theme.doc.mjs +13 -3
- package/assets/docs/tree/add-a-topic.doc.mjs +54 -9
- package/assets/docs/tree/agent-guidance.doc.mjs +19 -5
- package/assets/docs/tree/block-template.doc.mjs +8 -20
- package/assets/docs/tree/build-the-template.doc.mjs +1 -1
- package/assets/docs/tree/building-blocks.doc.mjs +4 -0
- package/assets/docs/tree/check-the-props.doc.mjs +201 -0
- package/assets/docs/tree/check-your-docs.doc.mjs +69 -11
- package/assets/docs/tree/checks.doc.mjs +32 -24
- package/assets/docs/tree/ci-and-containers.doc.mjs +88 -0
- package/assets/docs/tree/cli-command.doc.mjs +142 -0
- package/assets/docs/tree/cli.doc.mjs +6 -0
- package/assets/docs/tree/codemods.doc.mjs +17 -7
- package/assets/docs/tree/commands.doc.mjs +7 -1
- package/assets/docs/tree/component-family.doc.mjs +8 -6
- package/assets/docs/tree/component-imports.doc.mjs +21 -3
- package/assets/docs/tree/components.doc.mjs +7 -1
- package/assets/docs/tree/computer-agent-guide.doc.mjs +160 -0
- package/assets/docs/tree/computer-integrations.doc.mjs +93 -0
- package/assets/docs/tree/configuration.doc.mjs +7 -3
- package/assets/docs/tree/debug-and-gap-reports.doc.mjs +41 -22
- package/assets/docs/tree/define-the-theme.doc.mjs +6 -5
- package/assets/docs/tree/describe-the-component.doc.mjs +3 -3
- package/assets/docs/tree/docs.doc.mjs +9 -3
- package/assets/docs/tree/document-the-template.doc.mjs +1 -1
- package/assets/docs/tree/document-the-theme.doc.mjs +3 -3
- package/assets/docs/tree/export-template-assets.doc.mjs +1 -1
- package/assets/docs/tree/extend-or-replace.doc.mjs +19 -9
- package/assets/docs/tree/fonts-and-assets.doc.mjs +2 -2
- package/assets/docs/tree/generate-a-palette.doc.mjs +7 -5
- package/assets/docs/tree/global-integrations.doc.mjs +124 -0
- package/assets/docs/tree/global.doc.mjs +131 -0
- package/assets/docs/tree/grade-template-with-agent.doc.mjs +5 -5
- package/assets/docs/tree/install-once.doc.mjs +105 -0
- package/assets/docs/tree/integrations.doc.mjs +13 -1
- package/assets/docs/tree/layout-spacing.doc.mjs +2 -3
- package/assets/docs/tree/layout.doc.mjs +6 -6
- package/assets/docs/tree/links.doc.mjs +7 -6
- package/assets/docs/tree/migration-setup.doc.mjs +3 -2
- package/assets/docs/tree/migration-verification.doc.mjs +0 -1
- package/assets/docs/tree/migration.doc.mjs +0 -1
- package/assets/docs/tree/monorepos.doc.mjs +84 -0
- package/assets/docs/tree/package-and-test.doc.mjs +1 -1
- package/assets/docs/tree/page-template.doc.mjs +4 -8
- package/assets/docs/tree/problems.doc.mjs +205 -0
- package/assets/docs/tree/project-global-or-both.doc.mjs +131 -0
- package/assets/docs/tree/publishing.doc.mjs +6 -6
- package/assets/docs/tree/quick-start.doc.mjs +53 -27
- package/assets/docs/tree/reference.doc.mjs +192 -0
- package/assets/docs/tree/replace-a-core-component.doc.mjs +15 -7
- package/assets/docs/tree/replace-a-core-template.doc.mjs +10 -12
- package/assets/docs/tree/scaffold.doc.mjs +1 -1
- package/assets/docs/tree/sections-and-placement.doc.mjs +9 -11
- package/assets/docs/tree/see-it-in-an-app.doc.mjs +17 -5
- package/assets/docs/tree/short-and-findable.doc.mjs +9 -8
- package/assets/docs/tree/single-component.doc.mjs +15 -6
- package/assets/docs/tree/start-a-template.doc.mjs +18 -8
- package/assets/docs/tree/subcomponent.doc.mjs +6 -6
- package/assets/docs/tree/template-assets.doc.mjs +2 -2
- package/assets/docs/tree/template-doc-overview.doc.mjs +6 -17
- package/assets/docs/tree/template-fonts.doc.mjs +1 -1
- package/assets/docs/tree/template-icons.doc.mjs +1 -1
- package/assets/docs/tree/template-images-media.doc.mjs +1 -1
- package/assets/docs/tree/template-styles.doc.mjs +2 -2
- package/assets/docs/tree/templates.doc.mjs +7 -1
- package/assets/docs/tree/test-in-an-app.doc.mjs +7 -7
- package/assets/docs/tree/test-template-in-app.doc.mjs +5 -5
- package/assets/docs/tree/themes.doc.mjs +4 -0
- package/assets/docs/tree/tokens-and-setup.doc.mjs +19 -15
- package/assets/docs/tree/troubleshooting.doc.mjs +29 -13
- package/assets/docs/tree/type-scale.doc.mjs +3 -3
- package/assets/docs/tree/uninstall.doc.mjs +109 -0
- package/assets/docs/tree/updates.doc.mjs +92 -0
- package/assets/docs/tree/upgrading.doc.mjs +6 -6
- package/assets/docs/tree/use-a-theme-in-an-app.doc.mjs +14 -2
- package/assets/docs/tree/verify-packed-template.doc.mjs +3 -3
- package/assets/docs/tree/versioning.doc.mjs +10 -9
- package/assets/docs/tree/who-answers.doc.mjs +119 -0
- package/assets/docs/tree/write-the-template-file.doc.mjs +7 -6
- package/assets/docs/use-a-theme.doc.mjs +2 -2
- package/assets/docs/working-with-ai.doc.mjs +66 -13
- package/assets/theme.template.ts +1 -1
- package/authoring/codemod/codemod.doc.mjs +7 -3
- package/authoring/config/config.doc.mjs +9 -6
- package/authoring/config/type.ts +4 -2
- package/authoring/debug/parse.d.mts +5 -5
- package/authoring/discover/discover.doc.mjs +7 -1
- package/authoring/doctypes/_schema.d.mts +8 -3
- package/authoring/doctypes/_schema.mjs +1 -0
- package/authoring/doctypes/base/graph-fields.doc.mjs +6 -4
- package/authoring/doctypes/command/command.doc.mjs +20 -12
- package/authoring/doctypes/command/type.ts +14 -0
- package/authoring/doctypes/component/component.doc.mjs +30 -27
- package/authoring/doctypes/component/type.ts +21 -8
- package/authoring/doctypes/enum/enum.doc.mjs +7 -4
- package/authoring/doctypes/function/function.doc.mjs +9 -8
- package/authoring/doctypes/hook/hook.doc.mjs +5 -4
- package/authoring/doctypes/hook/type.ts +4 -0
- package/authoring/doctypes/namespace/namespace.doc.mjs +7 -6
- package/authoring/doctypes/reference/reference.doc.mjs +12 -11
- package/authoring/doctypes/schema/schema.doc.mjs +9 -9
- package/authoring/doctypes/template/integration-template.doc.d.mts +11 -0
- package/authoring/doctypes/template/integration-template.doc.mjs +49 -0
- package/authoring/doctypes/template/parse.d.mts +6 -2
- package/authoring/doctypes/template/parse.mjs +3 -1
- package/authoring/doctypes/template/template.doc.mjs +3 -3
- package/authoring/doctypes/template/type.ts +22 -0
- package/authoring/doctypes/theme/theme.doc.mjs +2 -2
- package/authoring/gap-report/gap-report.doc.mjs +2 -2
- package/authoring/identity/identity.doc.mjs +3 -3
- package/authoring/index.d.ts +2 -0
- package/authoring/integration/integration.doc.mjs +30 -6
- package/authoring/integration/parse.test.mjs +21 -0
- package/authoring/integration/schema.d.mts +16 -3
- package/authoring/integration/schema.mjs +34 -2
- package/authoring/integration/type.ts +12 -0
- package/clients/cli/bin/astryx.mjs +20 -3
- package/clients/cli/cli-command.test.mjs +166 -0
- package/clients/cli/commands/blog.doc.mjs +1 -0
- package/clients/cli/commands/build-theme.batch-report.test.mjs +17 -3
- package/clients/cli/commands/build-theme.font-warning.test.mjs +3 -3
- package/clients/cli/commands/build-theme.mjs +26 -13
- package/clients/cli/commands/build-theme.path-safety.test.mjs +224 -6
- package/clients/cli/commands/build-theme.registry.test.mjs +5 -2
- package/clients/cli/commands/build.doc.mjs +1 -0
- package/clients/cli/commands/build.exit-codes-doc.test.mjs +4 -0
- package/clients/cli/commands/cli-postinstall.test.mjs +49 -1
- package/clients/cli/commands/component.doc.mjs +1 -0
- package/clients/cli/commands/discover.broken-integration.test.mjs +11 -7
- package/clients/cli/commands/discover.doc.mjs +9 -1
- package/clients/cli/commands/discover.mjs +144 -93
- package/clients/cli/commands/discover.no-source.test.mjs +448 -33
- package/clients/cli/commands/discover.sources.test.mjs +20 -1
- package/clients/cli/commands/docs.doc.mjs +1 -0
- package/clients/cli/commands/docs.mjs +49 -19
- package/clients/cli/commands/docs.test.mjs +2 -2
- package/clients/cli/commands/doctor-integration-components.doc.mjs +19 -4
- package/clients/cli/commands/doctor-integration-docs.doc.mjs +20 -5
- package/clients/cli/commands/doctor-integration-templates.doc.mjs +1 -0
- package/clients/cli/commands/doctor-integration-validate.doc.mjs +22 -2
- package/clients/cli/commands/doctor-integration.test.mjs +888 -3
- package/clients/cli/commands/doctor.doc.mjs +12 -2
- package/clients/cli/commands/doctor.mjs +292 -7
- package/clients/cli/commands/doctor.test.mjs +10 -4
- package/clients/cli/commands/gap-report.doc.mjs +15 -2
- package/clients/cli/commands/gap-report.mjs +24 -2
- package/clients/cli/commands/gap-report.test.mjs +79 -0
- package/clients/cli/commands/hook.doc.mjs +1 -0
- package/clients/cli/commands/init.behavior.test.mjs +5 -0
- package/clients/cli/commands/init.doc.mjs +29 -3
- package/clients/cli/commands/integration-add.doc.mjs +7 -0
- package/clients/cli/commands/integration-authoring.test.mjs +49 -3
- package/clients/cli/commands/integration-check.doc.mjs +93 -0
- package/clients/cli/commands/integration-check.test.mjs +441 -0
- package/clients/cli/commands/integration-pack.doc.mjs +8 -1
- package/clients/cli/commands/integration-verify.doc.mjs +8 -1
- package/clients/cli/commands/integration.doc.mjs +6 -2
- package/clients/cli/commands/integration.mjs +119 -7
- package/clients/cli/commands/json-contract.test.mjs +11 -2
- package/clients/cli/commands/manifest.doc.mjs +1 -0
- package/clients/cli/commands/outside-project.test.mjs +774 -0
- package/clients/cli/commands/search.doc.mjs +1 -0
- package/clients/cli/commands/search.mjs +16 -11
- package/clients/cli/commands/search.test.mjs +429 -296
- package/clients/cli/commands/setup-nudge.test.mjs +102 -2
- package/clients/cli/commands/swizzle.doc.mjs +7 -0
- package/clients/cli/commands/swizzle.mjs +5 -3
- package/clients/cli/commands/swizzle.routing.test.mjs +19 -2
- package/clients/cli/commands/template.doc.mjs +1 -0
- package/clients/cli/commands/text-json-parity.test.mjs +5 -0
- package/clients/cli/commands/theme-add-lifecycle.test.mjs +3 -3
- package/clients/cli/commands/theme-add.doc.mjs +8 -1
- package/clients/cli/commands/theme-build.doc.mjs +3 -2
- package/clients/cli/commands/theme-eject.doc.mjs +1 -0
- package/clients/cli/commands/theme-list.behavior.test.mjs +6 -0
- package/clients/cli/commands/theme-list.doc.mjs +1 -0
- package/clients/cli/commands/theme-palette-generate.doc.mjs +1 -0
- package/clients/cli/commands/theme-remove.doc.mjs +7 -0
- package/clients/cli/commands/theme-targets.doc.mjs +1 -0
- package/clients/cli/commands/theme-template.doc.mjs +1 -0
- package/clients/cli/commands/theme-use.doc.mjs +7 -0
- package/clients/cli/commands/upgrade.config-ordering.test.mjs +2 -1
- package/clients/cli/commands/upgrade.doc.mjs +22 -1
- package/clients/cli/commands/upgrade.file-protection.test.mjs +3 -2
- package/clients/cli/commands/upgrade.hook-output.test.mjs +2 -1
- package/clients/cli/commands/upgrade.older-cli.test.mjs +160 -0
- package/clients/cli/index.mjs +112 -16
- package/clients/cli/lib/cli-error.mjs +4 -1
- package/clients/cli/lib/component-format.test.mjs +1 -1
- package/clients/cli/lib/define-command.mjs +2 -2
- package/clients/cli/lib/json-shim.mjs +3 -1
- package/clients/cli/lib/manifest.d.ts +9 -0
- package/clients/cli/lib/manifest.mjs +17 -1
- package/clients/cli/lib/manifest.test.mjs +25 -0
- package/foundation/agent-docs/agent-doc-state.d.mts +35 -6
- package/foundation/agent-docs/agent-doc-state.mjs +66 -6
- package/foundation/agent-docs/agent-docs.d.mts +4 -3
- package/foundation/agent-docs/agent-docs.mjs +11 -9
- package/foundation/agent-docs/computer-agent-text.d.mts +133 -0
- package/foundation/agent-docs/computer-agent-text.mjs +623 -0
- package/foundation/agent-docs/computer-agent-text.test.mjs +602 -0
- package/foundation/config/project.d.mts +35 -3
- package/foundation/config/project.mjs +226 -7
- package/foundation/config/project.test.mjs +66 -0
- package/foundation/config/theme-state.mjs +5 -4
- package/foundation/discovery/authoring-self-docs.mjs +2 -1
- package/foundation/discovery/cli-self-docs.mjs +20 -3
- package/foundation/discovery/cli-self-docs.test.mjs +3 -2
- package/foundation/discovery/component-discovery.d.mts +190 -10
- package/foundation/discovery/component-discovery.export-names.test.mjs +760 -0
- package/foundation/discovery/component-discovery.mjs +864 -56
- package/foundation/discovery/component-discovery.test.mjs +96 -0
- package/foundation/discovery/component-replacement.mjs +20 -1
- package/foundation/discovery/component-replacement.test.mjs +40 -0
- package/foundation/discovery/copied-passages.d.mts +216 -0
- package/foundation/discovery/copied-passages.mjs +720 -0
- package/foundation/discovery/copied-passages.test.mjs +124 -0
- package/foundation/discovery/doc-consistency.d.mts +34 -0
- package/foundation/discovery/doc-consistency.mjs +513 -0
- package/foundation/discovery/doc-consistency.test.mjs +347 -0
- package/foundation/discovery/doc-fluff.d.mts +112 -0
- package/foundation/discovery/doc-fluff.mjs +328 -0
- package/foundation/discovery/doc-fluff.test.mjs +142 -0
- package/foundation/discovery/doc-types.d.mts +157 -0
- package/foundation/discovery/doc-types.mjs +1231 -0
- package/foundation/discovery/doc-types.test.mjs +744 -0
- package/foundation/discovery/docs-discovery.d.mts +88 -0
- package/foundation/discovery/docs-discovery.mjs +83 -2
- package/foundation/discovery/integration-doc-files.d.mts +22 -0
- package/foundation/discovery/integration-doc-files.mjs +231 -0
- package/foundation/discovery/integration-doc-files.test.mjs +246 -0
- package/foundation/discovery/module-exports.d.mts +27 -0
- package/foundation/discovery/module-exports.mjs +356 -31
- package/foundation/discovery/module-exports.test.mjs +172 -0
- package/foundation/discovery/package-tsconfig.d.mts +14 -0
- package/foundation/discovery/package-tsconfig.mjs +228 -0
- package/foundation/discovery/package-tsconfig.test.mjs +210 -0
- package/foundation/discovery/project-typescript.d.mts +32 -0
- package/foundation/discovery/project-typescript.mjs +89 -0
- package/foundation/discovery/prop-drift.d.mts +297 -0
- package/foundation/discovery/prop-drift.mjs +2428 -0
- package/foundation/discovery/prop-drift.test.mjs +2337 -0
- package/foundation/discovery/runner-allowlist.d.mts +40 -0
- package/foundation/discovery/runner-allowlist.mjs +53 -0
- package/foundation/discovery/stray-pointers.d.mts +52 -0
- package/foundation/discovery/stray-pointers.mjs +293 -0
- package/foundation/discovery/stray-pointers.test.mjs +86 -0
- package/foundation/discovery/template-adapter.mjs +74 -5
- package/foundation/discovery/template-needs.mjs +5 -2
- package/foundation/discovery/theme-imports.mjs +8 -4
- package/foundation/discovery/theme-imports.test.mjs +1 -1
- package/foundation/discovery/type-match.d.mts +53 -0
- package/foundation/discovery/type-match.mjs +660 -0
- package/foundation/discovery/type-match.test.mjs +169 -0
- package/foundation/discovery/type-text.d.mts +68 -0
- package/foundation/discovery/type-text.mjs +658 -0
- package/foundation/discovery/type-text.test.mjs +196 -0
- package/foundation/discovery/unresolved-references.d.mts +62 -0
- package/foundation/discovery/unresolved-references.mjs +790 -0
- package/foundation/discovery/unresolved-references.test.mjs +567 -0
- package/foundation/doc-compiler/doc-loads.test.mjs +51 -1
- package/foundation/doc-compiler/inputs.mjs +27 -1
- package/foundation/doc-compiler/inputs.test.mjs +0 -1
- package/foundation/doc-compiler/links.d.mts +41 -5
- package/foundation/doc-compiler/links.mjs +167 -28
- package/foundation/doc-compiler/links.test.mjs +97 -4
- package/foundation/doc-compiler/read.d.mts +1 -1
- package/foundation/doc-compiler/tree.mjs +30 -1
- package/foundation/doc-compiler/tree.test.mjs +8 -1
- package/foundation/env/cli-command.d.mts +83 -0
- package/foundation/env/cli-command.mjs +152 -0
- package/foundation/env/cli-command.test.mjs +129 -0
- package/foundation/env/node-version.test.mjs +15 -3
- package/foundation/env/package-manager.d.mts +93 -9
- package/foundation/env/package-manager.global.test.mjs +66 -0
- package/foundation/env/package-manager.mjs +184 -13
- package/foundation/env/package-manager.test.mjs +341 -15
- package/foundation/env/project-scope.d.mts +9 -0
- package/foundation/env/project-scope.mjs +33 -0
- package/foundation/env/search-path.d.mts +42 -0
- package/foundation/env/search-path.mjs +205 -0
- package/foundation/env/search-path.test.mjs +122 -0
- package/foundation/env/user-dirs.d.mts +39 -0
- package/foundation/env/user-dirs.mjs +93 -0
- package/foundation/env/user-dirs.test.mjs +72 -0
- package/foundation/env/user-settings.d.mts +46 -0
- package/foundation/env/user-settings.mjs +106 -0
- package/foundation/env/user-settings.test.mjs +64 -0
- package/foundation/fs/file-protection.mjs +15 -1
- package/foundation/fs/module-loader.d.mts +2 -1
- package/foundation/fs/module-loader.mjs +60 -4
- package/foundation/fs/module-loader.stdout.test.mjs +3 -2
- package/foundation/fs/module-loader.test.mjs +194 -0
- package/foundation/fs/path-compare.d.mts +33 -0
- package/foundation/fs/path-compare.mjs +73 -0
- package/foundation/fs/paths.d.mts +57 -1
- package/foundation/fs/paths.mjs +131 -3
- package/foundation/fs/paths.test.mjs +10 -1
- package/foundation/integrations/computer-integrations.d.mts +78 -0
- package/foundation/integrations/computer-integrations.mjs +316 -0
- package/foundation/integrations/computer-integrations.test.mjs +292 -0
- package/foundation/integrations/contribution-inventory.d.mts +11 -0
- package/foundation/integrations/contribution-inventory.mjs +56 -3
- package/foundation/integrations/integration-warnings.mjs +3 -2
- package/foundation/integrations/integration-warnings.test.mjs +8 -9
- package/foundation/integrations/integrations.d.mts +25 -1
- package/foundation/integrations/integrations.mjs +46 -3
- package/foundation/integrations/issue.ts +6 -0
- package/foundation/integrations/validate-contributions.d.mts +2 -0
- package/foundation/integrations/validate-contributions.mjs +41 -1
- package/foundation/release/agent-text-worker.d.mts +4 -0
- package/foundation/release/agent-text-worker.mjs +52 -0
- package/foundation/release/cache.d.mts +310 -0
- package/foundation/release/cache.mjs +1216 -0
- package/foundation/release/cache.test.mjs +920 -0
- package/foundation/release/choose.d.mts +207 -0
- package/foundation/release/choose.mjs +677 -0
- package/foundation/release/choose.test.mjs +427 -0
- package/foundation/release/core-worker.d.mts +4 -0
- package/foundation/release/core-worker.mjs +38 -0
- package/foundation/release/global-state.d.mts +259 -0
- package/foundation/release/global-state.mjs +472 -0
- package/foundation/release/global-state.test.mjs +381 -0
- package/foundation/release/handoff.d.mts +60 -0
- package/foundation/release/handoff.e2e.test.mjs +278 -0
- package/foundation/release/handoff.mjs +357 -0
- package/foundation/release/lock-lease.d.mts +23 -0
- package/foundation/release/lock-lease.mjs +80 -0
- package/foundation/release/notices.d.mts +253 -0
- package/foundation/release/notices.mjs +596 -0
- package/foundation/release/notices.test.mjs +565 -0
- package/foundation/release/npm-guard.d.mts +4 -0
- package/foundation/release/npm-guard.mjs +126 -0
- package/foundation/release/project.d.mts +141 -0
- package/foundation/release/project.mjs +466 -0
- package/foundation/release/project.test.mjs +288 -0
- package/foundation/release/refresh-worker.d.mts +4 -0
- package/foundation/release/refresh-worker.mjs +27 -0
- package/foundation/release/run-context.d.mts +47 -0
- package/foundation/release/run-context.mjs +149 -0
- package/foundation/release/update-notice-env.d.mts +28 -0
- package/foundation/release/update-notice-env.mjs +39 -0
- package/foundation/response/base.d.ts +26 -3
- package/foundation/response/error-codes.d.mts +3 -1
- package/foundation/response/error-codes.doc.mjs +12 -0
- package/foundation/response/error-codes.mjs +17 -0
- package/foundation/response/error-codes.test.mjs +2 -0
- package/foundation/response/json-contract.test.mjs +7 -2
- package/foundation/response/json.mjs +4 -1
- package/foundation/response/response-types.doc.mjs +22 -11
- package/foundation/response/response-types.doc.test.mjs +46 -0
- package/foundation/response/response.doc.mjs +3 -3
- package/foundation/xle/browser-imports.test.mjs +74 -0
- package/foundation/xle/registry.mjs +4 -0
- package/foundation/xle/registry.test.mjs +28 -0
- package/package.json +11 -11
- package/scripts/postinstall.mjs +24 -5
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file init.user leaf — the `--user` path behind `astryx init`.
|
|
5
|
+
*
|
|
6
|
+
* `user(options)` writes, refreshes, or (with `remove`) removes the
|
|
7
|
+
* computer-level agent text: one skill file in the home folder, linked into
|
|
8
|
+
* the skill folders agents read (spec AST-081 FR7, FR8). It records the
|
|
9
|
+
* setting and the links it made in the settings file, so the global copy,
|
|
10
|
+
* which keeps the text current in the background, does the same, or, after
|
|
11
|
+
* `remove`, writes nothing. The adapter does every file access. It works in any
|
|
12
|
+
* folder and never touches a project's agent docs. A file without the Astryx
|
|
13
|
+
* markers, one a person edited, or a symlinked one is kept as it is. When no
|
|
14
|
+
* `astryx` on the computer's search path runs the Astryx CLI, the text is
|
|
15
|
+
* still written and the receipt warns that the CLI should be installed for
|
|
16
|
+
* the computer.
|
|
17
|
+
*
|
|
18
|
+
* @input `remove`; the home folder, search path, and settings of
|
|
19
|
+
* the computer
|
|
20
|
+
* @output an `init.user` receipt
|
|
21
|
+
* @position packages/cli/api/init — dispatched by init.mjs
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
import {
|
|
25
|
+
COMPUTER_COMMAND,
|
|
26
|
+
COMPUTER_INSTALL_STEP,
|
|
27
|
+
applyComputerAgentText,
|
|
28
|
+
displayHomePath,
|
|
29
|
+
} from '../_adapter.mjs';
|
|
30
|
+
import {logger} from '../../logger.mjs';
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @param {string} file
|
|
34
|
+
* @param {string} home
|
|
35
|
+
* @returns {string}
|
|
36
|
+
*/
|
|
37
|
+
const display = (file, home) => displayHomePath(file, home);
|
|
38
|
+
|
|
39
|
+
/** @type {Record<import('../init.type.mjs').InitUserAction, string>} */
|
|
40
|
+
const ACTION_LINES = {
|
|
41
|
+
written: '[ok] Wrote',
|
|
42
|
+
linked: '[ok] Linked',
|
|
43
|
+
unchanged: '[ok] Already current:',
|
|
44
|
+
removed: '[ok] Removed',
|
|
45
|
+
absent: '[ok] Nothing to remove:',
|
|
46
|
+
kept: '[skip] Kept',
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/** @type {Record<'edited' | 'not-astryx', string>} */
|
|
50
|
+
const KEPT_REASONS = {
|
|
51
|
+
edited: '(edited since Astryx wrote it; delete it to get the current text):',
|
|
52
|
+
'not-astryx': '(not created by Astryx):',
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Write or remove the computer-level agent text and return an `init.user`
|
|
57
|
+
* receipt. Progress is emitted through the shared `logger` (silent by
|
|
58
|
+
* default); warnings go to its warn channel.
|
|
59
|
+
*
|
|
60
|
+
* @param {{remove?: boolean}} [options]
|
|
61
|
+
* @returns {Promise<import('../init.type.mjs').InitUserResponse>}
|
|
62
|
+
*/
|
|
63
|
+
export async function user({remove = false} = {}) {
|
|
64
|
+
const {home, command, files, cliOnSearchPath} = applyComputerAgentText({
|
|
65
|
+
remove,
|
|
66
|
+
});
|
|
67
|
+
/** @type {string[]} */
|
|
68
|
+
const warnings = [];
|
|
69
|
+
// A host's door is its own command; only the plain `astryx` needs a copy of
|
|
70
|
+
// the CLI installed for the computer.
|
|
71
|
+
if (!remove && command === COMPUTER_COMMAND && !cliOnSearchPath) {
|
|
72
|
+
warnings.push(
|
|
73
|
+
`No \`${COMPUTER_COMMAND}\` command on this computer runs the Astryx CLI, so agents cannot run the commands this text names. Install the CLI for the computer: ${COMPUTER_INSTALL_STEP}`,
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
for (const file of files) {
|
|
77
|
+
const reason = file.reason ? ` ${KEPT_REASONS[file.reason]}` : '';
|
|
78
|
+
logger.log(
|
|
79
|
+
`${ACTION_LINES[file.action]}${reason || (file.action === 'kept' ? ':' : '')} ${display(file.path, home)}`,
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
for (const warning of warnings) logger.warn(`[warn] ${warning}`);
|
|
83
|
+
return {
|
|
84
|
+
type: 'init.user',
|
|
85
|
+
data: {files, command, warnings},
|
|
86
|
+
};
|
|
87
|
+
}
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file `init({user})` and `astryx init --user`: the `init.user` receipt, the
|
|
5
|
+
* install warning, the refused combinations, and that it touches nothing in
|
|
6
|
+
* the folder it runs in. Every test uses a temporary home folder and search
|
|
7
|
+
* path.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import * as fs from 'node:fs';
|
|
11
|
+
import * as os from 'node:os';
|
|
12
|
+
import * as path from 'node:path';
|
|
13
|
+
import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest';
|
|
14
|
+
import {init} from '../init.mjs';
|
|
15
|
+
import {user} from './user.mjs';
|
|
16
|
+
import {runWithCliDoor} from '../../../foundation/env/cli-command.mjs';
|
|
17
|
+
import {renderComputerAgentText} from '../../../foundation/agent-docs/computer-agent-text.mjs';
|
|
18
|
+
import {runCli} from '../../../test-utils/run-cli.mjs';
|
|
19
|
+
import {settingsFile} from '../../../foundation/env/user-settings.mjs';
|
|
20
|
+
import {readGlobalState} from '../../../foundation/release/global-state.mjs';
|
|
21
|
+
import {cliVersion} from '../../../foundation/release/run-context.mjs';
|
|
22
|
+
|
|
23
|
+
/** @type {string[]} */
|
|
24
|
+
const dirs = [];
|
|
25
|
+
/** @param {string} label */
|
|
26
|
+
function tmp(label) {
|
|
27
|
+
const dir = fs.mkdtempSync(
|
|
28
|
+
path.join(os.tmpdir(), `astryx-init-user-${label}-`),
|
|
29
|
+
);
|
|
30
|
+
dirs.push(dir);
|
|
31
|
+
return dir;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
let home = '';
|
|
35
|
+
let emptyPath = '';
|
|
36
|
+
beforeEach(() => {
|
|
37
|
+
home = tmp('home');
|
|
38
|
+
emptyPath = tmp('path');
|
|
39
|
+
vi.stubEnv('HOME', home);
|
|
40
|
+
vi.stubEnv('USERPROFILE', home);
|
|
41
|
+
vi.stubEnv('PATH', emptyPath);
|
|
42
|
+
// The settings file and the cache live under this home folder too.
|
|
43
|
+
vi.stubEnv('XDG_CONFIG_HOME', path.join(home, '.config'));
|
|
44
|
+
vi.stubEnv('XDG_CACHE_HOME', path.join(home, '.cache'));
|
|
45
|
+
vi.stubEnv('APPDATA', path.join(home, 'AppData', 'Roaming'));
|
|
46
|
+
vi.stubEnv('LOCALAPPDATA', path.join(home, 'AppData', 'Local'));
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
/** The settings file under the temporary home folder. */
|
|
50
|
+
const settings = () => {
|
|
51
|
+
try {
|
|
52
|
+
return JSON.parse(fs.readFileSync(settingsFile(), 'utf8'));
|
|
53
|
+
} catch {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
afterEach(() => {
|
|
58
|
+
vi.unstubAllEnvs();
|
|
59
|
+
while (dirs.length) {
|
|
60
|
+
fs.rmSync(/** @type {string} */ (dirs.pop()), {
|
|
61
|
+
recursive: true,
|
|
62
|
+
force: true,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
const FILE = path.join('.agents', 'skills', 'astryx', 'SKILL.md');
|
|
68
|
+
const CLAUDE = path.join('.claude', 'skills', 'astryx');
|
|
69
|
+
|
|
70
|
+
/** Put a linked Astryx CLI first on the search path. */
|
|
71
|
+
function installCliOnPath() {
|
|
72
|
+
const prefix = tmp('prefix');
|
|
73
|
+
const pkg = path.join(prefix, 'lib', 'node_modules', '@astryxdesign', 'cli');
|
|
74
|
+
fs.mkdirSync(pkg, {recursive: true});
|
|
75
|
+
fs.writeFileSync(
|
|
76
|
+
path.join(pkg, 'package.json'),
|
|
77
|
+
'{"name":"@astryxdesign/cli"}',
|
|
78
|
+
);
|
|
79
|
+
fs.writeFileSync(path.join(pkg, 'bin.mjs'), '#!/usr/bin/env node\n');
|
|
80
|
+
fs.chmodSync(path.join(pkg, 'bin.mjs'), 0o755);
|
|
81
|
+
fs.mkdirSync(path.join(prefix, 'bin'));
|
|
82
|
+
fs.symlinkSync(path.join(pkg, 'bin.mjs'), path.join(prefix, 'bin', 'astryx'));
|
|
83
|
+
vi.stubEnv('PATH', path.join(prefix, 'bin'));
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
describe('init({user: true})', () => {
|
|
87
|
+
it('writes the file, links Claude Code to it, and returns the init.user receipt, warning when no astryx runs the CLI', async () => {
|
|
88
|
+
const r = await init({user: true}, {cwd: tmp('cwd')});
|
|
89
|
+
expect(r.type).toBe('init.user');
|
|
90
|
+
if (r.type !== 'init.user') return;
|
|
91
|
+
expect(r.data.files).toEqual([
|
|
92
|
+
{path: path.join(home, FILE), action: 'written'},
|
|
93
|
+
{path: path.join(home, CLAUDE), action: 'linked'},
|
|
94
|
+
]);
|
|
95
|
+
expect(r.data.command).toBe('astryx');
|
|
96
|
+
expect(r.data.warnings).toHaveLength(1);
|
|
97
|
+
expect(r.data.warnings[0]).toContain('npm i -g @astryxdesign/cli');
|
|
98
|
+
expect(fs.readFileSync(path.join(home, FILE), 'utf8')).toBe(
|
|
99
|
+
renderComputerAgentText({command: 'astryx'}),
|
|
100
|
+
);
|
|
101
|
+
expect(fs.readFileSync(path.join(home, CLAUDE, 'SKILL.md'), 'utf8')).toBe(
|
|
102
|
+
renderComputerAgentText({command: 'astryx'}),
|
|
103
|
+
);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it.skipIf(process.platform === 'win32')(
|
|
107
|
+
'does not warn when the astryx on the search path is the Astryx CLI',
|
|
108
|
+
async () => {
|
|
109
|
+
installCliOnPath();
|
|
110
|
+
const r = await user();
|
|
111
|
+
expect(r.data.warnings).toEqual([]);
|
|
112
|
+
},
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
it("names the host's door and does not ask for a global install", async () => {
|
|
116
|
+
const r = await runWithCliDoor('acme astryx', () => user());
|
|
117
|
+
expect(r.data.command).toBe('acme astryx');
|
|
118
|
+
expect(r.data.warnings).toEqual([]);
|
|
119
|
+
expect(fs.readFileSync(path.join(home, FILE), 'utf8')).toContain(
|
|
120
|
+
"`acme astryx search '<what you need>'`",
|
|
121
|
+
);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it('works inside a project and writes nothing in it', async () => {
|
|
125
|
+
const dir = tmp('project');
|
|
126
|
+
fs.writeFileSync(
|
|
127
|
+
path.join(dir, 'package.json'),
|
|
128
|
+
'{"name":"app","dependencies":{"@astryxdesign/core":"*"}}',
|
|
129
|
+
);
|
|
130
|
+
const before = fs.readdirSync(dir).sort();
|
|
131
|
+
const r = await init({user: true}, {cwd: dir});
|
|
132
|
+
expect(r.type).toBe('init.user');
|
|
133
|
+
expect(fs.readdirSync(dir).sort()).toEqual(before);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it('records the links it made, and the release that wrote the text', async () => {
|
|
137
|
+
await init({user: true});
|
|
138
|
+
expect(settings()).toEqual({
|
|
139
|
+
computerAgentText: {install: true, links: [path.join(home, CLAUDE)]},
|
|
140
|
+
});
|
|
141
|
+
expect(readGlobalState().agentText).toEqual({writtenBy: cliVersion()});
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it('keeps every other setting when it records the choice', async () => {
|
|
145
|
+
fs.mkdirSync(path.dirname(settingsFile()), {recursive: true});
|
|
146
|
+
fs.writeFileSync(settingsFile(), '{"other": 1}');
|
|
147
|
+
await init({user: true, removeAgents: true});
|
|
148
|
+
expect(settings()).toEqual({
|
|
149
|
+
other: 1,
|
|
150
|
+
computerAgentText: {install: false, links: []},
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it('with removeAgents removes the file and the links it made, and records that the text is not wanted', async () => {
|
|
155
|
+
await init({user: true});
|
|
156
|
+
const r = await init({user: true, removeAgents: true});
|
|
157
|
+
expect(r.type).toBe('init.user');
|
|
158
|
+
if (r.type !== 'init.user') return;
|
|
159
|
+
expect(r.data.files).toEqual([
|
|
160
|
+
{path: path.join(home, FILE), action: 'removed'},
|
|
161
|
+
{path: path.join(home, CLAUDE), action: 'removed'},
|
|
162
|
+
]);
|
|
163
|
+
expect(r.data.warnings).toEqual([]);
|
|
164
|
+
expect(fs.existsSync(path.join(home, FILE))).toBe(false);
|
|
165
|
+
expect(fs.existsSync(path.join(home, CLAUDE))).toBe(false);
|
|
166
|
+
expect(settings()).toEqual({
|
|
167
|
+
computerAgentText: {install: false, links: []},
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it.each([
|
|
172
|
+
[{features: 'agents'}, '--features'],
|
|
173
|
+
[{all: true}, '--all'],
|
|
174
|
+
[{agentDocsPath: 'X.md'}, '--agent-docs-path'],
|
|
175
|
+
[{agent: 'claude'}, '--agent'],
|
|
176
|
+
[{removeAgents: true, agent: 'claude'}, '--agent'],
|
|
177
|
+
])(
|
|
178
|
+
'refuses %o with ERR_INVALID_ARGUMENT and writes nothing',
|
|
179
|
+
async (extra, flag) => {
|
|
180
|
+
await expect(init({user: true, ...extra})).rejects.toMatchObject({
|
|
181
|
+
code: 'ERR_INVALID_ARGUMENT',
|
|
182
|
+
message: expect.stringContaining(flag),
|
|
183
|
+
});
|
|
184
|
+
expect(fs.existsSync(path.join(home, '.agents'))).toBe(false);
|
|
185
|
+
expect(fs.existsSync(path.join(home, '.claude'))).toBe(false);
|
|
186
|
+
},
|
|
187
|
+
);
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
describe('astryx init --user', () => {
|
|
191
|
+
it('prints the file, the link, and the install warning in text mode', async () => {
|
|
192
|
+
const r = await runCli(['init', '--user'], tmp('cwd'));
|
|
193
|
+
expect(r.status).toBe(0);
|
|
194
|
+
expect(r.stdout).toContain(`Wrote ~${path.sep}${FILE}`);
|
|
195
|
+
expect(r.stdout).toContain(`Linked ~${path.sep}${CLAUDE}`);
|
|
196
|
+
expect(r.stderr).toContain('npm i -g @astryxdesign/cli');
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it('emits the init.user envelope under --json', async () => {
|
|
200
|
+
const r = await runCli(['--json', 'init', '--user'], tmp('cwd'));
|
|
201
|
+
expect(r.status).toBe(0);
|
|
202
|
+
const env = JSON.parse(r.stdout);
|
|
203
|
+
expect(env.type).toBe('init.user');
|
|
204
|
+
expect(
|
|
205
|
+
env.data.files.map((/** @type {{action: string}} */ f) => f.action),
|
|
206
|
+
).toEqual(['written', 'linked']);
|
|
207
|
+
expect(env.data.command).toBe('astryx');
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
it('names a file a person edited as kept, and why', async () => {
|
|
211
|
+
await runCli(['init', '--user'], tmp('cwd'));
|
|
212
|
+
const file = path.join(home, FILE);
|
|
213
|
+
fs.appendFileSync(file, 'my note\n');
|
|
214
|
+
const r = await runCli(['init', '--user'], tmp('cwd'));
|
|
215
|
+
expect(r.status).toBe(0);
|
|
216
|
+
expect(r.stdout).toContain(
|
|
217
|
+
`Kept (edited since Astryx wrote it; delete it to get the current text): ~${path.sep}${FILE}`,
|
|
218
|
+
);
|
|
219
|
+
expect(fs.readFileSync(file, 'utf8')).toMatch(/my note\n$/u);
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
it('exits 1 with ERR_INVALID_ARGUMENT when combined with --all or --agent', async () => {
|
|
223
|
+
for (const extra of [['--all'], ['--agent', 'claude']]) {
|
|
224
|
+
const r = await runCli(
|
|
225
|
+
['--json', 'init', '--user', ...extra],
|
|
226
|
+
tmp('cwd'),
|
|
227
|
+
);
|
|
228
|
+
expect(r.status).toBe(1);
|
|
229
|
+
expect(JSON.parse(r.stdout).code).toBe('ERR_INVALID_ARGUMENT');
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
});
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// @generated by scripts/sync-api-types.mjs from the JSDoc in api/**/*.mjs.
|
|
2
|
+
// DO NOT EDIT — run `pnpm sync:api-types` to regenerate.
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Each component doc's props compared with the component's TypeScript props,
|
|
6
|
+
* read with the project's own compiler (spec:AST-039 FR12). Without one, the
|
|
7
|
+
* report says the comparison was skipped.
|
|
8
|
+
* @param {any} integration a loaded integration
|
|
9
|
+
* @param {string} cwd
|
|
10
|
+
* @returns {Promise<import('../../foundation/discovery/prop-drift.mjs').PropDriftReport>}
|
|
11
|
+
*/
|
|
12
|
+
export function integrationPropDrift(integration: any, cwd: string): Promise<import("../../foundation/discovery/prop-drift.mjs").PropDriftReport>;
|
|
13
|
+
/**
|
|
14
|
+
* The passages two of a package's topics, or one of them and a Core topic,
|
|
15
|
+
* repeat word for word (architecture:cli-surface DEC-8). Reads the package's
|
|
16
|
+
* topics and Core's guides.
|
|
17
|
+
*
|
|
18
|
+
* @param {Parameters<typeof findCopiedPassages>[0]} discovered the package's
|
|
19
|
+
* docs, as discoverIntegrationDocs returns them
|
|
20
|
+
*/
|
|
21
|
+
export function integrationCopiedPassages(discovered: Parameters<typeof findCopiedPassages>[0]): Promise<import("./authoring-checks.type.mjs").CopiedPassage[]>;
|
|
22
|
+
/**
|
|
23
|
+
* Padding phrases and low-density topics in a package's prose
|
|
24
|
+
* (architecture:cli-surface DEC-8). Reads the package's topics, and Core's
|
|
25
|
+
* guides for the density median a finding names.
|
|
26
|
+
*
|
|
27
|
+
* @param {Parameters<typeof findFluff>[0]} discovered the package's docs, as
|
|
28
|
+
* discoverIntegrationDocs returns them
|
|
29
|
+
*/
|
|
30
|
+
export function integrationFluff(discovered: Parameters<typeof findFluff>[0]): Promise<import("./authoring-checks.type.mjs").DocFluff[]>;
|
|
31
|
+
/**
|
|
32
|
+
* Code spans in a package's prose that write `astryx docs <name>` for a doc
|
|
33
|
+
* that exists, where `{@link generic:<name>}` would be checked
|
|
34
|
+
* (architecture:cli-surface DEC-8). Reads the package's topics, its own
|
|
35
|
+
* component docs, and the names of Core's docs.
|
|
36
|
+
*
|
|
37
|
+
* @param {Parameters<typeof findStrayPointers>[0]} discovered the package's
|
|
38
|
+
* docs, as discoverIntegrationDocs returns them
|
|
39
|
+
* @param {any} [integration] the loaded integration, whose component docs are
|
|
40
|
+
* read too
|
|
41
|
+
*/
|
|
42
|
+
export function integrationStrayPointers(discovered: Parameters<typeof findStrayPointers>[0], integration?: any): Promise<import("./authoring-checks.type.mjs").StrayPointer[]>;
|
|
43
|
+
import { findCopiedPassages } from '../../foundation/discovery/copied-passages.mjs';
|
|
44
|
+
import { findFluff } from '../../foundation/discovery/doc-fluff.mjs';
|
|
45
|
+
import { findStrayPointers } from '../../foundation/discovery/stray-pointers.mjs';
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file The integration subject's access to the environment (INV21): reading
|
|
5
|
+
* one package's component docs and sources with the project's own TypeScript.
|
|
6
|
+
*
|
|
7
|
+
* @input a loaded integration and the directory the command runs in
|
|
8
|
+
* @output the reports the integration checks attach to their results
|
|
9
|
+
* @position api/integration (internal; not exported from ./api)
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import {
|
|
13
|
+
discoverValidIntegrationComponents,
|
|
14
|
+
forEachIntegrationDoc,
|
|
15
|
+
integrationSourceForDoc,
|
|
16
|
+
} from '../../foundation/discovery/component-discovery.mjs';
|
|
17
|
+
import {comparePropDocs} from '../../foundation/discovery/prop-drift.mjs';
|
|
18
|
+
import {findCopiedPassages} from '../../foundation/discovery/copied-passages.mjs';
|
|
19
|
+
import {findFluff} from '../../foundation/discovery/doc-fluff.mjs';
|
|
20
|
+
import {findStrayPointers} from '../../foundation/discovery/stray-pointers.mjs';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Each component doc's props compared with the component's TypeScript props,
|
|
24
|
+
* read with the project's own compiler (spec:AST-039 FR12). Without one, the
|
|
25
|
+
* report says the comparison was skipped.
|
|
26
|
+
* @param {any} integration a loaded integration
|
|
27
|
+
* @param {string} cwd
|
|
28
|
+
* @returns {Promise<import('../../foundation/discovery/prop-drift.mjs').PropDriftReport>}
|
|
29
|
+
*/
|
|
30
|
+
export async function integrationPropDrift(integration, cwd) {
|
|
31
|
+
const packageDir = /** @type {{__packageDir?: string}} */ (integration)
|
|
32
|
+
.__packageDir;
|
|
33
|
+
const {components} = await discoverValidIntegrationComponents(integration);
|
|
34
|
+
// Every doc the package ships has its prop tables compared or listed as not
|
|
35
|
+
// compared. A doc discovery leaves out (a hidden one, a second doc for one
|
|
36
|
+
// name, or one whose source or own file doesn't load) gets a record under
|
|
37
|
+
// its file name.
|
|
38
|
+
const recorded = new Set(components.map(c => c.docPath));
|
|
39
|
+
/** @type {typeof components} */
|
|
40
|
+
const left = [];
|
|
41
|
+
forEachIntegrationDoc(integration?.components, (docPath, stem) => {
|
|
42
|
+
if (recorded.has(docPath)) return;
|
|
43
|
+
recorded.add(docPath);
|
|
44
|
+
left.push({
|
|
45
|
+
name: stem,
|
|
46
|
+
package: integration.name,
|
|
47
|
+
docPath,
|
|
48
|
+
sourcePath: integrationSourceForDoc(docPath),
|
|
49
|
+
issuesUrl: integration.issuesUrl,
|
|
50
|
+
group: null,
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
return comparePropDocs([...components, ...left], {
|
|
54
|
+
packageDir: packageDir ?? cwd,
|
|
55
|
+
resolveFrom: [cwd, packageDir],
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* The passages two of a package's topics, or one of them and a Core topic,
|
|
61
|
+
* repeat word for word (architecture:cli-surface DEC-8). Reads the package's
|
|
62
|
+
* topics and Core's guides.
|
|
63
|
+
*
|
|
64
|
+
* @param {Parameters<typeof findCopiedPassages>[0]} discovered the package's
|
|
65
|
+
* docs, as discoverIntegrationDocs returns them
|
|
66
|
+
*/
|
|
67
|
+
export function integrationCopiedPassages(discovered) {
|
|
68
|
+
return findCopiedPassages(discovered);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Padding phrases and low-density topics in a package's prose
|
|
73
|
+
* (architecture:cli-surface DEC-8). Reads the package's topics, and Core's
|
|
74
|
+
* guides for the density median a finding names.
|
|
75
|
+
*
|
|
76
|
+
* @param {Parameters<typeof findFluff>[0]} discovered the package's docs, as
|
|
77
|
+
* discoverIntegrationDocs returns them
|
|
78
|
+
*/
|
|
79
|
+
export function integrationFluff(discovered) {
|
|
80
|
+
return findFluff(discovered);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Code spans in a package's prose that write `astryx docs <name>` for a doc
|
|
85
|
+
* that exists, where `{@link generic:<name>}` would be checked
|
|
86
|
+
* (architecture:cli-surface DEC-8). Reads the package's topics, its own
|
|
87
|
+
* component docs, and the names of Core's docs.
|
|
88
|
+
*
|
|
89
|
+
* @param {Parameters<typeof findStrayPointers>[0]} discovered the package's
|
|
90
|
+
* docs, as discoverIntegrationDocs returns them
|
|
91
|
+
* @param {any} [integration] the loaded integration, whose component docs are
|
|
92
|
+
* read too
|
|
93
|
+
*/
|
|
94
|
+
export async function integrationStrayPointers(discovered, integration) {
|
|
95
|
+
/** @type {{name: string, file: string}[]} */
|
|
96
|
+
const components = [];
|
|
97
|
+
if (integration?.components) {
|
|
98
|
+
const seen = new Set();
|
|
99
|
+
try {
|
|
100
|
+
const {components: records} =
|
|
101
|
+
await discoverValidIntegrationComponents(integration);
|
|
102
|
+
for (const record of records) {
|
|
103
|
+
if (!record.docPath || seen.has(record.docPath)) continue;
|
|
104
|
+
seen.add(record.docPath);
|
|
105
|
+
components.push({name: record.name, file: record.docPath});
|
|
106
|
+
}
|
|
107
|
+
} catch {
|
|
108
|
+
// `validate` reports component docs that do not load.
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return findStrayPointers({...discovered, components});
|
|
112
|
+
}
|
|
@@ -98,6 +98,72 @@ describe('integrationAddComponent name collisions', () => {
|
|
|
98
98
|
expect(snapshot()).toEqual(before);
|
|
99
99
|
});
|
|
100
100
|
|
|
101
|
+
it('adds a name a family doc lists but the module it imports does not export', async () => {
|
|
102
|
+
fs.writeFileSync(
|
|
103
|
+
path.join(tmpDir, 'package.json'),
|
|
104
|
+
`${JSON.stringify({name: '@acme/widgets', version: '1.0.0', files: ['dist'], exports: {'./tabs': './components/tabs/index.ts'}}, null, 2)}\n`,
|
|
105
|
+
);
|
|
106
|
+
const tabs = path.join(tmpDir, 'components', 'tabs');
|
|
107
|
+
fs.mkdirSync(tabs, {recursive: true});
|
|
108
|
+
fs.writeFileSync(
|
|
109
|
+
path.join(tabs, 'AcmeTabs.doc.mjs'),
|
|
110
|
+
"export default {type: 'component', name: 'AcmeTabs', import: '@acme/widgets/tabs', description: 'x', components: [{name: 'AcmeTabExtra', description: 'x'}]};\n",
|
|
111
|
+
);
|
|
112
|
+
fs.writeFileSync(
|
|
113
|
+
path.join(tabs, 'AcmeTabs.tsx'),
|
|
114
|
+
'export function AcmeTabs() { return null; }\nexport function AcmeTabExtra() { return null; }\n',
|
|
115
|
+
);
|
|
116
|
+
fs.writeFileSync(
|
|
117
|
+
path.join(tabs, 'index.ts'),
|
|
118
|
+
"export {AcmeTabs} from './AcmeTabs';\n",
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
const result = await integrationAdd('component', 'AcmeTabExtra', {
|
|
122
|
+
cwd: tmpDir,
|
|
123
|
+
dryRun: true,
|
|
124
|
+
});
|
|
125
|
+
expect(result.data.files).toContain('components/AcmeTabExtra.doc.mjs');
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it('refuses a member a family exports through built output', async () => {
|
|
129
|
+
fs.writeFileSync(
|
|
130
|
+
path.join(tmpDir, 'package.json'),
|
|
131
|
+
`${JSON.stringify({name: '@acme/widgets', version: '1.0.0', files: ['dist'], exports: {'./tabs': './dist/tabs/index.js'}}, null, 2)}\n`,
|
|
132
|
+
);
|
|
133
|
+
const tabs = path.join(tmpDir, 'components', 'tabs');
|
|
134
|
+
fs.mkdirSync(tabs, {recursive: true});
|
|
135
|
+
fs.writeFileSync(
|
|
136
|
+
path.join(tabs, 'AcmeTabs.doc.mjs'),
|
|
137
|
+
"export default {type: 'component', name: 'AcmeTabs', import: '@acme/widgets/tabs', description: 'x', components: [{name: 'AcmeTab', description: 'x'}]};\n",
|
|
138
|
+
);
|
|
139
|
+
fs.writeFileSync(
|
|
140
|
+
path.join(tabs, 'AcmeTabs.tsx'),
|
|
141
|
+
'export function AcmeTabs() { return null; }\n',
|
|
142
|
+
);
|
|
143
|
+
fs.writeFileSync(
|
|
144
|
+
path.join(tabs, 'AcmeTab.tsx'),
|
|
145
|
+
'export function AcmeTab() { return null; }\n',
|
|
146
|
+
);
|
|
147
|
+
const dist = path.join(tmpDir, 'dist', 'tabs');
|
|
148
|
+
fs.mkdirSync(dist, {recursive: true});
|
|
149
|
+
fs.writeFileSync(
|
|
150
|
+
path.join(dist, 'index.js'),
|
|
151
|
+
"export {AcmeTabs} from './tabs.js';\nexport {AcmeTab} from './tab.js';\n",
|
|
152
|
+
);
|
|
153
|
+
fs.writeFileSync(
|
|
154
|
+
path.join(dist, 'tabs.js'),
|
|
155
|
+
'export function AcmeTabs() { return null; }\n',
|
|
156
|
+
);
|
|
157
|
+
fs.writeFileSync(
|
|
158
|
+
path.join(dist, 'tab.js'),
|
|
159
|
+
'export function AcmeTab() { return null; }\n',
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
await expect(
|
|
163
|
+
integrationAdd('component', 'AcmeTab', {cwd: tmpDir, dryRun: true}),
|
|
164
|
+
).rejects.toThrow('Refusing to add component "AcmeTab"');
|
|
165
|
+
});
|
|
166
|
+
|
|
101
167
|
it('still adds a component whose name is free', async () => {
|
|
102
168
|
writeAuthoredComponent('components/AcmeWidget/AcmeWidget.doc.mjs');
|
|
103
169
|
|
|
@@ -264,9 +264,13 @@ async function addComponent(name, options) {
|
|
|
264
264
|
ERROR_CODES.ERR_FILE_EXISTS,
|
|
265
265
|
);
|
|
266
266
|
}
|
|
267
|
-
//
|
|
268
|
-
//
|
|
269
|
-
|
|
267
|
+
// A second doc under a name discovery already records, by a doc's file name
|
|
268
|
+
// anywhere under the root or by a name a doc documents, would shadow one of
|
|
269
|
+
// the two.
|
|
270
|
+
const existingDoc = findIntegrationComponentDoc(
|
|
271
|
+
{name: owner, components: root, __packageDir: packageDir},
|
|
272
|
+
name,
|
|
273
|
+
);
|
|
270
274
|
if (existingDoc != null) {
|
|
271
275
|
throw new AstryxError(
|
|
272
276
|
`Refusing to add component "${name}": ${projectPath(path.relative(packageDir, existingDoc))} already defines it.`,
|
|
@@ -691,7 +695,7 @@ async function addTemplate(name, options) {
|
|
|
691
695
|
const sourcePath = projectPath(path.relative(packageDir, sourceFile));
|
|
692
696
|
const extensionlessPath = sourcePath.replace(/\.tsx?$/u, '');
|
|
693
697
|
const blockFields = templateType === 'block' ? '\n aspectRatio: 1,' : '';
|
|
694
|
-
const specContents = `/** @type {import('@astryxdesign/cli/authoring').
|
|
698
|
+
const specContents = `/** @type {import('@astryxdesign/cli/authoring').IntegrationTemplateDoc} */\nexport default {\n type: '${templateType}',\n name: '${name}',\n displayName: '${kebabToTitle(name)}',\n description: '${kebabToTitle(name)} template.',${blockFields}\n};\n`;
|
|
695
699
|
const sourceContents = `export default function ${pascalName}() {\n return <div>${kebabToTitle(name)}</div>;\n}\n`;
|
|
696
700
|
|
|
697
701
|
/** @type {import('./add-helpers.mjs').WritePlan[]} */
|
|
@@ -536,7 +536,9 @@ describe('integrationAdd template', () => {
|
|
|
536
536
|
path.join(tmpDir, 'templates/my-widget.doc.mjs'),
|
|
537
537
|
'utf-8',
|
|
538
538
|
);
|
|
539
|
-
expect(spec).toContain(
|
|
539
|
+
expect(spec).toContain(
|
|
540
|
+
"@astryxdesign/cli/authoring').IntegrationTemplateDoc",
|
|
541
|
+
);
|
|
540
542
|
expect(spec).toContain("type: 'page'");
|
|
541
543
|
expect(spec).toContain("name: 'my-widget'");
|
|
542
544
|
|
|
@@ -830,7 +832,7 @@ describe('typed descriptor conformance', () => {
|
|
|
830
832
|
for (const [relativePath, type] of [
|
|
831
833
|
['components/MyWidget.doc.mjs', 'ComponentDoc'],
|
|
832
834
|
['docs/my-guide.doc.mjs', 'ReferenceDoc'],
|
|
833
|
-
['templates/my-page.doc.mjs', '
|
|
835
|
+
['templates/my-page.doc.mjs', 'IntegrationTemplateDoc'],
|
|
834
836
|
['themes/ocean/oceanTheme.doc.mjs', 'ThemeDoc'],
|
|
835
837
|
]) {
|
|
836
838
|
const source = fs.readFileSync(path.join(tmpDir, relativePath), 'utf-8');
|