@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
|
@@ -24,6 +24,7 @@ export const doc = {
|
|
|
24
24
|
{label: 'List posts', cli: 'astryx blog'},
|
|
25
25
|
{label: 'Read one post', cli: 'astryx blog introducing-astryx --json'},
|
|
26
26
|
],
|
|
27
|
+
outsideProject: 'same',
|
|
27
28
|
exitCodes: [
|
|
28
29
|
{code: 0, when: 'success'},
|
|
29
30
|
{code: 1, when: 'unknown slug, or the feed or a post cannot be fetched'},
|
|
@@ -91,12 +91,24 @@ function count(text, pattern) {
|
|
|
91
91
|
|
|
92
92
|
/** @param {string} stdout */
|
|
93
93
|
function lines(stdout) {
|
|
94
|
-
return stdout.split('\n').filter(Boolean);
|
|
94
|
+
return bareRecipe(stdout).split('\n').filter(Boolean);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* The font recipe names `docs typography` with the project's CLI invocation,
|
|
99
|
+
* which depends on where the test runs; compare it as bare `astryx`.
|
|
100
|
+
* @param {string} stdout
|
|
101
|
+
*/
|
|
102
|
+
function bareRecipe(stdout) {
|
|
103
|
+
return stdout.replace(
|
|
104
|
+
/(recipe: |guidance: )\S.*? docs typography/g,
|
|
105
|
+
'$1astryx docs typography',
|
|
106
|
+
);
|
|
95
107
|
}
|
|
96
108
|
|
|
97
109
|
/** @param {string} stdout The sizes follow Core's CSS, so goldens keep the shape. */
|
|
98
110
|
function normalized(stdout) {
|
|
99
|
-
return stdout.replace(/\d+(\.\d+)? KB/g, '<size> KB');
|
|
111
|
+
return bareRecipe(stdout).replace(/\d+(\.\d+)? KB/g, '<size> KB');
|
|
100
112
|
}
|
|
101
113
|
|
|
102
114
|
/** Bytes of the full report printed by one invocation per theme. */
|
|
@@ -168,7 +180,9 @@ describe('theme build report', () => {
|
|
|
168
180
|
}
|
|
169
181
|
expect(count(out, 'Install in your app')).toBe(1);
|
|
170
182
|
expect(count(out, 'Or with a <link> tag:')).toBe(1);
|
|
171
|
-
expect(
|
|
183
|
+
expect(
|
|
184
|
+
count(out, "import { Theme } from '@astryxdesign/core/theme';"),
|
|
185
|
+
).toBe(2);
|
|
172
186
|
expect(count(out, '[note]')).toBe(1);
|
|
173
187
|
expect(count(out, 'note: Font')).toBe(0);
|
|
174
188
|
expect(count(out, 'fonts.googleapis.com/css2')).toBe(1);
|
|
@@ -75,7 +75,7 @@ describe('theme build font-loading warning', () => {
|
|
|
75
75
|
expect(result.stdout).toContain('display=swap');
|
|
76
76
|
expect(result.stdout).toContain('@font-face');
|
|
77
77
|
expect(result.stdout).toContain('font-display: swap');
|
|
78
|
-
expect(result.stdout).toContain('
|
|
78
|
+
expect(result.stdout).toContain(' docs typography');
|
|
79
79
|
// The one-line summaries follow the CLI's stream contract. These are
|
|
80
80
|
// NOTICES about a correct theme, not warnings, so they go to stdout with
|
|
81
81
|
// the rest of the build's progress — stderr stays for the defects an
|
|
@@ -105,8 +105,8 @@ describe('theme build font-loading warning', () => {
|
|
|
105
105
|
);
|
|
106
106
|
|
|
107
107
|
expect(result.code).toBe(0);
|
|
108
|
-
expect(result.stdout).
|
|
109
|
-
|
|
108
|
+
expect(result.stdout).toMatch(
|
|
109
|
+
/\[note\] Fonts named but not loaded: "Space Grotesk", "JetBrains Mono"\. Load them in your app \(recipe: .+ docs typography\)\.\n/,
|
|
110
110
|
);
|
|
111
111
|
expect(result.stdout).not.toContain('fonts.googleapis.com');
|
|
112
112
|
expect(result.stdout).not.toContain('@font-face');
|
|
@@ -34,6 +34,7 @@ import * as path from 'node:path';
|
|
|
34
34
|
import {fileURLToPath} from 'node:url';
|
|
35
35
|
import {spawn} from 'node:child_process';
|
|
36
36
|
import {getCliInvocation} from '../../../foundation/env/package-manager.mjs';
|
|
37
|
+
import {isOutsideProject} from '../../../foundation/env/project-scope.mjs';
|
|
37
38
|
import {jsonOut} from '../../../foundation/response/json.mjs';
|
|
38
39
|
import {
|
|
39
40
|
emit,
|
|
@@ -224,10 +225,13 @@ async function runThemeBuildWatch(entries, options) {
|
|
|
224
225
|
emit(text(watchingLine));
|
|
225
226
|
|
|
226
227
|
await new Promise((/** @type {(value?: void) => void} */ resolve) => {
|
|
228
|
+
let stopping = false;
|
|
227
229
|
/** @param {NodeJS.Signals} signal */
|
|
228
230
|
const stop = async signal => {
|
|
229
|
-
|
|
230
|
-
|
|
231
|
+
// A second interrupt while stopping (a terminal's Ctrl-C and the same
|
|
232
|
+
// signal passed on by the copy that started the run) changes nothing.
|
|
233
|
+
if (stopping) return;
|
|
234
|
+
stopping = true;
|
|
231
235
|
stopped = true;
|
|
232
236
|
queued.clear();
|
|
233
237
|
for (const d of debounces.values()) clearTimeout(d);
|
|
@@ -237,10 +241,12 @@ async function runThemeBuildWatch(entries, options) {
|
|
|
237
241
|
rebuildChild?.kill(signal);
|
|
238
242
|
await rebuildDone;
|
|
239
243
|
emit(text('\nStopped watching.'));
|
|
244
|
+
process.removeListener('SIGINT', stop);
|
|
245
|
+
process.removeListener('SIGTERM', stop);
|
|
240
246
|
resolve();
|
|
241
247
|
};
|
|
242
|
-
process.
|
|
243
|
-
process.
|
|
248
|
+
process.on('SIGINT', stop);
|
|
249
|
+
process.on('SIGTERM', stop);
|
|
244
250
|
});
|
|
245
251
|
}
|
|
246
252
|
|
|
@@ -283,14 +289,24 @@ function printThemeAddList(themes) {
|
|
|
283
289
|
return theme.description ? [head, theme.description] : head;
|
|
284
290
|
}),
|
|
285
291
|
),
|
|
286
|
-
text(
|
|
287
|
-
`Import one: ${run} theme add <slug> [--package <package>]\n` +
|
|
288
|
-
`Fork source: ${run} theme eject <slug> [target-path]`,
|
|
289
|
-
),
|
|
292
|
+
text(themeNextSteps(run)),
|
|
290
293
|
more,
|
|
291
294
|
);
|
|
292
295
|
}
|
|
293
296
|
|
|
297
|
+
/**
|
|
298
|
+
* What to do with a listed theme. Outside a project there is no app to add one
|
|
299
|
+
* to, so only the fork step is named (spec AST-081 FR3).
|
|
300
|
+
* @param {string} run the CLI invocation
|
|
301
|
+
* @returns {string}
|
|
302
|
+
*/
|
|
303
|
+
function themeNextSteps(run) {
|
|
304
|
+
const fork = `Fork source: ${run} theme eject <slug> [target-path]`;
|
|
305
|
+
return isOutsideProject()
|
|
306
|
+
? fork
|
|
307
|
+
: `Import one: ${run} theme add <slug> [--package <package>]\n${fork}`;
|
|
308
|
+
}
|
|
309
|
+
|
|
294
310
|
/**
|
|
295
311
|
* Print every field in the `theme.list` entries. Duplicate slugs stay separate
|
|
296
312
|
* because each record names its owner.
|
|
@@ -325,10 +341,7 @@ function printThemeList(themes, unmigratedCopies = []) {
|
|
|
325
341
|
default: (/** @type {boolean} */ value) => (value ? 'yes' : 'no'),
|
|
326
342
|
},
|
|
327
343
|
}),
|
|
328
|
-
text(
|
|
329
|
-
`Import one: ${run} theme add <slug> [--package <package>]\n` +
|
|
330
|
-
`Fork source: ${run} theme eject <slug> [target-path]`,
|
|
331
|
-
),
|
|
344
|
+
text(themeNextSteps(run)),
|
|
332
345
|
more,
|
|
333
346
|
);
|
|
334
347
|
}
|
|
@@ -397,7 +410,7 @@ function printThemeApp(result) {
|
|
|
397
410
|
emit(
|
|
398
411
|
text('Wire the generated module once in the app root:'),
|
|
399
412
|
code(
|
|
400
|
-
"import {Theme} from '@astryxdesign/core';\n" +
|
|
413
|
+
"import {Theme} from '@astryxdesign/core/theme';\n" +
|
|
401
414
|
`import {themes, defaultThemeSlug} from './${stem}';\n\n` +
|
|
402
415
|
'<Theme theme={themes[defaultThemeSlug]}>\n <App />\n</Theme>',
|
|
403
416
|
),
|
|
@@ -9,6 +9,12 @@
|
|
|
9
9
|
* - Multi-file write is atomic: if one file fails, none are left behind.
|
|
10
10
|
* - An `--out` escape, or an output directory that cannot be created, fails
|
|
11
11
|
* with a registered error code.
|
|
12
|
+
* - Every output a build writes stays inside the working directory: an
|
|
13
|
+
* absolute `--out` path or a theme file outside it fails before anything
|
|
14
|
+
* is written, while absolute paths inside it build, also through a
|
|
15
|
+
* symlinked spelling. `--check` writes nothing, so it compares those
|
|
16
|
+
* outside outputs read-only, and a stale report for them ends with a
|
|
17
|
+
* remedy that works: the directory to build and check from.
|
|
12
18
|
*
|
|
13
19
|
* Runs the CLI in-process (shared runCli harness) against a tiny synthetic theme file.
|
|
14
20
|
*/
|
|
@@ -22,6 +28,7 @@ import {runCli} from '../../../test-utils/run-cli.mjs';
|
|
|
22
28
|
import {themeBuild} from '../../../api/theme/build/build.mjs';
|
|
23
29
|
import {AstryxError} from '../../../api/error.mjs';
|
|
24
30
|
import {ERROR_CODES} from '../../../foundation/response/error-codes.mjs';
|
|
31
|
+
import {getCliInvocation} from '../../../foundation/env/package-manager.mjs';
|
|
25
32
|
|
|
26
33
|
function writeTheme(dir, name) {
|
|
27
34
|
fs.mkdirSync(dir, {recursive: true});
|
|
@@ -59,7 +66,9 @@ describe('theme build path safety', () => {
|
|
|
59
66
|
);
|
|
60
67
|
|
|
61
68
|
expect(result.code).not.toBe(0);
|
|
62
|
-
expect(result.stderr + result.stdout).toMatch(
|
|
69
|
+
expect(result.stderr + result.stdout).toMatch(
|
|
70
|
+
/path separator|invalid theme name/i,
|
|
71
|
+
);
|
|
63
72
|
|
|
64
73
|
// The traversal target must not exist.
|
|
65
74
|
expect(fs.existsSync(path.join(tmpDir, 'escaped.js'))).toBe(false);
|
|
@@ -92,7 +101,10 @@ describe('theme build path safety', () => {
|
|
|
92
101
|
|
|
93
102
|
const themeFile = writeTheme(themesDir, '../leak');
|
|
94
103
|
|
|
95
|
-
await runCli(
|
|
104
|
+
await runCli(
|
|
105
|
+
['theme', 'build', path.relative(project, themeFile)],
|
|
106
|
+
project,
|
|
107
|
+
);
|
|
96
108
|
|
|
97
109
|
// Neither the CSS nor any sibling JS should have been written.
|
|
98
110
|
const entries = fs.readdirSync(themesDir).sort();
|
|
@@ -114,19 +126,200 @@ describe('theme build output-path failures carry registered codes', () => {
|
|
|
114
126
|
return {result, envelope: JSON.parse(result.stdout)};
|
|
115
127
|
}
|
|
116
128
|
|
|
117
|
-
it('reports
|
|
129
|
+
it('reports a relative --out path outside the project as ERR_PATH_TRAVERSAL, with --check too', async () => {
|
|
118
130
|
const project = path.join(tmpDir, 'project');
|
|
119
131
|
const themeFile = writeTheme(path.join(project, 'themes'), 'ocean');
|
|
120
132
|
|
|
133
|
+
for (const extra of [[], ['--check']]) {
|
|
134
|
+
const {result, envelope} = await buildJson(
|
|
135
|
+
[
|
|
136
|
+
path.relative(project, themeFile),
|
|
137
|
+
'--out',
|
|
138
|
+
'../escaped.css',
|
|
139
|
+
...extra,
|
|
140
|
+
],
|
|
141
|
+
project,
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
expect(result.code).toBe(1);
|
|
145
|
+
expect(envelope.code).toBe(ERROR_CODES.ERR_PATH_TRAVERSAL);
|
|
146
|
+
expect(registered.has(envelope.code)).toBe(true);
|
|
147
|
+
}
|
|
148
|
+
expect(fs.existsSync(path.join(tmpDir, 'escaped.css'))).toBe(false);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it('reports an absolute --out path outside the project as ERR_PATH_TRAVERSAL', async () => {
|
|
152
|
+
const project = path.join(tmpDir, 'project');
|
|
153
|
+
const outside = path.join(tmpDir, 'outside');
|
|
154
|
+
fs.mkdirSync(outside, {recursive: true});
|
|
155
|
+
const themeFile = writeTheme(path.join(project, 'themes'), 'ocean');
|
|
156
|
+
const out = path.join(outside, 'ocean.css');
|
|
157
|
+
|
|
121
158
|
const {result, envelope} = await buildJson(
|
|
122
|
-
[path.relative(project, themeFile), '--out',
|
|
159
|
+
[path.relative(project, themeFile), '--out', out],
|
|
123
160
|
project,
|
|
124
161
|
);
|
|
125
162
|
|
|
126
163
|
expect(result.code).toBe(1);
|
|
127
164
|
expect(envelope.code).toBe(ERROR_CODES.ERR_PATH_TRAVERSAL);
|
|
128
|
-
expect(
|
|
129
|
-
|
|
165
|
+
expect(fs.readdirSync(outside)).toEqual([]);
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it('checks an absolute --out path outside the project read-only', async () => {
|
|
169
|
+
const project = path.join(tmpDir, 'project');
|
|
170
|
+
const outside = path.join(tmpDir, 'outside');
|
|
171
|
+
fs.mkdirSync(outside, {recursive: true});
|
|
172
|
+
const themeFile = path.relative(
|
|
173
|
+
project,
|
|
174
|
+
writeTheme(path.join(project, 'themes'), 'ocean'),
|
|
175
|
+
);
|
|
176
|
+
const out = path.join(outside, 'ocean.css');
|
|
177
|
+
|
|
178
|
+
const missing = await buildJson(
|
|
179
|
+
[themeFile, '--out', out, '--check'],
|
|
180
|
+
project,
|
|
181
|
+
);
|
|
182
|
+
expect(missing.result.code).toBe(1);
|
|
183
|
+
expect(missing.envelope.type).toBe('theme.build.check');
|
|
184
|
+
expect(missing.envelope.data.upToDate).toBe(false);
|
|
185
|
+
expect(fs.readdirSync(outside)).toEqual([]);
|
|
186
|
+
|
|
187
|
+
// Outputs built inside the project compare equal once copied outside:
|
|
188
|
+
// only the volatile Command line, which --check ignores, names --out.
|
|
189
|
+
const dist = path.join(project, 'dist');
|
|
190
|
+
const built = await buildJson(
|
|
191
|
+
[themeFile, '--out', path.join(dist, 'ocean.css')],
|
|
192
|
+
project,
|
|
193
|
+
);
|
|
194
|
+
expect(built.result.code).toBe(0);
|
|
195
|
+
for (const file of fs.readdirSync(dist)) {
|
|
196
|
+
fs.copyFileSync(path.join(dist, file), path.join(outside, file));
|
|
197
|
+
}
|
|
198
|
+
const copied = fs.readdirSync(outside).sort();
|
|
199
|
+
|
|
200
|
+
const current = await buildJson(
|
|
201
|
+
[themeFile, '--out', out, '--check'],
|
|
202
|
+
project,
|
|
203
|
+
);
|
|
204
|
+
expect(current.result.code).toBe(0);
|
|
205
|
+
expect(current.envelope.type).toBe('theme.build.check');
|
|
206
|
+
expect(current.envelope.data.upToDate).toBe(true);
|
|
207
|
+
expect(fs.readdirSync(outside).sort()).toEqual(copied);
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
it('reports a theme file outside the project as ERR_PATH_TRAVERSAL, because its outputs go beside it; --check only compares them', async () => {
|
|
211
|
+
const project = path.join(tmpDir, 'project');
|
|
212
|
+
fs.mkdirSync(project, {recursive: true});
|
|
213
|
+
const shared = path.join(tmpDir, 'shared');
|
|
214
|
+
const themeFile = writeTheme(shared, 'ocean');
|
|
215
|
+
|
|
216
|
+
for (const file of [themeFile, path.relative(project, themeFile)]) {
|
|
217
|
+
const {result, envelope} = await buildJson([file], project);
|
|
218
|
+
|
|
219
|
+
expect(result.code).toBe(1);
|
|
220
|
+
expect(envelope.code).toBe(ERROR_CODES.ERR_PATH_TRAVERSAL);
|
|
221
|
+
|
|
222
|
+
const checked = await buildJson([file, '--check'], project);
|
|
223
|
+
expect(checked.result.code).toBe(1);
|
|
224
|
+
expect(checked.envelope.type).toBe('theme.build.check');
|
|
225
|
+
expect(checked.envelope.data.upToDate).toBe(false);
|
|
226
|
+
}
|
|
227
|
+
expect(fs.readdirSync(shared)).toEqual(['theme.mjs']);
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Read the remedy that ends a stale report for outputs outside cwd: the
|
|
232
|
+
* directory to run from, then the build and check arguments after `theme
|
|
233
|
+
* build`. Each command starts with the install-aware invocation for it.
|
|
234
|
+
* @param {string} stderr
|
|
235
|
+
*/
|
|
236
|
+
function readRemedy(stderr) {
|
|
237
|
+
const lines = stderr.split('\n').map(line => line.trim());
|
|
238
|
+
const cd = lines.find(line => line.startsWith('cd '));
|
|
239
|
+
expect(cd).toBeDefined();
|
|
240
|
+
const dir = /** @type {string} */ (cd).slice('cd '.length);
|
|
241
|
+
const stem = `${getCliInvocation(dir)} theme build `;
|
|
242
|
+
const commands = lines.filter(line => line.startsWith(stem));
|
|
243
|
+
expect(commands).toHaveLength(2);
|
|
244
|
+
const [build, check] = commands.map(line =>
|
|
245
|
+
line.slice(stem.length).split(' '),
|
|
246
|
+
);
|
|
247
|
+
expect(check).toEqual([...build, '--check']);
|
|
248
|
+
return {dir, build, check};
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
it('ends a stale report for outputs outside cwd with a remedy that works, and keeps the report for outputs inside it', async () => {
|
|
252
|
+
const project = path.join(tmpDir, 'project');
|
|
253
|
+
const inside = path.relative(
|
|
254
|
+
project,
|
|
255
|
+
writeTheme(path.join(project, 'themes'), 'ocean'),
|
|
256
|
+
);
|
|
257
|
+
const shared = writeTheme(path.join(tmpDir, 'shared'), 'ocean');
|
|
258
|
+
const outside = path.join(tmpDir, 'outside');
|
|
259
|
+
|
|
260
|
+
for (const args of [
|
|
261
|
+
[path.relative(project, shared)],
|
|
262
|
+
[inside, '--out', path.join(outside, 'ocean.css')],
|
|
263
|
+
]) {
|
|
264
|
+
const stale = await runCli(
|
|
265
|
+
['theme', 'build', ...args, '--check'],
|
|
266
|
+
project,
|
|
267
|
+
);
|
|
268
|
+
expect(stale.code).toBe(1);
|
|
269
|
+
// The old remedy ran the build from cwd, which refuses these outputs.
|
|
270
|
+
expect(stale.stderr).not.toContain('Rebuild with:');
|
|
271
|
+
expect(stale.stderr).not.toContain(`theme build ${args.join(' ')}`);
|
|
272
|
+
|
|
273
|
+
// Following the remedy builds, and the check from there passes.
|
|
274
|
+
const remedy = readRemedy(stale.stderr);
|
|
275
|
+
const built = await runCli(
|
|
276
|
+
['theme', 'build', ...remedy.build],
|
|
277
|
+
remedy.dir,
|
|
278
|
+
);
|
|
279
|
+
expect(built.code).toBe(0);
|
|
280
|
+
const checked = await runCli(
|
|
281
|
+
['--json', 'theme', 'build', ...remedy.check],
|
|
282
|
+
remedy.dir,
|
|
283
|
+
);
|
|
284
|
+
expect(checked.code).toBe(0);
|
|
285
|
+
expect(JSON.parse(checked.stdout).data.upToDate).toBe(true);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// Outputs inside cwd keep the plain rebuild line.
|
|
289
|
+
const local = await runCli(['theme', 'build', inside, '--check'], project);
|
|
290
|
+
expect(local.code).toBe(1);
|
|
291
|
+
expect(local.stderr).toContain(
|
|
292
|
+
`Rebuild with: astryx theme build ${inside}`,
|
|
293
|
+
);
|
|
294
|
+
expect(local.stderr).not.toMatch(/^\s*cd /m);
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
it('builds absolute paths inside the project, also when they reach it through a symlink', async () => {
|
|
298
|
+
const project = path.join(tmpDir, 'project');
|
|
299
|
+
const themeFile = writeTheme(path.join(project, 'themes'), 'ocean');
|
|
300
|
+
const alias = path.join(tmpDir, 'alias');
|
|
301
|
+
fs.symlinkSync(project, alias, 'dir');
|
|
302
|
+
|
|
303
|
+
for (const [args, written] of [
|
|
304
|
+
[
|
|
305
|
+
[themeFile, '--out', path.join(project, 'dist', 'direct.css')],
|
|
306
|
+
path.join(project, 'dist', 'direct.css'),
|
|
307
|
+
],
|
|
308
|
+
[
|
|
309
|
+
[themeFile, '--out', path.join(alias, 'dist', 'aliased.css')],
|
|
310
|
+
path.join(project, 'dist', 'aliased.css'),
|
|
311
|
+
],
|
|
312
|
+
[
|
|
313
|
+
[path.join(alias, 'themes', 'theme.mjs')],
|
|
314
|
+
path.join(project, 'themes', 'ocean.css'),
|
|
315
|
+
],
|
|
316
|
+
]) {
|
|
317
|
+
const {result, envelope} = await buildJson(args, project);
|
|
318
|
+
|
|
319
|
+
expect(result.code).toBe(0);
|
|
320
|
+
expect(envelope.type).toBe('theme.build');
|
|
321
|
+
expect(fs.existsSync(written)).toBe(true);
|
|
322
|
+
}
|
|
130
323
|
});
|
|
131
324
|
|
|
132
325
|
it('reports an --out path that escapes through a symlink as ERR_PATH_TRAVERSAL', async () => {
|
|
@@ -177,4 +370,29 @@ describe('theme build output-path failures carry registered codes', () => {
|
|
|
177
370
|
code: ERROR_CODES.ERR_PATH_TRAVERSAL,
|
|
178
371
|
});
|
|
179
372
|
});
|
|
373
|
+
|
|
374
|
+
it('themeBuild() rejects an output outside cwd, an absolute out path or the default beside a theme file outside cwd, and checks it read-only', async () => {
|
|
375
|
+
const project = path.join(tmpDir, 'project');
|
|
376
|
+
const inside = writeTheme(path.join(project, 'themes'), 'ocean');
|
|
377
|
+
const shared = path.join(tmpDir, 'shared');
|
|
378
|
+
const outsideTheme = writeTheme(shared, 'ocean');
|
|
379
|
+
const outDir = path.join(tmpDir, 'out');
|
|
380
|
+
|
|
381
|
+
for (const [file, options] of [
|
|
382
|
+
[path.relative(project, inside), {out: path.join(outDir, 'ocean.css')}],
|
|
383
|
+
[outsideTheme, {}],
|
|
384
|
+
]) {
|
|
385
|
+
await expect(
|
|
386
|
+
themeBuild(file, options, {cwd: project}),
|
|
387
|
+
).rejects.toMatchObject({code: ERROR_CODES.ERR_PATH_TRAVERSAL});
|
|
388
|
+
await expect(
|
|
389
|
+
themeBuild(file, {...options, check: true}, {cwd: project}),
|
|
390
|
+
).resolves.toMatchObject({
|
|
391
|
+
type: 'theme.build.check',
|
|
392
|
+
data: {upToDate: false},
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
expect(fs.existsSync(outDir)).toBe(false);
|
|
396
|
+
expect(fs.readdirSync(shared)).toEqual(['theme.mjs']);
|
|
397
|
+
});
|
|
180
398
|
});
|
|
@@ -126,7 +126,10 @@ describe('theme build emits a live TextInput selector (#4109)', () => {
|
|
|
126
126
|
`};\n`,
|
|
127
127
|
);
|
|
128
128
|
|
|
129
|
-
const result = await runCli(
|
|
129
|
+
const result = await runCli(
|
|
130
|
+
['theme', 'build', themeFile, '-o', outFile],
|
|
131
|
+
tmpDir,
|
|
132
|
+
);
|
|
130
133
|
const css = fs.readFileSync(outFile, 'utf8');
|
|
131
134
|
|
|
132
135
|
expect(result.status).toBe(0);
|
|
@@ -148,7 +151,7 @@ describe('theme build emits a live TextInput selector (#4109)', () => {
|
|
|
148
151
|
`};\n`,
|
|
149
152
|
);
|
|
150
153
|
|
|
151
|
-
await runCli(['theme', 'build', themeFile, '-o', outFile]);
|
|
154
|
+
await runCli(['theme', 'build', themeFile, '-o', outFile], tmpDir);
|
|
152
155
|
const css = fs.readFileSync(outFile, 'utf8');
|
|
153
156
|
|
|
154
157
|
expect(css).toContain('.astryx-text-input');
|
|
@@ -11,6 +11,7 @@ import * as os from 'node:os';
|
|
|
11
11
|
import * as path from 'node:path';
|
|
12
12
|
import {runCli} from '../../../test-utils/run-cli.mjs';
|
|
13
13
|
import {doc as buildDoc} from './build.doc.mjs';
|
|
14
|
+
import {linkThisCliAsProjectCli} from '../../../test-utils/release-fixtures.mjs';
|
|
14
15
|
|
|
15
16
|
const SLOW = 30_000;
|
|
16
17
|
|
|
@@ -20,6 +21,9 @@ let tmpDir;
|
|
|
20
21
|
beforeEach(() => {
|
|
21
22
|
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'astryx-build-no-core-'));
|
|
22
23
|
fs.writeFileSync(path.join(tmpDir, 'package.json'), JSON.stringify({name: 'consumer'}));
|
|
24
|
+
// A project whose own CLI answers and that installs no Core: outside a
|
|
25
|
+
// project a copy answers from the Core it carries instead (AST-081 FR3).
|
|
26
|
+
linkThisCliAsProjectCli(tmpDir);
|
|
23
27
|
});
|
|
24
28
|
|
|
25
29
|
afterEach(() => {
|
|
@@ -8,9 +8,16 @@
|
|
|
8
8
|
* transient fetch (path _npx or npm_command=exec), and once set up.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import {describe, it, expect} from 'vitest';
|
|
11
|
+
import {describe, it, expect, beforeEach, afterEach} from 'vitest';
|
|
12
|
+
import {spawnSync} from 'node:child_process';
|
|
13
|
+
import * as fs from 'node:fs';
|
|
14
|
+
import * as os from 'node:os';
|
|
15
|
+
import * as path from 'node:path';
|
|
16
|
+
import {fileURLToPath} from 'node:url';
|
|
12
17
|
import {shouldNudge} from '../../../scripts/postinstall.mjs';
|
|
13
18
|
|
|
19
|
+
const CLI = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../..');
|
|
20
|
+
|
|
14
21
|
const DEP = '/proj/node_modules/@astryxdesign/cli/scripts/postinstall.mjs'; // real dep install
|
|
15
22
|
const NPX = '/Users/x/.npm/_npx/a1b2/node_modules/@astryxdesign/cli/scripts/postinstall.mjs';
|
|
16
23
|
const REPO = '/repo/packages/cli/scripts/postinstall.mjs'; // monorepo/source
|
|
@@ -40,3 +47,44 @@ describe('cli postinstall — shouldNudge', () => {
|
|
|
40
47
|
expect(shouldNudge({})).toBe(false);
|
|
41
48
|
});
|
|
42
49
|
});
|
|
50
|
+
|
|
51
|
+
// Install time, end to end: the real script and the leaf it loads, installed
|
|
52
|
+
// under a monorepo's node_modules, run the way npm runs them for a package.
|
|
53
|
+
describe('cli postinstall — inside a monorepo package', () => {
|
|
54
|
+
let repo;
|
|
55
|
+
beforeEach(() => {
|
|
56
|
+
repo = fs.mkdtempSync(path.join(os.tmpdir(), 'astryx-cli-postinstall-'));
|
|
57
|
+
fs.mkdirSync(path.join(repo, '.git'));
|
|
58
|
+
fs.mkdirSync(path.join(repo, 'packages/app'), {recursive: true});
|
|
59
|
+
fs.writeFileSync(path.join(repo, 'packages/app/package.json'), '{"name":"app"}');
|
|
60
|
+
const installed = path.join(repo, 'node_modules/@astryxdesign/cli');
|
|
61
|
+
for (const rel of ['scripts/postinstall.mjs', 'foundation/agent-docs/agent-doc-state.mjs']) {
|
|
62
|
+
fs.mkdirSync(path.dirname(path.join(installed, rel)), {recursive: true});
|
|
63
|
+
fs.copyFileSync(path.join(CLI, rel), path.join(installed, rel));
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
afterEach(() => fs.rmSync(repo, {recursive: true, force: true}));
|
|
67
|
+
|
|
68
|
+
const install = () =>
|
|
69
|
+
spawnSync(
|
|
70
|
+
process.execPath,
|
|
71
|
+
[path.join(repo, 'node_modules/@astryxdesign/cli/scripts/postinstall.mjs')],
|
|
72
|
+
{
|
|
73
|
+
env: {...process.env, INIT_CWD: path.join(repo, 'packages/app'), npm_command: 'install'},
|
|
74
|
+
encoding: 'utf8',
|
|
75
|
+
},
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
it('stays quiet when init ran at the repository root', () => {
|
|
79
|
+
fs.writeFileSync(path.join(repo, 'AGENTS.md'), '<!-- ASTRYX:START -->\n');
|
|
80
|
+
const r = install();
|
|
81
|
+
expect(r.status).toBe(0);
|
|
82
|
+
expect(r.stdout).toBe('');
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('still nudges when no folder up to the repository root ran init', () => {
|
|
86
|
+
const r = install();
|
|
87
|
+
expect(r.status).toBe(0);
|
|
88
|
+
expect(r.stdout).toMatch(/finish setup and install the Astryx agent prompt/);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
@@ -68,8 +68,8 @@ describe('astryx discover with a manifest that fails to load', () => {
|
|
|
68
68
|
const {status, stdout, stderr} = await runCli(['discover'], {cwd: project});
|
|
69
69
|
|
|
70
70
|
expect(status).toBe(0);
|
|
71
|
-
expect(stderr).
|
|
72
|
-
|
|
71
|
+
expect(stderr).toMatch(
|
|
72
|
+
/Warning: @test\/broken has 1 integration issue\(s\)\. Run: .+ doctor/,
|
|
73
73
|
);
|
|
74
74
|
expect(stdout).not.toContain('No integrations configured.');
|
|
75
75
|
expect(stdout).toContain(
|
|
@@ -83,7 +83,11 @@ describe('astryx discover with a manifest that fails to load', () => {
|
|
|
83
83
|
});
|
|
84
84
|
|
|
85
85
|
expect(status).toBe(0);
|
|
86
|
-
|
|
86
|
+
const {meta} = JSON.parse(stdout);
|
|
87
|
+
expect(meta.configured).toBe(true);
|
|
88
|
+
// The official list still answers; nothing else is claimed.
|
|
89
|
+
expect(meta.sources.map(s => s.name)).toEqual(['Astryx']);
|
|
90
|
+
expect(meta.answeredBy).toEqual(expect.any(Object));
|
|
87
91
|
expect(stderr).not.toContain('integration issue');
|
|
88
92
|
});
|
|
89
93
|
});
|
|
@@ -129,8 +133,8 @@ describe('astryx discover with a configured package that is not installed', () =
|
|
|
129
133
|
const {status, stderr} = await runCli(['discover'], {cwd: project});
|
|
130
134
|
|
|
131
135
|
expect(status).toBe(0);
|
|
132
|
-
expect(stderr).
|
|
133
|
-
|
|
136
|
+
expect(stderr).toMatch(
|
|
137
|
+
/Warning: @test\/missing has 1 integration issue\(s\)\. Run: .+ doctor\n/,
|
|
134
138
|
);
|
|
135
139
|
});
|
|
136
140
|
});
|
|
@@ -148,8 +152,8 @@ describe('astryx search with a manifest that fails to load', () => {
|
|
|
148
152
|
const {status, stderr} = await runCli(['search', 'button'], {cwd: project});
|
|
149
153
|
|
|
150
154
|
expect(status).toBe(0);
|
|
151
|
-
expect(stderr).
|
|
152
|
-
|
|
155
|
+
expect(stderr).toMatch(
|
|
156
|
+
/Warning: @test\/broken has 1 integration issue\(s\)\. Run: .+ doctor/,
|
|
153
157
|
);
|
|
154
158
|
|
|
155
159
|
const asJson = await runCli(['search', 'button', '--json'], {cwd: project});
|
|
@@ -17,7 +17,8 @@ export const doc = {
|
|
|
17
17
|
summary:
|
|
18
18
|
'Browse and search integrations: the ones you have and the ones you could add',
|
|
19
19
|
description:
|
|
20
|
-
'Lists the integrations
|
|
20
|
+
'Lists what this project has, the integrations it loads and the official packages it declares, then what it could add: the official Astryx packages first, then whatever its discover sources list, with what each one adds. ' +
|
|
21
|
+
'Inside a project, integrations installed for the computer, beside the CLI installed for it, are listed as ones the project could add, with its install command; outside one they load. ' +
|
|
21
22
|
'A package query shows one package: what it adds, every version a source knows, and the command that adds it. ' +
|
|
22
23
|
"An @scope/name/Component path prints an installed component's doc; any other item path shows that item. " +
|
|
23
24
|
'Anything else, even an exact component name, searches every item and package and lists the matches. Discover only reads: your package manager installs, updates, and removes packages.',
|
|
@@ -78,6 +79,7 @@ export const doc = {
|
|
|
78
79
|
cli: 'astryx discover dashboard --type template --available',
|
|
79
80
|
},
|
|
80
81
|
],
|
|
82
|
+
outsideProject: 'same',
|
|
81
83
|
exitCodes: [
|
|
82
84
|
{code: 0, when: 'success'},
|
|
83
85
|
{
|
|
@@ -86,4 +88,10 @@ export const doc = {
|
|
|
86
88
|
},
|
|
87
89
|
],
|
|
88
90
|
related: ['component', 'search', 'template'],
|
|
91
|
+
notes: [
|
|
92
|
+
{
|
|
93
|
+
type: 'prose',
|
|
94
|
+
text: "In global mode: outside a project, integrations installed next to your global install are listed as installed and their items show up; inside a project, only the project's integrations are, and the global ones the project could add are listed under available, with the project's install command. In a project, the project's version of Astryx runs it, whichever astryx command you start. See {@link namespace:global} and {@link generic:computer-integrations}.",
|
|
95
|
+
},
|
|
96
|
+
],
|
|
89
97
|
};
|