@astryxdesign/cli 0.7.2 → 0.7.3-canary.02f5fe4
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/README.md +104 -71
- package/api/build/_adapter.d.mts +58 -0
- package/api/build/_adapter.mjs +127 -3
- package/api/build/blocks/blocks.d.mts +92 -0
- package/api/build/blocks/blocks.mjs +528 -0
- package/api/build/blocks/blocks.test.mjs +238 -0
- package/api/build/blocks/blocks.weights.json +1 -0
- package/api/build/build.mjs +25 -6
- package/api/build/build.type.mjs +1 -1
- package/api/build/kit/answer.d.mts +18 -0
- package/api/build/kit/answer.mjs +195 -0
- package/api/build/kit/answer.test.mjs +108 -0
- package/api/build/kit/kind.d.mts +25 -0
- package/api/build/kit/kind.mjs +170 -0
- package/api/build/kit/kit.d.mts +2 -4
- package/api/build/kit/kit.mjs +8 -398
- package/api/build/kit/rank.d.mts +3 -32
- package/api/build/kit/rank.mjs +25 -342
- package/api/build/kit/rank.test.mjs +2 -1
- package/api/build/kit/signals.d.mts +79 -0
- package/api/build/kit/signals.mjs +295 -0
- package/api/build/kit/start.d.mts +32 -0
- package/api/build/kit/start.mjs +163 -0
- package/api/build/kit/words.d.mts +72 -0
- package/api/build/kit/words.mjs +202 -0
- package/api/build/tree.d.mts +20 -0
- package/api/build/tree.mjs +53 -0
- package/api/build/tree.test.mjs +185 -0
- package/api/build/tree.weights.json +1 -0
- package/api/component/_adapter.mjs +39 -5
- package/api/component/component-replacement.test.mjs +1 -0
- package/api/component/component.mjs +17 -3
- package/api/component/component.test.mjs +15 -0
- package/api/component/doc-links.test.mjs +2 -2
- package/api/discover/_adapter.d.mts +1 -2
- package/api/discover/_adapter.mjs +42 -17
- package/api/discover/_adapter.test.mjs +42 -0
- package/api/discover/discover.mjs +0 -1
- package/api/docs/_adapter.d.mts +2 -2
- package/api/docs/_adapter.mjs +82 -23
- package/api/docs/docs-homes.test.mjs +127 -0
- package/api/docs/docs.doc.mjs +3 -3
- package/api/docs/docs.test.mjs +35 -19
- package/api/docs/integration-tree.test.mjs +20 -20
- package/api/docs/integrationDocs.test.mjs +1 -1
- package/api/docs/namespace-section.test.mjs +6 -6
- package/api/docs/reference-blocks.test.mjs +2 -2
- package/api/doctor/_adapter.d.mts +33 -13
- package/api/doctor/_adapter.mjs +55 -25
- package/api/doctor/doctor.d.mts +23 -5
- package/api/doctor/doctor.mjs +183 -40
- package/api/doctor/doctor.test.mjs +95 -12
- package/api/hook/hook.mjs +1 -1
- package/api/init/init.doc.mjs +20 -6
- package/api/init/init.test.mjs +18 -2
- package/api/init/init.type.d.mts +3 -3
- package/api/init/init.type.mjs +3 -3
- package/api/init/remove/remove.mjs +17 -4
- package/api/init/remove/remove.test.mjs +114 -2
- package/api/init/run/run.mjs +69 -6
- package/api/integration/_adapter.d.mts +8 -0
- package/api/integration/_adapter.mjs +21 -1
- package/api/integration/authoring-checks.mjs +83 -9
- package/api/integration/authoring-checks.test.mjs +220 -0
- package/api/integration/pack-check.mjs +123 -4
- package/api/integration/pack-check.test.mjs +87 -0
- package/api/integration/validate-integration-case-disk.test.mjs +111 -0
- package/api/integration/validate-integration-fixes.test.mjs +6 -5
- package/api/integration/validate-integration-gaps.test.mjs +1975 -0
- package/api/integration/validate-integration.d.mts +15 -2
- package/api/integration/validate-integration.mjs +298 -39
- package/api/integration/validate-integration.type.d.mts +90 -1
- package/api/integration/validate-integration.type.mjs +67 -2
- package/api/integration/validateIntegration.doc.mjs +1 -1
- package/api/search/ORDERING.md +28 -0
- package/api/search/_adapter.d.mts +82 -2
- package/api/search/_adapter.mjs +157 -10
- package/api/search/_adapter.test.mjs +173 -0
- package/api/search/_candidate-score.d.mts +40 -0
- package/api/search/_candidate-score.mjs +238 -0
- package/api/search/_cards.json +6098 -0
- package/api/search/_compound.d.mts +50 -0
- package/api/search/_compound.mjs +170 -0
- package/api/search/_doc-searcher.d.mts +4 -0
- package/api/search/_doc-searcher.mjs +23 -0
- package/api/search/_doc-searcher.test.mjs +36 -0
- package/api/search/_doc-searcher.weights.json +1 -0
- package/api/search/_doc-text.d.mts +30 -0
- package/api/search/_doc-text.mjs +87 -0
- package/api/search/_entries.d.mts +63 -0
- package/api/search/_entries.mjs +232 -0
- package/api/search/_entries.test.mjs +48 -0
- package/api/search/_features.d.mts +35 -0
- package/api/search/_features.mjs +155 -0
- package/api/search/_gather-components.d.mts +26 -0
- package/api/search/_gather-components.mjs +284 -0
- package/api/search/_gather-docs.d.mts +20 -0
- package/api/search/_gather-docs.mjs +254 -0
- package/api/search/_gather-hooks.d.mts +12 -0
- package/api/search/_gather-hooks.mjs +52 -0
- package/api/search/_gather-templates.d.mts +25 -0
- package/api/search/_gather-templates.mjs +107 -0
- package/api/search/_lexical.d.mts +135 -0
- package/api/search/_lexical.mjs +351 -0
- package/api/search/_main-searcher.d.mts +19 -0
- package/api/search/_main-searcher.mjs +115 -0
- package/api/search/_main-searcher.test.mjs +106 -0
- package/api/search/_main-searcher.weights.json +1 -0
- package/api/search/_module-doc.d.mts +32 -0
- package/api/search/_module-doc.mjs +78 -0
- package/api/search/_order.d.mts +32 -0
- package/api/search/_order.mjs +162 -0
- package/api/search/_order.test.mjs +72 -0
- package/api/search/_priority.d.mts +50 -0
- package/api/search/_priority.mjs +139 -0
- package/api/search/_query-words.d.mts +25 -0
- package/api/search/_query-words.mjs +92 -0
- package/api/search/_query.d.mts +65 -0
- package/api/search/_query.mjs +176 -0
- package/api/search/_result.d.mts +97 -0
- package/api/search/_result.mjs +150 -0
- package/api/search/_score.d.mts +60 -0
- package/api/search/_score.mjs +283 -0
- package/api/search/_synonyms.d.mts +21 -0
- package/api/search/_synonyms.mjs +67 -0
- package/api/search/_template-searcher.d.mts +4 -0
- package/api/search/_template-searcher.mjs +23 -0
- package/api/search/_template-searcher.test.mjs +40 -0
- package/api/search/_template-searcher.weights.json +1 -0
- package/api/search/_titles.d.mts +33 -0
- package/api/search/_titles.mjs +65 -0
- package/api/search/_words.d.mts +64 -0
- package/api/search/_words.mjs +157 -0
- package/api/search/search.d.mts +22 -305
- package/api/search/search.doc.mjs +8 -6
- package/api/search/search.mjs +56 -2482
- package/api/search/search.test.mjs +14 -14
- package/api/search/search.type.d.mts +6 -1
- package/api/search/search.type.mjs +6 -1
- package/api/search/tree.d.mts +15 -0
- package/api/search/tree.mjs +40 -0
- package/api/search/tree.test.mjs +66 -0
- package/api/search/tree.weights.json +1 -0
- package/api/template/template.mjs +5 -1
- package/api/theme/build/build.packed-old-core.test.mjs +1 -0
- package/api/upgrade/_adapter.d.mts +57 -9
- package/api/upgrade/_adapter.mjs +198 -28
- package/api/upgrade/registry/registry.d.mts +10 -4
- package/api/upgrade/registry/registry.mjs +33 -16
- package/api/upgrade/registry/registry.test.mjs +85 -0
- package/api/upgrade/run/run.d.mts +4 -2
- package/api/upgrade/run/run.mjs +13 -2
- package/api/upgrade/run/run.test.mjs +417 -3
- package/api/upgrade/upgrade.doc.mjs +10 -5
- package/api/upgrade/upgrade.mjs +13 -2
- package/api/upgrade/upgrade.test.mjs +194 -0
- package/api/upgrade/upgrade.type.d.mts +5 -3
- package/api/upgrade/upgrade.type.mjs +8 -6
- package/assets/codemods/transforms/v0.7.0/__tests__/validate-data-token-ownership.test.mjs +11 -0
- package/assets/codemods/transforms/v0.7.0/validate-data-token-ownership.mjs +3 -3
- package/assets/docs/author-a-theme.doc.mjs +2 -2
- package/assets/docs/is-my-code-good.doc.mjs +287 -0
- package/assets/docs/tree/add-a-component.doc.mjs +1 -1
- package/assets/docs/tree/add-a-theme.doc.mjs +1 -1
- package/assets/docs/tree/add-a-topic.doc.mjs +2 -2
- package/assets/docs/tree/agent-guidance.doc.mjs +1 -1
- package/assets/docs/tree/api.doc.mjs +6 -0
- package/assets/docs/tree/{integrations.doc.mjs → authoring.doc.mjs} +15 -6
- package/assets/docs/tree/block-template.doc.mjs +1 -1
- package/assets/docs/tree/build-the-template.doc.mjs +1 -1
- package/assets/docs/tree/building-blocks.doc.mjs +2 -2
- package/assets/docs/tree/check-the-props.doc.mjs +1 -1
- package/assets/docs/tree/check-your-docs.doc.mjs +2 -2
- package/assets/docs/tree/checks.doc.mjs +3 -3
- package/assets/docs/tree/ci-and-containers.doc.mjs +13 -0
- package/assets/docs/tree/cli-command.doc.mjs +1 -1
- package/assets/docs/tree/cli.doc.mjs +1 -1
- package/assets/docs/tree/codemods.doc.mjs +1 -1
- package/assets/docs/tree/component-family.doc.mjs +1 -1
- package/assets/docs/tree/component-imports.doc.mjs +1 -1
- package/assets/docs/tree/components.doc.mjs +1 -1
- package/assets/docs/tree/configuration.doc.mjs +1 -1
- package/assets/docs/tree/debug-and-gap-reports.doc.mjs +1 -1
- package/assets/docs/tree/define-the-theme.doc.mjs +1 -1
- package/assets/docs/tree/describe-the-component.doc.mjs +1 -1
- package/assets/docs/tree/docs.doc.mjs +1 -1
- package/assets/docs/tree/document-the-template.doc.mjs +1 -1
- package/assets/docs/tree/document-the-theme.doc.mjs +1 -1
- package/assets/docs/tree/export-template-assets.doc.mjs +1 -1
- package/assets/docs/tree/extend-or-replace.doc.mjs +1 -1
- package/assets/docs/{authoring.doc.mjs → tree/field-reference.doc.mjs} +4 -3
- package/assets/docs/tree/fonts-and-assets.doc.mjs +1 -1
- package/assets/docs/tree/generate-a-palette.doc.mjs +1 -1
- package/assets/docs/tree/global-integrations.doc.mjs +2 -2
- package/assets/docs/tree/grade-template-with-agent.doc.mjs +4 -4
- package/assets/docs/tree/help.doc.mjs +2 -2
- package/assets/docs/tree/host-entry.doc.mjs +128 -0
- package/assets/docs/tree/links.doc.mjs +1 -1
- package/assets/docs/tree/package-and-test.doc.mjs +1 -1
- package/assets/docs/tree/page-template.doc.mjs +1 -1
- package/assets/docs/tree/publishing.doc.mjs +1 -1
- package/assets/docs/tree/quick-start.doc.mjs +1 -1
- package/assets/docs/tree/replace-a-core-component.doc.mjs +1 -1
- package/assets/docs/tree/replace-a-core-template.doc.mjs +1 -1
- package/assets/docs/tree/sections-and-placement.doc.mjs +1 -1
- package/assets/docs/tree/see-it-in-an-app.doc.mjs +1 -1
- package/assets/docs/tree/ship.doc.mjs +2 -2
- package/assets/docs/tree/short-and-findable.doc.mjs +1 -1
- package/assets/docs/tree/single-component.doc.mjs +1 -1
- package/assets/docs/tree/start-a-template.doc.mjs +1 -1
- package/assets/docs/tree/subcomponent.doc.mjs +1 -1
- package/assets/docs/tree/template-assets.doc.mjs +1 -1
- package/assets/docs/tree/template-doc-overview.doc.mjs +2 -2
- package/assets/docs/tree/template-fonts.doc.mjs +1 -1
- package/assets/docs/tree/template-grading-rubric.doc.mjs +17 -38
- 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 +1 -1
- package/assets/docs/tree/templates.doc.mjs +1 -1
- package/assets/docs/tree/test-in-an-app.doc.mjs +1 -1
- package/assets/docs/tree/test-template-in-app.doc.mjs +1 -1
- package/assets/docs/tree/themes.doc.mjs +1 -1
- package/assets/docs/tree/tokens-data.doc.mjs +2 -2
- package/assets/docs/tree/troubleshooting.doc.mjs +1 -1
- package/assets/docs/tree/upgrading.doc.mjs +1 -1
- package/assets/docs/tree/use-a-theme-in-an-app.doc.mjs +1 -1
- package/assets/docs/tree/verify-packed-template.doc.mjs +1 -1
- package/assets/docs/tree/versioning.doc.mjs +5 -1
- package/assets/docs/tree/write-good-templates.doc.mjs +1 -1
- package/assets/docs/tree/write-the-template-file.doc.mjs +1 -1
- package/assets/docs/use-integrations.doc.mjs +120 -0
- package/assets/docs/working-with-ai.doc.mjs +6 -2
- package/assets/templates/themes/butter/butterTheme.ts +4 -2
- package/assets/templates/themes/stone/stoneTheme.ts +4 -2
- package/assets/templates/themes/y2k/y2kTheme.ts +4 -2
- package/authoring/debug/parse.d.mts +1 -1
- package/authoring/doctypes/schema/schema.doc.mjs +1 -1
- package/authoring/integration/integration.doc.mjs +1 -1
- package/authoring/integration/type.ts +1 -1
- package/clients/cli/bin/astryx.mjs +7 -78
- package/clients/cli/command-result-coverage.test.mjs +6 -5
- package/clients/cli/commands/build-theme.color-scheme.test.mjs +1 -1
- package/clients/cli/commands/{component/index.mjs → component.mjs} +37 -37
- package/clients/cli/commands/component.test.mjs +6 -6
- package/clients/cli/commands/docs.doc.mjs +2 -2
- package/clients/cli/commands/docs.mjs +1 -1
- package/clients/cli/commands/docs.test.mjs +14 -14
- package/clients/cli/commands/doctor-integration.test.mjs +49 -1
- package/clients/cli/commands/doctor.doc.mjs +1 -1
- package/clients/cli/commands/doctor.mjs +40 -0
- package/clients/cli/commands/doctor.test.mjs +65 -0
- package/clients/cli/commands/{hook/index.mjs → hook.mjs} +22 -22
- package/clients/cli/commands/import-hint-correctness.test.mjs +1 -1
- package/clients/cli/commands/init.behavior.test.mjs +230 -1
- package/clients/cli/commands/init.doc.mjs +28 -9
- package/clients/cli/commands/init.flag-help.test.mjs +1 -0
- package/clients/cli/commands/init.mjs +2 -2
- package/clients/cli/commands/integration-check.test.mjs +48 -0
- package/clients/cli/commands/integration.doc.mjs +1 -1
- package/clients/cli/commands/manifest.doc.mjs +1 -1
- package/clients/cli/commands/manifest.mjs +67 -0
- package/clients/cli/commands/outside-project.test.mjs +101 -1
- package/clients/cli/commands/postinstall.doc.mjs +23 -0
- package/clients/cli/commands/postinstall.mjs +31 -0
- package/clients/cli/commands/setup-nudge.test.mjs +78 -0
- package/clients/cli/commands/{build-theme.mjs → theme.mjs} +1 -1
- package/clients/cli/commands/upgrade.doc.mjs +4 -2
- package/clients/cli/commands/upgrade.mjs +9 -2
- package/clients/cli/commands/upgrade.subfolder-path.test.mjs +97 -0
- package/clients/cli/index.mjs +54 -94
- package/clients/cli/lib/component-format.mjs +1 -1
- package/clients/cli/lib/define-command.mjs +12 -7
- package/clients/cli/lib/exit-codes.test.mjs +5 -0
- package/clients/cli/lib/manifest.test.mjs +12 -0
- package/clients/cli/lib/welcome-box.mjs +50 -0
- package/clients/cli/run.mjs +108 -0
- package/foundation/agent-docs/agent-doc-state.d.mts +32 -7
- package/foundation/agent-docs/agent-doc-state.mjs +58 -9
- package/foundation/agent-docs/agent-docs.d.mts +100 -12
- package/foundation/agent-docs/agent-docs.mjs +1017 -105
- package/foundation/agent-docs/agent-docs.path-safety.test.mjs +1239 -17
- package/foundation/agent-docs/agent-docs.test.mjs +683 -39
- package/foundation/agent-docs/computer-agent-text.d.mts +39 -2
- package/foundation/agent-docs/computer-agent-text.mjs +135 -8
- package/foundation/agent-docs/computer-agent-text.test.mjs +99 -2
- package/foundation/config/project.mjs +20 -22
- package/foundation/config/project.test.mjs +56 -0
- package/foundation/discovery/authoring-self-docs.d.mts +7 -0
- package/foundation/discovery/authoring-self-docs.mjs +16 -4
- package/foundation/discovery/authoring-self-docs.test.mjs +15 -3
- package/foundation/discovery/authoring-surface.d.mts +1 -1
- package/foundation/discovery/authoring-surface.mjs +2 -2
- package/foundation/discovery/authoring-surface.test.mjs +1 -1
- package/foundation/discovery/cli-self-docs.d.mts +2 -1
- package/foundation/discovery/cli-self-docs.mjs +4 -3
- package/foundation/discovery/cli-self-docs.test.mjs +2 -2
- package/foundation/discovery/component-discovery.d.mts +37 -0
- package/foundation/discovery/component-discovery.mjs +80 -5
- package/foundation/discovery/component-loader.d.mts +1 -1
- package/foundation/discovery/docs-discovery.mjs +14 -1
- package/foundation/discovery/module-exports.d.mts +41 -0
- package/foundation/discovery/module-exports.mjs +253 -0
- package/foundation/discovery/runner-allowlist.d.mts +2 -4
- package/foundation/discovery/runner-allowlist.mjs +2 -4
- package/foundation/discovery/runner-commands.d.mts +77 -0
- package/foundation/discovery/runner-commands.mjs +294 -0
- package/foundation/discovery/runner-commands.test.mjs +128 -0
- package/foundation/discovery/stray-pointers.test.mjs +1 -1
- package/foundation/discovery/template-adapter.mjs +18 -1
- package/foundation/discovery/template-needs.mjs +1 -44
- package/foundation/discovery/theme-discovery.mjs +147 -3
- package/foundation/doc-compiler/doc-loads.test.mjs +33 -9
- package/foundation/doc-compiler/read.mjs +59 -1
- package/foundation/doc-compiler/read.test.mjs +11 -2
- package/foundation/doc-compiler/split-topic-keywords.test.mjs +3 -2
- package/foundation/doc-compiler/tree.d.mts +32 -6
- package/foundation/doc-compiler/tree.mjs +77 -43
- package/foundation/doc-compiler/tree.test.mjs +7 -7
- package/foundation/fs/paths.d.mts +70 -8
- package/foundation/fs/paths.mjs +556 -38
- package/foundation/fs/paths.test.mjs +430 -54
- package/foundation/fs/read-record.d.mts +18 -0
- package/foundation/fs/read-record.mjs +131 -0
- package/foundation/fs/read-record.test.mjs +77 -0
- package/foundation/integrations/autolink.d.mts +2 -1
- package/foundation/integrations/autolink.mjs +4 -13
- package/foundation/integrations/cli-peer-version.d.mts +36 -0
- package/foundation/integrations/cli-peer-version.mjs +132 -0
- package/foundation/integrations/cli-peer-version.test.mjs +354 -0
- package/foundation/integrations/computer-integrations.d.mts +6 -3
- package/foundation/integrations/computer-integrations.mjs +38 -9
- package/foundation/integrations/contribution-inventory.d.mts +15 -20
- package/foundation/integrations/contribution-inventory.mjs +41 -5
- package/foundation/integrations/exports-subpaths.d.mts +57 -0
- package/foundation/integrations/exports-subpaths.mjs +113 -0
- package/foundation/integrations/integrations.d.mts +27 -1
- package/foundation/integrations/integrations.mjs +61 -2
- package/foundation/integrations/public-imports.d.mts +118 -0
- package/foundation/integrations/public-imports.mjs +1769 -0
- package/foundation/integrations/public-imports.test.mjs +1793 -0
- package/foundation/integrations/validate-contributions.d.mts +115 -0
- package/foundation/integrations/validate-contributions.mjs +1168 -13
- package/foundation/release/cache.test.mjs +24 -21
- package/foundation/release/global-state.d.mts +8 -4
- package/foundation/release/global-state.mjs +4 -2
- package/foundation/release/handoff.d.mts +23 -4
- package/foundation/release/handoff.mjs +175 -8
- package/foundation/release/notices.d.mts +62 -8
- package/foundation/release/notices.mjs +136 -25
- package/foundation/release/notices.test.mjs +21 -0
- package/foundation/release/run-context.mjs +14 -0
- package/foundation/response/response-types.doc.mjs +1 -1
- package/foundation/route/route.d.mts +285 -0
- package/foundation/route/route.mjs +324 -0
- package/foundation/route/route.test.mjs +153 -0
- package/foundation/runtime/hosted-runtime.test.mjs +403 -0
- package/foundation/runtime/locked-versions.d.mts +32 -0
- package/foundation/runtime/locked-versions.mjs +65 -0
- package/foundation/runtime/package-root.d.mts +91 -0
- package/foundation/runtime/package-root.mjs +174 -0
- package/foundation/runtime/package-set.d.mts +62 -0
- package/foundation/runtime/package-set.mjs +130 -0
- package/foundation/runtime/package-set.test.mjs +432 -0
- package/foundation/text/string-utils.d.mts +2 -1
- package/foundation/text/string-utils.mjs +16 -5
- package/foundation/text/suggest-order.d.mts +72 -0
- package/foundation/text/suggest-order.mjs +363 -0
- package/foundation/text/suggest-order.test.mjs +259 -0
- package/host/door-conformance.test.mjs +274 -0
- package/host/index.d.ts +116 -0
- package/host/index.mjs +295 -0
- package/host/index.test.mjs +302 -0
- package/package.json +14 -9
|
@@ -225,12 +225,19 @@ export function peerProblem(pkg, release) {
|
|
|
225
225
|
|
|
226
226
|
/**
|
|
227
227
|
* The computer-level integrations installed beside the CLI at `cliRoot`, in
|
|
228
|
-
* name order (declaration order when the root declares them)
|
|
228
|
+
* name order (declaration order when the root declares them), then each
|
|
229
|
+
* integration a host approves (`approved`, architecture:cli-surface INV30),
|
|
230
|
+
* resolved by name from the package set that holds that CLI alone. Reads
|
|
229
231
|
* package.json files only.
|
|
230
|
-
* @param {{cliRoot: string, release: string, cacheDir?: string}} options
|
|
232
|
+
* @param {{cliRoot: string, release: string, cacheDir?: string, approved?: readonly string[]}} options
|
|
231
233
|
* @returns {ComputerIntegrationCandidate[]}
|
|
232
234
|
*/
|
|
233
|
-
export function scanComputerIntegrations({
|
|
235
|
+
export function scanComputerIntegrations({
|
|
236
|
+
cliRoot,
|
|
237
|
+
release,
|
|
238
|
+
cacheDir,
|
|
239
|
+
approved = [],
|
|
240
|
+
}) {
|
|
234
241
|
const self = real(cliRoot);
|
|
235
242
|
/** @type {ComputerIntegrationCandidate[]} */
|
|
236
243
|
const found = [];
|
|
@@ -238,21 +245,43 @@ export function scanComputerIntegrations({cliRoot, release, cacheDir}) {
|
|
|
238
245
|
for (const root of computerInstallRoots(cliRoot, {cacheDir})) {
|
|
239
246
|
scanRoot(root, {self, release, found, seen});
|
|
240
247
|
}
|
|
248
|
+
const owner = approved.length > 0 ? installPlaceOf(self).owner : null;
|
|
249
|
+
if (owner) scanRoot(owner, {self, release, found, seen}, approved);
|
|
241
250
|
return found;
|
|
242
251
|
}
|
|
243
252
|
|
|
244
253
|
/**
|
|
245
|
-
*
|
|
254
|
+
* `name` as installed in `root`'s own `node_modules`, never in a folder above.
|
|
255
|
+
* @param {string} name
|
|
256
|
+
* @param {string} root
|
|
257
|
+
* @returns {{packageDir: string, hostDir: string} | null}
|
|
258
|
+
*/
|
|
259
|
+
function ownPackageDir(name, root) {
|
|
260
|
+
const packageDir = path.join(root, 'node_modules', ...name.split('/'));
|
|
261
|
+
return fs.existsSync(path.join(packageDir, 'package.json'))
|
|
262
|
+
? {packageDir, hostDir: root}
|
|
263
|
+
: null;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Add the integrations installed in one install root: those it declares or
|
|
268
|
+
* installs, or, given `approved`, those names installed in its own
|
|
269
|
+
* `node_modules`.
|
|
246
270
|
* @param {string} root
|
|
247
271
|
* @param {{self: string, release: string, found: ComputerIntegrationCandidate[], seen: Set<string>}} into
|
|
272
|
+
* @param {readonly string[] | null} [approved]
|
|
248
273
|
*/
|
|
249
|
-
function scanRoot(root, {self, release, found, seen}) {
|
|
250
|
-
const declared =
|
|
251
|
-
|
|
252
|
-
|
|
274
|
+
function scanRoot(root, {self, release, found, seen}, approved = null) {
|
|
275
|
+
const declared =
|
|
276
|
+
approved ??
|
|
277
|
+
(readPackage(root)
|
|
278
|
+
? readDeclaredDependencies(root).map(d => d.name)
|
|
279
|
+
: installedNames(root));
|
|
253
280
|
for (const name of declared) {
|
|
254
281
|
if (NOT_INTEGRATIONS.has(name)) continue;
|
|
255
|
-
const resolved =
|
|
282
|
+
const resolved = approved
|
|
283
|
+
? ownPackageDir(name, root)
|
|
284
|
+
: resolveInstalledPackageDir(name, root);
|
|
256
285
|
if (!resolved) continue;
|
|
257
286
|
const identity = real(resolved.packageDir);
|
|
258
287
|
if (identity === self || seen.has(identity)) continue;
|
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
// @generated by scripts/sync-api-types.mjs from the JSDoc in foundation/**/*.mjs.
|
|
2
2
|
// DO NOT EDIT — run `pnpm sync:api-types` to regenerate.
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* The contribution files readers read under each declared root that is a
|
|
6
|
+
* readable folder, package-relative, without importing anything. A folder
|
|
7
|
+
* inside a root that cannot be listed is skipped.
|
|
8
|
+
* @param {{components?: string, templates?: string, codemods?: string, docs?: string, themes?: string}} loaded
|
|
9
|
+
* @param {string} pkgDir
|
|
10
|
+
* @returns {string[]}
|
|
11
|
+
*/
|
|
12
|
+
export function contributionFiles(loaded: {
|
|
13
|
+
components?: string;
|
|
14
|
+
templates?: string;
|
|
15
|
+
codemods?: string;
|
|
16
|
+
docs?: string;
|
|
17
|
+
themes?: string;
|
|
18
|
+
}, pkgDir: string): string[];
|
|
4
19
|
/**
|
|
5
20
|
* @typedef {object} FileInventoryRoot
|
|
6
21
|
* @property {'themes'|'components'|'templates'|'codemods'|'docs'} kind
|
|
@@ -22,26 +37,6 @@
|
|
|
22
37
|
* @returns {FileInventory}
|
|
23
38
|
*/
|
|
24
39
|
export function computeRequiredFiles(loaded: import("./integrations.mjs").LoadedIntegration): FileInventory;
|
|
25
|
-
/**
|
|
26
|
-
* @typedef {object} ContributionIdentities
|
|
27
|
-
* @property {{slug: string, exportName: string}[]} themes
|
|
28
|
-
* @property {string[]} components
|
|
29
|
-
* @property {{id: string, type: string, name: string, replaces?: string}[]} templates
|
|
30
|
-
* @property {{version: string, id: string}[]} codemods
|
|
31
|
-
* @property {string[]} docs
|
|
32
|
-
* @property {string[]} agentDocsAppend
|
|
33
|
-
*/
|
|
34
|
-
/**
|
|
35
|
-
* The resolved fields needed to discover contribution identities.
|
|
36
|
-
* @typedef {object} IdentitySource
|
|
37
|
-
* @property {string} name
|
|
38
|
-
* @property {string} [themes]
|
|
39
|
-
* @property {string} [components]
|
|
40
|
-
* @property {string} [templates]
|
|
41
|
-
* @property {string} [codemods]
|
|
42
|
-
* @property {string} [docs]
|
|
43
|
-
* @property {{append?: readonly string[]}} [agentDocs]
|
|
44
|
-
*/
|
|
45
40
|
/**
|
|
46
41
|
* Run the same discovery functions a consumer uses to collect every
|
|
47
42
|
* contribution identity from a loaded integration.
|
|
@@ -137,6 +137,29 @@ const ROOT_KINDS = /** @type {const} */ ([
|
|
|
137
137
|
'docs',
|
|
138
138
|
]);
|
|
139
139
|
|
|
140
|
+
/**
|
|
141
|
+
* The contribution files readers read under each declared root that is a
|
|
142
|
+
* readable folder, package-relative, without importing anything. A folder
|
|
143
|
+
* inside a root that cannot be listed is skipped.
|
|
144
|
+
* @param {{components?: string, templates?: string, codemods?: string, docs?: string, themes?: string}} loaded
|
|
145
|
+
* @param {string} pkgDir
|
|
146
|
+
* @returns {string[]}
|
|
147
|
+
*/
|
|
148
|
+
export function contributionFiles(loaded, pkgDir) {
|
|
149
|
+
/** @type {Set<string>} */
|
|
150
|
+
const files = new Set();
|
|
151
|
+
for (const kind of ROOT_KINDS) {
|
|
152
|
+
const root = loaded[kind];
|
|
153
|
+
if (!root || !isFolder(root)) continue;
|
|
154
|
+
try {
|
|
155
|
+
for (const file of ENUMERATORS[kind](root, pkgDir)) files.add(file);
|
|
156
|
+
} catch {
|
|
157
|
+
// An unreadable folder inside the root.
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return [...files].sort();
|
|
161
|
+
}
|
|
162
|
+
|
|
140
163
|
// ── Public: static file inventory ────────────────────────────────
|
|
141
164
|
|
|
142
165
|
/**
|
|
@@ -207,6 +230,19 @@ export function computeRequiredFiles(loaded) {
|
|
|
207
230
|
* @property {{append?: readonly string[]}} [agentDocs]
|
|
208
231
|
*/
|
|
209
232
|
|
|
233
|
+
/**
|
|
234
|
+
* Whether `dir` is a folder to list. A declared root that is a file is
|
|
235
|
+
* reported by the root check; discovery finds nothing in it.
|
|
236
|
+
* @param {string} dir
|
|
237
|
+
*/
|
|
238
|
+
function isFolder(dir) {
|
|
239
|
+
try {
|
|
240
|
+
return fs.statSync(dir).isDirectory();
|
|
241
|
+
} catch {
|
|
242
|
+
return false;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
210
246
|
/**
|
|
211
247
|
* Run the same discovery functions a consumer uses to collect every
|
|
212
248
|
* contribution identity from a loaded integration.
|
|
@@ -229,7 +265,7 @@ export async function collectIdentities(loaded) {
|
|
|
229
265
|
/** @type {Array<{kind: string, message: string}>} */
|
|
230
266
|
const errors = [];
|
|
231
267
|
|
|
232
|
-
if (loaded.themes &&
|
|
268
|
+
if (loaded.themes && isFolder(loaded.themes)) {
|
|
233
269
|
try {
|
|
234
270
|
const themes = await discoverIntegrationThemes(
|
|
235
271
|
/** @type {import('./integrations.mjs').LoadedIntegration} */ (loaded),
|
|
@@ -245,7 +281,7 @@ export async function collectIdentities(loaded) {
|
|
|
245
281
|
}
|
|
246
282
|
}
|
|
247
283
|
|
|
248
|
-
if (loaded.components &&
|
|
284
|
+
if (loaded.components && isFolder(loaded.components)) {
|
|
249
285
|
try {
|
|
250
286
|
const records = discoverIntegrationComponents(loaded) ?? [];
|
|
251
287
|
// A family doc backs several records: load it, and report it, once.
|
|
@@ -275,7 +311,7 @@ export async function collectIdentities(loaded) {
|
|
|
275
311
|
}
|
|
276
312
|
}
|
|
277
313
|
|
|
278
|
-
if (loaded.templates &&
|
|
314
|
+
if (loaded.templates && isFolder(loaded.templates)) {
|
|
279
315
|
try {
|
|
280
316
|
const {templates, errors: templateErrors} =
|
|
281
317
|
await discoverIntegrationTemplatesForOne(loaded);
|
|
@@ -298,7 +334,7 @@ export async function collectIdentities(loaded) {
|
|
|
298
334
|
}
|
|
299
335
|
}
|
|
300
336
|
|
|
301
|
-
if (loaded.codemods &&
|
|
337
|
+
if (loaded.codemods && isFolder(loaded.codemods)) {
|
|
302
338
|
try {
|
|
303
339
|
const byVersion = await discoverIntegrationCodemods([loaded]);
|
|
304
340
|
/** @type {{version: string, id: string}[]} */
|
|
@@ -317,7 +353,7 @@ export async function collectIdentities(loaded) {
|
|
|
317
353
|
}
|
|
318
354
|
}
|
|
319
355
|
|
|
320
|
-
if (loaded.docs &&
|
|
356
|
+
if (loaded.docs && isFolder(loaded.docs)) {
|
|
321
357
|
try {
|
|
322
358
|
const {
|
|
323
359
|
records,
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// @generated by scripts/sync-api-types.mjs from the JSDoc in foundation/**/*.mjs.
|
|
2
|
+
// DO NOT EDIT — run `pnpm sync:api-types` to regenerate.
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @file How a package.json `exports` field declares a subpath, read without
|
|
6
|
+
* touching the targets (which may be build output that does not exist yet).
|
|
7
|
+
*
|
|
8
|
+
* @input A package.json `exports` value and a `.`/`./…` subpath.
|
|
9
|
+
* @output Whether the subpath is declared for an ES module importer, and why
|
|
10
|
+
* not when it is not.
|
|
11
|
+
* @position foundation/integrations; read by the public-import checks.
|
|
12
|
+
*/
|
|
13
|
+
/** @param {unknown} value @returns {value is Record<string, unknown>} */
|
|
14
|
+
export function isRecord(value: unknown): value is Record<string, unknown>;
|
|
15
|
+
/**
|
|
16
|
+
* Whether an export value gives an ES module importer something: a string,
|
|
17
|
+
* or a condition object / fallback array with a target under a condition
|
|
18
|
+
* other than `require` and `types`.
|
|
19
|
+
* @param {unknown} value
|
|
20
|
+
* @returns {boolean}
|
|
21
|
+
*/
|
|
22
|
+
export function importable(value: unknown): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Every string target an export value names, any condition.
|
|
25
|
+
* @param {unknown} value
|
|
26
|
+
* @param {string[]} [out]
|
|
27
|
+
* @returns {string[]}
|
|
28
|
+
*/
|
|
29
|
+
export function allTargets(value: unknown, out?: string[]): string[];
|
|
30
|
+
/**
|
|
31
|
+
* @typedef {object} SubpathDeclaration
|
|
32
|
+
* @property {'declared'|'no_exports'|'root_only'|'missing'|'blocked'|'not_importable'} state
|
|
33
|
+
* @property {unknown} [value] the matched export value
|
|
34
|
+
* @property {string} [wildcard] what a `*` key matched
|
|
35
|
+
*/
|
|
36
|
+
/**
|
|
37
|
+
* How a package's `exports` field declares one subpath, without touching the
|
|
38
|
+
* targets: a missing key, a key with only a `require` condition, an `exports`
|
|
39
|
+
* that is a bare string or a condition object (so only `.`), a wildcard that
|
|
40
|
+
* does not match, or a `null` that blocks it. An `exports` of `null` is no
|
|
41
|
+
* `exports` field, as Node reads it.
|
|
42
|
+
* @param {unknown} exportsField
|
|
43
|
+
* @param {string} subpath `.` or `./…`
|
|
44
|
+
* @returns {SubpathDeclaration}
|
|
45
|
+
*/
|
|
46
|
+
export function subpathDeclaration(exportsField: unknown, subpath: string): SubpathDeclaration;
|
|
47
|
+
export type SubpathDeclaration = {
|
|
48
|
+
state: "declared" | "no_exports" | "root_only" | "missing" | "blocked" | "not_importable";
|
|
49
|
+
/**
|
|
50
|
+
* the matched export value
|
|
51
|
+
*/
|
|
52
|
+
value?: unknown;
|
|
53
|
+
/**
|
|
54
|
+
* what a `*` key matched
|
|
55
|
+
*/
|
|
56
|
+
wildcard?: string | undefined;
|
|
57
|
+
};
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file How a package.json `exports` field declares a subpath, read without
|
|
5
|
+
* touching the targets (which may be build output that does not exist yet).
|
|
6
|
+
*
|
|
7
|
+
* @input A package.json `exports` value and a `.`/`./…` subpath.
|
|
8
|
+
* @output Whether the subpath is declared for an ES module importer, and why
|
|
9
|
+
* not when it is not.
|
|
10
|
+
* @position foundation/integrations; read by the public-import checks.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/** @param {unknown} value @returns {value is Record<string, unknown>} */
|
|
14
|
+
export function isRecord(value) {
|
|
15
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Whether an export value gives an ES module importer something: a string,
|
|
20
|
+
* or a condition object / fallback array with a target under a condition
|
|
21
|
+
* other than `require` and `types`.
|
|
22
|
+
* @param {unknown} value
|
|
23
|
+
* @returns {boolean}
|
|
24
|
+
*/
|
|
25
|
+
export function importable(value) {
|
|
26
|
+
if (typeof value === 'string') return true;
|
|
27
|
+
if (Array.isArray(value)) return value.some(importable);
|
|
28
|
+
if (!isRecord(value)) return false;
|
|
29
|
+
return Object.entries(value).some(
|
|
30
|
+
([condition, target]) =>
|
|
31
|
+
condition !== 'require' && condition !== 'types' && importable(target),
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Every string target an export value names, any condition.
|
|
37
|
+
* @param {unknown} value
|
|
38
|
+
* @param {string[]} [out]
|
|
39
|
+
* @returns {string[]}
|
|
40
|
+
*/
|
|
41
|
+
export function allTargets(value, out = []) {
|
|
42
|
+
if (typeof value === 'string') out.push(value);
|
|
43
|
+
else if (Array.isArray(value)) for (const v of value) allTargets(v, out);
|
|
44
|
+
else if (isRecord(value))
|
|
45
|
+
for (const v of Object.values(value)) allTargets(v, out);
|
|
46
|
+
return out;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* @typedef {object} SubpathDeclaration
|
|
51
|
+
* @property {'declared'|'no_exports'|'root_only'|'missing'|'blocked'|'not_importable'} state
|
|
52
|
+
* @property {unknown} [value] the matched export value
|
|
53
|
+
* @property {string} [wildcard] what a `*` key matched
|
|
54
|
+
*/
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* How a package's `exports` field declares one subpath, without touching the
|
|
58
|
+
* targets: a missing key, a key with only a `require` condition, an `exports`
|
|
59
|
+
* that is a bare string or a condition object (so only `.`), a wildcard that
|
|
60
|
+
* does not match, or a `null` that blocks it. An `exports` of `null` is no
|
|
61
|
+
* `exports` field, as Node reads it.
|
|
62
|
+
* @param {unknown} exportsField
|
|
63
|
+
* @param {string} subpath `.` or `./…`
|
|
64
|
+
* @returns {SubpathDeclaration}
|
|
65
|
+
*/
|
|
66
|
+
export function subpathDeclaration(exportsField, subpath) {
|
|
67
|
+
if (exportsField == null) return {state: 'no_exports'};
|
|
68
|
+
const keys = isRecord(exportsField) ? Object.keys(exportsField) : [];
|
|
69
|
+
// An empty object is a subpath map with no keys: it exports nothing, so
|
|
70
|
+
// every subpath (the root too) is missing from it.
|
|
71
|
+
const isMap =
|
|
72
|
+
isRecord(exportsField) && keys.every(key => key.startsWith('.'));
|
|
73
|
+
if (!isMap) {
|
|
74
|
+
if (subpath !== '.') return {state: 'root_only'};
|
|
75
|
+
return importable(exportsField)
|
|
76
|
+
? {state: 'declared', value: exportsField}
|
|
77
|
+
: {state: 'not_importable', value: exportsField};
|
|
78
|
+
}
|
|
79
|
+
const map = /** @type {Record<string, unknown>} */ (exportsField);
|
|
80
|
+
/** @type {{value: unknown, wildcard: string} | null} */
|
|
81
|
+
let hit = null;
|
|
82
|
+
if (Object.hasOwn(map, subpath)) {
|
|
83
|
+
hit = {value: map[subpath], wildcard: ''};
|
|
84
|
+
} else {
|
|
85
|
+
const patterns = keys
|
|
86
|
+
.filter(key => key.split('*').length === 2)
|
|
87
|
+
.sort((a, b) => b.indexOf('*') - a.indexOf('*') || b.length - a.length);
|
|
88
|
+
for (const pattern of patterns) {
|
|
89
|
+
const star = pattern.indexOf('*');
|
|
90
|
+
const prefix = pattern.slice(0, star);
|
|
91
|
+
const suffix = pattern.slice(star + 1);
|
|
92
|
+
if (
|
|
93
|
+
subpath.length >= prefix.length + suffix.length &&
|
|
94
|
+
subpath.startsWith(prefix) &&
|
|
95
|
+
subpath.endsWith(suffix)
|
|
96
|
+
) {
|
|
97
|
+
hit = {
|
|
98
|
+
value: map[pattern],
|
|
99
|
+
wildcard: subpath.slice(
|
|
100
|
+
prefix.length,
|
|
101
|
+
subpath.length - suffix.length,
|
|
102
|
+
),
|
|
103
|
+
};
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
if (!hit) return {state: 'missing'};
|
|
109
|
+
if (hit.value == null) return {state: 'blocked'};
|
|
110
|
+
if (!importable(hit.value))
|
|
111
|
+
return {state: 'not_importable', value: hit.value, wildcard: hit.wildcard};
|
|
112
|
+
return {state: 'declared', value: hit.value, wildcard: hit.wildcard};
|
|
113
|
+
}
|
|
@@ -45,13 +45,14 @@ export function findManifestPaths(dir: string): string[];
|
|
|
45
45
|
* @param {string} file absolute manifest path
|
|
46
46
|
* @param {string} [label] used in error messages
|
|
47
47
|
* @param {{fresh?: boolean}} [options]
|
|
48
|
-
* @returns {Promise<{manifest: import('../../authoring/integration/type').AstryxIntegration, unknownKeys: string[], debug?: import('../../authoring/debug/type').DebugEventHandler, gapReport?: import('../../authoring/gap-report/type').GapReportHandler, gapReportError?: string, discover?: import('../../authoring/discover/type').DiscoverSource, discoverError?: string, agentDocsError?: string, cliCommandError?: string}>}
|
|
48
|
+
* @returns {Promise<{manifest: import('../../authoring/integration/type').AstryxIntegration, unknownKeys: string[], declaredKeys: string[], debug?: import('../../authoring/debug/type').DebugEventHandler, gapReport?: import('../../authoring/gap-report/type').GapReportHandler, gapReportError?: string, discover?: import('../../authoring/discover/type').DiscoverSource, discoverError?: string, agentDocsError?: string, cliCommandError?: string}>}
|
|
49
49
|
*/
|
|
50
50
|
export function loadManifest(file: string, label?: string, { fresh }?: {
|
|
51
51
|
fresh?: boolean;
|
|
52
52
|
}): Promise<{
|
|
53
53
|
manifest: import("../../authoring/integration/type").AstryxIntegration;
|
|
54
54
|
unknownKeys: string[];
|
|
55
|
+
declaredKeys: string[];
|
|
55
56
|
debug?: import("../../authoring/debug/type").DebugEventHandler;
|
|
56
57
|
gapReport?: import("../../authoring/gap-report/type").GapReportHandler;
|
|
57
58
|
gapReportError?: string;
|
|
@@ -79,6 +80,17 @@ export function loadManifestObject(file: string, label?: string, options?: {
|
|
|
79
80
|
* @param {string} [cwd]
|
|
80
81
|
*/
|
|
81
82
|
export function resolvePackageDir(packageName: string, cwd?: string): string;
|
|
83
|
+
/**
|
|
84
|
+
* Where an integration named in astryx.config is installed: the nearest
|
|
85
|
+
* `node_modules/<name>` at or above `cwd`, found the way an autolinked
|
|
86
|
+
* dependency is, so a package a workspace hoists to its root loads in every
|
|
87
|
+
* member. When it is installed nowhere, `cwd`'s own `node_modules/<name>`,
|
|
88
|
+
* which the caller reports as not installed.
|
|
89
|
+
* @param {string} packageName
|
|
90
|
+
* @param {string} [cwd]
|
|
91
|
+
* @returns {string}
|
|
92
|
+
*/
|
|
93
|
+
export function resolveInstalledIntegrationDir(packageName: string, cwd?: string): string;
|
|
82
94
|
/**
|
|
83
95
|
* Load the integration package rooted at `packageDir` directly, without first
|
|
84
96
|
* installing or publishing it. This is the self-resolution seam: an author in
|
|
@@ -134,6 +146,8 @@ export function loadIntegrations(specs?: string[], { cwd, fresh, resolveProvider
|
|
|
134
146
|
* @property {string} [__agentDocsError] contribution-specific validation
|
|
135
147
|
* failure; other manifest contributions remain available
|
|
136
148
|
* @property {string} __spec
|
|
149
|
+
* @property {string} [__declaredProviderId] the manifest's `providerId` as
|
|
150
|
+
* written, kept by validation so it can tell whether the package has one
|
|
137
151
|
* @property {string} __packageDir
|
|
138
152
|
* @property {Record<string, unknown>|null} [__packageExports] the owning
|
|
139
153
|
* package's `exports` map, kept from the package.json this loader already
|
|
@@ -145,6 +159,8 @@ export function loadIntegrations(specs?: string[], { cwd, fresh, resolveProvider
|
|
|
145
159
|
* set on a package whose provider ID an earlier-loaded package already
|
|
146
160
|
* claims; it contributes nothing and is reported as a `duplicate_provider`
|
|
147
161
|
* warning
|
|
162
|
+
* @property {string[]} [__declaredKeys] the keys the manifest object itself
|
|
163
|
+
* declares, before any is filled in (providerId from the package name)
|
|
148
164
|
* @property {string[]} [__unknownKeys] manifest keys this CLI does not know —
|
|
149
165
|
* surfaced as a warning; the rest of the manifest still contributes
|
|
150
166
|
* @property {boolean} [__autolinked] loaded because the project declares the
|
|
@@ -210,6 +226,11 @@ export type LoadedIntegration = {
|
|
|
210
226
|
*/
|
|
211
227
|
__agentDocsError?: string | undefined;
|
|
212
228
|
__spec: string;
|
|
229
|
+
/**
|
|
230
|
+
* the manifest's `providerId` as
|
|
231
|
+
* written, kept by validation so it can tell whether the package has one
|
|
232
|
+
*/
|
|
233
|
+
__declaredProviderId?: string | undefined;
|
|
213
234
|
__packageDir: string;
|
|
214
235
|
/**
|
|
215
236
|
* the owning
|
|
@@ -233,6 +254,11 @@ export type LoadedIntegration = {
|
|
|
233
254
|
claimedBy: string;
|
|
234
255
|
message: string;
|
|
235
256
|
} | undefined;
|
|
257
|
+
/**
|
|
258
|
+
* the keys the manifest object itself
|
|
259
|
+
* declares, before any is filled in (providerId from the package name)
|
|
260
|
+
*/
|
|
261
|
+
__declaredKeys?: string[] | undefined;
|
|
236
262
|
/**
|
|
237
263
|
* manifest keys this CLI does not know —
|
|
238
264
|
* surfaced as a warning; the rest of the manifest still contributes
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
import * as fs from 'node:fs';
|
|
20
20
|
import * as path from 'node:path';
|
|
21
21
|
import {assertWithin} from '../fs/path-safety.mjs';
|
|
22
|
+
import {findNodeModulesPackage} from '../fs/paths.mjs';
|
|
22
23
|
import {normalizeProviderId} from '../identity/provider-identity.mjs';
|
|
23
24
|
// The key census and contribution parsers are internal to the schema module on
|
|
24
25
|
// purpose: the public parser still validates the complete authored type, while
|
|
@@ -60,6 +61,8 @@ import {resolveProviders} from './provider-resolution.mjs';
|
|
|
60
61
|
* @property {string} [__agentDocsError] contribution-specific validation
|
|
61
62
|
* failure; other manifest contributions remain available
|
|
62
63
|
* @property {string} __spec
|
|
64
|
+
* @property {string} [__declaredProviderId] the manifest's `providerId` as
|
|
65
|
+
* written, kept by validation so it can tell whether the package has one
|
|
63
66
|
* @property {string} __packageDir
|
|
64
67
|
* @property {Record<string, unknown>|null} [__packageExports] the owning
|
|
65
68
|
* package's `exports` map, kept from the package.json this loader already
|
|
@@ -71,6 +74,8 @@ import {resolveProviders} from './provider-resolution.mjs';
|
|
|
71
74
|
* set on a package whose provider ID an earlier-loaded package already
|
|
72
75
|
* claims; it contributes nothing and is reported as a `duplicate_provider`
|
|
73
76
|
* warning
|
|
77
|
+
* @property {string[]} [__declaredKeys] the keys the manifest object itself
|
|
78
|
+
* declares, before any is filled in (providerId from the package name)
|
|
74
79
|
* @property {string[]} [__unknownKeys] manifest keys this CLI does not know —
|
|
75
80
|
* surfaced as a warning; the rest of the manifest still contributes
|
|
76
81
|
* @property {boolean} [__autolinked] loaded because the project declares the
|
|
@@ -213,7 +218,7 @@ function parseDiscoverSourceExport(value, label) {
|
|
|
213
218
|
* @param {string} file absolute manifest path
|
|
214
219
|
* @param {string} [label] used in error messages
|
|
215
220
|
* @param {{fresh?: boolean}} [options]
|
|
216
|
-
* @returns {Promise<{manifest: import('../../authoring/integration/type').AstryxIntegration, unknownKeys: string[], debug?: import('../../authoring/debug/type').DebugEventHandler, gapReport?: import('../../authoring/gap-report/type').GapReportHandler, gapReportError?: string, discover?: import('../../authoring/discover/type').DiscoverSource, discoverError?: string, agentDocsError?: string, cliCommandError?: string}>}
|
|
221
|
+
* @returns {Promise<{manifest: import('../../authoring/integration/type').AstryxIntegration, unknownKeys: string[], declaredKeys: string[], debug?: import('../../authoring/debug/type').DebugEventHandler, gapReport?: import('../../authoring/gap-report/type').GapReportHandler, gapReportError?: string, discover?: import('../../authoring/discover/type').DiscoverSource, discoverError?: string, agentDocsError?: string, cliCommandError?: string}>}
|
|
217
222
|
*/
|
|
218
223
|
export async function loadManifest(
|
|
219
224
|
file,
|
|
@@ -222,6 +227,7 @@ export async function loadManifest(
|
|
|
222
227
|
) {
|
|
223
228
|
const mod = await importUserModule(file, {fresh});
|
|
224
229
|
const raw = mod?.default;
|
|
230
|
+
if (raw === undefined) throw new Error(noDefaultExportMessage(file, label, mod));
|
|
225
231
|
const baseManifest = parseIntegrationBase(raw, label);
|
|
226
232
|
const gapReport = parseGapReportHandlerExport(mod?.gapReport, label);
|
|
227
233
|
const discover = parseDiscoverSourceExport(mod?.discover, label);
|
|
@@ -274,6 +280,8 @@ export async function loadManifest(
|
|
|
274
280
|
...(cliCommand == null ? {} : {cliCommand}),
|
|
275
281
|
},
|
|
276
282
|
unknownKeys: unknownIntegrationKeys(raw),
|
|
283
|
+
declaredKeys:
|
|
284
|
+
raw != null && typeof raw === 'object' ? Object.keys(raw) : [],
|
|
277
285
|
debug:
|
|
278
286
|
typeof mod?.debug === 'function'
|
|
279
287
|
? /** @type {import('../../authoring/debug/type').DebugEventHandler} */ (
|
|
@@ -289,6 +297,30 @@ export async function loadManifest(
|
|
|
289
297
|
};
|
|
290
298
|
}
|
|
291
299
|
|
|
300
|
+
/**
|
|
301
|
+
* Why a manifest has no default export, said plainly instead of as a schema
|
|
302
|
+
* failure on `undefined`: the file is empty, or it exports other names.
|
|
303
|
+
* @param {string} file
|
|
304
|
+
* @param {string} label
|
|
305
|
+
* @param {Record<string, unknown> | undefined} mod
|
|
306
|
+
*/
|
|
307
|
+
function noDefaultExportMessage(file, label, mod) {
|
|
308
|
+
const fix = `Fix: export the manifest object as the default export: \`export default {components: './components'}\`, naming the roots the package has.`;
|
|
309
|
+
let text = '';
|
|
310
|
+
try {
|
|
311
|
+
text = fs.readFileSync(file, 'utf8');
|
|
312
|
+
} catch {
|
|
313
|
+
// Unreadable now: say only what is missing.
|
|
314
|
+
}
|
|
315
|
+
const names = Object.keys(mod ?? {}).filter(name => name !== 'default');
|
|
316
|
+
if (text.trim() === '') return `${label} is empty. ${fix}`;
|
|
317
|
+
const found =
|
|
318
|
+
names.length > 0
|
|
319
|
+
? ` (it exports ${names.map(name => `\`${name}\``).join(', ')})`
|
|
320
|
+
: '';
|
|
321
|
+
return `${label} has no default export${found}. ${fix}`;
|
|
322
|
+
}
|
|
323
|
+
|
|
292
324
|
/**
|
|
293
325
|
* Load and validate a manifest module's default export against the integration
|
|
294
326
|
* schema. Throws if the default export is missing or invalid. Exposed for
|
|
@@ -337,6 +369,25 @@ export function resolvePackageDir(packageName, cwd = process.cwd()) {
|
|
|
337
369
|
return dir;
|
|
338
370
|
}
|
|
339
371
|
|
|
372
|
+
/**
|
|
373
|
+
* Where an integration named in astryx.config is installed: the nearest
|
|
374
|
+
* `node_modules/<name>` at or above `cwd`, found the way an autolinked
|
|
375
|
+
* dependency is, so a package a workspace hoists to its root loads in every
|
|
376
|
+
* member. When it is installed nowhere, `cwd`'s own `node_modules/<name>`,
|
|
377
|
+
* which the caller reports as not installed.
|
|
378
|
+
* @param {string} packageName
|
|
379
|
+
* @param {string} [cwd]
|
|
380
|
+
* @returns {string}
|
|
381
|
+
*/
|
|
382
|
+
export function resolveInstalledIntegrationDir(
|
|
383
|
+
packageName,
|
|
384
|
+
cwd = process.cwd(),
|
|
385
|
+
) {
|
|
386
|
+
// Validates the name first: it throws on a spec with path segments.
|
|
387
|
+
const ownDir = resolvePackageDir(packageName, cwd);
|
|
388
|
+
return findNodeModulesPackage(cwd, packageName)?.packageDir ?? ownDir;
|
|
389
|
+
}
|
|
390
|
+
|
|
340
391
|
/**
|
|
341
392
|
* Find the single conventional root manifest sibling of the package's
|
|
342
393
|
* package.json. Multiple present is a hard error; missing is a hard error.
|
|
@@ -396,6 +447,8 @@ export async function loadLocalIntegration(packageDir, {fresh = false} = {}) {
|
|
|
396
447
|
let manifest;
|
|
397
448
|
/** @type {string[]} */
|
|
398
449
|
let unknownKeys;
|
|
450
|
+
/** @type {string[]} */
|
|
451
|
+
let declaredKeys;
|
|
399
452
|
/** @type {import('../../authoring/debug/type').DebugEventHandler | undefined} */
|
|
400
453
|
let debugHandler;
|
|
401
454
|
/** @type {import('../../authoring/gap-report/type').GapReportHandler | undefined} */
|
|
@@ -414,6 +467,7 @@ export async function loadLocalIntegration(packageDir, {fresh = false} = {}) {
|
|
|
414
467
|
({
|
|
415
468
|
manifest,
|
|
416
469
|
unknownKeys,
|
|
470
|
+
declaredKeys,
|
|
417
471
|
debug: debugHandler,
|
|
418
472
|
gapReport: gapReportHandler,
|
|
419
473
|
gapReportError,
|
|
@@ -462,6 +516,7 @@ export async function loadLocalIntegration(packageDir, {fresh = false} = {}) {
|
|
|
462
516
|
__cliCommandError: cliCommandError,
|
|
463
517
|
__agentDocsError: agentDocsError,
|
|
464
518
|
__unknownKeys: unknownKeys,
|
|
519
|
+
__declaredKeys: declaredKeys,
|
|
465
520
|
__debug: debugHandler,
|
|
466
521
|
__gapReport: gapReportHandler,
|
|
467
522
|
__gapReportError: gapReportError,
|
|
@@ -496,7 +551,7 @@ export async function loadIntegrations(
|
|
|
496
551
|
if (!spec || seenSpecs.has(spec)) continue;
|
|
497
552
|
seenSpecs.add(spec);
|
|
498
553
|
|
|
499
|
-
const packageDir =
|
|
554
|
+
const packageDir = resolveInstalledIntegrationDir(spec, cwd);
|
|
500
555
|
const pkgPath = path.join(packageDir, 'package.json');
|
|
501
556
|
let pkg;
|
|
502
557
|
try {
|
|
@@ -512,6 +567,8 @@ export async function loadIntegrations(
|
|
|
512
567
|
let manifest;
|
|
513
568
|
/** @type {string[]} */
|
|
514
569
|
let unknownKeys;
|
|
570
|
+
/** @type {string[]} */
|
|
571
|
+
let declaredKeys;
|
|
515
572
|
/** @type {import('../../authoring/debug/type').DebugEventHandler | undefined} */
|
|
516
573
|
let debugHandler;
|
|
517
574
|
/** @type {import('../../authoring/gap-report/type').GapReportHandler | undefined} */
|
|
@@ -530,6 +587,7 @@ export async function loadIntegrations(
|
|
|
530
587
|
({
|
|
531
588
|
manifest,
|
|
532
589
|
unknownKeys,
|
|
590
|
+
declaredKeys,
|
|
533
591
|
debug: debugHandler,
|
|
534
592
|
gapReport: gapReportHandler,
|
|
535
593
|
gapReportError,
|
|
@@ -585,6 +643,7 @@ export async function loadIntegrations(
|
|
|
585
643
|
__cliCommandError: cliCommandError,
|
|
586
644
|
__agentDocsError: agentDocsError,
|
|
587
645
|
__unknownKeys: unknownKeys,
|
|
646
|
+
__declaredKeys: declaredKeys,
|
|
588
647
|
__debug: debugHandler,
|
|
589
648
|
__gapReport: gapReportHandler,
|
|
590
649
|
__gapReportError: gapReportError,
|