@astryxdesign/cli 0.6.4 → 0.6.5-canary.031021b
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/CHANGELOG.md +56 -0
- package/README.md +97 -90
- 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/_adapter.d.mts +25 -0
- package/api/component/_adapter.mjs +59 -5
- package/api/component/component.d.mts +6 -3
- package/api/component/component.doc.mjs +37 -17
- package/api/component/component.mjs +249 -9
- package/api/component/component.type.d.mts +25 -0
- package/api/component/component.type.mjs +44 -0
- package/api/discover/_adapter.d.mts +114 -6
- package/api/discover/_adapter.mjs +372 -17
- package/api/discover/_adapter.test.mjs +215 -0
- package/api/discover/_catalog-view.d.mts +115 -0
- package/api/discover/_catalog-view.mjs +203 -0
- package/api/discover/_catalog-view.test.mjs +128 -0
- package/api/discover/detail/detail.d.mts +18 -6
- package/api/discover/detail/detail.mjs +67 -13
- package/api/discover/detail/detail.test.mjs +85 -0
- package/api/discover/detail/item/item.d.mts +26 -0
- package/api/discover/detail/item/item.mjs +78 -0
- package/api/discover/detail/item/item.test.mjs +73 -0
- package/api/discover/discover.d.mts +3 -9
- package/api/discover/discover.doc.mjs +61 -18
- package/api/discover/discover.mjs +220 -36
- package/api/discover/discover.test.mjs +11 -2
- package/api/discover/discover.type.d.mts +147 -8
- package/api/discover/discover.type.mjs +102 -12
- package/api/discover/list/list.d.mts +20 -6
- package/api/discover/list/list.mjs +45 -12
- package/api/discover/list/list.test.mjs +46 -0
- package/api/discover/search/search.d.mts +18 -16
- package/api/discover/search/search.mjs +102 -56
- package/api/discover/search/search.test.mjs +144 -10
- 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.d.mts +8 -3
- package/api/doctor/doctor.doc.mjs +17 -8
- package/api/doctor/doctor.mjs +90 -9
- package/api/doctor/doctor.test.mjs +122 -10
- 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 +1 -0
- package/api/index.mjs +5 -3
- package/api/init/init.doc.mjs +17 -12
- package/api/integration/add-helpers.d.mts +5 -2
- package/api/integration/add-helpers.mjs +36 -9
- 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 +107 -0
- package/api/integration/pack-check.mjs +82 -9
- 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/isError.doc.mjs +1 -1
- 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.doc.mjs +2 -1
- package/api/theme/add/add.mjs +17 -25
- package/api/theme/add/add.rollback.test.mjs +158 -0
- package/api/theme/add/add.staging.test.mjs +40 -23
- package/api/theme/build/build.family.test.mjs +7 -12
- package/api/theme/build/build.mjs +8 -18
- package/api/theme/build/build.rollback.test.mjs +148 -0
- 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/files-changed.test.mjs +111 -0
- package/api/upgrade/run/run.mjs +5 -3
- package/api/upgrade/upgrade.doc.mjs +24 -22
- package/api/upgrade/upgrade.type.mjs +2 -2
- package/assets/codemods/__tests__/runner.test.mjs +3 -1
- package/assets/codemods/file-count.test.mjs +163 -0
- package/assets/codemods/integration-runner.mjs +3 -3
- package/assets/codemods/runner.mjs +5 -4
- 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/internationalization.doc.mjs +7 -5
- 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 +57 -47
- 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/component-lookups.doc.mjs +149 -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 -451
- 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/assets/templates/blocks/components/InternationalizationProvider/InternationalizationProvider01ShippedLocale.tsx +1 -1
- package/authoring/config/config.doc.mjs +9 -1
- package/authoring/config/parse.d.mts +2 -0
- package/authoring/config/parse.mjs +19 -0
- package/authoring/config/parse.test.mjs +8 -0
- package/authoring/config/type.ts +11 -0
- package/authoring/discover/discover.doc.d.mts +13 -0
- package/authoring/discover/discover.doc.mjs +138 -0
- package/authoring/discover/parse.d.mts +24 -0
- package/authoring/discover/parse.mjs +128 -0
- package/authoring/discover/parse.test.mjs +124 -0
- package/authoring/discover/type.ts +87 -0
- 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/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/index.d.mts +1 -0
- package/authoring/index.d.ts +10 -0
- package/authoring/index.mjs +1 -0
- package/authoring/integration/integration.doc.mjs +12 -10
- package/clients/cli/commands/component/index.mjs +152 -55
- package/clients/cli/commands/component-batch.test.mjs +341 -0
- package/clients/cli/commands/component-ownership.test.mjs +89 -0
- package/clients/cli/commands/component.doc.mjs +27 -9
- package/clients/cli/commands/discover.doc.mjs +53 -9
- package/clients/cli/commands/discover.mjs +393 -118
- package/clients/cli/commands/discover.sources.test.mjs +267 -0
- 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/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 +7 -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 +28 -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 +17 -1
- package/clients/cli/lib/json-shim.mjs +24 -14
- package/clients/cli/lib/manifest.mjs +18 -5
- package/clients/cli/lib/manifest.test.mjs +5 -2
- package/clients/cli/lib/parse-error-format.test.mjs +81 -0
- package/foundation/agent-docs/agent-docs.mjs +1 -1
- package/foundation/discovery/authoring-self-docs.mjs +1 -0
- 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/doc-compiler/doc-loads.test.mjs +3 -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/integrations/integrations.d.mts +14 -1
- package/foundation/integrations/integrations.mjs +41 -1
- package/foundation/integrations/integrations.test.mjs +31 -0
- package/foundation/response/batch.type.d.mts +33 -0
- package/foundation/response/batch.type.mjs +34 -0
- 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 +40 -10
- package/foundation/response/response-types.doc.test.mjs +23 -0
- package/foundation/response/response.doc.mjs +11 -10
- package/package.json +9 -9
- package/api/docs/docs.test.mjs +0 -243
- package/api/docs/integration-tree.test.mjs +0 -555
- package/api/docs/integrationDocs.test.mjs +0 -314
- package/api/search/search.test.mjs +0 -512
- 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 -294
- package/foundation/agent-docs/agent-docs.test.mjs +0 -1159
- package/foundation/doc-compiler/tree.test.mjs +0 -598
package/api/doctor/doctor.mjs
CHANGED
|
@@ -26,7 +26,11 @@ import * as path from 'node:path';
|
|
|
26
26
|
import {MIN_NODE_VERSION, isNodeVersionSupported} from '../../foundation/env/node-version.mjs';
|
|
27
27
|
import {CLI_ROOT, findCoreDir, findInstalledPackage} from '../../foundation/fs/paths.mjs';
|
|
28
28
|
import {explainPackageManager, getCliInvocation} from '../../foundation/env/package-manager.mjs';
|
|
29
|
-
import {
|
|
29
|
+
import {
|
|
30
|
+
findConfigPath,
|
|
31
|
+
Project,
|
|
32
|
+
providerLedgerOf,
|
|
33
|
+
} from '../../foundation/config/project.mjs';
|
|
30
34
|
import {DocsCatalog} from '../../foundation/discovery/docs-discovery.mjs';
|
|
31
35
|
import {buildDocsIndexData} from '../../foundation/discovery/docs-section-key.mjs';
|
|
32
36
|
import {
|
|
@@ -76,6 +80,8 @@ import {semverCompare, isValidSemver, satisfiesRange} from '../../foundation/env
|
|
|
76
80
|
* @property {string|null} [docsCatalogError] - Why the project's docs catalog
|
|
77
81
|
* could not be built, when it could not.
|
|
78
82
|
* @property {Array<{package: string, code: string, severity: 'warning'|'error', message: string}>|null} [integrationIssues]
|
|
83
|
+
* @property {Array<{spec: string, error: string}>|null} [autolinkFailures]
|
|
84
|
+
* installed dependencies whose integration manifest could not be loaded
|
|
79
85
|
* Combined project-level integration issues, including cross-package template replacement warnings.
|
|
80
86
|
* @property {Error|null} [configError] - Error thrown while resolving the config
|
|
81
87
|
* path (e.g. multiple config files present), surfaced by checkConfig as a FAIL.
|
|
@@ -417,6 +423,9 @@ export function checkImplicitIntegrations(ctx) {
|
|
|
417
423
|
const implicit = ctx.integrations.filter(
|
|
418
424
|
integration => integration.__autolinked,
|
|
419
425
|
);
|
|
426
|
+
// A dependency whose manifest cannot be loaded leaves no loaded record, so
|
|
427
|
+
// without this line doctor would say no dependency ships a manifest at all.
|
|
428
|
+
const unreadable = describeUnreadableManifests(ctx.autolinkFailures ?? []);
|
|
420
429
|
|
|
421
430
|
if (implicit.length === 0) {
|
|
422
431
|
return {
|
|
@@ -424,9 +433,12 @@ export function checkImplicitIntegrations(ctx) {
|
|
|
424
433
|
label,
|
|
425
434
|
status: 'info',
|
|
426
435
|
message:
|
|
427
|
-
ctx.integrations.length > 0
|
|
436
|
+
(ctx.integrations.length > 0
|
|
428
437
|
? 'None — every loaded integration is named in astryx.config.'
|
|
429
|
-
:
|
|
438
|
+
: unreadable
|
|
439
|
+
? 'None loaded.'
|
|
440
|
+
: 'None — no installed dependency ships an astryx.integration.* manifest.') +
|
|
441
|
+
unreadable,
|
|
430
442
|
};
|
|
431
443
|
}
|
|
432
444
|
|
|
@@ -439,11 +451,25 @@ export function checkImplicitIntegrations(ctx) {
|
|
|
439
451
|
integration.__spec && integration.__spec !== integration.name
|
|
440
452
|
? ` (declared as "${integration.__spec}")`
|
|
441
453
|
: '';
|
|
442
|
-
|
|
454
|
+
// A declared root counts only when it exists: the manifest's keys are a
|
|
455
|
+
// claim, and `integration-issues` reports the ones that are not true.
|
|
456
|
+
const declared = ['components', 'templates', 'themes', 'docs', 'codemods'].filter(
|
|
443
457
|
root => integration[/** @type {'components'} */ (root)],
|
|
444
458
|
);
|
|
459
|
+
const missing = declared.filter(root => {
|
|
460
|
+
const dir = integration[/** @type {'components'} */ (root)];
|
|
461
|
+
if (typeof dir !== 'string') return false;
|
|
462
|
+
const base =
|
|
463
|
+
typeof integration.__packageDir === 'string'
|
|
464
|
+
? integration.__packageDir
|
|
465
|
+
: (ctx.cwd ?? process.cwd());
|
|
466
|
+
return !fs.existsSync(path.isAbsolute(dir) ? dir : path.resolve(base, dir));
|
|
467
|
+
});
|
|
468
|
+
const roots = declared.filter(root => !missing.includes(root));
|
|
445
469
|
const contributes = roots.length > 0 ? roots.join(', ') : 'nothing';
|
|
446
|
-
|
|
470
|
+
const absent =
|
|
471
|
+
missing.length > 0 ? ` (declared ${missing.join(', ')} missing on disk)` : '';
|
|
472
|
+
return `${integration.name}${version}${alias} from ${integration.__dependencyField}, contributing ${contributes}${absent}`;
|
|
447
473
|
});
|
|
448
474
|
|
|
449
475
|
const plural = implicit.length === 1 ? '' : 's';
|
|
@@ -453,7 +479,8 @@ export function checkImplicitIntegrations(ctx) {
|
|
|
453
479
|
status: 'info',
|
|
454
480
|
message:
|
|
455
481
|
`${implicit.length} integration${plural} loaded from installed ` +
|
|
456
|
-
`dependencies with no astryx.config entry: ${described.join('; ')}
|
|
482
|
+
`dependencies with no astryx.config entry: ${described.join('; ')}.` +
|
|
483
|
+
unreadable,
|
|
457
484
|
fix:
|
|
458
485
|
'Nothing to fix. Keep these dependencies installed. The CLI links them ' +
|
|
459
486
|
'from package.json, so an unused-dependency check that looks only for ' +
|
|
@@ -462,6 +489,30 @@ export function checkImplicitIntegrations(ctx) {
|
|
|
462
489
|
};
|
|
463
490
|
}
|
|
464
491
|
|
|
492
|
+
/**
|
|
493
|
+
* The sentence `implicit-integrations` adds for dependencies whose manifest
|
|
494
|
+
* could not be loaded, or '' when there are none. Still informational: the
|
|
495
|
+
* package is a dependency's own bug, which `doctor integration validate`
|
|
496
|
+
* diagnoses, but doctor must not report it as absent.
|
|
497
|
+
* @param {Array<{spec: string, error: string}>} failures
|
|
498
|
+
* @returns {string}
|
|
499
|
+
*/
|
|
500
|
+
function describeUnreadableManifests(failures) {
|
|
501
|
+
if (failures.length === 0) return '';
|
|
502
|
+
const one = failures.length === 1;
|
|
503
|
+
const listed = failures
|
|
504
|
+
.map(({spec, error}) => {
|
|
505
|
+
const reason = String(error).split('\n')[0].slice(0, 160);
|
|
506
|
+
return `${spec} (${reason})`;
|
|
507
|
+
})
|
|
508
|
+
.join('; ');
|
|
509
|
+
return (
|
|
510
|
+
` ${failures.length} installed ${one ? 'dependency ships' : 'dependencies ship'} ` +
|
|
511
|
+
`an astryx.integration.* manifest that could not be loaded, so ${one ? 'it contributes' : 'they contribute'} ` +
|
|
512
|
+
`nothing: ${listed}. Run \`astryx doctor integration validate <package>\` for details.`
|
|
513
|
+
);
|
|
514
|
+
}
|
|
515
|
+
|
|
465
516
|
/**
|
|
466
517
|
* Check 7 — agent docs exist and contain the Astryx section markers.
|
|
467
518
|
* @param {DoctorContext} ctx
|
|
@@ -738,12 +789,26 @@ export function checkProviderIdentity(ctx) {
|
|
|
738
789
|
integration =>
|
|
739
790
|
integration.providerId != null && integration.__loadError == null,
|
|
740
791
|
).length;
|
|
792
|
+
// An integration that could not be read has no provider ID to check, so the
|
|
793
|
+
// count above is not a complete survey. Say so instead of counting silently.
|
|
794
|
+
const unread = ctx.integrations.filter(
|
|
795
|
+
integration => integration.__loadError != null,
|
|
796
|
+
).length;
|
|
797
|
+
const unreadNote =
|
|
798
|
+
unread === 0
|
|
799
|
+
? ''
|
|
800
|
+
: unread === 1
|
|
801
|
+
? ' 1 loaded integration could not be read, so its provider ID is unknown.'
|
|
802
|
+
: ` ${unread} loaded integrations could not be read, so their provider IDs are unknown.`;
|
|
741
803
|
if (count === 0) {
|
|
742
804
|
return {
|
|
743
805
|
id,
|
|
744
806
|
label,
|
|
745
807
|
status: 'info',
|
|
746
|
-
message:
|
|
808
|
+
message:
|
|
809
|
+
(unread === 0
|
|
810
|
+
? 'None — no loaded integration has a provider identity.'
|
|
811
|
+
: 'No readable integration has a provider identity.') + unreadNote,
|
|
747
812
|
};
|
|
748
813
|
}
|
|
749
814
|
return {
|
|
@@ -751,9 +816,10 @@ export function checkProviderIdentity(ctx) {
|
|
|
751
816
|
label,
|
|
752
817
|
status: 'pass',
|
|
753
818
|
message:
|
|
754
|
-
count === 1
|
|
819
|
+
(count === 1
|
|
755
820
|
? '1 loaded integration has its own provider ID.'
|
|
756
|
-
: `${count} loaded integrations each have their own provider ID
|
|
821
|
+
: `${count} loaded integrations each have their own provider ID.`) +
|
|
822
|
+
unreadNote,
|
|
757
823
|
};
|
|
758
824
|
}
|
|
759
825
|
|
|
@@ -1198,11 +1264,25 @@ export async function runChecks(options = {}) {
|
|
|
1198
1264
|
let docsCatalogError = null;
|
|
1199
1265
|
/** @type {Array<{package: string, code: string, severity: 'warning'|'error', message: string}>|null} */
|
|
1200
1266
|
let integrationIssues = null;
|
|
1267
|
+
/** @type {Array<{spec: string, error: string}>|null} */
|
|
1268
|
+
let autolinkFailures = null;
|
|
1201
1269
|
try {
|
|
1202
1270
|
const project = await Project.load(cwd);
|
|
1203
1271
|
configTheme =
|
|
1204
1272
|
/** @type {{theme?: string}} */ (project.config ?? {}).theme ?? null;
|
|
1205
1273
|
integrations = project.loadedIntegrations;
|
|
1274
|
+
// An installed dependency whose manifest cannot be loaded is kept out of
|
|
1275
|
+
// loadedIntegrations on purpose. The provider ledger still records it.
|
|
1276
|
+
autolinkFailures = [...providerLedgerOf(project).values()]
|
|
1277
|
+
.filter(
|
|
1278
|
+
entry =>
|
|
1279
|
+
entry.outcome === 'load-failed' &&
|
|
1280
|
+
entry.candidate.source === 'autolinked',
|
|
1281
|
+
)
|
|
1282
|
+
.map(entry => ({
|
|
1283
|
+
spec: entry.candidate.spec ?? entry.label,
|
|
1284
|
+
error: entry.error ?? 'its manifest could not be loaded',
|
|
1285
|
+
}));
|
|
1206
1286
|
try {
|
|
1207
1287
|
docsCatalog = await project.docs();
|
|
1208
1288
|
docsCatalogIssues = (await project.issues()).filter(
|
|
@@ -1229,6 +1309,7 @@ export async function runChecks(options = {}) {
|
|
|
1229
1309
|
docsCatalogIssues,
|
|
1230
1310
|
docsCatalogError,
|
|
1231
1311
|
integrationIssues,
|
|
1312
|
+
autolinkFailures,
|
|
1232
1313
|
configError,
|
|
1233
1314
|
};
|
|
1234
1315
|
|
|
@@ -354,16 +354,31 @@ describe('checkImplicitIntegrations', () => {
|
|
|
354
354
|
});
|
|
355
355
|
|
|
356
356
|
it('names the package, the field, and what it contributes', () => {
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
357
|
+
// Roots count only when they exist, so this one gives them real folders.
|
|
358
|
+
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'astryx-implicit-'));
|
|
359
|
+
try {
|
|
360
|
+
const dir = name => {
|
|
361
|
+
fs.mkdirSync(path.join(root, name));
|
|
362
|
+
return path.join(root, name);
|
|
363
|
+
};
|
|
364
|
+
const c = checkImplicitIntegrations({
|
|
365
|
+
integrations: [
|
|
366
|
+
autolinked({
|
|
367
|
+
components: dir('components'),
|
|
368
|
+
templates: dir('templates'),
|
|
369
|
+
themes: dir('themes'),
|
|
370
|
+
}),
|
|
371
|
+
],
|
|
372
|
+
});
|
|
373
|
+
expect(c.message).toContain('@acme/widgets@1.0.0');
|
|
374
|
+
expect(c.message).toContain('from dependencies');
|
|
375
|
+
expect(c.message).toContain(
|
|
376
|
+
'contributing components, templates, themes',
|
|
377
|
+
);
|
|
378
|
+
expect(c.message).not.toContain('missing on disk');
|
|
379
|
+
} finally {
|
|
380
|
+
fs.rmSync(root, {recursive: true, force: true});
|
|
381
|
+
}
|
|
367
382
|
});
|
|
368
383
|
|
|
369
384
|
it('names the declared key too when an npm alias makes them differ', () => {
|
|
@@ -906,3 +921,100 @@ describe('checkDocsProgressiveDisclosure languages', () => {
|
|
|
906
921
|
expect(c.message).not.toMatch(/deploying overview:/);
|
|
907
922
|
});
|
|
908
923
|
});
|
|
924
|
+
|
|
925
|
+
describe('doctor says what it could not check', () => {
|
|
926
|
+
const CORE = {
|
|
927
|
+
'node_modules/@astryxdesign/core/package.json': JSON.stringify({
|
|
928
|
+
name: '@astryxdesign/core',
|
|
929
|
+
version: '0.6.3',
|
|
930
|
+
}),
|
|
931
|
+
};
|
|
932
|
+
|
|
933
|
+
/** Installed dependency whose manifest declares roots that do not exist. */
|
|
934
|
+
const dangling = {
|
|
935
|
+
'node_modules/@acme/dangling/package.json': JSON.stringify({
|
|
936
|
+
name: '@acme/dangling',
|
|
937
|
+
version: '2.0.0',
|
|
938
|
+
}),
|
|
939
|
+
'node_modules/@acme/dangling/astryx.integration.mjs':
|
|
940
|
+
"export default {providerId: 'acme-dangling', components: './components', templates: './templates', docs: './docs'};\n",
|
|
941
|
+
};
|
|
942
|
+
|
|
943
|
+
/** Installed dependency whose manifest cannot be parsed at all. */
|
|
944
|
+
const broken = {
|
|
945
|
+
'node_modules/@acme/broken/package.json': JSON.stringify({
|
|
946
|
+
name: '@acme/broken',
|
|
947
|
+
version: '1.0.0',
|
|
948
|
+
}),
|
|
949
|
+
'node_modules/@acme/broken/astryx.integration.mjs':
|
|
950
|
+
'export default { this is not valid javascript ((\n',
|
|
951
|
+
};
|
|
952
|
+
|
|
953
|
+
/** @param {Record<string, string>} extra @param {string[]} deps */
|
|
954
|
+
const project = (extra, deps) =>
|
|
955
|
+
mkProject({
|
|
956
|
+
'package.json': JSON.stringify({
|
|
957
|
+
name: 'consumer',
|
|
958
|
+
version: '1.0.0',
|
|
959
|
+
dependencies: Object.fromEntries(
|
|
960
|
+
['@astryxdesign/core', ...deps].map(d => [d, '1.0.0']),
|
|
961
|
+
),
|
|
962
|
+
}),
|
|
963
|
+
...CORE,
|
|
964
|
+
...extra,
|
|
965
|
+
});
|
|
966
|
+
|
|
967
|
+
// An unparseable manifest is kept out of the loaded set on purpose, and
|
|
968
|
+
// doctor used to report that no installed dependency ships a manifest.
|
|
969
|
+
it('names an installed dependency whose manifest cannot be loaded', async () => {
|
|
970
|
+
const report = (await doctor({cwd: project(broken, ['@acme/broken'])})).data;
|
|
971
|
+
const check = report.checks.find(c => c.id === 'implicit-integrations');
|
|
972
|
+
|
|
973
|
+
expect(check.status).toBe('info');
|
|
974
|
+
expect(check.message).toContain('@acme/broken');
|
|
975
|
+
expect(check.message).toContain('could not be loaded');
|
|
976
|
+
expect(check.message).not.toContain('no installed dependency ships');
|
|
977
|
+
expect(report.summary.fail).toBe(0);
|
|
978
|
+
}, SLOW);
|
|
979
|
+
|
|
980
|
+
it('does not claim contributions from roots that are missing on disk', async () => {
|
|
981
|
+
const report = (await doctor({cwd: project(dangling, ['@acme/dangling'])}))
|
|
982
|
+
.data;
|
|
983
|
+
const implicit = report.checks.find(c => c.id === 'implicit-integrations');
|
|
984
|
+
const issues = report.checks.find(c => c.id === 'integration-issues');
|
|
985
|
+
|
|
986
|
+
expect(implicit.message).toContain('contributing nothing');
|
|
987
|
+
expect(implicit.message).toContain('missing on disk');
|
|
988
|
+
expect(implicit.message).not.toContain('contributing components');
|
|
989
|
+
expect(issues.status).toBe('warn');
|
|
990
|
+
expect(issues.message).toContain('@acme/dangling');
|
|
991
|
+
}, SLOW);
|
|
992
|
+
|
|
993
|
+
it('still says no dependency ships a manifest when none does', async () => {
|
|
994
|
+
const report = (await doctor({cwd: project({}, [])})).data;
|
|
995
|
+
const check = report.checks.find(c => c.id === 'implicit-integrations');
|
|
996
|
+
|
|
997
|
+
expect(check.message).toBe(
|
|
998
|
+
'None — no installed dependency ships an astryx.integration.* manifest.',
|
|
999
|
+
);
|
|
1000
|
+
}, SLOW);
|
|
1001
|
+
|
|
1002
|
+
it('says how many integrations could not be read, rather than counting silently', () => {
|
|
1003
|
+
/** @type {any} */
|
|
1004
|
+
const ctx = {
|
|
1005
|
+
cwd: '/x',
|
|
1006
|
+
nodeVersion: process.versions.node,
|
|
1007
|
+
coreDir: null,
|
|
1008
|
+
configPath: null,
|
|
1009
|
+
configTheme: null,
|
|
1010
|
+
integrations: [
|
|
1011
|
+
{name: '@acme/ok', __spec: '@acme/ok', providerId: 'ok'},
|
|
1012
|
+
{name: '@acme/bad', __spec: '@acme/bad', __loadError: 'boom'},
|
|
1013
|
+
],
|
|
1014
|
+
};
|
|
1015
|
+
const check = checkProviderIdentity(ctx);
|
|
1016
|
+
|
|
1017
|
+
expect(check.message).toContain('1 loaded integration has its own provider ID.');
|
|
1018
|
+
expect(check.message).toContain('could not be read');
|
|
1019
|
+
});
|
|
1020
|
+
});
|
|
@@ -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
|
@@ -18,6 +18,7 @@ export { integrationAddTheme } from "./integration/add-theme.mjs";
|
|
|
18
18
|
export { integrationPackCheck } from "./integration/pack-check.mjs";
|
|
19
19
|
export { AstryxError } from "./error.mjs";
|
|
20
20
|
export { logger } from "./logger.mjs";
|
|
21
|
+
export * from "../foundation/response/batch.type.mjs";
|
|
21
22
|
export * from "./component/component.type.mjs";
|
|
22
23
|
export * from "./docs/docs.type.mjs";
|
|
23
24
|
export * from "./blog/blog.type.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
|
|
@@ -73,10 +73,12 @@ export {logger} from './logger.mjs';
|
|
|
73
73
|
* @typedef {import('./logger.mjs').Logger} Logger
|
|
74
74
|
*/
|
|
75
75
|
|
|
76
|
-
// ── Types (re-exported from each command's
|
|
76
|
+
// ── Types (re-exported from the shared response foundation and each command's
|
|
77
|
+
// colocated `.type.mjs`) ──────────────────────────────────────────────────
|
|
77
78
|
// Runtime no-ops (the .type.mjs files are `export {}`); tsc carries these
|
|
78
79
|
// through to the generated api/index.d.mts so the public type surface exposes
|
|
79
|
-
// every command's Options + response types
|
|
80
|
+
// the shared receipt vocabulary and every command's Options + response types.
|
|
81
|
+
export * from '../foundation/response/batch.type.mjs';
|
|
80
82
|
export * from './component/component.type.mjs';
|
|
81
83
|
export * from './docs/docs.type.mjs';
|
|
82
84
|
export * from './blog/blog.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: [
|
|
@@ -8,7 +8,7 @@ export function findPackageDir(startDir: string): string;
|
|
|
8
8
|
/**
|
|
9
9
|
* @typedef {object} WritePlan
|
|
10
10
|
* @property {string} path
|
|
11
|
-
* @property {string} contents
|
|
11
|
+
* @property {string | Buffer} contents a Buffer is written byte for byte
|
|
12
12
|
* @property {boolean} createOnly
|
|
13
13
|
* @property {Buffer} [expectedOriginal] bytes captured before validation;
|
|
14
14
|
* a different current file is a concurrent edit and must never be overwritten
|
|
@@ -56,7 +56,10 @@ export function packageJsonUpdate(packageFile: string, rootPath: string, manifes
|
|
|
56
56
|
export function applyWrites(plans: WritePlan[]): () => void;
|
|
57
57
|
export type WritePlan = {
|
|
58
58
|
path: string;
|
|
59
|
-
|
|
59
|
+
/**
|
|
60
|
+
* a Buffer is written byte for byte
|
|
61
|
+
*/
|
|
62
|
+
contents: string | Buffer;
|
|
60
63
|
createOnly: boolean;
|
|
61
64
|
/**
|
|
62
65
|
* bytes captured before validation;
|