@astryxdesign/cli 0.6.4-canary.06c8fa3 → 0.6.4-canary.0e1fbdb
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 +49 -40
- package/api/build/build.doc.mjs +6 -1
- package/api/build/build.test.mjs +22 -0
- package/api/build/kit/kit.mjs +44 -5
- package/api/component/component.doc.mjs +14 -7
- package/api/docs/_adapter.d.mts +8 -3
- package/api/docs/_adapter.mjs +14 -6
- package/api/docs/docOverlays.test.mjs +27 -1
- package/api/docs/docs.doc.mjs +2 -2
- package/api/doctor/doctor.doc.mjs +17 -8
- 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 +19 -10
- package/api/hook/hook.doc.mjs +6 -3
- package/api/index.d.mts +2 -0
- package/api/index.mjs +3 -1
- package/api/init/init.doc.mjs +17 -12
- package/api/integration/add-theme.mjs +22 -1
- package/api/integration/add-theme.test.mjs +34 -0
- package/api/integration/authoring-checks.mjs +2 -2
- package/api/integration/integrationPackCheck.doc.mjs +3 -3
- package/api/integration/pack-check.lifecycle-output.test.mjs +2 -0
- package/api/integration/pack-check.mjs +54 -6
- package/api/integration/pack-check.test.mjs +90 -0
- 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 +27 -1
- package/api/search/search.doc.mjs +2 -2
- package/api/search/search.mjs +228 -16
- package/api/swizzle/swizzle.doc.mjs +7 -5
- package/api/template/copy/copy.mjs +1 -1
- package/api/template/copy/copy.test.mjs +9 -0
- package/api/template/template-integration.test.mjs +65 -1
- package/api/template/template.doc.mjs +2 -1
- package/api/template/template.mjs +1 -1
- package/api/theme/generateTonalPalette.doc.mjs +1 -2
- package/api/theme/listThemes.doc.mjs +1 -1
- package/api/theme/themeAdd.doc.mjs +9 -10
- package/api/theme/themeBuild.doc.mjs +13 -13
- package/api/theme/themeList.doc.mjs +1 -1
- package/api/theme/themeListAvailable.doc.mjs +2 -1
- package/api/theme/themePaletteGenerate.doc.mjs +15 -8
- package/api/theme/themeTargets.doc.mjs +3 -2
- package/api/theme/themeTemplate.doc.mjs +2 -1
- package/api/upgrade/run/run.mjs +1 -1
- package/api/upgrade/upgrade.doc.mjs +24 -22
- package/assets/docs/README.md +4 -2
- package/assets/docs/browser-support.doc.mjs +11 -11
- package/assets/docs/color.doc.mjs +8 -2
- package/assets/docs/elevation.doc.mjs +6 -4
- package/assets/docs/getting-started.doc.mjs +5 -16
- package/assets/docs/icons.doc.mjs +2 -21
- package/assets/docs/illustrations.doc.mjs +7 -15
- package/assets/docs/layout.doc.dense.mjs +130 -82
- package/assets/docs/layout.doc.mjs +133 -77
- package/assets/docs/migration.doc.mjs +19 -21
- package/assets/docs/motion.doc.mjs +16 -3
- package/assets/docs/principles.doc.dense.mjs +5 -5
- package/assets/docs/principles.doc.mjs +8 -0
- package/assets/docs/principles.doc.zh.mjs +6 -6
- package/assets/docs/shape.doc.mjs +8 -3
- package/assets/docs/spacing.doc.mjs +7 -2
- package/assets/docs/styling-libraries.doc.mjs +6 -2
- package/assets/docs/styling.doc.mjs +19 -23
- package/assets/docs/theme.doc.dense.mjs +58 -18
- package/assets/docs/theme.doc.mjs +56 -46
- package/assets/docs/theme.doc.zh.mjs +9 -8
- package/assets/docs/tokens.doc.dense.mjs +2 -2
- package/assets/docs/tokens.doc.mjs +389 -8
- package/assets/docs/tokens.doc.zh.mjs +2 -2
- package/assets/docs/tree/add-a-component.doc.mjs +75 -0
- package/assets/docs/tree/add-a-theme.doc.mjs +85 -0
- package/assets/docs/tree/add-a-topic.doc.mjs +144 -0
- package/assets/docs/tree/agent-guidance.doc.mjs +138 -0
- package/assets/docs/tree/block-template.doc.mjs +130 -0
- package/assets/docs/tree/build-the-template.doc.mjs +28 -0
- package/assets/docs/tree/building-blocks.doc.mjs +46 -0
- package/assets/docs/tree/check-your-docs.doc.mjs +137 -0
- package/assets/docs/tree/checks.doc.mjs +119 -0
- package/assets/docs/tree/codemods.doc.mjs +147 -0
- package/assets/docs/tree/component-family.doc.mjs +113 -0
- package/assets/docs/tree/component-imports.doc.mjs +69 -0
- package/assets/docs/tree/components.doc.mjs +23 -0
- package/assets/docs/tree/configuration.doc.mjs +23 -0
- package/assets/docs/tree/debug-and-gap-reports.doc.mjs +182 -0
- package/assets/docs/tree/define-the-theme.doc.mjs +118 -0
- package/assets/docs/tree/describe-the-component.doc.mjs +57 -0
- package/assets/docs/tree/docs.doc.mjs +21 -0
- package/assets/docs/tree/document-the-template.doc.mjs +28 -0
- package/assets/docs/tree/document-the-theme.doc.mjs +68 -0
- package/assets/docs/tree/export-template-assets.doc.mjs +147 -0
- package/assets/docs/tree/extend-or-replace.doc.mjs +103 -0
- package/assets/docs/tree/fonts-and-assets.doc.mjs +106 -0
- package/assets/docs/tree/generate-a-palette.doc.mjs +66 -0
- package/assets/docs/tree/grade-template-with-agent.doc.mjs +105 -0
- package/assets/docs/tree/help.doc.mjs +16 -0
- package/assets/docs/tree/integrations.doc.mjs +25 -470
- package/assets/docs/tree/links.doc.mjs +98 -0
- package/assets/docs/tree/package-and-test.doc.mjs +32 -0
- package/assets/docs/tree/page-template.doc.mjs +71 -0
- package/assets/docs/tree/publishing.doc.mjs +111 -0
- package/assets/docs/tree/quick-start.doc.mjs +272 -0
- package/assets/docs/tree/replace-a-core-component.doc.mjs +104 -0
- package/assets/docs/tree/replace-a-core-template.doc.mjs +172 -0
- package/assets/docs/tree/sections-and-placement.doc.mjs +108 -0
- package/assets/docs/tree/see-it-in-an-app.doc.mjs +59 -0
- package/assets/docs/tree/ship.doc.mjs +16 -0
- package/assets/docs/tree/short-and-findable.doc.mjs +108 -0
- package/assets/docs/tree/single-component.doc.mjs +165 -0
- package/assets/docs/tree/start-a-template.doc.mjs +143 -0
- package/assets/docs/tree/subcomponent.doc.mjs +115 -0
- package/assets/docs/tree/template-assets.doc.mjs +64 -0
- package/assets/docs/tree/template-doc-overview.doc.mjs +109 -0
- package/assets/docs/tree/template-fonts.doc.mjs +102 -0
- package/assets/docs/tree/template-grading-rubric.doc.mjs +452 -0
- package/assets/docs/tree/template-icons.doc.mjs +97 -0
- package/assets/docs/tree/template-images-media.doc.mjs +127 -0
- package/assets/docs/tree/template-styles.doc.mjs +93 -0
- package/assets/docs/tree/templates.doc.mjs +34 -0
- package/assets/docs/tree/test-in-an-app.doc.mjs +115 -0
- package/assets/docs/tree/test-template-in-app.doc.mjs +128 -0
- package/assets/docs/tree/themes.doc.mjs +39 -0
- package/assets/docs/tree/troubleshooting.doc.mjs +149 -0
- package/assets/docs/tree/upgrading.doc.mjs +103 -0
- package/assets/docs/tree/use-a-theme-in-an-app.doc.mjs +51 -0
- package/assets/docs/tree/verify-packed-template.doc.mjs +77 -0
- package/assets/docs/tree/versioning.doc.mjs +161 -0
- package/assets/docs/tree/write-good-templates.doc.mjs +64 -0
- package/assets/docs/tree/write-the-template-file.doc.mjs +154 -0
- package/assets/docs/typography.doc.mjs +24 -4
- package/assets/docs/working-with-ai.doc.mjs +30 -22
- package/authoring/config/config.doc.mjs +2 -2
- package/authoring/config/type.ts +2 -2
- package/authoring/doctypes/_schema.d.mts +3 -2
- package/authoring/doctypes/_schema.mjs +6 -0
- package/authoring/doctypes/base/graph-fields.doc.mjs +3 -3
- package/authoring/doctypes/base/type.ts +4 -2
- package/authoring/doctypes/command/command.doc.mjs +1 -1
- package/authoring/doctypes/command/type.ts +1 -1
- package/authoring/doctypes/component/component.doc.mjs +6 -0
- package/authoring/doctypes/component/type.ts +8 -0
- package/authoring/doctypes/reference/reference.doc.mjs +7 -0
- package/authoring/doctypes/reference/type.ts +5 -0
- 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/integration/integration.doc.mjs +12 -10
- package/clients/cli/command-result-coverage.test.mjs +7 -7
- package/clients/cli/commands/component.doc.mjs +4 -3
- package/clients/cli/commands/debug-result-summary.test.mjs +2 -2
- package/clients/cli/commands/docs.doc.mjs +1 -1
- package/clients/cli/commands/docs.mjs +60 -17
- package/clients/cli/commands/doctor-integration-docs.doc.mjs +3 -2
- package/clients/cli/commands/doctor-integration.test.mjs +53 -0
- package/clients/cli/commands/doctor.doc.mjs +3 -1
- package/clients/cli/commands/doctor.mjs +49 -5
- package/clients/cli/commands/gap-report.doc.mjs +10 -9
- package/clients/cli/commands/init.doc.mjs +9 -6
- package/clients/cli/commands/integration-add.doc.mjs +9 -9
- package/clients/cli/commands/integration-authoring.test.mjs +61 -10
- package/clients/cli/commands/integration-pack.doc.mjs +5 -9
- package/clients/cli/commands/integration-real-world.test.mjs +1 -1
- package/clients/cli/commands/integration-verify.doc.mjs +22 -0
- package/clients/cli/commands/integration.doc.mjs +4 -4
- package/clients/cli/commands/integration.mjs +74 -43
- 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 +10 -3
- package/clients/cli/commands/search.mjs +21 -2
- package/clients/cli/commands/search.test.mjs +21 -4
- 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 +24 -1
- package/clients/cli/commands/theme-add.doc.mjs +1 -1
- package/clients/cli/commands/theme-palette-generate.doc.mjs +3 -2
- package/clients/cli/commands/theme-palette.doc.mjs +1 -2
- package/clients/cli/commands/theme-targets.doc.mjs +2 -2
- package/clients/cli/commands/theme.doc.mjs +2 -1
- package/clients/cli/commands/upgrade.doc.mjs +62 -3
- package/clients/cli/index.mjs +32 -6
- package/clients/cli/lib/define-command.mjs +28 -4
- package/clients/cli/lib/define-command.test.mjs +54 -0
- package/clients/cli/lib/exit-codes.test.mjs +25 -2
- package/clients/cli/lib/json-shim.test.mjs +20 -6
- package/clients/cli/lib/manifest.mjs +23 -5
- package/foundation/agent-docs/agent-docs.mjs +1 -1
- package/foundation/discovery/authoring-self-docs.test.mjs +6 -2
- package/foundation/discovery/cli-self-docs.mjs +16 -2
- package/foundation/discovery/cli-self-docs.test.mjs +20 -0
- package/foundation/discovery/docs-discovery.mjs +5 -1
- package/foundation/discovery/docs-discovery.test.mjs +21 -0
- 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 +15 -2
- package/foundation/doc-compiler/inputs.test.mjs +0 -1
- package/foundation/doc-compiler/tree.d.mts +4 -0
- package/foundation/doc-compiler/tree.mjs +6 -1
- package/foundation/integrations/cli-requirement.d.mts +26 -6
- package/foundation/integrations/cli-requirement.mjs +46 -11
- package/foundation/integrations/cli-requirement.test.mjs +7 -2
- package/foundation/integrations/contribution-inventory.mjs +1 -1
- package/foundation/response/error-codes.doc.mjs +6 -8
- package/foundation/response/error-codes.test.mjs +30 -5
- package/foundation/response/response-types.doc.d.mts +4 -3
- package/foundation/response/response-types.doc.mjs +42 -6
- package/foundation/response/response.doc.mjs +11 -10
- 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/docs/docs.test.mjs +0 -245
- package/api/docs/integration-tree.test.mjs +0 -555
- package/api/docs/integrationDocs.test.mjs +0 -314
- package/api/search/search.test.mjs +0 -530
- package/assets/docs/tree/integrations.test.mjs +0 -62
- package/assets/docs/tree/writing-docs.doc.mjs +0 -286
- package/clients/cli/commands/docs.test.mjs +0 -323
- package/foundation/agent-docs/agent-docs.test.mjs +0 -1159
- package/foundation/doc-compiler/tree.test.mjs +0 -606
|
@@ -23,7 +23,7 @@ export type DoctorCheck = {
|
|
|
23
23
|
*/
|
|
24
24
|
message: string;
|
|
25
25
|
/**
|
|
26
|
-
* - Actionable remediation
|
|
26
|
+
* - Actionable remediation: always present on 'warn' and 'fail'; some 'info' checks carry one too.
|
|
27
27
|
*/
|
|
28
28
|
fix?: string | undefined;
|
|
29
29
|
};
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* @property {string} label - Human-readable check name.
|
|
20
20
|
* @property {DoctorStatus} status
|
|
21
21
|
* @property {string} message - One-line result summary.
|
|
22
|
-
* @property {string} [fix] - Actionable remediation
|
|
22
|
+
* @property {string} [fix] - Actionable remediation: always present on 'warn' and 'fail'; some 'info' checks carry one too.
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
25
|
/**
|
|
@@ -12,12 +12,16 @@ export const doc = {
|
|
|
12
12
|
name: 'gapReport',
|
|
13
13
|
namespace: 'cli/api',
|
|
14
14
|
displayName: 'gapReport()',
|
|
15
|
-
summary:
|
|
15
|
+
summary:
|
|
16
|
+
'Report a missing or hard-to-use design-system capability to the package that owns it.',
|
|
16
17
|
description:
|
|
17
|
-
'
|
|
18
|
+
'Sends a gap report to every configured handler: the project config handler first, then each integration handler in config order. ' +
|
|
19
|
+
'Each handler has 30 s to finish, and its output goes to stderr. Public handlers run only with confirmPublic; internal handlers always run. ' +
|
|
20
|
+
"With no handler, it files a GitHub issue for the owning package only with confirmPublic (without it nothing is sent), or returns the package's issues URL when that is not on GitHub. " +
|
|
21
|
+
'The report records whether an agent or a person ran it, and the response lists each handler outcome in order.',
|
|
18
22
|
importPath: '@astryxdesign/cli/api',
|
|
19
23
|
signature:
|
|
20
|
-
'gapReport(component
|
|
24
|
+
'gapReport(component: string | undefined, options?: GapReportOptions): Promise<GapReportCategoriesResponse | GapReportReceiptResponse>',
|
|
21
25
|
keywords: [
|
|
22
26
|
'gap',
|
|
23
27
|
'report',
|
|
@@ -56,13 +60,13 @@ export const doc = {
|
|
|
56
60
|
name: 'options.package',
|
|
57
61
|
type: 'string',
|
|
58
62
|
description:
|
|
59
|
-
'
|
|
63
|
+
'Package that owns the gap: @astryxdesign/core, or a loaded integration by package name or config entry. Overrides automatic owner routing; required when more than one package provides the component.',
|
|
60
64
|
},
|
|
61
65
|
{
|
|
62
66
|
name: 'options.confirmPublic',
|
|
63
67
|
type: 'boolean',
|
|
64
68
|
description:
|
|
65
|
-
'
|
|
69
|
+
'Allow public delivery: public handlers run, and with no handler a GitHub issue is filed through the gh CLI.',
|
|
66
70
|
default: 'false',
|
|
67
71
|
},
|
|
68
72
|
{
|
|
@@ -77,6 +81,7 @@ export const doc = {
|
|
|
77
81
|
type: 'string',
|
|
78
82
|
description:
|
|
79
83
|
'Directory used to load project config and component ownership.',
|
|
84
|
+
default: 'process.cwd()',
|
|
80
85
|
},
|
|
81
86
|
],
|
|
82
87
|
returns: [
|
|
@@ -87,17 +92,21 @@ export const doc = {
|
|
|
87
92
|
{
|
|
88
93
|
type: 'gap-report.file',
|
|
89
94
|
description:
|
|
90
|
-
'
|
|
95
|
+
'Receipt: status (filed, partial, failed, routed_only, consent_required, skipped), package, issuesUrl, ordered deliveries (handlerType, handler, audience, status, url, message), filedCount, and routedOnlyCount.',
|
|
91
96
|
},
|
|
92
97
|
],
|
|
93
98
|
throws: [
|
|
99
|
+
{
|
|
100
|
+
code: 'ERR_MISSING_ARGUMENT',
|
|
101
|
+
when: 'component, category, or reason is missing, blank, or not a string (unless listCategories is true)',
|
|
102
|
+
},
|
|
94
103
|
{
|
|
95
104
|
code: 'ERR_UNKNOWN_CATEGORY',
|
|
96
105
|
when: 'category is not one of the fixed gap-report values',
|
|
97
106
|
},
|
|
98
107
|
{
|
|
99
108
|
code: 'ERR_INVALID_ARGUMENT',
|
|
100
|
-
when: 'a
|
|
109
|
+
when: 'component is over 120 characters, category is over 80, reason is over 2000, or detail is not a string or is over 8000 characters',
|
|
101
110
|
},
|
|
102
111
|
{
|
|
103
112
|
code: 'ERR_AMBIGUOUS_COMPONENT',
|
|
@@ -109,7 +118,7 @@ export const doc = {
|
|
|
109
118
|
},
|
|
110
119
|
{
|
|
111
120
|
code: 'ERR_NOT_FOUND',
|
|
112
|
-
when: 'no handler and no issues URL
|
|
121
|
+
when: 'no report handler is configured and the owning package has no issues URL',
|
|
113
122
|
},
|
|
114
123
|
],
|
|
115
124
|
examples: [
|
|
@@ -122,8 +131,8 @@ export const doc = {
|
|
|
122
131
|
code: "const receipt = await gapReport('Button', {category: 'missing_variant', reason: 'Need a compact size'});",
|
|
123
132
|
},
|
|
124
133
|
{
|
|
125
|
-
label: '
|
|
126
|
-
code: "await gapReport('Button', {category: 'docs_gap', reason: 'Missing keyboard example',
|
|
134
|
+
label: 'Name the owning package',
|
|
135
|
+
code: "const receipt = await gapReport('Button', {category: 'docs_gap', reason: 'Missing keyboard example', package: '@astryxdesign/core'});",
|
|
127
136
|
},
|
|
128
137
|
],
|
|
129
138
|
command: 'gap-report',
|
package/api/hook/hook.doc.mjs
CHANGED
|
@@ -34,6 +34,7 @@ export const doc = {
|
|
|
34
34
|
name: 'options.cwd',
|
|
35
35
|
type: 'string',
|
|
36
36
|
description: 'Directory to resolve @astryxdesign/core from.',
|
|
37
|
+
default: 'process.cwd()',
|
|
37
38
|
},
|
|
38
39
|
{
|
|
39
40
|
name: 'options.list',
|
|
@@ -43,7 +44,8 @@ export const doc = {
|
|
|
43
44
|
{
|
|
44
45
|
name: 'options.category',
|
|
45
46
|
type: 'string',
|
|
46
|
-
description:
|
|
47
|
+
description:
|
|
48
|
+
"List only the hooks in this category, a key of the unfiltered list such as 'Media' or 'Focus'.",
|
|
47
49
|
},
|
|
48
50
|
{
|
|
49
51
|
name: 'options.params',
|
|
@@ -54,7 +56,8 @@ export const doc = {
|
|
|
54
56
|
name: 'options.detail',
|
|
55
57
|
type: "'full' | 'compact' | 'brief'",
|
|
56
58
|
description: 'Detail level for list views.',
|
|
57
|
-
default:
|
|
59
|
+
default:
|
|
60
|
+
"'full' for a named hook; 'brief' for lists (returned as data.detail: 'names')",
|
|
58
61
|
},
|
|
59
62
|
{
|
|
60
63
|
name: 'options.lang',
|
|
@@ -104,7 +107,7 @@ export const doc = {
|
|
|
104
107
|
},
|
|
105
108
|
{
|
|
106
109
|
label: 'Browse a category',
|
|
107
|
-
code: "await hook(undefined, {category: '
|
|
110
|
+
code: "await hook(undefined, {category: 'Media', detail: 'compact'});",
|
|
108
111
|
},
|
|
109
112
|
],
|
|
110
113
|
command: 'hook',
|
package/api/index.d.mts
CHANGED
|
@@ -33,12 +33,14 @@ export * from "./gap-report/gap-report.type.mjs";
|
|
|
33
33
|
export * from "./upgrade/upgrade.type.mjs";
|
|
34
34
|
export * from "./init/init.type.mjs";
|
|
35
35
|
export * from "./doctor/doctor.type.mjs";
|
|
36
|
+
export * from "./layout/layout.type.mjs";
|
|
36
37
|
export * from "./integration/integration-authoring.type.mjs";
|
|
37
38
|
export * from "./integration/pack-check.type.mjs";
|
|
38
39
|
export * from "./integration/validate-integration.type.mjs";
|
|
39
40
|
export * from "./integration/authoring-checks.type.mjs";
|
|
40
41
|
export type Logger = import("./logger.mjs").Logger;
|
|
41
42
|
export { themeBuild, themeAdd, themeTemplate, themeList, themeListAvailable, themeTargets, themePaletteGenerate, generateTonalPalette, listThemes } from "./theme/theme.mjs";
|
|
43
|
+
export { layoutExpand, layoutCheck, layoutGrammar } from "./layout/layout.mjs";
|
|
42
44
|
export { integrationAdd, integrationAddAgentDoc, integrationAddCodemod, integrationAddComponent, integrationAddDoc, integrationAddTemplate } from "./integration/add-contribution.mjs";
|
|
43
45
|
export { validateIntegration, summarizeIssues } from "./integration/validate-integration.mjs";
|
|
44
46
|
export { integrationTemplateConflicts, integrationComponentConflicts, integrationDocConflicts } from "./integration/authoring-checks.mjs";
|
package/api/index.mjs
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* @file Programmatic API for the Astryx CLI.
|
|
5
5
|
*
|
|
6
|
-
* Every function returns the same { type, data } envelope that `
|
|
6
|
+
* Every function returns the same { type, data } envelope that `astryx --json` outputs.
|
|
7
7
|
* Errors throw AstryxError (with optional .suggestions).
|
|
8
8
|
*
|
|
9
9
|
* @example
|
|
@@ -44,6 +44,7 @@ export {gapReport} from './gap-report/gap-report.mjs';
|
|
|
44
44
|
export {upgrade} from './upgrade/upgrade.mjs';
|
|
45
45
|
export {init} from './init/init.mjs';
|
|
46
46
|
export {doctor} from './doctor/doctor.mjs';
|
|
47
|
+
export {layoutExpand, layoutCheck, layoutGrammar} from './layout/layout.mjs';
|
|
47
48
|
export {
|
|
48
49
|
integrationAdd,
|
|
49
50
|
integrationAddAgentDoc,
|
|
@@ -92,6 +93,7 @@ export * from './gap-report/gap-report.type.mjs';
|
|
|
92
93
|
export * from './upgrade/upgrade.type.mjs';
|
|
93
94
|
export * from './init/init.type.mjs';
|
|
94
95
|
export * from './doctor/doctor.type.mjs';
|
|
96
|
+
export * from './layout/layout.type.mjs';
|
|
95
97
|
export * from './integration/integration-authoring.type.mjs';
|
|
96
98
|
export * from './integration/pack-check.type.mjs';
|
|
97
99
|
export * from './integration/validate-integration.type.mjs';
|
package/api/init/init.doc.mjs
CHANGED
|
@@ -19,10 +19,9 @@ export const doc = {
|
|
|
19
19
|
'Sets a project up with NO prompts, so it behaves identically for humans, ' +
|
|
20
20
|
'agents, CI, and piped I/O. By default it installs the AGENTS.md/CLAUDE.md ' +
|
|
21
21
|
'agent-docs cheat sheet, including guidance from configured integrations, and ' +
|
|
22
|
-
|
|
23
|
-
'
|
|
24
|
-
'
|
|
25
|
-
'instead of installing.',
|
|
22
|
+
"prints getting-started guidance; `features` / `all` print only the chosen features' " +
|
|
23
|
+
'guidance instead (the theme feature also writes the annotated theme template). ' +
|
|
24
|
+
'With `removeAgents` it removes the managed agent-docs block instead of installing.',
|
|
26
25
|
importPath: '@astryxdesign/cli/api',
|
|
27
26
|
signature:
|
|
28
27
|
'init(options?: InitOptions, ctx?: {cwd?: string}): Promise<InitRunResponse | InitRemoveResponse>',
|
|
@@ -32,7 +31,7 @@ export const doc = {
|
|
|
32
31
|
name: 'options.features',
|
|
33
32
|
type: 'string',
|
|
34
33
|
description:
|
|
35
|
-
'Comma-separated features to install: agents (agent docs), theme (writes the annotated theme.template.ts), template (page-
|
|
34
|
+
'Comma-separated features to install: agents (agent docs), theme (writes the annotated theme.template.ts), template (the page-building commands; writes a page only with templateName).',
|
|
36
35
|
},
|
|
37
36
|
{
|
|
38
37
|
name: 'options.all',
|
|
@@ -47,7 +46,8 @@ export const doc = {
|
|
|
47
46
|
{
|
|
48
47
|
name: 'options.agent',
|
|
49
48
|
type: 'string',
|
|
50
|
-
description:
|
|
49
|
+
description:
|
|
50
|
+
'Agent preset: claude, cursor, codex, hermes, muse, all. Used only when the agents feature runs.',
|
|
51
51
|
},
|
|
52
52
|
{
|
|
53
53
|
name: 'options.agentDocsPath',
|
|
@@ -58,9 +58,14 @@ export const doc = {
|
|
|
58
58
|
name: 'options.templateName',
|
|
59
59
|
type: 'string',
|
|
60
60
|
description:
|
|
61
|
-
'Scaffold
|
|
61
|
+
'Scaffold this page template to src/pages/<name>/page.tsx. Used only when the template feature runs (features includes template, or all); otherwise ignored. Programmatic only; the CLI never sets it.',
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
name: 'ctx.cwd',
|
|
65
|
+
type: 'string',
|
|
66
|
+
description: 'Directory to set up.',
|
|
67
|
+
default: 'process.cwd()',
|
|
62
68
|
},
|
|
63
|
-
{name: 'ctx.cwd', type: 'string', description: 'Directory to set up.'},
|
|
64
69
|
],
|
|
65
70
|
returns: [
|
|
66
71
|
{
|
|
@@ -71,13 +76,13 @@ export const doc = {
|
|
|
71
76
|
{
|
|
72
77
|
type: 'init.remove',
|
|
73
78
|
description:
|
|
74
|
-
'
|
|
79
|
+
'Returned when `removeAgents` is set. `data.removed` is always true, even when no managed block was found.',
|
|
75
80
|
},
|
|
76
81
|
],
|
|
77
82
|
throws: [
|
|
78
83
|
{
|
|
79
84
|
code: 'ERR_UNKNOWN_AGENT',
|
|
80
|
-
when: '`agent` is not one of claude, cursor, codex, hermes, muse, all',
|
|
85
|
+
when: 'the agents feature runs (default mode, features includes agents, or all) and `agent` is not one of claude, cursor, codex, hermes, muse, all',
|
|
81
86
|
},
|
|
82
87
|
{
|
|
83
88
|
code: 'ERR_UNKNOWN_FEATURE',
|
|
@@ -85,7 +90,7 @@ export const doc = {
|
|
|
85
90
|
},
|
|
86
91
|
{
|
|
87
92
|
code: 'ERR_UNKNOWN_TEMPLATE',
|
|
88
|
-
when: '`templateName` matches no bundled template',
|
|
93
|
+
when: 'the template feature runs and `templateName` matches no bundled template',
|
|
89
94
|
},
|
|
90
95
|
{
|
|
91
96
|
code: 'ERR_FILE_EXISTS',
|
|
@@ -93,7 +98,7 @@ export const doc = {
|
|
|
93
98
|
},
|
|
94
99
|
{
|
|
95
100
|
code: 'ERR_PATH_TRAVERSAL',
|
|
96
|
-
when: 'the template output path resolves outside cwd
|
|
101
|
+
when: 'the template output path resolves outside cwd (for example through a symlinked src directory), or, with removeAgents, a managed agent-docs file resolves outside cwd through a symlink',
|
|
97
102
|
},
|
|
98
103
|
],
|
|
99
104
|
examples: [
|
|
@@ -24,6 +24,10 @@ import {
|
|
|
24
24
|
import {loadManifestObject} from '../../foundation/integrations/integrations.mjs';
|
|
25
25
|
import {themeDescriptorSource} from '../../foundation/integrations/theme-descriptor.mjs';
|
|
26
26
|
import {assertContributionVisible} from '../../foundation/integrations/contribution-inventory.mjs';
|
|
27
|
+
import {
|
|
28
|
+
themesCliProblem,
|
|
29
|
+
withDocsTreeCli,
|
|
30
|
+
} from '../../foundation/integrations/cli-requirement.mjs';
|
|
27
31
|
import {
|
|
28
32
|
applyWrites,
|
|
29
33
|
findPackageDir,
|
|
@@ -233,11 +237,28 @@ export async function integrationAddTheme(name, options = {}) {
|
|
|
233
237
|
createOnly: true,
|
|
234
238
|
},
|
|
235
239
|
];
|
|
236
|
-
|
|
240
|
+
let packageUpdate = packageJsonUpdate(
|
|
237
241
|
packageFile,
|
|
238
242
|
rootPath,
|
|
239
243
|
path.basename(manifestFile),
|
|
240
244
|
);
|
|
245
|
+
// A CLI older than the one that reads typed theme descriptors rejects the
|
|
246
|
+
// themes root and withholds the package's themes and docs. Declare the CLI
|
|
247
|
+
// that reads them as a peer, so an older one is flagged at install instead.
|
|
248
|
+
{
|
|
249
|
+
const expectedOriginal =
|
|
250
|
+
packageUpdate?.expectedOriginal ?? fs.readFileSync(packageFile);
|
|
251
|
+
const text = packageUpdate?.contents ?? expectedOriginal.toString('utf-8');
|
|
252
|
+
const current = JSON.parse(text);
|
|
253
|
+
if (themesCliProblem(current) != null) {
|
|
254
|
+
packageUpdate = {
|
|
255
|
+
contents:
|
|
256
|
+
JSON.stringify(withDocsTreeCli(current), null, 2) +
|
|
257
|
+
(text.endsWith('\n') ? '\n' : ''),
|
|
258
|
+
expectedOriginal,
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
}
|
|
241
262
|
if (packageUpdate != null) {
|
|
242
263
|
plans.push({
|
|
243
264
|
path: packageFile,
|
|
@@ -77,6 +77,40 @@ describe('integrationAddTheme', () => {
|
|
|
77
77
|
expect((await validateLocalIntegration(tmpDir)).issues).toEqual([]);
|
|
78
78
|
});
|
|
79
79
|
|
|
80
|
+
it('declares the optional CLI peer that reads typed theme descriptors', async () => {
|
|
81
|
+
setup({includeFiles: false});
|
|
82
|
+
const result = await integrationAddTheme('ocean', {cwd: tmpDir});
|
|
83
|
+
expect(result.data.files).toContain('package.json');
|
|
84
|
+
const pkg = JSON.parse(
|
|
85
|
+
fs.readFileSync(path.join(tmpDir, 'package.json'), 'utf-8'),
|
|
86
|
+
);
|
|
87
|
+
expect(pkg.peerDependencies).toEqual({'@astryxdesign/cli': '>=0.7.0'});
|
|
88
|
+
expect(pkg.peerDependenciesMeta).toEqual({
|
|
89
|
+
'@astryxdesign/cli': {optional: true},
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it('keeps a CLI peer that already reads typed theme descriptors', async () => {
|
|
94
|
+
const pkg = {
|
|
95
|
+
name: '@acme/themes',
|
|
96
|
+
version: '1.0.0',
|
|
97
|
+
peerDependencies: {'@astryxdesign/cli': '^0.7.2'},
|
|
98
|
+
};
|
|
99
|
+
fs.writeFileSync(
|
|
100
|
+
path.join(tmpDir, 'package.json'),
|
|
101
|
+
`${JSON.stringify(pkg, null, 2)}\n`,
|
|
102
|
+
);
|
|
103
|
+
fs.writeFileSync(
|
|
104
|
+
path.join(tmpDir, 'astryx.integration.mjs'),
|
|
105
|
+
'export default {};\n',
|
|
106
|
+
);
|
|
107
|
+
const result = await integrationAddTheme('ocean', {cwd: tmpDir});
|
|
108
|
+
expect(result.data.files).not.toContain('package.json');
|
|
109
|
+
expect(
|
|
110
|
+
JSON.parse(fs.readFileSync(path.join(tmpDir, 'package.json'), 'utf-8')),
|
|
111
|
+
).toEqual(pkg);
|
|
112
|
+
});
|
|
113
|
+
|
|
80
114
|
it('dry-runs the identical receipt without writing anything', async () => {
|
|
81
115
|
setup();
|
|
82
116
|
const beforeManifest = fs.readFileSync(
|
|
@@ -368,11 +368,11 @@ export async function integrationDocConflicts(pkg, options = {}) {
|
|
|
368
368
|
// and placed guides this package adds to the docs tree, and every link in
|
|
369
369
|
// its docs (spec:AST-046, spec:AST-047).
|
|
370
370
|
if (errors.length === 0) {
|
|
371
|
-
for (const message of await packageDocsProblems(
|
|
371
|
+
for (const {severity, message} of await packageDocsProblems(
|
|
372
372
|
/** @type {{name: string}} */ (resolved.integration),
|
|
373
373
|
discovered,
|
|
374
374
|
)) {
|
|
375
|
-
issues.push({code: 'invalid_doc_graph', severity
|
|
375
|
+
issues.push({code: 'invalid_doc_graph', severity, message});
|
|
376
376
|
}
|
|
377
377
|
|
|
378
378
|
// A reference block includes content rather than linking to it, so one
|
|
@@ -7,13 +7,13 @@ export const doc = {
|
|
|
7
7
|
name: 'integrationPackCheck',
|
|
8
8
|
namespace: 'cli/api',
|
|
9
9
|
displayName: 'integrationPackCheck()',
|
|
10
|
-
summary: '
|
|
10
|
+
summary: 'Check an integration package the way npm will publish it.',
|
|
11
11
|
description:
|
|
12
12
|
"Validates the local integration, runs the package lifecycle, packs with npm, checks required files against npm's authoritative tarball list, extracts the real tarball into a scratch consumer, compares local and packed contribution inventories, and resolves every packed component through its documented public import to verify that module exports the component. A package that ships a namespace doc or a placed guide, or has a template that sets `replaces`, fails unless its `@astryxdesign/cli` peer range admits only CLIs that read them.",
|
|
13
13
|
importPath: '@astryxdesign/cli/api',
|
|
14
14
|
signature:
|
|
15
15
|
'integrationPackCheck(options?: IntegrationPackCheckOptions): Promise<IntegrationPackCheckResponse>',
|
|
16
|
-
keywords: ['
|
|
16
|
+
keywords: ['verify', 'pack', 'publish', 'tarball', 'consumer'],
|
|
17
17
|
params: [
|
|
18
18
|
{
|
|
19
19
|
name: 'options.cwd',
|
|
@@ -31,6 +31,6 @@ export const doc = {
|
|
|
31
31
|
examples: [
|
|
32
32
|
{label: 'Check the local package', code: 'await integrationPackCheck();'},
|
|
33
33
|
],
|
|
34
|
-
command: 'integration
|
|
34
|
+
command: 'integration verify',
|
|
35
35
|
related: ['integrationAdd', 'validateIntegration'],
|
|
36
36
|
};
|
|
@@ -24,6 +24,8 @@ function writeThemePackage(scripts) {
|
|
|
24
24
|
name: '@acme/widgets',
|
|
25
25
|
version: '1.0.0',
|
|
26
26
|
files: ['astryx.integration.mjs', 'themes'],
|
|
27
|
+
peerDependencies: {'@astryxdesign/cli': '>=0.7.0'},
|
|
28
|
+
peerDependenciesMeta: {'@astryxdesign/cli': {optional: true}},
|
|
27
29
|
scripts,
|
|
28
30
|
},
|
|
29
31
|
null,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* @file `astryx integration
|
|
4
|
+
* @file `astryx integration verify` — verify an integration package is
|
|
5
5
|
* ready to publish by cross-referencing its declared contributions against the
|
|
6
6
|
* real npm tarball.
|
|
7
7
|
*
|
|
@@ -30,8 +30,13 @@ import {resolvePackageDir} from '../../foundation/integrations/integrations.mjs'
|
|
|
30
30
|
import {
|
|
31
31
|
docsTreeCliProblem,
|
|
32
32
|
replacesCliProblem,
|
|
33
|
+
sectionIdsCliProblem,
|
|
34
|
+
themesCliProblem,
|
|
33
35
|
} from '../../foundation/integrations/cli-requirement.mjs';
|
|
34
|
-
import {
|
|
36
|
+
import {
|
|
37
|
+
discoverIntegrationDocs,
|
|
38
|
+
loadTopicModule,
|
|
39
|
+
} from '../../foundation/discovery/docs-discovery.mjs';
|
|
35
40
|
import {
|
|
36
41
|
discoverIntegrationComponents,
|
|
37
42
|
resolveIntegrationImportPath,
|
|
@@ -333,6 +338,23 @@ function moduleExportsName(file, exportName, seen = new Set()) {
|
|
|
333
338
|
return found;
|
|
334
339
|
}
|
|
335
340
|
|
|
341
|
+
/**
|
|
342
|
+
* Whether any of these doc files has a section that sets `id`.
|
|
343
|
+
* @param {string[]} files
|
|
344
|
+
* @returns {Promise<boolean>}
|
|
345
|
+
*/
|
|
346
|
+
async function setsSectionIds(files) {
|
|
347
|
+
for (const file of files) {
|
|
348
|
+
if (typeof file !== 'string') continue;
|
|
349
|
+
const doc = /** @type {any} */ (await loadTopicModule(file).catch(() => null));
|
|
350
|
+
const sections = Array.isArray(doc?.sections) ? doc.sections : [];
|
|
351
|
+
if (sections.some((/** @type {any} */ section) => section?.id != null)) {
|
|
352
|
+
return true;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
return false;
|
|
356
|
+
}
|
|
357
|
+
|
|
336
358
|
/**
|
|
337
359
|
* Resolve package specifiers through Node's real ESM resolver from the scratch
|
|
338
360
|
* consumer. Resolution does not execute the target module, so source `.tsx`
|
|
@@ -625,19 +647,31 @@ export async function integrationPackCheck(options = {}) {
|
|
|
625
647
|
// (spec:AST-046 FR11): an older CLI can hide every doc topic the package
|
|
626
648
|
// ships, so the declared CLI range must admit only CLIs that read it.
|
|
627
649
|
if (loaded.docs) {
|
|
628
|
-
const {namespaces, guides} = await discoverIntegrationDocs(
|
|
629
|
-
|
|
630
|
-
);
|
|
650
|
+
const {records, namespaces, guides} = await discoverIntegrationDocs(
|
|
651
|
+
loaded,
|
|
652
|
+
).catch(() => ({records: [], namespaces: [], guides: []}));
|
|
631
653
|
const problem =
|
|
632
654
|
namespaces.length > 0 || guides.length > 0
|
|
633
655
|
? docsTreeCliProblem(pkg)
|
|
634
656
|
: null;
|
|
635
657
|
if (problem != null) {
|
|
636
658
|
issues.push(error('docs_tree_needs_cli', problem));
|
|
659
|
+
} else if (
|
|
660
|
+
await setsSectionIds([
|
|
661
|
+
...records.map(record => record.path),
|
|
662
|
+
...guides.map(guide => /** @type {any} */ (guide.ref).topicFile),
|
|
663
|
+
])
|
|
664
|
+
) {
|
|
665
|
+
// A section `id` is also a field an older CLI rejects, hiding the
|
|
666
|
+
// package's doc topics; the same peer range fixes both.
|
|
667
|
+
const idProblem = sectionIdsCliProblem(pkg);
|
|
668
|
+
if (idProblem != null) {
|
|
669
|
+
issues.push(error('section_ids_need_cli', idProblem));
|
|
670
|
+
}
|
|
637
671
|
}
|
|
638
672
|
}
|
|
639
673
|
// A template that sets `replaces` needs a CLI that reads the field
|
|
640
|
-
// (spec:AST-035): an older CLI
|
|
674
|
+
// (spec:AST-035): an older CLI drops that template and hides the package's docs.
|
|
641
675
|
if (loaded.templates) {
|
|
642
676
|
const found = await discoverIntegrationTemplatesForOne(loaded).catch(
|
|
643
677
|
() => ({templates: [], errors: []}),
|
|
@@ -650,6 +684,12 @@ export async function integrationPackCheck(options = {}) {
|
|
|
650
684
|
const problem = setsReplaces ? replacesCliProblem(pkg) : null;
|
|
651
685
|
if (problem != null) issues.push(error('replaces_needs_cli', problem));
|
|
652
686
|
}
|
|
687
|
+
// A theme needs a CLI that reads typed theme descriptors: an older CLI
|
|
688
|
+
// rejects the themes root and withholds the package's themes and docs.
|
|
689
|
+
if (localIdentities.themes.length > 0) {
|
|
690
|
+
const problem = themesCliProblem(pkg);
|
|
691
|
+
if (problem != null) issues.push(error('themes_need_cli', problem));
|
|
692
|
+
}
|
|
653
693
|
|
|
654
694
|
// Temp resources — always cleaned up
|
|
655
695
|
const tgzTmpDir = fs.mkdtempSync(
|
|
@@ -682,6 +722,14 @@ export async function integrationPackCheck(options = {}) {
|
|
|
682
722
|
// package's already-installed dependencies. The unique suffix makes
|
|
683
723
|
// concurrent checks independent.
|
|
684
724
|
scratchBase = fs.mkdtempSync(path.join(packageDir, '.astryx-pack-check-'));
|
|
725
|
+
// The consumer's own package.json makes it the package scope for its
|
|
726
|
+
// imports. Without one, Node resolves the package's name through the
|
|
727
|
+
// SOURCE package.json (self-reference), so an export target left out of
|
|
728
|
+
// the tarball would still resolve.
|
|
729
|
+
fs.writeFileSync(
|
|
730
|
+
path.join(scratchBase, 'package.json'),
|
|
731
|
+
`${JSON.stringify({name: 'astryx-verify-consumer', private: true})}\n`,
|
|
732
|
+
);
|
|
685
733
|
|
|
686
734
|
// Cross-reference file inventory vs pack list
|
|
687
735
|
if (!packResult.packedPaths.has(fileInv.manifest)) {
|
|
@@ -36,6 +36,8 @@ function writePackage({
|
|
|
36
36
|
scripts,
|
|
37
37
|
} = {}) {
|
|
38
38
|
const pkg = {name, version};
|
|
39
|
+
// A theme needs a CLI that reads typed theme descriptors.
|
|
40
|
+
if (themes) pkg.peerDependencies = {'@astryxdesign/cli': '>=0.7.0'};
|
|
39
41
|
if (files !== undefined) pkg.files = files;
|
|
40
42
|
if (scripts !== undefined) pkg.scripts = scripts;
|
|
41
43
|
fs.writeFileSync(
|
|
@@ -94,6 +96,30 @@ describe('integrationPackCheck', () => {
|
|
|
94
96
|
);
|
|
95
97
|
});
|
|
96
98
|
|
|
99
|
+
it('fails a package that ships a theme on a CLI range that cannot read it', async () => {
|
|
100
|
+
writePackage({files: ['astryx.integration.mjs', 'themes']});
|
|
101
|
+
const pkgFile = path.join(tmpDir, 'package.json');
|
|
102
|
+
const pkg = JSON.parse(fs.readFileSync(pkgFile, 'utf-8'));
|
|
103
|
+
delete pkg.peerDependencies;
|
|
104
|
+
fs.writeFileSync(pkgFile, `${JSON.stringify(pkg, null, 2)}\n`);
|
|
105
|
+
|
|
106
|
+
const missing = await integrationPackCheck({cwd: tmpDir});
|
|
107
|
+
expect(missing.data.packable).toBe(false);
|
|
108
|
+
expect(missing.data.issues).toContainEqual(
|
|
109
|
+
expect.objectContaining({
|
|
110
|
+
code: 'themes_need_cli',
|
|
111
|
+
message: expect.stringContaining('ships a theme'),
|
|
112
|
+
}),
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
pkg.peerDependencies = {'@astryxdesign/cli': '^0.6.3'};
|
|
116
|
+
fs.writeFileSync(pkgFile, `${JSON.stringify(pkg, null, 2)}\n`);
|
|
117
|
+
const old = await integrationPackCheck({cwd: tmpDir});
|
|
118
|
+
expect(old.data.issues).toContainEqual(
|
|
119
|
+
expect.objectContaining({code: 'themes_need_cli'}),
|
|
120
|
+
);
|
|
121
|
+
});
|
|
122
|
+
|
|
97
123
|
it('fails when a theme entry omits its inferred runtime export', async () => {
|
|
98
124
|
writePackage({files: ['astryx.integration.mjs', 'themes']});
|
|
99
125
|
fs.writeFileSync(
|
|
@@ -193,6 +219,39 @@ describe('integrationPackCheck', () => {
|
|
|
193
219
|
);
|
|
194
220
|
});
|
|
195
221
|
|
|
222
|
+
it('resolves public imports in the packed package, not the source', async () => {
|
|
223
|
+
// The root export's target is left out of `files`: the source package
|
|
224
|
+
// resolves it, but an app that installs the tarball cannot.
|
|
225
|
+
fs.writeFileSync(
|
|
226
|
+
path.join(tmpDir, 'package.json'),
|
|
227
|
+
`${JSON.stringify({
|
|
228
|
+
name: '@acme/widgets',
|
|
229
|
+
version: '1.0.0',
|
|
230
|
+
files: ['astryx.integration.mjs'],
|
|
231
|
+
exports: {'.': './index.mjs'},
|
|
232
|
+
})}\n`,
|
|
233
|
+
);
|
|
234
|
+
fs.writeFileSync(
|
|
235
|
+
path.join(tmpDir, 'index.mjs'),
|
|
236
|
+
"export {AcmeWidget} from './components/AcmeWidget.tsx';\n",
|
|
237
|
+
);
|
|
238
|
+
await integrationAddComponent('AcmeWidget', {cwd: tmpDir});
|
|
239
|
+
const docFile = path.join(tmpDir, 'components', 'AcmeWidget.doc.mjs');
|
|
240
|
+
const doc = fs.readFileSync(docFile, 'utf-8');
|
|
241
|
+
expect(doc).toContain('@acme/widgets/components/AcmeWidget');
|
|
242
|
+
fs.writeFileSync(
|
|
243
|
+
docFile,
|
|
244
|
+
doc.replace('@acme/widgets/components/AcmeWidget', '@acme/widgets'),
|
|
245
|
+
);
|
|
246
|
+
|
|
247
|
+
const result = await integrationPackCheck({cwd: tmpDir});
|
|
248
|
+
|
|
249
|
+
expect(result.data.packable).toBe(false);
|
|
250
|
+
expect(result.data.issues).toContainEqual(
|
|
251
|
+
expect.objectContaining({code: 'component_export_missing'}),
|
|
252
|
+
);
|
|
253
|
+
});
|
|
254
|
+
|
|
196
255
|
it('fails when packed template source is hidden by package exports', async () => {
|
|
197
256
|
writePackage({
|
|
198
257
|
manifest: "export default {templates: './templates'};\n",
|
|
@@ -336,6 +395,37 @@ describe('integrationPackCheck', () => {
|
|
|
336
395
|
expect(await codes()).not.toContain('docs_tree_needs_cli');
|
|
337
396
|
}, 120_000);
|
|
338
397
|
|
|
398
|
+
it('fails a package whose doc section sets id on a CLI range that rejects the field', async () => {
|
|
399
|
+
writePackage({manifest: "export default {docs: './docs'};\n", themes: false});
|
|
400
|
+
fs.mkdirSync(path.join(tmpDir, 'docs'), {recursive: true});
|
|
401
|
+
const topic = (/** @type {string} */ section) =>
|
|
402
|
+
`export default {type: 'generic', name: 'notes', title: 'Notes', description: 'Notes.', sections: [${section}]};\n`;
|
|
403
|
+
const file = path.join(tmpDir, 'docs', 'notes.doc.mjs');
|
|
404
|
+
const codes = async () =>
|
|
405
|
+
(await integrationPackCheck({cwd: tmpDir})).data.issues.map(
|
|
406
|
+
(/** @type {{code: string}} */ issue) => issue.code,
|
|
407
|
+
);
|
|
408
|
+
fs.writeFileSync(
|
|
409
|
+
file,
|
|
410
|
+
topic("{title: 'Take notes', content: [{type: 'prose', text: 'Notes.'}]}"),
|
|
411
|
+
);
|
|
412
|
+
expect(await codes()).not.toContain('section_ids_need_cli');
|
|
413
|
+
// A fresh file name: the module loader caches a path once it is imported.
|
|
414
|
+
fs.rmSync(file);
|
|
415
|
+
fs.writeFileSync(
|
|
416
|
+
path.join(tmpDir, 'docs', 'notes-with-ids.doc.mjs'),
|
|
417
|
+
topic(
|
|
418
|
+
"{id: 'take-notes', title: 'Take notes', content: [{type: 'prose', text: 'Notes.'}]}",
|
|
419
|
+
),
|
|
420
|
+
);
|
|
421
|
+
expect(await codes()).toContain('section_ids_need_cli');
|
|
422
|
+
const pkgFile = path.join(tmpDir, 'package.json');
|
|
423
|
+
const pkg = JSON.parse(fs.readFileSync(pkgFile, 'utf-8'));
|
|
424
|
+
pkg.peerDependencies = {'@astryxdesign/cli': '>=0.7.0'};
|
|
425
|
+
fs.writeFileSync(pkgFile, `${JSON.stringify(pkg, null, 2)}\n`);
|
|
426
|
+
expect(await codes()).not.toContain('section_ids_need_cli');
|
|
427
|
+
}, 120_000);
|
|
428
|
+
|
|
339
429
|
it('fails a package with a template that sets replaces on a CLI range that rejects the field', async () => {
|
|
340
430
|
writePackage({manifest: "export default {templates: './templates'};\n", themes: false});
|
|
341
431
|
fs.mkdirSync(path.join(tmpDir, 'templates'), {recursive: true});
|
|
@@ -49,7 +49,7 @@ export const doc = {
|
|
|
49
49
|
throws: [
|
|
50
50
|
{
|
|
51
51
|
code: 'Error',
|
|
52
|
-
when: 'the CLI returned an error envelope (
|
|
52
|
+
when: 'a plain Error with no code: the CLI returned an error envelope (its message is rethrown; code and suggestions are dropped), or the response `type` is not expectedType',
|
|
53
53
|
},
|
|
54
54
|
],
|
|
55
55
|
examples: [
|