@astryxdesign/cli 0.7.2-canary.ebcc404 → 0.7.2-canary.f2b60a0
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 +15 -14
- package/api/build/help/help.mjs +1 -1
- package/api/component/_adapter.d.mts +14 -0
- package/api/component/_adapter.mjs +48 -0
- package/api/component/component.mjs +10 -2
- package/api/component/integration-export-name.test.mjs +233 -8
- package/api/docs/_adapter.d.mts +11 -0
- package/api/docs/_adapter.mjs +244 -1
- package/api/docs/integrationDocs.test.mjs +124 -0
- package/api/doctor/doctor.mjs +27 -3
- package/api/doctor/doctor.test.mjs +43 -0
- package/api/doctor/theme-checks.mjs +1 -1
- package/api/gap-report/gap-report.mjs +2 -1
- package/api/index.d.mts +2 -0
- package/api/index.mjs +2 -0
- package/api/init/run/run.mjs +2 -2
- package/api/integration/_adapter.d.mts +12 -0
- package/api/integration/_adapter.mjs +54 -0
- package/api/integration/add-contribution.component-names.test.mjs +66 -0
- package/api/integration/add-contribution.mjs +8 -4
- package/api/integration/add-contribution.test.mjs +4 -2
- package/api/integration/authoring-checks.mjs +11 -2
- package/api/integration/authoring-checks.test.mjs +39 -0
- package/api/integration/authoring-checks.type.d.mts +9 -0
- package/api/integration/authoring-checks.type.mjs +14 -1
- package/api/integration/check/check.d.mts +96 -0
- package/api/integration/check/check.mjs +357 -0
- package/api/integration/check/check.test.mjs +489 -0
- package/api/integration/integration-check.type.d.mts +118 -0
- package/api/integration/integration-check.type.mjs +84 -0
- package/api/integration/integrationCheck.doc.d.mts +10 -0
- package/api/integration/integrationCheck.doc.mjs +73 -0
- package/api/integration/integrationComponentConflicts.doc.mjs +36 -5
- package/api/integration/pack-check.mjs +48 -3
- package/api/integration/pack-check.test.mjs +247 -0
- package/api/integration/validate-integration.mjs +8 -0
- package/api/integration/validate-integration.test.mjs +11 -0
- package/api/integration/validate-integration.type.d.mts +8 -0
- package/api/integration/validate-integration.type.mjs +12 -1
- package/api/integration/validateIntegration.doc.mjs +17 -3
- package/api/search/search.d.mts +13 -6
- package/api/search/search.domain-priority.test.mjs +108 -18
- package/api/search/search.integration-check.test.mjs +24 -0
- package/api/search/search.mjs +53 -17
- package/api/theme/build/build.family.test.mjs +54 -6
- package/api/theme/build/build.mjs +114 -17
- package/api/theme/themeBuild.doc.mjs +4 -4
- package/assets/docs/README.md +10 -0
- package/assets/docs/author-a-theme.doc.mjs +1 -1
- package/assets/docs/getting-started.doc.mjs +3 -3
- package/assets/docs/styling-overview.doc.mjs +1 -1
- package/assets/docs/theme.doc.dense.mjs +1 -1
- package/assets/docs/theme.doc.mjs +1 -1
- package/assets/docs/theme.doc.zh.mjs +1 -1
- package/assets/docs/tree/add-a-component.doc.mjs +11 -1
- package/assets/docs/tree/add-a-theme.doc.mjs +1 -1
- package/assets/docs/tree/add-a-topic.doc.mjs +10 -7
- package/assets/docs/tree/agent-guidance.doc.mjs +2 -2
- package/assets/docs/tree/block-template.doc.mjs +8 -20
- package/assets/docs/tree/build-the-template.doc.mjs +1 -1
- package/assets/docs/tree/check-the-props.doc.mjs +196 -0
- package/assets/docs/tree/check-your-docs.doc.mjs +51 -5
- package/assets/docs/tree/checks.doc.mjs +24 -16
- package/assets/docs/tree/codemods.doc.mjs +4 -4
- package/assets/docs/tree/component-family.doc.mjs +8 -6
- package/assets/docs/tree/component-imports.doc.mjs +3 -3
- package/assets/docs/tree/components.doc.mjs +1 -1
- package/assets/docs/tree/debug-and-gap-reports.doc.mjs +7 -18
- package/assets/docs/tree/define-the-theme.doc.mjs +6 -5
- package/assets/docs/tree/describe-the-component.doc.mjs +2 -2
- package/assets/docs/tree/docs.doc.mjs +3 -3
- 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 +6 -6
- package/assets/docs/tree/fonts-and-assets.doc.mjs +2 -2
- package/assets/docs/tree/generate-a-palette.doc.mjs +5 -3
- package/assets/docs/tree/grade-template-with-agent.doc.mjs +1 -1
- package/assets/docs/tree/integrations.doc.mjs +8 -0
- package/assets/docs/tree/links.doc.mjs +6 -5
- package/assets/docs/tree/migration-setup.doc.mjs +1 -0
- package/assets/docs/tree/migration-verification.doc.mjs +0 -1
- package/assets/docs/tree/migration.doc.mjs +0 -1
- package/assets/docs/tree/package-and-test.doc.mjs +1 -1
- package/assets/docs/tree/page-template.doc.mjs +4 -8
- package/assets/docs/tree/publishing.doc.mjs +1 -1
- package/assets/docs/tree/quick-start.doc.mjs +37 -21
- package/assets/docs/tree/replace-a-core-component.doc.mjs +4 -6
- package/assets/docs/tree/replace-a-core-template.doc.mjs +6 -8
- package/assets/docs/tree/sections-and-placement.doc.mjs +4 -6
- package/assets/docs/tree/see-it-in-an-app.doc.mjs +4 -2
- package/assets/docs/tree/short-and-findable.doc.mjs +6 -5
- package/assets/docs/tree/single-component.doc.mjs +15 -6
- package/assets/docs/tree/start-a-template.doc.mjs +3 -3
- package/assets/docs/tree/subcomponent.doc.mjs +6 -6
- package/assets/docs/tree/template-assets.doc.mjs +2 -2
- package/assets/docs/tree/template-doc-overview.doc.mjs +4 -15
- package/assets/docs/tree/template-fonts.doc.mjs +1 -1
- 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 +2 -2
- package/assets/docs/tree/templates.doc.mjs +1 -1
- package/assets/docs/tree/test-in-an-app.doc.mjs +3 -3
- package/assets/docs/tree/test-template-in-app.doc.mjs +1 -1
- package/assets/docs/tree/tokens-and-setup.doc.mjs +19 -15
- package/assets/docs/tree/troubleshooting.doc.mjs +13 -5
- package/assets/docs/tree/type-scale.doc.mjs +3 -3
- package/assets/docs/tree/upgrading.doc.mjs +3 -3
- package/assets/docs/tree/use-a-theme-in-an-app.doc.mjs +3 -1
- package/assets/docs/tree/verify-packed-template.doc.mjs +1 -1
- package/assets/docs/tree/versioning.doc.mjs +7 -6
- package/assets/docs/tree/write-the-template-file.doc.mjs +4 -3
- package/assets/docs/use-a-theme.doc.mjs +2 -2
- package/assets/theme.template.ts +1 -1
- package/authoring/codemod/codemod.doc.mjs +7 -3
- package/authoring/config/config.doc.mjs +9 -6
- package/authoring/config/type.ts +4 -2
- package/authoring/discover/discover.doc.mjs +1 -1
- package/authoring/doctypes/base/graph-fields.doc.mjs +6 -4
- package/authoring/doctypes/command/command.doc.mjs +14 -12
- package/authoring/doctypes/component/component.doc.mjs +29 -26
- package/authoring/doctypes/component/type.ts +7 -5
- package/authoring/doctypes/enum/enum.doc.mjs +7 -4
- package/authoring/doctypes/function/function.doc.mjs +9 -8
- package/authoring/doctypes/hook/hook.doc.mjs +5 -4
- package/authoring/doctypes/namespace/namespace.doc.mjs +7 -6
- package/authoring/doctypes/reference/reference.doc.mjs +11 -10
- package/authoring/doctypes/schema/schema.doc.mjs +9 -9
- package/authoring/doctypes/template/integration-template.doc.d.mts +11 -0
- package/authoring/doctypes/template/integration-template.doc.mjs +49 -0
- package/authoring/doctypes/template/parse.d.mts +6 -2
- package/authoring/doctypes/template/parse.mjs +3 -1
- package/authoring/doctypes/template/template.doc.mjs +3 -3
- package/authoring/doctypes/template/type.ts +22 -0
- package/authoring/doctypes/theme/theme.doc.mjs +2 -2
- package/authoring/gap-report/gap-report.doc.mjs +2 -2
- package/authoring/identity/identity.doc.mjs +3 -3
- package/authoring/index.d.ts +1 -0
- package/authoring/integration/integration.doc.mjs +12 -4
- package/authoring/integration/parse.test.mjs +10 -0
- package/authoring/integration/schema.d.mts +2 -0
- package/authoring/integration/schema.mjs +1 -0
- package/authoring/integration/type.ts +4 -0
- package/clients/cli/commands/build-theme.batch-report.test.mjs +3 -1
- package/clients/cli/commands/build-theme.mjs +1 -1
- package/clients/cli/commands/build-theme.path-safety.test.mjs +155 -21
- package/clients/cli/commands/cli-postinstall.test.mjs +49 -1
- package/clients/cli/commands/doctor-integration-components.doc.mjs +15 -4
- package/clients/cli/commands/doctor-integration-validate.doc.mjs +11 -2
- package/clients/cli/commands/doctor-integration.test.mjs +837 -0
- package/clients/cli/commands/doctor.mjs +190 -0
- package/clients/cli/commands/integration-check.doc.mjs +85 -0
- package/clients/cli/commands/integration-check.test.mjs +267 -0
- package/clients/cli/commands/integration.doc.mjs +6 -2
- package/clients/cli/commands/integration.mjs +107 -1
- package/clients/cli/commands/setup-nudge.test.mjs +79 -1
- package/clients/cli/commands/swizzle.mjs +5 -3
- package/clients/cli/commands/swizzle.routing.test.mjs +18 -1
- package/clients/cli/commands/text-json-parity.test.mjs +5 -0
- package/clients/cli/commands/theme-build.doc.mjs +2 -2
- package/clients/cli/index.mjs +30 -5
- package/foundation/agent-docs/agent-doc-state.d.mts +14 -0
- package/foundation/agent-docs/agent-doc-state.mjs +38 -0
- package/foundation/agent-docs/agent-docs.d.mts +2 -1
- package/foundation/agent-docs/agent-docs.mjs +8 -6
- package/foundation/config/project.mjs +82 -0
- package/foundation/discovery/authoring-self-docs.mjs +2 -1
- package/foundation/discovery/component-discovery.d.mts +108 -17
- package/foundation/discovery/component-discovery.export-names.test.mjs +469 -2
- package/foundation/discovery/component-discovery.mjs +380 -47
- package/foundation/discovery/component-replacement.test.mjs +20 -0
- package/foundation/discovery/doc-types.d.mts +157 -0
- package/foundation/discovery/doc-types.mjs +1224 -0
- package/foundation/discovery/doc-types.test.mjs +652 -0
- package/foundation/discovery/docs-discovery.d.mts +81 -0
- package/foundation/discovery/docs-discovery.mjs +57 -0
- package/foundation/discovery/integration-doc-files.d.mts +22 -0
- package/foundation/discovery/integration-doc-files.mjs +231 -0
- package/foundation/discovery/integration-doc-files.test.mjs +246 -0
- package/foundation/discovery/module-exports.d.mts +6 -0
- package/foundation/discovery/module-exports.mjs +15 -2
- package/foundation/discovery/package-tsconfig.d.mts +14 -0
- package/foundation/discovery/package-tsconfig.mjs +228 -0
- package/foundation/discovery/package-tsconfig.test.mjs +210 -0
- package/foundation/discovery/project-typescript.d.mts +23 -0
- package/foundation/discovery/project-typescript.mjs +61 -0
- package/foundation/discovery/prop-drift.d.mts +278 -0
- package/foundation/discovery/prop-drift.mjs +2263 -0
- package/foundation/discovery/prop-drift.test.mjs +2219 -0
- package/foundation/discovery/type-match.d.mts +53 -0
- package/foundation/discovery/type-match.mjs +660 -0
- package/foundation/discovery/type-match.test.mjs +169 -0
- package/foundation/discovery/type-text.d.mts +68 -0
- package/foundation/discovery/type-text.mjs +658 -0
- package/foundation/discovery/type-text.test.mjs +196 -0
- package/foundation/discovery/unresolved-references.d.mts +62 -0
- package/foundation/discovery/unresolved-references.mjs +790 -0
- package/foundation/discovery/unresolved-references.test.mjs +567 -0
- package/foundation/doc-compiler/doc-loads.test.mjs +6 -0
- package/foundation/doc-compiler/links.d.mts +9 -5
- package/foundation/doc-compiler/links.mjs +4 -2
- package/foundation/integrations/contribution-inventory.mjs +6 -1
- package/foundation/response/response-types.doc.mjs +7 -2
- package/package.json +9 -9
- package/scripts/postinstall.mjs +3 -3
|
@@ -98,6 +98,72 @@ describe('integrationAddComponent name collisions', () => {
|
|
|
98
98
|
expect(snapshot()).toEqual(before);
|
|
99
99
|
});
|
|
100
100
|
|
|
101
|
+
it('adds a name a family doc lists but the module it imports does not export', async () => {
|
|
102
|
+
fs.writeFileSync(
|
|
103
|
+
path.join(tmpDir, 'package.json'),
|
|
104
|
+
`${JSON.stringify({name: '@acme/widgets', version: '1.0.0', files: ['dist'], exports: {'./tabs': './components/tabs/index.ts'}}, null, 2)}\n`,
|
|
105
|
+
);
|
|
106
|
+
const tabs = path.join(tmpDir, 'components', 'tabs');
|
|
107
|
+
fs.mkdirSync(tabs, {recursive: true});
|
|
108
|
+
fs.writeFileSync(
|
|
109
|
+
path.join(tabs, 'AcmeTabs.doc.mjs'),
|
|
110
|
+
"export default {type: 'component', name: 'AcmeTabs', import: '@acme/widgets/tabs', description: 'x', components: [{name: 'AcmeTabExtra', description: 'x'}]};\n",
|
|
111
|
+
);
|
|
112
|
+
fs.writeFileSync(
|
|
113
|
+
path.join(tabs, 'AcmeTabs.tsx'),
|
|
114
|
+
'export function AcmeTabs() { return null; }\nexport function AcmeTabExtra() { return null; }\n',
|
|
115
|
+
);
|
|
116
|
+
fs.writeFileSync(
|
|
117
|
+
path.join(tabs, 'index.ts'),
|
|
118
|
+
"export {AcmeTabs} from './AcmeTabs';\n",
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
const result = await integrationAdd('component', 'AcmeTabExtra', {
|
|
122
|
+
cwd: tmpDir,
|
|
123
|
+
dryRun: true,
|
|
124
|
+
});
|
|
125
|
+
expect(result.data.files).toContain('components/AcmeTabExtra.doc.mjs');
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it('refuses a member a family exports through built output', async () => {
|
|
129
|
+
fs.writeFileSync(
|
|
130
|
+
path.join(tmpDir, 'package.json'),
|
|
131
|
+
`${JSON.stringify({name: '@acme/widgets', version: '1.0.0', files: ['dist'], exports: {'./tabs': './dist/tabs/index.js'}}, null, 2)}\n`,
|
|
132
|
+
);
|
|
133
|
+
const tabs = path.join(tmpDir, 'components', 'tabs');
|
|
134
|
+
fs.mkdirSync(tabs, {recursive: true});
|
|
135
|
+
fs.writeFileSync(
|
|
136
|
+
path.join(tabs, 'AcmeTabs.doc.mjs'),
|
|
137
|
+
"export default {type: 'component', name: 'AcmeTabs', import: '@acme/widgets/tabs', description: 'x', components: [{name: 'AcmeTab', description: 'x'}]};\n",
|
|
138
|
+
);
|
|
139
|
+
fs.writeFileSync(
|
|
140
|
+
path.join(tabs, 'AcmeTabs.tsx'),
|
|
141
|
+
'export function AcmeTabs() { return null; }\n',
|
|
142
|
+
);
|
|
143
|
+
fs.writeFileSync(
|
|
144
|
+
path.join(tabs, 'AcmeTab.tsx'),
|
|
145
|
+
'export function AcmeTab() { return null; }\n',
|
|
146
|
+
);
|
|
147
|
+
const dist = path.join(tmpDir, 'dist', 'tabs');
|
|
148
|
+
fs.mkdirSync(dist, {recursive: true});
|
|
149
|
+
fs.writeFileSync(
|
|
150
|
+
path.join(dist, 'index.js'),
|
|
151
|
+
"export {AcmeTabs} from './tabs.js';\nexport {AcmeTab} from './tab.js';\n",
|
|
152
|
+
);
|
|
153
|
+
fs.writeFileSync(
|
|
154
|
+
path.join(dist, 'tabs.js'),
|
|
155
|
+
'export function AcmeTabs() { return null; }\n',
|
|
156
|
+
);
|
|
157
|
+
fs.writeFileSync(
|
|
158
|
+
path.join(dist, 'tab.js'),
|
|
159
|
+
'export function AcmeTab() { return null; }\n',
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
await expect(
|
|
163
|
+
integrationAdd('component', 'AcmeTab', {cwd: tmpDir, dryRun: true}),
|
|
164
|
+
).rejects.toThrow('Refusing to add component "AcmeTab"');
|
|
165
|
+
});
|
|
166
|
+
|
|
101
167
|
it('still adds a component whose name is free', async () => {
|
|
102
168
|
writeAuthoredComponent('components/AcmeWidget/AcmeWidget.doc.mjs');
|
|
103
169
|
|
|
@@ -264,9 +264,13 @@ async function addComponent(name, options) {
|
|
|
264
264
|
ERROR_CODES.ERR_FILE_EXISTS,
|
|
265
265
|
);
|
|
266
266
|
}
|
|
267
|
-
//
|
|
268
|
-
//
|
|
269
|
-
|
|
267
|
+
// A second doc under a name discovery already records, by a doc's file name
|
|
268
|
+
// anywhere under the root or by a name a doc documents, would shadow one of
|
|
269
|
+
// the two.
|
|
270
|
+
const existingDoc = findIntegrationComponentDoc(
|
|
271
|
+
{name: owner, components: root, __packageDir: packageDir},
|
|
272
|
+
name,
|
|
273
|
+
);
|
|
270
274
|
if (existingDoc != null) {
|
|
271
275
|
throw new AstryxError(
|
|
272
276
|
`Refusing to add component "${name}": ${projectPath(path.relative(packageDir, existingDoc))} already defines it.`,
|
|
@@ -691,7 +695,7 @@ async function addTemplate(name, options) {
|
|
|
691
695
|
const sourcePath = projectPath(path.relative(packageDir, sourceFile));
|
|
692
696
|
const extensionlessPath = sourcePath.replace(/\.tsx?$/u, '');
|
|
693
697
|
const blockFields = templateType === 'block' ? '\n aspectRatio: 1,' : '';
|
|
694
|
-
const specContents = `/** @type {import('@astryxdesign/cli/authoring').
|
|
698
|
+
const specContents = `/** @type {import('@astryxdesign/cli/authoring').IntegrationTemplateDoc} */\nexport default {\n type: '${templateType}',\n name: '${name}',\n displayName: '${kebabToTitle(name)}',\n description: '${kebabToTitle(name)} template.',${blockFields}\n};\n`;
|
|
695
699
|
const sourceContents = `export default function ${pascalName}() {\n return <div>${kebabToTitle(name)}</div>;\n}\n`;
|
|
696
700
|
|
|
697
701
|
/** @type {import('./add-helpers.mjs').WritePlan[]} */
|
|
@@ -536,7 +536,9 @@ describe('integrationAdd template', () => {
|
|
|
536
536
|
path.join(tmpDir, 'templates/my-widget.doc.mjs'),
|
|
537
537
|
'utf-8',
|
|
538
538
|
);
|
|
539
|
-
expect(spec).toContain(
|
|
539
|
+
expect(spec).toContain(
|
|
540
|
+
"@astryxdesign/cli/authoring').IntegrationTemplateDoc",
|
|
541
|
+
);
|
|
540
542
|
expect(spec).toContain("type: 'page'");
|
|
541
543
|
expect(spec).toContain("name: 'my-widget'");
|
|
542
544
|
|
|
@@ -830,7 +832,7 @@ describe('typed descriptor conformance', () => {
|
|
|
830
832
|
for (const [relativePath, type] of [
|
|
831
833
|
['components/MyWidget.doc.mjs', 'ComponentDoc'],
|
|
832
834
|
['docs/my-guide.doc.mjs', 'ReferenceDoc'],
|
|
833
|
-
['templates/my-page.doc.mjs', '
|
|
835
|
+
['templates/my-page.doc.mjs', 'IntegrationTemplateDoc'],
|
|
834
836
|
['themes/ocean/oceanTheme.doc.mjs', 'ThemeDoc'],
|
|
835
837
|
]) {
|
|
836
838
|
const source = fs.readFileSync(path.join(tmpDir, relativePath), 'utf-8');
|
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* @file Integration authoring diagnostics against the built-in Core catalog.
|
|
5
5
|
*
|
|
6
|
+
* The components check also compares each component doc's props with the
|
|
7
|
+
* component's TypeScript props (foundation/discovery/prop-drift.mjs); those
|
|
8
|
+
* findings are warnings under `propDrift`.
|
|
9
|
+
*
|
|
6
10
|
* Templates may intentionally replace Core identities; undeclared same-id
|
|
7
11
|
* overlaps stay fail-closed and require package selection. The CLI package
|
|
8
12
|
* version gates replacement-specific fields so 0.6.x keeps its released shape.
|
|
@@ -25,6 +29,7 @@ import {
|
|
|
25
29
|
discoverOwnedComponents,
|
|
26
30
|
} from '../../foundation/discovery/component-discovery.mjs';
|
|
27
31
|
import {loadComponentReplacements} from '../component/_adapter.mjs';
|
|
32
|
+
import {integrationPropDrift} from './_adapter.mjs';
|
|
28
33
|
import {
|
|
29
34
|
discoverBuiltinTopics,
|
|
30
35
|
discoverIntegrationDocs,
|
|
@@ -242,6 +247,10 @@ export async function integrationComponentConflicts(pkg, options = {}) {
|
|
|
242
247
|
};
|
|
243
248
|
}
|
|
244
249
|
|
|
250
|
+
// Each documented prop against the component's TypeScript props, read with
|
|
251
|
+
// the project's own compiler; without one the report says it was skipped.
|
|
252
|
+
const propDrift = await integrationPropDrift(resolved.integration, cwd);
|
|
253
|
+
|
|
245
254
|
const coreDir = findCoreDir(cwd);
|
|
246
255
|
if (!coreDir) {
|
|
247
256
|
issues.push({
|
|
@@ -252,7 +261,7 @@ export async function integrationComponentConflicts(pkg, options = {}) {
|
|
|
252
261
|
});
|
|
253
262
|
return {
|
|
254
263
|
type: 'integration.component-conflicts',
|
|
255
|
-
data: {validated, name, version, conflicts: [], issues},
|
|
264
|
+
data: {validated, name, version, conflicts: [], issues, propDrift},
|
|
256
265
|
};
|
|
257
266
|
}
|
|
258
267
|
|
|
@@ -296,7 +305,7 @@ export async function integrationComponentConflicts(pkg, options = {}) {
|
|
|
296
305
|
|
|
297
306
|
return {
|
|
298
307
|
type: 'integration.component-conflicts',
|
|
299
|
-
data: {validated, name, version, conflicts, issues},
|
|
308
|
+
data: {validated, name, version, conflicts, issues, propDrift},
|
|
300
309
|
};
|
|
301
310
|
}
|
|
302
311
|
|
|
@@ -417,6 +417,45 @@ describe('integrationComponentConflicts', () => {
|
|
|
417
417
|
expect(result.data.conflicts).toEqual([]);
|
|
418
418
|
expect(result.data.issues).toEqual([]);
|
|
419
419
|
});
|
|
420
|
+
|
|
421
|
+
it("compares each component doc's props with the component's TypeScript props, as warnings", async () => {
|
|
422
|
+
writeComponentIntegration('AcmeBadge');
|
|
423
|
+
fs.writeFileSync(
|
|
424
|
+
path.join(tmpDir, 'components', 'AcmeBadge.doc.mjs'),
|
|
425
|
+
`export default {type: 'component', name: 'AcmeBadge', displayName: 'AcmeBadge', description: 'Fixture component.', props: [{name: 'label', type: 'string', description: 'Text.', required: true}, {name: 'size', type: "'sm' | 'md'", description: 'Size.'}]};\n`,
|
|
426
|
+
);
|
|
427
|
+
fs.writeFileSync(
|
|
428
|
+
path.join(tmpDir, 'components', 'AcmeBadge.tsx'),
|
|
429
|
+
'export function AcmeBadge(props: {label: string; count?: number}) { return null; }\n',
|
|
430
|
+
);
|
|
431
|
+
|
|
432
|
+
const result = await integrationComponentConflicts(undefined, {
|
|
433
|
+
cwd: tmpDir,
|
|
434
|
+
});
|
|
435
|
+
|
|
436
|
+
expect(result.data.issues).toEqual([]);
|
|
437
|
+
expect(result.data.propDrift).toMatchObject({
|
|
438
|
+
status: 'checked',
|
|
439
|
+
components: 1,
|
|
440
|
+
unchecked: [],
|
|
441
|
+
});
|
|
442
|
+
expect(
|
|
443
|
+
result.data.propDrift?.findings.map(f => [f.prop, f.kind, f.severity]),
|
|
444
|
+
).toEqual([
|
|
445
|
+
['count', 'not_in_doc', 'warning'],
|
|
446
|
+
['size', 'not_in_code', 'warning'],
|
|
447
|
+
]);
|
|
448
|
+
});
|
|
449
|
+
|
|
450
|
+
it('leaves propDrift out when the package has no components root', async () => {
|
|
451
|
+
writeDocIntegration({name: 'acme-setup'});
|
|
452
|
+
|
|
453
|
+
const result = await integrationComponentConflicts(undefined, {
|
|
454
|
+
cwd: tmpDir,
|
|
455
|
+
});
|
|
456
|
+
|
|
457
|
+
expect(result.data).not.toHaveProperty('propDrift');
|
|
458
|
+
});
|
|
420
459
|
});
|
|
421
460
|
|
|
422
461
|
describe('integrationDocConflicts', () => {
|
|
@@ -47,6 +47,14 @@ export type IntegrationTemplateConflictResponse = {
|
|
|
47
47
|
issues: import("../../foundation/integrations/issue").AstryxIntegrationIssue[];
|
|
48
48
|
};
|
|
49
49
|
};
|
|
50
|
+
/**
|
|
51
|
+
* Documented props compared with the component's TypeScript props. Present
|
|
52
|
+
* when the manifest loads and declares a components root. `status: 'skipped'`
|
|
53
|
+
* means nothing was compared (no TypeScript in the project) and `reason` says
|
|
54
|
+
* why. Every finding is a warning.
|
|
55
|
+
*/
|
|
56
|
+
export type PropDriftReport = import("../../foundation/discovery/prop-drift.mjs").PropDriftReport;
|
|
57
|
+
export type PropDriftFinding = import("../../foundation/discovery/prop-drift.mjs").PropDriftFinding;
|
|
50
58
|
export type IntegrationComponentConflictResponse = {
|
|
51
59
|
type: "integration.component-conflicts";
|
|
52
60
|
data: {
|
|
@@ -55,6 +63,7 @@ export type IntegrationComponentConflictResponse = {
|
|
|
55
63
|
version: string | null;
|
|
56
64
|
conflicts: IntegrationComponentConflict[];
|
|
57
65
|
issues: import("../../foundation/integrations/issue").AstryxIntegrationIssue[];
|
|
66
|
+
propDrift?: PropDriftReport;
|
|
58
67
|
};
|
|
59
68
|
};
|
|
60
69
|
export type IntegrationDocConflictResponse = {
|
|
@@ -58,10 +58,23 @@
|
|
|
58
58
|
* @property {{validated: boolean, name: string | null, version: string | null, conflicts: IntegrationTemplateConflict[], issues: import('../../foundation/integrations/issue').AstryxIntegrationIssue[]}} data
|
|
59
59
|
*/
|
|
60
60
|
|
|
61
|
+
/**
|
|
62
|
+
* Documented props compared with the component's TypeScript props. Present
|
|
63
|
+
* when the manifest loads and declares a components root. `status: 'skipped'`
|
|
64
|
+
* means nothing was compared (no TypeScript in the project) and `reason` says
|
|
65
|
+
* why. Every finding is a warning.
|
|
66
|
+
*
|
|
67
|
+
* @typedef {import('../../foundation/discovery/prop-drift.mjs').PropDriftReport} PropDriftReport
|
|
68
|
+
*/
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* @typedef {import('../../foundation/discovery/prop-drift.mjs').PropDriftFinding} PropDriftFinding
|
|
72
|
+
*/
|
|
73
|
+
|
|
61
74
|
/**
|
|
62
75
|
* @typedef {object} IntegrationComponentConflictResponse
|
|
63
76
|
* @property {'integration.component-conflicts'} type
|
|
64
|
-
* @property {{validated: boolean, name: string | null, version: string | null, conflicts: IntegrationComponentConflict[], issues: import('../../foundation/integrations/issue').AstryxIntegrationIssue[]}} data
|
|
77
|
+
* @property {{validated: boolean, name: string | null, version: string | null, conflicts: IntegrationComponentConflict[], issues: import('../../foundation/integrations/issue').AstryxIntegrationIssue[], propDrift?: PropDriftReport}} data
|
|
65
78
|
*/
|
|
66
79
|
|
|
67
80
|
/**
|
|
@@ -0,0 +1,96 @@
|
|
|
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
|
+
* The code a skipped comparison carries under `--strict`: its key in the
|
|
6
|
+
* check's result, in snake case, then `_skipped` (`propDrift` is
|
|
7
|
+
* `prop_drift_skipped`).
|
|
8
|
+
* @param {string} key
|
|
9
|
+
*/
|
|
10
|
+
export function skippedCode(key: string): string;
|
|
11
|
+
/**
|
|
12
|
+
* Whether a value is a report a check carries beside its issues: a
|
|
13
|
+
* comparison with a `status` of `checked` or `skipped` and its `findings`.
|
|
14
|
+
* @param {unknown} value
|
|
15
|
+
* @returns {value is IntegrationCheckReport}
|
|
16
|
+
*/
|
|
17
|
+
export function isCheckReport(value: unknown): value is IntegrationCheckReport;
|
|
18
|
+
/**
|
|
19
|
+
* Every warning in one check's result, and every piece of work it skipped,
|
|
20
|
+
* as issues: what `--strict` reports as errors. The counts come from the
|
|
21
|
+
* same list, so the default run and the strict run read the same data.
|
|
22
|
+
* @param {IntegrationCheckName} check
|
|
23
|
+
* @param {IntegrationCheckResponse} response
|
|
24
|
+
* @param {{noPackage?: boolean}} [context] `noPackage`: validate found no
|
|
25
|
+
* package.json, which only it reports; then no other check names a
|
|
26
|
+
* missing manifest as skipped work
|
|
27
|
+
* @returns {{warnings: Array<Omit<IntegrationCheckFailure, 'check' | 'severity'>>, skipped: Array<Omit<IntegrationCheckFailure, 'check' | 'severity'>>}}
|
|
28
|
+
*/
|
|
29
|
+
export function strictIssues(check: IntegrationCheckName, response: IntegrationCheckResponse, context?: {
|
|
30
|
+
noPackage?: boolean;
|
|
31
|
+
}): {
|
|
32
|
+
warnings: Array<Omit<IntegrationCheckFailure, "check" | "severity">>;
|
|
33
|
+
skipped: Array<Omit<IntegrationCheckFailure, "check" | "severity">>;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Count one check's result the way its own subcommand exits. Errors are what
|
|
37
|
+
* make it exit 1: error-severity issues, and for `docs` error findings.
|
|
38
|
+
* Warnings are warning issues, conflicts and findings, and the findings of
|
|
39
|
+
* any report the check carries. Skipped names work that did not run: no
|
|
40
|
+
* integration manifest, or a report that was skipped.
|
|
41
|
+
* @param {IntegrationCheckResponse} response
|
|
42
|
+
* @param {{noPackage?: boolean}} [context] as {@link strictIssues} takes it
|
|
43
|
+
* @returns {Omit<IntegrationCheckResult, 'check' | 'response'>}
|
|
44
|
+
*/
|
|
45
|
+
export function summarizeCheck(response: IntegrationCheckResponse, context?: {
|
|
46
|
+
noPackage?: boolean;
|
|
47
|
+
}): Omit<IntegrationCheckResult, "check" | "response">;
|
|
48
|
+
/**
|
|
49
|
+
* Run every `doctor integration` check against the integration package in
|
|
50
|
+
* `cwd`, as its own build does, and return the `integration.check` envelope.
|
|
51
|
+
*
|
|
52
|
+
* @param {IntegrationCheckOptions} [options]
|
|
53
|
+
* @returns {Promise<IntegrationCheckCommandResponse>}
|
|
54
|
+
*/
|
|
55
|
+
export function integrationCheck(options?: IntegrationCheckOptions): Promise<IntegrationCheckCommandResponse>;
|
|
56
|
+
/**
|
|
57
|
+
* Count the four checks' results into one summary. Each check's own row
|
|
58
|
+
* counts as its subcommand exits; the totals and `failures` count validate's
|
|
59
|
+
* issues once, though the other checks repeat them, and every other finding
|
|
60
|
+
* on its own, so two findings with one message stay two.
|
|
61
|
+
* @param {IntegrationCheckResponse[]} responses validate first
|
|
62
|
+
* @param {boolean} strict
|
|
63
|
+
*/
|
|
64
|
+
export function combineChecks(responses: IntegrationCheckResponse[], strict: boolean): {
|
|
65
|
+
checks: import("../integration-check.type.mjs").IntegrationCheckResult[];
|
|
66
|
+
errors: number;
|
|
67
|
+
warnings: number;
|
|
68
|
+
skipped: string[];
|
|
69
|
+
unchecked: number;
|
|
70
|
+
failures: import("../integration-check.type.mjs").IntegrationCheckFailure[];
|
|
71
|
+
failed: boolean;
|
|
72
|
+
};
|
|
73
|
+
/** @typedef {import('../integration-check.type.mjs').IntegrationCheckName} IntegrationCheckName */
|
|
74
|
+
/** @typedef {import('../integration-check.type.mjs').IntegrationCheckReport} IntegrationCheckReport */
|
|
75
|
+
/** @typedef {import('../integration-check.type.mjs').IntegrationCheckResponse} IntegrationCheckResponse */
|
|
76
|
+
/** @typedef {import('../integration-check.type.mjs').IntegrationCheckResult} IntegrationCheckResult */
|
|
77
|
+
/** @typedef {import('../integration-check.type.mjs').IntegrationCheckOptions} IntegrationCheckOptions */
|
|
78
|
+
/** @typedef {import('../integration-check.type.mjs').IntegrationCheckCommandResponse} IntegrationCheckCommandResponse */
|
|
79
|
+
/** @typedef {import('../integration-check.type.mjs').IntegrationCheckFailure} IntegrationCheckFailure */
|
|
80
|
+
/** The checks `integration check` runs, in the order it runs them. */
|
|
81
|
+
export const INTEGRATION_CHECKS: readonly ["validate", "components", "templates", "docs"];
|
|
82
|
+
/** The skipped-work line for a package with no integration manifest. */
|
|
83
|
+
export const NO_MANIFEST_SKIP: "No astryx.integration.* found next to package.json, so nothing was checked.";
|
|
84
|
+
export namespace CONFLICT_CODES {
|
|
85
|
+
let components: "component_name_conflict";
|
|
86
|
+
let templates: "template_id_conflict";
|
|
87
|
+
}
|
|
88
|
+
/** The code a check with no integration manifest carries under `--strict`. */
|
|
89
|
+
export const NO_MANIFEST_CODE: "missing_manifest";
|
|
90
|
+
export type IntegrationCheckName = import("../integration-check.type.mjs").IntegrationCheckName;
|
|
91
|
+
export type IntegrationCheckReport = import("../integration-check.type.mjs").IntegrationCheckReport;
|
|
92
|
+
export type IntegrationCheckResponse = import("../integration-check.type.mjs").IntegrationCheckResponse;
|
|
93
|
+
export type IntegrationCheckResult = import("../integration-check.type.mjs").IntegrationCheckResult;
|
|
94
|
+
export type IntegrationCheckOptions = import("../integration-check.type.mjs").IntegrationCheckOptions;
|
|
95
|
+
export type IntegrationCheckCommandResponse = import("../integration-check.type.mjs").IntegrationCheckCommandResponse;
|
|
96
|
+
export type IntegrationCheckFailure = import("../integration-check.type.mjs").IntegrationCheckFailure;
|