@astryxdesign/cli 0.6.3-canary.db4e378 → 0.6.3-canary.db7b338
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 +22 -1
- package/api/blog/blog.doc.mjs +1 -0
- package/api/build/build.doc.mjs +1 -0
- package/api/component/component.doc.mjs +1 -0
- package/api/discover/discover.doc.mjs +1 -0
- package/api/docs/_adapter.d.mts +3 -8
- package/api/docs/_adapter.mjs +13 -105
- package/api/docs/detail/section/section.mjs +9 -15
- package/api/docs/detail/section/section.test.mjs +15 -6
- package/api/docs/docs.doc.mjs +1 -0
- package/api/docs/list/list.mjs +3 -7
- package/api/doctor/doctor.d.mts +25 -3
- package/api/doctor/doctor.doc.mjs +1 -0
- package/api/doctor/doctor.mjs +186 -14
- package/api/doctor/doctor.test.mjs +332 -7
- package/api/gap-report/gap-report.doc.mjs +1 -0
- package/api/hook/_adapter.mjs +19 -5
- package/api/hook/hook.doc.mjs +1 -0
- package/api/hook/list/list.d.mts +1 -1
- package/api/hook/list/list.mjs +69 -17
- package/api/init/init.doc.mjs +1 -0
- package/api/integration/add-contribution.mjs +7 -7
- package/api/integration/add-contribution.test.mjs +37 -3
- package/api/integration/add-theme.mjs +34 -64
- package/api/integration/add-theme.test.mjs +105 -21
- package/api/integration/authoring-checks.test.mjs +8 -4
- package/api/integration/integration-block-exports.test.mjs +10 -6
- package/api/integration/integrationAdd.doc.mjs +1 -0
- package/api/integration/integrationAddAgentDoc.doc.mjs +1 -0
- package/api/integration/integrationAddCodemod.doc.mjs +1 -0
- package/api/integration/integrationAddComponent.doc.mjs +1 -0
- package/api/integration/integrationAddDoc.doc.mjs +1 -0
- package/api/integration/integrationAddTemplate.doc.mjs +1 -0
- package/api/integration/integrationAddTheme.doc.mjs +6 -5
- package/api/integration/integrationComponentConflicts.doc.mjs +1 -0
- package/api/integration/integrationDocConflicts.doc.mjs +1 -0
- package/api/integration/integrationPackCheck.doc.mjs +1 -0
- package/api/integration/integrationTemplateConflicts.doc.mjs +1 -0
- package/api/integration/pack-check.test.mjs +17 -47
- package/api/integration/summarizeIssues.doc.mjs +1 -0
- package/api/integration/validate-integration-fixes.test.mjs +1389 -0
- package/api/integration/validate-integration.mjs +50 -102
- package/api/integration/validate-integration.test.mjs +85 -23
- package/api/integration/validate-unread-theme-folders.test.mjs +110 -0
- package/api/integration/validateIntegration.doc.mjs +1 -0
- package/api/json/assertResponse.doc.mjs +1 -0
- package/api/json/isError.doc.mjs +1 -0
- package/api/json/parseResponse.doc.mjs +1 -0
- package/api/layout/layoutCheck.doc.mjs +1 -0
- package/api/layout/layoutExpand.doc.mjs +1 -0
- package/api/layout/layoutGrammar.doc.mjs +1 -0
- package/api/search/search.doc.mjs +1 -0
- package/api/search/search.mjs +16 -6
- package/api/swizzle/swizzle.doc.mjs +1 -0
- package/api/template/template-suffix.test.mjs +41 -21
- package/api/template/template.doc.mjs +1 -0
- package/api/theme/_adapter.d.mts +2 -3
- package/api/theme/_adapter.mjs +4 -5
- package/api/theme/add/add.binary.test.mjs +10 -17
- package/api/theme/add/add.test.mjs +14 -1
- package/api/theme/generateTonalPalette.doc.mjs +1 -0
- package/api/theme/integration-themes.test.mjs +39 -28
- package/api/theme/list/list.test.mjs +19 -20
- package/api/theme/listThemes.doc.mjs +6 -5
- package/api/theme/themeAdd.doc.mjs +4 -3
- package/api/theme/themeBuild.doc.mjs +1 -0
- package/api/theme/themeList.doc.mjs +6 -3
- package/api/theme/themeListAvailable.doc.mjs +5 -3
- package/api/theme/themePaletteGenerate.doc.mjs +1 -0
- package/api/theme/themeTargets.doc.mjs +1 -0
- package/api/theme/themeTemplate.doc.mjs +1 -0
- package/api/upgrade/_adapter.d.mts +32 -5
- package/api/upgrade/_adapter.mjs +97 -69
- package/api/upgrade/provider-agreement.test.mjs +152 -0
- package/api/upgrade/run/run.mjs +356 -59
- package/api/upgrade/upgrade.doc.mjs +6 -1
- package/api/upgrade/upgrade.type.d.mts +34 -0
- package/api/upgrade/upgrade.type.mjs +15 -0
- package/assets/codemods/__tests__/runner.test.mjs +330 -8
- package/assets/codemods/integration-discovery.mjs +8 -2
- package/assets/codemods/integration-discovery.test.mjs +15 -0
- package/assets/codemods/integration-runner.mjs +56 -4
- package/assets/codemods/integration-runner.protection.test.mjs +153 -0
- package/assets/codemods/run-codemod.mjs +177 -34
- package/assets/codemods/runner.mjs +350 -102
- package/assets/codemods/transforms/next/__tests__/migrate-native-picker-to-presentation.test.mjs +63 -0
- package/assets/codemods/transforms/next/__tests__/migrate-theme-catalog-to-descriptors.test.mjs +220 -0
- package/assets/codemods/transforms/next/index.mjs +19 -1
- package/assets/codemods/transforms/next/migrate-native-picker-to-presentation.mjs +148 -0
- package/assets/codemods/transforms/next/migrate-theme-catalog-to-descriptors.mjs +141 -0
- package/assets/docs/cli-integrations.doc.mjs +30 -30
- package/assets/docs/cli.doc.mjs +15 -0
- package/assets/docs/theme.doc.mjs +1 -1
- package/assets/templates/blocks/components/DateInput/DateInputDateRange.tsx +1 -1
- package/assets/templates/blocks/components/Item/ItemDocumentTabs.doc.mjs +14 -0
- package/assets/templates/blocks/components/Item/ItemDocumentTabs.tsx +100 -0
- package/assets/templates/blocks/components/TimeInput/TimeInputConstrained.tsx +1 -0
- package/assets/templates/themes/butter/butterTheme.doc.mjs +11 -0
- package/assets/templates/themes/chocolate/chocolateTheme.doc.mjs +11 -0
- package/assets/templates/themes/gothic/gothicTheme.doc.mjs +11 -0
- package/assets/templates/themes/matcha/matchaTheme.doc.mjs +11 -0
- package/assets/templates/themes/neutral/neutralTheme.doc.mjs +11 -0
- package/assets/templates/themes/stone/stoneTheme.doc.mjs +11 -0
- package/assets/templates/themes/y2k/y2kTheme.doc.mjs +11 -0
- package/authoring/codemod/codemod.doc.mjs +1 -1
- package/authoring/codemod/type.ts +12 -0
- package/authoring/config/config.doc.mjs +1 -1
- package/authoring/debug/debug.doc.d.mts +11 -0
- package/authoring/debug/debug.doc.mjs +182 -0
- package/authoring/doctypes/_schema.d.mts +71 -141
- package/authoring/doctypes/_schema.mjs +29 -2
- package/authoring/doctypes/base/graph-fields.doc.mjs +1 -1
- package/authoring/doctypes/command/command.doc.mjs +1 -1
- package/authoring/doctypes/command/type.ts +1 -1
- package/authoring/doctypes/component/type.ts +2 -2
- package/authoring/doctypes/doctypes-new.test.mjs +48 -6
- package/authoring/doctypes/enum/enum.doc.mjs +1 -1
- package/authoring/doctypes/enum/type.ts +1 -1
- package/authoring/doctypes/function/function.doc.mjs +1 -1
- package/authoring/doctypes/function/type.ts +1 -1
- package/authoring/doctypes/hook/type.ts +2 -2
- package/authoring/doctypes/load-contract.test.mjs +3 -2
- package/authoring/doctypes/namespace/namespace.doc.mjs +2 -2
- package/authoring/doctypes/namespace/parse.test.mjs +23 -25
- package/authoring/doctypes/namespace/type.ts +5 -2
- package/authoring/doctypes/parse.d.mts +4 -2
- package/authoring/doctypes/parse.mjs +10 -5
- package/authoring/doctypes/reference/reference.doc.mjs +6 -4
- package/authoring/doctypes/reference/type.ts +9 -10
- package/authoring/doctypes/schema/schema.doc.mjs +1 -1
- package/authoring/doctypes/schema/type.ts +1 -2
- package/authoring/doctypes/template/template.doc.mjs +3 -3
- package/authoring/doctypes/theme/parse.d.mts +35 -0
- package/authoring/doctypes/theme/parse.mjs +76 -0
- package/authoring/doctypes/theme/theme.doc.d.mts +9 -0
- package/authoring/doctypes/theme/theme.doc.mjs +79 -0
- package/authoring/doctypes/theme/type.ts +42 -0
- package/authoring/doctypes/types.ts +2 -1
- package/authoring/gap-report/gap-report.doc.d.mts +12 -0
- package/authoring/gap-report/gap-report.doc.mjs +183 -0
- package/authoring/index.d.mts +1 -0
- package/authoring/index.d.ts +7 -4
- package/authoring/index.mjs +2 -1
- package/authoring/integration/integration.doc.mjs +2 -2
- package/authoring/integration/type.ts +3 -9
- package/clients/cli/__tests__/cliManifest.test.ts +27 -29
- package/clients/cli/commands/blog.doc.mjs +1 -1
- package/clients/cli/commands/build-theme.adaptations.test.mjs +100 -1
- package/clients/cli/commands/build-theme.mjs +10 -44
- package/clients/cli/commands/build.doc.mjs +1 -1
- package/clients/cli/commands/component.doc.mjs +1 -1
- package/clients/cli/commands/discover.doc.mjs +1 -1
- package/clients/cli/commands/docs.doc.mjs +1 -1
- package/clients/cli/commands/docs.mjs +15 -58
- package/clients/cli/commands/docs.test.mjs +11 -14
- package/clients/cli/commands/doctor-integration-components.doc.mjs +1 -1
- package/clients/cli/commands/doctor-integration-docs.doc.mjs +1 -1
- package/clients/cli/commands/doctor-integration-templates.doc.mjs +1 -1
- package/clients/cli/commands/doctor-integration-validate.doc.mjs +1 -1
- package/clients/cli/commands/doctor-integration.doc.mjs +1 -1
- package/clients/cli/commands/doctor-integration.test.mjs +15 -7
- package/clients/cli/commands/doctor.doc.mjs +1 -1
- package/clients/cli/commands/gap-report.doc.mjs +1 -1
- package/clients/cli/commands/hook.doc.mjs +1 -1
- package/clients/cli/commands/init.doc.mjs +1 -1
- package/clients/cli/commands/integration-add.controls.test.mjs +1 -1
- package/clients/cli/commands/integration-add.doc.mjs +1 -1
- package/clients/cli/commands/integration-pack.doc.mjs +1 -1
- package/clients/cli/commands/integration-real-world.test.mjs +3 -9
- package/clients/cli/commands/integration.doc.mjs +1 -1
- package/clients/cli/commands/layout-check.doc.mjs +1 -1
- package/clients/cli/commands/layout-expand.doc.mjs +1 -1
- package/clients/cli/commands/layout-grammar.doc.mjs +1 -1
- package/clients/cli/commands/layout.doc.mjs +1 -1
- package/clients/cli/commands/manifest.doc.mjs +1 -1
- package/clients/cli/commands/search.doc.mjs +1 -1
- 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 +718 -0
- package/clients/cli/commands/theme-add.doc.mjs +2 -2
- package/clients/cli/commands/theme-build.doc.mjs +1 -1
- package/clients/cli/commands/theme-list.doc.mjs +2 -2
- package/clients/cli/commands/theme-palette-generate.doc.mjs +3 -3
- package/clients/cli/commands/theme-palette.doc.mjs +1 -1
- package/clients/cli/commands/theme-targets.behavior.test.mjs +4 -3
- package/clients/cli/commands/theme-targets.doc.mjs +1 -1
- package/clients/cli/commands/theme-template.doc.mjs +1 -1
- package/clients/cli/commands/theme.doc.mjs +1 -1
- package/clients/cli/commands/upgrade.doc.mjs +3 -2
- package/clients/cli/commands/upgrade.file-protection.test.mjs +228 -0
- package/clients/cli/commands/upgrade.mjs +29 -7
- package/clients/cli/formatters/index.mjs +2 -0
- package/clients/cli/formatters/index.test.mjs +6 -0
- package/clients/cli/lib/hook-format.mjs +14 -5
- package/foundation/config/project-themes.test.mjs +11 -19
- package/foundation/config/project.d.mts +8 -0
- package/foundation/config/project.mjs +50 -21
- package/foundation/config/project.test.mjs +3 -16
- package/foundation/discovery/authoring-self-docs.d.mts +6 -0
- package/foundation/discovery/authoring-self-docs.mjs +17 -7
- package/foundation/discovery/authoring-self-docs.test.mjs +3 -2
- package/foundation/discovery/authoring-surface.d.mts +74 -0
- package/foundation/discovery/authoring-surface.mjs +525 -0
- package/foundation/discovery/authoring-surface.test.mjs +392 -0
- package/foundation/discovery/cli-self-docs.d.mts +113 -0
- package/foundation/discovery/cli-self-docs.mjs +514 -0
- package/foundation/discovery/cli-self-docs.test.mjs +437 -0
- package/foundation/discovery/component-loader.d.mts +35 -38
- package/foundation/discovery/component-loader.mjs +53 -222
- package/foundation/discovery/docs-discovery.d.mts +3 -2
- package/foundation/discovery/docs-discovery.mjs +14 -17
- package/foundation/discovery/docs-discovery.test.mjs +15 -15
- package/foundation/discovery/docs-section-key.d.mts +19 -8
- package/foundation/discovery/docs-section-key.mjs +119 -32
- package/foundation/discovery/docs-section-key.test.mjs +41 -19
- package/foundation/discovery/template-adapter.d.mts +7 -0
- package/foundation/discovery/template-adapter.mjs +27 -40
- package/foundation/discovery/template-adapter.test.mjs +15 -0
- package/foundation/discovery/theme-discovery.d.mts +67 -7
- package/foundation/discovery/theme-discovery.mjs +916 -186
- package/foundation/discovery/theme-discovery.test.mjs +613 -219
- package/foundation/doc-compiler/bundle.d.mts +47 -0
- package/foundation/doc-compiler/bundle.mjs +218 -0
- package/foundation/doc-compiler/bundle.test.mjs +255 -0
- package/foundation/doc-compiler/compile.d.mts +200 -0
- package/foundation/doc-compiler/compile.mjs +259 -9
- package/foundation/doc-compiler/diagnostics.d.mts +126 -0
- package/foundation/doc-compiler/diagnostics.mjs +277 -0
- package/foundation/doc-compiler/doc-compiler.test.mjs +28 -1
- package/foundation/doc-compiler/doc-loads.test.mjs +1642 -0
- package/foundation/doc-compiler/import.d.mts +24 -0
- package/foundation/doc-compiler/import.mjs +59 -0
- package/foundation/doc-compiler/inputs.d.mts +102 -0
- package/foundation/doc-compiler/inputs.mjs +286 -0
- package/foundation/doc-compiler/inputs.test.mjs +299 -0
- package/foundation/doc-compiler/ir.d.mts +13 -0
- package/foundation/doc-compiler/ir.mjs +189 -12
- package/foundation/doc-compiler/lower-doc.test.mjs +492 -0
- package/foundation/doc-compiler/overlays.d.mts +37 -0
- package/foundation/doc-compiler/overlays.mjs +206 -0
- package/foundation/doc-compiler/parse-readable.d.mts +9 -0
- package/foundation/doc-compiler/parse-readable.mjs +29 -0
- package/foundation/doc-compiler/read.d.mts +126 -0
- package/foundation/doc-compiler/read.mjs +320 -0
- package/foundation/doc-compiler/read.test.mjs +313 -0
- package/foundation/doc-compiler/source.d.mts +33 -0
- package/foundation/doc-compiler/source.mjs +128 -0
- package/foundation/fs/file-protection.d.mts +33 -0
- package/foundation/fs/file-protection.mjs +825 -0
- package/foundation/fs/file-protection.test.mjs +250 -0
- package/foundation/integrations/autolink.d.mts +58 -1
- package/foundation/integrations/autolink.mjs +143 -57
- package/foundation/integrations/contribution-fixes.d.mts +145 -0
- package/foundation/integrations/contribution-fixes.mjs +1284 -0
- package/foundation/integrations/contribution-inventory.d.mts +1 -1
- package/foundation/integrations/contribution-inventory.mjs +17 -20
- package/foundation/integrations/contribution-inventory.test.mjs +67 -27
- package/foundation/integrations/integrations.d.mts +3 -0
- package/foundation/integrations/integrations.mjs +11 -97
- package/foundation/integrations/provider-ledger.test.mjs +275 -0
- package/foundation/integrations/provider-resolution.d.mts +152 -0
- package/foundation/integrations/provider-resolution.mjs +576 -0
- package/foundation/integrations/provider-resolution.test.mjs +369 -0
- package/foundation/integrations/theme-descriptor.d.mts +8 -0
- package/foundation/integrations/theme-descriptor.mjs +44 -0
- package/foundation/integrations/validate-contributions.mjs +104 -10
- package/foundation/response/error-codes.d.mts +3 -1
- package/foundation/response/error-codes.d.ts +2 -0
- package/foundation/response/error-codes.doc.mjs +12 -2
- package/foundation/response/error-codes.mjs +7 -1
- package/foundation/response/error-codes.test.mjs +55 -11
- package/foundation/response/response-types.doc.mjs +1 -1
- package/foundation/response/response.doc.mjs +1 -1
- package/foundation/text/string-utils.mjs +22 -10
- package/package.json +10 -9
- package/assets/templates/themes/manifest.json +0 -95
package/api/doctor/doctor.mjs
CHANGED
|
@@ -34,8 +34,8 @@ import {
|
|
|
34
34
|
docsIndexBytes,
|
|
35
35
|
oversizedDocSections,
|
|
36
36
|
} from '../../foundation/discovery/docs-output-budget.mjs';
|
|
37
|
-
import {compileTopic, overlayLanguages} from '../docs/_adapter.mjs';
|
|
38
|
-
import {detailView} from '../../foundation/doc-compiler/lenses.mjs';
|
|
37
|
+
import {compileTopic, lowerTopic, overlayLanguages} from '../docs/_adapter.mjs';
|
|
38
|
+
import {detailView, indexView} from '../../foundation/doc-compiler/lenses.mjs';
|
|
39
39
|
import {semverCompare, isValidSemver, satisfiesRange} from '../../foundation/env/semver.mjs';
|
|
40
40
|
|
|
41
41
|
/**
|
|
@@ -721,38 +721,144 @@ function joinProblems(problems) {
|
|
|
721
721
|
: `${problems.length} problems: ${problems.join('; ')}`;
|
|
722
722
|
}
|
|
723
723
|
|
|
724
|
+
/** How the self-doc audit's problems are fixed. */
|
|
725
|
+
const AUTHORING_DOCS_FIX =
|
|
726
|
+
'List every authoring self-doc in AUTHORING_SELF_DOCS, fix the one that fails to load, and split a section that is too large.';
|
|
727
|
+
|
|
728
|
+
/** How the public-surface audit's problems are fixed. */
|
|
729
|
+
const AUTHORING_SURFACE_FIX =
|
|
730
|
+
'Put a self-doc beside each module whose types @astryxdesign/cli/authoring exports and list it in AUTHORING_SELF_DOCS; export what each listed self-doc documents, or remove that self-doc.';
|
|
731
|
+
|
|
732
|
+
/** Types one problem names before it counts the rest. */
|
|
733
|
+
const NAMED_TYPES = 40;
|
|
734
|
+
|
|
735
|
+
/**
|
|
736
|
+
* @param {string[]} names
|
|
737
|
+
* @returns {string}
|
|
738
|
+
*/
|
|
739
|
+
function nameTypes(names) {
|
|
740
|
+
return names.length <= NAMED_TYPES
|
|
741
|
+
? names.join(', ')
|
|
742
|
+
: `${names.slice(0, NAMED_TYPES).join(', ')} and ${names.length - NAMED_TYPES} more`;
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
/**
|
|
746
|
+
* The section keys `astryx docs authoring --index` lists, read the way that
|
|
747
|
+
* command reads them.
|
|
748
|
+
* @returns {Promise<{keys: Set<string>} | {keys: null, error: string}>}
|
|
749
|
+
*/
|
|
750
|
+
async function authoringTopicKeys() {
|
|
751
|
+
try {
|
|
752
|
+
const catalog = DocsCatalog.fromBuiltins();
|
|
753
|
+
const entry = catalog.resolve('authoring');
|
|
754
|
+
if (!entry) return {keys: null, error: 'it is not a built-in topic'};
|
|
755
|
+
const index = indexView(await lowerTopic(catalog, entry));
|
|
756
|
+
return {keys: new Set(index.sections.map(section => section.id))};
|
|
757
|
+
} catch (err) {
|
|
758
|
+
return {
|
|
759
|
+
keys: null,
|
|
760
|
+
error: err instanceof Error ? err.message : String(err),
|
|
761
|
+
};
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
/**
|
|
766
|
+
* @param {Awaited<ReturnType<typeof import('../../foundation/discovery/authoring-surface.mjs').auditAuthoringSurface>>} surface
|
|
767
|
+
* @returns {string[]}
|
|
768
|
+
*/
|
|
769
|
+
function surfaceProblems(surface) {
|
|
770
|
+
/** @type {string[]} */
|
|
771
|
+
const problems = [];
|
|
772
|
+
if (surface.types === 0 && surface.untraced.length === 0) {
|
|
773
|
+
problems.push(
|
|
774
|
+
'@astryxdesign/cli/authoring exports no types, so nothing was compared with `astryx docs authoring`',
|
|
775
|
+
);
|
|
776
|
+
}
|
|
777
|
+
for (const {module, names, reason, source, key} of surface.unreadable) {
|
|
778
|
+
const why =
|
|
779
|
+
reason === 'no-self-doc'
|
|
780
|
+
? `no self-doc sits beside ${module}`
|
|
781
|
+
: reason === 'unregistered'
|
|
782
|
+
? `${source} is not listed in AUTHORING_SELF_DOCS`
|
|
783
|
+
: reason === 'failed'
|
|
784
|
+
? `${source} does not load`
|
|
785
|
+
: `${source} renders section "${key}", which the topic's index does not list`;
|
|
786
|
+
problems.push(
|
|
787
|
+
`${nameTypes(names)} from ${module} ${names.length === 1 ? 'has' : 'have'} no doc in \`astryx docs authoring\`: ${why}`,
|
|
788
|
+
);
|
|
789
|
+
}
|
|
790
|
+
for (const {name, reason} of surface.untraced) {
|
|
791
|
+
problems.push(
|
|
792
|
+
`${name} cannot be traced to the module that declares it: ${reason}`,
|
|
793
|
+
);
|
|
794
|
+
}
|
|
795
|
+
for (const {source, subject} of surface.unmatched) {
|
|
796
|
+
problems.push(
|
|
797
|
+
subject
|
|
798
|
+
? `${source} documents ${subject}, which @astryxdesign/cli/authoring does not export`
|
|
799
|
+
: `${source} documents no type @astryxdesign/cli/authoring exports`,
|
|
800
|
+
);
|
|
801
|
+
}
|
|
802
|
+
return problems;
|
|
803
|
+
}
|
|
804
|
+
|
|
724
805
|
/**
|
|
725
806
|
* Every authoring self-doc is reachable from `astryx docs authoring`, loads,
|
|
726
|
-
* and fits in one read
|
|
727
|
-
*
|
|
807
|
+
* and fits in one read, and every type `@astryxdesign/cli/authoring` exports
|
|
808
|
+
* has its doc there: the self-doc beside the module that declares it. The
|
|
809
|
+
* audits are imported here, inside the try, so a malformed self-doc is
|
|
810
|
+
* reported rather than taking Doctor down.
|
|
728
811
|
* @param {DoctorContext} [_ctx]
|
|
812
|
+
* @param {{root?: string, sources?: string[], topicKeys?: Set<string> | null}} [options]
|
|
813
|
+
* Another authoring tree, list, or topic index to audit (for tests).
|
|
729
814
|
* @returns {Promise<DoctorCheck>}
|
|
730
815
|
*/
|
|
731
|
-
export async function checkAuthoringDocs(_ctx) {
|
|
816
|
+
export async function checkAuthoringDocs(_ctx, options = {}) {
|
|
732
817
|
const id = 'authoring-docs';
|
|
733
818
|
const label = 'Authoring docs';
|
|
734
819
|
try {
|
|
735
|
-
const {auditAuthoringSelfDocs} =
|
|
736
|
-
'../../foundation/discovery/authoring-self-docs.mjs'
|
|
737
|
-
|
|
738
|
-
|
|
820
|
+
const {auditAuthoringSelfDocs} =
|
|
821
|
+
await import('../../foundation/discovery/authoring-self-docs.mjs');
|
|
822
|
+
const {auditAuthoringSurface} =
|
|
823
|
+
await import('../../foundation/discovery/authoring-surface.mjs');
|
|
824
|
+
const {root, sources} = options;
|
|
825
|
+
const audit = await auditAuthoringSelfDocs({root, sources});
|
|
739
826
|
const problems = [
|
|
740
827
|
...audit.unreachable.map(
|
|
741
828
|
source => `${source} is not in \`astryx docs authoring\``,
|
|
742
829
|
),
|
|
743
|
-
...audit.failed.map(
|
|
830
|
+
...audit.failed.map(
|
|
831
|
+
({source, error}) => `${source} failed to load: ${error}`,
|
|
832
|
+
),
|
|
744
833
|
...audit.oversized.map(
|
|
745
834
|
({key, bytes}) =>
|
|
746
835
|
`authoring section "${key}" is ${kilobytes(bytes)}, over the ${kilobytes(DOC_OUTPUT_BUDGET_BYTES)} one read may return`,
|
|
747
836
|
),
|
|
748
837
|
];
|
|
749
|
-
|
|
838
|
+
const topic =
|
|
839
|
+
options.topicKeys === undefined
|
|
840
|
+
? await authoringTopicKeys()
|
|
841
|
+
: {keys: options.topicKeys};
|
|
842
|
+
const surface = [
|
|
843
|
+
...('error' in topic
|
|
844
|
+
? [`\`astryx docs authoring\` could not be read: ${topic.error}`]
|
|
845
|
+
: []),
|
|
846
|
+
...surfaceProblems(
|
|
847
|
+
await auditAuthoringSurface({root, sources, topicKeys: topic.keys}),
|
|
848
|
+
),
|
|
849
|
+
];
|
|
850
|
+
if (problems.length + surface.length > 0) {
|
|
750
851
|
return {
|
|
751
852
|
id,
|
|
752
853
|
label,
|
|
753
854
|
status: 'fail',
|
|
754
|
-
message: joinProblems(problems),
|
|
755
|
-
fix:
|
|
855
|
+
message: joinProblems([...problems, ...surface]),
|
|
856
|
+
fix: [
|
|
857
|
+
problems.length > 0 ? AUTHORING_DOCS_FIX : null,
|
|
858
|
+
surface.length > 0 ? AUTHORING_SURFACE_FIX : null,
|
|
859
|
+
]
|
|
860
|
+
.filter(Boolean)
|
|
861
|
+
.join(' '),
|
|
756
862
|
};
|
|
757
863
|
}
|
|
758
864
|
return {
|
|
@@ -772,6 +878,71 @@ export async function checkAuthoringDocs(_ctx) {
|
|
|
772
878
|
}
|
|
773
879
|
}
|
|
774
880
|
|
|
881
|
+
/** How the CLI-docs audit's problems are fixed. */
|
|
882
|
+
const CLI_DOCS_FIX =
|
|
883
|
+
"Set `namespace` on each CLI doc to the one that reads it: cli/commands for a command, cli/api for an API function or the output schema, error codes, and response types, and authoring for a file an author writes (and list it in AUTHORING_SELF_DOCS).";
|
|
884
|
+
|
|
885
|
+
/**
|
|
886
|
+
* Every command, API function, schema, and enum doc the CLI ships declares a
|
|
887
|
+
* namespace, and the topic that namespace names reads it: `astryx docs cli`
|
|
888
|
+
* for `cli/commands` and `cli/api`, `astryx docs authoring` for `authoring`.
|
|
889
|
+
* @param {DoctorContext | Partial<DoctorContext>} _ctx
|
|
890
|
+
* @param {{root?: string, sources?: string[], authoringSources?: string[]}} [options]
|
|
891
|
+
* test seams: the CLI root, the docs to audit, and the authoring topic's list
|
|
892
|
+
* @returns {Promise<DoctorCheck>}
|
|
893
|
+
*/
|
|
894
|
+
export async function checkCliDocs(_ctx, options = {}) {
|
|
895
|
+
const id = 'cli-docs';
|
|
896
|
+
const label = 'CLI docs';
|
|
897
|
+
try {
|
|
898
|
+
const {auditCliSelfDocs} =
|
|
899
|
+
await import('../../foundation/discovery/cli-self-docs.mjs');
|
|
900
|
+
const audit = await auditCliSelfDocs(options);
|
|
901
|
+
const problems = [
|
|
902
|
+
...audit.missing.map(
|
|
903
|
+
source =>
|
|
904
|
+
`${source} has no namespace, so no \`astryx docs\` topic reads it`,
|
|
905
|
+
),
|
|
906
|
+
...audit.unknown.map(
|
|
907
|
+
({source, namespace}) =>
|
|
908
|
+
`${source} has namespace "${namespace}", which no \`astryx docs\` topic reads`,
|
|
909
|
+
),
|
|
910
|
+
...audit.misfiled.map(({message}) => message),
|
|
911
|
+
...audit.failed.map(
|
|
912
|
+
({source, error}) => `${source} failed to load: ${error}`,
|
|
913
|
+
),
|
|
914
|
+
...audit.keyProblems.map(problem => `\`astryx docs cli\`: ${problem}`),
|
|
915
|
+
...audit.oversized.map(
|
|
916
|
+
({key, bytes}) =>
|
|
917
|
+
`cli section "${key}" is ${kilobytes(bytes)}, over the ${kilobytes(DOC_OUTPUT_BUDGET_BYTES)} one read may return`,
|
|
918
|
+
),
|
|
919
|
+
];
|
|
920
|
+
if (problems.length > 0) {
|
|
921
|
+
return {
|
|
922
|
+
id,
|
|
923
|
+
label,
|
|
924
|
+
status: 'fail',
|
|
925
|
+
message: joinProblems(problems),
|
|
926
|
+
fix: CLI_DOCS_FIX,
|
|
927
|
+
};
|
|
928
|
+
}
|
|
929
|
+
return {
|
|
930
|
+
id,
|
|
931
|
+
label,
|
|
932
|
+
status: 'pass',
|
|
933
|
+
message: `All ${audit.docs} CLI docs are readable: ${audit.sections} in \`astryx docs cli\` and ${audit.authoring} in \`astryx docs authoring\`.`,
|
|
934
|
+
};
|
|
935
|
+
} catch (err) {
|
|
936
|
+
return {
|
|
937
|
+
id,
|
|
938
|
+
label,
|
|
939
|
+
status: 'fail',
|
|
940
|
+
message: `The CLI docs could not be audited: ${err instanceof Error ? err.message : String(err)}`,
|
|
941
|
+
fix: 'Reinstall @astryxdesign/cli.',
|
|
942
|
+
};
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
|
|
775
946
|
/**
|
|
776
947
|
* Every topic reads progressively, in every language it ships: it loads, its
|
|
777
948
|
* section index and each of its sections fit in one read, and no contributed
|
|
@@ -823,7 +994,7 @@ export async function checkDocsProgressiveDisclosure(ctx) {
|
|
|
823
994
|
return {
|
|
824
995
|
id,
|
|
825
996
|
label,
|
|
826
|
-
status: '
|
|
997
|
+
status: 'warn',
|
|
827
998
|
message: joinProblems(problems),
|
|
828
999
|
fix: 'Fix the doc each problem names; split a section that is too large into smaller ones, each with its own key.',
|
|
829
1000
|
};
|
|
@@ -929,6 +1100,7 @@ export async function runChecks(options = {}) {
|
|
|
929
1100
|
}
|
|
930
1101
|
}
|
|
931
1102
|
checks.push(await checkAuthoringDocs(ctx));
|
|
1103
|
+
checks.push(await checkCliDocs(ctx));
|
|
932
1104
|
checks.push(await checkDocsProgressiveDisclosure(ctx));
|
|
933
1105
|
|
|
934
1106
|
const summary = {pass: 0, warn: 0, fail: 0, info: 0};
|
|
@@ -6,15 +6,23 @@
|
|
|
6
6
|
* invariant (the counts must always add up to the number of checks).
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import {describe, it, expect, afterEach} from 'vitest';
|
|
9
|
+
import {describe, it, expect, afterEach, vi} from 'vitest';
|
|
10
10
|
import * as fs from 'node:fs';
|
|
11
11
|
import * as os from 'node:os';
|
|
12
12
|
import * as path from 'node:path';
|
|
13
13
|
import {fileURLToPath} from 'node:url';
|
|
14
14
|
import {DocsCatalog} from '../../foundation/discovery/docs-discovery.mjs';
|
|
15
|
+
import {
|
|
16
|
+
AUTHORING_ROOT,
|
|
17
|
+
AUTHORING_SELF_DOCS,
|
|
18
|
+
auditAuthoringSelfDocs,
|
|
19
|
+
} from '../../foundation/discovery/authoring-self-docs.mjs';
|
|
20
|
+
import {docs} from '../docs/docs.mjs';
|
|
21
|
+
import {auditCliSelfDocs} from '../../foundation/discovery/cli-self-docs.mjs';
|
|
15
22
|
import {
|
|
16
23
|
doctor,
|
|
17
24
|
checkAuthoringDocs,
|
|
25
|
+
checkCliDocs,
|
|
18
26
|
checkDocsProgressiveDisclosure,
|
|
19
27
|
checkImplicitIntegrations,
|
|
20
28
|
checkProviderIdentity,
|
|
@@ -383,7 +391,7 @@ describe('checkDocsProgressiveDisclosure', () => {
|
|
|
383
391
|
expect(c.message).toMatch(/^\d+ topics: /);
|
|
384
392
|
}, SLOW);
|
|
385
393
|
|
|
386
|
-
it('
|
|
394
|
+
it('warns on an invalid doc an integration contributed', async () => {
|
|
387
395
|
const c = await checkDocsProgressiveDisclosure({
|
|
388
396
|
docsCatalogIssues: [
|
|
389
397
|
{
|
|
@@ -394,13 +402,13 @@ describe('checkDocsProgressiveDisclosure', () => {
|
|
|
394
402
|
},
|
|
395
403
|
],
|
|
396
404
|
});
|
|
397
|
-
expect(c.status).toBe('
|
|
405
|
+
expect(c.status).toBe('warn');
|
|
398
406
|
expect(c.message).toBe('@acme/widgets: bad.doc.mjs exports no doc');
|
|
399
407
|
});
|
|
400
408
|
|
|
401
|
-
it('
|
|
409
|
+
it('warns when the docs catalog cannot be built', async () => {
|
|
402
410
|
const c = await checkDocsProgressiveDisclosure({docsCatalogError: 'boom'});
|
|
403
|
-
expect(c.status).toBe('
|
|
411
|
+
expect(c.status).toBe('warn');
|
|
404
412
|
expect(c.message).toContain('boom');
|
|
405
413
|
});
|
|
406
414
|
|
|
@@ -428,7 +436,7 @@ describe('checkDocsProgressiveDisclosure', () => {
|
|
|
428
436
|
}),
|
|
429
437
|
docsCatalogIssues: [],
|
|
430
438
|
});
|
|
431
|
-
expect(c.status).toBe('
|
|
439
|
+
expect(c.status).toBe('warn');
|
|
432
440
|
expect(c.message).toMatch(/^2 problems: /);
|
|
433
441
|
expect(c.message).toContain('huge everything: 41 KB, over the 32 KB one read may return');
|
|
434
442
|
expect(c.message).toContain('broken: ');
|
|
@@ -444,6 +452,323 @@ describe('checkAuthoringDocs', () => {
|
|
|
444
452
|
}, SLOW);
|
|
445
453
|
});
|
|
446
454
|
|
|
455
|
+
describe('checkCliDocs', () => {
|
|
456
|
+
const CLI_DOCS_FIX =
|
|
457
|
+
'Set `namespace` on each CLI doc to the one that reads it: cli/commands for a command, cli/api for an API function or the output schema, error codes, and response types, and authoring for a file an author writes (and list it in AUTHORING_SELF_DOCS).';
|
|
458
|
+
|
|
459
|
+
/** A doc tree under the working directory, as the CLI root. */
|
|
460
|
+
function writeRoot(/** @type {Record<string, any>} */ docsByPath) {
|
|
461
|
+
const root = fs.mkdtempSync(path.join(process.cwd(), '.astryx-doctor-cli-docs-'));
|
|
462
|
+
tmpDirs.push(root);
|
|
463
|
+
for (const [rel, doc] of Object.entries(docsByPath)) {
|
|
464
|
+
const file = path.join(root, rel);
|
|
465
|
+
fs.mkdirSync(path.dirname(file), {recursive: true});
|
|
466
|
+
fs.writeFileSync(file, `export const doc = ${JSON.stringify(doc)};\n`);
|
|
467
|
+
}
|
|
468
|
+
return root;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
it(
|
|
472
|
+
'passes on this repo, counting where each CLI doc is read',
|
|
473
|
+
async () => {
|
|
474
|
+
const audit = await auditCliSelfDocs();
|
|
475
|
+
expect(await checkCliDocs()).toEqual({
|
|
476
|
+
id: 'cli-docs',
|
|
477
|
+
label: 'CLI docs',
|
|
478
|
+
status: 'pass',
|
|
479
|
+
message: `All ${audit.docs} CLI docs are readable: ${audit.sections} in \`astryx docs cli\` and ${audit.authoring} in \`astryx docs authoring\`.`,
|
|
480
|
+
});
|
|
481
|
+
},
|
|
482
|
+
SLOW,
|
|
483
|
+
);
|
|
484
|
+
|
|
485
|
+
it(
|
|
486
|
+
'fails on a doc with no namespace and one no topic reads, and names the fix',
|
|
487
|
+
async () => {
|
|
488
|
+
const root = writeRoot({
|
|
489
|
+
'api/alpha/alpha.doc.mjs': {
|
|
490
|
+
type: 'function',
|
|
491
|
+
kind: 'api',
|
|
492
|
+
name: 'alpha',
|
|
493
|
+
displayName: 'alpha()',
|
|
494
|
+
summary: 'The alpha function.',
|
|
495
|
+
params: [],
|
|
496
|
+
returns: [{type: 'alpha', description: 'The alpha.'}],
|
|
497
|
+
},
|
|
498
|
+
'clients/cli/commands/beta.doc.mjs': {
|
|
499
|
+
type: 'command',
|
|
500
|
+
name: 'beta',
|
|
501
|
+
displayName: 'astryx beta',
|
|
502
|
+
namespace: 'cli',
|
|
503
|
+
summary: 'Do beta',
|
|
504
|
+
},
|
|
505
|
+
});
|
|
506
|
+
expect(
|
|
507
|
+
await checkCliDocs(undefined, {root, authoringSources: []}),
|
|
508
|
+
).toEqual({
|
|
509
|
+
id: 'cli-docs',
|
|
510
|
+
label: 'CLI docs',
|
|
511
|
+
status: 'fail',
|
|
512
|
+
message:
|
|
513
|
+
'2 problems: api/alpha/alpha.doc.mjs has no namespace, so no `astryx docs` topic reads it; clients/cli/commands/beta.doc.mjs has namespace "cli", which no `astryx docs` topic reads',
|
|
514
|
+
fix: CLI_DOCS_FIX,
|
|
515
|
+
});
|
|
516
|
+
},
|
|
517
|
+
SLOW,
|
|
518
|
+
);
|
|
519
|
+
});
|
|
520
|
+
|
|
521
|
+
describe('checkAuthoringDocs against the public authoring surface', () => {
|
|
522
|
+
const NAMESPACE = 'doctypes/namespace/namespace.doc.mjs';
|
|
523
|
+
const NAMESPACE_TYPES =
|
|
524
|
+
'NamespaceDoc, NamespaceProviderScope, NamespaceSlotAcceptance, NamespaceSlot, NamespaceAdoptionSource, NamespaceAdoptionRule from doctypes/namespace/type.ts have no doc in `astryx docs authoring`';
|
|
525
|
+
const SURFACE_FIX =
|
|
526
|
+
'Put a self-doc beside each module whose types @astryxdesign/cli/authoring exports and list it in AUTHORING_SELF_DOCS; export what each listed self-doc documents, or remove that self-doc.';
|
|
527
|
+
|
|
528
|
+
/** A copy of this repo's authoring tree, to break one piece of at a time. */
|
|
529
|
+
function copyAuthoring() {
|
|
530
|
+
const root = fs.mkdtempSync(
|
|
531
|
+
path.join(process.cwd(), '.astryx-doctor-authoring-'),
|
|
532
|
+
);
|
|
533
|
+
tmpDirs.push(root);
|
|
534
|
+
fs.cpSync(AUTHORING_ROOT, root, {
|
|
535
|
+
recursive: true,
|
|
536
|
+
filter: src => !src.endsWith('.test.mjs'),
|
|
537
|
+
});
|
|
538
|
+
return root;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
/** @param {string} source */
|
|
542
|
+
const without = source => AUTHORING_SELF_DOCS.filter(s => s !== source);
|
|
543
|
+
|
|
544
|
+
/** @param {string} text */
|
|
545
|
+
const escape = text => text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
546
|
+
|
|
547
|
+
it(
|
|
548
|
+
'passes on this repo and prints exactly what it printed before',
|
|
549
|
+
async () => {
|
|
550
|
+
expect(await checkAuthoringDocs()).toEqual({
|
|
551
|
+
id: 'authoring-docs',
|
|
552
|
+
label: 'Authoring docs',
|
|
553
|
+
status: 'pass',
|
|
554
|
+
message: `All ${AUTHORING_SELF_DOCS.length} authoring schemas are readable in \`astryx docs authoring\`.`,
|
|
555
|
+
});
|
|
556
|
+
},
|
|
557
|
+
SLOW,
|
|
558
|
+
);
|
|
559
|
+
|
|
560
|
+
it(
|
|
561
|
+
'passes on an unchanged copy of the tree, and writes nothing to it',
|
|
562
|
+
async () => {
|
|
563
|
+
const root = copyAuthoring();
|
|
564
|
+
const before = snapshot(root);
|
|
565
|
+
expect(await checkAuthoringDocs(undefined, {root})).toMatchObject({
|
|
566
|
+
status: 'pass',
|
|
567
|
+
});
|
|
568
|
+
expect(snapshot(root)).toEqual(before);
|
|
569
|
+
},
|
|
570
|
+
SLOW,
|
|
571
|
+
);
|
|
572
|
+
|
|
573
|
+
it(
|
|
574
|
+
'fails when the NamespaceDoc self-doc is left out of AUTHORING_SELF_DOCS',
|
|
575
|
+
async () => {
|
|
576
|
+
const root = copyAuthoring();
|
|
577
|
+
const c = await checkAuthoringDocs(undefined, {
|
|
578
|
+
root,
|
|
579
|
+
sources: without(NAMESPACE),
|
|
580
|
+
});
|
|
581
|
+
expect(c.status).toBe('fail');
|
|
582
|
+
expect(c.message).toBe(
|
|
583
|
+
`2 problems: ${NAMESPACE} is not in \`astryx docs authoring\`; ${NAMESPACE_TYPES}: ${NAMESPACE} is not listed in AUTHORING_SELF_DOCS`,
|
|
584
|
+
);
|
|
585
|
+
},
|
|
586
|
+
SLOW,
|
|
587
|
+
);
|
|
588
|
+
|
|
589
|
+
it(
|
|
590
|
+
"fails when the topic's index no longer exposes the NamespaceDoc section",
|
|
591
|
+
async () => {
|
|
592
|
+
const index = await docs('authoring', undefined, {index: true});
|
|
593
|
+
const topicKeys = new Set(
|
|
594
|
+
index.data.sections
|
|
595
|
+
.map((/** @type {any} */ s) => s.id)
|
|
596
|
+
.filter((/** @type {string} */ id) => id !== 'namespace-doc'),
|
|
597
|
+
);
|
|
598
|
+
const c = await checkAuthoringDocs(undefined, {topicKeys});
|
|
599
|
+
expect(c).toMatchObject({
|
|
600
|
+
status: 'fail',
|
|
601
|
+
message: `${NAMESPACE_TYPES}: ${NAMESPACE} renders section "namespace-doc", which the topic's index does not list`,
|
|
602
|
+
fix: SURFACE_FIX,
|
|
603
|
+
});
|
|
604
|
+
},
|
|
605
|
+
SLOW,
|
|
606
|
+
);
|
|
607
|
+
|
|
608
|
+
it(
|
|
609
|
+
'fails when @astryxdesign/cli/authoring stops exporting NamespaceDoc',
|
|
610
|
+
async () => {
|
|
611
|
+
const root = copyAuthoring();
|
|
612
|
+
const index = path.join(root, 'index.d.ts');
|
|
613
|
+
const before = fs.readFileSync(index, 'utf8');
|
|
614
|
+
const after = before.replace(
|
|
615
|
+
/^export type \{NamespaceDoc\} from .*\n/m,
|
|
616
|
+
'',
|
|
617
|
+
);
|
|
618
|
+
expect(after).not.toBe(before);
|
|
619
|
+
fs.writeFileSync(index, after);
|
|
620
|
+
expect(await checkAuthoringDocs(undefined, {root})).toMatchObject({
|
|
621
|
+
status: 'fail',
|
|
622
|
+
message: `${NAMESPACE} documents NamespaceDoc, which @astryxdesign/cli/authoring does not export`,
|
|
623
|
+
fix: SURFACE_FIX,
|
|
624
|
+
});
|
|
625
|
+
},
|
|
626
|
+
SLOW,
|
|
627
|
+
);
|
|
628
|
+
|
|
629
|
+
it.each([
|
|
630
|
+
[
|
|
631
|
+
'the graph-fields doc',
|
|
632
|
+
'doctypes/base/graph-fields.doc.mjs',
|
|
633
|
+
'doctypes/base/type.ts',
|
|
634
|
+
[
|
|
635
|
+
'AuthoredDocKind',
|
|
636
|
+
'DocAudience',
|
|
637
|
+
'DocPlacement',
|
|
638
|
+
'AuthoredDocGraphFields',
|
|
639
|
+
],
|
|
640
|
+
],
|
|
641
|
+
[
|
|
642
|
+
'the identity doc',
|
|
643
|
+
'identity/identity.doc.mjs',
|
|
644
|
+
'identity/type.ts',
|
|
645
|
+
[
|
|
646
|
+
'ProviderId',
|
|
647
|
+
'ArtifactId',
|
|
648
|
+
'DocId',
|
|
649
|
+
'ProviderInstance',
|
|
650
|
+
'AuthoredDocEntry',
|
|
651
|
+
],
|
|
652
|
+
],
|
|
653
|
+
[
|
|
654
|
+
'the semantic-block doc',
|
|
655
|
+
'doctypes/reference/reference.doc.mjs',
|
|
656
|
+
'doctypes/reference/type.ts',
|
|
657
|
+
[
|
|
658
|
+
'WorkflowStep',
|
|
659
|
+
'WorkflowDocBlock',
|
|
660
|
+
'CollectionDocBlock',
|
|
661
|
+
'ReferenceDocBlock',
|
|
662
|
+
],
|
|
663
|
+
],
|
|
664
|
+
])(
|
|
665
|
+
'fails when %s is removed, which the self-doc audit alone passes',
|
|
666
|
+
async (_what, source, module, names) => {
|
|
667
|
+
const root = copyAuthoring();
|
|
668
|
+
fs.rmSync(path.join(root, source));
|
|
669
|
+
const sources = without(source);
|
|
670
|
+
expect(await auditAuthoringSelfDocs({root, sources})).toEqual({
|
|
671
|
+
sections: sources.length,
|
|
672
|
+
unreachable: [],
|
|
673
|
+
failed: [],
|
|
674
|
+
oversized: [],
|
|
675
|
+
});
|
|
676
|
+
const c = await checkAuthoringDocs(undefined, {root, sources});
|
|
677
|
+
expect(c.status).toBe('fail');
|
|
678
|
+
expect(c.fix).toBe(SURFACE_FIX);
|
|
679
|
+
expect(c.message).toMatch(
|
|
680
|
+
new RegExp(
|
|
681
|
+
`^[A-Za-z, ]+ from ${escape(module)} have no doc in \`astryx docs authoring\`: no self-doc sits beside ${escape(module)}$`,
|
|
682
|
+
),
|
|
683
|
+
);
|
|
684
|
+
for (const name of names) {
|
|
685
|
+
expect(c.message).toMatch(new RegExp(`(^|, )${name}(,| from)`));
|
|
686
|
+
}
|
|
687
|
+
},
|
|
688
|
+
SLOW,
|
|
689
|
+
);
|
|
690
|
+
|
|
691
|
+
it(
|
|
692
|
+
'keeps the message and fix of a failure only the self-doc audit reports',
|
|
693
|
+
async () => {
|
|
694
|
+
const root = copyAuthoring();
|
|
695
|
+
fs.writeFileSync(
|
|
696
|
+
path.join(root, 'identity', 'broken.doc.mjs'),
|
|
697
|
+
'export const doc = {;\n',
|
|
698
|
+
);
|
|
699
|
+
const c = await checkAuthoringDocs(undefined, {
|
|
700
|
+
root,
|
|
701
|
+
sources: [...AUTHORING_SELF_DOCS, 'identity/broken.doc.mjs'],
|
|
702
|
+
});
|
|
703
|
+
expect(c.status).toBe('fail');
|
|
704
|
+
expect(c.message).toMatch(/^identity\/broken\.doc\.mjs failed to load: /);
|
|
705
|
+
expect(c.fix).toBe(
|
|
706
|
+
'List every authoring self-doc in AUTHORING_SELF_DOCS, fix the one that fails to load, and split a section that is too large.',
|
|
707
|
+
);
|
|
708
|
+
},
|
|
709
|
+
SLOW,
|
|
710
|
+
);
|
|
711
|
+
|
|
712
|
+
it(
|
|
713
|
+
'reports a topic it cannot read rather than skipping the comparison',
|
|
714
|
+
async () => {
|
|
715
|
+
const spy = vi
|
|
716
|
+
.spyOn(DocsCatalog, 'fromBuiltins')
|
|
717
|
+
.mockImplementationOnce(() => {
|
|
718
|
+
throw new Error('no built-in docs');
|
|
719
|
+
});
|
|
720
|
+
try {
|
|
721
|
+
expect(await checkAuthoringDocs()).toMatchObject({
|
|
722
|
+
status: 'fail',
|
|
723
|
+
message:
|
|
724
|
+
'`astryx docs authoring` could not be read: no built-in docs',
|
|
725
|
+
fix: SURFACE_FIX,
|
|
726
|
+
});
|
|
727
|
+
} finally {
|
|
728
|
+
spy.mockRestore();
|
|
729
|
+
}
|
|
730
|
+
},
|
|
731
|
+
SLOW,
|
|
732
|
+
);
|
|
733
|
+
|
|
734
|
+
it(
|
|
735
|
+
'fails rather than passes when the surface exports no types at all',
|
|
736
|
+
async () => {
|
|
737
|
+
const root = copyAuthoring();
|
|
738
|
+
fs.writeFileSync(
|
|
739
|
+
path.join(root, 'index.d.ts'),
|
|
740
|
+
"export {parseDoc} from './doctypes/parse.mjs';\n",
|
|
741
|
+
);
|
|
742
|
+
const c = await checkAuthoringDocs(undefined, {root});
|
|
743
|
+
expect(c.status).toBe('fail');
|
|
744
|
+
expect(c.message).toContain(
|
|
745
|
+
'@astryxdesign/cli/authoring exports no types, so nothing was compared with `astryx docs authoring`',
|
|
746
|
+
);
|
|
747
|
+
},
|
|
748
|
+
SLOW,
|
|
749
|
+
);
|
|
750
|
+
});
|
|
751
|
+
|
|
752
|
+
/**
|
|
753
|
+
* Every file under `root` with its contents.
|
|
754
|
+
* @param {string} root
|
|
755
|
+
* @returns {Record<string, string>}
|
|
756
|
+
*/
|
|
757
|
+
function snapshot(root) {
|
|
758
|
+
/** @type {Record<string, string>} */
|
|
759
|
+
const out = {};
|
|
760
|
+
/** @param {string} dir */
|
|
761
|
+
const walk = dir => {
|
|
762
|
+
for (const entry of fs.readdirSync(dir, {withFileTypes: true})) {
|
|
763
|
+
const full = path.join(dir, entry.name);
|
|
764
|
+
if (entry.isDirectory()) walk(full);
|
|
765
|
+
else out[path.relative(root, full)] = fs.readFileSync(full, 'utf8');
|
|
766
|
+
}
|
|
767
|
+
};
|
|
768
|
+
walk(root);
|
|
769
|
+
return out;
|
|
770
|
+
}
|
|
771
|
+
|
|
447
772
|
describe('doctor docs checks', () => {
|
|
448
773
|
it('runs both docs checks and they pass on the repo', async () => {
|
|
449
774
|
const r = await doctor({cwd});
|
|
@@ -487,7 +812,7 @@ describe('checkDocsProgressiveDisclosure languages', () => {
|
|
|
487
812
|
docsCatalog: DocsCatalog.fromBuiltins({deploying: path.join(dir, 'deploying.doc.mjs')}),
|
|
488
813
|
docsCatalogIssues: [],
|
|
489
814
|
});
|
|
490
|
-
expect(c.status).toBe('
|
|
815
|
+
expect(c.status).toBe('warn');
|
|
491
816
|
expect(c.message).toContain('deploying [zh]: zh overlay broken');
|
|
492
817
|
expect(c.message).toContain('deploying [dense] overview: 41 KB');
|
|
493
818
|
expect(c.message).not.toMatch(/deploying overview:/);
|