@astryxdesign/cli 0.6.4-canary.f0355e3 → 0.6.4
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 +96 -99
- package/api/build/build.doc.mjs +1 -6
- package/api/build/build.test.mjs +0 -22
- package/api/build/kit/kit.mjs +5 -44
- package/api/component/_adapter.d.mts +0 -25
- package/api/component/_adapter.mjs +5 -59
- package/api/component/component.d.mts +3 -6
- package/api/component/component.doc.mjs +17 -37
- package/api/component/component.mjs +9 -249
- package/api/component/component.type.d.mts +0 -25
- package/api/component/component.type.mjs +0 -44
- package/api/discover/_adapter.d.mts +6 -114
- package/api/discover/_adapter.mjs +17 -372
- package/api/discover/detail/detail.d.mts +6 -18
- package/api/discover/detail/detail.mjs +13 -67
- package/api/discover/detail/detail.test.mjs +0 -85
- package/api/discover/discover.d.mts +9 -3
- package/api/discover/discover.doc.mjs +18 -61
- package/api/discover/discover.mjs +36 -220
- package/api/discover/discover.test.mjs +2 -11
- package/api/discover/discover.type.d.mts +8 -147
- package/api/discover/discover.type.mjs +12 -102
- package/api/discover/list/list.d.mts +6 -20
- package/api/discover/list/list.mjs +12 -45
- package/api/discover/list/list.test.mjs +0 -46
- package/api/discover/search/search.d.mts +16 -18
- package/api/discover/search/search.mjs +56 -102
- package/api/discover/search/search.test.mjs +10 -144
- package/api/docs/_adapter.d.mts +3 -8
- package/api/docs/_adapter.mjs +6 -14
- package/api/docs/docOverlays.test.mjs +1 -27
- package/api/docs/docs.doc.mjs +2 -2
- package/api/docs/docs.test.mjs +243 -0
- package/api/docs/integration-tree.test.mjs +555 -0
- package/api/docs/integrationDocs.test.mjs +314 -0
- package/api/doctor/doctor.d.mts +3 -8
- package/api/doctor/doctor.doc.mjs +8 -17
- package/api/doctor/doctor.mjs +9 -90
- package/api/doctor/doctor.test.mjs +10 -122
- package/api/doctor/doctor.type.d.mts +1 -1
- package/api/doctor/doctor.type.mjs +1 -1
- package/api/gap-report/gap-report.doc.mjs +10 -19
- package/api/hook/hook.doc.mjs +3 -6
- package/api/index.d.mts +2 -1
- package/api/index.mjs +5 -5
- package/api/init/init.doc.mjs +12 -17
- package/api/integration/add-helpers.d.mts +2 -5
- package/api/integration/add-helpers.mjs +9 -36
- package/api/integration/add-theme.mjs +1 -22
- package/api/integration/add-theme.test.mjs +0 -34
- package/api/integration/authoring-checks.mjs +2 -2
- package/api/integration/integrationPackCheck.doc.mjs +3 -3
- package/api/integration/pack-check.mjs +9 -82
- package/api/integration/pack-check.test.mjs +0 -90
- package/api/integration/pack-check.type.mjs +1 -1
- package/api/json/assertResponse.doc.mjs +1 -1
- package/api/json/index.ts +1 -0
- package/api/json/isError.doc.mjs +1 -1
- package/api/layout/_adapter.d.mts +34 -0
- package/api/layout/_adapter.mjs +148 -0
- package/api/layout/check/check.d.mts +16 -0
- package/api/layout/check/check.mjs +40 -0
- package/api/layout/expand/expand.d.mts +22 -0
- package/api/layout/expand/expand.mjs +155 -0
- package/api/layout/expand/expand.path-safety.test.mjs +53 -0
- package/api/layout/grammar/grammar.d.mts +13 -0
- package/api/layout/grammar/grammar.mjs +87 -0
- package/api/layout/layout.d.mts +6 -0
- package/api/layout/layout.mjs +17 -0
- package/api/layout/layout.test.mjs +297 -0
- package/api/layout/layout.type.d.mts +89 -0
- package/api/layout/layout.type.mjs +103 -0
- package/api/layout/layoutCheck.doc.d.mts +11 -0
- package/api/layout/layoutCheck.doc.mjs +85 -0
- package/api/layout/layoutExpand.doc.d.mts +11 -0
- package/api/layout/layoutExpand.doc.mjs +107 -0
- package/api/layout/layoutGrammar.doc.d.mts +11 -0
- package/api/layout/layoutGrammar.doc.mjs +57 -0
- package/api/search/search.d.mts +1 -27
- package/api/search/search.doc.mjs +2 -2
- package/api/search/search.mjs +16 -228
- package/api/search/search.test.mjs +512 -0
- package/api/swizzle/swizzle.doc.mjs +5 -7
- package/api/template/copy/copy.mjs +1 -1
- package/api/template/copy/copy.test.mjs +0 -9
- package/api/template/template-integration.test.mjs +65 -1
- package/api/template/template.doc.mjs +1 -2
- package/api/template/template.mjs +1 -1
- package/api/theme/add/add.mjs +25 -17
- package/api/theme/add/add.staging.test.mjs +23 -40
- package/api/theme/build/build.family.test.mjs +12 -7
- package/api/theme/build/build.mjs +18 -8
- package/api/theme/generateTonalPalette.doc.mjs +2 -1
- package/api/theme/listThemes.doc.mjs +1 -1
- package/api/theme/themeAdd.doc.mjs +10 -9
- package/api/theme/themeBuild.doc.mjs +13 -13
- package/api/theme/themeList.doc.mjs +1 -1
- package/api/theme/themeListAvailable.doc.mjs +1 -2
- package/api/theme/themePaletteGenerate.doc.mjs +8 -15
- package/api/theme/themeTargets.doc.mjs +2 -3
- package/api/theme/themeTemplate.doc.mjs +1 -2
- package/api/upgrade/run/run.mjs +4 -6
- package/api/upgrade/upgrade.doc.mjs +22 -24
- package/api/upgrade/upgrade.type.mjs +2 -2
- package/assets/codemods/__tests__/runner.test.mjs +1 -3
- package/assets/codemods/integration-runner.mjs +3 -3
- package/assets/codemods/runner.mjs +4 -5
- package/assets/docs/README.md +2 -4
- package/assets/docs/browser-support.doc.mjs +11 -11
- package/assets/docs/color.doc.mjs +2 -8
- package/assets/docs/elevation.doc.mjs +4 -6
- package/assets/docs/getting-started.doc.mjs +16 -5
- package/assets/docs/icons.doc.mjs +21 -2
- package/assets/docs/illustrations.doc.mjs +15 -7
- package/assets/docs/internationalization.doc.mjs +5 -7
- package/assets/docs/layout.doc.dense.mjs +82 -130
- package/assets/docs/layout.doc.mjs +77 -133
- package/assets/docs/migration.doc.mjs +21 -19
- package/assets/docs/motion.doc.mjs +3 -16
- package/assets/docs/principles.doc.dense.mjs +5 -5
- package/assets/docs/principles.doc.mjs +0 -8
- package/assets/docs/principles.doc.zh.mjs +6 -6
- package/assets/docs/shape.doc.mjs +3 -8
- package/assets/docs/spacing.doc.mjs +2 -7
- package/assets/docs/styling-libraries.doc.mjs +2 -6
- package/assets/docs/styling.doc.mjs +23 -19
- package/assets/docs/theme.doc.dense.mjs +18 -58
- package/assets/docs/theme.doc.mjs +46 -56
- package/assets/docs/theme.doc.zh.mjs +8 -9
- package/assets/docs/tokens.doc.dense.mjs +2 -2
- package/assets/docs/tokens.doc.mjs +8 -389
- package/assets/docs/tokens.doc.zh.mjs +2 -2
- package/assets/docs/tree/integrations.doc.mjs +451 -25
- package/assets/docs/tree/integrations.test.mjs +62 -0
- package/assets/docs/tree/writing-docs.doc.mjs +286 -0
- package/assets/docs/typography.doc.mjs +4 -24
- package/assets/docs/working-with-ai.doc.mjs +22 -30
- package/assets/templates/blocks/components/InternationalizationProvider/InternationalizationProvider01ShippedLocale.tsx +1 -1
- package/authoring/config/config.doc.mjs +2 -10
- package/authoring/config/parse.d.mts +0 -2
- package/authoring/config/parse.mjs +0 -19
- package/authoring/config/parse.test.mjs +0 -8
- package/authoring/config/type.ts +2 -13
- package/authoring/doctypes/_schema.d.mts +2 -3
- package/authoring/doctypes/_schema.mjs +0 -6
- package/authoring/doctypes/base/graph-fields.doc.mjs +3 -3
- package/authoring/doctypes/base/type.ts +2 -4
- package/authoring/doctypes/command/command.doc.mjs +1 -1
- package/authoring/doctypes/command/type.ts +1 -1
- package/authoring/doctypes/component/component.doc.mjs +0 -6
- package/authoring/doctypes/component/type.ts +0 -8
- package/authoring/doctypes/reference/reference.doc.mjs +0 -7
- package/authoring/doctypes/reference/type.ts +0 -5
- package/authoring/doctypes/schema/schema.doc.mjs +2 -2
- package/authoring/doctypes/template/template.doc.mjs +1 -1
- package/authoring/doctypes/template/type.ts +2 -2
- package/authoring/index.d.mts +0 -1
- package/authoring/index.d.ts +0 -10
- package/authoring/index.mjs +0 -1
- package/authoring/integration/integration.doc.mjs +10 -12
- package/clients/cli/command-result-coverage.test.mjs +7 -7
- package/clients/cli/commands/component/index.mjs +55 -152
- package/clients/cli/commands/component-ownership.test.mjs +0 -89
- package/clients/cli/commands/component.doc.mjs +9 -27
- package/clients/cli/commands/debug-result-summary.test.mjs +2 -2
- package/clients/cli/commands/discover.doc.mjs +9 -53
- package/clients/cli/commands/discover.mjs +118 -393
- package/clients/cli/commands/docs.doc.mjs +1 -1
- package/clients/cli/commands/docs.mjs +17 -60
- package/clients/cli/commands/docs.test.mjs +294 -0
- package/clients/cli/commands/doctor-integration-docs.doc.mjs +2 -3
- package/clients/cli/commands/doctor-integration.test.mjs +0 -53
- package/clients/cli/commands/doctor.doc.mjs +1 -3
- package/clients/cli/commands/doctor.mjs +5 -49
- package/clients/cli/commands/gap-report.doc.mjs +9 -10
- package/clients/cli/commands/init.doc.mjs +6 -9
- package/clients/cli/commands/integration-add.doc.mjs +9 -9
- package/clients/cli/commands/integration-authoring.test.mjs +10 -61
- package/clients/cli/commands/integration-pack.doc.mjs +9 -5
- package/clients/cli/commands/integration-real-world.test.mjs +1 -1
- package/clients/cli/commands/integration.doc.mjs +4 -4
- package/clients/cli/commands/integration.mjs +43 -74
- package/clients/cli/commands/layout-check.doc.mjs +65 -0
- package/clients/cli/commands/layout-expand.doc.mjs +83 -0
- package/clients/cli/commands/layout-grammar.doc.mjs +30 -0
- package/clients/cli/commands/layout.doc.mjs +34 -0
- package/clients/cli/commands/layout.error-codes.test.mjs +66 -0
- package/clients/cli/commands/layout.exit-parity.test.mjs +41 -0
- package/clients/cli/commands/layout.mjs +275 -0
- package/clients/cli/commands/layout.path-help.test.mjs +33 -0
- package/clients/cli/commands/layout.stdin-cap.test.mjs +47 -0
- package/clients/cli/commands/layout.text-fields.test.mjs +39 -0
- package/clients/cli/commands/manifest.doc.mjs +1 -1
- package/clients/cli/commands/search.doc.mjs +3 -10
- package/clients/cli/commands/search.mjs +2 -21
- package/clients/cli/commands/search.test.mjs +4 -21
- package/clients/cli/commands/swizzle.doc.mjs +1 -1
- package/clients/cli/commands/template.doc.mjs +1 -1
- package/clients/cli/commands/text-json-parity.test.mjs +16 -5
- package/clients/cli/commands/theme-add.doc.mjs +1 -1
- package/clients/cli/commands/theme-palette-generate.doc.mjs +2 -3
- package/clients/cli/commands/theme-palette.doc.mjs +2 -1
- package/clients/cli/commands/theme-targets.doc.mjs +2 -2
- package/clients/cli/commands/theme.doc.mjs +1 -2
- package/clients/cli/commands/upgrade.doc.mjs +3 -62
- package/clients/cli/index.mjs +10 -28
- package/clients/cli/lib/define-command.mjs +4 -28
- package/clients/cli/lib/define-command.test.mjs +0 -54
- package/clients/cli/lib/exit-codes.test.mjs +9 -18
- package/clients/cli/lib/json-shim.mjs +14 -24
- package/clients/cli/lib/json-shim.test.mjs +20 -6
- package/clients/cli/lib/manifest.mjs +13 -18
- package/clients/cli/lib/manifest.test.mjs +2 -5
- package/foundation/agent-docs/agent-docs.mjs +1 -1
- package/foundation/agent-docs/agent-docs.test.mjs +1159 -0
- package/foundation/discovery/authoring-self-docs.mjs +0 -1
- package/foundation/discovery/authoring-self-docs.test.mjs +2 -6
- package/foundation/discovery/cli-self-docs.mjs +2 -16
- package/foundation/discovery/cli-self-docs.test.mjs +0 -20
- package/foundation/discovery/docs-discovery.mjs +1 -5
- package/foundation/discovery/docs-discovery.test.mjs +0 -21
- package/foundation/discovery/docs-section-key.d.mts +1 -1
- package/foundation/discovery/docs-section-key.mjs +1 -1
- package/foundation/discovery/template-adapter.mjs +1 -1
- package/foundation/doc-compiler/doc-loads.test.mjs +14 -3
- package/foundation/doc-compiler/tree.d.mts +0 -4
- package/foundation/doc-compiler/tree.mjs +1 -6
- package/foundation/doc-compiler/tree.test.mjs +598 -0
- package/foundation/integrations/cli-requirement.d.mts +6 -26
- package/foundation/integrations/cli-requirement.mjs +11 -46
- package/foundation/integrations/cli-requirement.test.mjs +2 -7
- package/foundation/integrations/contribution-inventory.mjs +1 -1
- package/foundation/integrations/integrations.d.mts +1 -14
- package/foundation/integrations/integrations.mjs +1 -41
- package/foundation/integrations/integrations.test.mjs +0 -31
- package/foundation/response/error-codes.doc.mjs +8 -6
- package/foundation/response/error-codes.test.mjs +5 -30
- package/foundation/response/response-types.doc.d.mts +3 -4
- package/foundation/response/response-types.doc.mjs +27 -40
- package/foundation/response/response-types.doc.test.mjs +0 -23
- package/foundation/response/response.doc.mjs +10 -11
- package/foundation/xle/browser.d.mts +3 -3
- package/foundation/xle/browser.mjs +3 -3
- package/foundation/xle/expand.mjs +2 -2
- package/foundation/xle/parse.mjs +1 -1
- package/foundation/xle/print.mjs +2 -2
- package/foundation/xle/splice.mjs +1 -1
- package/package.json +9 -9
- package/api/discover/_adapter.test.mjs +0 -215
- package/api/discover/_catalog-view.d.mts +0 -115
- package/api/discover/_catalog-view.mjs +0 -203
- package/api/discover/_catalog-view.test.mjs +0 -128
- package/api/discover/detail/item/item.d.mts +0 -26
- package/api/discover/detail/item/item.mjs +0 -78
- package/api/discover/detail/item/item.test.mjs +0 -73
- package/api/integration/pack-check.lifecycle-output.test.mjs +0 -107
- package/api/theme/add/add.rollback.test.mjs +0 -158
- package/api/theme/build/build.rollback.test.mjs +0 -148
- package/api/upgrade/run/files-changed.test.mjs +0 -111
- package/assets/codemods/file-count.test.mjs +0 -163
- package/assets/docs/tree/add-a-component.doc.mjs +0 -75
- package/assets/docs/tree/add-a-theme.doc.mjs +0 -85
- package/assets/docs/tree/add-a-topic.doc.mjs +0 -144
- package/assets/docs/tree/agent-guidance.doc.mjs +0 -138
- package/assets/docs/tree/block-template.doc.mjs +0 -130
- package/assets/docs/tree/build-the-template.doc.mjs +0 -28
- package/assets/docs/tree/building-blocks.doc.mjs +0 -46
- package/assets/docs/tree/check-your-docs.doc.mjs +0 -137
- package/assets/docs/tree/checks.doc.mjs +0 -119
- package/assets/docs/tree/codemods.doc.mjs +0 -147
- package/assets/docs/tree/component-family.doc.mjs +0 -113
- package/assets/docs/tree/component-imports.doc.mjs +0 -69
- package/assets/docs/tree/component-lookups.doc.mjs +0 -149
- package/assets/docs/tree/components.doc.mjs +0 -23
- package/assets/docs/tree/configuration.doc.mjs +0 -23
- package/assets/docs/tree/debug-and-gap-reports.doc.mjs +0 -182
- package/assets/docs/tree/define-the-theme.doc.mjs +0 -118
- package/assets/docs/tree/describe-the-component.doc.mjs +0 -57
- package/assets/docs/tree/docs.doc.mjs +0 -21
- package/assets/docs/tree/document-the-template.doc.mjs +0 -28
- package/assets/docs/tree/document-the-theme.doc.mjs +0 -68
- package/assets/docs/tree/export-template-assets.doc.mjs +0 -147
- package/assets/docs/tree/extend-or-replace.doc.mjs +0 -103
- package/assets/docs/tree/fonts-and-assets.doc.mjs +0 -106
- package/assets/docs/tree/generate-a-palette.doc.mjs +0 -66
- package/assets/docs/tree/grade-template-with-agent.doc.mjs +0 -105
- package/assets/docs/tree/help.doc.mjs +0 -16
- package/assets/docs/tree/links.doc.mjs +0 -98
- package/assets/docs/tree/package-and-test.doc.mjs +0 -32
- package/assets/docs/tree/page-template.doc.mjs +0 -71
- package/assets/docs/tree/publishing.doc.mjs +0 -111
- package/assets/docs/tree/quick-start.doc.mjs +0 -272
- package/assets/docs/tree/replace-a-core-component.doc.mjs +0 -104
- package/assets/docs/tree/replace-a-core-template.doc.mjs +0 -172
- package/assets/docs/tree/sections-and-placement.doc.mjs +0 -108
- package/assets/docs/tree/see-it-in-an-app.doc.mjs +0 -59
- package/assets/docs/tree/ship.doc.mjs +0 -16
- package/assets/docs/tree/short-and-findable.doc.mjs +0 -108
- package/assets/docs/tree/single-component.doc.mjs +0 -165
- package/assets/docs/tree/start-a-template.doc.mjs +0 -143
- package/assets/docs/tree/subcomponent.doc.mjs +0 -115
- package/assets/docs/tree/template-assets.doc.mjs +0 -64
- package/assets/docs/tree/template-doc-overview.doc.mjs +0 -109
- package/assets/docs/tree/template-fonts.doc.mjs +0 -102
- package/assets/docs/tree/template-grading-rubric.doc.mjs +0 -452
- package/assets/docs/tree/template-icons.doc.mjs +0 -97
- package/assets/docs/tree/template-images-media.doc.mjs +0 -127
- package/assets/docs/tree/template-styles.doc.mjs +0 -93
- package/assets/docs/tree/templates.doc.mjs +0 -34
- package/assets/docs/tree/test-in-an-app.doc.mjs +0 -115
- package/assets/docs/tree/test-template-in-app.doc.mjs +0 -128
- package/assets/docs/tree/themes.doc.mjs +0 -39
- package/assets/docs/tree/troubleshooting.doc.mjs +0 -149
- package/assets/docs/tree/upgrading.doc.mjs +0 -103
- package/assets/docs/tree/use-a-theme-in-an-app.doc.mjs +0 -51
- package/assets/docs/tree/verify-packed-template.doc.mjs +0 -77
- package/assets/docs/tree/versioning.doc.mjs +0 -161
- package/assets/docs/tree/write-good-templates.doc.mjs +0 -64
- package/assets/docs/tree/write-the-template-file.doc.mjs +0 -154
- package/authoring/discover/discover.doc.d.mts +0 -13
- package/authoring/discover/discover.doc.mjs +0 -138
- package/authoring/discover/parse.d.mts +0 -24
- package/authoring/discover/parse.mjs +0 -128
- package/authoring/discover/parse.test.mjs +0 -124
- package/authoring/discover/type.ts +0 -87
- package/clients/cli/commands/component-batch.test.mjs +0 -341
- package/clients/cli/commands/discover.sources.test.mjs +0 -267
- package/clients/cli/commands/integration-verify.doc.mjs +0 -22
- package/clients/cli/lib/parse-error-format.test.mjs +0 -81
- package/foundation/response/batch.type.d.mts +0 -33
- package/foundation/response/batch.type.mjs +0 -34
|
@@ -0,0 +1,598 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file Tests for the docs tree (spec:AST-046): one home per doc, decided by
|
|
5
|
+
* explicit placement, then one adoption rule; every way a placement can fail;
|
|
6
|
+
* generated kind levels; deterministic order; and the CLI's own tree.
|
|
7
|
+
*
|
|
8
|
+
* @input Plain fixture inputs for the pure builder, and this package's own
|
|
9
|
+
* tree files and typed docs for the loader.
|
|
10
|
+
* @output Assertions on routes, parents, slots, children order, and
|
|
11
|
+
* diagnostics.
|
|
12
|
+
* @position packages/cli/foundation/doc-compiler — tests for tree.mjs.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import {describe, expect, it} from 'vitest';
|
|
16
|
+
import {
|
|
17
|
+
buildDocsTree,
|
|
18
|
+
KIND_GROUPS,
|
|
19
|
+
loadDocsTree,
|
|
20
|
+
loadTreeInputs,
|
|
21
|
+
routeSegment,
|
|
22
|
+
} from './tree.mjs';
|
|
23
|
+
import {loadCliSelfDocs} from '../discovery/cli-self-docs.mjs';
|
|
24
|
+
import * as api from '../../api/index.mjs';
|
|
25
|
+
import {createDocId} from '../identity/provider-identity.mjs';
|
|
26
|
+
import {CLI_PROVIDER_ID} from '../identity/providers.mjs';
|
|
27
|
+
|
|
28
|
+
const SLOW = 60_000;
|
|
29
|
+
const P = '@acme/kit';
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @param {string} name
|
|
33
|
+
* @param {object} [extra]
|
|
34
|
+
* @returns {import('./tree.mjs').TreeNamespaceInput}
|
|
35
|
+
*/
|
|
36
|
+
const ns = (name, extra = {}) => ({
|
|
37
|
+
provider: P,
|
|
38
|
+
providerId: P,
|
|
39
|
+
source: `${P}/tree/${name}.doc.mjs`,
|
|
40
|
+
doc: /** @type {any} */ ({
|
|
41
|
+
type: 'namespace',
|
|
42
|
+
name,
|
|
43
|
+
title: name.toUpperCase(),
|
|
44
|
+
summary: `The ${name} level.`,
|
|
45
|
+
slots: {
|
|
46
|
+
items: {title: 'Items', accepts: {kinds: ['generic', 'namespace']}},
|
|
47
|
+
},
|
|
48
|
+
...extra,
|
|
49
|
+
}),
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @param {string} name
|
|
54
|
+
* @param {object} [extra]
|
|
55
|
+
* @returns {import('./tree.mjs').TreeDocInput}
|
|
56
|
+
*/
|
|
57
|
+
const guide = (name, extra = {}) => ({
|
|
58
|
+
provider: P,
|
|
59
|
+
providerId: P,
|
|
60
|
+
source: `${P}/tree/${name}.doc.mjs`,
|
|
61
|
+
kind: 'generic',
|
|
62
|
+
name,
|
|
63
|
+
title: `Guide ${name}`,
|
|
64
|
+
summary: `About ${name}.`,
|
|
65
|
+
group: null,
|
|
66
|
+
placement: undefined,
|
|
67
|
+
...extra,
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* @param {string} kind
|
|
72
|
+
* @param {string} name
|
|
73
|
+
* @param {string} group
|
|
74
|
+
* @returns {import('./tree.mjs').TreeDocInput}
|
|
75
|
+
*/
|
|
76
|
+
const typed = (kind, name, group) => ({
|
|
77
|
+
provider: P,
|
|
78
|
+
providerId: P,
|
|
79
|
+
source: `${P}/api/${name}.doc.mjs`,
|
|
80
|
+
kind,
|
|
81
|
+
name,
|
|
82
|
+
title: name,
|
|
83
|
+
summary: `The ${name} ${kind}.`,
|
|
84
|
+
group,
|
|
85
|
+
placement: undefined,
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
/** @param {ReturnType<typeof buildDocsTree>} tree */
|
|
89
|
+
const routes = tree => [...tree.nodes.keys()];
|
|
90
|
+
|
|
91
|
+
/** @param {ReturnType<typeof buildDocsTree>} tree */
|
|
92
|
+
const problems = tree => tree.diagnostics.map(d => [d.code, d.message]);
|
|
93
|
+
|
|
94
|
+
describe('buildDocsTree', () => {
|
|
95
|
+
|
|
96
|
+
it('withdraws a namespace placed in a withdrawn namespace, and what is placed in it', () => {
|
|
97
|
+
const CLI = '@astryxdesign/cli';
|
|
98
|
+
const tree = buildDocsTree({
|
|
99
|
+
namespaces: [
|
|
100
|
+
ns('tokens'),
|
|
101
|
+
ns('alpha', {placement: {parent: 'namespace:tokens', slot: 'items'}}),
|
|
102
|
+
],
|
|
103
|
+
docs: [guide('deep', {placement: {parent: 'namespace:alpha', slot: 'items'}})],
|
|
104
|
+
topics: [
|
|
105
|
+
{provider: CLI, providerId: CLI, name: 'tokens', title: 'Tokens', summary: 'Tokens.', source: `${CLI}/tokens.doc.mjs`},
|
|
106
|
+
],
|
|
107
|
+
});
|
|
108
|
+
expect(tree.get('tokens')?.provider).toBe(CLI);
|
|
109
|
+
expect(routes(tree).filter(route => route.startsWith('tokens/'))).toEqual([]);
|
|
110
|
+
expect(problems(tree)).toEqual(
|
|
111
|
+
expect.arrayContaining([
|
|
112
|
+
['duplicate_route', expect.stringContaining('takes the route "tokens"')],
|
|
113
|
+
['invalid_placement', 'Namespace "alpha" has no route: the namespace it is placed in was withdrawn.'],
|
|
114
|
+
['invalid_placement', expect.stringContaining('names a namespace that has no route')],
|
|
115
|
+
]),
|
|
116
|
+
);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it("keeps a name a topic answers to through replaces as that topic's route", () => {
|
|
120
|
+
const tree = buildDocsTree({
|
|
121
|
+
namespaces: [ns('tokens')],
|
|
122
|
+
docs: [],
|
|
123
|
+
topics: [
|
|
124
|
+
{provider: '@acme/a', providerId: '@acme/a', name: 'acme-tokens', title: 'Acme tokens', summary: 'Acme tokens.', source: '@acme/a:acme-tokens', aliases: ['tokens', 'old-tokens']},
|
|
125
|
+
],
|
|
126
|
+
});
|
|
127
|
+
expect(tree.get('tokens')).toBeUndefined();
|
|
128
|
+
expect(tree.get('acme-tokens')?.provider).toBe('@acme/a');
|
|
129
|
+
expect(problems(tree)).toEqual([
|
|
130
|
+
['duplicate_route', expect.stringContaining('takes the route "tokens", which the topic "acme-tokens" also answers to')],
|
|
131
|
+
]);
|
|
132
|
+
// Every name it answers to is reserved, not only the last one it replaced.
|
|
133
|
+
const older = buildDocsTree({
|
|
134
|
+
namespaces: [ns('old-tokens')],
|
|
135
|
+
docs: [],
|
|
136
|
+
topics: [
|
|
137
|
+
{provider: '@acme/a', providerId: '@acme/a', name: 'acme-tokens', title: 'Acme tokens', summary: 'Acme tokens.', source: '@acme/a:acme-tokens', aliases: ['tokens', 'old-tokens']},
|
|
138
|
+
],
|
|
139
|
+
});
|
|
140
|
+
expect(older.get('old-tokens')).toBeUndefined();
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it("keeps the CLI's own routes from an integration, compared without case", () => {
|
|
144
|
+
const CLI = '@astryxdesign/cli';
|
|
145
|
+
/** @param {string} name @param {string} [provider] */
|
|
146
|
+
const topic = (name, provider = P) => ({
|
|
147
|
+
provider,
|
|
148
|
+
providerId: provider,
|
|
149
|
+
name,
|
|
150
|
+
title: name,
|
|
151
|
+
summary: `The ${name} topic.`,
|
|
152
|
+
source: `${provider}/${name}.doc.mjs`,
|
|
153
|
+
});
|
|
154
|
+
const cliNs = {...ns('cli'), provider: CLI, providerId: CLI, source: `${CLI}/tree/cli.doc.mjs`};
|
|
155
|
+
// An integration's topics named `CLI` and `UNORGANIZED` claim the CLI's
|
|
156
|
+
// namespace and the generated level; both are withdrawn.
|
|
157
|
+
const tree = buildDocsTree({
|
|
158
|
+
namespaces: [cliNs],
|
|
159
|
+
docs: [],
|
|
160
|
+
topics: [topic('theme', CLI), topic('CLI'), topic('UNORGANIZED')],
|
|
161
|
+
});
|
|
162
|
+
expect(tree.get('cli')?.provider).toBe(CLI);
|
|
163
|
+
expect(tree.get('unorganized')?.provider).toBe(CLI);
|
|
164
|
+
expect(routes(tree)).not.toContain('CLI');
|
|
165
|
+
expect(routes(tree)).not.toContain('UNORGANIZED');
|
|
166
|
+
expect(problems(tree)).toEqual(
|
|
167
|
+
expect.arrayContaining([
|
|
168
|
+
['duplicate_route', expect.stringContaining('both have the route "CLI"')],
|
|
169
|
+
['duplicate_route', expect.stringContaining('takes the route "UNORGANIZED", which the CLI\'s own docs keep')],
|
|
170
|
+
]),
|
|
171
|
+
);
|
|
172
|
+
expect(tree.getFolded('THEME')?.provider).toBe(CLI);
|
|
173
|
+
// A CLI topic whose own name has capitals keeps its route against a
|
|
174
|
+
// lowercase namespace, although namespaces go into the tree first.
|
|
175
|
+
const caps = buildDocsTree({namespaces: [ns('tokens')], docs: [], topics: [topic('Tokens', CLI)]});
|
|
176
|
+
expect(caps.get('Tokens')?.provider).toBe(CLI);
|
|
177
|
+
expect(caps.get('tokens')).toBeUndefined();
|
|
178
|
+
expect(problems(caps)).toEqual([
|
|
179
|
+
['duplicate_route', expect.stringContaining('takes the route "tokens", which the CLI\'s own docs keep')],
|
|
180
|
+
]);
|
|
181
|
+
});
|
|
182
|
+
it('builds three authored levels and a guide below them', () => {
|
|
183
|
+
const tree = buildDocsTree({
|
|
184
|
+
namespaces: [
|
|
185
|
+
ns('top'),
|
|
186
|
+
ns('middle', {placement: {parent: 'namespace:top', slot: 'items'}}),
|
|
187
|
+
ns('bottom', {placement: {parent: 'namespace:middle'}}),
|
|
188
|
+
],
|
|
189
|
+
docs: [
|
|
190
|
+
guide('deep', {placement: {parent: 'namespace:bottom', order: 1}}),
|
|
191
|
+
],
|
|
192
|
+
});
|
|
193
|
+
expect(problems(tree)).toEqual([]);
|
|
194
|
+
expect(routes(tree)).toEqual([
|
|
195
|
+
'top',
|
|
196
|
+
'top/middle',
|
|
197
|
+
'top/middle/bottom',
|
|
198
|
+
'top/middle/bottom/deep',
|
|
199
|
+
]);
|
|
200
|
+
const deep = /** @type {any} */ (tree.get('top/middle/bottom/deep'));
|
|
201
|
+
expect(deep).toMatchObject({
|
|
202
|
+
id: 'astryx:artifact:v1/%40acme%2Fkit/generic/deep',
|
|
203
|
+
parent: 'top/middle/bottom',
|
|
204
|
+
slot: 'items',
|
|
205
|
+
order: 1,
|
|
206
|
+
generated: false,
|
|
207
|
+
});
|
|
208
|
+
expect(tree.ancestors(deep).map(node => node.route)).toEqual([
|
|
209
|
+
'top',
|
|
210
|
+
'top/middle',
|
|
211
|
+
'top/middle/bottom',
|
|
212
|
+
]);
|
|
213
|
+
expect(tree.roots().map(node => node.route)).toEqual(['top']);
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
it('adopts typed docs by group, with one generated level per kind', () => {
|
|
217
|
+
const tree = buildDocsTree({
|
|
218
|
+
namespaces: [
|
|
219
|
+
ns('api', {
|
|
220
|
+
slots: {kinds: {title: 'Reference', accepts: {kinds: ['namespace']}}},
|
|
221
|
+
adopts: [
|
|
222
|
+
{
|
|
223
|
+
source: {group: 'kit/api', kinds: ['function', 'enum']},
|
|
224
|
+
into: 'kinds',
|
|
225
|
+
groupBy: 'kind',
|
|
226
|
+
},
|
|
227
|
+
],
|
|
228
|
+
}),
|
|
229
|
+
],
|
|
230
|
+
docs: [
|
|
231
|
+
typed('enum', 'errorCodes', 'kit/api'),
|
|
232
|
+
typed('function', 'search', 'kit/api'),
|
|
233
|
+
typed('function', 'build', 'kit/api'),
|
|
234
|
+
typed('schema', 'config', 'kit/api'),
|
|
235
|
+
typed('function', 'other', 'kit/elsewhere'),
|
|
236
|
+
],
|
|
237
|
+
});
|
|
238
|
+
expect(problems(tree)).toEqual([]);
|
|
239
|
+
expect(routes(tree)).toEqual([
|
|
240
|
+
'api',
|
|
241
|
+
'api/enums',
|
|
242
|
+
'api/enums/error-codes',
|
|
243
|
+
'api/functions',
|
|
244
|
+
'api/functions/build',
|
|
245
|
+
'api/functions/search',
|
|
246
|
+
]);
|
|
247
|
+
const functions = /** @type {any} */ (tree.get('api/functions'));
|
|
248
|
+
expect(functions).toMatchObject({
|
|
249
|
+
id: null,
|
|
250
|
+
kind: 'namespace',
|
|
251
|
+
title: KIND_GROUPS.function.title,
|
|
252
|
+
generated: true,
|
|
253
|
+
parent: 'api',
|
|
254
|
+
slot: 'kinds',
|
|
255
|
+
});
|
|
256
|
+
// Kind levels follow the rule's kind order; docs inside sort by title.
|
|
257
|
+
expect(tree.get('api')?.slots[0].children).toEqual([
|
|
258
|
+
'api/functions',
|
|
259
|
+
'api/enums',
|
|
260
|
+
]);
|
|
261
|
+
expect(functions.slots[0].children).toEqual([
|
|
262
|
+
'api/functions/build',
|
|
263
|
+
'api/functions/search',
|
|
264
|
+
]);
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
it('adopts without grouping straight into the named slot', () => {
|
|
268
|
+
const tree = buildDocsTree({
|
|
269
|
+
namespaces: [
|
|
270
|
+
ns('commands', {
|
|
271
|
+
slots: {all: {title: 'All', accepts: {kinds: ['command']}}},
|
|
272
|
+
adopts: [{source: {group: 'kit/commands'}, into: 'all'}],
|
|
273
|
+
}),
|
|
274
|
+
],
|
|
275
|
+
docs: [typed('command', 'theme add', 'kit/commands')],
|
|
276
|
+
});
|
|
277
|
+
expect(routes(tree)).toEqual(['commands', 'commands/theme-add']);
|
|
278
|
+
expect(tree.get('commands')?.slots[0].children).toEqual([
|
|
279
|
+
'commands/theme-add',
|
|
280
|
+
]);
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
it('prefers explicit placement over adoption, and never falls back', () => {
|
|
284
|
+
const namespaces = [
|
|
285
|
+
ns('guides'),
|
|
286
|
+
ns('api', {
|
|
287
|
+
slots: {all: {title: 'All', accepts: {kinds: ['generic']}}},
|
|
288
|
+
adopts: [{source: {group: 'kit/api'}, into: 'all'}],
|
|
289
|
+
}),
|
|
290
|
+
];
|
|
291
|
+
const placed = buildDocsTree({
|
|
292
|
+
namespaces,
|
|
293
|
+
docs: [
|
|
294
|
+
guide('intro', {
|
|
295
|
+
group: 'kit/api',
|
|
296
|
+
placement: {parent: 'namespace:guides'},
|
|
297
|
+
}),
|
|
298
|
+
],
|
|
299
|
+
});
|
|
300
|
+
expect(routes(placed)).toContain('guides/intro');
|
|
301
|
+
expect(routes(placed)).not.toContain('api/intro');
|
|
302
|
+
|
|
303
|
+
const broken = buildDocsTree({
|
|
304
|
+
namespaces,
|
|
305
|
+
docs: [
|
|
306
|
+
guide('intro', {
|
|
307
|
+
group: 'kit/api',
|
|
308
|
+
placement: {parent: 'namespace:nope'},
|
|
309
|
+
}),
|
|
310
|
+
],
|
|
311
|
+
});
|
|
312
|
+
expect(routes(broken).some(route => route.endsWith('/intro'))).toBe(false);
|
|
313
|
+
expect(problems(broken)).toEqual([
|
|
314
|
+
[
|
|
315
|
+
'invalid_placement',
|
|
316
|
+
'placement.parent "namespace:nope" names no namespace; @acme/kit declares "api", "guides".',
|
|
317
|
+
],
|
|
318
|
+
]);
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
it('reports every way a placement can fail', () => {
|
|
322
|
+
const tree = buildDocsTree({
|
|
323
|
+
namespaces: [
|
|
324
|
+
ns('home', {
|
|
325
|
+
slots: {
|
|
326
|
+
one: {title: 'One', accepts: {kinds: ['generic']}},
|
|
327
|
+
two: {title: 'Two', accepts: {kinds: ['command']}},
|
|
328
|
+
},
|
|
329
|
+
}),
|
|
330
|
+
],
|
|
331
|
+
docs: [
|
|
332
|
+
guide('no-slot', {placement: {parent: 'namespace:home'}}),
|
|
333
|
+
guide('bad-slot', {
|
|
334
|
+
placement: {parent: 'namespace:home', slot: 'three'},
|
|
335
|
+
}),
|
|
336
|
+
guide('wrong-kind', {
|
|
337
|
+
placement: {parent: 'namespace:home', slot: 'two'},
|
|
338
|
+
}),
|
|
339
|
+
guide('other-package', {
|
|
340
|
+
placement: {parent: '@other/pkg/namespace/home'},
|
|
341
|
+
}),
|
|
342
|
+
guide('not-a-ref', {placement: {parent: 'home'}}),
|
|
343
|
+
],
|
|
344
|
+
});
|
|
345
|
+
expect(routes(tree)).toEqual(['home']);
|
|
346
|
+
expect(
|
|
347
|
+
problems(tree)
|
|
348
|
+
.map(([, message]) => message)
|
|
349
|
+
.sort(),
|
|
350
|
+
).toEqual(
|
|
351
|
+
[
|
|
352
|
+
'placement names no slot, and namespace "home" has 2 (one, two). Name one with placement.slot.',
|
|
353
|
+
'placement.slot "three" is not a slot of namespace "home"; it declares one, two.',
|
|
354
|
+
'slot "two" of namespace "home" does not accept generic docs; it accepts command.',
|
|
355
|
+
'placement.parent "@other/pkg/namespace/home" belongs to @other/pkg. A doc can only be placed in a namespace of its own package (@acme/kit).',
|
|
356
|
+
'placement.parent "home" is not a namespace reference. Write "namespace:<name>".',
|
|
357
|
+
].sort(),
|
|
358
|
+
);
|
|
359
|
+
expect(tree.diagnostics.every(d => d.code === 'invalid_placement')).toBe(
|
|
360
|
+
true,
|
|
361
|
+
);
|
|
362
|
+
expect(tree.diagnostics.every(d => d.severity === 'error')).toBe(true);
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
it('fails a doc two namespaces adopt, naming both', () => {
|
|
366
|
+
const rule = {source: {group: 'kit/api'}, into: 'items'};
|
|
367
|
+
const tree = buildDocsTree({
|
|
368
|
+
namespaces: [ns('a', {adopts: [rule]}), ns('b', {adopts: [rule]})],
|
|
369
|
+
docs: [guide('shared', {group: 'kit/api'})],
|
|
370
|
+
});
|
|
371
|
+
expect(routes(tree)).toEqual(['a', 'b']);
|
|
372
|
+
expect(problems(tree)).toEqual([
|
|
373
|
+
[
|
|
374
|
+
'overlapping_adoption',
|
|
375
|
+
'@acme/kit/generic/shared is adopted by "a" and "b"; exactly one namespace may adopt a doc.',
|
|
376
|
+
],
|
|
377
|
+
]);
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
it('fails two docs at one route, keeping the first by identity', () => {
|
|
381
|
+
const tree = buildDocsTree({
|
|
382
|
+
namespaces: [ns('home')],
|
|
383
|
+
docs: [
|
|
384
|
+
guide('fooBar', {placement: {parent: 'namespace:home'}}),
|
|
385
|
+
guide('foo_bar', {placement: {parent: 'namespace:home'}}),
|
|
386
|
+
],
|
|
387
|
+
});
|
|
388
|
+
expect(routes(tree)).toEqual(['home', 'home/foo-bar']);
|
|
389
|
+
expect(tree.get('home/foo-bar')?.id).toBe(
|
|
390
|
+
'astryx:artifact:v1/%40acme%2Fkit/generic/fooBar',
|
|
391
|
+
);
|
|
392
|
+
expect(problems(tree)).toEqual([
|
|
393
|
+
[
|
|
394
|
+
'duplicate_route',
|
|
395
|
+
'astryx:artifact:v1/%40acme%2Fkit/generic/foo_bar and astryx:artifact:v1/%40acme%2Fkit/generic/fooBar both have the route "home/foo-bar". Rename or move one of them.',
|
|
396
|
+
],
|
|
397
|
+
]);
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
it('fails a namespace cycle and everything under it', () => {
|
|
401
|
+
const tree = buildDocsTree({
|
|
402
|
+
namespaces: [
|
|
403
|
+
ns('a', {placement: {parent: 'namespace:b'}}),
|
|
404
|
+
ns('b', {placement: {parent: 'namespace:a'}}),
|
|
405
|
+
],
|
|
406
|
+
docs: [guide('lost', {placement: {parent: 'namespace:a'}})],
|
|
407
|
+
});
|
|
408
|
+
expect(routes(tree)).toEqual([]);
|
|
409
|
+
expect(problems(tree).map(([code]) => code)).toEqual([
|
|
410
|
+
'invalid_placement',
|
|
411
|
+
'invalid_placement',
|
|
412
|
+
'invalid_placement',
|
|
413
|
+
]);
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
it('fails a duplicate or unsafe namespace name', () => {
|
|
417
|
+
const tree = buildDocsTree({
|
|
418
|
+
namespaces: [
|
|
419
|
+
ns('twice'),
|
|
420
|
+
{...ns('twice'), source: `${P}/other.doc.mjs`},
|
|
421
|
+
ns('Bad Name'),
|
|
422
|
+
],
|
|
423
|
+
docs: [],
|
|
424
|
+
});
|
|
425
|
+
expect(routes(tree)).toEqual(['twice']);
|
|
426
|
+
expect(tree.diagnostics.map(d => d.code)).toEqual([
|
|
427
|
+
'invalid_namespace',
|
|
428
|
+
'invalid_namespace',
|
|
429
|
+
]);
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
it('leaves a doc with no placement and no adoption out, in phase 1', () => {
|
|
433
|
+
const tree = buildDocsTree({
|
|
434
|
+
namespaces: [ns('home')],
|
|
435
|
+
docs: [guide('loose'), typed('function', 'free', 'kit/nowhere')],
|
|
436
|
+
});
|
|
437
|
+
expect(routes(tree)).toEqual(['home']);
|
|
438
|
+
expect(tree.diagnostics).toEqual([]);
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
it('is the same tree whatever order its inputs arrive in', () => {
|
|
442
|
+
const namespaces = [
|
|
443
|
+
ns('top'),
|
|
444
|
+
ns('child', {placement: {parent: 'namespace:top'}}),
|
|
445
|
+
];
|
|
446
|
+
const docs = [
|
|
447
|
+
guide('b', {placement: {parent: 'namespace:child'}}),
|
|
448
|
+
guide('a', {placement: {parent: 'namespace:child'}}),
|
|
449
|
+
];
|
|
450
|
+
const one = buildDocsTree({namespaces, docs});
|
|
451
|
+
const two = buildDocsTree({
|
|
452
|
+
namespaces: [...namespaces].reverse(),
|
|
453
|
+
docs: [...docs].reverse(),
|
|
454
|
+
});
|
|
455
|
+
expect(JSON.stringify([...two.nodes])).toBe(JSON.stringify([...one.nodes]));
|
|
456
|
+
});
|
|
457
|
+
|
|
458
|
+
it('orders children by order, then title', () => {
|
|
459
|
+
const tree = buildDocsTree({
|
|
460
|
+
namespaces: [ns('home')],
|
|
461
|
+
docs: [
|
|
462
|
+
guide('z', {
|
|
463
|
+
title: 'Zed',
|
|
464
|
+
placement: {parent: 'namespace:home', order: 1},
|
|
465
|
+
}),
|
|
466
|
+
guide('b', {title: 'Beta', placement: {parent: 'namespace:home'}}),
|
|
467
|
+
guide('a', {title: 'Alpha', placement: {parent: 'namespace:home'}}),
|
|
468
|
+
],
|
|
469
|
+
});
|
|
470
|
+
expect(tree.get('home')?.slots[0].children).toEqual([
|
|
471
|
+
'home/z',
|
|
472
|
+
'home/a',
|
|
473
|
+
'home/b',
|
|
474
|
+
]);
|
|
475
|
+
});
|
|
476
|
+
});
|
|
477
|
+
|
|
478
|
+
describe('routeSegment', () => {
|
|
479
|
+
it('joins lowercase words with hyphens, whatever the name looks like', () => {
|
|
480
|
+
expect(routeSegment('integrationPackCheck')).toBe('integration-pack-check');
|
|
481
|
+
expect(routeSegment('doctor integration validate')).toBe(
|
|
482
|
+
'doctor-integration-validate',
|
|
483
|
+
);
|
|
484
|
+
expect(routeSegment('error-codes')).toBe('error-codes');
|
|
485
|
+
expect(routeSegment('isError')).toBe('is-error');
|
|
486
|
+
expect(routeSegment('!!')).toBe('');
|
|
487
|
+
});
|
|
488
|
+
});
|
|
489
|
+
|
|
490
|
+
describe("the CLI's own docs tree", () => {
|
|
491
|
+
it(
|
|
492
|
+
'builds with no diagnostic, rooted at cli',
|
|
493
|
+
async () => {
|
|
494
|
+
const tree = await loadDocsTree({fresh: true});
|
|
495
|
+
expect(tree.diagnostics).toEqual([]);
|
|
496
|
+
expect(tree.roots().map(node => node.route)).toEqual(['cli']);
|
|
497
|
+
expect(
|
|
498
|
+
tree.get('cli')?.slots.map(slot => [slot.name, slot.children]),
|
|
499
|
+
).toEqual([
|
|
500
|
+
['guides', ['cli/integrations', 'cli/writing-docs']],
|
|
501
|
+
['reference', ['cli/commands', 'cli/api']],
|
|
502
|
+
]);
|
|
503
|
+
expect(tree.get('cli/api')?.slots[0].children).toEqual([
|
|
504
|
+
'cli/api/functions',
|
|
505
|
+
'cli/api/schemas',
|
|
506
|
+
'cli/api/enums',
|
|
507
|
+
]);
|
|
508
|
+
},
|
|
509
|
+
SLOW,
|
|
510
|
+
);
|
|
511
|
+
|
|
512
|
+
it(
|
|
513
|
+
'gives every CLI typed doc in a cli group one route, by its kind',
|
|
514
|
+
async () => {
|
|
515
|
+
const tree = await loadDocsTree();
|
|
516
|
+
const {loaded} = await loadCliSelfDocs();
|
|
517
|
+
const inTree = loaded.filter(({doc}) =>
|
|
518
|
+
String(doc.namespace).startsWith('cli/'),
|
|
519
|
+
);
|
|
520
|
+
expect(inTree.length).toBeGreaterThan(0);
|
|
521
|
+
const expected = inTree.map(({doc}) =>
|
|
522
|
+
doc.type === 'command'
|
|
523
|
+
? `cli/commands/${routeSegment(doc.name)}`
|
|
524
|
+
: `cli/api/${KIND_GROUPS[doc.type].segment}/${routeSegment(doc.name)}`,
|
|
525
|
+
);
|
|
526
|
+
expect(expected.filter(route => tree.get(route) == null)).toEqual([]);
|
|
527
|
+
// A doc in the authoring group stays a section of `astryx docs authoring`.
|
|
528
|
+
const authoring = loaded.filter(({doc}) => doc.namespace === 'authoring');
|
|
529
|
+
expect(authoring.length).toBeGreaterThan(0);
|
|
530
|
+
const ids = new Set([...tree.nodes.values()].map(node => node.id));
|
|
531
|
+
expect(
|
|
532
|
+
authoring.filter(({doc}) =>
|
|
533
|
+
ids.has(createDocId(CLI_PROVIDER_ID, doc.type, doc.name)),
|
|
534
|
+
),
|
|
535
|
+
).toEqual([]);
|
|
536
|
+
},
|
|
537
|
+
SLOW,
|
|
538
|
+
);
|
|
539
|
+
|
|
540
|
+
it(
|
|
541
|
+
'gives every function @astryxdesign/cli/api exports a route',
|
|
542
|
+
async () => {
|
|
543
|
+
const tree = await loadDocsTree();
|
|
544
|
+
const exported = Object.entries(api)
|
|
545
|
+
.filter(
|
|
546
|
+
([, value]) =>
|
|
547
|
+
typeof value === 'function' &&
|
|
548
|
+
Object.getOwnPropertyDescriptor(value, 'prototype')?.writable !==
|
|
549
|
+
false,
|
|
550
|
+
)
|
|
551
|
+
.map(([name]) => `cli/api/functions/${routeSegment(name)}`);
|
|
552
|
+
expect(exported.length).toBeGreaterThan(0);
|
|
553
|
+
expect(exported.filter(route => tree.get(route) == null)).toEqual([]);
|
|
554
|
+
},
|
|
555
|
+
SLOW,
|
|
556
|
+
);
|
|
557
|
+
|
|
558
|
+
it(
|
|
559
|
+
'reads only namespace and generic docs from the tree directory, each named after its file',
|
|
560
|
+
async () => {
|
|
561
|
+
const inputs = await loadTreeInputs({selfDocs: false});
|
|
562
|
+
expect(inputs.diagnostics).toEqual([]);
|
|
563
|
+
expect(inputs.namespaces.map(n => n.doc.name).sort()).toEqual([
|
|
564
|
+
'api',
|
|
565
|
+
'cli',
|
|
566
|
+
'commands',
|
|
567
|
+
]);
|
|
568
|
+
expect(inputs.docs.map(d => [d.name, d.placement?.parent])).toEqual([
|
|
569
|
+
['integrations', 'namespace:cli'],
|
|
570
|
+
['writing-docs', 'namespace:cli'],
|
|
571
|
+
]);
|
|
572
|
+
},
|
|
573
|
+
SLOW,
|
|
574
|
+
);
|
|
575
|
+
});
|
|
576
|
+
|
|
577
|
+
describe('doc identity', () => {
|
|
578
|
+
it('builds each id from the provider id, never the package name', () => {
|
|
579
|
+
const provider = '@acme/tree-provider';
|
|
580
|
+
const tree = buildDocsTree({
|
|
581
|
+
namespaces: [{...ns('home'), providerId: provider}],
|
|
582
|
+
docs: [
|
|
583
|
+
{
|
|
584
|
+
...guide('intro', {placement: {parent: 'namespace:home'}}),
|
|
585
|
+
providerId: provider,
|
|
586
|
+
},
|
|
587
|
+
],
|
|
588
|
+
});
|
|
589
|
+
expect(problems(tree)).toEqual([]);
|
|
590
|
+
expect(tree.get('home')?.id).toBe(
|
|
591
|
+
'astryx:artifact:v1/%40acme%2Ftree-provider/namespace/home',
|
|
592
|
+
);
|
|
593
|
+
expect(tree.get('home/intro')).toMatchObject({
|
|
594
|
+
id: 'astryx:artifact:v1/%40acme%2Ftree-provider/generic/intro',
|
|
595
|
+
provider: P,
|
|
596
|
+
});
|
|
597
|
+
});
|
|
598
|
+
});
|
|
@@ -20,31 +20,13 @@ export function lowestAdmitted(range: unknown): string | null;
|
|
|
20
20
|
*/
|
|
21
21
|
export function docsTreeCliProblem(pkg: any): string | null;
|
|
22
22
|
/**
|
|
23
|
-
* Why a package with a template that sets `replaces` would lose templates
|
|
24
|
-
* doc topics on an older CLI (spec:AST-035), or null when its declared CLI
|
|
23
|
+
* Why a package with a template that sets `replaces` would lose its templates
|
|
24
|
+
* and doc topics on an older CLI (spec:AST-035), or null when its declared CLI
|
|
25
25
|
* range admits only CLIs that read the field.
|
|
26
26
|
* @param {any} pkg package.json
|
|
27
27
|
* @returns {string | null}
|
|
28
28
|
*/
|
|
29
29
|
export function replacesCliProblem(pkg: any): string | null;
|
|
30
|
-
/**
|
|
31
|
-
* Why a package with a doc section that sets `id` would lose its doc topics on
|
|
32
|
-
* an older CLI, or null when its declared CLI range admits only CLIs that read
|
|
33
|
-
* the field. Published 0.6.3 rejects a section `id` and hides every doc topic
|
|
34
|
-
* the package ships.
|
|
35
|
-
* @param {any} pkg package.json
|
|
36
|
-
* @returns {string | null}
|
|
37
|
-
*/
|
|
38
|
-
export function sectionIdsCliProblem(pkg: any): string | null;
|
|
39
|
-
/**
|
|
40
|
-
* Why a package that ships a theme would lose its themes and doc topics on an
|
|
41
|
-
* older CLI, or null when its declared CLI range admits only CLIs that read
|
|
42
|
-
* typed theme descriptors. Published 0.6.3 rejects a themes root with no
|
|
43
|
-
* `manifest.json` catalog, which `integration add theme` no longer writes.
|
|
44
|
-
* @param {any} pkg package.json
|
|
45
|
-
* @returns {string | null}
|
|
46
|
-
*/
|
|
47
|
-
export function themesCliProblem(pkg: any): string | null;
|
|
48
30
|
/**
|
|
49
31
|
* The package.json with a CLI peer that reads namespace docs: optional, unless
|
|
50
32
|
* the package already says otherwise.
|
|
@@ -55,11 +37,9 @@ export function withDocsTreeCli(pkg: any): any;
|
|
|
55
37
|
export const CLI_PACKAGE: "@astryxdesign/cli";
|
|
56
38
|
/**
|
|
57
39
|
* The first CLI release that reads an integration's docs tree (namespace docs
|
|
58
|
-
* and placed guides)
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
* rejects a themes root without the `manifest.json` catalog the CLI no longer
|
|
63
|
-
* writes, withholding the package's themes and doc topics.
|
|
40
|
+
* and placed guides) and its templates' `replaces`. A release before it can
|
|
41
|
+
* hide every doc topic a package with a namespace doc or a placed guide
|
|
42
|
+
* ships, with no warning, and it rejects `replaces` and withholds the
|
|
43
|
+
* package's templates and doc topics.
|
|
64
44
|
*/
|
|
65
45
|
export const DOCS_TREE_CLI: "0.7.0";
|