@astryxdesign/cli 0.7.2 → 0.7.3-canary.0bf23bd
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 +115 -3
- package/api/build/blocks/blocks.d.mts +42 -0
- package/api/build/blocks/blocks.mjs +169 -0
- package/api/build/blocks/blocks.test.mjs +108 -0
- package/api/build/blocks/blocks.weights.json +1 -0
- package/api/build/build.mjs +25 -6
- package/api/build/kit/answer.d.mts +14 -0
- package/api/build/kit/answer.mjs +85 -0
- package/api/build/kit/answer.test.mjs +38 -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 +60 -0
- package/api/build/kit/signals.mjs +284 -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 +52 -0
- package/api/build/tree.test.mjs +177 -0
- package/api/build/tree.weights.json +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.mjs +36 -9
- package/api/discover/_adapter.test.mjs +42 -0
- package/api/docs/_adapter.d.mts +2 -2
- package/api/docs/_adapter.mjs +78 -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/doctor.mjs +102 -24
- package/api/doctor/doctor.test.mjs +37 -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-gaps.test.mjs +1964 -0
- package/api/integration/validate-integration.d.mts +11 -2
- package/api/integration/validate-integration.mjs +250 -32
- package/api/integration/validate-integration.type.d.mts +59 -1
- package/api/integration/validate-integration.type.mjs +46 -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 +52 -0
- package/api/search/_entries.mjs +214 -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/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 +2 -2
- 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 +1 -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.mjs +30 -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 +2 -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 +61 -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 +29 -86
- 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 +20 -7
- package/foundation/agent-docs/agent-doc-state.mjs +35 -8
- package/foundation/agent-docs/agent-docs.d.mts +100 -12
- package/foundation/agent-docs/agent-docs.mjs +1012 -100
- package/foundation/agent-docs/agent-docs.path-safety.test.mjs +1239 -17
- package/foundation/agent-docs/agent-docs.test.mjs +683 -39
- 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/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/integrations.d.mts +27 -1
- package/foundation/integrations/integrations.mjs +61 -2
- package/foundation/integrations/validate-contributions.d.mts +115 -0
- package/foundation/integrations/validate-contributions.mjs +1168 -13
- package/foundation/release/handoff.d.mts +23 -4
- package/foundation/release/handoff.mjs +175 -8
- 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/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
|
@@ -21,6 +21,10 @@ import {
|
|
|
21
21
|
withDeclaredOfficial,
|
|
22
22
|
} from './_adapter.mjs';
|
|
23
23
|
import {parseDiscoverCatalog} from '../../authoring/discover/parse.mjs';
|
|
24
|
+
import {
|
|
25
|
+
_resetHostedRun,
|
|
26
|
+
activateHostedRun,
|
|
27
|
+
} from '../../foundation/runtime/package-root.mjs';
|
|
24
28
|
|
|
25
29
|
/** No official packages, so a test sees only its own sources after it. */
|
|
26
30
|
const NO_OFFICIAL = {packages: []};
|
|
@@ -230,6 +234,44 @@ describe('callSources', () => {
|
|
|
230
234
|
expect(otherRequest.sources[0].status).toBe('failed');
|
|
231
235
|
});
|
|
232
236
|
|
|
237
|
+
it("keeps a host's saved copies per host, so one tool never answers with another's", async () => {
|
|
238
|
+
let online = true;
|
|
239
|
+
const source = async () => {
|
|
240
|
+
if (!online) throw new Error('offline');
|
|
241
|
+
return catalog('Acme catalog', [pkg('@acme/one')]);
|
|
242
|
+
};
|
|
243
|
+
const options = {cacheDir, official: NO_OFFICIAL};
|
|
244
|
+
try {
|
|
245
|
+
activateHostedRun({
|
|
246
|
+
discoverSources: [source],
|
|
247
|
+
startingRoot: '/tools/acme',
|
|
248
|
+
});
|
|
249
|
+
await callSources(undefined, {}, options);
|
|
250
|
+
online = false;
|
|
251
|
+
const sameHost = await callSources(undefined, {}, options);
|
|
252
|
+
expect(sameHost.sources[0]).toMatchObject({
|
|
253
|
+
name: 'Acme catalog',
|
|
254
|
+
from: 'the host',
|
|
255
|
+
status: 'saved',
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
_resetHostedRun();
|
|
259
|
+
activateHostedRun({
|
|
260
|
+
discoverSources: [source],
|
|
261
|
+
startingRoot: '/tools/other',
|
|
262
|
+
});
|
|
263
|
+
const otherHost = await callSources(undefined, {}, options);
|
|
264
|
+
expect(otherHost.sources[0]).toMatchObject({
|
|
265
|
+
from: 'the host',
|
|
266
|
+
status: 'failed',
|
|
267
|
+
error: 'offline',
|
|
268
|
+
});
|
|
269
|
+
expect(otherHost.packages).toEqual([]);
|
|
270
|
+
} finally {
|
|
271
|
+
_resetHostedRun();
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
|
|
233
275
|
it('keeps the saved copy in the cache directory, not in the project', async () => {
|
|
234
276
|
await callSources(
|
|
235
277
|
project({
|
package/api/docs/_adapter.d.mts
CHANGED
|
@@ -226,7 +226,7 @@ export function topicUp(entry: import("../../foundation/discovery/docs-discovery
|
|
|
226
226
|
export function placeLinks(tree: DocsTree, node: TreeNode): import("./docs.type.mjs").DocsLinks;
|
|
227
227
|
/**
|
|
228
228
|
* The moves a topic read offers: from its place in the tree, where a guide
|
|
229
|
-
* sits in its namespace and a flat topic in
|
|
229
|
+
* sits in its namespace and a flat topic in its topic level.
|
|
230
230
|
* @param {DocsCatalog} catalog
|
|
231
231
|
* @param {import('../../foundation/discovery/docs-discovery.mjs').DocsTopicEntry} entry
|
|
232
232
|
* @returns {Promise<import('./docs.type.mjs').DocsLinks>}
|
|
@@ -290,7 +290,7 @@ export function holdsOwnName(tree: DocsTree, catalog: DocsCatalog, entry: import
|
|
|
290
290
|
/**
|
|
291
291
|
* The doc that took a flat topic's route in the docs tree, when it is not
|
|
292
292
|
* that topic (spec:AST-046 FR11): the CLI keeps its routes, such as `cli`
|
|
293
|
-
* and `
|
|
293
|
+
* and `guides`, and a namespace keeps its route over a topic of the same
|
|
294
294
|
* name. Null when the topic owns its route, or the tree has no node there.
|
|
295
295
|
* @param {DocsTree} tree
|
|
296
296
|
* @param {import('../../foundation/discovery/docs-discovery.mjs').DocsTopicEntry} entry
|
package/api/docs/_adapter.mjs
CHANGED
|
@@ -52,6 +52,7 @@ import {
|
|
|
52
52
|
cliDocSection,
|
|
53
53
|
} from '../../foundation/discovery/cli-self-docs.mjs';
|
|
54
54
|
import {
|
|
55
|
+
AUTHORING_REFERENCE_ROUTE,
|
|
55
56
|
loadAuthoringSelfDocs,
|
|
56
57
|
schemaFieldTable,
|
|
57
58
|
selfDocSection,
|
|
@@ -385,7 +386,7 @@ export function projectTree(catalog, {fresh = false} = {}) {
|
|
|
385
386
|
let cliTreeInputs;
|
|
386
387
|
|
|
387
388
|
/**
|
|
388
|
-
* Every flat topic in the catalog, as the tree's
|
|
389
|
+
* Every flat topic in the catalog, as the tree's topic levels read it.
|
|
389
390
|
* @param {DocsCatalog} catalog
|
|
390
391
|
* @returns {Promise<import('../../foundation/doc-compiler/tree.mjs').TreeTopicInput[]>}
|
|
391
392
|
*/
|
|
@@ -394,12 +395,13 @@ async function flatTopicInputs(catalog) {
|
|
|
394
395
|
const topics = [];
|
|
395
396
|
for (const entry of catalog.entries()) {
|
|
396
397
|
const aliases = catalog.aliasesOf(entry);
|
|
397
|
-
let {title, description} = entry;
|
|
398
|
-
if (title == null || description == null) {
|
|
398
|
+
let {title, description, category} = entry;
|
|
399
|
+
if (title == null || description == null || category === undefined) {
|
|
399
400
|
try {
|
|
400
401
|
const file = await loadTopicFile(entry.path, null);
|
|
401
402
|
title ??= file.doc?.title;
|
|
402
403
|
description ??= file.doc?.description;
|
|
404
|
+
category ??= file.doc?.category;
|
|
403
405
|
} catch {
|
|
404
406
|
// A topic that does not load is reported where it is read.
|
|
405
407
|
}
|
|
@@ -410,6 +412,7 @@ async function flatTopicInputs(catalog) {
|
|
|
410
412
|
name: entry.name,
|
|
411
413
|
title: title ?? entry.name,
|
|
412
414
|
summary: description ?? '',
|
|
415
|
+
category: category ?? null,
|
|
413
416
|
source: `${entry.package}:${entry.name}`,
|
|
414
417
|
...(aliases.length > 0 ? {aliases} : {}),
|
|
415
418
|
});
|
|
@@ -419,7 +422,7 @@ async function flatTopicInputs(catalog) {
|
|
|
419
422
|
|
|
420
423
|
/**
|
|
421
424
|
* The CLI's tree, each configured integration's namespaces and guides, and
|
|
422
|
-
* every flat topic in the generated
|
|
425
|
+
* every flat topic in the generated level for its category.
|
|
423
426
|
* @param {DocsCatalog} catalog
|
|
424
427
|
* @param {boolean} fresh
|
|
425
428
|
* @returns {Promise<DocsTree>}
|
|
@@ -509,23 +512,22 @@ function identitiesOf(tree) {
|
|
|
509
512
|
}
|
|
510
513
|
|
|
511
514
|
/**
|
|
512
|
-
* The CLI's authoring docs, by kind and name.
|
|
513
|
-
* each as one section keyed by its name, so a
|
|
514
|
-
* Loaded once per process, like the CLI's
|
|
515
|
+
* The CLI's authoring docs, by kind and name. The field reference under
|
|
516
|
+
* `astryx docs authoring` reads each as one section keyed by its name, so a
|
|
517
|
+
* link to one opens that section. Loaded once per process, like the CLI's
|
|
518
|
+
* tree files.
|
|
515
519
|
* @type {Promise<Map<string, any>> | undefined}
|
|
516
520
|
*/
|
|
517
521
|
let authoringDocs;
|
|
518
522
|
|
|
519
523
|
/**
|
|
520
|
-
* The CLI authoring doc a link names
|
|
521
|
-
*
|
|
522
|
-
* @param {DocsCatalog} catalog
|
|
524
|
+
* The CLI authoring doc a link names. The `authoring` namespace is the CLI's
|
|
525
|
+
* own, so no integration can take its route.
|
|
523
526
|
* @param {string} kind
|
|
524
527
|
* @param {string} name
|
|
525
528
|
* @returns {Promise<any | null>}
|
|
526
529
|
*/
|
|
527
|
-
async function authoringDoc(
|
|
528
|
-
if (catalog.resolve('authoring')?.package !== CLI_PROVIDER_ID) return null;
|
|
530
|
+
async function authoringDoc(kind, name) {
|
|
529
531
|
authoringDocs ??= loadAuthoringSelfDocs().then(
|
|
530
532
|
({loaded}) =>
|
|
531
533
|
new Map(loaded.map(({doc}) => [`${doc.type}\u0000${doc.name}`, doc])),
|
|
@@ -611,14 +613,14 @@ function docFinderOver(catalog, tree, fromProvider, summaries = true) {
|
|
|
611
613
|
}
|
|
612
614
|
const authored =
|
|
613
615
|
provider === CLI_PROVIDER_ID
|
|
614
|
-
? await authoringDoc(
|
|
616
|
+
? await authoringDoc(parsed.kind, parsed.name)
|
|
615
617
|
: null;
|
|
616
618
|
if (authored) {
|
|
617
619
|
return {
|
|
618
620
|
link: {
|
|
619
621
|
target,
|
|
620
622
|
id: createDocId(provider, authored.type, authored.name),
|
|
621
|
-
route:
|
|
623
|
+
route: AUTHORING_REFERENCE_ROUTE,
|
|
622
624
|
title: authored.displayName ?? authored.name,
|
|
623
625
|
summary: authored.description ?? '',
|
|
624
626
|
command: `astryx docs authoring ${authored.name}`,
|
|
@@ -1146,6 +1148,14 @@ function packageCatalog(integration, discovered) {
|
|
|
1146
1148
|
* @returns {Promise<Array<{severity: 'warning', message: string}>>}
|
|
1147
1149
|
*/
|
|
1148
1150
|
export async function packageComponentLinkProblems(integration, discovered) {
|
|
1151
|
+
// A package with no provider id (its manifest's, else its name) links
|
|
1152
|
+
// nothing, as on the read path: its text reads as written, so there is
|
|
1153
|
+
// nothing to report.
|
|
1154
|
+
try {
|
|
1155
|
+
normalizeProviderId(integration.providerId ?? integration.name);
|
|
1156
|
+
} catch {
|
|
1157
|
+
return [];
|
|
1158
|
+
}
|
|
1149
1159
|
const catalog = packageCatalog(integration, discovered);
|
|
1150
1160
|
return (await componentLinkProblems(catalog, integration.name)).map(
|
|
1151
1161
|
message => ({severity: /** @type {const} */ ('warning'), message}),
|
|
@@ -1176,11 +1186,15 @@ async function componentLinkProblems(catalog, owner) {
|
|
|
1176
1186
|
// The components check reports a doc that does not load.
|
|
1177
1187
|
continue;
|
|
1178
1188
|
}
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
componentLinkProvider(record.package, record.providerId)
|
|
1182
|
-
|
|
1183
|
-
|
|
1189
|
+
let provider;
|
|
1190
|
+
try {
|
|
1191
|
+
provider = componentLinkProvider(record.package, record.providerId);
|
|
1192
|
+
} catch {
|
|
1193
|
+
// An owner that is not a provider id links nothing (as on the read
|
|
1194
|
+
// path); its text reads as written.
|
|
1195
|
+
continue;
|
|
1196
|
+
}
|
|
1197
|
+
const linked = await linkComponentDoc(catalog, provider, doc);
|
|
1184
1198
|
const name = typeof doc?.name === 'string' ? doc.name : record.name;
|
|
1185
1199
|
for (const problem of linked.problems) {
|
|
1186
1200
|
problems.push(
|
|
@@ -1416,7 +1430,7 @@ export function placeLinks(tree, node) {
|
|
|
1416
1430
|
|
|
1417
1431
|
/**
|
|
1418
1432
|
* The moves a topic read offers: from its place in the tree, where a guide
|
|
1419
|
-
* sits in its namespace and a flat topic in
|
|
1433
|
+
* sits in its namespace and a flat topic in its topic level.
|
|
1420
1434
|
* @param {DocsCatalog} catalog
|
|
1421
1435
|
* @param {import('../../foundation/discovery/docs-discovery.mjs').DocsTopicEntry} entry
|
|
1422
1436
|
* @returns {Promise<import('./docs.type.mjs').DocsLinks>}
|
|
@@ -1514,7 +1528,7 @@ function treeArgument(catalog, tree, node) {
|
|
|
1514
1528
|
/**
|
|
1515
1529
|
* The doc that took a flat topic's route in the docs tree, when it is not
|
|
1516
1530
|
* that topic (spec:AST-046 FR11): the CLI keeps its routes, such as `cli`
|
|
1517
|
-
* and `
|
|
1531
|
+
* and `guides`, and a namespace keeps its route over a topic of the same
|
|
1518
1532
|
* name. Null when the topic owns its route, or the tree has no node there.
|
|
1519
1533
|
* @param {DocsTree} tree
|
|
1520
1534
|
* @param {import('../../foundation/discovery/docs-discovery.mjs').DocsTopicEntry} entry
|
|
@@ -1528,6 +1542,35 @@ export function routeOwner(tree, entry) {
|
|
|
1528
1542
|
: node;
|
|
1529
1543
|
}
|
|
1530
1544
|
|
|
1545
|
+
/**
|
|
1546
|
+
* Routes that moved, old prefix first: the integration guides moved from
|
|
1547
|
+
* `cli/integrations` (and, before that, the `cli-integrations` topic) into
|
|
1548
|
+
* `authoring`, the one home for integration authors.
|
|
1549
|
+
* Only the not-found error reads this, to name where a doc went; an old route
|
|
1550
|
+
* opens nothing.
|
|
1551
|
+
*/
|
|
1552
|
+
const MOVED_ROUTES = [
|
|
1553
|
+
['cli/integrations', 'authoring'],
|
|
1554
|
+
['cli-integrations', 'authoring'],
|
|
1555
|
+
];
|
|
1556
|
+
|
|
1557
|
+
/**
|
|
1558
|
+
* The node an old route moved to, or null.
|
|
1559
|
+
* @param {unknown} topic
|
|
1560
|
+
* @param {DocsTree} tree
|
|
1561
|
+
* @returns {TreeNode | null}
|
|
1562
|
+
*/
|
|
1563
|
+
function movedRoute(topic, tree) {
|
|
1564
|
+
if (typeof topic !== 'string') return null;
|
|
1565
|
+
const wanted = topic.toLowerCase();
|
|
1566
|
+
for (const [from, to] of MOVED_ROUTES) {
|
|
1567
|
+
if (wanted !== from && !wanted.startsWith(`${from}/`)) continue;
|
|
1568
|
+
const node = tree.getFolded(`${to}${wanted.slice(from.length)}`);
|
|
1569
|
+
if (node) return node;
|
|
1570
|
+
}
|
|
1571
|
+
return null;
|
|
1572
|
+
}
|
|
1573
|
+
|
|
1531
1574
|
/**
|
|
1532
1575
|
* The error for a docs argument that names nothing. For a route, it suggests
|
|
1533
1576
|
* the children of the deepest namespace the route reaches; otherwise, every
|
|
@@ -1560,8 +1603,7 @@ export async function unknownTopicError(topic, catalog) {
|
|
|
1560
1603
|
}
|
|
1561
1604
|
if (suggestions.length === 0 && typeof topic === 'string') {
|
|
1562
1605
|
// The docs whose own name it is (`doctor` is cli/commands/doctor), or whose
|
|
1563
|
-
// route it spells with hyphens (`cli-
|
|
1564
|
-
// it moved to cli/integrations).
|
|
1606
|
+
// route it spells with hyphens (`cli-host-entry` is cli/host-entry).
|
|
1565
1607
|
const wanted = topic.toLowerCase();
|
|
1566
1608
|
suggestions = [...tree.nodes.values()]
|
|
1567
1609
|
.filter(
|
|
@@ -1580,6 +1622,19 @@ export async function unknownTopicError(topic, catalog) {
|
|
|
1580
1622
|
...catalog.names().map(name => ({name, reason: 'available topic'})),
|
|
1581
1623
|
];
|
|
1582
1624
|
}
|
|
1625
|
+
// A route that moved names where it went, ahead of the usual suggestions
|
|
1626
|
+
// (spec:AST-046 FR9, FR6).
|
|
1627
|
+
const moved = movedRoute(topic, tree);
|
|
1628
|
+
if (moved) {
|
|
1629
|
+
return new AstryxError(
|
|
1630
|
+
`Unknown topic "${String(topic)}". It moved to "${moved.route}"${notLoaded(catalog)}`,
|
|
1631
|
+
[
|
|
1632
|
+
{name: moved.route, reason: moved.summary},
|
|
1633
|
+
...suggestions.filter(entry => entry.name !== moved.route),
|
|
1634
|
+
],
|
|
1635
|
+
ERROR_CODES.ERR_UNKNOWN_TOPIC,
|
|
1636
|
+
);
|
|
1637
|
+
}
|
|
1583
1638
|
return new AstryxError(
|
|
1584
1639
|
`Unknown topic "${String(topic)}"${notLoaded(catalog)}`,
|
|
1585
1640
|
suggestions,
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file Every Core doc has a named home in the docs tree (spec:AST-046 FR12).
|
|
5
|
+
*
|
|
6
|
+
* A reader sees a doc's home in its path (`Guides › Getting started`) and in
|
|
7
|
+
* its Up move. A flat Core topic sits in Guides or Foundations by the
|
|
8
|
+
* category it declares, so a new topic with no category, or one the levels
|
|
9
|
+
* do not know, fails here instead of landing in a catch-all. The integration
|
|
10
|
+
* guides and their field reference live under `authoring`, and the routes
|
|
11
|
+
* they left name where they went.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import {describe, expect, it} from 'vitest';
|
|
15
|
+
import {docs} from './docs.mjs';
|
|
16
|
+
import {TOPIC_LEVELS} from '../../foundation/doc-compiler/tree.mjs';
|
|
17
|
+
|
|
18
|
+
const CLI = '@astryxdesign/cli';
|
|
19
|
+
const SLOW = 60_000;
|
|
20
|
+
|
|
21
|
+
describe('every Core doc has a named home', () => {
|
|
22
|
+
it(
|
|
23
|
+
'puts each flat Core topic in Guides or Foundations by its category',
|
|
24
|
+
async () => {
|
|
25
|
+
const list = await docs();
|
|
26
|
+
const core = list.data.filter(topic => topic.package === CLI);
|
|
27
|
+
expect(core.length).toBeGreaterThan(10);
|
|
28
|
+
/** @type {string[]} */
|
|
29
|
+
const unfiled = [];
|
|
30
|
+
for (const topic of core) {
|
|
31
|
+
const read = await docs(topic.topic);
|
|
32
|
+
const {category} = read.data;
|
|
33
|
+
if (category !== 'guide' && category !== 'foundations') {
|
|
34
|
+
unfiled.push(`${topic.topic} (category ${String(category)})`);
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
const level =
|
|
38
|
+
category === 'foundations'
|
|
39
|
+
? TOPIC_LEVELS.foundations
|
|
40
|
+
: TOPIC_LEVELS.guides;
|
|
41
|
+
expect(read.data.links.up, topic.topic).toBe(
|
|
42
|
+
`astryx docs ${level.route}`,
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
expect(unfiled, 'Core topics with no home: give each a category').toEqual(
|
|
46
|
+
[],
|
|
47
|
+
);
|
|
48
|
+
},
|
|
49
|
+
SLOW,
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
it(
|
|
53
|
+
'lists each level under a plain name, and no catch-all',
|
|
54
|
+
async () => {
|
|
55
|
+
const list = await docs();
|
|
56
|
+
const roots = (list.meta.namespaces ?? []).map(entry => entry.topic);
|
|
57
|
+
expect(roots).toEqual(expect.arrayContaining(['guides', 'foundations']));
|
|
58
|
+
expect(roots).not.toContain('unorganized');
|
|
59
|
+
const guides = await docs('guides');
|
|
60
|
+
expect(guides.data).toMatchObject({route: 'guides', title: 'Guides'});
|
|
61
|
+
expect(guides.data.slots[0].children.map(child => child.route)).toEqual(
|
|
62
|
+
expect.arrayContaining(['getting-started', 'principles', 'theme']),
|
|
63
|
+
);
|
|
64
|
+
const foundations = await docs('foundations');
|
|
65
|
+
expect(foundations.data.title).toBe('Foundations');
|
|
66
|
+
expect(
|
|
67
|
+
foundations.data.slots[0].children.map(child => child.route),
|
|
68
|
+
).toEqual(expect.arrayContaining(['color', 'icons', 'spacing']));
|
|
69
|
+
await expect(docs('unorganized')).rejects.toMatchObject({
|
|
70
|
+
code: 'ERR_UNKNOWN_TOPIC',
|
|
71
|
+
});
|
|
72
|
+
},
|
|
73
|
+
SLOW,
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
it(
|
|
77
|
+
'keeps everything for integration authors under authoring, and names where an old route went',
|
|
78
|
+
async () => {
|
|
79
|
+
const authoring = await docs('authoring');
|
|
80
|
+
expect(authoring.data).toMatchObject({
|
|
81
|
+
route: 'authoring',
|
|
82
|
+
kind: 'namespace',
|
|
83
|
+
breadcrumb: [],
|
|
84
|
+
links: {up: 'astryx docs'},
|
|
85
|
+
});
|
|
86
|
+
const children = authoring.data.slots.flatMap(slot =>
|
|
87
|
+
slot.children.map(child => child.route),
|
|
88
|
+
);
|
|
89
|
+
expect(children).toEqual(
|
|
90
|
+
expect.arrayContaining([
|
|
91
|
+
'authoring/quick-start',
|
|
92
|
+
'authoring/building-blocks',
|
|
93
|
+
'authoring/ship',
|
|
94
|
+
'authoring/help',
|
|
95
|
+
'authoring/field-reference',
|
|
96
|
+
]),
|
|
97
|
+
);
|
|
98
|
+
// Every field reference section still opens from the namespace by its
|
|
99
|
+
// key, as `astryx docs authoring <name>` did on the topic (FR13).
|
|
100
|
+
const reference = await docs('authoring/field-reference', undefined, {
|
|
101
|
+
index: true,
|
|
102
|
+
});
|
|
103
|
+
const keys = reference.data.sections.map(section => section.id);
|
|
104
|
+
expect(keys.length).toBeGreaterThan(15);
|
|
105
|
+
for (const key of keys) {
|
|
106
|
+
const section = await docs('authoring', key);
|
|
107
|
+
expect(section.type, key).toBe('docs.detail.section');
|
|
108
|
+
expect(section.data.id, key).toBe(key);
|
|
109
|
+
}
|
|
110
|
+
for (const [old, now] of [
|
|
111
|
+
['cli/integrations', 'authoring'],
|
|
112
|
+
['cli/integrations/quick-start', 'authoring/quick-start'],
|
|
113
|
+
['cli/integrations/ship/publishing', 'authoring/ship/publishing'],
|
|
114
|
+
]) {
|
|
115
|
+
const error = await docs(old).catch(e => e);
|
|
116
|
+
expect(error).toMatchObject({
|
|
117
|
+
code: 'ERR_UNKNOWN_TOPIC',
|
|
118
|
+
message: expect.stringContaining(`It moved to "${now}"`),
|
|
119
|
+
});
|
|
120
|
+
// The new route comes first, ahead of the suggestions any unknown
|
|
121
|
+
// route gets (FR6).
|
|
122
|
+
expect(error.suggestions[0]).toMatchObject({name: now});
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
SLOW,
|
|
126
|
+
);
|
|
127
|
+
});
|
package/api/docs/docs.doc.mjs
CHANGED
|
@@ -28,7 +28,7 @@ export const doc = {
|
|
|
28
28
|
'`cli/api` returns its children one level down (`depth` reads as many ' +
|
|
29
29
|
'levels as asked, and `detail` how much of each doc below), a typed doc such as ' +
|
|
30
30
|
"`cli/api/functions/search` returns its content, and a guide the tree " +
|
|
31
|
-
'places (`
|
|
31
|
+
'places (`authoring/quick-start`) reads like any topic. ' +
|
|
32
32
|
'Every read but the list carries `links`, the commands that move from it: ' +
|
|
33
33
|
'`up` to the level it sits in, `previous` and `next` to its neighbors, and, ' +
|
|
34
34
|
'for a typed doc, `related` to the docs it names (its command or function, ' +
|
|
@@ -162,12 +162,12 @@ export const doc = {
|
|
|
162
162
|
},
|
|
163
163
|
{
|
|
164
164
|
label: 'A namespace and everything below it, in full',
|
|
165
|
-
code: "await docs('
|
|
165
|
+
code: "await docs('authoring', undefined, {depth: 'all', detail: 'full'});",
|
|
166
166
|
},
|
|
167
167
|
{label: 'One API function', code: "await docs('cli/api/functions/search');"},
|
|
168
168
|
{
|
|
169
169
|
label: 'A whole guide from the docs tree',
|
|
170
|
-
code: "await docs('
|
|
170
|
+
code: "await docs('authoring/quick-start');",
|
|
171
171
|
},
|
|
172
172
|
{label: 'One section by key', code: "await docs('spacing', 'scale');"},
|
|
173
173
|
],
|
package/api/docs/docs.test.mjs
CHANGED
|
@@ -93,7 +93,7 @@ describe('docs() dispatcher routing', () => {
|
|
|
93
93
|
|
|
94
94
|
it("lists the docs tree's namespaces in meta, so every data entry reads as a topic", async () => {
|
|
95
95
|
const res = await docs();
|
|
96
|
-
expect(res.meta.namespaces.map(entry => entry.topic)).toEqual(['cli', 'global', 'internationalization', 'layout', 'migration', 'styling', 'styling-libraries', 'tokens', 'typography'
|
|
96
|
+
expect(res.meta.namespaces.map(entry => entry.topic)).toEqual(['authoring', 'cli', 'foundations', 'global', 'guides', 'internationalization', 'layout', 'migration', 'styling', 'styling-libraries', 'tokens', 'typography']);
|
|
97
97
|
for (const entry of res.data) {
|
|
98
98
|
expect((await docs(entry.topic)).type).toBe('docs.detail');
|
|
99
99
|
}
|
|
@@ -123,7 +123,13 @@ describe('docs() dispatcher routing', () => {
|
|
|
123
123
|
kind: 'namespace',
|
|
124
124
|
package: '@astryxdesign/cli',
|
|
125
125
|
breadcrumb: [{route: 'cli', title: 'Astryx CLI'}],
|
|
126
|
-
|
|
126
|
+
// Its one block points to the host entry's guide.
|
|
127
|
+
content: [
|
|
128
|
+
{
|
|
129
|
+
type: 'prose',
|
|
130
|
+
text: expect.stringContaining('`astryx docs cli/host-entry`'),
|
|
131
|
+
},
|
|
132
|
+
],
|
|
127
133
|
});
|
|
128
134
|
expect(r.data.slots.flatMap(slot => slot.children.map(c => c.route))).toEqual([
|
|
129
135
|
'cli/api/functions',
|
|
@@ -152,8 +158,8 @@ describe('docs() dispatcher routing', () => {
|
|
|
152
158
|
}, SLOW);
|
|
153
159
|
|
|
154
160
|
it('a guide the tree places reads like a topic: the whole doc, its index, a section', async () => {
|
|
155
|
-
//
|
|
156
|
-
const integrations = await docs('
|
|
161
|
+
// authoring is a namespace of short guides; each guide reads like a topic.
|
|
162
|
+
const integrations = await docs('authoring');
|
|
157
163
|
expect(integrations.type).toBe('docs.node');
|
|
158
164
|
const guide = placedGuide(integrations.data);
|
|
159
165
|
expect((await docs(guide)).type).toBe('docs.detail');
|
|
@@ -172,7 +178,7 @@ describe('docs() dispatcher routing', () => {
|
|
|
172
178
|
expect(leaf.links.up).toBe('astryx docs cli/api/functions');
|
|
173
179
|
expect(leaf.links.previous).toMatch(/^astryx docs cli\/api\/functions\/[a-z-]+$/);
|
|
174
180
|
expect(leaf.links.next).toMatch(/^astryx docs cli\/api\/functions\/[a-z-]+$/);
|
|
175
|
-
const integrations = (await docs('
|
|
181
|
+
const integrations = (await docs('authoring')).data;
|
|
176
182
|
const guide = placedGuide(integrations);
|
|
177
183
|
const siblings = integrations.slots
|
|
178
184
|
.find(slot => slot.children.some(child => child.route === guide))
|
|
@@ -181,7 +187,7 @@ describe('docs() dispatcher routing', () => {
|
|
|
181
187
|
const index = await docs(guide, undefined, {index: true});
|
|
182
188
|
// A guide moves across its namespace's slot, as any tree node does.
|
|
183
189
|
expect(index.data.links).toEqual({
|
|
184
|
-
up: 'astryx docs
|
|
190
|
+
up: 'astryx docs authoring',
|
|
185
191
|
...(at > 0 ? {previous: `astryx docs ${siblings[at - 1]}`} : {}),
|
|
186
192
|
...(at < siblings.length - 1
|
|
187
193
|
? {next: `astryx docs ${siblings[at + 1]}`}
|
|
@@ -198,16 +204,22 @@ describe('docs() dispatcher routing', () => {
|
|
|
198
204
|
expect(end.links.previous).toBe(
|
|
199
205
|
`astryx docs ${guide} ${index.data.sections.at(-2).id}`,
|
|
200
206
|
);
|
|
201
|
-
// A flat topic's home is the
|
|
207
|
+
// A flat topic's home is the level for its category, and it moves across it.
|
|
202
208
|
const flat = (await docs('principles')).data.links;
|
|
203
|
-
expect(flat.up).toBe('astryx docs
|
|
209
|
+
expect(flat.up).toBe('astryx docs guides');
|
|
204
210
|
expect(flat.previous).toMatch(/^astryx docs [a-z-]+$/);
|
|
205
211
|
expect(flat.next).toMatch(/^astryx docs [a-z-]+$/);
|
|
206
|
-
const
|
|
207
|
-
expect(
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
212
|
+
const guides = (await docs('guides')).data;
|
|
213
|
+
expect(guides).toMatchObject({id: null, kind: 'namespace', links: {up: 'astryx docs'}});
|
|
214
|
+
const foundations = (await docs('foundations')).data;
|
|
215
|
+
expect(foundations).toMatchObject({id: null, kind: 'namespace', links: {up: 'astryx docs'}});
|
|
216
|
+
// Between them the two levels hold every flat topic, each in list order.
|
|
217
|
+
const topics = (await docs()).data.map(entry => entry.topic);
|
|
218
|
+
const held = [guides, foundations].map(level => level.slots[0].children.map(child => child.route));
|
|
219
|
+
for (const routes of held) {
|
|
220
|
+
expect(routes).toEqual(topics.filter(topic => routes.includes(topic)));
|
|
221
|
+
}
|
|
222
|
+
expect(held.flat().sort()).toEqual([...topics].sort());
|
|
211
223
|
}, SLOW);
|
|
212
224
|
|
|
213
225
|
it('names a node by its doc identity; a generated level has id null', async () => {
|
|
@@ -234,10 +246,9 @@ describe('docs() dispatcher routing', () => {
|
|
|
234
246
|
}, SLOW);
|
|
235
247
|
|
|
236
248
|
it("the guide's old flat name is gone, and its error names the new route", async () => {
|
|
237
|
-
await
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
});
|
|
249
|
+
const error = await docs('cli-integrations').catch(e => e);
|
|
250
|
+
expect(error.code).toBe('ERR_UNKNOWN_TOPIC');
|
|
251
|
+
expect(error.suggestions[0]).toMatchObject({name: 'authoring'});
|
|
241
252
|
expect((await docs()).data.map(entry => entry.topic)).not.toContain(
|
|
242
253
|
'cli-integrations',
|
|
243
254
|
);
|
|
@@ -247,11 +258,16 @@ describe('docs() dispatcher routing', () => {
|
|
|
247
258
|
const err = await docs('cli', 'zzzz-nope').catch(e => e);
|
|
248
259
|
expect(err).toBeInstanceOf(AstryxError);
|
|
249
260
|
expect(err.code).toBe('ERR_UNKNOWN_SECTION');
|
|
250
|
-
// It names every guide below the namespace, at any depth.
|
|
251
261
|
const names = err.suggestions.map(s => s.name);
|
|
252
262
|
expect(names).toContain('cli/component-lookups');
|
|
253
|
-
expect(names).toContain('cli/integrations/quick-start');
|
|
254
263
|
expect(names.every(name => name.startsWith('cli/'))).toBe(true);
|
|
264
|
+
// It names every guide below the namespace, at any depth.
|
|
265
|
+
const deep = await docs('authoring', 'zzzz-nope').catch(e => e);
|
|
266
|
+
expect(deep.code).toBe('ERR_UNKNOWN_SECTION');
|
|
267
|
+
const below = deep.suggestions.map(s => s.name);
|
|
268
|
+
expect(below).toContain('authoring/quick-start');
|
|
269
|
+
expect(below).toContain('authoring/building-blocks/components/add-a-component');
|
|
270
|
+
expect(below.every(name => name.startsWith('authoring/'))).toBe(true);
|
|
255
271
|
}, SLOW);
|
|
256
272
|
|
|
257
273
|
it('an unknown route suggests the children of the deepest namespace it reaches', async () => {
|