@astryxdesign/cli 0.6.4-canary.f0355e3 → 0.6.4
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 +96 -99
- package/api/build/build.doc.mjs +1 -6
- package/api/build/build.test.mjs +0 -22
- package/api/build/kit/kit.mjs +5 -44
- package/api/component/_adapter.d.mts +0 -25
- package/api/component/_adapter.mjs +5 -59
- package/api/component/component.d.mts +3 -6
- package/api/component/component.doc.mjs +17 -37
- package/api/component/component.mjs +9 -249
- package/api/component/component.type.d.mts +0 -25
- package/api/component/component.type.mjs +0 -44
- package/api/discover/_adapter.d.mts +6 -114
- package/api/discover/_adapter.mjs +17 -372
- package/api/discover/detail/detail.d.mts +6 -18
- package/api/discover/detail/detail.mjs +13 -67
- package/api/discover/detail/detail.test.mjs +0 -85
- package/api/discover/discover.d.mts +9 -3
- package/api/discover/discover.doc.mjs +18 -61
- package/api/discover/discover.mjs +36 -220
- package/api/discover/discover.test.mjs +2 -11
- package/api/discover/discover.type.d.mts +8 -147
- package/api/discover/discover.type.mjs +12 -102
- package/api/discover/list/list.d.mts +6 -20
- package/api/discover/list/list.mjs +12 -45
- package/api/discover/list/list.test.mjs +0 -46
- package/api/discover/search/search.d.mts +16 -18
- package/api/discover/search/search.mjs +56 -102
- package/api/discover/search/search.test.mjs +10 -144
- package/api/docs/_adapter.d.mts +3 -8
- package/api/docs/_adapter.mjs +6 -14
- package/api/docs/docOverlays.test.mjs +1 -27
- package/api/docs/docs.doc.mjs +2 -2
- package/api/docs/docs.test.mjs +243 -0
- package/api/docs/integration-tree.test.mjs +555 -0
- package/api/docs/integrationDocs.test.mjs +314 -0
- package/api/doctor/doctor.d.mts +3 -8
- package/api/doctor/doctor.doc.mjs +8 -17
- package/api/doctor/doctor.mjs +9 -90
- package/api/doctor/doctor.test.mjs +10 -122
- 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 +10 -19
- package/api/hook/hook.doc.mjs +3 -6
- package/api/index.d.mts +2 -1
- package/api/index.mjs +5 -5
- package/api/init/init.doc.mjs +12 -17
- package/api/integration/add-helpers.d.mts +2 -5
- package/api/integration/add-helpers.mjs +9 -36
- package/api/integration/add-theme.mjs +1 -22
- package/api/integration/add-theme.test.mjs +0 -34
- package/api/integration/authoring-checks.mjs +2 -2
- package/api/integration/integrationPackCheck.doc.mjs +3 -3
- package/api/integration/pack-check.mjs +9 -82
- package/api/integration/pack-check.test.mjs +0 -90
- package/api/integration/pack-check.type.mjs +1 -1
- package/api/json/assertResponse.doc.mjs +1 -1
- package/api/json/index.ts +1 -0
- package/api/json/isError.doc.mjs +1 -1
- package/api/layout/_adapter.d.mts +34 -0
- package/api/layout/_adapter.mjs +148 -0
- package/api/layout/check/check.d.mts +16 -0
- package/api/layout/check/check.mjs +40 -0
- package/api/layout/expand/expand.d.mts +22 -0
- package/api/layout/expand/expand.mjs +155 -0
- package/api/layout/expand/expand.path-safety.test.mjs +53 -0
- package/api/layout/grammar/grammar.d.mts +13 -0
- package/api/layout/grammar/grammar.mjs +87 -0
- package/api/layout/layout.d.mts +6 -0
- package/api/layout/layout.mjs +17 -0
- package/api/layout/layout.test.mjs +297 -0
- package/api/layout/layout.type.d.mts +89 -0
- package/api/layout/layout.type.mjs +103 -0
- package/api/layout/layoutCheck.doc.d.mts +11 -0
- package/api/layout/layoutCheck.doc.mjs +85 -0
- package/api/layout/layoutExpand.doc.d.mts +11 -0
- package/api/layout/layoutExpand.doc.mjs +107 -0
- package/api/layout/layoutGrammar.doc.d.mts +11 -0
- package/api/layout/layoutGrammar.doc.mjs +57 -0
- package/api/search/search.d.mts +1 -27
- package/api/search/search.doc.mjs +2 -2
- package/api/search/search.mjs +16 -228
- package/api/search/search.test.mjs +512 -0
- package/api/swizzle/swizzle.doc.mjs +5 -7
- package/api/template/copy/copy.mjs +1 -1
- package/api/template/copy/copy.test.mjs +0 -9
- package/api/template/template-integration.test.mjs +65 -1
- package/api/template/template.doc.mjs +1 -2
- package/api/template/template.mjs +1 -1
- package/api/theme/add/add.mjs +25 -17
- package/api/theme/add/add.staging.test.mjs +23 -40
- package/api/theme/build/build.family.test.mjs +12 -7
- package/api/theme/build/build.mjs +18 -8
- package/api/theme/generateTonalPalette.doc.mjs +2 -1
- package/api/theme/listThemes.doc.mjs +1 -1
- package/api/theme/themeAdd.doc.mjs +10 -9
- package/api/theme/themeBuild.doc.mjs +13 -13
- package/api/theme/themeList.doc.mjs +1 -1
- package/api/theme/themeListAvailable.doc.mjs +1 -2
- package/api/theme/themePaletteGenerate.doc.mjs +8 -15
- package/api/theme/themeTargets.doc.mjs +2 -3
- package/api/theme/themeTemplate.doc.mjs +1 -2
- package/api/upgrade/run/run.mjs +4 -6
- package/api/upgrade/upgrade.doc.mjs +22 -24
- package/api/upgrade/upgrade.type.mjs +2 -2
- package/assets/codemods/__tests__/runner.test.mjs +1 -3
- package/assets/codemods/integration-runner.mjs +3 -3
- package/assets/codemods/runner.mjs +4 -5
- package/assets/docs/README.md +2 -4
- package/assets/docs/browser-support.doc.mjs +11 -11
- package/assets/docs/color.doc.mjs +2 -8
- package/assets/docs/elevation.doc.mjs +4 -6
- package/assets/docs/getting-started.doc.mjs +16 -5
- package/assets/docs/icons.doc.mjs +21 -2
- package/assets/docs/illustrations.doc.mjs +15 -7
- package/assets/docs/internationalization.doc.mjs +5 -7
- package/assets/docs/layout.doc.dense.mjs +82 -130
- package/assets/docs/layout.doc.mjs +77 -133
- package/assets/docs/migration.doc.mjs +21 -19
- package/assets/docs/motion.doc.mjs +3 -16
- package/assets/docs/principles.doc.dense.mjs +5 -5
- package/assets/docs/principles.doc.mjs +0 -8
- package/assets/docs/principles.doc.zh.mjs +6 -6
- package/assets/docs/shape.doc.mjs +3 -8
- package/assets/docs/spacing.doc.mjs +2 -7
- package/assets/docs/styling-libraries.doc.mjs +2 -6
- package/assets/docs/styling.doc.mjs +23 -19
- package/assets/docs/theme.doc.dense.mjs +18 -58
- package/assets/docs/theme.doc.mjs +46 -56
- package/assets/docs/theme.doc.zh.mjs +8 -9
- package/assets/docs/tokens.doc.dense.mjs +2 -2
- package/assets/docs/tokens.doc.mjs +8 -389
- package/assets/docs/tokens.doc.zh.mjs +2 -2
- package/assets/docs/tree/integrations.doc.mjs +451 -25
- package/assets/docs/tree/integrations.test.mjs +62 -0
- package/assets/docs/tree/writing-docs.doc.mjs +286 -0
- package/assets/docs/typography.doc.mjs +4 -24
- package/assets/docs/working-with-ai.doc.mjs +22 -30
- package/assets/templates/blocks/components/InternationalizationProvider/InternationalizationProvider01ShippedLocale.tsx +1 -1
- package/authoring/config/config.doc.mjs +2 -10
- package/authoring/config/parse.d.mts +0 -2
- package/authoring/config/parse.mjs +0 -19
- package/authoring/config/parse.test.mjs +0 -8
- package/authoring/config/type.ts +2 -13
- package/authoring/doctypes/_schema.d.mts +2 -3
- package/authoring/doctypes/_schema.mjs +0 -6
- package/authoring/doctypes/base/graph-fields.doc.mjs +3 -3
- package/authoring/doctypes/base/type.ts +2 -4
- package/authoring/doctypes/command/command.doc.mjs +1 -1
- package/authoring/doctypes/command/type.ts +1 -1
- package/authoring/doctypes/component/component.doc.mjs +0 -6
- package/authoring/doctypes/component/type.ts +0 -8
- package/authoring/doctypes/reference/reference.doc.mjs +0 -7
- package/authoring/doctypes/reference/type.ts +0 -5
- 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 +0 -1
- package/authoring/index.d.ts +0 -10
- package/authoring/index.mjs +0 -1
- package/authoring/integration/integration.doc.mjs +10 -12
- package/clients/cli/command-result-coverage.test.mjs +7 -7
- package/clients/cli/commands/component/index.mjs +55 -152
- package/clients/cli/commands/component-ownership.test.mjs +0 -89
- package/clients/cli/commands/component.doc.mjs +9 -27
- package/clients/cli/commands/debug-result-summary.test.mjs +2 -2
- package/clients/cli/commands/discover.doc.mjs +9 -53
- package/clients/cli/commands/discover.mjs +118 -393
- package/clients/cli/commands/docs.doc.mjs +1 -1
- package/clients/cli/commands/docs.mjs +17 -60
- package/clients/cli/commands/docs.test.mjs +294 -0
- package/clients/cli/commands/doctor-integration-docs.doc.mjs +2 -3
- package/clients/cli/commands/doctor-integration.test.mjs +0 -53
- package/clients/cli/commands/doctor.doc.mjs +1 -3
- package/clients/cli/commands/doctor.mjs +5 -49
- package/clients/cli/commands/gap-report.doc.mjs +9 -10
- package/clients/cli/commands/init.doc.mjs +6 -9
- package/clients/cli/commands/integration-add.doc.mjs +9 -9
- package/clients/cli/commands/integration-authoring.test.mjs +10 -61
- package/clients/cli/commands/integration-pack.doc.mjs +9 -5
- package/clients/cli/commands/integration-real-world.test.mjs +1 -1
- package/clients/cli/commands/integration.doc.mjs +4 -4
- package/clients/cli/commands/integration.mjs +43 -74
- package/clients/cli/commands/layout-check.doc.mjs +65 -0
- package/clients/cli/commands/layout-expand.doc.mjs +83 -0
- package/clients/cli/commands/layout-grammar.doc.mjs +30 -0
- package/clients/cli/commands/layout.doc.mjs +34 -0
- package/clients/cli/commands/layout.error-codes.test.mjs +66 -0
- package/clients/cli/commands/layout.exit-parity.test.mjs +41 -0
- package/clients/cli/commands/layout.mjs +275 -0
- package/clients/cli/commands/layout.path-help.test.mjs +33 -0
- package/clients/cli/commands/layout.stdin-cap.test.mjs +47 -0
- package/clients/cli/commands/layout.text-fields.test.mjs +39 -0
- package/clients/cli/commands/manifest.doc.mjs +1 -1
- package/clients/cli/commands/search.doc.mjs +3 -10
- package/clients/cli/commands/search.mjs +2 -21
- package/clients/cli/commands/search.test.mjs +4 -21
- 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 +16 -5
- package/clients/cli/commands/theme-add.doc.mjs +1 -1
- package/clients/cli/commands/theme-palette-generate.doc.mjs +2 -3
- package/clients/cli/commands/theme-palette.doc.mjs +2 -1
- package/clients/cli/commands/theme-targets.doc.mjs +2 -2
- package/clients/cli/commands/theme.doc.mjs +1 -2
- package/clients/cli/commands/upgrade.doc.mjs +3 -62
- package/clients/cli/index.mjs +10 -28
- package/clients/cli/lib/define-command.mjs +4 -28
- package/clients/cli/lib/define-command.test.mjs +0 -54
- package/clients/cli/lib/exit-codes.test.mjs +9 -18
- package/clients/cli/lib/json-shim.mjs +14 -24
- package/clients/cli/lib/json-shim.test.mjs +20 -6
- package/clients/cli/lib/manifest.mjs +13 -18
- package/clients/cli/lib/manifest.test.mjs +2 -5
- package/foundation/agent-docs/agent-docs.mjs +1 -1
- package/foundation/agent-docs/agent-docs.test.mjs +1159 -0
- package/foundation/discovery/authoring-self-docs.mjs +0 -1
- package/foundation/discovery/authoring-self-docs.test.mjs +2 -6
- package/foundation/discovery/cli-self-docs.mjs +2 -16
- package/foundation/discovery/cli-self-docs.test.mjs +0 -20
- package/foundation/discovery/docs-discovery.mjs +1 -5
- package/foundation/discovery/docs-discovery.test.mjs +0 -21
- package/foundation/discovery/docs-section-key.d.mts +1 -1
- package/foundation/discovery/docs-section-key.mjs +1 -1
- package/foundation/discovery/template-adapter.mjs +1 -1
- package/foundation/doc-compiler/doc-loads.test.mjs +14 -3
- package/foundation/doc-compiler/tree.d.mts +0 -4
- package/foundation/doc-compiler/tree.mjs +1 -6
- package/foundation/doc-compiler/tree.test.mjs +598 -0
- package/foundation/integrations/cli-requirement.d.mts +6 -26
- package/foundation/integrations/cli-requirement.mjs +11 -46
- package/foundation/integrations/cli-requirement.test.mjs +2 -7
- package/foundation/integrations/contribution-inventory.mjs +1 -1
- package/foundation/integrations/integrations.d.mts +1 -14
- package/foundation/integrations/integrations.mjs +1 -41
- package/foundation/integrations/integrations.test.mjs +0 -31
- package/foundation/response/error-codes.doc.mjs +8 -6
- package/foundation/response/error-codes.test.mjs +5 -30
- package/foundation/response/response-types.doc.d.mts +3 -4
- package/foundation/response/response-types.doc.mjs +27 -40
- package/foundation/response/response-types.doc.test.mjs +0 -23
- package/foundation/response/response.doc.mjs +10 -11
- package/foundation/xle/browser.d.mts +3 -3
- package/foundation/xle/browser.mjs +3 -3
- package/foundation/xle/expand.mjs +2 -2
- package/foundation/xle/parse.mjs +1 -1
- package/foundation/xle/print.mjs +2 -2
- package/foundation/xle/splice.mjs +1 -1
- package/package.json +9 -9
- package/api/discover/_adapter.test.mjs +0 -215
- package/api/discover/_catalog-view.d.mts +0 -115
- package/api/discover/_catalog-view.mjs +0 -203
- package/api/discover/_catalog-view.test.mjs +0 -128
- package/api/discover/detail/item/item.d.mts +0 -26
- package/api/discover/detail/item/item.mjs +0 -78
- package/api/discover/detail/item/item.test.mjs +0 -73
- package/api/integration/pack-check.lifecycle-output.test.mjs +0 -107
- package/api/theme/add/add.rollback.test.mjs +0 -158
- package/api/theme/build/build.rollback.test.mjs +0 -148
- package/api/upgrade/run/files-changed.test.mjs +0 -111
- package/assets/codemods/file-count.test.mjs +0 -163
- package/assets/docs/tree/add-a-component.doc.mjs +0 -75
- package/assets/docs/tree/add-a-theme.doc.mjs +0 -85
- package/assets/docs/tree/add-a-topic.doc.mjs +0 -144
- package/assets/docs/tree/agent-guidance.doc.mjs +0 -138
- package/assets/docs/tree/block-template.doc.mjs +0 -130
- package/assets/docs/tree/build-the-template.doc.mjs +0 -28
- package/assets/docs/tree/building-blocks.doc.mjs +0 -46
- package/assets/docs/tree/check-your-docs.doc.mjs +0 -137
- package/assets/docs/tree/checks.doc.mjs +0 -119
- package/assets/docs/tree/codemods.doc.mjs +0 -147
- package/assets/docs/tree/component-family.doc.mjs +0 -113
- package/assets/docs/tree/component-imports.doc.mjs +0 -69
- package/assets/docs/tree/component-lookups.doc.mjs +0 -149
- package/assets/docs/tree/components.doc.mjs +0 -23
- package/assets/docs/tree/configuration.doc.mjs +0 -23
- package/assets/docs/tree/debug-and-gap-reports.doc.mjs +0 -182
- package/assets/docs/tree/define-the-theme.doc.mjs +0 -118
- package/assets/docs/tree/describe-the-component.doc.mjs +0 -57
- package/assets/docs/tree/docs.doc.mjs +0 -21
- package/assets/docs/tree/document-the-template.doc.mjs +0 -28
- package/assets/docs/tree/document-the-theme.doc.mjs +0 -68
- package/assets/docs/tree/export-template-assets.doc.mjs +0 -147
- package/assets/docs/tree/extend-or-replace.doc.mjs +0 -103
- package/assets/docs/tree/fonts-and-assets.doc.mjs +0 -106
- package/assets/docs/tree/generate-a-palette.doc.mjs +0 -66
- package/assets/docs/tree/grade-template-with-agent.doc.mjs +0 -105
- package/assets/docs/tree/help.doc.mjs +0 -16
- package/assets/docs/tree/links.doc.mjs +0 -98
- package/assets/docs/tree/package-and-test.doc.mjs +0 -32
- package/assets/docs/tree/page-template.doc.mjs +0 -71
- package/assets/docs/tree/publishing.doc.mjs +0 -111
- package/assets/docs/tree/quick-start.doc.mjs +0 -272
- package/assets/docs/tree/replace-a-core-component.doc.mjs +0 -104
- package/assets/docs/tree/replace-a-core-template.doc.mjs +0 -172
- package/assets/docs/tree/sections-and-placement.doc.mjs +0 -108
- package/assets/docs/tree/see-it-in-an-app.doc.mjs +0 -59
- package/assets/docs/tree/ship.doc.mjs +0 -16
- package/assets/docs/tree/short-and-findable.doc.mjs +0 -108
- package/assets/docs/tree/single-component.doc.mjs +0 -165
- package/assets/docs/tree/start-a-template.doc.mjs +0 -143
- package/assets/docs/tree/subcomponent.doc.mjs +0 -115
- package/assets/docs/tree/template-assets.doc.mjs +0 -64
- package/assets/docs/tree/template-doc-overview.doc.mjs +0 -109
- package/assets/docs/tree/template-fonts.doc.mjs +0 -102
- package/assets/docs/tree/template-grading-rubric.doc.mjs +0 -452
- package/assets/docs/tree/template-icons.doc.mjs +0 -97
- package/assets/docs/tree/template-images-media.doc.mjs +0 -127
- package/assets/docs/tree/template-styles.doc.mjs +0 -93
- package/assets/docs/tree/templates.doc.mjs +0 -34
- package/assets/docs/tree/test-in-an-app.doc.mjs +0 -115
- package/assets/docs/tree/test-template-in-app.doc.mjs +0 -128
- package/assets/docs/tree/themes.doc.mjs +0 -39
- package/assets/docs/tree/troubleshooting.doc.mjs +0 -149
- package/assets/docs/tree/upgrading.doc.mjs +0 -103
- package/assets/docs/tree/use-a-theme-in-an-app.doc.mjs +0 -51
- package/assets/docs/tree/verify-packed-template.doc.mjs +0 -77
- package/assets/docs/tree/versioning.doc.mjs +0 -161
- package/assets/docs/tree/write-good-templates.doc.mjs +0 -64
- package/assets/docs/tree/write-the-template-file.doc.mjs +0 -154
- package/authoring/discover/discover.doc.d.mts +0 -13
- package/authoring/discover/discover.doc.mjs +0 -138
- package/authoring/discover/parse.d.mts +0 -24
- package/authoring/discover/parse.mjs +0 -128
- package/authoring/discover/parse.test.mjs +0 -124
- package/authoring/discover/type.ts +0 -87
- package/clients/cli/commands/component-batch.test.mjs +0 -341
- package/clients/cli/commands/discover.sources.test.mjs +0 -267
- package/clients/cli/commands/integration-verify.doc.mjs +0 -22
- package/clients/cli/lib/parse-error-format.test.mjs +0 -81
- package/foundation/response/batch.type.d.mts +0 -33
- package/foundation/response/batch.type.mjs +0 -34
|
@@ -354,31 +354,16 @@ 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
|
-
|
|
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
|
-
}
|
|
357
|
+
const c = checkImplicitIntegrations({
|
|
358
|
+
integrations: [
|
|
359
|
+
autolinked({templates: '/abs/templates', themes: '/abs/themes'}),
|
|
360
|
+
],
|
|
361
|
+
});
|
|
362
|
+
expect(c.message).toContain('@acme/widgets@1.0.0');
|
|
363
|
+
expect(c.message).toContain('from dependencies');
|
|
364
|
+
expect(c.message).toContain(
|
|
365
|
+
'contributing components, templates, themes',
|
|
366
|
+
);
|
|
382
367
|
});
|
|
383
368
|
|
|
384
369
|
it('names the declared key too when an npm alias makes them differ', () => {
|
|
@@ -921,100 +906,3 @@ describe('checkDocsProgressiveDisclosure languages', () => {
|
|
|
921
906
|
expect(c.message).not.toMatch(/deploying overview:/);
|
|
922
907
|
});
|
|
923
908
|
});
|
|
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, present when status is not 'pass'.
|
|
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, present when status is not 'pass'.
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
25
|
/**
|
|
@@ -12,16 +12,12 @@ export const doc = {
|
|
|
12
12
|
name: 'gapReport',
|
|
13
13
|
namespace: 'cli/api',
|
|
14
14
|
displayName: 'gapReport()',
|
|
15
|
-
summary:
|
|
16
|
-
'Report a missing or hard-to-use design-system capability to the package that owns it.',
|
|
15
|
+
summary: 'Route a design-system gap through the fan-out handler composition.',
|
|
17
16
|
description:
|
|
18
|
-
'
|
|
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.',
|
|
17
|
+
'Creates a normalized gap report and fans it out to every effective handler: the project config handler first, then each loaded integration handler in config order, deduplicated by handle function identity. Each handler receives a structuredClone of the report and an AbortSignal, then runs in its own worker with a 30 s timeout and stdout redirected to stderr. A timed-out worker is terminated before the next handler starts, so process.exit, process.exitCode, and late continuations cannot affect the CLI process. A public handler requires confirmPublic per handler; internal handlers always run. When no handlers exist, a built-in GitHub/routed-only fallback runs. The aggregate response carries ordered deliveries with per-handler outcomes.',
|
|
22
18
|
importPath: '@astryxdesign/cli/api',
|
|
23
19
|
signature:
|
|
24
|
-
'gapReport(component
|
|
20
|
+
'gapReport(component?: string, options?: GapReportOptions): Promise<GapReportCategoriesResponse | GapReportReceiptResponse>',
|
|
25
21
|
keywords: [
|
|
26
22
|
'gap',
|
|
27
23
|
'report',
|
|
@@ -60,13 +56,13 @@ export const doc = {
|
|
|
60
56
|
name: 'options.package',
|
|
61
57
|
type: 'string',
|
|
62
58
|
description:
|
|
63
|
-
'
|
|
59
|
+
'Explicit owning package when automatic routing is ambiguous.',
|
|
64
60
|
},
|
|
65
61
|
{
|
|
66
62
|
name: 'options.confirmPublic',
|
|
67
63
|
type: 'boolean',
|
|
68
64
|
description:
|
|
69
|
-
'
|
|
65
|
+
'Explicitly consent to invoking public handlers or creating a GitHub issue.',
|
|
70
66
|
default: 'false',
|
|
71
67
|
},
|
|
72
68
|
{
|
|
@@ -81,7 +77,6 @@ export const doc = {
|
|
|
81
77
|
type: 'string',
|
|
82
78
|
description:
|
|
83
79
|
'Directory used to load project config and component ownership.',
|
|
84
|
-
default: 'process.cwd()',
|
|
85
80
|
},
|
|
86
81
|
],
|
|
87
82
|
returns: [
|
|
@@ -92,21 +87,17 @@ export const doc = {
|
|
|
92
87
|
{
|
|
93
88
|
type: 'gap-report.file',
|
|
94
89
|
description:
|
|
95
|
-
'
|
|
90
|
+
'An aggregate receipt with per-handler deliveries, filedCount/routedOnlyCount totals, and overall status.',
|
|
96
91
|
},
|
|
97
92
|
],
|
|
98
93
|
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
|
-
},
|
|
103
94
|
{
|
|
104
95
|
code: 'ERR_UNKNOWN_CATEGORY',
|
|
105
96
|
when: 'category is not one of the fixed gap-report values',
|
|
106
97
|
},
|
|
107
98
|
{
|
|
108
99
|
code: 'ERR_INVALID_ARGUMENT',
|
|
109
|
-
when: '
|
|
100
|
+
when: 'a field value is invalid',
|
|
110
101
|
},
|
|
111
102
|
{
|
|
112
103
|
code: 'ERR_AMBIGUOUS_COMPONENT',
|
|
@@ -118,7 +109,7 @@ export const doc = {
|
|
|
118
109
|
},
|
|
119
110
|
{
|
|
120
111
|
code: 'ERR_NOT_FOUND',
|
|
121
|
-
when: 'no
|
|
112
|
+
when: 'no handler and no issues URL available',
|
|
122
113
|
},
|
|
123
114
|
],
|
|
124
115
|
examples: [
|
|
@@ -131,8 +122,8 @@ export const doc = {
|
|
|
131
122
|
code: "const receipt = await gapReport('Button', {category: 'missing_variant', reason: 'Need a compact size'});",
|
|
132
123
|
},
|
|
133
124
|
{
|
|
134
|
-
label: '
|
|
135
|
-
code: "
|
|
125
|
+
label: 'Confirm public filing',
|
|
126
|
+
code: "await gapReport('Button', {category: 'docs_gap', reason: 'Missing keyboard example', confirmPublic: true});",
|
|
136
127
|
},
|
|
137
128
|
],
|
|
138
129
|
command: 'gap-report',
|
package/api/hook/hook.doc.mjs
CHANGED
|
@@ -34,7 +34,6 @@ 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()',
|
|
38
37
|
},
|
|
39
38
|
{
|
|
40
39
|
name: 'options.list',
|
|
@@ -44,8 +43,7 @@ export const doc = {
|
|
|
44
43
|
{
|
|
45
44
|
name: 'options.category',
|
|
46
45
|
type: 'string',
|
|
47
|
-
description:
|
|
48
|
-
"List only the hooks in this category, a key of the unfiltered list such as 'Media' or 'Focus'.",
|
|
46
|
+
description: 'List only hooks in this category.',
|
|
49
47
|
},
|
|
50
48
|
{
|
|
51
49
|
name: 'options.params',
|
|
@@ -56,8 +54,7 @@ export const doc = {
|
|
|
56
54
|
name: 'options.detail',
|
|
57
55
|
type: "'full' | 'compact' | 'brief'",
|
|
58
56
|
description: 'Detail level for list views.',
|
|
59
|
-
default:
|
|
60
|
-
"'full' for a named hook; 'brief' for lists (returned as data.detail: 'names')",
|
|
57
|
+
default: "'full' for a named hook, 'brief' for list views",
|
|
61
58
|
},
|
|
62
59
|
{
|
|
63
60
|
name: 'options.lang',
|
|
@@ -107,7 +104,7 @@ export const doc = {
|
|
|
107
104
|
},
|
|
108
105
|
{
|
|
109
106
|
label: 'Browse a category',
|
|
110
|
-
code: "await hook(undefined, {category: '
|
|
107
|
+
code: "await hook(undefined, {category: 'State', detail: 'compact'});",
|
|
111
108
|
},
|
|
112
109
|
],
|
|
113
110
|
command: 'hook',
|
package/api/index.d.mts
CHANGED
|
@@ -18,7 +18,6 @@ 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";
|
|
22
21
|
export * from "./component/component.type.mjs";
|
|
23
22
|
export * from "./docs/docs.type.mjs";
|
|
24
23
|
export * from "./blog/blog.type.mjs";
|
|
@@ -33,12 +32,14 @@ export * from "./gap-report/gap-report.type.mjs";
|
|
|
33
32
|
export * from "./upgrade/upgrade.type.mjs";
|
|
34
33
|
export * from "./init/init.type.mjs";
|
|
35
34
|
export * from "./doctor/doctor.type.mjs";
|
|
35
|
+
export * from "./layout/layout.type.mjs";
|
|
36
36
|
export * from "./integration/integration-authoring.type.mjs";
|
|
37
37
|
export * from "./integration/pack-check.type.mjs";
|
|
38
38
|
export * from "./integration/validate-integration.type.mjs";
|
|
39
39
|
export * from "./integration/authoring-checks.type.mjs";
|
|
40
40
|
export type Logger = import("./logger.mjs").Logger;
|
|
41
41
|
export { themeBuild, themeAdd, themeTemplate, themeList, themeListAvailable, themeTargets, themePaletteGenerate, generateTonalPalette, listThemes } from "./theme/theme.mjs";
|
|
42
|
+
export { layoutExpand, layoutCheck, layoutGrammar } from "./layout/layout.mjs";
|
|
42
43
|
export { integrationAdd, integrationAddAgentDoc, integrationAddCodemod, integrationAddComponent, integrationAddDoc, integrationAddTemplate } from "./integration/add-contribution.mjs";
|
|
43
44
|
export { validateIntegration, summarizeIssues } from "./integration/validate-integration.mjs";
|
|
44
45
|
export { integrationTemplateConflicts, integrationComponentConflicts, integrationDocConflicts } from "./integration/authoring-checks.mjs";
|
package/api/index.mjs
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* @file Programmatic API for the Astryx CLI.
|
|
5
5
|
*
|
|
6
|
-
* Every function returns the same { type, data } envelope that `
|
|
6
|
+
* Every function returns the same { type, data } envelope that `xds --json` outputs.
|
|
7
7
|
* Errors throw AstryxError (with optional .suggestions).
|
|
8
8
|
*
|
|
9
9
|
* @example
|
|
@@ -44,6 +44,7 @@ export {gapReport} from './gap-report/gap-report.mjs';
|
|
|
44
44
|
export {upgrade} from './upgrade/upgrade.mjs';
|
|
45
45
|
export {init} from './init/init.mjs';
|
|
46
46
|
export {doctor} from './doctor/doctor.mjs';
|
|
47
|
+
export {layoutExpand, layoutCheck, layoutGrammar} from './layout/layout.mjs';
|
|
47
48
|
export {
|
|
48
49
|
integrationAdd,
|
|
49
50
|
integrationAddAgentDoc,
|
|
@@ -72,12 +73,10 @@ export {logger} from './logger.mjs';
|
|
|
72
73
|
* @typedef {import('./logger.mjs').Logger} Logger
|
|
73
74
|
*/
|
|
74
75
|
|
|
75
|
-
// ── Types (re-exported from
|
|
76
|
-
// colocated `.type.mjs`) ──────────────────────────────────────────────────
|
|
76
|
+
// ── Types (re-exported from each command's colocated `.type.mjs`) ─────
|
|
77
77
|
// Runtime no-ops (the .type.mjs files are `export {}`); tsc carries these
|
|
78
78
|
// through to the generated api/index.d.mts so the public type surface exposes
|
|
79
|
-
//
|
|
80
|
-
export * from '../foundation/response/batch.type.mjs';
|
|
79
|
+
// every command's Options + response types by name.
|
|
81
80
|
export * from './component/component.type.mjs';
|
|
82
81
|
export * from './docs/docs.type.mjs';
|
|
83
82
|
export * from './blog/blog.type.mjs';
|
|
@@ -92,6 +91,7 @@ export * from './gap-report/gap-report.type.mjs';
|
|
|
92
91
|
export * from './upgrade/upgrade.type.mjs';
|
|
93
92
|
export * from './init/init.type.mjs';
|
|
94
93
|
export * from './doctor/doctor.type.mjs';
|
|
94
|
+
export * from './layout/layout.type.mjs';
|
|
95
95
|
export * from './integration/integration-authoring.type.mjs';
|
|
96
96
|
export * from './integration/pack-check.type.mjs';
|
|
97
97
|
export * from './integration/validate-integration.type.mjs';
|
package/api/init/init.doc.mjs
CHANGED
|
@@ -19,9 +19,10 @@ 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
|
-
'With `removeAgents` it removes the managed agent-docs block
|
|
22
|
+
'prints getting-started guidance; `features` / ' +
|
|
23
|
+
'`all` add theme and page-building guidance and can scaffold a starter ' +
|
|
24
|
+
'template. With `removeAgents` it removes the managed agent-docs block ' +
|
|
25
|
+
'instead of installing.',
|
|
25
26
|
importPath: '@astryxdesign/cli/api',
|
|
26
27
|
signature:
|
|
27
28
|
'init(options?: InitOptions, ctx?: {cwd?: string}): Promise<InitRunResponse | InitRemoveResponse>',
|
|
@@ -31,7 +32,7 @@ export const doc = {
|
|
|
31
32
|
name: 'options.features',
|
|
32
33
|
type: 'string',
|
|
33
34
|
description:
|
|
34
|
-
'Comma-separated features to install: agents (agent docs), theme (writes the annotated theme.template.ts), template (
|
|
35
|
+
'Comma-separated features to install: agents (agent docs), theme (writes the annotated theme.template.ts), template (page-template guidance).',
|
|
35
36
|
},
|
|
36
37
|
{
|
|
37
38
|
name: 'options.all',
|
|
@@ -46,8 +47,7 @@ export const doc = {
|
|
|
46
47
|
{
|
|
47
48
|
name: 'options.agent',
|
|
48
49
|
type: 'string',
|
|
49
|
-
description:
|
|
50
|
-
'Agent preset: claude, cursor, codex, hermes, muse, all. Used only when the agents feature runs.',
|
|
50
|
+
description: 'Agent preset: claude, cursor, codex, hermes, muse, all.',
|
|
51
51
|
},
|
|
52
52
|
{
|
|
53
53
|
name: 'options.agentDocsPath',
|
|
@@ -58,14 +58,9 @@ export const doc = {
|
|
|
58
58
|
name: 'options.templateName',
|
|
59
59
|
type: 'string',
|
|
60
60
|
description:
|
|
61
|
-
'Scaffold
|
|
62
|
-
},
|
|
63
|
-
{
|
|
64
|
-
name: 'ctx.cwd',
|
|
65
|
-
type: 'string',
|
|
66
|
-
description: 'Directory to set up.',
|
|
67
|
-
default: 'process.cwd()',
|
|
61
|
+
'Scaffold a named page template (programmatic only; the CLI never sets it).',
|
|
68
62
|
},
|
|
63
|
+
{name: 'ctx.cwd', type: 'string', description: 'Directory to set up.'},
|
|
69
64
|
],
|
|
70
65
|
returns: [
|
|
71
66
|
{
|
|
@@ -76,13 +71,13 @@ export const doc = {
|
|
|
76
71
|
{
|
|
77
72
|
type: 'init.remove',
|
|
78
73
|
description:
|
|
79
|
-
'
|
|
74
|
+
'Confirmation that the managed agent-docs block was removed (`data.removed: true`), returned when `removeAgents` is set.',
|
|
80
75
|
},
|
|
81
76
|
],
|
|
82
77
|
throws: [
|
|
83
78
|
{
|
|
84
79
|
code: 'ERR_UNKNOWN_AGENT',
|
|
85
|
-
when: '
|
|
80
|
+
when: '`agent` is not one of claude, cursor, codex, hermes, muse, all',
|
|
86
81
|
},
|
|
87
82
|
{
|
|
88
83
|
code: 'ERR_UNKNOWN_FEATURE',
|
|
@@ -90,7 +85,7 @@ export const doc = {
|
|
|
90
85
|
},
|
|
91
86
|
{
|
|
92
87
|
code: 'ERR_UNKNOWN_TEMPLATE',
|
|
93
|
-
when: '
|
|
88
|
+
when: '`templateName` matches no bundled template',
|
|
94
89
|
},
|
|
95
90
|
{
|
|
96
91
|
code: 'ERR_FILE_EXISTS',
|
|
@@ -98,7 +93,7 @@ export const doc = {
|
|
|
98
93
|
},
|
|
99
94
|
{
|
|
100
95
|
code: 'ERR_PATH_TRAVERSAL',
|
|
101
|
-
when: 'the template output path resolves outside cwd
|
|
96
|
+
when: 'the template output path resolves outside cwd, for example through a symlinked src directory',
|
|
102
97
|
},
|
|
103
98
|
],
|
|
104
99
|
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
|
|
11
|
+
* @property {string} contents
|
|
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,10 +56,7 @@ 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
|
-
|
|
60
|
-
* a Buffer is written byte for byte
|
|
61
|
-
*/
|
|
62
|
-
contents: string | Buffer;
|
|
59
|
+
contents: string;
|
|
63
60
|
createOnly: boolean;
|
|
64
61
|
/**
|
|
65
62
|
* bytes captured before validation;
|
|
@@ -5,8 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Hosts the atomic staged-write transaction, package.json files-array
|
|
7
7
|
* maintenance, package-dir resolution, and project-path normalization that
|
|
8
|
-
* every `integration add <kind>` command needs.
|
|
9
|
-
* write through the same transaction. Stateless and side-effect-free
|
|
8
|
+
* every `integration add <kind>` command needs. Stateless and side-effect-free
|
|
10
9
|
* outside of {@link applyWrites}.
|
|
11
10
|
*/
|
|
12
11
|
|
|
@@ -41,7 +40,7 @@ export function findPackageDir(startDir) {
|
|
|
41
40
|
/**
|
|
42
41
|
* @typedef {object} WritePlan
|
|
43
42
|
* @property {string} path
|
|
44
|
-
* @property {string
|
|
43
|
+
* @property {string} contents
|
|
45
44
|
* @property {boolean} createOnly
|
|
46
45
|
* @property {Buffer} [expectedOriginal] bytes captured before validation;
|
|
47
46
|
* a different current file is a concurrent edit and must never be overwritten
|
|
@@ -193,29 +192,21 @@ export function packageJsonUpdate(
|
|
|
193
192
|
|
|
194
193
|
// ── Atomic staged-write transaction ─────────────────────────────────
|
|
195
194
|
|
|
196
|
-
/**
|
|
197
|
-
* @param {string} file
|
|
198
|
-
* @returns {boolean} false when the file is still there
|
|
199
|
-
*/
|
|
195
|
+
/** @param {string} file */
|
|
200
196
|
function removeTemporary(file) {
|
|
201
197
|
try {
|
|
202
198
|
fs.rmSync(file, {force: true});
|
|
203
|
-
return true;
|
|
204
199
|
} catch {
|
|
205
200
|
// Best effort. The transaction error remains the actionable failure.
|
|
206
|
-
return false;
|
|
207
201
|
}
|
|
208
202
|
}
|
|
209
203
|
|
|
210
204
|
/**
|
|
211
205
|
* Restore writes that already published. Best-effort so callers preserve
|
|
212
|
-
* the original actionable error
|
|
206
|
+
* the original actionable error.
|
|
213
207
|
* @param {Array<WritePlan & {temporary: string, original: Buffer|null, mode: number}>} published
|
|
214
|
-
* @returns {string[]}
|
|
215
208
|
*/
|
|
216
209
|
function rollbackWrites(published) {
|
|
217
|
-
/** @type {string[]} */
|
|
218
|
-
const unrestored = [];
|
|
219
210
|
for (const plan of [...published].reverse()) {
|
|
220
211
|
let restore = null;
|
|
221
212
|
try {
|
|
@@ -234,18 +225,12 @@ function rollbackWrites(published) {
|
|
|
234
225
|
fs.renameSync(restore, plan.path);
|
|
235
226
|
restore = null;
|
|
236
227
|
}
|
|
237
|
-
} catch
|
|
238
|
-
//
|
|
239
|
-
// leaves this call's bytes, or no bytes, where the original was.
|
|
240
|
-
const gone =
|
|
241
|
-
error instanceof Error &&
|
|
242
|
-
/** @type {NodeJS.ErrnoException} */ (error).code === 'ENOENT';
|
|
243
|
-
if (!(gone && plan.original == null)) unrestored.push(plan.path);
|
|
228
|
+
} catch {
|
|
229
|
+
// Best effort. A concurrent edit belongs to its writer, not this rollback.
|
|
244
230
|
} finally {
|
|
245
231
|
if (restore != null) removeTemporary(restore);
|
|
246
232
|
}
|
|
247
233
|
}
|
|
248
|
-
return unrestored;
|
|
249
234
|
}
|
|
250
235
|
|
|
251
236
|
/** @param {string} file */
|
|
@@ -340,22 +325,10 @@ export function applyWrites(plans) {
|
|
|
340
325
|
}
|
|
341
326
|
published.push(plan);
|
|
342
327
|
}
|
|
343
|
-
return () =>
|
|
344
|
-
rollbackWrites(published);
|
|
345
|
-
};
|
|
328
|
+
return () => rollbackWrites(published);
|
|
346
329
|
} catch (error) {
|
|
347
|
-
const
|
|
348
|
-
|
|
349
|
-
.map(plan => plan.temporary);
|
|
350
|
-
const unrestored = rollbackWrites(published);
|
|
351
|
-
if (error instanceof Error) {
|
|
352
|
-
if (unrestored.length > 0) {
|
|
353
|
-
error.message += ` Could not restore: ${unrestored.join(', ')}.`;
|
|
354
|
-
}
|
|
355
|
-
if (leftovers.length > 0) {
|
|
356
|
-
error.message += ` Could not remove temporary files: ${leftovers.join(', ')}.`;
|
|
357
|
-
}
|
|
358
|
-
}
|
|
330
|
+
for (const plan of staged) removeTemporary(plan.temporary);
|
|
331
|
+
rollbackWrites(published);
|
|
359
332
|
throw error;
|
|
360
333
|
}
|
|
361
334
|
}
|
|
@@ -24,10 +24,6 @@ import {
|
|
|
24
24
|
import {loadManifestObject} from '../../foundation/integrations/integrations.mjs';
|
|
25
25
|
import {themeDescriptorSource} from '../../foundation/integrations/theme-descriptor.mjs';
|
|
26
26
|
import {assertContributionVisible} from '../../foundation/integrations/contribution-inventory.mjs';
|
|
27
|
-
import {
|
|
28
|
-
themesCliProblem,
|
|
29
|
-
withDocsTreeCli,
|
|
30
|
-
} from '../../foundation/integrations/cli-requirement.mjs';
|
|
31
27
|
import {
|
|
32
28
|
applyWrites,
|
|
33
29
|
findPackageDir,
|
|
@@ -237,28 +233,11 @@ export async function integrationAddTheme(name, options = {}) {
|
|
|
237
233
|
createOnly: true,
|
|
238
234
|
},
|
|
239
235
|
];
|
|
240
|
-
|
|
236
|
+
const packageUpdate = packageJsonUpdate(
|
|
241
237
|
packageFile,
|
|
242
238
|
rootPath,
|
|
243
239
|
path.basename(manifestFile),
|
|
244
240
|
);
|
|
245
|
-
// A CLI older than the one that reads typed theme descriptors rejects the
|
|
246
|
-
// themes root and withholds the package's themes and docs. Declare the CLI
|
|
247
|
-
// that reads them as a peer, so an older one is flagged at install instead.
|
|
248
|
-
{
|
|
249
|
-
const expectedOriginal =
|
|
250
|
-
packageUpdate?.expectedOriginal ?? fs.readFileSync(packageFile);
|
|
251
|
-
const text = packageUpdate?.contents ?? expectedOriginal.toString('utf-8');
|
|
252
|
-
const current = JSON.parse(text);
|
|
253
|
-
if (themesCliProblem(current) != null) {
|
|
254
|
-
packageUpdate = {
|
|
255
|
-
contents:
|
|
256
|
-
JSON.stringify(withDocsTreeCli(current), null, 2) +
|
|
257
|
-
(text.endsWith('\n') ? '\n' : ''),
|
|
258
|
-
expectedOriginal,
|
|
259
|
-
};
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
241
|
if (packageUpdate != null) {
|
|
263
242
|
plans.push({
|
|
264
243
|
path: packageFile,
|
|
@@ -77,40 +77,6 @@ describe('integrationAddTheme', () => {
|
|
|
77
77
|
expect((await validateLocalIntegration(tmpDir)).issues).toEqual([]);
|
|
78
78
|
});
|
|
79
79
|
|
|
80
|
-
it('declares the optional CLI peer that reads typed theme descriptors', async () => {
|
|
81
|
-
setup({includeFiles: false});
|
|
82
|
-
const result = await integrationAddTheme('ocean', {cwd: tmpDir});
|
|
83
|
-
expect(result.data.files).toContain('package.json');
|
|
84
|
-
const pkg = JSON.parse(
|
|
85
|
-
fs.readFileSync(path.join(tmpDir, 'package.json'), 'utf-8'),
|
|
86
|
-
);
|
|
87
|
-
expect(pkg.peerDependencies).toEqual({'@astryxdesign/cli': '>=0.7.0'});
|
|
88
|
-
expect(pkg.peerDependenciesMeta).toEqual({
|
|
89
|
-
'@astryxdesign/cli': {optional: true},
|
|
90
|
-
});
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
it('keeps a CLI peer that already reads typed theme descriptors', async () => {
|
|
94
|
-
const pkg = {
|
|
95
|
-
name: '@acme/themes',
|
|
96
|
-
version: '1.0.0',
|
|
97
|
-
peerDependencies: {'@astryxdesign/cli': '^0.7.2'},
|
|
98
|
-
};
|
|
99
|
-
fs.writeFileSync(
|
|
100
|
-
path.join(tmpDir, 'package.json'),
|
|
101
|
-
`${JSON.stringify(pkg, null, 2)}\n`,
|
|
102
|
-
);
|
|
103
|
-
fs.writeFileSync(
|
|
104
|
-
path.join(tmpDir, 'astryx.integration.mjs'),
|
|
105
|
-
'export default {};\n',
|
|
106
|
-
);
|
|
107
|
-
const result = await integrationAddTheme('ocean', {cwd: tmpDir});
|
|
108
|
-
expect(result.data.files).not.toContain('package.json');
|
|
109
|
-
expect(
|
|
110
|
-
JSON.parse(fs.readFileSync(path.join(tmpDir, 'package.json'), 'utf-8')),
|
|
111
|
-
).toEqual(pkg);
|
|
112
|
-
});
|
|
113
|
-
|
|
114
80
|
it('dry-runs the identical receipt without writing anything', async () => {
|
|
115
81
|
setup();
|
|
116
82
|
const beforeManifest = fs.readFileSync(
|
|
@@ -368,11 +368,11 @@ export async function integrationDocConflicts(pkg, options = {}) {
|
|
|
368
368
|
// and placed guides this package adds to the docs tree, and every link in
|
|
369
369
|
// its docs (spec:AST-046, spec:AST-047).
|
|
370
370
|
if (errors.length === 0) {
|
|
371
|
-
for (const
|
|
371
|
+
for (const message of await packageDocsProblems(
|
|
372
372
|
/** @type {{name: string}} */ (resolved.integration),
|
|
373
373
|
discovered,
|
|
374
374
|
)) {
|
|
375
|
-
issues.push({code: 'invalid_doc_graph', severity, message});
|
|
375
|
+
issues.push({code: 'invalid_doc_graph', severity: 'warning', message});
|
|
376
376
|
}
|
|
377
377
|
|
|
378
378
|
// A reference block includes content rather than linking to it, so one
|