@astryxdesign/cli 0.6.3-canary.ea2f048 → 0.6.3-canary.ebaebc4
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 +2 -1
- package/api/build/build.type.d.mts +2 -2
- package/api/build/build.type.mjs +2 -2
- package/api/component/component.type.d.mts +6 -6
- package/api/component/component.type.mjs +19 -19
- package/api/discover/discover.type.d.mts +4 -4
- package/api/discover/discover.type.mjs +10 -10
- package/api/docs/_adapter.d.mts +37 -24
- package/api/docs/_adapter.mjs +169 -83
- package/api/docs/compiled-topics.test.mjs +78 -0
- package/api/docs/detail/detail.mjs +14 -63
- package/api/docs/detail/section/section.d.mts +1 -1
- package/api/docs/detail/section/section.mjs +44 -20
- package/api/docs/detail/section/section.test.mjs +41 -0
- package/api/docs/docs.d.mts +7 -2
- package/api/docs/docs.doc.mjs +27 -10
- package/api/docs/docs.mjs +16 -9
- package/api/docs/docs.test.mjs +6 -0
- package/api/docs/docs.type.d.mts +40 -3
- package/api/docs/docs.type.mjs +36 -8
- package/api/docs/index/index.d.mts +18 -0
- package/api/docs/index/index.mjs +32 -0
- package/api/docs/index/index.test.mjs +62 -0
- package/api/docs/integrationDocs.test.mjs +106 -0
- package/api/doctor/doctor.d.mts +48 -0
- package/api/doctor/doctor.mjs +232 -0
- package/api/doctor/doctor.test.mjs +196 -0
- package/api/hook/hook.type.d.mts +3 -3
- package/api/hook/hook.type.mjs +11 -11
- package/api/hook/list/list.d.mts +1 -1
- package/api/integration/add-contribution.mjs +5 -3
- package/api/integration/add-contribution.test.mjs +4 -4
- package/api/integration/integration-authoring.type.d.mts +1 -1
- package/api/integration/pack-check.mjs +49 -7
- package/api/integration/pack-check.test.mjs +249 -0
- package/api/search/search.d.mts +1 -1
- package/api/search/search.mjs +5 -5
- package/api/search/search.type.d.mts +2 -2
- package/api/search/search.type.mjs +1 -1
- package/api/swizzle/swizzle.type.d.mts +2 -2
- package/api/swizzle/swizzle.type.mjs +2 -2
- package/api/template/template.d.mts +1 -1
- package/api/template/template.type.d.mts +6 -6
- package/api/template/template.type.mjs +12 -12
- package/api/theme/build/build.mjs +20 -6
- package/api/theme/build/build.test.mjs +127 -0
- package/api/theme/palette/generate/generate.mjs +1 -1
- package/api/theme/palette/generate/generator.d.mts +10 -13
- package/api/theme/palette/generate/generator.mjs +7 -3
- package/api/theme/theme.type.d.mts +170 -11
- package/api/theme/theme.type.mjs +94 -27
- package/api/upgrade/_adapter.mjs +71 -5
- package/api/upgrade/project-context.test.mjs +272 -0
- package/api/upgrade/upgrade.doc.mjs +4 -3
- package/api/upgrade/upgrade.type.d.mts +5 -5
- package/api/upgrade/upgrade.type.mjs +11 -11
- package/assets/codemods/integration-discovery.mjs +40 -2
- package/assets/codemods/integration-discovery.test.mjs +58 -0
- package/assets/codemods/transforms/v0.3.0/__tests__/unwrap-authoring-factories.test.mjs +27 -5
- package/assets/codemods/transforms/v0.3.0/unwrap-authoring-factories.mjs +20 -5
- package/assets/docs/README.md +9 -0
- package/assets/docs/authoring.doc.mjs +14 -0
- package/assets/docs/cli-integrations.doc.mjs +86 -15
- package/assets/docs/styling-libraries.doc.mjs +1 -1
- package/assets/docs/working-with-ai.doc.mjs +1 -1
- package/authoring/_shared/contract.ts +22 -0
- package/authoring/codemod/codemod.doc.mjs +6 -1
- package/authoring/codemod/parse.d.mts +8 -8
- package/authoring/codemod/parse.mjs +8 -6
- package/authoring/config/parse.d.mts +13 -13
- package/authoring/config/parse.mjs +8 -8
- package/authoring/config/type.ts +3 -3
- package/authoring/debug/parse.d.mts +5 -5
- package/authoring/debug/parse.mjs +3 -3
- package/authoring/doctypes/_schema.d.mts +788 -23
- package/authoring/doctypes/_schema.mjs +492 -39
- package/authoring/doctypes/base/graph-fields.doc.d.mts +9 -0
- package/authoring/doctypes/base/graph-fields.doc.mjs +62 -0
- package/authoring/doctypes/base/type.ts +40 -0
- package/authoring/doctypes/command/command.doc.mjs +3 -2
- package/authoring/doctypes/command/parse.d.mts +2 -2
- package/authoring/doctypes/command/parse.mjs +1 -1
- package/authoring/doctypes/command/type.ts +3 -2
- package/authoring/doctypes/component/component.doc.mjs +6 -3
- package/authoring/doctypes/component/parse.d.mts +2 -2
- package/authoring/doctypes/component/parse.mjs +1 -1
- package/authoring/doctypes/component/type.ts +4 -3
- package/authoring/doctypes/enum/parse.d.mts +2 -2
- package/authoring/doctypes/enum/parse.mjs +1 -1
- package/authoring/doctypes/enum/type.ts +3 -1
- package/authoring/doctypes/function/function.doc.mjs +4 -0
- package/authoring/doctypes/function/parse.d.mts +2 -2
- package/authoring/doctypes/function/parse.mjs +1 -1
- package/authoring/doctypes/function/type.ts +6 -2
- package/authoring/doctypes/hook/hook.doc.mjs +4 -0
- package/authoring/doctypes/hook/parse.d.mts +2 -2
- package/authoring/doctypes/hook/parse.mjs +1 -1
- package/authoring/doctypes/hook/type.ts +3 -2
- package/authoring/doctypes/legacy.d.mts +8 -6
- package/authoring/doctypes/legacy.mjs +5 -4
- package/authoring/doctypes/load-contract.test.mjs +207 -0
- package/authoring/doctypes/namespace/namespace.doc.d.mts +9 -0
- package/authoring/doctypes/namespace/namespace.doc.mjs +132 -0
- package/authoring/doctypes/namespace/parse.d.mts +12 -0
- package/authoring/doctypes/namespace/parse.mjs +25 -0
- package/authoring/doctypes/namespace/parse.test.mjs +165 -0
- package/authoring/doctypes/namespace/type.ts +71 -0
- package/authoring/doctypes/parse.d.mts +20 -18
- package/authoring/doctypes/parse.mjs +16 -10
- package/authoring/doctypes/parse.test.mjs +77 -3
- package/authoring/doctypes/reference/parse.d.mts +2 -2
- package/authoring/doctypes/reference/parse.mjs +8 -5
- package/authoring/doctypes/reference/reference.doc.mjs +17 -4
- package/authoring/doctypes/reference/type.ts +51 -5
- package/authoring/doctypes/schema/parse.d.mts +2 -2
- package/authoring/doctypes/schema/parse.mjs +1 -1
- package/authoring/doctypes/schema/type.ts +3 -2
- package/authoring/doctypes/template/parse.d.mts +92 -1
- package/authoring/doctypes/template/parse.mjs +36 -2
- package/authoring/doctypes/template/parse.test.mjs +8 -2
- package/authoring/doctypes/template/template.doc.mjs +4 -0
- package/authoring/doctypes/template/type.ts +5 -2
- package/authoring/doctypes/types.ts +10 -9
- package/authoring/gap-report/parse.d.mts +10 -10
- package/authoring/gap-report/parse.mjs +6 -6
- package/authoring/gap-report/type.ts +1 -1
- package/authoring/identity/identity.doc.d.mts +9 -0
- package/authoring/identity/identity.doc.mjs +61 -0
- package/authoring/identity/type.ts +132 -0
- package/authoring/index.d.mts +1 -0
- package/authoring/index.d.ts +49 -17
- package/authoring/index.mjs +1 -0
- package/authoring/integration/integration.doc.mjs +13 -6
- package/authoring/integration/parse.d.mts +2 -2
- package/authoring/integration/parse.mjs +1 -1
- package/authoring/integration/parse.test.mjs +10 -1
- package/authoring/integration/schema.d.mts +6 -4
- package/authoring/integration/schema.mjs +9 -3
- package/authoring/integration/type.ts +23 -6
- package/authoring/shadcn/receipt.d.mts +6 -6
- package/clients/cli/commands/docs.doc.mjs +13 -3
- package/clients/cli/commands/docs.mjs +121 -21
- package/clients/cli/commands/docs.test.mjs +88 -0
- package/clients/cli/commands/integration-authoring.test.mjs +13 -9
- package/clients/cli/commands/theme-palette-generate.doc.mjs +8 -4
- package/clients/cli/commands/upgrade.doc.mjs +2 -2
- package/clients/cli/formatters/index.mjs +162 -1
- package/clients/cli/formatters/index.test.mjs +91 -0
- package/clients/cli/lib/manifest.mjs +7 -2
- package/foundation/config/project.mjs +21 -6
- package/foundation/discovery/authoring-self-docs.d.mts +69 -0
- package/foundation/discovery/authoring-self-docs.mjs +214 -0
- package/foundation/discovery/authoring-self-docs.test.mjs +154 -0
- package/foundation/discovery/component-discovery.d.mts +1 -1
- package/foundation/discovery/component-discovery.mjs +2 -1
- package/foundation/discovery/docs-discovery.d.mts +11 -4
- package/foundation/discovery/docs-discovery.mjs +208 -88
- package/foundation/discovery/docs-discovery.test.mjs +279 -13
- package/foundation/discovery/docs-output-budget.d.mts +28 -0
- package/foundation/discovery/docs-output-budget.mjs +50 -0
- package/foundation/discovery/docs-section-key.d.mts +98 -0
- package/foundation/discovery/docs-section-key.mjs +221 -0
- package/foundation/discovery/docs-section-key.test.mjs +224 -0
- package/foundation/discovery/template-adapter.mjs +2 -1
- package/foundation/discovery/theming-targets.test.mjs +4 -0
- package/foundation/doc-compiler/compile.d.mts +162 -0
- package/foundation/doc-compiler/compile.mjs +262 -0
- package/foundation/doc-compiler/doc-compiler.test.mjs +687 -0
- package/foundation/doc-compiler/ir.d.mts +9 -0
- package/foundation/doc-compiler/ir.mjs +287 -0
- package/foundation/doc-compiler/lenses.d.mts +33 -0
- package/foundation/doc-compiler/lenses.mjs +127 -0
- package/foundation/identity/provider-identity.d.mts +90 -0
- package/foundation/identity/provider-identity.mjs +320 -0
- package/foundation/identity/provider-identity.test.mjs +254 -0
- package/foundation/identity/providers.d.mts +7 -0
- package/foundation/identity/providers.mjs +16 -0
- package/foundation/integrations/autolink.mjs +12 -5
- package/foundation/integrations/integration-warnings.mjs +6 -0
- package/foundation/integrations/integrations.d.mts +46 -2
- package/foundation/integrations/integrations.mjs +167 -8
- package/foundation/integrations/integrations.test.mjs +384 -1
- package/foundation/integrations/provider-conflicts.test.mjs +125 -0
- package/foundation/integrations/validate-contributions.d.mts +2 -0
- package/foundation/integrations/validate-contributions.mjs +10 -0
- package/foundation/response/json-contract.test.mjs +46 -17
- package/foundation/response/response-types.doc.mjs +6 -1
- package/package.json +9 -11
package/api/docs/docs.d.mts
CHANGED
|
@@ -8,9 +8,12 @@
|
|
|
8
8
|
* @param {string} [options.lang]
|
|
9
9
|
* @param {boolean} [options.zh]
|
|
10
10
|
* @param {boolean} [options.dense]
|
|
11
|
+
* @param {boolean} [options.index] return the topic's section index instead of
|
|
12
|
+
* the whole doc
|
|
11
13
|
* @param {string} [options.cwd]
|
|
12
14
|
* @returns {Promise<
|
|
13
15
|
* import('./docs.type.mjs').DocsListResponse |
|
|
16
|
+
* import('./docs.type.mjs').DocsIndexResponse |
|
|
14
17
|
* import('./docs.type.mjs').DocsDetailResponse |
|
|
15
18
|
* import('./docs.type.mjs').DocsDetailSectionResponse
|
|
16
19
|
* >}
|
|
@@ -19,9 +22,11 @@ export function docs(topic?: string, section?: string, options?: {
|
|
|
19
22
|
lang?: string | undefined;
|
|
20
23
|
zh?: boolean | undefined;
|
|
21
24
|
dense?: boolean | undefined;
|
|
25
|
+
index?: boolean | undefined;
|
|
22
26
|
cwd?: string | undefined;
|
|
23
|
-
}): Promise<import("./docs.type.mjs").DocsListResponse | import("./docs.type.mjs").DocsDetailResponse | import("./docs.type.mjs").DocsDetailSectionResponse>;
|
|
27
|
+
}): Promise<import("./docs.type.mjs").DocsListResponse | import("./docs.type.mjs").DocsIndexResponse | import("./docs.type.mjs").DocsDetailResponse | import("./docs.type.mjs").DocsDetailSectionResponse>;
|
|
24
28
|
import { list } from './list/list.mjs';
|
|
29
|
+
import { index } from './index/index.mjs';
|
|
25
30
|
import { detail } from './detail/detail.mjs';
|
|
26
31
|
import { section as sectionLeaf } from './detail/section/section.mjs';
|
|
27
|
-
export { list, detail, sectionLeaf as section };
|
|
32
|
+
export { list, index, detail, sectionLeaf as section };
|
package/api/docs/docs.doc.mjs
CHANGED
|
@@ -13,18 +13,20 @@ export const doc = {
|
|
|
13
13
|
name: 'docs',
|
|
14
14
|
displayName: 'docs()',
|
|
15
15
|
summary:
|
|
16
|
-
'Read the reference docs: list every topic, one topic,
|
|
16
|
+
'Read the reference docs: list every topic, one topic\'s sections, one section, or a whole topic.',
|
|
17
17
|
description:
|
|
18
|
-
'
|
|
19
|
-
'
|
|
20
|
-
'
|
|
21
|
-
'
|
|
18
|
+
'No topic lists every reference-doc topic; a topic returns that full ' +
|
|
19
|
+
'ReferenceDoc; `index: true` returns the topic\'s section index instead ' +
|
|
20
|
+
'(each section\'s key, title, and summary); a topic plus a section returns ' +
|
|
21
|
+
'that one section, found by its key, then its exact title, then a unique ' +
|
|
22
|
+
'part of its title (an ambiguous query is refused). Token-ref blocks are ' +
|
|
23
|
+
'inlined in every read. The topic set is the CLI\'s own docs plus the ' +
|
|
22
24
|
'ones the project\'s configured integrations contribute, including any ' +
|
|
23
25
|
'topic an integration replaces or extends, so it depends on the cwd. ' +
|
|
24
26
|
'Overlay options select localized or dense variants.',
|
|
25
27
|
importPath: '@astryxdesign/cli/api',
|
|
26
28
|
signature:
|
|
27
|
-
'docs(topic?: string, section?: string, options?: DocsOptions): Promise<DocsListResponse | DocsDetailResponse | DocsDetailSectionResponse>',
|
|
29
|
+
'docs(topic?: string, section?: string, options?: DocsOptions): Promise<DocsListResponse | DocsIndexResponse | DocsDetailResponse | DocsDetailSectionResponse>',
|
|
28
30
|
keywords: [
|
|
29
31
|
'docs',
|
|
30
32
|
'documentation',
|
|
@@ -46,7 +48,7 @@ export const doc = {
|
|
|
46
48
|
name: 'section',
|
|
47
49
|
type: 'string',
|
|
48
50
|
description:
|
|
49
|
-
|
|
51
|
+
"Section to return: its key (from the topic's index), its title, or a unique part of its title (case-insensitive).",
|
|
50
52
|
},
|
|
51
53
|
{
|
|
52
54
|
name: 'options.lang',
|
|
@@ -63,6 +65,12 @@ export const doc = {
|
|
|
63
65
|
type: 'boolean',
|
|
64
66
|
description: 'Return the token-efficient dense doc variant.',
|
|
65
67
|
},
|
|
68
|
+
{
|
|
69
|
+
name: 'options.index',
|
|
70
|
+
type: 'boolean',
|
|
71
|
+
description:
|
|
72
|
+
"Return the topic's section index (each section's key, title, and summary) instead of the whole doc.",
|
|
73
|
+
},
|
|
66
74
|
{
|
|
67
75
|
name: 'options.cwd',
|
|
68
76
|
type: 'string',
|
|
@@ -81,10 +89,15 @@ export const doc = {
|
|
|
81
89
|
description:
|
|
82
90
|
"One topic's full ReferenceDoc, with token-ref blocks inlined.",
|
|
83
91
|
},
|
|
92
|
+
{
|
|
93
|
+
type: 'docs.index',
|
|
94
|
+
description:
|
|
95
|
+
"One topic's section index (index: true): {name, title, description, sections: [{id, title, summary}]}.",
|
|
96
|
+
},
|
|
84
97
|
{
|
|
85
98
|
type: 'docs.detail.section',
|
|
86
99
|
description:
|
|
87
|
-
'
|
|
100
|
+
'One ReferenceSection of the topic, found by key or title, with token-ref blocks inlined.',
|
|
88
101
|
},
|
|
89
102
|
],
|
|
90
103
|
throws: [
|
|
@@ -94,13 +107,17 @@ export const doc = {
|
|
|
94
107
|
},
|
|
95
108
|
{
|
|
96
109
|
code: 'ERR_UNKNOWN_SECTION',
|
|
97
|
-
when: 'a section is requested but is empty
|
|
110
|
+
when: 'a section is requested but is empty, matches no section, or matches more than one',
|
|
98
111
|
},
|
|
99
112
|
],
|
|
100
113
|
examples: [
|
|
101
114
|
{label: 'List topics', code: 'const r = await docs();'},
|
|
102
115
|
{label: 'Load a topic', code: "await docs('principles');"},
|
|
103
|
-
{
|
|
116
|
+
{
|
|
117
|
+
label: "A topic's sections",
|
|
118
|
+
code: "await docs('principles', undefined, {index: true});",
|
|
119
|
+
},
|
|
120
|
+
{label: 'One section by key', code: "await docs('tokens', 'spacing');"},
|
|
104
121
|
],
|
|
105
122
|
command: 'docs',
|
|
106
123
|
related: ['search', 'component', 'hook', 'template'],
|
package/api/docs/docs.mjs
CHANGED
|
@@ -3,24 +3,27 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* @file Programmatic API for the docs command.
|
|
5
5
|
*
|
|
6
|
-
* Dispatcher + barrel. `docs()` routes by argument shape into one of
|
|
6
|
+
* Dispatcher + barrel. `docs()` routes by argument shape into one of four
|
|
7
7
|
* leaves, each projecting into a single { type, data } envelope:
|
|
8
8
|
*
|
|
9
|
-
* docs()
|
|
10
|
-
* docs(topic)
|
|
11
|
-
* docs(topic,
|
|
9
|
+
* docs() -> list -> docs.list
|
|
10
|
+
* docs(topic) -> detail -> docs.detail
|
|
11
|
+
* docs(topic, undefined, {index: true}) -> index -> docs.index
|
|
12
|
+
* docs(topic, section) -> section -> docs.detail.section
|
|
12
13
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
14
|
+
* A topic read returns the whole doc, as it always has. The index is how a
|
|
15
|
+
* reader works progressively instead: list the topic's sections, then read one
|
|
16
|
+
* by its key. The leaves live in list/, index/, detail/, and detail/section/;
|
|
17
|
+
* the discovery, overlay loading, and topic resolution they share sit in
|
|
18
|
+
* _adapter.mjs.
|
|
17
19
|
*/
|
|
18
20
|
|
|
19
21
|
import {list} from './list/list.mjs';
|
|
22
|
+
import {index} from './index/index.mjs';
|
|
20
23
|
import {detail} from './detail/detail.mjs';
|
|
21
24
|
import {section as sectionLeaf} from './detail/section/section.mjs';
|
|
22
25
|
|
|
23
|
-
export {list, detail, sectionLeaf as section};
|
|
26
|
+
export {list, index, detail, sectionLeaf as section};
|
|
24
27
|
|
|
25
28
|
/**
|
|
26
29
|
* @param {string} [topic]
|
|
@@ -29,9 +32,12 @@ export {list, detail, sectionLeaf as section};
|
|
|
29
32
|
* @param {string} [options.lang]
|
|
30
33
|
* @param {boolean} [options.zh]
|
|
31
34
|
* @param {boolean} [options.dense]
|
|
35
|
+
* @param {boolean} [options.index] return the topic's section index instead of
|
|
36
|
+
* the whole doc
|
|
32
37
|
* @param {string} [options.cwd]
|
|
33
38
|
* @returns {Promise<
|
|
34
39
|
* import('./docs.type.mjs').DocsListResponse |
|
|
40
|
+
* import('./docs.type.mjs').DocsIndexResponse |
|
|
35
41
|
* import('./docs.type.mjs').DocsDetailResponse |
|
|
36
42
|
* import('./docs.type.mjs').DocsDetailSectionResponse
|
|
37
43
|
* >}
|
|
@@ -39,5 +45,6 @@ export {list, detail, sectionLeaf as section};
|
|
|
39
45
|
export async function docs(topic, section, options = {}) {
|
|
40
46
|
if (!topic) return list(options);
|
|
41
47
|
if (section) return sectionLeaf(topic, section, options);
|
|
48
|
+
if (options.index) return index(topic, options);
|
|
42
49
|
return detail(topic, options);
|
|
43
50
|
}
|
package/api/docs/docs.test.mjs
CHANGED
|
@@ -33,6 +33,12 @@ describe('docs() dispatcher routing', () => {
|
|
|
33
33
|
expect(r.type).toBe('docs.detail');
|
|
34
34
|
}, SLOW);
|
|
35
35
|
|
|
36
|
+
it('topic + index -> docs.index', async () => {
|
|
37
|
+
const {data} = await docs();
|
|
38
|
+
const r = await docs(data[0].topic, undefined, {index: true});
|
|
39
|
+
expect(r.type).toBe('docs.index');
|
|
40
|
+
}, SLOW);
|
|
41
|
+
|
|
36
42
|
it('topic + section -> docs.detail.section', async () => {
|
|
37
43
|
const {data} = await docs();
|
|
38
44
|
let routed = null;
|
package/api/docs/docs.type.d.mts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// DO NOT EDIT — run `pnpm sync:api-types` to regenerate.
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* astryx --json docs
|
|
6
6
|
*/
|
|
7
7
|
export type DocsListResponse = {
|
|
8
8
|
type: "docs.list";
|
|
@@ -23,14 +23,46 @@ export type DocsListEntry = {
|
|
|
23
23
|
replaces?: string | undefined;
|
|
24
24
|
};
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
26
|
+
* astryx --json docs <topic> --index
|
|
27
|
+
*/
|
|
28
|
+
export type DocsIndexResponse = {
|
|
29
|
+
type: "docs.index";
|
|
30
|
+
data: DocsIndex;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* astryx --json docs <topic>
|
|
27
34
|
*/
|
|
28
35
|
export type DocsDetailResponse = {
|
|
29
36
|
type: "docs.detail";
|
|
30
37
|
data: import("@astryxdesign/cli/authoring").ReferenceDoc;
|
|
31
38
|
};
|
|
32
39
|
/**
|
|
33
|
-
*
|
|
40
|
+
* The section index of one topic: what the topic is, and the key each section
|
|
41
|
+
* is read by.
|
|
42
|
+
*/
|
|
43
|
+
export type DocsIndex = {
|
|
44
|
+
/**
|
|
45
|
+
* the topic
|
|
46
|
+
*/
|
|
47
|
+
name: string;
|
|
48
|
+
title: string;
|
|
49
|
+
description: string;
|
|
50
|
+
sections: DocsIndexSection[];
|
|
51
|
+
};
|
|
52
|
+
export type DocsIndexSection = {
|
|
53
|
+
/**
|
|
54
|
+
* stable key; pass it as the section argument
|
|
55
|
+
*/
|
|
56
|
+
id: string;
|
|
57
|
+
title: string;
|
|
58
|
+
/**
|
|
59
|
+
* the section's first line of text, at most 240
|
|
60
|
+
* characters
|
|
61
|
+
*/
|
|
62
|
+
summary: string;
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* astryx --json docs <topic> <section>
|
|
34
66
|
*/
|
|
35
67
|
export type DocsDetailSectionResponse = {
|
|
36
68
|
type: "docs.detail.section";
|
|
@@ -43,6 +75,11 @@ export type DocsOptions = {
|
|
|
43
75
|
lang?: string | undefined;
|
|
44
76
|
zh?: boolean | undefined;
|
|
45
77
|
dense?: boolean | undefined;
|
|
78
|
+
/**
|
|
79
|
+
* return a topic's section index instead of its
|
|
80
|
+
* whole doc
|
|
81
|
+
*/
|
|
82
|
+
index?: boolean | undefined;
|
|
46
83
|
/**
|
|
47
84
|
* project directory whose configured integrations
|
|
48
85
|
* contribute topics; defaults to process.cwd()
|
package/api/docs/docs.type.mjs
CHANGED
|
@@ -4,16 +4,17 @@
|
|
|
4
4
|
* @file Colocated types for the `docs` command — source of truth for the docs
|
|
5
5
|
* command JSON responses. `types/docs.d.ts` re-exports these.
|
|
6
6
|
*
|
|
7
|
-
* Invocation
|
|
7
|
+
* Invocation -> type discriminator
|
|
8
8
|
* ------------------------------------------------------------
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
9
|
+
* astryx --json docs -> docs.list
|
|
10
|
+
* astryx --json docs <topic> -> docs.detail
|
|
11
|
+
* astryx --json docs <topic> --index -> docs.index
|
|
12
|
+
* astryx --json docs <topic> <section> -> docs.detail.section
|
|
13
|
+
* (unknown topic/section) -> CLIError
|
|
13
14
|
*/
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
|
-
*
|
|
17
|
+
* astryx --json docs
|
|
17
18
|
* @typedef {object} DocsListResponse
|
|
18
19
|
* @property {'docs.list'} type
|
|
19
20
|
* @property {DocsListEntry[]} data
|
|
@@ -30,14 +31,39 @@
|
|
|
30
31
|
*/
|
|
31
32
|
|
|
32
33
|
/**
|
|
33
|
-
*
|
|
34
|
+
* astryx --json docs <topic> --index
|
|
35
|
+
* @typedef {object} DocsIndexResponse
|
|
36
|
+
* @property {'docs.index'} type
|
|
37
|
+
* @property {DocsIndex} data
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* astryx --json docs <topic>
|
|
34
42
|
* @typedef {object} DocsDetailResponse
|
|
35
43
|
* @property {'docs.detail'} type
|
|
36
44
|
* @property {import('@astryxdesign/cli/authoring').ReferenceDoc} data
|
|
37
45
|
*/
|
|
38
46
|
|
|
39
47
|
/**
|
|
40
|
-
*
|
|
48
|
+
* The section index of one topic: what the topic is, and the key each section
|
|
49
|
+
* is read by.
|
|
50
|
+
* @typedef {object} DocsIndex
|
|
51
|
+
* @property {string} name the topic
|
|
52
|
+
* @property {string} title
|
|
53
|
+
* @property {string} description
|
|
54
|
+
* @property {DocsIndexSection[]} sections
|
|
55
|
+
*/
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @typedef {object} DocsIndexSection
|
|
59
|
+
* @property {string} id stable key; pass it as the section argument
|
|
60
|
+
* @property {string} title
|
|
61
|
+
* @property {string} summary the section's first line of text, at most 240
|
|
62
|
+
* characters
|
|
63
|
+
*/
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* astryx --json docs <topic> <section>
|
|
41
67
|
* @typedef {object} DocsDetailSectionResponse
|
|
42
68
|
* @property {'docs.detail.section'} type
|
|
43
69
|
* @property {import('@astryxdesign/cli/authoring').ReferenceSection} data
|
|
@@ -49,6 +75,8 @@
|
|
|
49
75
|
* @property {string} [lang]
|
|
50
76
|
* @property {boolean} [zh]
|
|
51
77
|
* @property {boolean} [dense]
|
|
78
|
+
* @property {boolean} [index] return a topic's section index instead of its
|
|
79
|
+
* whole doc
|
|
52
80
|
* @property {string} [cwd] project directory whose configured integrations
|
|
53
81
|
* contribute topics; defaults to process.cwd()
|
|
54
82
|
*/
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// @generated by scripts/sync-api-types.mjs from the JSDoc in api/**/*.mjs.
|
|
2
|
+
// DO NOT EDIT — run `pnpm sync:api-types` to regenerate.
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @param {string} topic
|
|
6
|
+
* @param {object} [options]
|
|
7
|
+
* @param {string} [options.lang]
|
|
8
|
+
* @param {boolean} [options.zh]
|
|
9
|
+
* @param {boolean} [options.dense]
|
|
10
|
+
* @param {string} [options.cwd]
|
|
11
|
+
* @returns {Promise<import('../docs.type.mjs').DocsIndexResponse>}
|
|
12
|
+
*/
|
|
13
|
+
export function index(topic: string, options?: {
|
|
14
|
+
lang?: string | undefined;
|
|
15
|
+
zh?: boolean | undefined;
|
|
16
|
+
dense?: boolean | undefined;
|
|
17
|
+
cwd?: string | undefined;
|
|
18
|
+
}): Promise<import("../docs.type.mjs").DocsIndexResponse>;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file docs.index leaf — the section index of one topic.
|
|
5
|
+
*
|
|
6
|
+
* @input A topic name plus optional {lang, zh, dense, cwd}. Resolves the topic
|
|
7
|
+
* via the shared adapter and reads its lowered compiled node; nothing is
|
|
8
|
+
* linked, since the index never inlines a token reference.
|
|
9
|
+
* @output { type: 'docs.index', data: DocsIndex } — the topic's name, title and
|
|
10
|
+
* description and, for each section, the key it is read by, its title, and a
|
|
11
|
+
* one-line summary. Matches `astryx --json docs <topic> --index`.
|
|
12
|
+
* @position Leaf under api/docs: a topic's opt-in progressive read. One section
|
|
13
|
+
* is the section leaf (`docs <topic> <key>`); the whole topic, a plain topic
|
|
14
|
+
* read, is the detail leaf.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import {indexView} from '../../../foundation/doc-compiler/lenses.mjs';
|
|
18
|
+
import {resolveTopicDocs} from '../_adapter.mjs';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @param {string} topic
|
|
22
|
+
* @param {object} [options]
|
|
23
|
+
* @param {string} [options.lang]
|
|
24
|
+
* @param {boolean} [options.zh]
|
|
25
|
+
* @param {boolean} [options.dense]
|
|
26
|
+
* @param {string} [options.cwd]
|
|
27
|
+
* @returns {Promise<import('../docs.type.mjs').DocsIndexResponse>}
|
|
28
|
+
*/
|
|
29
|
+
export async function index(topic, options = {}) {
|
|
30
|
+
const {node} = await resolveTopicDocs(topic, options);
|
|
31
|
+
return {type: 'docs.index', data: indexView(node)};
|
|
32
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
import {describe, expect, it} from 'vitest';
|
|
4
|
+
import {docs} from '../docs.mjs';
|
|
5
|
+
import {index} from './index.mjs';
|
|
6
|
+
import {loadDocsCatalog} from '../_adapter.mjs';
|
|
7
|
+
|
|
8
|
+
const SLOW = 60_000;
|
|
9
|
+
|
|
10
|
+
describe('docs.index leaf', () => {
|
|
11
|
+
it('lists each section by key, title, and summary', async () => {
|
|
12
|
+
const res = await index('theme');
|
|
13
|
+
expect(res.type).toBe('docs.index');
|
|
14
|
+
expect(res.data).toMatchObject({name: 'theme', title: expect.any(String)});
|
|
15
|
+
const keys = res.data.sections.map(s => s.id);
|
|
16
|
+
expect(new Set(keys).size).toBe(keys.length);
|
|
17
|
+
for (const entry of res.data.sections) {
|
|
18
|
+
expect(Object.keys(entry)).toEqual(['id', 'title', 'summary']);
|
|
19
|
+
expect(entry.summary.length).toBeLessThanOrEqual(240);
|
|
20
|
+
}
|
|
21
|
+
}, SLOW);
|
|
22
|
+
|
|
23
|
+
it('names the sections the full topic has, with the same keys', async () => {
|
|
24
|
+
const full = await docs('theme');
|
|
25
|
+
const {data} = await index('theme');
|
|
26
|
+
expect(data.sections.map(s => [s.id, s.title])).toEqual(
|
|
27
|
+
full.data.sections.map(s => [s.id, s.title]),
|
|
28
|
+
);
|
|
29
|
+
}, SLOW);
|
|
30
|
+
|
|
31
|
+
it('keeps every key the same in every language', async () => {
|
|
32
|
+
const english = (await index('theme')).data.sections.map(s => s.id);
|
|
33
|
+
for (const lang of ['zh', 'dense']) {
|
|
34
|
+
const localized = await index('theme', {lang});
|
|
35
|
+
expect(localized.data.sections.map(s => s.id)).toEqual(english);
|
|
36
|
+
}
|
|
37
|
+
}, SLOW);
|
|
38
|
+
|
|
39
|
+
it('lists keys every section can be read by', async () => {
|
|
40
|
+
const catalog = await loadDocsCatalog();
|
|
41
|
+
for (const entry of catalog.entries()) {
|
|
42
|
+
const {data} = await index(entry.name);
|
|
43
|
+
for (const {id, title} of data.sections) {
|
|
44
|
+
const read = await docs(entry.name, id);
|
|
45
|
+
expect(read.data.title).toBe(title);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}, SLOW);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
describe('docs() topic reads', () => {
|
|
52
|
+
it('returns the whole topic by default, as before', async () => {
|
|
53
|
+
const res = await docs('theme');
|
|
54
|
+
expect(res.type).toBe('docs.detail');
|
|
55
|
+
expect(res.data.sections[0].content.length).toBeGreaterThan(0);
|
|
56
|
+
}, SLOW);
|
|
57
|
+
|
|
58
|
+
it('returns the section index on request', async () => {
|
|
59
|
+
const res = await docs('theme', undefined, {index: true});
|
|
60
|
+
expect(res.type).toBe('docs.index');
|
|
61
|
+
}, SLOW);
|
|
62
|
+
});
|
|
@@ -177,6 +177,112 @@ describe('integration-contributed topics', () => {
|
|
|
177
177
|
expect(extended.data.sections.length).toBe(builtin.data.sections.length + 1);
|
|
178
178
|
}, SLOW);
|
|
179
179
|
|
|
180
|
+
it('migrates a real built-in section to a stable ID without duplicating it', async () => {
|
|
181
|
+
const builtin = await docs('theme');
|
|
182
|
+
// Readers see a key on every section; the migration case is one whose
|
|
183
|
+
// source authors no id.
|
|
184
|
+
const {docs: authored} = await import('../../assets/docs/theme.doc.mjs');
|
|
185
|
+
const target = authored.sections.find(section => section.id == null);
|
|
186
|
+
expect(target).toBeDefined();
|
|
187
|
+
scaffold({
|
|
188
|
+
'theme-internal.doc.mjs': topic({
|
|
189
|
+
name: 'theme-internal',
|
|
190
|
+
extends: 'theme',
|
|
191
|
+
sections: [
|
|
192
|
+
{
|
|
193
|
+
id: 'acme-theme-setup',
|
|
194
|
+
title: target.title,
|
|
195
|
+
content: [{type: 'prose', text: 'Use the Acme theme.'}],
|
|
196
|
+
},
|
|
197
|
+
],
|
|
198
|
+
}),
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
const extended = await docs('theme', undefined, {cwd: tmpDir});
|
|
202
|
+
expect(extended.data.sections).toHaveLength(builtin.data.sections.length);
|
|
203
|
+
const matches = extended.data.sections.filter(
|
|
204
|
+
section => section.title === target.title,
|
|
205
|
+
);
|
|
206
|
+
expect(matches).toEqual([
|
|
207
|
+
expect.objectContaining({
|
|
208
|
+
id: 'acme-theme-setup',
|
|
209
|
+
content: [{type: 'prose', text: 'Use the Acme theme.'}],
|
|
210
|
+
}),
|
|
211
|
+
]);
|
|
212
|
+
}, SLOW);
|
|
213
|
+
|
|
214
|
+
it('replaces a real built-in section by the key its index shows', async () => {
|
|
215
|
+
const index = await docs('theme', undefined, {index: true});
|
|
216
|
+
const target = index.data.sections[0];
|
|
217
|
+
scaffold({
|
|
218
|
+
'theme-internal.doc.mjs': topic({
|
|
219
|
+
name: 'theme-internal',
|
|
220
|
+
extends: 'theme',
|
|
221
|
+
sections: [
|
|
222
|
+
{
|
|
223
|
+
id: target.id,
|
|
224
|
+
title: `${target.title} with Acme`,
|
|
225
|
+
content: [{type: 'prose', text: 'Acme first.'}],
|
|
226
|
+
},
|
|
227
|
+
],
|
|
228
|
+
}),
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
const extended = await docs('theme', undefined, {cwd: tmpDir});
|
|
232
|
+
expect(extended.data.sections).toHaveLength(index.data.sections.length);
|
|
233
|
+
expect(extended.data.sections.filter(s => s.id === target.id)).toEqual([
|
|
234
|
+
expect.objectContaining({content: [{type: 'prose', text: 'Acme first.'}]}),
|
|
235
|
+
]);
|
|
236
|
+
const read = await docs('theme', target.id, {cwd: tmpDir});
|
|
237
|
+
expect(read.data.title).toBe(`${target.title} with Acme`);
|
|
238
|
+
}, SLOW);
|
|
239
|
+
|
|
240
|
+
it.each(['zh', 'dense'])(
|
|
241
|
+
'replaces translated real sections by their authored titles under --%s',
|
|
242
|
+
async lang => {
|
|
243
|
+
const english = await docs('theme');
|
|
244
|
+
const englishTitles = english.data.sections.map(section => section.title);
|
|
245
|
+
expect(englishTitles).toEqual(
|
|
246
|
+
expect.arrayContaining(['Quick Start', 'Theme Props']),
|
|
247
|
+
);
|
|
248
|
+
scaffold({
|
|
249
|
+
'theme-internal.doc.mjs': topic({
|
|
250
|
+
name: 'theme-internal',
|
|
251
|
+
extends: 'theme',
|
|
252
|
+
sections: [
|
|
253
|
+
{
|
|
254
|
+
id: 'acme-quick-start',
|
|
255
|
+
title: 'Quick Start',
|
|
256
|
+
content: [{type: 'prose', text: 'Acme quick start.'}],
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
title: 'Theme Props',
|
|
260
|
+
content: [{type: 'prose', text: 'Acme props.'}],
|
|
261
|
+
},
|
|
262
|
+
],
|
|
263
|
+
}),
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
const base = await docs('theme', undefined, {lang});
|
|
267
|
+
expect(base.data.sections.map(section => section.title)).not.toEqual(
|
|
268
|
+
englishTitles,
|
|
269
|
+
);
|
|
270
|
+
const extended = await docs('theme', undefined, {cwd: tmpDir, lang});
|
|
271
|
+
expect(extended.data.sections).toHaveLength(base.data.sections.length);
|
|
272
|
+
expect(
|
|
273
|
+
extended.data.sections.filter(
|
|
274
|
+
section => section.id === 'acme-quick-start',
|
|
275
|
+
),
|
|
276
|
+
).toHaveLength(1);
|
|
277
|
+
expect(
|
|
278
|
+
extended.data.sections.filter(
|
|
279
|
+
section => section.content[0]?.text === 'Acme props.',
|
|
280
|
+
),
|
|
281
|
+
).toHaveLength(1);
|
|
282
|
+
},
|
|
283
|
+
SLOW,
|
|
284
|
+
);
|
|
285
|
+
|
|
180
286
|
it('offers the contributed topics as suggestions on an unknown one', async () => {
|
|
181
287
|
scaffold({'deploying.doc.mjs': topic()});
|
|
182
288
|
await expect(docs('nope-not-a-topic', undefined, {cwd: tmpDir})).rejects.toBeInstanceOf(
|
package/api/doctor/doctor.d.mts
CHANGED
|
@@ -84,6 +84,36 @@ export function checkPeerDeps(ctx: DoctorContext): DoctorCheck;
|
|
|
84
84
|
* @returns {DoctorCheck}
|
|
85
85
|
*/
|
|
86
86
|
export function checkPackageManager(ctx: DoctorContext): DoctorCheck;
|
|
87
|
+
/**
|
|
88
|
+
* Check 6b — every contributing integration owns its provider identity.
|
|
89
|
+
*
|
|
90
|
+
* Artifact and document IDs are provider-scoped, so a package that claims a
|
|
91
|
+
* provider ID an earlier-loaded package already holds is loaded inert: its
|
|
92
|
+
* components, templates, themes, docs, and codemods are withdrawn while the
|
|
93
|
+
* earlier package keeps contributing. That can be a deliberate transition
|
|
94
|
+
* (a renamed package installed beside its predecessor), so it warns rather
|
|
95
|
+
* than fails, but it is never allowed to happen quietly.
|
|
96
|
+
*
|
|
97
|
+
* @param {DoctorContext} ctx
|
|
98
|
+
* @returns {DoctorCheck}
|
|
99
|
+
*/
|
|
100
|
+
export function checkProviderIdentity(ctx: DoctorContext): DoctorCheck;
|
|
101
|
+
/**
|
|
102
|
+
* Every authoring self-doc is reachable from `astryx docs authoring`, loads,
|
|
103
|
+
* and fits in one read. The audit is imported here, inside the try, so a
|
|
104
|
+
* malformed self-doc is reported rather than taking Doctor down.
|
|
105
|
+
* @param {DoctorContext} [_ctx]
|
|
106
|
+
* @returns {Promise<DoctorCheck>}
|
|
107
|
+
*/
|
|
108
|
+
export function checkAuthoringDocs(_ctx?: DoctorContext): Promise<DoctorCheck>;
|
|
109
|
+
/**
|
|
110
|
+
* Every topic reads progressively, in every language it ships: it loads, its
|
|
111
|
+
* section index and each of its sections fit in one read, and no contributed
|
|
112
|
+
* doc is invalid.
|
|
113
|
+
* @param {DoctorContext | Partial<DoctorContext>} ctx
|
|
114
|
+
* @returns {Promise<DoctorCheck>}
|
|
115
|
+
*/
|
|
116
|
+
export function checkDocsProgressiveDisclosure(ctx: DoctorContext | Partial<DoctorContext>): Promise<DoctorCheck>;
|
|
87
117
|
/**
|
|
88
118
|
* Run all diagnostic checks and return a structured report.
|
|
89
119
|
*
|
|
@@ -169,9 +199,27 @@ export type DoctorContext = {
|
|
|
169
199
|
* read at all.
|
|
170
200
|
*/
|
|
171
201
|
integrations?: import("../../foundation/integrations/integrations.mjs").LoadedIntegration[] | null | undefined;
|
|
202
|
+
/**
|
|
203
|
+
* - The topics a docs read sees.
|
|
204
|
+
*/
|
|
205
|
+
docsCatalog?: DocsCatalog | null | undefined;
|
|
206
|
+
/**
|
|
207
|
+
* `invalid_doc` issues from the project's contributed docs.
|
|
208
|
+
*/
|
|
209
|
+
docsCatalogIssues?: {
|
|
210
|
+
package?: string;
|
|
211
|
+
code: string;
|
|
212
|
+
message: string;
|
|
213
|
+
}[] | undefined;
|
|
214
|
+
/**
|
|
215
|
+
* - Why the project's docs catalog
|
|
216
|
+
* could not be built, when it could not.
|
|
217
|
+
*/
|
|
218
|
+
docsCatalogError?: string | null | undefined;
|
|
172
219
|
/**
|
|
173
220
|
* - Error thrown while resolving the config
|
|
174
221
|
* path (e.g. multiple config files present), surfaced by checkConfig as a FAIL.
|
|
175
222
|
*/
|
|
176
223
|
configError?: Error | null | undefined;
|
|
177
224
|
};
|
|
225
|
+
import { DocsCatalog } from '../../foundation/discovery/docs-discovery.mjs';
|