@astryxdesign/cli 0.7.2-canary.fe2c655 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +119 -0
- package/README.md +175 -154
- package/api/build/_adapter.d.mts +8 -0
- package/api/build/_adapter.mjs +12 -1
- package/api/build/build.doc.mjs +4 -0
- package/api/build/help/help.mjs +1 -1
- package/api/build/kit/kit.mjs +3 -11
- package/api/component/_adapter.d.mts +72 -1
- package/api/component/_adapter.mjs +212 -18
- package/api/component/component.doc.mjs +6 -1
- package/api/component/component.mjs +82 -15
- package/api/component/component.test.mjs +80 -0
- package/api/component/doc-links.test.mjs +386 -0
- package/api/component/integration-export-name.test.mjs +644 -0
- package/api/component/list/list.mjs +42 -4
- package/api/discover/_adapter.d.mts +132 -12
- package/api/discover/_adapter.mjs +488 -27
- package/api/discover/_adapter.test.mjs +599 -17
- package/api/discover/_catalog-view.d.mts +16 -5
- package/api/discover/_catalog-view.mjs +32 -8
- package/api/discover/detail/doc/doc.mjs +9 -1
- package/api/discover/discover.d.mts +11 -0
- package/api/discover/discover.doc.mjs +9 -7
- package/api/discover/discover.mjs +121 -19
- package/api/discover/discover.type.d.mts +20 -7
- package/api/discover/discover.type.mjs +17 -7
- package/api/discover/list/list.d.mts +4 -3
- package/api/discover/list/list.mjs +17 -10
- package/api/docs/_adapter.d.mts +74 -0
- package/api/docs/_adapter.mjs +553 -16
- package/api/docs/docs.doc.mjs +2 -1
- package/api/docs/docs.mjs +2 -1
- package/api/docs/docs.test.mjs +5 -2
- package/api/docs/integration-tree.test.mjs +22 -0
- package/api/docs/integrationDocs.test.mjs +124 -0
- package/api/docs/list/list.mjs +12 -2
- package/api/docs/reference-blocks.test.mjs +1 -3
- package/api/doctor/_adapter.d.mts +108 -0
- package/api/doctor/_adapter.mjs +223 -4
- package/api/doctor/doctor.d.mts +199 -0
- package/api/doctor/doctor.doc.mjs +3 -2
- package/api/doctor/doctor.mjs +530 -34
- package/api/doctor/doctor.test.mjs +180 -14
- package/api/doctor/release-checks.test.mjs +156 -0
- package/api/doctor/theme-checks.mjs +17 -4
- package/api/doctor/theme-checks.test.mjs +223 -7
- package/api/error.d.mts +10 -0
- package/api/error.mjs +25 -0
- package/api/gap-report/gap-report.d.mts +3 -0
- package/api/gap-report/gap-report.doc.mjs +11 -3
- package/api/gap-report/gap-report.mjs +219 -52
- package/api/gap-report/gap-report.test.mjs +233 -0
- package/api/gap-report/gap-report.type.d.mts +41 -0
- package/api/gap-report/gap-report.type.mjs +18 -0
- package/api/hook/_adapter.mjs +3 -11
- package/api/hook/hook.doc.mjs +4 -0
- package/api/hook/list/list.d.mts +1 -1
- package/api/index.d.mts +2 -0
- package/api/index.mjs +2 -0
- package/api/init/_adapter.d.mts +22 -0
- package/api/init/_adapter.mjs +59 -0
- package/api/init/init.d.mts +7 -5
- package/api/init/init.doc.mjs +28 -7
- package/api/init/init.mjs +28 -4
- package/api/init/init.type.d.mts +48 -3
- package/api/init/init.type.mjs +37 -3
- package/api/init/run/run.d.mts +1 -1
- package/api/init/run/run.mjs +17 -6
- package/api/init/user/user.d.mts +14 -0
- package/api/init/user/user.mjs +87 -0
- package/api/init/user/user.test.mjs +232 -0
- package/api/integration/_adapter.d.mts +45 -0
- package/api/integration/_adapter.mjs +112 -0
- package/api/integration/add-contribution.component-names.test.mjs +66 -0
- package/api/integration/add-contribution.mjs +8 -4
- package/api/integration/add-contribution.test.mjs +4 -2
- package/api/integration/authoring-checks.mjs +110 -6
- package/api/integration/authoring-checks.test.mjs +808 -0
- package/api/integration/authoring-checks.type.d.mts +143 -0
- package/api/integration/authoring-checks.type.mjs +74 -2
- package/api/integration/check/check.d.mts +96 -0
- package/api/integration/check/check.mjs +357 -0
- package/api/integration/check/check.test.mjs +489 -0
- package/api/integration/integration-check.type.d.mts +118 -0
- package/api/integration/integration-check.type.mjs +84 -0
- package/api/integration/integrationCheck.doc.d.mts +10 -0
- package/api/integration/integrationCheck.doc.mjs +73 -0
- package/api/integration/integrationComponentConflicts.doc.mjs +45 -6
- package/api/integration/integrationDocConflicts.doc.mjs +22 -5
- package/api/integration/pack-check.mjs +364 -120
- package/api/integration/pack-check.test.mjs +730 -10
- package/api/integration/validate-integration-fixes.test.mjs +67 -0
- package/api/integration/validate-integration.d.mts +8 -0
- package/api/integration/validate-integration.mjs +63 -9
- package/api/integration/validate-integration.test.mjs +88 -8
- package/api/integration/validate-integration.type.d.mts +16 -0
- package/api/integration/validate-integration.type.mjs +14 -1
- package/api/integration/validate-unread-theme-folders.test.mjs +3 -2
- package/api/integration/validateIntegration.doc.mjs +19 -3
- package/api/search/_adapter.d.mts +11 -0
- package/api/search/_adapter.mjs +25 -0
- package/api/search/search.d.mts +82 -13
- package/api/search/search.doc.mjs +8 -3
- package/api/search/search.domain-priority.test.mjs +108 -18
- package/api/search/search.integration-check.test.mjs +24 -0
- package/api/search/search.mjs +645 -64
- package/api/search/search.test.mjs +179 -1
- package/api/search/search.type.d.mts +14 -1
- package/api/search/search.type.mjs +6 -1
- package/api/swizzle/_adapter.mjs +2 -2
- package/api/swizzle/copy/copy.mjs +29 -15
- package/api/template/template-integration.test.mjs +1 -1
- package/api/template/template.test.mjs +120 -3
- package/api/theme/_adapter.d.mts +16 -0
- package/api/theme/_adapter.mjs +32 -5
- package/api/theme/build/build.d.mts +2 -1
- package/api/theme/build/build.family.test.mjs +64 -0
- package/api/theme/build/build.mjs +250 -38
- package/api/theme/build/build.packed-old-core.test.mjs +20 -3
- package/api/theme/build/font-warning.mjs +5 -3
- package/api/theme/build/font-warning.test.mjs +2 -1
- package/api/theme/remove/remove.test.mjs +2 -2
- package/api/theme/targets/targets.mjs +3 -10
- package/api/theme/themeBuild.doc.mjs +4 -4
- package/api/theme/themeTargets.doc.mjs +4 -0
- package/api/theme/use/use.test.mjs +1 -1
- package/api/upgrade/_adapter.d.mts +40 -2
- package/api/upgrade/_adapter.mjs +118 -5
- package/api/upgrade/run/cli-behind-core.test.mjs +438 -0
- package/api/upgrade/run/run.mjs +35 -2
- package/api/upgrade/status/status.d.mts +21 -5
- package/api/upgrade/status/status.mjs +45 -8
- package/api/upgrade/upgrade.doc.mjs +6 -3
- package/api/upgrade/upgrade.mjs +5 -1
- package/api/upgrade/upgrade.type.d.mts +23 -0
- package/api/upgrade/upgrade.type.mjs +16 -1
- package/assets/codemods/__tests__/registry.test.mjs +1 -0
- package/assets/codemods/registry.mjs +1 -0
- package/assets/codemods/runner.mjs +7 -1
- package/assets/codemods/transforms/v0.7.2/__tests__/migrate-list-edge-compensation-to-edge.test.mjs +120 -0
- package/assets/codemods/transforms/v0.7.2/index.mjs +20 -0
- package/assets/codemods/transforms/v0.7.2/migrate-list-edge-compensation-to-edge.mjs +198 -0
- package/assets/discover/official-packages.json +367 -0
- package/assets/docs/README.md +10 -0
- package/assets/docs/author-a-theme.doc.mjs +3 -3
- package/assets/docs/browser-support.doc.mjs +1 -1
- package/assets/docs/getting-started.doc.mjs +26 -6
- package/assets/docs/styling-overview.doc.mjs +1 -1
- package/assets/docs/theme.doc.dense.mjs +1 -1
- package/assets/docs/theme.doc.mjs +2 -2
- package/assets/docs/theme.doc.zh.mjs +1 -1
- package/assets/docs/tree/add-a-component.doc.mjs +22 -2
- package/assets/docs/tree/add-a-theme.doc.mjs +13 -3
- package/assets/docs/tree/add-a-topic.doc.mjs +54 -9
- package/assets/docs/tree/agent-guidance.doc.mjs +19 -5
- package/assets/docs/tree/block-template.doc.mjs +8 -20
- package/assets/docs/tree/build-the-template.doc.mjs +1 -1
- package/assets/docs/tree/building-blocks.doc.mjs +4 -0
- package/assets/docs/tree/check-the-props.doc.mjs +201 -0
- package/assets/docs/tree/check-your-docs.doc.mjs +69 -11
- package/assets/docs/tree/checks.doc.mjs +32 -24
- package/assets/docs/tree/ci-and-containers.doc.mjs +88 -0
- package/assets/docs/tree/cli-command.doc.mjs +142 -0
- package/assets/docs/tree/cli.doc.mjs +6 -0
- package/assets/docs/tree/codemods.doc.mjs +17 -7
- package/assets/docs/tree/commands.doc.mjs +7 -1
- package/assets/docs/tree/component-family.doc.mjs +8 -6
- package/assets/docs/tree/component-imports.doc.mjs +21 -3
- package/assets/docs/tree/components.doc.mjs +7 -1
- package/assets/docs/tree/computer-agent-guide.doc.mjs +160 -0
- package/assets/docs/tree/computer-integrations.doc.mjs +93 -0
- package/assets/docs/tree/configuration.doc.mjs +7 -3
- package/assets/docs/tree/debug-and-gap-reports.doc.mjs +41 -22
- package/assets/docs/tree/define-the-theme.doc.mjs +6 -5
- package/assets/docs/tree/describe-the-component.doc.mjs +3 -3
- package/assets/docs/tree/docs.doc.mjs +9 -3
- package/assets/docs/tree/document-the-template.doc.mjs +1 -1
- package/assets/docs/tree/document-the-theme.doc.mjs +3 -3
- package/assets/docs/tree/export-template-assets.doc.mjs +1 -1
- package/assets/docs/tree/extend-or-replace.doc.mjs +19 -9
- package/assets/docs/tree/fonts-and-assets.doc.mjs +2 -2
- package/assets/docs/tree/generate-a-palette.doc.mjs +7 -5
- package/assets/docs/tree/global-integrations.doc.mjs +124 -0
- package/assets/docs/tree/global.doc.mjs +131 -0
- package/assets/docs/tree/grade-template-with-agent.doc.mjs +5 -5
- package/assets/docs/tree/install-once.doc.mjs +105 -0
- package/assets/docs/tree/integrations.doc.mjs +13 -1
- package/assets/docs/tree/layout-spacing.doc.mjs +2 -3
- package/assets/docs/tree/layout.doc.mjs +6 -6
- package/assets/docs/tree/links.doc.mjs +7 -6
- package/assets/docs/tree/migration-setup.doc.mjs +3 -2
- package/assets/docs/tree/migration-verification.doc.mjs +0 -1
- package/assets/docs/tree/migration.doc.mjs +0 -1
- package/assets/docs/tree/monorepos.doc.mjs +84 -0
- package/assets/docs/tree/package-and-test.doc.mjs +1 -1
- package/assets/docs/tree/page-template.doc.mjs +4 -8
- package/assets/docs/tree/problems.doc.mjs +205 -0
- package/assets/docs/tree/project-global-or-both.doc.mjs +131 -0
- package/assets/docs/tree/publishing.doc.mjs +6 -6
- package/assets/docs/tree/quick-start.doc.mjs +53 -27
- package/assets/docs/tree/reference.doc.mjs +192 -0
- package/assets/docs/tree/replace-a-core-component.doc.mjs +15 -7
- package/assets/docs/tree/replace-a-core-template.doc.mjs +10 -12
- package/assets/docs/tree/scaffold.doc.mjs +1 -1
- package/assets/docs/tree/sections-and-placement.doc.mjs +9 -11
- package/assets/docs/tree/see-it-in-an-app.doc.mjs +17 -5
- package/assets/docs/tree/short-and-findable.doc.mjs +9 -8
- package/assets/docs/tree/single-component.doc.mjs +15 -6
- package/assets/docs/tree/start-a-template.doc.mjs +18 -8
- package/assets/docs/tree/subcomponent.doc.mjs +6 -6
- package/assets/docs/tree/template-assets.doc.mjs +2 -2
- package/assets/docs/tree/template-doc-overview.doc.mjs +6 -17
- package/assets/docs/tree/template-fonts.doc.mjs +1 -1
- package/assets/docs/tree/template-icons.doc.mjs +1 -1
- package/assets/docs/tree/template-images-media.doc.mjs +1 -1
- package/assets/docs/tree/template-styles.doc.mjs +2 -2
- package/assets/docs/tree/templates.doc.mjs +7 -1
- package/assets/docs/tree/test-in-an-app.doc.mjs +7 -7
- package/assets/docs/tree/test-template-in-app.doc.mjs +5 -5
- package/assets/docs/tree/themes.doc.mjs +4 -0
- package/assets/docs/tree/tokens-and-setup.doc.mjs +19 -15
- package/assets/docs/tree/troubleshooting.doc.mjs +29 -13
- package/assets/docs/tree/type-scale.doc.mjs +3 -3
- package/assets/docs/tree/uninstall.doc.mjs +109 -0
- package/assets/docs/tree/updates.doc.mjs +92 -0
- package/assets/docs/tree/upgrading.doc.mjs +6 -6
- package/assets/docs/tree/use-a-theme-in-an-app.doc.mjs +14 -2
- package/assets/docs/tree/verify-packed-template.doc.mjs +3 -3
- package/assets/docs/tree/versioning.doc.mjs +10 -9
- package/assets/docs/tree/who-answers.doc.mjs +119 -0
- package/assets/docs/tree/write-the-template-file.doc.mjs +7 -6
- package/assets/docs/use-a-theme.doc.mjs +2 -2
- package/assets/docs/working-with-ai.doc.mjs +66 -13
- package/assets/theme.template.ts +1 -1
- package/authoring/codemod/codemod.doc.mjs +7 -3
- package/authoring/config/config.doc.mjs +9 -6
- package/authoring/config/type.ts +4 -2
- package/authoring/debug/parse.d.mts +5 -5
- package/authoring/discover/discover.doc.mjs +7 -1
- package/authoring/doctypes/_schema.d.mts +8 -3
- package/authoring/doctypes/_schema.mjs +1 -0
- package/authoring/doctypes/base/graph-fields.doc.mjs +6 -4
- package/authoring/doctypes/command/command.doc.mjs +20 -12
- package/authoring/doctypes/command/type.ts +14 -0
- package/authoring/doctypes/component/component.doc.mjs +30 -27
- package/authoring/doctypes/component/type.ts +21 -8
- package/authoring/doctypes/enum/enum.doc.mjs +7 -4
- package/authoring/doctypes/function/function.doc.mjs +9 -8
- package/authoring/doctypes/hook/hook.doc.mjs +5 -4
- package/authoring/doctypes/hook/type.ts +4 -0
- package/authoring/doctypes/namespace/namespace.doc.mjs +7 -6
- package/authoring/doctypes/reference/reference.doc.mjs +12 -11
- package/authoring/doctypes/schema/schema.doc.mjs +9 -9
- package/authoring/doctypes/template/integration-template.doc.d.mts +11 -0
- package/authoring/doctypes/template/integration-template.doc.mjs +49 -0
- package/authoring/doctypes/template/parse.d.mts +6 -2
- package/authoring/doctypes/template/parse.mjs +3 -1
- package/authoring/doctypes/template/template.doc.mjs +3 -3
- package/authoring/doctypes/template/type.ts +22 -0
- package/authoring/doctypes/theme/theme.doc.mjs +2 -2
- package/authoring/gap-report/gap-report.doc.mjs +2 -2
- package/authoring/identity/identity.doc.mjs +3 -3
- package/authoring/index.d.ts +2 -0
- package/authoring/integration/integration.doc.mjs +30 -6
- package/authoring/integration/parse.test.mjs +21 -0
- package/authoring/integration/schema.d.mts +16 -3
- package/authoring/integration/schema.mjs +34 -2
- package/authoring/integration/type.ts +12 -0
- package/clients/cli/bin/astryx.mjs +20 -3
- package/clients/cli/cli-command.test.mjs +166 -0
- package/clients/cli/commands/blog.doc.mjs +1 -0
- package/clients/cli/commands/build-theme.batch-report.test.mjs +17 -3
- package/clients/cli/commands/build-theme.font-warning.test.mjs +3 -3
- package/clients/cli/commands/build-theme.mjs +26 -13
- package/clients/cli/commands/build-theme.path-safety.test.mjs +224 -6
- package/clients/cli/commands/build-theme.registry.test.mjs +5 -2
- package/clients/cli/commands/build.doc.mjs +1 -0
- package/clients/cli/commands/build.exit-codes-doc.test.mjs +4 -0
- package/clients/cli/commands/cli-postinstall.test.mjs +49 -1
- package/clients/cli/commands/component.doc.mjs +1 -0
- package/clients/cli/commands/discover.broken-integration.test.mjs +11 -7
- package/clients/cli/commands/discover.doc.mjs +9 -1
- package/clients/cli/commands/discover.mjs +144 -93
- package/clients/cli/commands/discover.no-source.test.mjs +448 -33
- package/clients/cli/commands/discover.sources.test.mjs +20 -1
- package/clients/cli/commands/docs.doc.mjs +1 -0
- package/clients/cli/commands/docs.mjs +49 -19
- package/clients/cli/commands/docs.test.mjs +2 -2
- package/clients/cli/commands/doctor-integration-components.doc.mjs +19 -4
- package/clients/cli/commands/doctor-integration-docs.doc.mjs +20 -5
- package/clients/cli/commands/doctor-integration-templates.doc.mjs +1 -0
- package/clients/cli/commands/doctor-integration-validate.doc.mjs +22 -2
- package/clients/cli/commands/doctor-integration.test.mjs +888 -3
- package/clients/cli/commands/doctor.doc.mjs +12 -2
- package/clients/cli/commands/doctor.mjs +292 -7
- package/clients/cli/commands/doctor.test.mjs +10 -4
- package/clients/cli/commands/gap-report.doc.mjs +15 -2
- package/clients/cli/commands/gap-report.mjs +24 -2
- package/clients/cli/commands/gap-report.test.mjs +79 -0
- package/clients/cli/commands/hook.doc.mjs +1 -0
- package/clients/cli/commands/init.behavior.test.mjs +5 -0
- package/clients/cli/commands/init.doc.mjs +29 -3
- package/clients/cli/commands/integration-add.doc.mjs +7 -0
- package/clients/cli/commands/integration-authoring.test.mjs +49 -3
- package/clients/cli/commands/integration-check.doc.mjs +93 -0
- package/clients/cli/commands/integration-check.test.mjs +441 -0
- package/clients/cli/commands/integration-pack.doc.mjs +8 -1
- package/clients/cli/commands/integration-verify.doc.mjs +8 -1
- package/clients/cli/commands/integration.doc.mjs +6 -2
- package/clients/cli/commands/integration.mjs +119 -7
- package/clients/cli/commands/json-contract.test.mjs +11 -2
- package/clients/cli/commands/manifest.doc.mjs +1 -0
- package/clients/cli/commands/outside-project.test.mjs +774 -0
- package/clients/cli/commands/search.doc.mjs +1 -0
- package/clients/cli/commands/search.mjs +16 -11
- package/clients/cli/commands/search.test.mjs +429 -296
- package/clients/cli/commands/setup-nudge.test.mjs +102 -2
- package/clients/cli/commands/swizzle.doc.mjs +7 -0
- package/clients/cli/commands/swizzle.mjs +5 -3
- package/clients/cli/commands/swizzle.routing.test.mjs +19 -2
- package/clients/cli/commands/template.doc.mjs +1 -0
- package/clients/cli/commands/text-json-parity.test.mjs +5 -0
- package/clients/cli/commands/theme-add-lifecycle.test.mjs +3 -3
- package/clients/cli/commands/theme-add.doc.mjs +8 -1
- package/clients/cli/commands/theme-build.doc.mjs +3 -2
- package/clients/cli/commands/theme-eject.doc.mjs +1 -0
- package/clients/cli/commands/theme-list.behavior.test.mjs +6 -0
- package/clients/cli/commands/theme-list.doc.mjs +1 -0
- package/clients/cli/commands/theme-palette-generate.doc.mjs +1 -0
- package/clients/cli/commands/theme-remove.doc.mjs +7 -0
- package/clients/cli/commands/theme-targets.doc.mjs +1 -0
- package/clients/cli/commands/theme-template.doc.mjs +1 -0
- package/clients/cli/commands/theme-use.doc.mjs +7 -0
- package/clients/cli/commands/upgrade.config-ordering.test.mjs +2 -1
- package/clients/cli/commands/upgrade.doc.mjs +22 -1
- package/clients/cli/commands/upgrade.file-protection.test.mjs +3 -2
- package/clients/cli/commands/upgrade.hook-output.test.mjs +2 -1
- package/clients/cli/commands/upgrade.older-cli.test.mjs +160 -0
- package/clients/cli/index.mjs +112 -16
- package/clients/cli/lib/cli-error.mjs +4 -1
- package/clients/cli/lib/component-format.test.mjs +1 -1
- package/clients/cli/lib/define-command.mjs +2 -2
- package/clients/cli/lib/json-shim.mjs +3 -1
- package/clients/cli/lib/manifest.d.ts +9 -0
- package/clients/cli/lib/manifest.mjs +17 -1
- package/clients/cli/lib/manifest.test.mjs +25 -0
- package/foundation/agent-docs/agent-doc-state.d.mts +35 -6
- package/foundation/agent-docs/agent-doc-state.mjs +66 -6
- package/foundation/agent-docs/agent-docs.d.mts +4 -3
- package/foundation/agent-docs/agent-docs.mjs +11 -9
- package/foundation/agent-docs/computer-agent-text.d.mts +133 -0
- package/foundation/agent-docs/computer-agent-text.mjs +623 -0
- package/foundation/agent-docs/computer-agent-text.test.mjs +602 -0
- package/foundation/config/project.d.mts +35 -3
- package/foundation/config/project.mjs +226 -7
- package/foundation/config/project.test.mjs +66 -0
- package/foundation/config/theme-state.mjs +5 -4
- package/foundation/discovery/authoring-self-docs.mjs +2 -1
- package/foundation/discovery/cli-self-docs.mjs +20 -3
- package/foundation/discovery/cli-self-docs.test.mjs +3 -2
- package/foundation/discovery/component-discovery.d.mts +190 -10
- package/foundation/discovery/component-discovery.export-names.test.mjs +760 -0
- package/foundation/discovery/component-discovery.mjs +864 -56
- package/foundation/discovery/component-discovery.test.mjs +96 -0
- package/foundation/discovery/component-replacement.mjs +20 -1
- package/foundation/discovery/component-replacement.test.mjs +40 -0
- package/foundation/discovery/copied-passages.d.mts +216 -0
- package/foundation/discovery/copied-passages.mjs +720 -0
- package/foundation/discovery/copied-passages.test.mjs +124 -0
- package/foundation/discovery/doc-consistency.d.mts +34 -0
- package/foundation/discovery/doc-consistency.mjs +513 -0
- package/foundation/discovery/doc-consistency.test.mjs +347 -0
- package/foundation/discovery/doc-fluff.d.mts +112 -0
- package/foundation/discovery/doc-fluff.mjs +328 -0
- package/foundation/discovery/doc-fluff.test.mjs +142 -0
- package/foundation/discovery/doc-types.d.mts +157 -0
- package/foundation/discovery/doc-types.mjs +1231 -0
- package/foundation/discovery/doc-types.test.mjs +744 -0
- package/foundation/discovery/docs-discovery.d.mts +88 -0
- package/foundation/discovery/docs-discovery.mjs +83 -2
- package/foundation/discovery/integration-doc-files.d.mts +22 -0
- package/foundation/discovery/integration-doc-files.mjs +231 -0
- package/foundation/discovery/integration-doc-files.test.mjs +246 -0
- package/foundation/discovery/module-exports.d.mts +27 -0
- package/foundation/discovery/module-exports.mjs +356 -31
- package/foundation/discovery/module-exports.test.mjs +172 -0
- package/foundation/discovery/package-tsconfig.d.mts +14 -0
- package/foundation/discovery/package-tsconfig.mjs +228 -0
- package/foundation/discovery/package-tsconfig.test.mjs +210 -0
- package/foundation/discovery/project-typescript.d.mts +32 -0
- package/foundation/discovery/project-typescript.mjs +89 -0
- package/foundation/discovery/prop-drift.d.mts +297 -0
- package/foundation/discovery/prop-drift.mjs +2428 -0
- package/foundation/discovery/prop-drift.test.mjs +2337 -0
- package/foundation/discovery/runner-allowlist.d.mts +40 -0
- package/foundation/discovery/runner-allowlist.mjs +53 -0
- package/foundation/discovery/stray-pointers.d.mts +52 -0
- package/foundation/discovery/stray-pointers.mjs +293 -0
- package/foundation/discovery/stray-pointers.test.mjs +86 -0
- package/foundation/discovery/template-adapter.mjs +74 -5
- package/foundation/discovery/template-needs.mjs +5 -2
- package/foundation/discovery/theme-imports.mjs +8 -4
- package/foundation/discovery/theme-imports.test.mjs +1 -1
- package/foundation/discovery/type-match.d.mts +53 -0
- package/foundation/discovery/type-match.mjs +660 -0
- package/foundation/discovery/type-match.test.mjs +169 -0
- package/foundation/discovery/type-text.d.mts +68 -0
- package/foundation/discovery/type-text.mjs +658 -0
- package/foundation/discovery/type-text.test.mjs +196 -0
- package/foundation/discovery/unresolved-references.d.mts +62 -0
- package/foundation/discovery/unresolved-references.mjs +790 -0
- package/foundation/discovery/unresolved-references.test.mjs +567 -0
- package/foundation/doc-compiler/doc-loads.test.mjs +51 -1
- package/foundation/doc-compiler/inputs.mjs +27 -1
- package/foundation/doc-compiler/inputs.test.mjs +0 -1
- package/foundation/doc-compiler/links.d.mts +41 -5
- package/foundation/doc-compiler/links.mjs +167 -28
- package/foundation/doc-compiler/links.test.mjs +97 -4
- package/foundation/doc-compiler/read.d.mts +1 -1
- package/foundation/doc-compiler/tree.mjs +30 -1
- package/foundation/doc-compiler/tree.test.mjs +8 -1
- package/foundation/env/cli-command.d.mts +83 -0
- package/foundation/env/cli-command.mjs +152 -0
- package/foundation/env/cli-command.test.mjs +129 -0
- package/foundation/env/node-version.test.mjs +15 -3
- package/foundation/env/package-manager.d.mts +93 -9
- package/foundation/env/package-manager.global.test.mjs +66 -0
- package/foundation/env/package-manager.mjs +184 -13
- package/foundation/env/package-manager.test.mjs +341 -15
- package/foundation/env/project-scope.d.mts +9 -0
- package/foundation/env/project-scope.mjs +33 -0
- package/foundation/env/search-path.d.mts +42 -0
- package/foundation/env/search-path.mjs +205 -0
- package/foundation/env/search-path.test.mjs +122 -0
- package/foundation/env/user-dirs.d.mts +39 -0
- package/foundation/env/user-dirs.mjs +93 -0
- package/foundation/env/user-dirs.test.mjs +72 -0
- package/foundation/env/user-settings.d.mts +46 -0
- package/foundation/env/user-settings.mjs +106 -0
- package/foundation/env/user-settings.test.mjs +64 -0
- package/foundation/fs/file-protection.mjs +15 -1
- package/foundation/fs/module-loader.d.mts +2 -1
- package/foundation/fs/module-loader.mjs +60 -4
- package/foundation/fs/module-loader.stdout.test.mjs +3 -2
- package/foundation/fs/module-loader.test.mjs +194 -0
- package/foundation/fs/path-compare.d.mts +33 -0
- package/foundation/fs/path-compare.mjs +73 -0
- package/foundation/fs/paths.d.mts +57 -1
- package/foundation/fs/paths.mjs +131 -3
- package/foundation/fs/paths.test.mjs +10 -1
- package/foundation/integrations/computer-integrations.d.mts +78 -0
- package/foundation/integrations/computer-integrations.mjs +316 -0
- package/foundation/integrations/computer-integrations.test.mjs +292 -0
- package/foundation/integrations/contribution-inventory.d.mts +11 -0
- package/foundation/integrations/contribution-inventory.mjs +56 -3
- package/foundation/integrations/integration-warnings.mjs +3 -2
- package/foundation/integrations/integration-warnings.test.mjs +8 -9
- package/foundation/integrations/integrations.d.mts +25 -1
- package/foundation/integrations/integrations.mjs +46 -3
- package/foundation/integrations/issue.ts +6 -0
- package/foundation/integrations/validate-contributions.d.mts +2 -0
- package/foundation/integrations/validate-contributions.mjs +41 -1
- package/foundation/release/agent-text-worker.d.mts +4 -0
- package/foundation/release/agent-text-worker.mjs +52 -0
- package/foundation/release/cache.d.mts +310 -0
- package/foundation/release/cache.mjs +1216 -0
- package/foundation/release/cache.test.mjs +920 -0
- package/foundation/release/choose.d.mts +207 -0
- package/foundation/release/choose.mjs +677 -0
- package/foundation/release/choose.test.mjs +427 -0
- package/foundation/release/core-worker.d.mts +4 -0
- package/foundation/release/core-worker.mjs +38 -0
- package/foundation/release/global-state.d.mts +259 -0
- package/foundation/release/global-state.mjs +472 -0
- package/foundation/release/global-state.test.mjs +381 -0
- package/foundation/release/handoff.d.mts +60 -0
- package/foundation/release/handoff.e2e.test.mjs +278 -0
- package/foundation/release/handoff.mjs +357 -0
- package/foundation/release/lock-lease.d.mts +23 -0
- package/foundation/release/lock-lease.mjs +80 -0
- package/foundation/release/notices.d.mts +253 -0
- package/foundation/release/notices.mjs +596 -0
- package/foundation/release/notices.test.mjs +565 -0
- package/foundation/release/npm-guard.d.mts +4 -0
- package/foundation/release/npm-guard.mjs +126 -0
- package/foundation/release/project.d.mts +141 -0
- package/foundation/release/project.mjs +466 -0
- package/foundation/release/project.test.mjs +288 -0
- package/foundation/release/refresh-worker.d.mts +4 -0
- package/foundation/release/refresh-worker.mjs +27 -0
- package/foundation/release/run-context.d.mts +47 -0
- package/foundation/release/run-context.mjs +149 -0
- package/foundation/release/update-notice-env.d.mts +28 -0
- package/foundation/release/update-notice-env.mjs +39 -0
- package/foundation/response/base.d.ts +26 -3
- package/foundation/response/error-codes.d.mts +3 -1
- package/foundation/response/error-codes.doc.mjs +12 -0
- package/foundation/response/error-codes.mjs +17 -0
- package/foundation/response/error-codes.test.mjs +2 -0
- package/foundation/response/json-contract.test.mjs +7 -2
- package/foundation/response/json.mjs +4 -1
- package/foundation/response/response-types.doc.mjs +22 -11
- package/foundation/response/response-types.doc.test.mjs +46 -0
- package/foundation/response/response.doc.mjs +3 -3
- package/foundation/xle/browser-imports.test.mjs +74 -0
- package/foundation/xle/registry.mjs +4 -0
- package/foundation/xle/registry.test.mjs +28 -0
- package/package.json +11 -11
- package/scripts/postinstall.mjs +24 -5
|
@@ -0,0 +1,472 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file The per-user update state, and the background check that keeps it
|
|
5
|
+
* current (spec AST-081 FR6).
|
|
6
|
+
*
|
|
7
|
+
* The CLI never installs a newer release for the computer; it tells its user
|
|
8
|
+
* one exists, the way `gh` and the Vercel CLI do (notices.mjs). At most once a
|
|
9
|
+
* day, never in the first day after the first run, a run starts a detached
|
|
10
|
+
* check of the release the registry tags `latest`; no run waits for it. No
|
|
11
|
+
* check starts when the standard `CI` variable is set, or when
|
|
12
|
+
* `NO_UPDATE_NOTIFIER` is (update-notice-env.mjs).
|
|
13
|
+
*
|
|
14
|
+
* <user config>/astryx/state.json
|
|
15
|
+
* firstRunAt when a run first kept this state (no check before a day)
|
|
16
|
+
* checkedAt when the last check started
|
|
17
|
+
* checkOkAt when a check last reached the registry
|
|
18
|
+
* latest the version `latest` named then
|
|
19
|
+
* latestNode the Node range that release declares, or null
|
|
20
|
+
* agentText the computer-level agent text: {writtenBy, attemptFor,
|
|
21
|
+
* attemptAt}, the release that last wrote it and the last
|
|
22
|
+
* background attempt (spec AST-081 FR8)
|
|
23
|
+
* notifiedAt when each update notice last printed (notices.mjs)
|
|
24
|
+
*
|
|
25
|
+
* @input the clock, the registry's `latest` tag (in the worker)
|
|
26
|
+
* @output the newest release known, for notices and doctor
|
|
27
|
+
* @position foundation/release — read by the bin and doctor; the check runs
|
|
28
|
+
* in refresh-worker.mjs.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
import * as fs from 'node:fs';
|
|
32
|
+
import * as path from 'node:path';
|
|
33
|
+
import {spawn} from 'node:child_process';
|
|
34
|
+
import {fileURLToPath} from 'node:url';
|
|
35
|
+
import {
|
|
36
|
+
cachedRelease,
|
|
37
|
+
isReleaseVersion,
|
|
38
|
+
recentFailedInstall,
|
|
39
|
+
releasesDir,
|
|
40
|
+
resolveLatestRelease,
|
|
41
|
+
tryLock,
|
|
42
|
+
} from './cache.mjs';
|
|
43
|
+
import {readJson} from './project.mjs';
|
|
44
|
+
import {userConfigDir} from '../env/user-dirs.mjs';
|
|
45
|
+
import {computerAgentTextSettings} from '../env/user-settings.mjs';
|
|
46
|
+
import {isCi, updateNoticesOff} from './update-notice-env.mjs';
|
|
47
|
+
|
|
48
|
+
/** How often a check may start: once a day, as `gh` and update-notifier do. */
|
|
49
|
+
export const CHECK_INTERVAL_MS = 24 * 60 * 60_000;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* @typedef {object} GlobalState
|
|
53
|
+
* @property {number} [firstRunAt]
|
|
54
|
+
* @property {number} [checkedAt]
|
|
55
|
+
* @property {number} [checkOkAt]
|
|
56
|
+
* @property {string} [latest]
|
|
57
|
+
* @property {string | null} [latestNode]
|
|
58
|
+
* @property {{at: number, reason: string}} [checkFailed] why the last check
|
|
59
|
+
* did not reach the registry, for diagnosis only (`astryx doctor`); cleared
|
|
60
|
+
* by a check that does. Not part of any contract.
|
|
61
|
+
* @property {{writtenBy?: string, attemptFor?: string, attemptAt?: number}} [agentText]
|
|
62
|
+
* @property {Record<string, number>} [notifiedAt] when each update notice
|
|
63
|
+
* last printed (notices.mjs)
|
|
64
|
+
* @property {Record<string, NoticeSkip>} [noticeSkips] why each update notice
|
|
65
|
+
* last did not print, for diagnosis only: `astryx doctor` shows the newest.
|
|
66
|
+
* Not part of any contract; its shape may change in any release.
|
|
67
|
+
*/
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Why an update notice did not print: `already-shown` (it printed within the
|
|
71
|
+
* day) or `no-newer` (nothing newer is known). Recorded only while the run
|
|
72
|
+
* holds the state file's lock.
|
|
73
|
+
* @typedef {{reason: 'already-shown' | 'no-newer', at: number}} NoticeSkip
|
|
74
|
+
*/
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* The state file.
|
|
78
|
+
* @param {string} [stateDir] the per-user configuration folder
|
|
79
|
+
* @returns {string}
|
|
80
|
+
*/
|
|
81
|
+
export function stateFile(stateDir = userConfigDir()) {
|
|
82
|
+
return path.join(stateDir, 'state.json');
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* The saved state; `{}` when there is none or it cannot be read.
|
|
87
|
+
* @param {string} [stateDir]
|
|
88
|
+
* @returns {GlobalState}
|
|
89
|
+
*/
|
|
90
|
+
export function readGlobalState(stateDir = userConfigDir()) {
|
|
91
|
+
const state = readJson(stateFile(stateDir));
|
|
92
|
+
return state && typeof state === 'object' && !Array.isArray(state)
|
|
93
|
+
? state
|
|
94
|
+
: {};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** How long a run waits for another run's change to the state file. */
|
|
98
|
+
const STATE_LOCK_WAIT_MS = 2000;
|
|
99
|
+
|
|
100
|
+
/** Sleep the thread without spinning. @param {number} ms */
|
|
101
|
+
function sleep(ms) {
|
|
102
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Run `change` while holding the state file's lock, so runs that finish at
|
|
107
|
+
* the same moment change the state one at a time: each reads what the one
|
|
108
|
+
* before it wrote. Returns `change`'s result, or `undefined` when the lock
|
|
109
|
+
* cannot be taken in time or the folder cannot be written, in which case
|
|
110
|
+
* nothing changes.
|
|
111
|
+
* @template T
|
|
112
|
+
* @param {string} stateDir
|
|
113
|
+
* @param {() => T} change
|
|
114
|
+
* @returns {T | undefined}
|
|
115
|
+
*/
|
|
116
|
+
export function withStateLock(stateDir, change) {
|
|
117
|
+
const outcome = tryStateLock(stateDir, change);
|
|
118
|
+
return outcome.ran ? outcome.value : undefined;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Who holds the state file's lock now, read from its owner record, for
|
|
123
|
+
* diagnosis: null when it is free. `since` is when the lock folder was made.
|
|
124
|
+
* @param {string} [stateDir]
|
|
125
|
+
* @returns {{pid: number | null, host: string | null, since: number} | null}
|
|
126
|
+
*/
|
|
127
|
+
export function stateLockHolder(stateDir = userConfigDir()) {
|
|
128
|
+
const lockDir = path.join(stateDir, '.lock-state');
|
|
129
|
+
try {
|
|
130
|
+
const since = fs.statSync(lockDir).mtimeMs;
|
|
131
|
+
const owner = readJson(path.join(lockDir, 'owner.json'));
|
|
132
|
+
return {
|
|
133
|
+
pid: Number.isInteger(owner?.pid) ? owner.pid : null,
|
|
134
|
+
host: typeof owner?.host === 'string' ? owner.host : null,
|
|
135
|
+
since,
|
|
136
|
+
};
|
|
137
|
+
} catch {
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* {@link withStateLock}, saying why `change` did not run: the lock stayed
|
|
144
|
+
* taken past the wait (`lock-timeout`), or the folder cannot hold it
|
|
145
|
+
* (`state-unwritable`).
|
|
146
|
+
* @template T
|
|
147
|
+
* @param {string} stateDir
|
|
148
|
+
* @param {() => T} change
|
|
149
|
+
* @returns {{ran: true, value: T} | {ran: false, reason: 'lock-timeout' | 'state-unwritable'}}
|
|
150
|
+
*/
|
|
151
|
+
export function tryStateLock(stateDir, change) {
|
|
152
|
+
const lockDir = path.join(stateDir, '.lock-state');
|
|
153
|
+
const deadline = Date.now() + STATE_LOCK_WAIT_MS;
|
|
154
|
+
try {
|
|
155
|
+
while (!tryLock(lockDir)) {
|
|
156
|
+
if (Date.now() > deadline) return {ran: false, reason: 'lock-timeout'};
|
|
157
|
+
sleep(10);
|
|
158
|
+
}
|
|
159
|
+
} catch {
|
|
160
|
+
return {ran: false, reason: 'state-unwritable'};
|
|
161
|
+
}
|
|
162
|
+
try {
|
|
163
|
+
return {ran: true, value: change()};
|
|
164
|
+
} finally {
|
|
165
|
+
fs.rmSync(lockDir, {recursive: true, force: true});
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Write the whole state, atomically. Call only while holding the lock.
|
|
171
|
+
* @param {GlobalState} state
|
|
172
|
+
* @param {string} stateDir
|
|
173
|
+
* @returns {boolean} whether it was written
|
|
174
|
+
*/
|
|
175
|
+
export function writeGlobalState(state, stateDir) {
|
|
176
|
+
const file = stateFile(stateDir);
|
|
177
|
+
try {
|
|
178
|
+
const tmp = `${file}.${process.pid}.tmp`;
|
|
179
|
+
fs.writeFileSync(tmp, `${JSON.stringify(state, null, 2)}\n`);
|
|
180
|
+
fs.renameSync(tmp, file);
|
|
181
|
+
return true;
|
|
182
|
+
} catch {
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Merge `patch` into the saved state under the lock. An unwritable folder
|
|
189
|
+
* never fails a run; the state is simply not kept.
|
|
190
|
+
* @param {Partial<GlobalState>} patch
|
|
191
|
+
* @param {string} [stateDir]
|
|
192
|
+
* @returns {GlobalState}
|
|
193
|
+
*/
|
|
194
|
+
export function updateGlobalState(patch, stateDir = userConfigDir()) {
|
|
195
|
+
try {
|
|
196
|
+
fs.mkdirSync(stateDir, {recursive: true});
|
|
197
|
+
} catch {
|
|
198
|
+
// Unwritable: nothing is kept.
|
|
199
|
+
}
|
|
200
|
+
return (
|
|
201
|
+
withStateLock(stateDir, () => {
|
|
202
|
+
const next = {...readGlobalState(stateDir), ...patch};
|
|
203
|
+
writeGlobalState(next, stateDir);
|
|
204
|
+
return next;
|
|
205
|
+
}) ?? {...readGlobalState(stateDir), ...patch}
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* The newest release the last check found, and the Node range it declares;
|
|
211
|
+
* null when no check has reached the registry.
|
|
212
|
+
* @param {string} [stateDir]
|
|
213
|
+
* @returns {{version: string, node: string | null} | null}
|
|
214
|
+
*/
|
|
215
|
+
export function knownLatest(stateDir = userConfigDir()) {
|
|
216
|
+
const state = readGlobalState(stateDir);
|
|
217
|
+
if (typeof state.checkOkAt !== 'number' || !isReleaseVersion(state.latest)) {
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
return {
|
|
221
|
+
version: state.latest,
|
|
222
|
+
node: typeof state.latestNode === 'string' ? state.latestNode : null,
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* The version of the newest release known, or null.
|
|
228
|
+
* @param {string} [stateDir]
|
|
229
|
+
* @returns {string | null}
|
|
230
|
+
*/
|
|
231
|
+
export function knownLatestRelease(stateDir = userConfigDir()) {
|
|
232
|
+
return knownLatest(stateDir)?.version ?? null;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Record the release that last wrote the computer-level agent text.
|
|
237
|
+
* @param {string | null} version
|
|
238
|
+
* @param {string} [stateDir]
|
|
239
|
+
*/
|
|
240
|
+
export function recordAgentTextWritten(version, stateDir = userConfigDir()) {
|
|
241
|
+
if (!isReleaseVersion(version)) return;
|
|
242
|
+
updateGlobalState({agentText: {writtenBy: version}}, stateDir);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/** A background attempt to write the agent text is retried after an hour. */
|
|
246
|
+
export const AGENT_TEXT_RETRY_MS = 60 * 60_000;
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* The global copy keeps the computer-level agent text installed (spec
|
|
250
|
+
* AST-081 FR8): when the person has not turned it off and the running global
|
|
251
|
+
* version has not written it yet, as after the person upgraded the global
|
|
252
|
+
* copy, that release's own background step writes it, detached, so no command
|
|
253
|
+
* waits. Returns whether a step was started.
|
|
254
|
+
*
|
|
255
|
+
* @param {{
|
|
256
|
+
* release: {version: string, root: string},
|
|
257
|
+
* stateDir?: string,
|
|
258
|
+
* configDir?: string,
|
|
259
|
+
* now?: number,
|
|
260
|
+
* start?: (worker: string, stateDir: string) => void,
|
|
261
|
+
* }} options
|
|
262
|
+
* @returns {boolean}
|
|
263
|
+
*/
|
|
264
|
+
export function maybeKeepAgentText({
|
|
265
|
+
release,
|
|
266
|
+
stateDir = userConfigDir(),
|
|
267
|
+
configDir,
|
|
268
|
+
now = Date.now(),
|
|
269
|
+
start = startWorker,
|
|
270
|
+
}) {
|
|
271
|
+
if (!computerAgentTextSettings(configDir).install) return false;
|
|
272
|
+
const {agentText} = readGlobalState(stateDir);
|
|
273
|
+
if (agentText?.writtenBy === release.version) return false;
|
|
274
|
+
if (
|
|
275
|
+
agentText?.attemptFor === release.version &&
|
|
276
|
+
typeof agentText.attemptAt === 'number' &&
|
|
277
|
+
now - agentText.attemptAt < AGENT_TEXT_RETRY_MS
|
|
278
|
+
) {
|
|
279
|
+
return false;
|
|
280
|
+
}
|
|
281
|
+
const worker = path.join(
|
|
282
|
+
release.root,
|
|
283
|
+
'foundation',
|
|
284
|
+
'release',
|
|
285
|
+
'agent-text-worker.mjs',
|
|
286
|
+
);
|
|
287
|
+
// A release without the step predates it; it never writes the text.
|
|
288
|
+
if (!fs.existsSync(worker)) return false;
|
|
289
|
+
updateGlobalState(
|
|
290
|
+
{agentText: {...agentText, attemptFor: release.version, attemptAt: now}},
|
|
291
|
+
stateDir,
|
|
292
|
+
);
|
|
293
|
+
// An attempt that cannot be recorded would start again on every run.
|
|
294
|
+
if (readGlobalState(stateDir).agentText?.attemptAt !== now) return false;
|
|
295
|
+
start(worker, stateDir);
|
|
296
|
+
return true;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Start the background step that installs this release's Core into the
|
|
301
|
+
* per-user cache, so commands that read Core work offline outside a project
|
|
302
|
+
* after one online run (spec AST-081 FR3, FR6): when the global copy carries
|
|
303
|
+
* no Core beside it and none is cached for its release, no install of it is
|
|
304
|
+
* under way, no recent attempt failed (the release cache's backoff), and
|
|
305
|
+
* `CI` is not set. It never blocks a command, prints nothing, and a failure
|
|
306
|
+
* is retried by a later run's step. Returns whether it was started.
|
|
307
|
+
*
|
|
308
|
+
* Never on Windows: a detached child there inherits the caller's open handles,
|
|
309
|
+
* such as the pipes a tool or agent reads this run's output from, and the
|
|
310
|
+
* caller would wait for the download to end. A component read on Windows
|
|
311
|
+
* fetches the Core itself when it first needs it.
|
|
312
|
+
* @param {{release: {version: string, root: string}, cacheDir: string, env?: NodeJS.ProcessEnv, start?: typeof startWorker, platform?: NodeJS.Platform}} options
|
|
313
|
+
* @returns {boolean}
|
|
314
|
+
*/
|
|
315
|
+
export function maybeFetchCore({
|
|
316
|
+
release,
|
|
317
|
+
cacheDir,
|
|
318
|
+
env = process.env,
|
|
319
|
+
start = startWorker,
|
|
320
|
+
platform = process.platform,
|
|
321
|
+
}) {
|
|
322
|
+
if (isCi(env) || platform === 'win32') return false;
|
|
323
|
+
if (!isReleaseVersion(release.version)) return false;
|
|
324
|
+
const beside = readJson(
|
|
325
|
+
path.join(release.root, '..', 'core', 'package.json'),
|
|
326
|
+
);
|
|
327
|
+
if (
|
|
328
|
+
beside?.name === '@astryxdesign/core' &&
|
|
329
|
+
beside.version === release.version
|
|
330
|
+
) {
|
|
331
|
+
return false;
|
|
332
|
+
}
|
|
333
|
+
if (cachedRelease(release.version, cacheDir)) return false;
|
|
334
|
+
if (recentFailedInstall(release.version, cacheDir)) return false;
|
|
335
|
+
if (
|
|
336
|
+
fs.existsSync(path.join(releasesDir(cacheDir), `.lock-${release.version}`))
|
|
337
|
+
) {
|
|
338
|
+
return false;
|
|
339
|
+
}
|
|
340
|
+
const worker = path.join(
|
|
341
|
+
release.root,
|
|
342
|
+
'foundation',
|
|
343
|
+
'release',
|
|
344
|
+
'core-worker.mjs',
|
|
345
|
+
);
|
|
346
|
+
// A release without the step predates it.
|
|
347
|
+
if (!fs.existsSync(worker)) return false;
|
|
348
|
+
start(worker, cacheDir);
|
|
349
|
+
return true;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Start the background check when one is due: never when the environment
|
|
354
|
+
* turns update notices off (`CI`, `NO_UPDATE_NOTIFIER`), never in the first
|
|
355
|
+
* day after the first run, and at most once a day. Returns whether a check
|
|
356
|
+
* was started.
|
|
357
|
+
*
|
|
358
|
+
* @param {{
|
|
359
|
+
* stateDir?: string,
|
|
360
|
+
* now?: number,
|
|
361
|
+
* env?: Record<string, string | undefined>,
|
|
362
|
+
* start?: (worker: string, stateDir: string) => void,
|
|
363
|
+
* }} [options]
|
|
364
|
+
* @returns {boolean}
|
|
365
|
+
*/
|
|
366
|
+
export function maybeStartCheck(options = {}) {
|
|
367
|
+
const {
|
|
368
|
+
stateDir = userConfigDir(),
|
|
369
|
+
now = Date.now(),
|
|
370
|
+
env = process.env,
|
|
371
|
+
start = startWorker,
|
|
372
|
+
} = options;
|
|
373
|
+
if (updateNoticesOff(env)) return false;
|
|
374
|
+
const state = readGlobalState(stateDir);
|
|
375
|
+
if (typeof state.firstRunAt !== 'number') {
|
|
376
|
+
updateGlobalState({firstRunAt: now}, stateDir);
|
|
377
|
+
return false;
|
|
378
|
+
}
|
|
379
|
+
const last = Math.max(state.firstRunAt, state.checkedAt ?? 0);
|
|
380
|
+
if (now - last < CHECK_INTERVAL_MS) return false;
|
|
381
|
+
updateGlobalState({checkedAt: now}, stateDir);
|
|
382
|
+
// A start time that cannot be recorded would start a check on every run.
|
|
383
|
+
if (readGlobalState(stateDir).checkedAt !== now) return false;
|
|
384
|
+
start(
|
|
385
|
+
fileURLToPath(new URL('./refresh-worker.mjs', import.meta.url)),
|
|
386
|
+
stateDir,
|
|
387
|
+
);
|
|
388
|
+
return true;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Why the last update check did not reach the registry, when it failed after
|
|
393
|
+
* the last one that did; null otherwise. For diagnosis only.
|
|
394
|
+
* @param {string} [stateDir]
|
|
395
|
+
* @returns {{at: number, reason: string} | null}
|
|
396
|
+
*/
|
|
397
|
+
export function lastCheckFailure(stateDir = userConfigDir()) {
|
|
398
|
+
const state = readGlobalState(stateDir);
|
|
399
|
+
const failed = state.checkFailed;
|
|
400
|
+
if (
|
|
401
|
+
!failed ||
|
|
402
|
+
typeof failed.at !== 'number' ||
|
|
403
|
+
typeof failed.reason !== 'string'
|
|
404
|
+
) {
|
|
405
|
+
return null;
|
|
406
|
+
}
|
|
407
|
+
return typeof state.checkOkAt === 'number' && state.checkOkAt > failed.at
|
|
408
|
+
? null
|
|
409
|
+
: {at: failed.at, reason: failed.reason};
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Start a detached worker that outlives this run and reaches no stream.
|
|
414
|
+
* @param {string} worker
|
|
415
|
+
* @param {string} stateDir
|
|
416
|
+
*/
|
|
417
|
+
function startWorker(worker, stateDir) {
|
|
418
|
+
try {
|
|
419
|
+
const child = spawn(process.execPath, [worker, stateDir], {
|
|
420
|
+
detached: true,
|
|
421
|
+
stdio: 'ignore',
|
|
422
|
+
windowsHide: true,
|
|
423
|
+
});
|
|
424
|
+
child.on('error', () => {});
|
|
425
|
+
child.unref();
|
|
426
|
+
} catch {
|
|
427
|
+
// A check that cannot start is the same as a failed check.
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* The check itself: ask the registry for `latest` and save what it says. It
|
|
433
|
+
* installs nothing. At most one check runs at a time.
|
|
434
|
+
* @param {{stateDir?: string, resolve?: typeof resolveLatestRelease}} [options]
|
|
435
|
+
* @returns {GlobalState}
|
|
436
|
+
*/
|
|
437
|
+
export function runCheck(options = {}) {
|
|
438
|
+
const {stateDir = userConfigDir(), resolve = resolveLatestRelease} = options;
|
|
439
|
+
const lockDir = path.join(stateDir, '.lock-check');
|
|
440
|
+
try {
|
|
441
|
+
if (!tryLock(lockDir)) return readGlobalState(stateDir);
|
|
442
|
+
} catch {
|
|
443
|
+
return readGlobalState(stateDir);
|
|
444
|
+
}
|
|
445
|
+
try {
|
|
446
|
+
/** @type {string} */
|
|
447
|
+
let reason = 'unknown';
|
|
448
|
+
const latest = resolve({
|
|
449
|
+
onFailure: why => {
|
|
450
|
+
reason = why;
|
|
451
|
+
},
|
|
452
|
+
});
|
|
453
|
+
if (!latest) {
|
|
454
|
+
// Recorded so doctor can say why notices stopped (diagnosis only).
|
|
455
|
+
return updateGlobalState(
|
|
456
|
+
{checkFailed: {at: Date.now(), reason}},
|
|
457
|
+
stateDir,
|
|
458
|
+
);
|
|
459
|
+
}
|
|
460
|
+
return updateGlobalState(
|
|
461
|
+
{
|
|
462
|
+
latest: latest.version,
|
|
463
|
+
latestNode: latest.node,
|
|
464
|
+
checkOkAt: Date.now(),
|
|
465
|
+
checkFailed: undefined,
|
|
466
|
+
},
|
|
467
|
+
stateDir,
|
|
468
|
+
);
|
|
469
|
+
} finally {
|
|
470
|
+
fs.rmSync(lockDir, {recursive: true, force: true});
|
|
471
|
+
}
|
|
472
|
+
}
|