@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
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
*/
|
|
11
11
|
export function validateLocalIntegration(cwd?: string): Promise<ValidateResult>;
|
|
12
12
|
/**
|
|
13
|
-
* Validate an INSTALLED integration package
|
|
13
|
+
* Validate an INSTALLED integration package: the nearest `node_modules/<spec>`
|
|
14
|
+
* at or above `cwd`, resolved the way the project loads it.
|
|
14
15
|
* @param {string} spec package name
|
|
15
16
|
* @param {string} [cwd]
|
|
16
17
|
* @returns {Promise<ValidateResult>}
|
|
@@ -43,7 +44,6 @@ export function summarizeIssues(issues: Issue[]): {
|
|
|
43
44
|
errors: number;
|
|
44
45
|
warnings: number;
|
|
45
46
|
};
|
|
46
|
-
export { validateLoadedIntegration };
|
|
47
47
|
export type Issue = import("../../foundation/integrations/issue").AstryxIntegrationIssue;
|
|
48
48
|
export type ValidateResult = {
|
|
49
49
|
/**
|
|
@@ -75,6 +75,19 @@ export type ValidateResult = {
|
|
|
75
75
|
code: string;
|
|
76
76
|
message: string;
|
|
77
77
|
}[] | undefined;
|
|
78
|
+
/**
|
|
79
|
+
* Layout findings added after the last minor
|
|
80
|
+
* release: validate lists them as notes, which count nowhere, since they
|
|
81
|
+
* may not fail `--strict` until the next (architecture:cli-surface INV35);
|
|
82
|
+
* `integration verify` still fails on a package.json npm cannot pack.
|
|
83
|
+
*/
|
|
84
|
+
listed?: import("../../foundation/integrations/issue").AstryxIntegrationIssue[] | undefined;
|
|
78
85
|
integration?: import("../../foundation/integrations/integrations.mjs").LoadedIntegration | undefined;
|
|
86
|
+
/**
|
|
87
|
+
* what the public-import check could not judge
|
|
88
|
+
*/
|
|
89
|
+
publicImports?: import("./validate-integration.type.mjs").PublicImportsReport | undefined;
|
|
79
90
|
};
|
|
80
91
|
import { validateLoadedIntegration } from '../../foundation/integrations/validate-contributions.mjs';
|
|
92
|
+
import { isListedIssue } from '../../foundation/integrations/validate-contributions.mjs';
|
|
93
|
+
export { validateLoadedIntegration, isListedIssue };
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* - validateLocalIntegration(cwd) — the package rooted at `cwd` (nearest
|
|
13
13
|
* package.json + sibling astryx.integration.{ts,mjs,js}).
|
|
14
14
|
* - validateInstalledIntegration(spec, cwd) — an installed package resolved
|
|
15
|
-
* from `cwd
|
|
15
|
+
* from the node_modules chain at or above `cwd`.
|
|
16
16
|
*
|
|
17
17
|
* Both return a { found, name, version, manifestFile, issues } result. `found`
|
|
18
18
|
* is false only for the no-manifest local case, which is guidance (not an
|
|
@@ -34,8 +34,10 @@
|
|
|
34
34
|
import * as fs from 'node:fs';
|
|
35
35
|
import * as path from 'node:path';
|
|
36
36
|
import {assertWithin} from '../../foundation/fs/path-safety.mjs';
|
|
37
|
+
import {normalizeProviderId} from '../../foundation/identity/provider-identity.mjs';
|
|
37
38
|
import {integrationDocTypes} from '../docs/_adapter.mjs';
|
|
38
39
|
import {integrationDocConsistency} from '../../foundation/discovery/doc-consistency.mjs';
|
|
40
|
+
import {integrationRunnerCommands} from './_adapter.mjs';
|
|
39
41
|
import {
|
|
40
42
|
THEME_SLUG_RE,
|
|
41
43
|
unreadThemeFolders,
|
|
@@ -51,20 +53,31 @@ import {
|
|
|
51
53
|
import {
|
|
52
54
|
findManifestPaths,
|
|
53
55
|
loadManifest,
|
|
54
|
-
|
|
56
|
+
resolveInstalledIntegrationDir,
|
|
55
57
|
} from '../../foundation/integrations/integrations.mjs';
|
|
56
58
|
// The on-disk contribution validators live in foundation: Project and
|
|
57
59
|
// integration-warnings need them too, and foundation must not depend on api.
|
|
58
60
|
import {
|
|
61
|
+
blockComponentsCheck,
|
|
62
|
+
componentDocNamesCheck,
|
|
59
63
|
INVALID_CLI_COMMAND,
|
|
64
|
+
isListedIssue,
|
|
65
|
+
issueListed as listed,
|
|
60
66
|
validateLoadedIntegration,
|
|
67
|
+
validateLoadedIntegrationListed,
|
|
61
68
|
issueError as error,
|
|
62
69
|
issueWarning as warning,
|
|
63
70
|
rootProblem,
|
|
64
71
|
} from '../../foundation/integrations/validate-contributions.mjs';
|
|
65
72
|
import {formatCliCommand} from '../../foundation/env/package-manager.mjs';
|
|
73
|
+
import {cliPeerVersionProblem} from '../../foundation/integrations/cli-peer-version.mjs';
|
|
74
|
+
import {publicImportIssues} from '../../foundation/integrations/public-imports.mjs';
|
|
75
|
+
import {runChoice} from '../../foundation/release/run-context.mjs';
|
|
66
76
|
|
|
67
|
-
|
|
77
|
+
/** The running CLI is outside the package's `@astryxdesign/cli` peer range. */
|
|
78
|
+
const CLI_PEER_VERSION = 'cli_peer_version';
|
|
79
|
+
|
|
80
|
+
export {validateLoadedIntegration, isListedIssue};
|
|
68
81
|
|
|
69
82
|
/**
|
|
70
83
|
* @typedef {import('../../foundation/integrations/issue').AstryxIntegrationIssue} Issue
|
|
@@ -80,7 +93,13 @@ export {validateLoadedIntegration};
|
|
|
80
93
|
* @property {Issue[]} issues
|
|
81
94
|
* @property {Array<{code: string, message: string}>} [notes] Information that
|
|
82
95
|
* fails nothing, such as `invalid_cli_command` (a malformed `cliCommand`).
|
|
96
|
+
* @property {Issue[]} [listed] Layout findings added after the last minor
|
|
97
|
+
* release: validate lists them as notes, which count nowhere, since they
|
|
98
|
+
* may not fail `--strict` until the next (architecture:cli-surface INV35);
|
|
99
|
+
* `integration verify` still fails on a package.json npm cannot pack.
|
|
83
100
|
* @property {import('../../foundation/integrations/integrations.mjs').LoadedIntegration} [integration]
|
|
101
|
+
* @property {import('./validate-integration.type.mjs').PublicImportsReport} [publicImports]
|
|
102
|
+
* what the public-import check could not judge
|
|
84
103
|
*/
|
|
85
104
|
|
|
86
105
|
/**
|
|
@@ -99,6 +118,14 @@ function findNearestPackageJson(cwd) {
|
|
|
99
118
|
}
|
|
100
119
|
}
|
|
101
120
|
|
|
121
|
+
const ROOT_KINDS = /** @type {const} */ ([
|
|
122
|
+
'components',
|
|
123
|
+
'templates',
|
|
124
|
+
'codemods',
|
|
125
|
+
'docs',
|
|
126
|
+
'themes',
|
|
127
|
+
]);
|
|
128
|
+
|
|
102
129
|
const UNREACHABLE_SCAN_LIMIT = 5_000;
|
|
103
130
|
const UNREACHABLE_SKIP_DIRS = new Set([
|
|
104
131
|
'node_modules',
|
|
@@ -148,27 +175,51 @@ function unreadThemeFolderIssues(packageDir, loaded) {
|
|
|
148
175
|
*
|
|
149
176
|
* @param {string} packageDir
|
|
150
177
|
* @param {import('../../foundation/integrations/integrations.mjs').LoadedIntegration} loaded
|
|
178
|
+
* @param {string[]} [reported] folders whose files another issue already covers
|
|
151
179
|
* @returns {Promise<Issue[]>}
|
|
152
180
|
*/
|
|
153
|
-
async function findUnreachableContributionIssues(
|
|
181
|
+
async function findUnreachableContributionIssues(
|
|
182
|
+
packageDir,
|
|
183
|
+
loaded,
|
|
184
|
+
reported = [],
|
|
185
|
+
) {
|
|
186
|
+
// A root that is not a readable folder holds nothing: a fix must never
|
|
187
|
+
// send a file into it.
|
|
188
|
+
const usable = {...loaded};
|
|
189
|
+
for (const kind of ROOT_KINDS) {
|
|
190
|
+
const root = usable[kind];
|
|
191
|
+
if (root != null && rootProblem(root)) usable[kind] = undefined;
|
|
192
|
+
}
|
|
193
|
+
// Every declared root is skipped, readable or not: one that cannot be read
|
|
194
|
+
// has its own issue.
|
|
154
195
|
const roots = /** @type {string[]} */ (
|
|
155
|
-
[
|
|
156
|
-
loaded.components,
|
|
157
|
-
loaded.templates,
|
|
158
|
-
loaded.codemods,
|
|
159
|
-
loaded.docs,
|
|
160
|
-
loaded.themes,
|
|
161
|
-
].filter(Boolean)
|
|
196
|
+
ROOT_KINDS.map(kind => loaded[kind]).filter(Boolean)
|
|
162
197
|
);
|
|
198
|
+
// A folder a symlinked root points at is read through that root.
|
|
199
|
+
const realRoots = roots.map(root => {
|
|
200
|
+
try {
|
|
201
|
+
return fs.realpathSync(root);
|
|
202
|
+
} catch {
|
|
203
|
+
return root;
|
|
204
|
+
}
|
|
205
|
+
});
|
|
163
206
|
/** @type {Issue[]} */
|
|
164
207
|
const issues = [];
|
|
165
|
-
const context = createFixContext(packageDir,
|
|
208
|
+
const context = createFixContext(packageDir, usable);
|
|
166
209
|
let scanned = 0;
|
|
167
210
|
let truncated = false;
|
|
168
211
|
|
|
169
212
|
/** @param {string} dir */
|
|
170
213
|
async function walk(dir) {
|
|
171
214
|
if (roots.some(root => pathIsInside(dir, root))) return;
|
|
215
|
+
if (reported.some(folder => pathIsInside(dir, folder))) return;
|
|
216
|
+
let realDir = dir;
|
|
217
|
+
try {
|
|
218
|
+
realDir = fs.realpathSync(dir);
|
|
219
|
+
} catch {
|
|
220
|
+
// Unreadable: reported below.
|
|
221
|
+
}
|
|
222
|
+
if (realRoots.some(root => pathIsInside(realDir, root))) return;
|
|
172
223
|
let entries;
|
|
173
224
|
try {
|
|
174
225
|
entries = fs
|
|
@@ -235,13 +286,15 @@ async function findUnreachableContributionIssues(packageDir, loaded) {
|
|
|
235
286
|
* Shared core for the local and installed entry points.
|
|
236
287
|
* @param {string} packageDir
|
|
237
288
|
* @param {{name: string, version?: string}} identity
|
|
238
|
-
* @param {{scanUnreachable?: boolean}} [options]
|
|
289
|
+
* @param {{scanUnreachable?: boolean, own?: boolean, cwd?: string}} [options]
|
|
290
|
+
* `own`: the package is the one being authored in the current folder;
|
|
291
|
+
* `cwd`: the folder whose package manager an install command names
|
|
239
292
|
* @returns {Promise<ValidateResult>}
|
|
240
293
|
*/
|
|
241
294
|
async function validateAtPackageDir(
|
|
242
295
|
packageDir,
|
|
243
296
|
identity,
|
|
244
|
-
{scanUnreachable = false} = {},
|
|
297
|
+
{scanUnreachable = false, own = false, cwd = packageDir} = {},
|
|
245
298
|
) {
|
|
246
299
|
/** @type {Issue[]} */
|
|
247
300
|
const issues = [];
|
|
@@ -286,12 +339,14 @@ async function validateAtPackageDir(
|
|
|
286
339
|
let manifest;
|
|
287
340
|
/** @type {string[]} */
|
|
288
341
|
let unknownKeys;
|
|
342
|
+
/** @type {string[]} */
|
|
343
|
+
let declaredKeys;
|
|
289
344
|
/** @type {string | undefined} */
|
|
290
345
|
let agentDocsError;
|
|
291
346
|
/** @type {string | undefined} */
|
|
292
347
|
let cliCommandError;
|
|
293
348
|
try {
|
|
294
|
-
({manifest, unknownKeys, agentDocsError, cliCommandError} =
|
|
349
|
+
({manifest, unknownKeys, declaredKeys, agentDocsError, cliCommandError} =
|
|
295
350
|
await loadManifest(
|
|
296
351
|
manifestFile,
|
|
297
352
|
`Integration manifest (${path.basename(manifestFile)})`,
|
|
@@ -301,9 +356,36 @@ async function validateAtPackageDir(
|
|
|
301
356
|
return result;
|
|
302
357
|
}
|
|
303
358
|
|
|
304
|
-
/** @
|
|
305
|
-
const
|
|
359
|
+
/** @type {string[]} absolute roots inside the package */
|
|
360
|
+
const absoluteRoots = [];
|
|
361
|
+
/**
|
|
362
|
+
* @param {string | null | undefined} value
|
|
363
|
+
* @param {string} key the manifest key that declares it
|
|
364
|
+
*/
|
|
365
|
+
const resolveRoot = (value, key, kind = 'contribution root') => {
|
|
306
366
|
if (value == null) return undefined;
|
|
367
|
+
if (path.isAbsolute(value)) {
|
|
368
|
+
// An absolute root names this machine's disk, which no install shares,
|
|
369
|
+
// even when it happens to point inside the package.
|
|
370
|
+
const inside = path.relative(packageDir, value);
|
|
371
|
+
const relative =
|
|
372
|
+
inside === '' || (!inside.startsWith('..') && !path.isAbsolute(inside))
|
|
373
|
+
? `./${inside.split(path.sep).join('/')}`.replace(/\/$/u, '')
|
|
374
|
+
: null;
|
|
375
|
+
// The code an absolute root has always carried, reworded.
|
|
376
|
+
result.issues.push(
|
|
377
|
+
error(
|
|
378
|
+
'root_outside_package',
|
|
379
|
+
`The ${key} root "${value}" is an absolute path, so Astryx reads nothing from it: a root is relative to the package, so it resolves the same wherever the package is installed.` +
|
|
380
|
+
(relative
|
|
381
|
+
? ` Fix: set \`${key}: '${relative === './' ? '.' : relative}'\` in ${path.basename(manifestFile)}.`
|
|
382
|
+
: ` It also points outside the package. Fix: move the files into the package and set \`${key}\` to their folder relative to package.json, such as './${key}'.`),
|
|
383
|
+
),
|
|
384
|
+
);
|
|
385
|
+
// Its files are reported through this issue, not one by one.
|
|
386
|
+
if (relative) absoluteRoots.push(path.resolve(value));
|
|
387
|
+
return undefined;
|
|
388
|
+
}
|
|
307
389
|
try {
|
|
308
390
|
return assertWithin(value, packageDir, {label: kind});
|
|
309
391
|
} catch {
|
|
@@ -320,18 +402,20 @@ async function validateAtPackageDir(
|
|
|
320
402
|
const loaded = {
|
|
321
403
|
name: identity.name,
|
|
322
404
|
version: identity.version,
|
|
323
|
-
components: resolveRoot(manifest.components),
|
|
324
|
-
templates: resolveRoot(manifest.templates),
|
|
325
|
-
codemods: resolveRoot(manifest.codemods),
|
|
326
|
-
docs: resolveRoot(manifest.docs),
|
|
327
|
-
themes: resolveRoot(manifest.themes),
|
|
405
|
+
components: resolveRoot(manifest.components, 'components'),
|
|
406
|
+
templates: resolveRoot(manifest.templates, 'templates'),
|
|
407
|
+
codemods: resolveRoot(manifest.codemods, 'codemods'),
|
|
408
|
+
docs: resolveRoot(manifest.docs, 'docs'),
|
|
409
|
+
themes: resolveRoot(manifest.themes, 'themes'),
|
|
328
410
|
issuesUrl: manifest.issuesUrl,
|
|
329
411
|
agentDocs: manifest.agentDocs,
|
|
330
412
|
cliCommand: manifest.cliCommand,
|
|
331
413
|
__cliCommandError: cliCommandError,
|
|
332
414
|
__agentDocsError: agentDocsError,
|
|
333
415
|
__unknownKeys: unknownKeys,
|
|
416
|
+
__declaredKeys: declaredKeys,
|
|
334
417
|
__spec: identity.name,
|
|
418
|
+
__declaredProviderId: manifest.providerId,
|
|
335
419
|
__packageDir: packageDir,
|
|
336
420
|
__manifestFile: manifestFile,
|
|
337
421
|
};
|
|
@@ -343,13 +427,33 @@ async function validateAtPackageDir(
|
|
|
343
427
|
// `integration check --strict` fails on any warning, and a new failure code
|
|
344
428
|
// joins only in a minor release (architecture:cli-surface INV35). Doctor's
|
|
345
429
|
// project check still warns about it.
|
|
346
|
-
|
|
430
|
+
const contribution = await validateLoadedIntegrationListed(loaded);
|
|
431
|
+
(result.listed ??= []).push(...contribution.listed);
|
|
432
|
+
for (const issue of contribution.issues) {
|
|
347
433
|
if (issue.code === INVALID_CLI_COMMAND) {
|
|
348
434
|
(result.notes ??= []).push({code: issue.code, message: issue.message});
|
|
349
435
|
} else {
|
|
350
436
|
issues.push(issue);
|
|
351
437
|
}
|
|
352
438
|
}
|
|
439
|
+
// The running CLI outside the package's `@astryxdesign/cli` peer range is a
|
|
440
|
+
// note for the same reason. It is built here, not among the contribution
|
|
441
|
+
// checks, so `integration verify` (which reports their layout findings)
|
|
442
|
+
// does not see it.
|
|
443
|
+
// The version an upgrade starts from is the project's: its own CLI's, or,
|
|
444
|
+
// with none, its Core's, as the project-upgrade notice takes it.
|
|
445
|
+
const choice = runChoice(cwd);
|
|
446
|
+
const from =
|
|
447
|
+
choice.inProject && choice.copy === 'starting' && choice.coreVersion
|
|
448
|
+
? choice.coreVersion
|
|
449
|
+
: undefined;
|
|
450
|
+
const peerProblem = cliPeerVersionProblem(loaded, undefined, cwd, {
|
|
451
|
+
own,
|
|
452
|
+
from,
|
|
453
|
+
});
|
|
454
|
+
if (peerProblem) {
|
|
455
|
+
(result.notes ??= []).push({code: CLI_PEER_VERSION, message: peerProblem});
|
|
456
|
+
}
|
|
353
457
|
if (loaded.themes && !rootProblem(loaded.themes))
|
|
354
458
|
issues.push(...unreadThemeFolderIssues(packageDir, loaded));
|
|
355
459
|
// What the docs say that no reader serves: a prop listed twice, an
|
|
@@ -368,9 +472,21 @@ async function validateAtPackageDir(
|
|
|
368
472
|
packageDir,
|
|
369
473
|
)),
|
|
370
474
|
);
|
|
475
|
+
// What the package tells apps to import, read from source: package.json
|
|
476
|
+
// `exports`, docs, examples and template imports.
|
|
477
|
+
const publicImports = await publicImportIssues(packageDir, loaded);
|
|
478
|
+
issues.push(...publicImports.issues);
|
|
479
|
+
// Each finding is a note until the next minor makes it a warning.
|
|
480
|
+
if (publicImports.notes.length > 0)
|
|
481
|
+
(result.notes ??= []).push(...publicImports.notes);
|
|
482
|
+
result.publicImports = publicImports.report;
|
|
371
483
|
if (scanUnreachable) {
|
|
372
484
|
issues.push(
|
|
373
|
-
...(await findUnreachableContributionIssues(
|
|
485
|
+
...(await findUnreachableContributionIssues(
|
|
486
|
+
packageDir,
|
|
487
|
+
loaded,
|
|
488
|
+
absoluteRoots,
|
|
489
|
+
)),
|
|
374
490
|
);
|
|
375
491
|
}
|
|
376
492
|
|
|
@@ -397,7 +513,7 @@ export async function validateLocalIntegration(cwd = process.cwd()) {
|
|
|
397
513
|
return {found: false, issues: []};
|
|
398
514
|
}
|
|
399
515
|
|
|
400
|
-
/** @type {{name?: string, version?: string}} */
|
|
516
|
+
/** @type {{name?: string, version?: string, private?: boolean}} */
|
|
401
517
|
let pkg;
|
|
402
518
|
try {
|
|
403
519
|
pkg = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf-8'));
|
|
@@ -416,31 +532,121 @@ export async function validateLocalIntegration(cwd = process.cwd()) {
|
|
|
416
532
|
};
|
|
417
533
|
}
|
|
418
534
|
|
|
419
|
-
|
|
535
|
+
// npm publishes nothing without a name and a version, and the name is the
|
|
536
|
+
// provider ID every reader keys the package's contributions on.
|
|
537
|
+
// A package without one is still checked, under a placeholder name.
|
|
538
|
+
const fields = packageJsonFieldIssues(pkg, pkgJsonPath);
|
|
539
|
+
const name =
|
|
540
|
+
typeof pkg.name === 'string' && pkg.name !== ''
|
|
541
|
+
? pkg.name
|
|
542
|
+
: '(local package)';
|
|
543
|
+
const result = await validateAtPackageDir(
|
|
420
544
|
packageDir,
|
|
421
|
-
{
|
|
422
|
-
|
|
423
|
-
version: pkg.version,
|
|
424
|
-
},
|
|
425
|
-
{scanUnreachable: true},
|
|
545
|
+
{name, version: pkg.version},
|
|
546
|
+
{scanUnreachable: true, own: true},
|
|
426
547
|
);
|
|
548
|
+
(result.listed ??= []).unshift(
|
|
549
|
+
...fields,
|
|
550
|
+
// Only a manifest that loaded says whether it declares a providerId; one
|
|
551
|
+
// that did not is reported as invalid_manifest.
|
|
552
|
+
...(result.integration
|
|
553
|
+
? providerIdIssues(
|
|
554
|
+
pkg.name,
|
|
555
|
+
result.integration.__declaredProviderId,
|
|
556
|
+
result.integration.__manifestFile,
|
|
557
|
+
)
|
|
558
|
+
: []),
|
|
559
|
+
);
|
|
560
|
+
return result;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
/**
|
|
564
|
+
* Whether `name` is a bare npm package name, the form a provider ID takes.
|
|
565
|
+
* @param {string} name
|
|
566
|
+
*/
|
|
567
|
+
function isPackageName(name) {
|
|
568
|
+
try {
|
|
569
|
+
normalizeProviderId(name);
|
|
570
|
+
return true;
|
|
571
|
+
} catch {
|
|
572
|
+
return false;
|
|
573
|
+
}
|
|
427
574
|
}
|
|
428
575
|
|
|
429
576
|
/**
|
|
430
|
-
*
|
|
577
|
+
* A warning when no provider ID can be derived for the package: its
|
|
578
|
+
* package.json `name` is not a bare package name and its manifest declares
|
|
579
|
+
* no `providerId` that is one. Readers key the package's contributions on
|
|
580
|
+
* that ID; a missing name is its own warning.
|
|
581
|
+
* @param {unknown} name package.json `name`
|
|
582
|
+
* @param {unknown} declared the manifest's `providerId`
|
|
583
|
+
* @param {string} manifestFile
|
|
584
|
+
* @returns {Issue[]}
|
|
585
|
+
*/
|
|
586
|
+
function providerIdIssues(name, declared, manifestFile) {
|
|
587
|
+
if (typeof name !== 'string' || name === '') return [];
|
|
588
|
+
if (isPackageName(name)) return [];
|
|
589
|
+
if (typeof declared === 'string' && isPackageName(declared)) return [];
|
|
590
|
+
const manifest = path.basename(manifestFile);
|
|
591
|
+
return [
|
|
592
|
+
listed(
|
|
593
|
+
'no_provider_id',
|
|
594
|
+
`No provider ID can be derived for this package: package.json "name" ${JSON.stringify(name)} is not a bare package name (an optional @scope/ and a name, each starting with a lowercase letter or digit and holding only lowercase letters, digits, "-", ".", "_" and "~"), and ${manifest} declares no providerId that is one. Astryx files the package's components, templates and docs under that ID, so links to them and selecting the package cannot work. Fix: rename the package, such as "@your-scope/your-package", or set \`providerId: '@your-scope/your-package'\` in ${manifest}.`,
|
|
595
|
+
),
|
|
596
|
+
];
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
/**
|
|
600
|
+
* A warning for each field npm needs that package.json lacks.
|
|
601
|
+
* @param {{name?: unknown, version?: unknown, private?: unknown}} pkg
|
|
602
|
+
* @param {string} pkgJsonPath
|
|
603
|
+
* @returns {Issue[]}
|
|
604
|
+
*/
|
|
605
|
+
function packageJsonFieldIssues(pkg, pkgJsonPath) {
|
|
606
|
+
/** @type {Issue[]} */
|
|
607
|
+
const issues = [];
|
|
608
|
+
const shown = path.basename(pkgJsonPath);
|
|
609
|
+
// Listed, so validate and `--strict` keep the result they had for these
|
|
610
|
+
// packages; `integration verify`, which packs, reports them as errors.
|
|
611
|
+
if (typeof pkg.name !== 'string' || pkg.name === '') {
|
|
612
|
+
issues.push(
|
|
613
|
+
listed(
|
|
614
|
+
'invalid_package_json',
|
|
615
|
+
`${shown} has no "name", so npm cannot pack or publish the package, and a project that installs it has no name to select it by. Fix: add "name": "@your-scope/your-package" to ${shown}.`,
|
|
616
|
+
),
|
|
617
|
+
);
|
|
618
|
+
}
|
|
619
|
+
// A private package is never published, so it needs no version.
|
|
620
|
+
if (
|
|
621
|
+
pkg.private !== true &&
|
|
622
|
+
(typeof pkg.version !== 'string' || pkg.version === '')
|
|
623
|
+
) {
|
|
624
|
+
issues.push(
|
|
625
|
+
listed(
|
|
626
|
+
'invalid_package_json',
|
|
627
|
+
`${shown} has no "version", so npm cannot pack or publish the package. Fix: add "version": "0.1.0" to ${shown}.`,
|
|
628
|
+
),
|
|
629
|
+
);
|
|
630
|
+
}
|
|
631
|
+
return issues;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
/**
|
|
635
|
+
* Validate an INSTALLED integration package: the nearest `node_modules/<spec>`
|
|
636
|
+
* at or above `cwd`, resolved the way the project loads it.
|
|
431
637
|
* @param {string} spec package name
|
|
432
638
|
* @param {string} [cwd]
|
|
433
639
|
* @returns {Promise<ValidateResult>}
|
|
434
640
|
*/
|
|
435
641
|
export async function validateInstalledIntegration(spec, cwd = process.cwd()) {
|
|
436
|
-
//
|
|
642
|
+
// The resolver throws (path-safety guard) on a spec with path segments,
|
|
437
643
|
// `..`, or an absolute path. Every other malformed input to this command
|
|
438
644
|
// degrades into a diagnostic — so catch it here and return an issue instead
|
|
439
645
|
// of letting the throw escape to a raw stack (human) / generic ERR_UNKNOWN
|
|
440
646
|
// (--json).
|
|
441
647
|
let packageDir;
|
|
442
648
|
try {
|
|
443
|
-
packageDir =
|
|
649
|
+
packageDir = resolveInstalledIntegrationDir(spec, cwd);
|
|
444
650
|
} catch (err) {
|
|
445
651
|
return {
|
|
446
652
|
found: true,
|
|
@@ -472,10 +678,29 @@ export async function validateInstalledIntegration(spec, cwd = process.cwd()) {
|
|
|
472
678
|
};
|
|
473
679
|
}
|
|
474
680
|
|
|
475
|
-
return validateAtPackageDir(
|
|
476
|
-
|
|
477
|
-
version: pkg.version,
|
|
478
|
-
|
|
681
|
+
return validateAtPackageDir(
|
|
682
|
+
packageDir,
|
|
683
|
+
{name: pkg.name ?? spec, version: pkg.version},
|
|
684
|
+
{cwd},
|
|
685
|
+
);
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
/**
|
|
689
|
+
* The runner-command notes for a package's topics: each Astryx command a topic
|
|
690
|
+
* writes with a package runner, where the doc file is, and the bare command to
|
|
691
|
+
* write.
|
|
692
|
+
* @param {any} integration a loaded integration
|
|
693
|
+
* @returns {Promise<Array<{code: string, message: string}>>}
|
|
694
|
+
*/
|
|
695
|
+
async function runnerCommandNotes(integration) {
|
|
696
|
+
const packageDir = integration.__packageDir;
|
|
697
|
+
return (await integrationRunnerCommands(integration)).map(each => ({
|
|
698
|
+
code: 'runner_command',
|
|
699
|
+
message:
|
|
700
|
+
typeof packageDir === 'string'
|
|
701
|
+
? `${path.relative(packageDir, each.file).split(path.sep).join('/')}: ${each.message}`
|
|
702
|
+
: each.message,
|
|
703
|
+
}));
|
|
479
704
|
}
|
|
480
705
|
|
|
481
706
|
/**
|
|
@@ -504,7 +729,35 @@ export async function validateIntegration(pkg, options = {}) {
|
|
|
504
729
|
const docTypes = integration
|
|
505
730
|
? await integrationDocTypes(integration, cwd)
|
|
506
731
|
: undefined;
|
|
507
|
-
|
|
732
|
+
// The component names docs and blocks give: those that cannot be judged
|
|
733
|
+
// are listed in their reports, and those judged wrong are notes.
|
|
734
|
+
const names = integration
|
|
735
|
+
? [
|
|
736
|
+
await componentDocNamesCheck(integration),
|
|
737
|
+
await blockComponentsCheck(integration),
|
|
738
|
+
]
|
|
739
|
+
: undefined;
|
|
740
|
+
const docNames = names?.[0].report;
|
|
741
|
+
const blockComponents = names?.[1].report;
|
|
742
|
+
// Notes fail nothing: a malformed `cliCommand`, and the findings added
|
|
743
|
+
// after the last minor release, each with its fix in the message, which
|
|
744
|
+
// may not fail `--strict` until the next (architecture:cli-surface INV35):
|
|
745
|
+
// the layout findings and the component names judged wrong.
|
|
746
|
+
const notes = result.found
|
|
747
|
+
? [
|
|
748
|
+
...(result.notes ?? []),
|
|
749
|
+
...(result.listed ?? []).map(issue => ({
|
|
750
|
+
code: issue.code,
|
|
751
|
+
message: issue.message,
|
|
752
|
+
})),
|
|
753
|
+
...(names ?? []).flatMap(each => each.notes),
|
|
754
|
+
]
|
|
755
|
+
: [];
|
|
756
|
+
// Each Astryx command a topic writes with a package runner, as a
|
|
757
|
+
// `runner_command` note with its fix, the same way.
|
|
758
|
+
if (integration?.docs) {
|
|
759
|
+
notes.push(...(await runnerCommandNotes(integration)));
|
|
760
|
+
}
|
|
508
761
|
return {
|
|
509
762
|
type: 'integration.validate',
|
|
510
763
|
data: {
|
|
@@ -526,6 +779,12 @@ export async function validateIntegration(pkg, options = {}) {
|
|
|
526
779
|
: result.issues,
|
|
527
780
|
...(notes.length > 0 ? {notes} : {}),
|
|
528
781
|
...(docTypes ? {docTypes} : {}),
|
|
782
|
+
...(docNames ? {docNames} : {}),
|
|
783
|
+
...(blockComponents ? {blockComponents} : {}),
|
|
784
|
+
// What the public-import check could not judge: listed, never failed on.
|
|
785
|
+
...(result.found && result.publicImports
|
|
786
|
+
? {publicImports: result.publicImports}
|
|
787
|
+
: {}),
|
|
529
788
|
},
|
|
530
789
|
};
|
|
531
790
|
}
|
|
@@ -14,6 +14,7 @@ export type LoadedIntegration = {
|
|
|
14
14
|
codemods?: string | undefined;
|
|
15
15
|
docs?: string | undefined;
|
|
16
16
|
issuesUrl?: string | undefined;
|
|
17
|
+
__declaredKeys?: string[] | undefined;
|
|
17
18
|
__unknownKeys?: string[] | undefined;
|
|
18
19
|
__spec: string;
|
|
19
20
|
__packageDir: string;
|
|
@@ -36,7 +37,21 @@ export type ValidateIntegrationResponse = {
|
|
|
36
37
|
type: "integration.validate";
|
|
37
38
|
/**
|
|
38
39
|
* `notes`: information beside the issues that fails nothing, such as
|
|
39
|
-
* `invalid_cli_command`, a `cliCommand` that was ignored as malformed
|
|
40
|
+
* `invalid_cli_command`, a `cliCommand` that was ignored as malformed;
|
|
41
|
+
* `cli_peer_version`, the running CLI outside the package's
|
|
42
|
+
* `@astryxdesign/cli` peer range; and
|
|
43
|
+
* the package layout findings added after the last minor release, each with
|
|
44
|
+
* its fix in the message: two docs for one component
|
|
45
|
+
* (`duplicate_component_doc`), a root reached through a symlink
|
|
46
|
+
* (`symlinked_root`), a contribution file that cannot be read
|
|
47
|
+
* (`unreadable_file`), a package.json without `name` or `version`
|
|
48
|
+
* (`invalid_package_json`), no provider ID (`no_provider_id`), and a doc
|
|
49
|
+
* whose file name differs from its source only in letter case where the two
|
|
50
|
+
* still pair (`source_without_component_doc`); `doc_name_mismatch` and
|
|
51
|
+
* `unknown_block_component` (see `docNames` and `blockComponents`); and
|
|
52
|
+
* since 0.7.3 each public-import finding; they become warnings in the next
|
|
53
|
+
* minor release; and `runner_command`, an Astryx command a topic writes
|
|
54
|
+
* with a package runner
|
|
40
55
|
*/
|
|
41
56
|
data: {
|
|
42
57
|
validated: boolean;
|
|
@@ -48,6 +63,9 @@ export type ValidateIntegrationResponse = {
|
|
|
48
63
|
message: string;
|
|
49
64
|
}>;
|
|
50
65
|
docTypes?: DocTypesReport;
|
|
66
|
+
docNames?: DocNamesReport;
|
|
67
|
+
blockComponents?: BlockComponentsReport;
|
|
68
|
+
publicImports?: PublicImportsReport;
|
|
51
69
|
};
|
|
52
70
|
};
|
|
53
71
|
/**
|
|
@@ -57,3 +75,74 @@ export type ValidateIntegrationResponse = {
|
|
|
57
75
|
export type DocTypesReport = import("../../foundation/discovery/doc-types.mjs").DocTypesReport & {
|
|
58
76
|
fixtures?: number;
|
|
59
77
|
};
|
|
78
|
+
/**
|
|
79
|
+
* Each component doc whose `name` differs from the name it is listed under,
|
|
80
|
+
* judged against its source. Present when the manifest loads. A name the
|
|
81
|
+
* module its printed import names provably does not export is a
|
|
82
|
+
* `doc_name_mismatch` note beside the issues, with its fix in the message
|
|
83
|
+
* (it becomes a warning in the next minor release), so `findings` is always
|
|
84
|
+
* empty; `unchecked` lists each doc whose source's
|
|
85
|
+
* exports could not all be read (a re-export from another package, `export
|
|
86
|
+
* =`, a destructured binding, a namespace): `file` (the doc, package-relative),
|
|
87
|
+
* `name` (what the doc says), and `reason`.
|
|
88
|
+
*/
|
|
89
|
+
export type DocNamesReport = {
|
|
90
|
+
status: "checked";
|
|
91
|
+
findings: [];
|
|
92
|
+
unchecked: Array<{
|
|
93
|
+
file: string;
|
|
94
|
+
name: string;
|
|
95
|
+
reason: string;
|
|
96
|
+
}>;
|
|
97
|
+
};
|
|
98
|
+
/**
|
|
99
|
+
* Each component name a template gives in `exampleFor` or `componentsUsed`
|
|
100
|
+
* that could not be judged. Present when the manifest loads. A name neither
|
|
101
|
+
* the package nor Core has, and the template does not import, is an
|
|
102
|
+
* `unknown_block_component` note beside the issues, with its fix in the
|
|
103
|
+
* message (it becomes a warning in the next minor release), so `findings` is
|
|
104
|
+
* always empty;
|
|
105
|
+
* `unchecked` lists each name that cannot be judged: one the template may
|
|
106
|
+
* reach through anything other than named imports and re-exports from
|
|
107
|
+
* Core, React, StyleX, local helpers or the package's own entry (an import from another
|
|
108
|
+
* package, a default or namespace import, an alias of or member read off an imported
|
|
109
|
+
* binding, require(), a dynamic import(), a local module this check cannot
|
|
110
|
+
* read), or, without Core installed, any name Core would have to resolve: `file` (the template doc, package-relative),
|
|
111
|
+
* `name`, and `reason`.
|
|
112
|
+
*/
|
|
113
|
+
export type BlockComponentsReport = {
|
|
114
|
+
status: "checked";
|
|
115
|
+
findings: [];
|
|
116
|
+
unchecked: Array<{
|
|
117
|
+
file: string;
|
|
118
|
+
name: string;
|
|
119
|
+
reason: string;
|
|
120
|
+
}>;
|
|
121
|
+
};
|
|
122
|
+
/**
|
|
123
|
+
* An import the public-import check could not judge.
|
|
124
|
+
*/
|
|
125
|
+
export type PublicImportUnchecked = {
|
|
126
|
+
/**
|
|
127
|
+
* package-relative file that names it
|
|
128
|
+
*/
|
|
129
|
+
file: string;
|
|
130
|
+
/**
|
|
131
|
+
* the import specifier
|
|
132
|
+
*/
|
|
133
|
+
specifier: string;
|
|
134
|
+
/**
|
|
135
|
+
* why it was not checked
|
|
136
|
+
*/
|
|
137
|
+
reason: string;
|
|
138
|
+
};
|
|
139
|
+
/**
|
|
140
|
+
* The public-import check's report on validate's result: `unchecked` lists
|
|
141
|
+
* what it could not judge, never counted or failed on. Its findings are
|
|
142
|
+
* notes on the result (`data.notes`), so `findings` stays empty.
|
|
143
|
+
*/
|
|
144
|
+
export type PublicImportsReport = {
|
|
145
|
+
status: "checked";
|
|
146
|
+
findings: never[];
|
|
147
|
+
unchecked: PublicImportUnchecked[];
|
|
148
|
+
};
|