@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
|
@@ -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();
|
|
@@ -754,6 +1098,285 @@ describe('integrationPackCheck', () => {
|
|
|
754
1098
|
);
|
|
755
1099
|
});
|
|
756
1100
|
|
|
1101
|
+
it('checks the export a component doc names when its file is named otherwise', async () => {
|
|
1102
|
+
fs.writeFileSync(
|
|
1103
|
+
path.join(tmpDir, 'package.json'),
|
|
1104
|
+
`${JSON.stringify({
|
|
1105
|
+
name: '@acme/widgets',
|
|
1106
|
+
version: '1.0.0',
|
|
1107
|
+
files: ['astryx.integration.mjs', 'components'],
|
|
1108
|
+
exports: {'./components/Slides': './components/Slides.tsx'},
|
|
1109
|
+
})}\n`,
|
|
1110
|
+
);
|
|
1111
|
+
fs.writeFileSync(
|
|
1112
|
+
path.join(tmpDir, 'astryx.integration.mjs'),
|
|
1113
|
+
"export default {components: './components'};\n",
|
|
1114
|
+
);
|
|
1115
|
+
fs.mkdirSync(path.join(tmpDir, 'components'));
|
|
1116
|
+
// Slides.tsx exports AcmeCarousel and nothing named Slides.
|
|
1117
|
+
fs.writeFileSync(
|
|
1118
|
+
path.join(tmpDir, 'components', 'Slides.tsx'),
|
|
1119
|
+
'export function AcmeCarousel() { return null; }\n',
|
|
1120
|
+
);
|
|
1121
|
+
fs.writeFileSync(
|
|
1122
|
+
path.join(tmpDir, 'components', 'Slides.doc.mjs'),
|
|
1123
|
+
"export default {type: 'component', name: 'AcmeCarousel', import: '@acme/widgets/components/Slides', description: 'x', props: []};\n",
|
|
1124
|
+
);
|
|
1125
|
+
|
|
1126
|
+
const result = await integrationPackCheck({cwd: tmpDir});
|
|
1127
|
+
expect(result.data.packable).toBe(true);
|
|
1128
|
+
expect(result.data.contributions.packed.components).toEqual([
|
|
1129
|
+
'AcmeCarousel',
|
|
1130
|
+
]);
|
|
1131
|
+
});
|
|
1132
|
+
|
|
1133
|
+
it('checks each family member against the module its family doc imports', async () => {
|
|
1134
|
+
fs.writeFileSync(
|
|
1135
|
+
path.join(tmpDir, 'package.json'),
|
|
1136
|
+
`${JSON.stringify({
|
|
1137
|
+
name: '@acme/widgets',
|
|
1138
|
+
version: '1.0.0',
|
|
1139
|
+
files: ['astryx.integration.mjs', 'components'],
|
|
1140
|
+
exports: {'./tabs': './components/tabs/index.ts'},
|
|
1141
|
+
})}\n`,
|
|
1142
|
+
);
|
|
1143
|
+
fs.writeFileSync(
|
|
1144
|
+
path.join(tmpDir, 'astryx.integration.mjs'),
|
|
1145
|
+
"export default {components: './components'};\n",
|
|
1146
|
+
);
|
|
1147
|
+
const dir = path.join(tmpDir, 'components', 'tabs');
|
|
1148
|
+
fs.mkdirSync(dir, {recursive: true});
|
|
1149
|
+
fs.writeFileSync(
|
|
1150
|
+
path.join(dir, 'AcmeTabs.tsx'),
|
|
1151
|
+
'export function AcmeTabs() { return null; }\nexport function AcmeTabsLegacy() { return null; }\n',
|
|
1152
|
+
);
|
|
1153
|
+
fs.writeFileSync(
|
|
1154
|
+
path.join(dir, 'tab.tsx'),
|
|
1155
|
+
'export function AcmeTab() { return null; }\n',
|
|
1156
|
+
);
|
|
1157
|
+
// The module apps import exports AcmeTabs and AcmeTab, not AcmeTabsLegacy.
|
|
1158
|
+
fs.writeFileSync(
|
|
1159
|
+
path.join(dir, 'index.ts'),
|
|
1160
|
+
"export {AcmeTabs} from './AcmeTabs';\nexport {AcmeTab} from './tab';\n",
|
|
1161
|
+
);
|
|
1162
|
+
fs.writeFileSync(
|
|
1163
|
+
path.join(dir, 'AcmeTabs.doc.mjs'),
|
|
1164
|
+
"export default {type: 'component', name: 'AcmeTabs', import: '@acme/widgets/tabs', description: 'x', components: [{name: 'AcmeTabs', description: 'x', props: []}, {name: 'AcmeTab', description: 'x', props: []}, {name: 'AcmeTabsLegacy', description: 'x', props: []}]};\n",
|
|
1165
|
+
);
|
|
1166
|
+
|
|
1167
|
+
const result = await integrationPackCheck({cwd: tmpDir});
|
|
1168
|
+
|
|
1169
|
+
expect(result.data.issues).toEqual([]);
|
|
1170
|
+
expect(result.data.packable).toBe(true);
|
|
1171
|
+
expect(result.data.contributions.packed.components).toEqual([
|
|
1172
|
+
'AcmeTab',
|
|
1173
|
+
'AcmeTabs',
|
|
1174
|
+
]);
|
|
1175
|
+
});
|
|
1176
|
+
|
|
1177
|
+
it.each([
|
|
1178
|
+
'a clean checkout',
|
|
1179
|
+
'a stale build',
|
|
1180
|
+
'a stale build that exports more',
|
|
1181
|
+
])(
|
|
1182
|
+
'reads members a family imports from output its pack lifecycle builds, from %s',
|
|
1183
|
+
async start => {
|
|
1184
|
+
fs.writeFileSync(
|
|
1185
|
+
path.join(tmpDir, 'package.json'),
|
|
1186
|
+
`${JSON.stringify({
|
|
1187
|
+
name: '@acme/widgets',
|
|
1188
|
+
version: '1.0.0',
|
|
1189
|
+
files: ['astryx.integration.mjs', 'components', 'dist'],
|
|
1190
|
+
exports: {'./tabs': './dist/tabs/index.mjs'},
|
|
1191
|
+
scripts: {prepack: 'node build.mjs'},
|
|
1192
|
+
})}\n`,
|
|
1193
|
+
);
|
|
1194
|
+
fs.writeFileSync(
|
|
1195
|
+
path.join(tmpDir, 'astryx.integration.mjs'),
|
|
1196
|
+
"export default {components: './components'};\n",
|
|
1197
|
+
);
|
|
1198
|
+
// The build writes the module the family imports; a clean checkout has none.
|
|
1199
|
+
fs.writeFileSync(
|
|
1200
|
+
path.join(tmpDir, 'build.mjs'),
|
|
1201
|
+
"import fs from 'node:fs';\nfs.mkdirSync('dist/tabs', {recursive: true});\nfs.writeFileSync('dist/tabs/index.mjs', \"export {AcmeTabs, AcmeTab} from '../../components/tabs/AcmeTabs.tsx';\\n\");\n",
|
|
1202
|
+
);
|
|
1203
|
+
const dir = path.join(tmpDir, 'components', 'tabs');
|
|
1204
|
+
fs.mkdirSync(dir, {recursive: true});
|
|
1205
|
+
fs.writeFileSync(
|
|
1206
|
+
path.join(dir, 'AcmeTabs.tsx'),
|
|
1207
|
+
'export function AcmeTabs() { return null; }\nexport function AcmeTab() { return null; }\nexport function AcmeTabLegacy() { return null; }\n',
|
|
1208
|
+
);
|
|
1209
|
+
fs.writeFileSync(
|
|
1210
|
+
path.join(dir, 'AcmeTabs.doc.mjs'),
|
|
1211
|
+
"export default {type: 'component', name: 'AcmeTabs', import: '@acme/widgets/tabs', description: 'x', components: [{name: 'AcmeTabs', description: 'x', props: []}, {name: 'AcmeTab', description: 'x', props: []}, {name: 'AcmeTabLegacy', description: 'x', props: []}]};\n",
|
|
1212
|
+
);
|
|
1213
|
+
|
|
1214
|
+
if (start !== 'a clean checkout') {
|
|
1215
|
+
// An earlier build: before AcmeTab was exported, or while AcmeTabLegacy
|
|
1216
|
+
// still was.
|
|
1217
|
+
const names =
|
|
1218
|
+
start === 'a stale build'
|
|
1219
|
+
? 'AcmeTabs'
|
|
1220
|
+
: 'AcmeTabs, AcmeTab, AcmeTabLegacy';
|
|
1221
|
+
fs.mkdirSync(path.join(tmpDir, 'dist', 'tabs'), {recursive: true});
|
|
1222
|
+
fs.writeFileSync(
|
|
1223
|
+
path.join(tmpDir, 'dist', 'tabs', 'index.mjs'),
|
|
1224
|
+
`export {${names}} from '../../components/tabs/AcmeTabs.tsx';\n`,
|
|
1225
|
+
);
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
const result = await integrationPackCheck({cwd: tmpDir});
|
|
1229
|
+
|
|
1230
|
+
expect(result.data.issues).toEqual([]);
|
|
1231
|
+
expect(result.data.packable).toBe(true);
|
|
1232
|
+
expect(result.data.contributions.local.components).toEqual(
|
|
1233
|
+
result.data.contributions.packed.components,
|
|
1234
|
+
);
|
|
1235
|
+
},
|
|
1236
|
+
);
|
|
1237
|
+
|
|
1238
|
+
it.each(['a clean checkout', 'an incremental build'])(
|
|
1239
|
+
'reads members built output re-exports from compiled files, from %s',
|
|
1240
|
+
async start => {
|
|
1241
|
+
fs.writeFileSync(
|
|
1242
|
+
path.join(tmpDir, 'package.json'),
|
|
1243
|
+
`${JSON.stringify({
|
|
1244
|
+
name: '@acme/widgets',
|
|
1245
|
+
version: '1.0.0',
|
|
1246
|
+
files: ['astryx.integration.mjs', 'components', 'dist'],
|
|
1247
|
+
exports: {'./tabs': './dist/tabs/index.mjs'},
|
|
1248
|
+
scripts: {prepack: 'node build.mjs'},
|
|
1249
|
+
})}\n`,
|
|
1250
|
+
);
|
|
1251
|
+
fs.writeFileSync(
|
|
1252
|
+
path.join(tmpDir, 'astryx.integration.mjs'),
|
|
1253
|
+
"export default {components: './components'};\n",
|
|
1254
|
+
);
|
|
1255
|
+
// The build compiles each source to its own file and, like an
|
|
1256
|
+
// incremental build, rewrites only the files whose output changed.
|
|
1257
|
+
const output = {
|
|
1258
|
+
'index.mjs':
|
|
1259
|
+
"export {AcmeTabs} from './tabs.mjs';\nexport * from './tab.mjs';\n",
|
|
1260
|
+
'tabs.mjs': 'export function AcmeTabs() { return null; }\n',
|
|
1261
|
+
'tab.mjs': 'export function AcmeTab() { return null; }\n',
|
|
1262
|
+
};
|
|
1263
|
+
fs.writeFileSync(
|
|
1264
|
+
path.join(tmpDir, 'build.mjs'),
|
|
1265
|
+
`import fs from 'node:fs';\nconst output = ${JSON.stringify(output)};\nfs.mkdirSync('dist/tabs', {recursive: true});\nfor (const [file, text] of Object.entries(output)) {\n const target = 'dist/tabs/' + file;\n if (!fs.existsSync(target) || fs.readFileSync(target, 'utf-8') !== text) fs.writeFileSync(target, text);\n}\n`,
|
|
1266
|
+
);
|
|
1267
|
+
const dir = path.join(tmpDir, 'components', 'tabs');
|
|
1268
|
+
fs.mkdirSync(dir, {recursive: true});
|
|
1269
|
+
fs.writeFileSync(
|
|
1270
|
+
path.join(dir, 'AcmeTabs.tsx'),
|
|
1271
|
+
'export function AcmeTabs() { return null; }\n',
|
|
1272
|
+
);
|
|
1273
|
+
fs.writeFileSync(
|
|
1274
|
+
path.join(dir, 'AcmeTab.tsx'),
|
|
1275
|
+
'export function AcmeTab() { return null; }\n',
|
|
1276
|
+
);
|
|
1277
|
+
fs.writeFileSync(
|
|
1278
|
+
path.join(dir, 'AcmeTabs.doc.mjs'),
|
|
1279
|
+
"export default {type: 'component', name: 'AcmeTabs', import: '@acme/widgets/tabs', description: 'x', components: [{name: 'AcmeTabs', description: 'x', props: []}, {name: 'AcmeTab', description: 'x', props: []}]};\n",
|
|
1280
|
+
);
|
|
1281
|
+
if (start === 'an incremental build') {
|
|
1282
|
+
// An earlier build from before AcmeTab existed: the file the import
|
|
1283
|
+
// names is already current, so the build leaves it untouched.
|
|
1284
|
+
fs.mkdirSync(path.join(tmpDir, 'dist', 'tabs'), {recursive: true});
|
|
1285
|
+
for (const [file, text] of Object.entries({...output, 'tab.mjs': ''})) {
|
|
1286
|
+
fs.writeFileSync(path.join(tmpDir, 'dist', 'tabs', file), text);
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1290
|
+
const result = await integrationPackCheck({cwd: tmpDir});
|
|
1291
|
+
|
|
1292
|
+
expect(result.data.issues).toEqual([]);
|
|
1293
|
+
expect(result.data.packable).toBe(true);
|
|
1294
|
+
expect(result.data.contributions.packed.components).toEqual([
|
|
1295
|
+
'AcmeTab',
|
|
1296
|
+
'AcmeTabs',
|
|
1297
|
+
]);
|
|
1298
|
+
expect(result.data.contributions.local.components).toEqual(
|
|
1299
|
+
result.data.contributions.packed.components,
|
|
1300
|
+
);
|
|
1301
|
+
},
|
|
1302
|
+
);
|
|
1303
|
+
|
|
1304
|
+
it('passes a member another folder declares, which has no source', async () => {
|
|
1305
|
+
fs.writeFileSync(
|
|
1306
|
+
path.join(tmpDir, 'package.json'),
|
|
1307
|
+
`${JSON.stringify({
|
|
1308
|
+
name: '@acme/widgets',
|
|
1309
|
+
version: '1.0.0',
|
|
1310
|
+
files: ['astryx.integration.mjs', 'components'],
|
|
1311
|
+
exports: {'./menu': './components/menu/index.ts'},
|
|
1312
|
+
})}\n`,
|
|
1313
|
+
);
|
|
1314
|
+
fs.writeFileSync(
|
|
1315
|
+
path.join(tmpDir, 'astryx.integration.mjs'),
|
|
1316
|
+
"export default {components: './components'};\n",
|
|
1317
|
+
);
|
|
1318
|
+
const menu = path.join(tmpDir, 'components', 'menu');
|
|
1319
|
+
const shared = path.join(tmpDir, 'components', 'shared');
|
|
1320
|
+
fs.mkdirSync(menu, {recursive: true});
|
|
1321
|
+
fs.mkdirSync(shared, {recursive: true});
|
|
1322
|
+
fs.writeFileSync(
|
|
1323
|
+
path.join(menu, 'AcmeMenu.doc.mjs'),
|
|
1324
|
+
"export default {type: 'component', name: 'AcmeMenu', import: '@acme/widgets/menu', description: 'x', components: [{name: 'AcmeMenuItem', description: 'x', props: []}]};\n",
|
|
1325
|
+
);
|
|
1326
|
+
fs.writeFileSync(
|
|
1327
|
+
path.join(menu, 'AcmeMenu.tsx'),
|
|
1328
|
+
'export function AcmeMenu() { return null; }\n',
|
|
1329
|
+
);
|
|
1330
|
+
fs.writeFileSync(
|
|
1331
|
+
path.join(menu, 'index.ts'),
|
|
1332
|
+
"export {AcmeMenu} from './AcmeMenu';\nexport {AcmeMenuItem} from '../shared/AcmeMenuItem';\n",
|
|
1333
|
+
);
|
|
1334
|
+
fs.writeFileSync(
|
|
1335
|
+
path.join(shared, 'AcmeMenuItem.tsx'),
|
|
1336
|
+
'export function AcmeMenuItem() { return null; }\n',
|
|
1337
|
+
);
|
|
1338
|
+
|
|
1339
|
+
const result = await integrationPackCheck({cwd: tmpDir});
|
|
1340
|
+
|
|
1341
|
+
expect(result.data.issues).toEqual([]);
|
|
1342
|
+
expect(result.data.packable).toBe(true);
|
|
1343
|
+
expect(result.data.contributions.packed.components).toEqual([
|
|
1344
|
+
'AcmeMenu',
|
|
1345
|
+
'AcmeMenuItem',
|
|
1346
|
+
]);
|
|
1347
|
+
});
|
|
1348
|
+
|
|
1349
|
+
it('reports a family doc the loader rejects once, not once per member', async () => {
|
|
1350
|
+
fs.writeFileSync(
|
|
1351
|
+
path.join(tmpDir, 'package.json'),
|
|
1352
|
+
`${JSON.stringify({
|
|
1353
|
+
name: '@acme/widgets',
|
|
1354
|
+
version: '1.0.0',
|
|
1355
|
+
files: ['astryx.integration.mjs', 'components'],
|
|
1356
|
+
})}\n`,
|
|
1357
|
+
);
|
|
1358
|
+
fs.writeFileSync(
|
|
1359
|
+
path.join(tmpDir, 'astryx.integration.mjs'),
|
|
1360
|
+
"export default {components: './components'};\n",
|
|
1361
|
+
);
|
|
1362
|
+
fs.mkdirSync(path.join(tmpDir, 'components'));
|
|
1363
|
+
fs.writeFileSync(
|
|
1364
|
+
path.join(tmpDir, 'components', 'AcmeTabs.tsx'),
|
|
1365
|
+
'export function AcmeTabs() { return null; }\nexport function AcmeTab() { return null; }\nexport function AcmeTabPanel() { return null; }\n',
|
|
1366
|
+
);
|
|
1367
|
+
// A displayName that is not a string makes the loader reject the doc.
|
|
1368
|
+
fs.writeFileSync(
|
|
1369
|
+
path.join(tmpDir, 'components', 'AcmeTabs.doc.mjs'),
|
|
1370
|
+
"export default {type: 'component', name: 'AcmeTabs', displayName: 1, description: 'x', components: [{name: 'AcmeTab', description: 'x', props: []}, {name: 'AcmeTabPanel', description: 'x', props: []}]};\n",
|
|
1371
|
+
);
|
|
1372
|
+
|
|
1373
|
+
const result = await integrationPackCheck({cwd: tmpDir});
|
|
1374
|
+
const codes = result.data.issues.map(issue => issue.code);
|
|
1375
|
+
|
|
1376
|
+
expect(codes).toContain('component_doc_unloadable');
|
|
1377
|
+
expect(codes.length).toBe(new Set(codes).size);
|
|
1378
|
+
});
|
|
1379
|
+
|
|
757
1380
|
it('passes a generated component through its exact packed export', async () => {
|
|
758
1381
|
fs.writeFileSync(
|
|
759
1382
|
path.join(tmpDir, 'package.json'),
|
|
@@ -811,6 +1434,86 @@ describe('integrationPackCheck', () => {
|
|
|
811
1434
|
);
|
|
812
1435
|
});
|
|
813
1436
|
|
|
1437
|
+
it('does not count a type-only re-export as the component', async () => {
|
|
1438
|
+
fs.writeFileSync(
|
|
1439
|
+
path.join(tmpDir, 'package.json'),
|
|
1440
|
+
`${JSON.stringify({
|
|
1441
|
+
name: '@acme/widgets',
|
|
1442
|
+
version: '1.0.0',
|
|
1443
|
+
files: ['astryx.integration.mjs', 'src'],
|
|
1444
|
+
exports: {'.': './src/index.ts'},
|
|
1445
|
+
})}\n`,
|
|
1446
|
+
);
|
|
1447
|
+
fs.writeFileSync(
|
|
1448
|
+
path.join(tmpDir, 'astryx.integration.mjs'),
|
|
1449
|
+
"export default {components: './src'};\n",
|
|
1450
|
+
);
|
|
1451
|
+
fs.mkdirSync(path.join(tmpDir, 'src'));
|
|
1452
|
+
fs.writeFileSync(
|
|
1453
|
+
path.join(tmpDir, 'src', 'index.ts'),
|
|
1454
|
+
"export type {AcmeWidget} from './AcmeWidget';\n",
|
|
1455
|
+
);
|
|
1456
|
+
fs.writeFileSync(
|
|
1457
|
+
path.join(tmpDir, 'src', 'AcmeWidget.tsx'),
|
|
1458
|
+
'export function AcmeWidget() { return null; }\n',
|
|
1459
|
+
);
|
|
1460
|
+
fs.writeFileSync(
|
|
1461
|
+
path.join(tmpDir, 'src', 'AcmeWidget.doc.mjs'),
|
|
1462
|
+
"export default {type: 'component', name: 'AcmeWidget', import: '@acme/widgets', description: 'Widget.', props: []};\n",
|
|
1463
|
+
);
|
|
1464
|
+
|
|
1465
|
+
const result = await integrationPackCheck({cwd: tmpDir});
|
|
1466
|
+
|
|
1467
|
+
expect(result.data.issues).toContainEqual(
|
|
1468
|
+
expect.objectContaining({code: 'component_export_missing'}),
|
|
1469
|
+
);
|
|
1470
|
+
});
|
|
1471
|
+
|
|
1472
|
+
it('follows a re-export of a folder to its index file', async () => {
|
|
1473
|
+
// `./primitives` names a folder: TypeScript and bundlers load its index file.
|
|
1474
|
+
fs.writeFileSync(
|
|
1475
|
+
path.join(tmpDir, 'package.json'),
|
|
1476
|
+
`${JSON.stringify({
|
|
1477
|
+
name: '@acme/widgets',
|
|
1478
|
+
version: '1.0.0',
|
|
1479
|
+
files: ['astryx.integration.mjs', 'src'],
|
|
1480
|
+
exports: {'.': './src/index.ts'},
|
|
1481
|
+
})}\n`,
|
|
1482
|
+
);
|
|
1483
|
+
fs.writeFileSync(
|
|
1484
|
+
path.join(tmpDir, 'astryx.integration.mjs'),
|
|
1485
|
+
"export default {components: './src'};\n",
|
|
1486
|
+
);
|
|
1487
|
+
const primitives = path.join(tmpDir, 'src', 'primitives');
|
|
1488
|
+
fs.mkdirSync(primitives, {recursive: true});
|
|
1489
|
+
fs.writeFileSync(
|
|
1490
|
+
path.join(tmpDir, 'src', 'index.ts'),
|
|
1491
|
+
"export * from './primitives';\n",
|
|
1492
|
+
);
|
|
1493
|
+
fs.writeFileSync(
|
|
1494
|
+
path.join(primitives, 'index.ts'),
|
|
1495
|
+
"export * from './AcmeWidget';\n",
|
|
1496
|
+
);
|
|
1497
|
+
fs.writeFileSync(
|
|
1498
|
+
path.join(primitives, 'AcmeWidget.tsx'),
|
|
1499
|
+
'export function AcmeWidget() { return null; }\n',
|
|
1500
|
+
);
|
|
1501
|
+
fs.writeFileSync(
|
|
1502
|
+
path.join(primitives, 'AcmeWidget.doc.mjs'),
|
|
1503
|
+
"export default {type: 'component', name: 'AcmeWidget', import: '@acme/widgets', description: 'Widget.', props: []};\n",
|
|
1504
|
+
);
|
|
1505
|
+
|
|
1506
|
+
const result = await integrationPackCheck({cwd: tmpDir});
|
|
1507
|
+
|
|
1508
|
+
expect(result.data.issues).not.toContainEqual(
|
|
1509
|
+
expect.objectContaining({code: 'component_export_missing'}),
|
|
1510
|
+
);
|
|
1511
|
+
expect(
|
|
1512
|
+
result.data.packable,
|
|
1513
|
+
JSON.stringify(result.data.issues, null, 2),
|
|
1514
|
+
).toBe(true);
|
|
1515
|
+
});
|
|
1516
|
+
|
|
814
1517
|
it('fails when packed template source is hidden by package exports', async () => {
|
|
815
1518
|
writePackage({
|
|
816
1519
|
manifest: "export default {templates: './templates'};\n",
|
|
@@ -1199,6 +1902,23 @@ describe('integrationPackCheck', () => {
|
|
|
1199
1902
|
expect(sourceWarnings[0].message).toContain('Card.tsx');
|
|
1200
1903
|
});
|
|
1201
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
|
+
|
|
1202
1922
|
it('cleans up its scratch consumer when npm pack fails', async () => {
|
|
1203
1923
|
writePackage({
|
|
1204
1924
|
files: ['astryx.integration.mjs', 'themes'],
|