@astryxdesign/cli 0.7.2-canary.fdd384f → 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 +169 -149
- 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/kit/kit.mjs +3 -11
- package/api/component/_adapter.d.mts +31 -0
- package/api/component/_adapter.mjs +119 -11
- package/api/component/component.doc.mjs +6 -1
- package/api/component/component.mjs +60 -10
- package/api/component/doc-links.test.mjs +386 -0
- 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 +63 -0
- package/api/docs/_adapter.mjs +312 -18
- 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/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 +16 -3
- 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 +152 -48
- 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/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 +15 -4
- 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 +33 -0
- package/api/integration/_adapter.mjs +58 -0
- package/api/integration/authoring-checks.mjs +100 -5
- package/api/integration/authoring-checks.test.mjs +769 -0
- package/api/integration/authoring-checks.type.d.mts +134 -0
- package/api/integration/authoring-checks.type.mjs +60 -1
- package/api/integration/integrationCheck.doc.mjs +1 -1
- package/api/integration/integrationComponentConflicts.doc.mjs +11 -3
- package/api/integration/integrationDocConflicts.doc.mjs +22 -5
- package/api/integration/pack-check.mjs +303 -13
- package/api/integration/pack-check.test.mjs +371 -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 +55 -9
- package/api/integration/validate-integration.test.mjs +77 -8
- package/api/integration/validate-integration.type.d.mts +8 -0
- package/api/integration/validate-integration.type.mjs +3 -1
- package/api/integration/validate-unread-theme-folders.test.mjs +3 -2
- package/api/integration/validateIntegration.doc.mjs +4 -2
- package/api/search/_adapter.d.mts +11 -0
- package/api/search/_adapter.mjs +25 -0
- package/api/search/search.d.mts +73 -13
- package/api/search/search.doc.mjs +8 -3
- package/api/search/search.domain-priority.test.mjs +108 -18
- package/api/search/search.mjs +541 -52
- package/api/search/search.test.mjs +143 -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 +1 -1
- package/api/template/template-integration.test.mjs +1 -1
- 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.mjs +70 -14
- 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/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/next/index.mjs +1 -11
- package/assets/codemods/transforms/v0.7.2/index.mjs +20 -0
- package/assets/discover/official-packages.json +367 -0
- package/assets/docs/author-a-theme.doc.mjs +2 -2
- package/assets/docs/browser-support.doc.mjs +1 -1
- package/assets/docs/getting-started.doc.mjs +23 -3
- package/assets/docs/styling-overview.doc.mjs +1 -1
- package/assets/docs/theme.doc.mjs +1 -1
- package/assets/docs/tree/add-a-component.doc.mjs +12 -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 +6 -18
- 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 +8 -3
- package/assets/docs/tree/check-your-docs.doc.mjs +30 -13
- package/assets/docs/tree/checks.doc.mjs +17 -17
- 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 +3 -5
- package/assets/docs/tree/component-imports.doc.mjs +13 -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 +2 -2
- 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 +6 -5
- 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 +3 -7
- 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 +52 -26
- 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 +9 -11
- 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 +14 -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 +22 -14
- 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 +9 -9
- package/assets/docs/tree/who-answers.doc.mjs +119 -0
- package/assets/docs/tree/write-the-template-file.doc.mjs +5 -5
- package/assets/docs/working-with-ai.doc.mjs +23 -9
- 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 +29 -26
- package/authoring/doctypes/component/type.ts +15 -5
- 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/template.doc.mjs +2 -2
- 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 +1 -0
- package/authoring/integration/integration.doc.mjs +22 -5
- package/authoring/integration/parse.test.mjs +11 -0
- package/authoring/integration/schema.d.mts +14 -3
- package/authoring/integration/schema.mjs +33 -2
- package/authoring/integration/type.ts +8 -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 +14 -2
- package/clients/cli/commands/build-theme.font-warning.test.mjs +3 -3
- package/clients/cli/commands/build-theme.mjs +25 -12
- 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 +7 -3
- 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 +13 -2
- package/clients/cli/commands/doctor-integration.test.mjs +52 -4
- package/clients/cli/commands/doctor.doc.mjs +12 -2
- package/clients/cli/commands/doctor.mjs +102 -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 +10 -2
- package/clients/cli/commands/integration-check.test.mjs +175 -1
- 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.mjs +15 -9
- 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/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 +1 -0
- 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 +111 -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 +145 -8
- package/foundation/config/project.test.mjs +66 -0
- package/foundation/config/theme-state.mjs +5 -4
- package/foundation/discovery/authoring-self-docs.mjs +1 -1
- package/foundation/discovery/cli-self-docs.mjs +20 -3
- package/foundation/discovery/cli-self-docs.test.mjs +3 -2
- package/foundation/discovery/component-replacement.mjs +2 -1
- 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 +1 -1
- package/foundation/discovery/doc-types.mjs +15 -8
- package/foundation/discovery/doc-types.test.mjs +94 -2
- package/foundation/discovery/docs-discovery.d.mts +7 -0
- package/foundation/discovery/docs-discovery.mjs +26 -2
- package/foundation/discovery/project-typescript.d.mts +11 -2
- package/foundation/discovery/project-typescript.mjs +32 -4
- package/foundation/discovery/prop-drift.d.mts +26 -7
- package/foundation/discovery/prop-drift.mjs +173 -8
- package/foundation/discovery/prop-drift.test.mjs +120 -2
- 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-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-text.mjs +1 -1
- package/foundation/discovery/type-text.test.mjs +1 -1
- package/foundation/doc-compiler/doc-loads.test.mjs +42 -2
- package/foundation/doc-compiler/inputs.mjs +4 -1
- package/foundation/doc-compiler/links.d.mts +32 -0
- package/foundation/doc-compiler/links.mjs +163 -26
- 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 +50 -2
- 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 +17 -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/package.json +11 -11
- package/scripts/postinstall.mjs +24 -5
- /package/assets/codemods/transforms/{next → v0.7.2}/__tests__/migrate-list-edge-compensation-to-edge.test.mjs +0 -0
- /package/assets/codemods/transforms/{next → v0.7.2}/migrate-list-edge-compensation-to-edge.mjs +0 -0
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
integrationAddComponent,
|
|
18
18
|
integrationAddTemplate,
|
|
19
19
|
} from './add-contribution.mjs';
|
|
20
|
+
import {formatCliCommand} from '../../foundation/env/package-manager.mjs';
|
|
20
21
|
|
|
21
22
|
let tmpDir;
|
|
22
23
|
|
|
@@ -213,6 +214,7 @@ function writePackage({
|
|
|
213
214
|
themeExports = false,
|
|
214
215
|
npmignore,
|
|
215
216
|
components = false,
|
|
217
|
+
templates = false,
|
|
216
218
|
scripts,
|
|
217
219
|
} = {}) {
|
|
218
220
|
const pkg = {name, version};
|
|
@@ -272,6 +274,14 @@ export default {type: 'theme', name: 'ocean', displayName: 'Ocean', description:
|
|
|
272
274
|
'export default function Card() { return null; }\n',
|
|
273
275
|
);
|
|
274
276
|
}
|
|
277
|
+
if (templates) {
|
|
278
|
+
const root = path.join(tmpDir, 'templates');
|
|
279
|
+
fs.mkdirSync(root, {recursive: true});
|
|
280
|
+
fs.writeFileSync(
|
|
281
|
+
path.join(root, 'stray.tsx'),
|
|
282
|
+
'export default function Stray() { return null; }\n',
|
|
283
|
+
);
|
|
284
|
+
}
|
|
275
285
|
if (npmignore) {
|
|
276
286
|
fs.writeFileSync(path.join(tmpDir, '.npmignore'), npmignore);
|
|
277
287
|
}
|
|
@@ -303,6 +313,345 @@ function runCliVerify() {
|
|
|
303
313
|
};
|
|
304
314
|
}
|
|
305
315
|
|
|
316
|
+
/**
|
|
317
|
+
* Give the built ocean theme a font stylesheet and an entry module that loads
|
|
318
|
+
* the theme's own styles, and export them the way such a package does.
|
|
319
|
+
* @param {string} entry
|
|
320
|
+
* @param {string} [file] the entry's file name in `entries/`
|
|
321
|
+
*/
|
|
322
|
+
function writeOwnStylesEntry(entry, file = 'ocean.mjs') {
|
|
323
|
+
fs.writeFileSync(
|
|
324
|
+
path.join(tmpDir, 'themes', 'ocean', 'ocean.fonts.css'),
|
|
325
|
+
"@font-face { font-family: 'Ocean Sans'; src: local('Ocean Sans'); }\n",
|
|
326
|
+
);
|
|
327
|
+
fs.mkdirSync(path.join(tmpDir, 'entries'), {recursive: true});
|
|
328
|
+
fs.writeFileSync(path.join(tmpDir, 'entries', file), entry);
|
|
329
|
+
const packageFile = path.join(tmpDir, 'package.json');
|
|
330
|
+
const pkg = JSON.parse(fs.readFileSync(packageFile, 'utf-8'));
|
|
331
|
+
pkg.files = ['astryx.integration.mjs', 'themes', 'entries'];
|
|
332
|
+
pkg.exports = {
|
|
333
|
+
'./themes/ocean': `./entries/${file}`,
|
|
334
|
+
'./themes/ocean.css': './themes/ocean/ocean.css',
|
|
335
|
+
'./themes/ocean.fonts.css': './themes/ocean/ocean.fonts.css',
|
|
336
|
+
};
|
|
337
|
+
fs.writeFileSync(packageFile, `${JSON.stringify(pkg, null, 2)}\n`);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* Rename the ocean theme to deep-sea, keeping its `ocean` slug, and build it,
|
|
342
|
+
* so its outputs are named after the theme: `deep-sea.css` and `deep-sea.js`,
|
|
343
|
+
* which exports `deepSeaTheme`.
|
|
344
|
+
*/
|
|
345
|
+
function writeRenamedOcean() {
|
|
346
|
+
writePackage({files: ['astryx.integration.mjs', 'themes', 'entries']});
|
|
347
|
+
fs.writeFileSync(
|
|
348
|
+
path.join(tmpDir, 'themes', 'ocean', 'oceanTheme.ts'),
|
|
349
|
+
"import {defineTheme} from '@astryxdesign/core/theme';\n\nexport const oceanTheme = defineTheme({name: 'deep-sea'});\n",
|
|
350
|
+
);
|
|
351
|
+
const built = spawnSync(
|
|
352
|
+
process.execPath,
|
|
353
|
+
[
|
|
354
|
+
path.join(process.cwd(), 'packages/cli/clients/cli/bin/astryx.mjs'),
|
|
355
|
+
'theme',
|
|
356
|
+
'build',
|
|
357
|
+
'themes/ocean/oceanTheme.ts',
|
|
358
|
+
],
|
|
359
|
+
{cwd: tmpDir, encoding: 'utf-8', timeout: 30_000},
|
|
360
|
+
);
|
|
361
|
+
if (built.status !== 0) {
|
|
362
|
+
throw new Error(`Could not build the theme fixture: ${built.stderr}`);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Give the ocean theme an icon registry and build it, so its built module
|
|
368
|
+
* also exports `oceanIcons`.
|
|
369
|
+
*/
|
|
370
|
+
function writeOceanWithIcons() {
|
|
371
|
+
writePackage({files: ['astryx.integration.mjs', 'themes', 'entries']});
|
|
372
|
+
const themeDir = path.join(tmpDir, 'themes', 'ocean');
|
|
373
|
+
fs.writeFileSync(
|
|
374
|
+
path.join(themeDir, 'icons.js'),
|
|
375
|
+
'export const oceanIcons = {};\n',
|
|
376
|
+
);
|
|
377
|
+
fs.writeFileSync(
|
|
378
|
+
path.join(themeDir, 'oceanTheme.ts'),
|
|
379
|
+
"import {defineTheme} from '@astryxdesign/core/theme';\nimport {oceanIcons} from './icons';\n\nexport const oceanTheme = defineTheme({name: 'ocean', icons: oceanIcons});\n",
|
|
380
|
+
);
|
|
381
|
+
const built = spawnSync(
|
|
382
|
+
process.execPath,
|
|
383
|
+
[
|
|
384
|
+
path.join(process.cwd(), 'packages/cli/clients/cli/bin/astryx.mjs'),
|
|
385
|
+
'theme',
|
|
386
|
+
'build',
|
|
387
|
+
'themes/ocean/oceanTheme.ts',
|
|
388
|
+
],
|
|
389
|
+
{cwd: tmpDir, encoding: 'utf-8', timeout: 30_000},
|
|
390
|
+
);
|
|
391
|
+
if (built.status !== 0) {
|
|
392
|
+
throw new Error(`Could not build the theme fixture: ${built.stderr}`);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// An entry like one whose import is the whole integration: it loads the
|
|
397
|
+
// theme's fonts and stylesheet, by relative path and through the package's
|
|
398
|
+
// own exports, and re-exports the built theme.
|
|
399
|
+
const OWN_STYLES_ENTRY = `// Copyright (c) Acme.
|
|
400
|
+
|
|
401
|
+
import '../themes/ocean/ocean.fonts.css';
|
|
402
|
+
import '@acme/widgets/themes/ocean.css';
|
|
403
|
+
|
|
404
|
+
export {oceanTheme} from '../themes/ocean/ocean.js';
|
|
405
|
+
`;
|
|
406
|
+
|
|
407
|
+
describe('a theme module that loads its own styles', () => {
|
|
408
|
+
it('passes an entry that imports the theme stylesheet and fonts and re-exports the built module', async () => {
|
|
409
|
+
writePackage({themeExports: true});
|
|
410
|
+
writeOwnStylesEntry(OWN_STYLES_ENTRY);
|
|
411
|
+
|
|
412
|
+
const result = await integrationPackCheck({cwd: tmpDir});
|
|
413
|
+
|
|
414
|
+
expect(result.data.issues).toEqual([]);
|
|
415
|
+
expect(result.data.packable).toBe(true);
|
|
416
|
+
const cli = runCliVerify();
|
|
417
|
+
expect(cli.status, cli.stderr).toBe(0);
|
|
418
|
+
expect(cli.receipt?.data.issues).toEqual([]);
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
it('passes an entry that imports its fonts through the package exports and re-exports everything', async () => {
|
|
422
|
+
writePackage({themeExports: true});
|
|
423
|
+
writeOwnStylesEntry(
|
|
424
|
+
"import '@acme/widgets/themes/ocean.fonts.css';\nimport '../themes/ocean/ocean.css';\nexport * from '../themes/ocean/ocean.js';\n",
|
|
425
|
+
);
|
|
426
|
+
|
|
427
|
+
const result = await integrationPackCheck({cwd: tmpDir});
|
|
428
|
+
|
|
429
|
+
expect(result.data.issues).toEqual([]);
|
|
430
|
+
expect(result.data.packable).toBe(true);
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
it.each([
|
|
434
|
+
[
|
|
435
|
+
'also imports another stylesheet',
|
|
436
|
+
`${OWN_STYLES_ENTRY}import './other.css';\n`,
|
|
437
|
+
"./other.css is not the theme's own stylesheet or font stylesheet",
|
|
438
|
+
],
|
|
439
|
+
[
|
|
440
|
+
'also imports a script',
|
|
441
|
+
`import './setup.mjs';\n${OWN_STYLES_ENTRY}`,
|
|
442
|
+
"./setup.mjs is not the theme's own stylesheet or font stylesheet",
|
|
443
|
+
],
|
|
444
|
+
[
|
|
445
|
+
'runs code',
|
|
446
|
+
`${OWN_STYLES_ENTRY}console.log('ocean');\n`,
|
|
447
|
+
'line 7 is neither a stylesheet import nor the re-export',
|
|
448
|
+
],
|
|
449
|
+
[
|
|
450
|
+
'exports another value',
|
|
451
|
+
`${OWN_STYLES_ENTRY}export const extra = 1;\n`,
|
|
452
|
+
'line 7 is neither a stylesheet import nor the re-export',
|
|
453
|
+
],
|
|
454
|
+
[
|
|
455
|
+
'renames the theme it re-exports',
|
|
456
|
+
"import '../themes/ocean/ocean.css';\nexport {oceanTheme, oceanTheme as theme} from '../themes/ocean/ocean.js';\n",
|
|
457
|
+
'it re-exports names other than oceanTheme',
|
|
458
|
+
],
|
|
459
|
+
[
|
|
460
|
+
'binds the stylesheet it imports',
|
|
461
|
+
"import styles from '../themes/ocean/ocean.css';\nexport {oceanTheme} from '../themes/ocean/ocean.js';\n",
|
|
462
|
+
'its import of ../themes/ocean/ocean.css is not a side-effect import',
|
|
463
|
+
],
|
|
464
|
+
[
|
|
465
|
+
'imports the stylesheet as a CSS module script',
|
|
466
|
+
"import '../themes/ocean/ocean.css' with {type: 'css'};\nexport {oceanTheme} from '../themes/ocean/ocean.js';\n",
|
|
467
|
+
'its import of ../themes/ocean/ocean.css is not a side-effect import',
|
|
468
|
+
],
|
|
469
|
+
[
|
|
470
|
+
're-exports another name',
|
|
471
|
+
"import '../themes/ocean/ocean.css';\nexport {oceanTheme, missing} from '../themes/ocean/ocean.js';\n",
|
|
472
|
+
'it re-exports names other than oceanTheme',
|
|
473
|
+
],
|
|
474
|
+
[
|
|
475
|
+
're-exports a copy that is not a .js module',
|
|
476
|
+
"import '../themes/ocean/ocean.css';\nexport {oceanTheme} from './copy.cjs';\n",
|
|
477
|
+
'its re-export from ./copy.cjs does not name a .js module',
|
|
478
|
+
],
|
|
479
|
+
[
|
|
480
|
+
'has a directive',
|
|
481
|
+
`'use client';\n${OWN_STYLES_ENTRY}`,
|
|
482
|
+
'it has a directive',
|
|
483
|
+
],
|
|
484
|
+
[
|
|
485
|
+
're-exports twice',
|
|
486
|
+
`${OWN_STYLES_ENTRY}export * from '../themes/ocean/ocean.js';\n`,
|
|
487
|
+
'it has more than one re-export',
|
|
488
|
+
],
|
|
489
|
+
])('fails an entry that %s', async (_label, entry, reason) => {
|
|
490
|
+
writePackage({themeExports: true});
|
|
491
|
+
writeOwnStylesEntry(entry);
|
|
492
|
+
fs.writeFileSync(path.join(tmpDir, 'entries', 'other.css'), '.x {}\n');
|
|
493
|
+
fs.writeFileSync(path.join(tmpDir, 'entries', 'setup.mjs'), 'export {};\n');
|
|
494
|
+
fs.copyFileSync(
|
|
495
|
+
path.join(tmpDir, 'themes', 'ocean', 'ocean.js'),
|
|
496
|
+
path.join(tmpDir, 'entries', 'copy.cjs'),
|
|
497
|
+
);
|
|
498
|
+
|
|
499
|
+
const result = await integrationPackCheck({cwd: tmpDir});
|
|
500
|
+
|
|
501
|
+
expect(result.data.packable).toBe(false);
|
|
502
|
+
expect(result.data.issues).toEqual([
|
|
503
|
+
{
|
|
504
|
+
code: 'theme_module_stale',
|
|
505
|
+
severity: 'error',
|
|
506
|
+
message: `Theme "ocean" module is not the module \`${formatCliCommand('theme build themes/ocean/oceanTheme.ts', tmpDir)}\` writes and does not only wrap it: ${reason}. A module that wraps the built module may only import the theme's own stylesheet and font stylesheet for their side effects and re-export from the built module either everything or only its theme, as oceanTheme.`,
|
|
507
|
+
},
|
|
508
|
+
]);
|
|
509
|
+
});
|
|
510
|
+
|
|
511
|
+
it('fails an entry whose re-exported module drifts from source', async () => {
|
|
512
|
+
writePackage({themeExports: true});
|
|
513
|
+
writeOwnStylesEntry(OWN_STYLES_ENTRY);
|
|
514
|
+
fs.appendFileSync(
|
|
515
|
+
path.join(tmpDir, 'themes', 'ocean', 'ocean.js'),
|
|
516
|
+
'// stale module\n',
|
|
517
|
+
);
|
|
518
|
+
|
|
519
|
+
const result = await integrationPackCheck({cwd: tmpDir});
|
|
520
|
+
|
|
521
|
+
expect(result.data.packable).toBe(false);
|
|
522
|
+
expect(result.data.issues).toEqual([
|
|
523
|
+
{
|
|
524
|
+
code: 'theme_module_stale',
|
|
525
|
+
severity: 'error',
|
|
526
|
+
message: `Theme "ocean" module re-exports ../themes/ocean/ocean.js, which does not match themes/ocean/oceanTheme.ts. Run \`${formatCliCommand('theme build themes/ocean/oceanTheme.ts', tmpDir)}\` before packing.`,
|
|
527
|
+
},
|
|
528
|
+
]);
|
|
529
|
+
});
|
|
530
|
+
|
|
531
|
+
it('does not accept a TypeScript entry', async () => {
|
|
532
|
+
writePackage({themeExports: true});
|
|
533
|
+
writeOwnStylesEntry(OWN_STYLES_ENTRY, 'ocean.ts');
|
|
534
|
+
|
|
535
|
+
const result = await integrationPackCheck({cwd: tmpDir});
|
|
536
|
+
|
|
537
|
+
expect(result.data.packable).toBe(false);
|
|
538
|
+
expect(result.data.issues).toEqual([
|
|
539
|
+
{
|
|
540
|
+
code: 'theme_module_stale',
|
|
541
|
+
severity: 'error',
|
|
542
|
+
message: `Theme "ocean" module does not match themes/ocean/oceanTheme.ts. Run \`${formatCliCommand('theme build themes/ocean/oceanTheme.ts', tmpDir)}\` before packing.`,
|
|
543
|
+
},
|
|
544
|
+
]);
|
|
545
|
+
});
|
|
546
|
+
|
|
547
|
+
it('does not accept an entry that re-exports itself', async () => {
|
|
548
|
+
writePackage({themeExports: true});
|
|
549
|
+
writeOwnStylesEntry(
|
|
550
|
+
"import '../themes/ocean/ocean.css';\nexport * from './ocean.js';\n",
|
|
551
|
+
'ocean.js',
|
|
552
|
+
);
|
|
553
|
+
|
|
554
|
+
const result = await integrationPackCheck({cwd: tmpDir});
|
|
555
|
+
|
|
556
|
+
expect(result.data.packable).toBe(false);
|
|
557
|
+
expect(result.data.issues).toContainEqual(
|
|
558
|
+
expect.objectContaining({
|
|
559
|
+
code: 'theme_import_unresolvable',
|
|
560
|
+
message: expect.stringContaining('does not export "oceanTheme"'),
|
|
561
|
+
}),
|
|
562
|
+
);
|
|
563
|
+
});
|
|
564
|
+
|
|
565
|
+
it('passes an entry for a theme whose own name differs from its slug', async () => {
|
|
566
|
+
writeRenamedOcean();
|
|
567
|
+
writeOwnStylesEntry(
|
|
568
|
+
"import '../themes/ocean/deep-sea.css';\nexport {deepSeaTheme as oceanTheme} from '../themes/ocean/deep-sea.js';\n",
|
|
569
|
+
);
|
|
570
|
+
setThemeExports({
|
|
571
|
+
'./themes/ocean': './entries/ocean.mjs',
|
|
572
|
+
'./themes/ocean.css': './themes/ocean/deep-sea.css',
|
|
573
|
+
});
|
|
574
|
+
|
|
575
|
+
const result = await integrationPackCheck({cwd: tmpDir});
|
|
576
|
+
|
|
577
|
+
expect(result.data.issues).toEqual([]);
|
|
578
|
+
expect(result.data.packable).toBe(true);
|
|
579
|
+
const cli = runCliVerify();
|
|
580
|
+
expect(cli.status, cli.stderr).toBe(0);
|
|
581
|
+
});
|
|
582
|
+
|
|
583
|
+
it('compares a partial export set with the module named after the theme', async () => {
|
|
584
|
+
writeRenamedOcean();
|
|
585
|
+
setThemeExports({'./themes/ocean': './themes/ocean/deep-sea.js'});
|
|
586
|
+
|
|
587
|
+
const result = await integrationPackCheck({cwd: tmpDir});
|
|
588
|
+
|
|
589
|
+
expect(result.data.packable).toBe(true);
|
|
590
|
+
expect(result.data.issues.map(issue => issue.code)).toEqual([
|
|
591
|
+
'theme_exports_incomplete',
|
|
592
|
+
]);
|
|
593
|
+
});
|
|
594
|
+
|
|
595
|
+
it('passes an entry that re-exports only the theme from a built module that also exports its icons', async () => {
|
|
596
|
+
writeOceanWithIcons();
|
|
597
|
+
writeOwnStylesEntry(OWN_STYLES_ENTRY);
|
|
598
|
+
|
|
599
|
+
const result = await integrationPackCheck({cwd: tmpDir});
|
|
600
|
+
|
|
601
|
+
expect(result.data.issues).toEqual([]);
|
|
602
|
+
expect(result.data.packable).toBe(true);
|
|
603
|
+
});
|
|
604
|
+
|
|
605
|
+
it('fails an entry that gives the built icons the theme export name', async () => {
|
|
606
|
+
writeOceanWithIcons();
|
|
607
|
+
writeOwnStylesEntry(
|
|
608
|
+
"import '../themes/ocean/ocean.css';\nexport {oceanIcons as oceanTheme} from '../themes/ocean/ocean.js';\n",
|
|
609
|
+
);
|
|
610
|
+
|
|
611
|
+
const result = await integrationPackCheck({cwd: tmpDir});
|
|
612
|
+
|
|
613
|
+
expect(result.data.packable).toBe(false);
|
|
614
|
+
expect(result.data.issues).toEqual([
|
|
615
|
+
expect.objectContaining({
|
|
616
|
+
code: 'theme_module_stale',
|
|
617
|
+
message: expect.stringContaining(
|
|
618
|
+
'it re-exports oceanIcons, which is not the built theme',
|
|
619
|
+
),
|
|
620
|
+
}),
|
|
621
|
+
]);
|
|
622
|
+
});
|
|
623
|
+
|
|
624
|
+
it('fails when packing changes the module an entry re-exports', async () => {
|
|
625
|
+
const prepack = [
|
|
626
|
+
"const fs=require('fs')",
|
|
627
|
+
"fs.copyFileSync('themes/ocean/ocean.js','.ocean.js.orig')",
|
|
628
|
+
"fs.appendFileSync('themes/ocean/ocean.js','// packed\\n')",
|
|
629
|
+
].join(';');
|
|
630
|
+
const postpack =
|
|
631
|
+
"require('fs').renameSync('.ocean.js.orig','themes/ocean/ocean.js')";
|
|
632
|
+
writePackage({
|
|
633
|
+
themeExports: true,
|
|
634
|
+
scripts: {
|
|
635
|
+
prepack: `node -e "${prepack}"`,
|
|
636
|
+
postpack: `node -e "${postpack}"`,
|
|
637
|
+
},
|
|
638
|
+
});
|
|
639
|
+
writeOwnStylesEntry(OWN_STYLES_ENTRY);
|
|
640
|
+
|
|
641
|
+
const result = await integrationPackCheck({cwd: tmpDir});
|
|
642
|
+
|
|
643
|
+
expect(result.data.packable).toBe(false);
|
|
644
|
+
expect(result.data.issues).toEqual([
|
|
645
|
+
{
|
|
646
|
+
code: 'packed_theme_module_changed',
|
|
647
|
+
severity: 'error',
|
|
648
|
+
message:
|
|
649
|
+
'Theme "ocean" module changed during packing. Keep the built output unchanged in the tarball.',
|
|
650
|
+
},
|
|
651
|
+
]);
|
|
652
|
+
});
|
|
653
|
+
});
|
|
654
|
+
|
|
306
655
|
describe('integrationPackCheck', () => {
|
|
307
656
|
it('returns packable:true for a valid integration with themes', async () => {
|
|
308
657
|
writePackage({files: ['astryx.integration.mjs', 'themes']});
|
|
@@ -337,8 +686,7 @@ describe('integrationPackCheck', () => {
|
|
|
337
686
|
{
|
|
338
687
|
code: 'theme_exports_missing',
|
|
339
688
|
severity: 'warning',
|
|
340
|
-
message:
|
|
341
|
-
'Theme "ocean" has no declared built exports. The package remains source-compatible. To make it importable, run `astryx theme build themes/ocean/oceanTheme.ts` and export "./themes/ocean" plus "./themes/ocean.css" from package.json; `astryx integration add theme ocean` creates those exports for a new theme.',
|
|
689
|
+
message: `Theme "ocean" has no declared built exports. The package remains source-compatible. To make it importable, run \`${formatCliCommand('theme build themes/ocean/oceanTheme.ts', tmpDir)}\` and export "./themes/ocean" plus "./themes/ocean.css" from package.json; \`${formatCliCommand('integration add theme ocean', tmpDir)}\` creates those exports for a new theme.`,
|
|
342
690
|
},
|
|
343
691
|
]);
|
|
344
692
|
const cli = runCliVerify();
|
|
@@ -509,8 +857,7 @@ describe('integrationPackCheck', () => {
|
|
|
509
857
|
{
|
|
510
858
|
code: 'theme_stylesheet_stale',
|
|
511
859
|
severity: 'warning',
|
|
512
|
-
message:
|
|
513
|
-
'Theme "ocean" stylesheet does not match themes/ocean/oceanTheme.ts. This incomplete export remains packable, but run `astryx theme build themes/ocean/oceanTheme.ts` before adding its matching export.',
|
|
860
|
+
message: `Theme "ocean" stylesheet does not match themes/ocean/oceanTheme.ts. This incomplete export remains packable, but run \`${formatCliCommand('theme build themes/ocean/oceanTheme.ts', tmpDir)}\` before adding its matching export.`,
|
|
514
861
|
},
|
|
515
862
|
]);
|
|
516
863
|
const cli = runCliVerify();
|
|
@@ -543,8 +890,7 @@ describe('integrationPackCheck', () => {
|
|
|
543
890
|
{
|
|
544
891
|
code: 'theme_stylesheet_stale',
|
|
545
892
|
severity: 'warning',
|
|
546
|
-
message:
|
|
547
|
-
'Theme "ocean" stylesheet does not match themes/ocean/oceanTheme.ts. This incomplete export remains packable, but run `astryx theme build themes/ocean/oceanTheme.ts` before adding its matching export.',
|
|
893
|
+
message: `Theme "ocean" stylesheet does not match themes/ocean/oceanTheme.ts. This incomplete export remains packable, but run \`${formatCliCommand('theme build themes/ocean/oceanTheme.ts', tmpDir)}\` before adding its matching export.`,
|
|
548
894
|
},
|
|
549
895
|
]);
|
|
550
896
|
const cli = runCliVerify();
|
|
@@ -617,14 +963,12 @@ describe('integrationPackCheck', () => {
|
|
|
617
963
|
{
|
|
618
964
|
code: 'theme_module_stale',
|
|
619
965
|
severity: 'error',
|
|
620
|
-
message:
|
|
621
|
-
'Theme "ocean" module does not match themes/ocean/oceanTheme.ts. Run `astryx theme build themes/ocean/oceanTheme.ts` before packing.',
|
|
966
|
+
message: `Theme "ocean" module does not match themes/ocean/oceanTheme.ts. Run \`${formatCliCommand('theme build themes/ocean/oceanTheme.ts', tmpDir)}\` before packing.`,
|
|
622
967
|
},
|
|
623
968
|
{
|
|
624
969
|
code: 'theme_stylesheet_stale',
|
|
625
970
|
severity: 'error',
|
|
626
|
-
message:
|
|
627
|
-
'Theme "ocean" stylesheet does not match themes/ocean/oceanTheme.ts. Run `astryx theme build themes/ocean/oceanTheme.ts` before packing.',
|
|
971
|
+
message: `Theme "ocean" stylesheet does not match themes/ocean/oceanTheme.ts. Run \`${formatCliCommand('theme build themes/ocean/oceanTheme.ts', tmpDir)}\` before packing.`,
|
|
628
972
|
},
|
|
629
973
|
]);
|
|
630
974
|
const cli = runCliVerify();
|
|
@@ -1558,6 +1902,23 @@ describe('integrationPackCheck', () => {
|
|
|
1558
1902
|
expect(sourceWarnings[0].message).toContain('Card.tsx');
|
|
1559
1903
|
});
|
|
1560
1904
|
|
|
1905
|
+
it('reports template sources without metadata as warnings', async () => {
|
|
1906
|
+
writePackage({
|
|
1907
|
+
manifest:
|
|
1908
|
+
"export default {themes: './themes', templates: './templates'};\n",
|
|
1909
|
+
files: ['astryx.integration.mjs', 'themes', 'templates'],
|
|
1910
|
+
templates: true,
|
|
1911
|
+
});
|
|
1912
|
+
const result = await integrationPackCheck({cwd: tmpDir});
|
|
1913
|
+
|
|
1914
|
+
const sourceWarnings = result.data.issues.filter(
|
|
1915
|
+
issue => issue.code === 'source_without_template_doc',
|
|
1916
|
+
);
|
|
1917
|
+
expect(sourceWarnings).toHaveLength(1);
|
|
1918
|
+
expect(sourceWarnings[0].severity).toBe('warning');
|
|
1919
|
+
expect(sourceWarnings[0].message).toContain('stray.tsx');
|
|
1920
|
+
});
|
|
1921
|
+
|
|
1561
1922
|
it('cleans up its scratch consumer when npm pack fails', async () => {
|
|
1562
1923
|
writePackage({
|
|
1563
1924
|
files: ['astryx.integration.mjs', 'themes'],
|
|
@@ -37,6 +37,8 @@ const componentDoc = name =>
|
|
|
37
37
|
`export default {type: 'component', name: '${name}', displayName: '${name}', usage: {description: '${name}.'}, props: []};\n`;
|
|
38
38
|
/** @param {string} name */
|
|
39
39
|
const componentSource = name => `export function ${name}() { return null; }\n`;
|
|
40
|
+
const templateSource = name =>
|
|
41
|
+
`export default function ${name}() { return null; }\n`;
|
|
40
42
|
/** @param {string} name */
|
|
41
43
|
const topic = name =>
|
|
42
44
|
`export default ${JSON.stringify({
|
|
@@ -1131,6 +1133,71 @@ describe('source_without_component_doc fixes hold when followed', () => {
|
|
|
1131
1133
|
});
|
|
1132
1134
|
});
|
|
1133
1135
|
|
|
1136
|
+
describe('source_without_template_doc fixes hold when followed', () => {
|
|
1137
|
+
it('adds the named doc, which resolves the warning', async () => {
|
|
1138
|
+
const dir = writePackage({
|
|
1139
|
+
[MANIFEST]: manifest({templates: './templates'}),
|
|
1140
|
+
'templates/hero.tsx': templateSource('Hero'),
|
|
1141
|
+
'templates/hero.test.tsx': templateSource('HeroTest'),
|
|
1142
|
+
});
|
|
1143
|
+
|
|
1144
|
+
const message = only(await issuesOf(dir), 'source_without_template_doc');
|
|
1145
|
+
expect(message).toBe(
|
|
1146
|
+
"Template source \"hero.tsx\" has no same-stem metadata file hero.doc.mjs, so `astryx template` never lists it. Fix: add hero.doc.mjs beside it with type: 'page' or 'block'; `astryx docs authoring integration-template-doc` lists its fields. If it is not a template, move it out of the templates root.",
|
|
1147
|
+
);
|
|
1148
|
+
|
|
1149
|
+
const fixed = follow(dir, {
|
|
1150
|
+
write: {
|
|
1151
|
+
'templates/hero.doc.mjs': `export default {type: 'page', name: 'hero', displayName: 'Hero'};\n`,
|
|
1152
|
+
},
|
|
1153
|
+
});
|
|
1154
|
+
expect(await issuesOf(fixed)).toEqual([]);
|
|
1155
|
+
});
|
|
1156
|
+
|
|
1157
|
+
it('checks a dotted template id, but no test, spec or story file', async () => {
|
|
1158
|
+
const dir = writePackage({
|
|
1159
|
+
[MANIFEST]: manifest({templates: './templates'}),
|
|
1160
|
+
'templates/landing.page.tsx': templateSource('LandingPage'),
|
|
1161
|
+
'templates/hero.test.tsx': templateSource('HeroTest'),
|
|
1162
|
+
'templates/hero.spec.tsx': templateSource('HeroSpec'),
|
|
1163
|
+
'templates/hero.stories.tsx': templateSource('HeroStories'),
|
|
1164
|
+
});
|
|
1165
|
+
|
|
1166
|
+
const message = only(await issuesOf(dir), 'source_without_template_doc');
|
|
1167
|
+
expect(message).toContain(
|
|
1168
|
+
'Template source "landing.page.tsx" has no same-stem metadata file landing.page.doc.mjs',
|
|
1169
|
+
);
|
|
1170
|
+
|
|
1171
|
+
const fixed = follow(dir, {
|
|
1172
|
+
write: {
|
|
1173
|
+
'templates/landing.page.doc.mjs': `export default {type: 'page', name: 'landing.page', displayName: 'Landing'};\n`,
|
|
1174
|
+
},
|
|
1175
|
+
});
|
|
1176
|
+
expect(await issuesOf(fixed)).toEqual([]);
|
|
1177
|
+
});
|
|
1178
|
+
|
|
1179
|
+
it('never flags a helper in a subfolder of the templates root', async () => {
|
|
1180
|
+
const dir = writePackage({
|
|
1181
|
+
[MANIFEST]: manifest({templates: './templates'}),
|
|
1182
|
+
'templates/hero.doc.mjs': `export default {type: 'page', name: 'hero', displayName: 'Hero'};\n`,
|
|
1183
|
+
'templates/hero.tsx': templateSource('Hero'),
|
|
1184
|
+
'templates/hero/HeroCard.tsx': templateSource('HeroCard'),
|
|
1185
|
+
});
|
|
1186
|
+
|
|
1187
|
+
expect(await issuesOf(dir)).toEqual([]);
|
|
1188
|
+
});
|
|
1189
|
+
|
|
1190
|
+
it('accepts a released .template.mjs spec as the metadata', async () => {
|
|
1191
|
+
const dir = writePackage({
|
|
1192
|
+
[MANIFEST]: manifest({templates: './templates'}),
|
|
1193
|
+
'templates/hero.tsx': templateSource('Hero'),
|
|
1194
|
+
'templates/hero.template.mjs': `export default {type: 'page', name: 'hero', displayName: 'Hero'};\n`,
|
|
1195
|
+
});
|
|
1196
|
+
|
|
1197
|
+
expect(await issuesOf(dir)).toEqual([]);
|
|
1198
|
+
});
|
|
1199
|
+
});
|
|
1200
|
+
|
|
1134
1201
|
describe('codemod fixes hold when followed', () => {
|
|
1135
1202
|
it('moves a stray codemod into a version folder, and renames a mis-named one', async () => {
|
|
1136
1203
|
const dir = writePackage({
|
|
@@ -67,6 +67,14 @@ export type ValidateResult = {
|
|
|
67
67
|
*/
|
|
68
68
|
reason?: "no_package_json" | undefined;
|
|
69
69
|
issues: Issue[];
|
|
70
|
+
/**
|
|
71
|
+
* Information that
|
|
72
|
+
* fails nothing, such as `invalid_cli_command` (a malformed `cliCommand`).
|
|
73
|
+
*/
|
|
74
|
+
notes?: {
|
|
75
|
+
code: string;
|
|
76
|
+
message: string;
|
|
77
|
+
}[] | undefined;
|
|
70
78
|
integration?: import("../../foundation/integrations/integrations.mjs").LoadedIntegration | undefined;
|
|
71
79
|
};
|
|
72
80
|
import { validateLoadedIntegration } from '../../foundation/integrations/validate-contributions.mjs';
|
|
@@ -35,6 +35,7 @@ import * as fs from 'node:fs';
|
|
|
35
35
|
import * as path from 'node:path';
|
|
36
36
|
import {assertWithin} from '../../foundation/fs/path-safety.mjs';
|
|
37
37
|
import {integrationDocTypes} from '../docs/_adapter.mjs';
|
|
38
|
+
import {integrationDocConsistency} from '../../foundation/discovery/doc-consistency.mjs';
|
|
38
39
|
import {
|
|
39
40
|
THEME_SLUG_RE,
|
|
40
41
|
unreadThemeFolders,
|
|
@@ -55,11 +56,13 @@ import {
|
|
|
55
56
|
// The on-disk contribution validators live in foundation: Project and
|
|
56
57
|
// integration-warnings need them too, and foundation must not depend on api.
|
|
57
58
|
import {
|
|
59
|
+
INVALID_CLI_COMMAND,
|
|
58
60
|
validateLoadedIntegration,
|
|
59
61
|
issueError as error,
|
|
60
62
|
issueWarning as warning,
|
|
61
63
|
rootProblem,
|
|
62
64
|
} from '../../foundation/integrations/validate-contributions.mjs';
|
|
65
|
+
import {formatCliCommand} from '../../foundation/env/package-manager.mjs';
|
|
63
66
|
|
|
64
67
|
export {validateLoadedIntegration};
|
|
65
68
|
|
|
@@ -75,6 +78,8 @@ export {validateLoadedIntegration};
|
|
|
75
78
|
* @property {string} [manifestFile] Absolute path to the loaded manifest.
|
|
76
79
|
* @property {'no_package_json'} [reason] Why nothing was validated (internal).
|
|
77
80
|
* @property {Issue[]} issues
|
|
81
|
+
* @property {Array<{code: string, message: string}>} [notes] Information that
|
|
82
|
+
* fails nothing, such as `invalid_cli_command` (a malformed `cliCommand`).
|
|
78
83
|
* @property {import('../../foundation/integrations/integrations.mjs').LoadedIntegration} [integration]
|
|
79
84
|
*/
|
|
80
85
|
|
|
@@ -124,7 +129,7 @@ function unreadThemeFolderIssues(packageDir, loaded) {
|
|
|
124
129
|
let fix;
|
|
125
130
|
if (THEME_SLUG_RE.test(name)) {
|
|
126
131
|
const stem = `${name.replace(/-([a-z0-9])/gu, (_, character) => character.toUpperCase())}Theme`;
|
|
127
|
-
fix = `if it is a theme, add ${stem}.ts and ${stem}.doc.mjs to it (
|
|
132
|
+
fix = `if it is a theme, add ${stem}.ts and ${stem}.doc.mjs to it (\`${formatCliCommand(`integration add theme ${name}`, packageDir)}\` writes both) and move its code into ${stem}.ts; if not, ${hide}.`;
|
|
128
133
|
} else {
|
|
129
134
|
fix = `${hide}; a theme folder needs a lower-kebab name.`;
|
|
130
135
|
}
|
|
@@ -283,11 +288,14 @@ async function validateAtPackageDir(
|
|
|
283
288
|
let unknownKeys;
|
|
284
289
|
/** @type {string | undefined} */
|
|
285
290
|
let agentDocsError;
|
|
291
|
+
/** @type {string | undefined} */
|
|
292
|
+
let cliCommandError;
|
|
286
293
|
try {
|
|
287
|
-
({manifest, unknownKeys, agentDocsError} =
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
294
|
+
({manifest, unknownKeys, agentDocsError, cliCommandError} =
|
|
295
|
+
await loadManifest(
|
|
296
|
+
manifestFile,
|
|
297
|
+
`Integration manifest (${path.basename(manifestFile)})`,
|
|
298
|
+
));
|
|
291
299
|
} catch (err) {
|
|
292
300
|
issues.push(error('invalid_manifest', /** @type {any} */ (err).message));
|
|
293
301
|
return result;
|
|
@@ -319,6 +327,8 @@ async function validateAtPackageDir(
|
|
|
319
327
|
themes: resolveRoot(manifest.themes),
|
|
320
328
|
issuesUrl: manifest.issuesUrl,
|
|
321
329
|
agentDocs: manifest.agentDocs,
|
|
330
|
+
cliCommand: manifest.cliCommand,
|
|
331
|
+
__cliCommandError: cliCommandError,
|
|
322
332
|
__agentDocsError: agentDocsError,
|
|
323
333
|
__unknownKeys: unknownKeys,
|
|
324
334
|
__spec: identity.name,
|
|
@@ -329,9 +339,35 @@ async function validateAtPackageDir(
|
|
|
329
339
|
|
|
330
340
|
// Roots + contribution checks are shared with validateLoadedIntegration so
|
|
331
341
|
// the everyday-command nudge runs the exact same validators.
|
|
332
|
-
issues
|
|
342
|
+
// A malformed `cliCommand` is an info note beside the issues, not an issue:
|
|
343
|
+
// `integration check --strict` fails on any warning, and a new failure code
|
|
344
|
+
// joins only in a minor release (architecture:cli-surface INV35). Doctor's
|
|
345
|
+
// project check still warns about it.
|
|
346
|
+
for (const issue of await validateLoadedIntegration(loaded)) {
|
|
347
|
+
if (issue.code === INVALID_CLI_COMMAND) {
|
|
348
|
+
(result.notes ??= []).push({code: issue.code, message: issue.message});
|
|
349
|
+
} else {
|
|
350
|
+
issues.push(issue);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
333
353
|
if (loaded.themes && !rootProblem(loaded.themes))
|
|
334
354
|
issues.push(...unreadThemeFolderIssues(packageDir, loaded));
|
|
355
|
+
// What the docs say that no reader serves: a prop listed twice, an
|
|
356
|
+
// overlay's text for a prop the doc lacks, an empty or unreachable section,
|
|
357
|
+
// and an overlay of no topic.
|
|
358
|
+
issues.push(
|
|
359
|
+
...(await integrationDocConsistency(
|
|
360
|
+
{
|
|
361
|
+
components:
|
|
362
|
+
loaded.components && !rootProblem(loaded.components)
|
|
363
|
+
? loaded.components
|
|
364
|
+
: undefined,
|
|
365
|
+
docs:
|
|
366
|
+
loaded.docs && !rootProblem(loaded.docs) ? loaded.docs : undefined,
|
|
367
|
+
},
|
|
368
|
+
packageDir,
|
|
369
|
+
)),
|
|
370
|
+
);
|
|
335
371
|
if (scanUnreachable) {
|
|
336
372
|
issues.push(
|
|
337
373
|
...(await findUnreachableContributionIssues(packageDir, loaded)),
|
|
@@ -468,6 +504,7 @@ export async function validateIntegration(pkg, options = {}) {
|
|
|
468
504
|
const docTypes = integration
|
|
469
505
|
? await integrationDocTypes(integration, cwd)
|
|
470
506
|
: undefined;
|
|
507
|
+
const notes = result.found ? (result.notes ?? []) : [];
|
|
471
508
|
return {
|
|
472
509
|
type: 'integration.validate',
|
|
473
510
|
data: {
|
|
@@ -476,9 +513,18 @@ export async function validateIntegration(pkg, options = {}) {
|
|
|
476
513
|
validated: result.found,
|
|
477
514
|
name: result.found ? (result.name ?? null) : null,
|
|
478
515
|
version: result.found ? (result.version ?? null) : null,
|
|
479
|
-
issues:
|
|
480
|
-
|
|
481
|
-
|
|
516
|
+
issues:
|
|
517
|
+
result.reason === 'no_package_json'
|
|
518
|
+
? [
|
|
519
|
+
{
|
|
520
|
+
code: 'no_package',
|
|
521
|
+
severity: 'error',
|
|
522
|
+
message:
|
|
523
|
+
'No package.json found. Run this command inside a package directory.',
|
|
524
|
+
},
|
|
525
|
+
]
|
|
526
|
+
: result.issues,
|
|
527
|
+
...(notes.length > 0 ? {notes} : {}),
|
|
482
528
|
...(docTypes ? {docTypes} : {}),
|
|
483
529
|
},
|
|
484
530
|
};
|