@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
|
@@ -13,6 +13,7 @@ import {themeBuild, themeBuildFamily} from './build.mjs';
|
|
|
13
13
|
import {interceptCore} from './core-interception.mjs';
|
|
14
14
|
import {ensureCoreBuilt} from '../../../clients/cli/commands/ensure-core-built.mjs';
|
|
15
15
|
import {runCli} from '../../../test-utils/run-cli.mjs';
|
|
16
|
+
import {getCliInvocation} from '../../../foundation/env/package-manager.mjs';
|
|
16
17
|
vi.setConfig({testTimeout: 120_000});
|
|
17
18
|
const CLI_ROOT = path.resolve(import.meta.dirname, '../../..');
|
|
18
19
|
const FAMILY_KEY = 'ocean-family';
|
|
@@ -252,6 +253,69 @@ describe('themeBuildFamily()', () => {
|
|
|
252
253
|
expect(fs.existsSync(dtsPath)).toBe(false);
|
|
253
254
|
});
|
|
254
255
|
|
|
256
|
+
it('refuses to write family outputs outside cwd, and checks them read-only', async () => {
|
|
257
|
+
const dir = makeDir();
|
|
258
|
+
const files = writeFamily(dir).map(file => path.join(dir, file));
|
|
259
|
+
const app = path.join(dir, 'app');
|
|
260
|
+
fs.mkdirSync(app);
|
|
261
|
+
|
|
262
|
+
await expect(
|
|
263
|
+
themeBuildFamily(files, {familyKey: FAMILY_KEY}, {cwd: app}),
|
|
264
|
+
).rejects.toMatchObject({code: 'ERR_PATH_TRAVERSAL'});
|
|
265
|
+
const checked = await themeBuildFamily(
|
|
266
|
+
files,
|
|
267
|
+
{familyKey: FAMILY_KEY, check: true},
|
|
268
|
+
{cwd: app},
|
|
269
|
+
);
|
|
270
|
+
expect(checked?.type).toBe('theme.build.check');
|
|
271
|
+
expect(checked?.data.upToDate).toBe(false);
|
|
272
|
+
// The `.css.d.ts` import stub may be absent in check mode.
|
|
273
|
+
expect(checked?.data.stale).toEqual(
|
|
274
|
+
OUTPUTS.filter(file => !file.endsWith('.css.d.ts')).map(file => ({
|
|
275
|
+
path: `../themes/${file}`,
|
|
276
|
+
reason: 'missing',
|
|
277
|
+
})),
|
|
278
|
+
);
|
|
279
|
+
for (const output of OUTPUTS) {
|
|
280
|
+
expect(fs.existsSync(path.join(dir, 'themes', output))).toBe(false);
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
it('ends a stale family report for outputs outside cwd with a remedy that works', async () => {
|
|
285
|
+
const dir = makeDir();
|
|
286
|
+
const files = writeFamily(dir).map(file => path.join(dir, file));
|
|
287
|
+
const app = path.join(dir, 'app');
|
|
288
|
+
fs.mkdirSync(app);
|
|
289
|
+
const family = ['--family', ...files, '--family-key', FAMILY_KEY];
|
|
290
|
+
|
|
291
|
+
const stale = await runCli(['theme', 'build', ...family, '--check'], app);
|
|
292
|
+
expect(stale.code).toBe(1);
|
|
293
|
+
// The old remedy ran the build from cwd, which refuses these outputs.
|
|
294
|
+
expect(stale.stderr).not.toContain('Rebuild with:');
|
|
295
|
+
|
|
296
|
+
const lines = stale.stderr.split('\n').map(line => line.trim());
|
|
297
|
+
const runDir = lines.find(line => line.startsWith('cd '))?.slice(3);
|
|
298
|
+
expect(runDir).toBe(fs.realpathSync(path.join(dir, 'themes')));
|
|
299
|
+
const stem = `${getCliInvocation(runDir)} theme build `;
|
|
300
|
+
const [buildArgs, checkArgs] = lines
|
|
301
|
+
.filter(line => line.startsWith(stem))
|
|
302
|
+
.map(line => line.slice(stem.length).split(' '));
|
|
303
|
+
expect(checkArgs).toEqual([...buildArgs, '--check']);
|
|
304
|
+
|
|
305
|
+
// Following the remedy builds, and the check from there passes.
|
|
306
|
+
const built = await runCli(['theme', 'build', ...buildArgs], runDir);
|
|
307
|
+
expect(built.code).toBe(0);
|
|
308
|
+
for (const output of OUTPUTS) {
|
|
309
|
+
expect(fs.existsSync(path.join(dir, 'themes', output))).toBe(true);
|
|
310
|
+
}
|
|
311
|
+
const checked = await runCli(
|
|
312
|
+
['--json', 'theme', 'build', ...checkArgs],
|
|
313
|
+
runDir,
|
|
314
|
+
);
|
|
315
|
+
expect(checked.code).toBe(0);
|
|
316
|
+
expect(JSON.parse(checked.stdout).data.upToDate).toBe(true);
|
|
317
|
+
});
|
|
318
|
+
|
|
255
319
|
it('fails without publishing a mixed trio when staging a write fails', async () => {
|
|
256
320
|
const dir = makeDir();
|
|
257
321
|
const files = writeFamily(dir);
|
|
@@ -27,6 +27,10 @@
|
|
|
27
27
|
* files; an internal callback lets the CLI make only the process status fail.
|
|
28
28
|
* Human progress is emitted through the shared `logger` (silent by default), so
|
|
29
29
|
* the CLI keeps its exact output while a programmatic caller stays quiet.
|
|
30
|
+
* Every output a build writes, explicit or beside the theme file, stays inside
|
|
31
|
+
* `cwd` (`ERR_PATH_TRAVERSAL` otherwise). Check mode writes nothing, so it
|
|
32
|
+
* compares outputs outside `cwd` read-only; only a relative `out` path that
|
|
33
|
+
* escapes `cwd` is refused there too.
|
|
30
34
|
*
|
|
31
35
|
* The installed `@astryxdesign/core` is an independently versioned optional
|
|
32
36
|
* peer, so it can be older than the CLI. A theme that uses only baseline
|
|
@@ -58,12 +62,19 @@ import {isBuiltin} from 'node:module';
|
|
|
58
62
|
import {fileURLToPath, pathToFileURL} from 'node:url';
|
|
59
63
|
import {parse} from '@babel/parser';
|
|
60
64
|
import {createJiti} from 'jiti';
|
|
61
|
-
import {
|
|
65
|
+
import {
|
|
66
|
+
formatCliCommand,
|
|
67
|
+
getCliInvocation,
|
|
68
|
+
} from '../../../foundation/env/package-manager.mjs';
|
|
62
69
|
import {
|
|
63
70
|
CLI_ROOT,
|
|
64
71
|
findCoreDir,
|
|
65
72
|
findInstalledPackage,
|
|
73
|
+
findProjectCoreDir,
|
|
66
74
|
} from '../../../foundation/fs/paths.mjs';
|
|
75
|
+
import {isGlobalCopy} from '../../../foundation/release/choose.mjs';
|
|
76
|
+
import {isInReleaseCache} from '../../../foundation/release/cache.mjs';
|
|
77
|
+
import {fetchCarriedThemeCoreDir} from '../_adapter.mjs';
|
|
67
78
|
import {
|
|
68
79
|
assertWithin,
|
|
69
80
|
sanitizeName,
|
|
@@ -270,6 +281,25 @@ function realOrSelf(file) {
|
|
|
270
281
|
}
|
|
271
282
|
}
|
|
272
283
|
|
|
284
|
+
/**
|
|
285
|
+
* `target` spelled through real directories: the deepest ancestor that exists
|
|
286
|
+
* is resolved through its symlinks, and the missing rest is appended as given.
|
|
287
|
+
* @param {string} target absolute path
|
|
288
|
+
* @returns {string}
|
|
289
|
+
*/
|
|
290
|
+
function realLocation(target) {
|
|
291
|
+
/** @type {string[]} */
|
|
292
|
+
const missing = [];
|
|
293
|
+
let existing = target;
|
|
294
|
+
while (!fs.existsSync(existing)) {
|
|
295
|
+
const parent = path.dirname(existing);
|
|
296
|
+
if (parent === existing) break;
|
|
297
|
+
missing.unshift(path.basename(existing));
|
|
298
|
+
existing = parent;
|
|
299
|
+
}
|
|
300
|
+
return path.join(realOrSelf(existing), ...missing);
|
|
301
|
+
}
|
|
302
|
+
|
|
273
303
|
/**
|
|
274
304
|
* The Core the project at `cwd` installed, when it differs from the one the
|
|
275
305
|
* CLI's own import found and loads. The app's `<Theme>` runs on the app's
|
|
@@ -280,10 +310,15 @@ function realOrSelf(file) {
|
|
|
280
310
|
*
|
|
281
311
|
* @param {string} cwd
|
|
282
312
|
* @param {CoreBindings} cliCore - The CLI's own Core, from {@link loadCliCore}.
|
|
313
|
+
* @param {{projectOnly?: boolean}} [options] `projectOnly`: never the
|
|
314
|
+
* carried Core, as for doctor (spec AST-081 FR3)
|
|
283
315
|
* @returns {Promise<CoreBindings | null>}
|
|
284
316
|
*/
|
|
285
|
-
async function loadProjectCore(cwd, cliCore) {
|
|
286
|
-
|
|
317
|
+
async function loadProjectCore(cwd, cliCore, {projectOnly = false} = {}) {
|
|
318
|
+
// Outside a project, the Core the answering copy carries (spec AST-081 FR3).
|
|
319
|
+
const dir =
|
|
320
|
+
findInstalledPackage(cwd, '@astryxdesign/core') ??
|
|
321
|
+
(projectOnly ? null : fetchCarriedThemeCoreDir(cwd));
|
|
287
322
|
const themeFile = dir ? importTarget(dir, './theme') : null;
|
|
288
323
|
if (!dir || !themeFile) return null;
|
|
289
324
|
if (cliCore.themeModule) {
|
|
@@ -329,14 +364,54 @@ const _projectCores = new Map();
|
|
|
329
364
|
|
|
330
365
|
/**
|
|
331
366
|
* Choose the Core this build generates with: the project's installed one when
|
|
332
|
-
* {@link loadProjectCore} finds it, else the CLI's own.
|
|
367
|
+
* {@link loadProjectCore} finds it, else the CLI's own. With `projectOnly`,
|
|
368
|
+
* only the project's installed Core: a build that cannot use it fails rather
|
|
369
|
+
* than read the Core the answering copy carries (spec AST-081 FR3).
|
|
333
370
|
* @param {string} cwd
|
|
371
|
+
* @param {{projectOnly?: boolean}} [options]
|
|
334
372
|
*/
|
|
335
|
-
async function selectCore(cwd) {
|
|
373
|
+
async function selectCore(cwd, {projectOnly = false} = {}) {
|
|
336
374
|
const cliCore = await loadCliCore();
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
375
|
+
const key = `${projectOnly ? 'project' : 'any'}\0${cwd}`;
|
|
376
|
+
if (!_projectCores.has(key))
|
|
377
|
+
_projectCores.set(key, await loadProjectCore(cwd, cliCore, {projectOnly}));
|
|
378
|
+
const projectCore = _projectCores.get(key);
|
|
379
|
+
// A global or cached copy's own Core is the carried one.
|
|
380
|
+
if (projectOnly && !projectCore && carriesCore() && !cliCoreIsProjects(cwd)) {
|
|
381
|
+
throw new AstryxError(
|
|
382
|
+
"The project's Core isn't installed or does not load.",
|
|
383
|
+
undefined,
|
|
384
|
+
ERROR_CODES.ERR_CORE_NOT_FOUND,
|
|
385
|
+
);
|
|
386
|
+
}
|
|
387
|
+
setCore(projectCore ?? cliCore);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Whether this CLI copy is one installed for the computer or kept in the
|
|
392
|
+
* per-user release cache, whose own Core import is the carried Core.
|
|
393
|
+
* @returns {boolean}
|
|
394
|
+
*/
|
|
395
|
+
function carriesCore() {
|
|
396
|
+
return isGlobalCopy(CLI_ROOT) || isInReleaseCache(CLI_ROOT);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Whether the Core the CLI's own import loads is the one the project at
|
|
401
|
+
* `cwd` installed.
|
|
402
|
+
* @param {string} cwd
|
|
403
|
+
* @returns {boolean}
|
|
404
|
+
*/
|
|
405
|
+
function cliCoreIsProjects(cwd) {
|
|
406
|
+
const dir = findProjectCoreDir(cwd);
|
|
407
|
+
if (!dir) return false;
|
|
408
|
+
try {
|
|
409
|
+
const own = fileURLToPath(import.meta.resolve('@astryxdesign/core/theme'));
|
|
410
|
+
const theirs = importTarget(dir, './theme');
|
|
411
|
+
return theirs != null && realOrSelf(own) === realOrSelf(theirs);
|
|
412
|
+
} catch {
|
|
413
|
+
return false;
|
|
414
|
+
}
|
|
340
415
|
}
|
|
341
416
|
|
|
342
417
|
/**
|
|
@@ -375,8 +450,7 @@ function inAstryxRepository(cwd) {
|
|
|
375
450
|
* @returns {string}
|
|
376
451
|
*/
|
|
377
452
|
export function coreUnavailableMessage(cwd, importError) {
|
|
378
|
-
const why =
|
|
379
|
-
'`astryx theme build` generates CSS with @astryxdesign/core, the same code the runtime <Theme> uses';
|
|
453
|
+
const why = `\`${formatCliCommand('theme build')}\` generates CSS with @astryxdesign/core, the same code the runtime <Theme> uses`;
|
|
380
454
|
const detail = importError ? `\n Import error: ${importError.message}` : '';
|
|
381
455
|
if (inAstryxRepository(cwd)) {
|
|
382
456
|
return (
|
|
@@ -506,6 +580,127 @@ function checkedBuildOutputs(writes, cwd) {
|
|
|
506
580
|
.map(write => path.relative(cwd, write.dest));
|
|
507
581
|
}
|
|
508
582
|
|
|
583
|
+
/** Remedies that end a confinement error, by where the output path came from. */
|
|
584
|
+
const OUT_REMEDY = 'Pass an --out path inside it.';
|
|
585
|
+
const SOURCE_REMEDY =
|
|
586
|
+
'Without --out the outputs go beside the theme file, so run the build from a directory that contains the theme file, or pass an --out path inside the working directory.';
|
|
587
|
+
const FAMILY_REMEDY =
|
|
588
|
+
"Family outputs go beside the family's root theme file, so run the build from a directory that contains it.";
|
|
589
|
+
|
|
590
|
+
/**
|
|
591
|
+
* Refuse an output outside `root`: every write is confined, whether `out` names
|
|
592
|
+
* the path or it defaults to the theme file's directory (architecture:cli-surface
|
|
593
|
+
* INV10). Both sides are compared by real location, so an absolute path that
|
|
594
|
+
* reaches the working directory through a symlink is inside it, and a symlink
|
|
595
|
+
* inside it that leads elsewhere is not.
|
|
596
|
+
* @param {string} dest absolute output path
|
|
597
|
+
* @param {string} root the directory writes stay inside: the working directory
|
|
598
|
+
* @param {string} remedy what to do instead; ends the error message
|
|
599
|
+
* @param {string} [shown] the path as the caller wrote it, for the message
|
|
600
|
+
*/
|
|
601
|
+
function confineOutput(dest, root, remedy, shown = dest) {
|
|
602
|
+
try {
|
|
603
|
+
assertWithin(realLocation(dest), realOrSelf(path.resolve(root)), {
|
|
604
|
+
allowAbsolute: true,
|
|
605
|
+
label: 'output path',
|
|
606
|
+
});
|
|
607
|
+
} catch (err) {
|
|
608
|
+
if (!(err instanceof PathSafetyError)) throw err;
|
|
609
|
+
throw new AstryxError(
|
|
610
|
+
err.code === ERROR_CODES.ERR_PATH_TRAVERSAL
|
|
611
|
+
? `Output path "${shown}" is outside the working directory (${root}). ${remedy}`
|
|
612
|
+
: err.message,
|
|
613
|
+
undefined,
|
|
614
|
+
ERROR_CODES.ERR_PATH_TRAVERSAL,
|
|
615
|
+
);
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
/** @param {Array<{dest: string}>} writes @param {string} root @param {string} remedy */
|
|
620
|
+
function confineOutputs(writes, root, remedy) {
|
|
621
|
+
for (const write of writes) confineOutput(write.dest, root, remedy);
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
/** @param {string} dest absolute output path @param {string} root @returns {boolean} whether a build at `root` refuses to write `dest` */
|
|
625
|
+
function refusedOutput(dest, root) {
|
|
626
|
+
try {
|
|
627
|
+
confineOutput(dest, root, '');
|
|
628
|
+
return false;
|
|
629
|
+
} catch (err) {
|
|
630
|
+
if (
|
|
631
|
+
err instanceof AstryxError &&
|
|
632
|
+
err.code === ERROR_CODES.ERR_PATH_TRAVERSAL
|
|
633
|
+
)
|
|
634
|
+
return true;
|
|
635
|
+
throw err;
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
/** @param {string[]} dirs absolute directories @returns {string | null} the deepest directory containing all of them, or null across roots */
|
|
640
|
+
function commonDirectory(dirs) {
|
|
641
|
+
let common = dirs[0];
|
|
642
|
+
for (const dir of dirs.slice(1)) {
|
|
643
|
+
while (
|
|
644
|
+
path.relative(common, dir).startsWith('..') ||
|
|
645
|
+
path.isAbsolute(path.relative(common, dir))
|
|
646
|
+
) {
|
|
647
|
+
const parent = path.dirname(common);
|
|
648
|
+
if (parent === common) return null;
|
|
649
|
+
common = parent;
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
return common;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
/** @param {string} value @returns {string} `value` as one shell word */
|
|
656
|
+
function shellWord(value) {
|
|
657
|
+
if (/^[A-Za-z0-9@%+=:,./_-]+$/.test(value)) return value;
|
|
658
|
+
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
/**
|
|
662
|
+
* How a stale check report ends when outputs sit outside the write root. A
|
|
663
|
+
* build there refuses them, and each output's `Source:` header records the
|
|
664
|
+
* directory its build ran from, so the build and the check both run from the
|
|
665
|
+
* nearest directory that contains every theme file and output.
|
|
666
|
+
* @param {Array<{dest: string}>} writes
|
|
667
|
+
* @param {string[]} sources absolute theme files the build reads
|
|
668
|
+
* @param {string} root the directory a build here keeps its writes inside
|
|
669
|
+
* @param {(relative: (file: string) => string) => string[]} args the arguments after `theme build`, given each path relative to the directory to run from
|
|
670
|
+
* @returns {string[] | null} report lines, or null when every output is inside `root`
|
|
671
|
+
*/
|
|
672
|
+
function outsideCheckRemedy(writes, sources, root, args) {
|
|
673
|
+
if (!writes.some(write => refusedOutput(write.dest, root))) return null;
|
|
674
|
+
const real = (/** @type {string} */ file) => realLocation(path.resolve(file));
|
|
675
|
+
const dir = commonDirectory([
|
|
676
|
+
...sources.map(file => path.dirname(real(file))),
|
|
677
|
+
...writes.map(write => path.dirname(real(write.dest))),
|
|
678
|
+
]);
|
|
679
|
+
if (!dir) {
|
|
680
|
+
return [
|
|
681
|
+
'These outputs are outside the working directory, so a build here refuses them. Build and check them from one directory that contains the theme files and the outputs.',
|
|
682
|
+
];
|
|
683
|
+
}
|
|
684
|
+
const command = (/** @type {string[]} */ extra) =>
|
|
685
|
+
formatCliCommand(
|
|
686
|
+
[
|
|
687
|
+
'theme',
|
|
688
|
+
'build',
|
|
689
|
+
...args(file => path.relative(dir, real(file))),
|
|
690
|
+
...extra,
|
|
691
|
+
]
|
|
692
|
+
.map(shellWord)
|
|
693
|
+
.join(' '),
|
|
694
|
+
dir,
|
|
695
|
+
);
|
|
696
|
+
return [
|
|
697
|
+
'These outputs are outside the working directory, so a build here refuses them, and each output records the directory it was built from. Build and check them from a directory that contains them:',
|
|
698
|
+
` cd ${shellWord(dir)}`,
|
|
699
|
+
` ${command([])}`,
|
|
700
|
+
` ${command(['--check'])}`,
|
|
701
|
+
];
|
|
702
|
+
}
|
|
703
|
+
|
|
509
704
|
/** @param {Array<{dest: string, content: string}>} writes */
|
|
510
705
|
function writeBuildOutputs(writes) {
|
|
511
706
|
if (writes.length === 0) return;
|
|
@@ -2344,18 +2539,20 @@ function validateHeadingTypeAugmentationSupport(themeDef) {
|
|
|
2344
2539
|
* `logger` (silent by default).
|
|
2345
2540
|
*
|
|
2346
2541
|
* @param {string} file - Theme file path, resolved against `cwd`.
|
|
2347
|
-
* @param {{out?: string, check?: boolean, iconsSpecifier?: string, __prepareFamily?: boolean, __familyLoader?: any, __familyInterception?: any, __onPrivateVarError?: () => void}} [options] -
|
|
2542
|
+
* @param {{out?: string, check?: boolean, iconsSpecifier?: string, __prepareFamily?: boolean, __familyLoader?: any, __familyInterception?: any, __onPrivateVarError?: () => void, __writeRoot?: string}} [options] -
|
|
2348
2543
|
* `out` overrides the output CSS path; `check` compares against on-disk outputs
|
|
2349
|
-
* instead of writing. `
|
|
2544
|
+
* instead of writing. `__writeRoot` replaces `cwd` as the directory every
|
|
2545
|
+
* output must stay inside, for a CLI-internal scratch build. `iconsSpecifier` overrides the icon registry import
|
|
2350
2546
|
* specifier in the generated module (e.g. `./icons.mjs`); when omitted, the
|
|
2351
2547
|
* direct registry specifiers from the theme source are emitted unchanged.
|
|
2352
|
-
* @param {{cwd?: string}} [ctx]
|
|
2548
|
+
* @param {{cwd?: string, projectCore?: boolean}} [ctx] `projectCore`: only the
|
|
2549
|
+
* project's installed Core (spec AST-081 FR3)
|
|
2353
2550
|
* @returns {Promise<any>}
|
|
2354
2551
|
*/
|
|
2355
2552
|
async function themeBuildInternal(
|
|
2356
2553
|
file,
|
|
2357
2554
|
options = {},
|
|
2358
|
-
{cwd = process.cwd()} = {},
|
|
2555
|
+
{cwd = process.cwd(), projectCore = false} = {},
|
|
2359
2556
|
/** @type {{compact?: boolean, trailers?: ThemeBuildTrailer[]}} */ report = {},
|
|
2360
2557
|
) {
|
|
2361
2558
|
const filePath = path.resolve(cwd, file);
|
|
@@ -2374,7 +2571,14 @@ async function themeBuildInternal(
|
|
|
2374
2571
|
// A compact report has no per-theme heading, so each warning names its file.
|
|
2375
2572
|
const source = report.compact ? `${path.relative(cwd, filePath)}: ` : '';
|
|
2376
2573
|
|
|
2377
|
-
|
|
2574
|
+
if (projectCore && !findProjectCoreDir(cwd)) {
|
|
2575
|
+
throw new AstryxError(
|
|
2576
|
+
"The project's Core isn't installed.",
|
|
2577
|
+
undefined,
|
|
2578
|
+
ERROR_CODES.ERR_CORE_NOT_FOUND,
|
|
2579
|
+
);
|
|
2580
|
+
}
|
|
2581
|
+
await selectCore(cwd, {projectOnly: projectCore});
|
|
2378
2582
|
|
|
2379
2583
|
// Standalone builds only need interception when an older Core could erase
|
|
2380
2584
|
// adaptations. Family preparation always supplies the same recorder as its
|
|
@@ -2791,24 +2995,17 @@ async function themeBuildInternal(
|
|
|
2791
2995
|
// Derive the default CSS name from the theme name so .css/.js/.d.ts
|
|
2792
2996
|
// share one scheme; an explicit --out still wins.
|
|
2793
2997
|
const baseName = themeDef.name;
|
|
2998
|
+
// Every write stays inside cwd. A CLI-internal caller that renders into a
|
|
2999
|
+
// scratch directory it creates and removes names that directory instead.
|
|
3000
|
+
const writeRoot = options.__writeRoot ?? cwd;
|
|
2794
3001
|
let outPath;
|
|
2795
3002
|
if (options.out) {
|
|
2796
3003
|
outPath = path.resolve(cwd, options.out);
|
|
2797
|
-
//
|
|
2798
|
-
//
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
} catch (err) {
|
|
2803
|
-
if (err instanceof PathSafetyError) {
|
|
2804
|
-
throw new AstryxError(
|
|
2805
|
-
err.message,
|
|
2806
|
-
undefined,
|
|
2807
|
-
ERROR_CODES.ERR_PATH_TRAVERSAL,
|
|
2808
|
-
);
|
|
2809
|
-
}
|
|
2810
|
-
throw err;
|
|
2811
|
-
}
|
|
3004
|
+
// A build keeps the explicit output inside the write root, relative or
|
|
3005
|
+
// absolute. Check mode writes nothing, so it refuses only a relative path
|
|
3006
|
+
// that escapes cwd.
|
|
3007
|
+
if (!options.check || !path.isAbsolute(options.out)) {
|
|
3008
|
+
confineOutput(outPath, writeRoot, OUT_REMEDY, options.out);
|
|
2812
3009
|
}
|
|
2813
3010
|
} else {
|
|
2814
3011
|
outPath = path.join(path.dirname(filePath), `${baseName}.css`);
|
|
@@ -2905,6 +3102,13 @@ async function themeBuildInternal(
|
|
|
2905
3102
|
writes.push({dest: variantDtsPath, content: variantContent});
|
|
2906
3103
|
}
|
|
2907
3104
|
|
|
3105
|
+
// Every output a build writes stays inside cwd, including the defaults
|
|
3106
|
+
// beside the theme file. Check mode writes nothing, so it compares outputs
|
|
3107
|
+
// outside cwd read-only.
|
|
3108
|
+
if (!options.check) {
|
|
3109
|
+
confineOutputs(writes, writeRoot, options.out ? OUT_REMEDY : SOURCE_REMEDY);
|
|
3110
|
+
}
|
|
3111
|
+
|
|
2908
3112
|
// Check mode: compare generated content against what's on disk instead of
|
|
2909
3113
|
// writing. A file is "stale" if it's missing or its content differs once the
|
|
2910
3114
|
// volatile @generated `Command:` line is ignored. Returns a
|
|
@@ -2923,7 +3127,10 @@ async function themeBuildInternal(
|
|
|
2923
3127
|
` ${s.reason === 'missing' ? 'missing' : 'stale'}: ${s.path}`,
|
|
2924
3128
|
);
|
|
2925
3129
|
}
|
|
2926
|
-
|
|
3130
|
+
// prettier-ignore
|
|
3131
|
+
const remedy = outsideCheckRemedy(writes, [filePath], writeRoot, relative => [relative(filePath), ...(options.out ? ['--out', relative(outPath)] : []), ...(options.iconsSpecifier ? ['--icons-specifier', options.iconsSpecifier] : [])]);
|
|
3132
|
+
if (remedy) logger.error(`\n ${remedy.join('\n ')}`);
|
|
3133
|
+
else logger.error(`\n Rebuild with: ${buildCommand}`);
|
|
2927
3134
|
}
|
|
2928
3135
|
return {
|
|
2929
3136
|
type: 'theme.build.check',
|
|
@@ -3036,7 +3243,7 @@ function printBuildTrailer(trailer) {
|
|
|
3036
3243
|
logger.log(`
|
|
3037
3244
|
Install in your app (paths are relative to a file in src/; adjust if yours lives elsewhere):
|
|
3038
3245
|
|
|
3039
|
-
import { Theme } from '@astryxdesign/core';
|
|
3246
|
+
import { Theme } from '@astryxdesign/core/theme';
|
|
3040
3247
|
import { ${trailer.exportName} } from '${trailer.jsImport}';
|
|
3041
3248
|
import '${trailer.cssImport}';
|
|
3042
3249
|
|
|
@@ -3046,7 +3253,7 @@ Install in your app (paths are relative to a file in src/; adjust if yours lives
|
|
|
3046
3253
|
|
|
3047
3254
|
Or with a <link> tag:
|
|
3048
3255
|
|
|
3049
|
-
import { Theme } from '@astryxdesign/core';
|
|
3256
|
+
import { Theme } from '@astryxdesign/core/theme';
|
|
3050
3257
|
import { ${trailer.exportName} } from '${trailer.jsImport}';
|
|
3051
3258
|
|
|
3052
3259
|
<link rel="stylesheet" href="${trailer.cssImport}" />
|
|
@@ -3072,7 +3279,7 @@ export function printBatchTrailer(trailers) {
|
|
|
3072
3279
|
logger.log(`
|
|
3073
3280
|
Install in your app (paths are relative to a file in src/; adjust if yours lives elsewhere):
|
|
3074
3281
|
|
|
3075
|
-
import { Theme } from '@astryxdesign/core';
|
|
3282
|
+
import { Theme } from '@astryxdesign/core/theme';
|
|
3076
3283
|
import { ${first.exportName} } from '${first.jsImport}';
|
|
3077
3284
|
import '${first.cssImport}';
|
|
3078
3285
|
|
|
@@ -3082,7 +3289,7 @@ Install in your app (paths are relative to a file in src/; adjust if yours lives
|
|
|
3082
3289
|
|
|
3083
3290
|
Or with a <link> tag:
|
|
3084
3291
|
|
|
3085
|
-
import { Theme } from '@astryxdesign/core';
|
|
3292
|
+
import { Theme } from '@astryxdesign/core/theme';
|
|
3086
3293
|
import { ${first.exportName} } from '${first.jsImport}';
|
|
3087
3294
|
|
|
3088
3295
|
<link rel="stylesheet" href="${first.cssImport}" />
|
|
@@ -3121,7 +3328,7 @@ export function printCompactTrailer(trailers, {hint = false} = {}) {
|
|
|
3121
3328
|
)
|
|
3122
3329
|
.join(', ');
|
|
3123
3330
|
logger.log(
|
|
3124
|
-
`[note] Fonts named but not loaded: ${named}. Load them in your app (recipe:
|
|
3331
|
+
`[note] Fonts named but not loaded: ${named}. Load them in your app (recipe: ${formatCliCommand('docs typography')}).`,
|
|
3125
3332
|
);
|
|
3126
3333
|
}
|
|
3127
3334
|
if (hint) {
|
|
@@ -3176,7 +3383,7 @@ export async function themeBuildForReport(
|
|
|
3176
3383
|
return {receipt, trailer: trailers[0] ?? null};
|
|
3177
3384
|
}
|
|
3178
3385
|
|
|
3179
|
-
/** @param {string} file @param {{out?: string, check?: boolean, iconsSpecifier?: string}} [options] @param {{cwd?: string}} [ctx] @returns {Promise<import('../theme.type.mjs').ThemeBuildResponse | import('../theme.type.mjs').ThemeBuildCheckResponse | null>} */
|
|
3386
|
+
/** @param {string} file @param {{out?: string, check?: boolean, iconsSpecifier?: string}} [options] @param {{cwd?: string, projectCore?: boolean}} [ctx] `projectCore`: read only the project's installed Core, never the carried one (doctor; spec AST-081 FR3) @returns {Promise<import('../theme.type.mjs').ThemeBuildResponse | import('../theme.type.mjs').ThemeBuildCheckResponse | null>} */
|
|
3180
3387
|
export async function themeBuild(file, options = {}, ctx = {}) {
|
|
3181
3388
|
return /** @type {any} */ (themeBuildInternal(file, options, ctx));
|
|
3182
3389
|
}
|
|
@@ -3449,6 +3656,8 @@ export async function themeBuildFamily(
|
|
|
3449
3656
|
js: path.relative(cwd, jsPath),
|
|
3450
3657
|
dts: path.relative(cwd, dtsPath),
|
|
3451
3658
|
};
|
|
3659
|
+
// A family build's outputs stay inside cwd too; check mode only reads them.
|
|
3660
|
+
if (!options.check) confineOutputs(writes, cwd, FAMILY_REMEDY);
|
|
3452
3661
|
if (options.check) {
|
|
3453
3662
|
const stale = staleBuildOutputs(writes, cwd);
|
|
3454
3663
|
const upToDate = stale.length === 0;
|
|
@@ -3465,7 +3674,10 @@ export async function themeBuildFamily(
|
|
|
3465
3674
|
` ${entry.reason === 'missing' ? 'missing' : 'stale'}: ${entry.path}`,
|
|
3466
3675
|
);
|
|
3467
3676
|
}
|
|
3468
|
-
|
|
3677
|
+
// prettier-ignore
|
|
3678
|
+
const remedy = outsideCheckRemedy(writes, members.map(member => member.filePath), cwd, relative => ['--family', ...members.map(member => relative(member.filePath)), '--family-key', baseName, ...(options.iconsSpecifier ? ['--icons-specifier', options.iconsSpecifier] : [])]);
|
|
3679
|
+
if (remedy) logger.error(`\n ${remedy.join('\n ')}`);
|
|
3680
|
+
else logger.error(`\n Rebuild with: ${buildCommand}`);
|
|
3469
3681
|
}
|
|
3470
3682
|
return {
|
|
3471
3683
|
type: 'theme.build.check',
|
|
@@ -37,6 +37,7 @@ import * as path from 'node:path';
|
|
|
37
37
|
import {fileURLToPath} from 'node:url';
|
|
38
38
|
|
|
39
39
|
import {findInstalledPackage} from '../../../foundation/fs/paths.mjs';
|
|
40
|
+
import {CLI_VERSION} from '../../../test-utils/release-fixtures.mjs';
|
|
40
41
|
|
|
41
42
|
const HERE = path.dirname(fileURLToPath(import.meta.url));
|
|
42
43
|
const REPO_ROOT = path.resolve(HERE, '../../../../..');
|
|
@@ -55,8 +56,12 @@ const RUNTIME_DEPS = [
|
|
|
55
56
|
'zod',
|
|
56
57
|
];
|
|
57
58
|
|
|
58
|
-
|
|
59
|
-
|
|
59
|
+
// Both Cores carry the packed CLI's own version: a run through the bin in a
|
|
60
|
+
// project whose Core is another release is handed to that release (spec
|
|
61
|
+
// AST-081 FR2), so the old surface is told apart by what it exports, not by
|
|
62
|
+
// its version.
|
|
63
|
+
const OLD_CORE_VERSION = CLI_VERSION;
|
|
64
|
+
const CURRENT_CORE_VERSION = CLI_VERSION;
|
|
60
65
|
const TSC_BIN = path.join(REPO_ROOT, 'node_modules/typescript/bin/tsc');
|
|
61
66
|
|
|
62
67
|
/**
|
|
@@ -278,8 +283,20 @@ function buildTheme(themeFile, extraArgs = []) {
|
|
|
278
283
|
'node_modules/@astryxdesign/cli/clients/cli/bin/astryx.mjs',
|
|
279
284
|
);
|
|
280
285
|
try {
|
|
286
|
+
// A packed CLI outside any project's package.json reads as installed for
|
|
287
|
+
// the computer, so it gets a home folder of its own: nothing it keeps for
|
|
288
|
+
// the computer lands in the real one.
|
|
289
|
+
const home = path.join(root, 'home');
|
|
290
|
+
const env = {
|
|
291
|
+
...process.env,
|
|
292
|
+
HOME: home,
|
|
293
|
+
USERPROFILE: home,
|
|
294
|
+
XDG_CONFIG_HOME: path.join(home, '.config'),
|
|
295
|
+
XDG_CACHE_HOME: path.join(home, '.cache'),
|
|
296
|
+
NO_UPDATE_NOTIFIER: '1',
|
|
297
|
+
};
|
|
281
298
|
// prettier-ignore
|
|
282
|
-
const stdout = execFileSync(process.execPath, [bin, 'theme', 'build', ...(Array.isArray(themeFile) ? themeFile : [themeFile]), ...extraArgs, '--json'], {cwd: consumer, encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe']});
|
|
299
|
+
const stdout = execFileSync(process.execPath, [bin, 'theme', 'build', ...(Array.isArray(themeFile) ? themeFile : [themeFile]), ...extraArgs, '--json'], {cwd: consumer, encoding: 'utf8', env, stdio: ['ignore', 'pipe', 'pipe']});
|
|
283
300
|
return {status: 0, envelope: JSON.parse(stdout)};
|
|
284
301
|
} catch (error) {
|
|
285
302
|
const e = /** @type {any} */ (error);
|
|
@@ -21,9 +21,11 @@
|
|
|
21
21
|
* @output Ordered, case-insensitively deduped family names, and the human
|
|
22
22
|
* help snippet (<link> pair + @font-face) printed after the install
|
|
23
23
|
* instructions.
|
|
24
|
-
* @position Sits beside build.mjs (api/theme/build/). Pure functions, no IO
|
|
25
|
-
*
|
|
24
|
+
* @position Sits beside build.mjs (api/theme/build/). Pure functions, no IO
|
|
25
|
+
* beyond the CLI invocation the human help names (formatCliCommand), so the
|
|
26
|
+
* `--json` receipt and the human output share one source of truth.
|
|
26
27
|
*/
|
|
28
|
+
import {formatCliCommand} from '../../../foundation/env/package-manager.mjs';
|
|
27
29
|
|
|
28
30
|
// font-family values that never need loading: CSS generic families, the ui-*
|
|
29
31
|
// system keywords, and CSS-wide keywords that can appear in a token value.
|
|
@@ -254,6 +256,6 @@ function fontLoadingRecipe(families) {
|
|
|
254
256
|
font-display: swap;
|
|
255
257
|
}
|
|
256
258
|
|
|
257
|
-
Recipe and fallback-stack guidance:
|
|
259
|
+
Recipe and fallback-stack guidance: ${formatCliCommand('docs typography')}
|
|
258
260
|
`;
|
|
259
261
|
}
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
import {describe, it, expect} from 'vitest';
|
|
17
17
|
import {collectUnloadedFonts, formatFontLoadingHelp} from './font-warning.mjs';
|
|
18
|
+
import {formatCliCommand} from '../../../foundation/env/package-manager.mjs';
|
|
18
19
|
|
|
19
20
|
describe('collectUnloadedFonts', () => {
|
|
20
21
|
it('returns webfont families from font-family tokens, skipping known fallbacks', () => {
|
|
@@ -255,7 +256,7 @@ describe('formatFontLoadingHelp', () => {
|
|
|
255
256
|
});
|
|
256
257
|
|
|
257
258
|
it('points at the docs recipe', () => {
|
|
258
|
-
expect(help).toContain('
|
|
259
|
+
expect(help).toContain(formatCliCommand('docs typography'));
|
|
259
260
|
});
|
|
260
261
|
|
|
261
262
|
it('percent-encodes family names in the css2 URL', () => {
|
|
@@ -81,14 +81,14 @@ describe('themeRemove', () => {
|
|
|
81
81
|
it('refuses to remove the default and names theme use', async () => {
|
|
82
82
|
await expect(themeRemove('ocean', {cwd: tmpDir})).rejects.toMatchObject({
|
|
83
83
|
code: 'ERR_THEME_INVALID',
|
|
84
|
-
message: expect.stringContaining('
|
|
84
|
+
message: expect.stringContaining(' theme use <other-slug>`'),
|
|
85
85
|
});
|
|
86
86
|
});
|
|
87
87
|
|
|
88
88
|
it('names theme add when the slug is not added', async () => {
|
|
89
89
|
await expect(themeRemove('missing', {cwd: tmpDir})).rejects.toMatchObject({
|
|
90
90
|
code: 'ERR_UNKNOWN_THEME',
|
|
91
|
-
message: expect.stringContaining('
|
|
91
|
+
message: expect.stringContaining(' theme add missing`'),
|
|
92
92
|
});
|
|
93
93
|
});
|
|
94
94
|
});
|
|
@@ -12,10 +12,10 @@
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
import * as path from 'node:path';
|
|
15
|
-
import {
|
|
15
|
+
import {requireThemeCoreDir} from '../_adapter.mjs';
|
|
16
16
|
import {collectThemingTargets} from '../../../foundation/discovery/theming-targets.mjs';
|
|
17
17
|
import {ERROR_CODES} from '../../../foundation/response/error-codes.mjs';
|
|
18
|
-
import {AstryxError} from '../../error.mjs';
|
|
18
|
+
import {AstryxError, coreDirOrThrow} from '../../error.mjs';
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
21
|
* Whether a target matches the caller's filter loosely: any target whose key,
|
|
@@ -46,14 +46,7 @@ function matchesLoosely(target, filter) {
|
|
|
46
46
|
* @returns {Promise<import('../theme.type.mjs').ThemeTargetsResponse>}
|
|
47
47
|
*/
|
|
48
48
|
export async function themeTargets(filter, {cwd = process.cwd()} = {}) {
|
|
49
|
-
const coreDir =
|
|
50
|
-
if (!coreDir) {
|
|
51
|
-
throw new AstryxError(
|
|
52
|
-
'Could not find @astryxdesign/core package',
|
|
53
|
-
undefined,
|
|
54
|
-
ERROR_CODES.ERR_CORE_NOT_FOUND,
|
|
55
|
-
);
|
|
56
|
-
}
|
|
49
|
+
const coreDir = coreDirOrThrow(requireThemeCoreDir, cwd);
|
|
57
50
|
|
|
58
51
|
const all = await collectThemingTargets(path.join(coreDir, 'src'));
|
|
59
52
|
const needle = filter ? String(filter).toLowerCase() : null;
|