@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
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* `theme add` writes a theme as one transaction: when a later file fails to
|
|
5
|
-
* publish, every file it already replaced gets its previous bytes back and
|
|
6
|
-
* every file it created is removed. Publishing is forced to fail by wrapping
|
|
7
|
-
* the two calls that publish a staged file: `linkSync` for a new file and
|
|
8
|
-
* `renameSync` for a replacement.
|
|
9
|
-
*
|
|
10
|
-
* Separate file because vi.mock is hoisted and affects the whole module.
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest';
|
|
14
|
-
import * as os from 'node:os';
|
|
15
|
-
import * as path from 'node:path';
|
|
16
|
-
|
|
17
|
-
const failures = vi.hoisted(() => ({
|
|
18
|
-
/** Fail the Nth staged-file publish (1-based); 0 disables. */
|
|
19
|
-
publish: 0,
|
|
20
|
-
/** Also fail every rollback restore. */
|
|
21
|
-
restore: false,
|
|
22
|
-
count: 0,
|
|
23
|
-
}));
|
|
24
|
-
|
|
25
|
-
vi.mock('node:fs', async importOriginal => {
|
|
26
|
-
const actual = /** @type {typeof import('node:fs')} */ (
|
|
27
|
-
await importOriginal()
|
|
28
|
-
);
|
|
29
|
-
/** @param {string} source */
|
|
30
|
-
const isStaged = source => path.basename(String(source)).includes('.tmp');
|
|
31
|
-
/** @param {string} source */
|
|
32
|
-
const isRestore = source =>
|
|
33
|
-
path.basename(String(source)).includes('.restore-');
|
|
34
|
-
/** @param {string} source @param {string} op */
|
|
35
|
-
const maybeFail = (source, op) => {
|
|
36
|
-
if (isStaged(source) && failures.publish > 0) {
|
|
37
|
-
failures.count++;
|
|
38
|
-
if (failures.count === failures.publish) {
|
|
39
|
-
throw Object.assign(new Error(`EIO: forced ${op} failure`), {
|
|
40
|
-
code: 'EIO',
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
if (isRestore(source) && failures.restore) {
|
|
45
|
-
throw Object.assign(new Error(`EIO: forced restore failure`), {
|
|
46
|
-
code: 'EIO',
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
return {
|
|
51
|
-
...actual,
|
|
52
|
-
linkSync: vi.fn((source, destination) => {
|
|
53
|
-
maybeFail(source, 'link');
|
|
54
|
-
return actual.linkSync(source, destination);
|
|
55
|
-
}),
|
|
56
|
-
renameSync: vi.fn((source, destination) => {
|
|
57
|
-
maybeFail(source, 'rename');
|
|
58
|
-
return actual.renameSync(source, destination);
|
|
59
|
-
}),
|
|
60
|
-
};
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
const fs = await import('node:fs');
|
|
64
|
-
const {themeAdd} = await import('./add.mjs');
|
|
65
|
-
const {listThemes} = await import('../_adapter.mjs');
|
|
66
|
-
|
|
67
|
-
let tmpDir;
|
|
68
|
-
|
|
69
|
-
beforeEach(() => {
|
|
70
|
-
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'astryx-themeadd-rollback-'));
|
|
71
|
-
failures.publish = 0;
|
|
72
|
-
failures.restore = false;
|
|
73
|
-
failures.count = 0;
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
afterEach(() => {
|
|
77
|
-
failures.publish = 0;
|
|
78
|
-
failures.restore = false;
|
|
79
|
-
fs.rmSync(tmpDir, {recursive: true, force: true});
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
function stoneFiles() {
|
|
83
|
-
const theme = listThemes().find(entry => entry.slug === 'stone');
|
|
84
|
-
if (!theme) throw new Error('missing bundled theme stone');
|
|
85
|
-
expect(theme.files.length).toBeGreaterThanOrEqual(2);
|
|
86
|
-
return theme.files.map(name =>
|
|
87
|
-
path.join(tmpDir, 'src', 'themes', 'stone', name),
|
|
88
|
-
);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/** Entries staging or rollback left behind in the theme directory. */
|
|
92
|
-
function strays() {
|
|
93
|
-
const dir = path.join(tmpDir, 'src', 'themes', 'stone');
|
|
94
|
-
if (!fs.existsSync(dir)) return [];
|
|
95
|
-
return fs
|
|
96
|
-
.readdirSync(dir, {recursive: true})
|
|
97
|
-
.map(String)
|
|
98
|
-
.filter(name => name.includes('.tmp') || name.includes('.restore-'));
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
describe('themeAdd rolls back a partial write', () => {
|
|
102
|
-
it('removes every created file when the second publish fails', async () => {
|
|
103
|
-
const files = stoneFiles();
|
|
104
|
-
failures.publish = 2;
|
|
105
|
-
|
|
106
|
-
await expect(themeAdd('stone', {cwd: tmpDir})).rejects.toMatchObject({
|
|
107
|
-
code: 'ERR_WRITE_FAILED',
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
for (const file of files) expect(fs.existsSync(file)).toBe(false);
|
|
111
|
-
expect(strays()).toEqual([]);
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
it('restores every replaced byte when the second publish fails', async () => {
|
|
115
|
-
const files = stoneFiles();
|
|
116
|
-
fs.mkdirSync(path.dirname(files[0]), {recursive: true});
|
|
117
|
-
const before = Buffer.from([0x00, 0xff, 0x0a, 0x62, 0x65, 0x66]);
|
|
118
|
-
fs.writeFileSync(files[0], before);
|
|
119
|
-
failures.publish = 2;
|
|
120
|
-
|
|
121
|
-
await expect(
|
|
122
|
-
themeAdd('stone', {cwd: tmpDir, overwrite: true}),
|
|
123
|
-
).rejects.toMatchObject({code: 'ERR_WRITE_FAILED'});
|
|
124
|
-
|
|
125
|
-
expect(fs.readFileSync(files[0]).equals(before)).toBe(true);
|
|
126
|
-
for (const file of files.slice(1)) expect(fs.existsSync(file)).toBe(false);
|
|
127
|
-
expect(strays()).toEqual([]);
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
it('names a file it could not restore', async () => {
|
|
131
|
-
const files = stoneFiles();
|
|
132
|
-
fs.mkdirSync(path.dirname(files[0]), {recursive: true});
|
|
133
|
-
fs.writeFileSync(files[0], 'before\n');
|
|
134
|
-
failures.publish = 2;
|
|
135
|
-
failures.restore = true;
|
|
136
|
-
|
|
137
|
-
let error;
|
|
138
|
-
try {
|
|
139
|
-
await themeAdd('stone', {cwd: tmpDir, overwrite: true});
|
|
140
|
-
} catch (caught) {
|
|
141
|
-
error = caught;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
expect(error?.code).toBe('ERR_WRITE_FAILED');
|
|
145
|
-
expect(error?.message).toContain('Could not restore');
|
|
146
|
-
expect(error?.message).toContain(files[0]);
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
it('writes every file when nothing fails', async () => {
|
|
150
|
-
const files = stoneFiles();
|
|
151
|
-
|
|
152
|
-
const result = await themeAdd('stone', {cwd: tmpDir});
|
|
153
|
-
|
|
154
|
-
expect(result.type).toBe('theme.add');
|
|
155
|
-
for (const file of files) expect(fs.existsSync(file)).toBe(true);
|
|
156
|
-
expect(strays()).toEqual([]);
|
|
157
|
-
});
|
|
158
|
-
});
|
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* `theme build` writes its CSS, JS, and declarations as one transaction: when
|
|
5
|
-
* a later output fails to publish, every output it already replaced gets its
|
|
6
|
-
* previous bytes back and every output it created is removed. Publishing is
|
|
7
|
-
* forced to fail by wrapping the two calls that publish a staged file:
|
|
8
|
-
* `linkSync` for a new file and `renameSync` for a replacement.
|
|
9
|
-
*
|
|
10
|
-
* Separate file because vi.mock is hoisted and affects the whole module.
|
|
11
|
-
* `themeBuild` needs a built core; the `node` project's globalSetup builds it.
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest';
|
|
15
|
-
import * as os from 'node:os';
|
|
16
|
-
import * as path from 'node:path';
|
|
17
|
-
|
|
18
|
-
const failures = vi.hoisted(() => ({
|
|
19
|
-
/** Fail the Nth staged-file publish (1-based); 0 disables. */
|
|
20
|
-
publish: 0,
|
|
21
|
-
count: 0,
|
|
22
|
-
}));
|
|
23
|
-
|
|
24
|
-
vi.mock('node:fs', async importOriginal => {
|
|
25
|
-
const actual = /** @type {typeof import('node:fs')} */ (
|
|
26
|
-
await importOriginal()
|
|
27
|
-
);
|
|
28
|
-
/** @param {string} source @param {string} op */
|
|
29
|
-
const maybeFail = (source, op) => {
|
|
30
|
-
if (!path.basename(String(source)).includes('.tmp')) return;
|
|
31
|
-
if (failures.publish === 0) return;
|
|
32
|
-
failures.count++;
|
|
33
|
-
if (failures.count === failures.publish) {
|
|
34
|
-
throw Object.assign(new Error(`EIO: forced ${op} failure`), {
|
|
35
|
-
code: 'EIO',
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
return {
|
|
40
|
-
...actual,
|
|
41
|
-
linkSync: vi.fn((source, destination) => {
|
|
42
|
-
maybeFail(source, 'link');
|
|
43
|
-
return actual.linkSync(source, destination);
|
|
44
|
-
}),
|
|
45
|
-
renameSync: vi.fn((source, destination) => {
|
|
46
|
-
maybeFail(source, 'rename');
|
|
47
|
-
return actual.renameSync(source, destination);
|
|
48
|
-
}),
|
|
49
|
-
};
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
const fs = await import('node:fs');
|
|
53
|
-
const {themeBuild} = await import('./build.mjs');
|
|
54
|
-
|
|
55
|
-
vi.setConfig({testTimeout: 30000});
|
|
56
|
-
|
|
57
|
-
let tmpDir;
|
|
58
|
-
|
|
59
|
-
beforeEach(() => {
|
|
60
|
-
tmpDir = fs.mkdtempSync(
|
|
61
|
-
path.join(os.tmpdir(), 'astryx-theme-build-rollback-'),
|
|
62
|
-
);
|
|
63
|
-
failures.publish = 0;
|
|
64
|
-
failures.count = 0;
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
afterEach(() => {
|
|
68
|
-
failures.publish = 0;
|
|
69
|
-
fs.rmSync(tmpDir, {recursive: true, force: true});
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Write a source for the theme named `rollbacktheme`. Each call uses a new
|
|
74
|
-
* file so the loader cannot serve an earlier version from its cache.
|
|
75
|
-
* @param {string} file @param {string} background
|
|
76
|
-
*/
|
|
77
|
-
function writeTheme(file, background) {
|
|
78
|
-
fs.writeFileSync(
|
|
79
|
-
path.join(tmpDir, file),
|
|
80
|
-
`export default { name: 'rollbacktheme', tokens: { '--color-bg': '${background}' } };\n`,
|
|
81
|
-
);
|
|
82
|
-
return file;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
const OUTPUTS = ['rollbacktheme.css', 'rollbacktheme.js', 'rollbacktheme.d.ts'];
|
|
86
|
-
|
|
87
|
-
/** @returns {Map<string, Buffer | null>} */
|
|
88
|
-
function readOutputs() {
|
|
89
|
-
return new Map(
|
|
90
|
-
OUTPUTS.map(name => {
|
|
91
|
-
const file = path.join(tmpDir, name);
|
|
92
|
-
return [name, fs.existsSync(file) ? fs.readFileSync(file) : null];
|
|
93
|
-
}),
|
|
94
|
-
);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
function strays() {
|
|
98
|
-
return fs
|
|
99
|
-
.readdirSync(tmpDir)
|
|
100
|
-
.filter(name => name.includes('.tmp') || name.includes('.restore-'));
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
describe('themeBuild rolls back a partial write', () => {
|
|
104
|
-
it('removes every created output when the second publish fails', async () => {
|
|
105
|
-
const source = writeTheme('first.mjs', '#0a0a0a');
|
|
106
|
-
failures.publish = 2;
|
|
107
|
-
|
|
108
|
-
await expect(themeBuild(source, {}, {cwd: tmpDir})).rejects.toMatchObject({
|
|
109
|
-
code: 'ERR_WRITE_FAILED',
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
for (const bytes of readOutputs().values()) expect(bytes).toBeNull();
|
|
113
|
-
expect(strays()).toEqual([]);
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
it('restores every replaced output when the second publish fails', async () => {
|
|
117
|
-
const first = await themeBuild(
|
|
118
|
-
writeTheme('first.mjs', '#0a0a0a'),
|
|
119
|
-
{},
|
|
120
|
-
{cwd: tmpDir},
|
|
121
|
-
);
|
|
122
|
-
expect(first?.type).toBe('theme.build');
|
|
123
|
-
const before = readOutputs();
|
|
124
|
-
for (const bytes of before.values()) expect(bytes).not.toBeNull();
|
|
125
|
-
|
|
126
|
-
const next = writeTheme('next.mjs', '#fafafa');
|
|
127
|
-
failures.publish = 2;
|
|
128
|
-
await expect(themeBuild(next, {}, {cwd: tmpDir})).rejects.toMatchObject({
|
|
129
|
-
code: 'ERR_WRITE_FAILED',
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
const after = readOutputs();
|
|
133
|
-
for (const name of OUTPUTS) {
|
|
134
|
-
expect(
|
|
135
|
-
after.get(name)?.equals(/** @type {Buffer} */ (before.get(name))),
|
|
136
|
-
).toBe(true);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// The failed build really had different bytes to write.
|
|
140
|
-
failures.publish = 0;
|
|
141
|
-
await themeBuild(next, {}, {cwd: tmpDir});
|
|
142
|
-
const css = readOutputs().get('rollbacktheme.css');
|
|
143
|
-
expect(
|
|
144
|
-
css?.equals(/** @type {Buffer} */ (before.get('rollbacktheme.css'))),
|
|
145
|
-
).toBe(false);
|
|
146
|
-
expect(strays()).toEqual([]);
|
|
147
|
-
});
|
|
148
|
-
});
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @file The upgrade receipt counts a file once when a core codemod AND an
|
|
5
|
-
* integration codemod both change it: `filesChanged` is the union of the two
|
|
6
|
-
* runners' files, while `transformsApplied` adds their changes.
|
|
7
|
-
*
|
|
8
|
-
* Uses a real consumer under a repo-local temp dir (Vite blocks dynamic import
|
|
9
|
-
* of config and integration modules from /tmp), the real core registry, and an
|
|
10
|
-
* installed integration whose code codemod stamps the same file.
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
import {describe, it, expect, afterEach} from 'vitest';
|
|
14
|
-
import * as fs from 'node:fs';
|
|
15
|
-
import * as path from 'node:path';
|
|
16
|
-
import {upgrade} from '../upgrade.mjs';
|
|
17
|
-
import {
|
|
18
|
-
latestVersion,
|
|
19
|
-
versions,
|
|
20
|
-
getTransformsBetween,
|
|
21
|
-
} from '../../../assets/codemods/registry.mjs';
|
|
22
|
-
|
|
23
|
-
const SLOW = 60_000;
|
|
24
|
-
|
|
25
|
-
/** The registry version whose manifest ships the authoring migration. */
|
|
26
|
-
async function authoringTier() {
|
|
27
|
-
const all = await getTransformsBetween('0.0.0', latestVersion);
|
|
28
|
-
const tier = all.find(({transforms}) =>
|
|
29
|
-
transforms.some(t => t.name === 'migrate-authoring-imports'),
|
|
30
|
-
);
|
|
31
|
-
if (!tier) throw new Error('no registry version ships the authoring migration');
|
|
32
|
-
return tier.version;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* A consumer with installed core at the registry's latest version and one
|
|
37
|
-
* old-surface file that the core authoring codemods rewrite.
|
|
38
|
-
* @param {string} dir
|
|
39
|
-
* @param {{integrationCodemod: boolean}} options
|
|
40
|
-
*/
|
|
41
|
-
function seed(dir, {integrationCodemod}) {
|
|
42
|
-
fs.writeFileSync(
|
|
43
|
-
path.join(dir, 'package.json'),
|
|
44
|
-
JSON.stringify({name: 'consumer', version: '1.0.0'}),
|
|
45
|
-
);
|
|
46
|
-
const core = path.join(dir, 'node_modules', '@astryxdesign', 'core');
|
|
47
|
-
fs.mkdirSync(core, {recursive: true});
|
|
48
|
-
fs.writeFileSync(
|
|
49
|
-
path.join(core, 'package.json'),
|
|
50
|
-
JSON.stringify({name: '@astryxdesign/core', version: latestVersion}),
|
|
51
|
-
);
|
|
52
|
-
fs.mkdirSync(path.join(dir, 'src'), {recursive: true});
|
|
53
|
-
fs.writeFileSync(
|
|
54
|
-
path.join(dir, 'src', 'Button.doc.mjs'),
|
|
55
|
-
[
|
|
56
|
-
"import {createComponentDoc} from '@astryxdesign/core/authoring';",
|
|
57
|
-
"export default createComponentDoc({name: 'Button', props: []});",
|
|
58
|
-
'',
|
|
59
|
-
].join('\n'),
|
|
60
|
-
);
|
|
61
|
-
if (!integrationCodemod) return;
|
|
62
|
-
fs.writeFileSync(
|
|
63
|
-
path.join(dir, 'astryx.config.mjs'),
|
|
64
|
-
"export default {integrations: ['@acme/widgets']};\n",
|
|
65
|
-
);
|
|
66
|
-
const pkg = path.join(dir, 'node_modules', '@acme', 'widgets');
|
|
67
|
-
fs.mkdirSync(path.join(pkg, 'codemods', latestVersion), {recursive: true});
|
|
68
|
-
fs.writeFileSync(
|
|
69
|
-
path.join(pkg, 'package.json'),
|
|
70
|
-
JSON.stringify({name: '@acme/widgets', version: '1.0.0'}),
|
|
71
|
-
);
|
|
72
|
-
fs.writeFileSync(
|
|
73
|
-
path.join(pkg, 'astryx.integration.mjs'),
|
|
74
|
-
"export default {codemods: './codemods'};\n",
|
|
75
|
-
);
|
|
76
|
-
fs.writeFileSync(
|
|
77
|
-
path.join(pkg, 'codemods', latestVersion, 'acme-stamp.mjs'),
|
|
78
|
-
"export default {type: 'code', title: 'Stamp', transform: file => (file.source.includes('// acme') ? null : `${file.source}// acme\\n`)};\n",
|
|
79
|
-
);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
describe('upgrade receipt — filesChanged across core and integration codemods', () => {
|
|
83
|
-
/** @type {string[]} */
|
|
84
|
-
const dirs = [];
|
|
85
|
-
afterEach(() => {
|
|
86
|
-
for (const dir of dirs.splice(0)) fs.rmSync(dir, {recursive: true, force: true});
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
/** @param {{integrationCodemod: boolean}} options */
|
|
90
|
-
async function run(options) {
|
|
91
|
-
const dir = fs.mkdtempSync(path.join(process.cwd(), '.astryx-files-changed-'));
|
|
92
|
-
dirs.push(dir);
|
|
93
|
-
seed(dir, options);
|
|
94
|
-
const tier = await authoringTier();
|
|
95
|
-
const from = versions[versions.indexOf(tier) - 1];
|
|
96
|
-
const res = await upgrade({from, path: 'src'}, {cwd: dir});
|
|
97
|
-
expect(res.type).toBe('upgrade.run');
|
|
98
|
-
return res.data;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
it('counts a file changed by both a core and an integration codemod once', async () => {
|
|
102
|
-
const coreOnly = await run({integrationCodemod: false});
|
|
103
|
-
expect(coreOnly.filesChanged).toBe(1);
|
|
104
|
-
expect(coreOnly.transformsApplied).toBeGreaterThan(0);
|
|
105
|
-
|
|
106
|
-
const both = await run({integrationCodemod: true});
|
|
107
|
-
expect(both.integrations).toEqual(['@acme/widgets']);
|
|
108
|
-
expect(both.filesChanged).toBe(1);
|
|
109
|
-
expect(both.transformsApplied).toBe(coreOnly.transformsApplied + 1);
|
|
110
|
-
}, SLOW);
|
|
111
|
-
});
|
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @file `filesChanged` counts FILES, not (codemod, file) pairs.
|
|
5
|
-
*
|
|
6
|
-
* One source file that four codemods each changed was reported as four files
|
|
7
|
-
* changed — the total was incremented once per transform per file, so it
|
|
8
|
-
* equalled `transformsApplied` in every run and the documented meaning of the
|
|
9
|
-
* field ("Total files changed") was never true. The two numbers answer
|
|
10
|
-
* different questions and both are in the receipt.
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
import {describe, it, expect, beforeEach, afterEach} from 'vitest';
|
|
14
|
-
import * as fs from 'node:fs';
|
|
15
|
-
import * as os from 'node:os';
|
|
16
|
-
import * as path from 'node:path';
|
|
17
|
-
import jscodeshift from 'jscodeshift';
|
|
18
|
-
import {runCodemods} from './runner.mjs';
|
|
19
|
-
import {runIntegrationCodemods} from './integration-runner.mjs';
|
|
20
|
-
|
|
21
|
-
let dir;
|
|
22
|
-
|
|
23
|
-
beforeEach(() => {
|
|
24
|
-
dir = fs.mkdtempSync(path.join(os.tmpdir(), 'astryx-file-count-'));
|
|
25
|
-
});
|
|
26
|
-
afterEach(() => fs.rmSync(dir, {recursive: true, force: true}));
|
|
27
|
-
|
|
28
|
-
/** A transform that rewrites one distinctive token, so several can stack. */
|
|
29
|
-
const renaming = (from, to) => (file) =>
|
|
30
|
-
file.source.includes(from) ? file.source.split(from).join(to) : null;
|
|
31
|
-
|
|
32
|
-
/** @param {string} name @param {string[]} contents */
|
|
33
|
-
function writeSources(...contents) {
|
|
34
|
-
return contents.map((content, i) => {
|
|
35
|
-
const file = path.join(dir, `file${i}.ts`);
|
|
36
|
-
fs.writeFileSync(file, content);
|
|
37
|
-
return file;
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
describe('core codemod runner — filesChanged counts files', () => {
|
|
42
|
-
it('reports 1 file for one file changed by four codemods', async () => {
|
|
43
|
-
writeSources('const a = ONE + TWO + THREE + FOUR;\n');
|
|
44
|
-
|
|
45
|
-
const result = await runCodemods(
|
|
46
|
-
[
|
|
47
|
-
{
|
|
48
|
-
version: '0.0.2',
|
|
49
|
-
transforms: [
|
|
50
|
-
{name: 'one', transform: renaming('ONE', '1'), meta: {title: 'one'}},
|
|
51
|
-
{name: 'two', transform: renaming('TWO', '2'), meta: {title: 'two'}},
|
|
52
|
-
{name: 'three', transform: renaming('THREE', '3'), meta: {title: 'three'}},
|
|
53
|
-
{name: 'four', transform: renaming('FOUR', '4'), meta: {title: 'four'}},
|
|
54
|
-
],
|
|
55
|
-
},
|
|
56
|
-
],
|
|
57
|
-
{apply: true, path: dir, root: dir, codemod: undefined, skipCodemods: new Set(), silent: true},
|
|
58
|
-
);
|
|
59
|
-
|
|
60
|
-
expect(result.totalTransformsApplied).toBe(4);
|
|
61
|
-
expect(result.totalFilesChanged).toBe(1);
|
|
62
|
-
expect(new Set(result.changedFiles).size).toBe(1);
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
it('still counts two files as two', async () => {
|
|
66
|
-
writeSources('const a = ONE;\n', 'const b = ONE;\n');
|
|
67
|
-
|
|
68
|
-
const result = await runCodemods(
|
|
69
|
-
[
|
|
70
|
-
{
|
|
71
|
-
version: '0.0.2',
|
|
72
|
-
transforms: [
|
|
73
|
-
{name: 'one', transform: renaming('ONE', '1'), meta: {title: 'one'}},
|
|
74
|
-
],
|
|
75
|
-
},
|
|
76
|
-
],
|
|
77
|
-
{apply: true, path: dir, root: dir, codemod: undefined, skipCodemods: new Set(), silent: true},
|
|
78
|
-
);
|
|
79
|
-
|
|
80
|
-
expect(result.totalTransformsApplied).toBe(2);
|
|
81
|
-
expect(result.totalFilesChanged).toBe(2);
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
it('reports 0 when nothing matched', async () => {
|
|
85
|
-
writeSources('const a = 1;\n');
|
|
86
|
-
|
|
87
|
-
const result = await runCodemods(
|
|
88
|
-
[
|
|
89
|
-
{
|
|
90
|
-
version: '0.0.2',
|
|
91
|
-
transforms: [
|
|
92
|
-
{name: 'one', transform: renaming('ONE', '1'), meta: {title: 'one'}},
|
|
93
|
-
],
|
|
94
|
-
},
|
|
95
|
-
],
|
|
96
|
-
{apply: true, path: dir, root: dir, codemod: undefined, skipCodemods: new Set(), silent: true},
|
|
97
|
-
);
|
|
98
|
-
|
|
99
|
-
expect(result.totalFilesChanged).toBe(0);
|
|
100
|
-
expect(result.totalTransformsApplied).toBe(0);
|
|
101
|
-
});
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
describe('integration codemod runner — filesChanged counts files', () => {
|
|
105
|
-
it('reports 1 file for one file changed by three integration codemods', () => {
|
|
106
|
-
writeSources('const a = ONE + TWO + THREE;\n');
|
|
107
|
-
|
|
108
|
-
const entry = (id, from, to) => ({
|
|
109
|
-
id,
|
|
110
|
-
package: '@acme/widgets',
|
|
111
|
-
type: 'code',
|
|
112
|
-
codemod: {title: id, transform: renaming(from, to)},
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
const result = runIntegrationCodemods(
|
|
116
|
-
[
|
|
117
|
-
{
|
|
118
|
-
version: '1.0.0',
|
|
119
|
-
codemods: [
|
|
120
|
-
entry('one', 'ONE', '1'),
|
|
121
|
-
entry('two', 'TWO', '2'),
|
|
122
|
-
entry('three', 'THREE', '3'),
|
|
123
|
-
],
|
|
124
|
-
},
|
|
125
|
-
],
|
|
126
|
-
{apply: true, path: dir, root: dir, skipCodemods: new Set(), jscodeshift, silent: true},
|
|
127
|
-
);
|
|
128
|
-
|
|
129
|
-
expect(result.totalTransformsApplied).toBe(3);
|
|
130
|
-
expect(result.totalFilesChanged).toBe(1);
|
|
131
|
-
expect(new Set(result.changedFiles).size).toBe(1);
|
|
132
|
-
});
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
describe('core codemod runner — a project codemod', () => {
|
|
136
|
-
it('counts every file it writes, and one change', async () => {
|
|
137
|
-
const result = await runCodemods(
|
|
138
|
-
[
|
|
139
|
-
{
|
|
140
|
-
version: '0.0.2',
|
|
141
|
-
transforms: [
|
|
142
|
-
{
|
|
143
|
-
name: 'project-plan',
|
|
144
|
-
meta: {title: 'project plan', codemodType: 'project'},
|
|
145
|
-
transform: async root => ({
|
|
146
|
-
writes: [
|
|
147
|
-
{path: path.join(root, 'a.ts'), contents: 'a\n'},
|
|
148
|
-
{path: path.join(root, 'b.ts'), contents: 'b\n'},
|
|
149
|
-
],
|
|
150
|
-
deletes: [],
|
|
151
|
-
problems: [],
|
|
152
|
-
}),
|
|
153
|
-
},
|
|
154
|
-
],
|
|
155
|
-
},
|
|
156
|
-
],
|
|
157
|
-
{apply: true, path: dir, root: dir, codemod: undefined, skipCodemods: new Set(), silent: true},
|
|
158
|
-
);
|
|
159
|
-
|
|
160
|
-
expect(result.totalFilesChanged).toBe(2);
|
|
161
|
-
expect(result.totalTransformsApplied).toBe(1);
|
|
162
|
-
});
|
|
163
|
-
});
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @file `astryx docs cli/integrations/components/add-a-component`: choose a
|
|
5
|
-
* component name and generate its first source and doc files.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
/** @type {import('@astryxdesign/cli/authoring').ReferenceDoc} */
|
|
9
|
-
export const docs = {
|
|
10
|
-
type: 'generic',
|
|
11
|
-
name: 'add-a-component',
|
|
12
|
-
placement: {parent: 'namespace:components', slot: 'guides', order: 10},
|
|
13
|
-
title: 'Add a component',
|
|
14
|
-
category: 'guide',
|
|
15
|
-
description:
|
|
16
|
-
'Choose a stable component name and generate its source, doc, package export, and integration entry.',
|
|
17
|
-
sections: [
|
|
18
|
-
{
|
|
19
|
-
id: 'pick-a-component-name',
|
|
20
|
-
title: 'Pick a component name',
|
|
21
|
-
content: [
|
|
22
|
-
{
|
|
23
|
-
type: 'prose',
|
|
24
|
-
text: 'Choose a unique PascalCase name, such as `AcmeCarousel`. The name is the component\'s public export and CLI identity, so keep it stable. Use `displayName` when you only want to change the label people read.',
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
type: 'list',
|
|
28
|
-
style: 'unordered',
|
|
29
|
-
items: [
|
|
30
|
-
'Prefer a name that describes the component\'s purpose in your product.',
|
|
31
|
-
'Avoid a Core component name unless you are deliberately replacing that component.',
|
|
32
|
-
'If replacement is truly required, read {@link generic:replace-a-core-component}.',
|
|
33
|
-
],
|
|
34
|
-
},
|
|
35
|
-
],
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
id: 'run-the-add-command',
|
|
39
|
-
title: 'Run the add command',
|
|
40
|
-
content: [
|
|
41
|
-
{
|
|
42
|
-
type: 'prose',
|
|
43
|
-
text: 'Run `integration add component` in your package with the name. It writes the component, its doc file, and the public import apps use.',
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
type: 'code',
|
|
47
|
-
lang: 'bash',
|
|
48
|
-
code: 'npx astryx integration add component AcmeCarousel',
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
type: 'code',
|
|
52
|
-
lang: 'text',
|
|
53
|
-
code: `component contribution added
|
|
54
|
-
|
|
55
|
-
[ok] AcmeCarousel
|
|
56
|
-
|
|
57
|
-
Declare component root ./components in astryx.integration.mjs.
|
|
58
|
-
|
|
59
|
-
- components/AcmeCarousel.doc.mjs
|
|
60
|
-
- components/AcmeCarousel.tsx
|
|
61
|
-
- package.json
|
|
62
|
-
- astryx.integration.mjs`,
|
|
63
|
-
},
|
|
64
|
-
{
|
|
65
|
-
type: 'prose',
|
|
66
|
-
text: '`integration add` starts with one source export and one single-component `.doc.mjs`. Keep that shape for one public component. If the source exposes a family, choose the correct shape in {@link namespace:describe-the-component}.',
|
|
67
|
-
},
|
|
68
|
-
{
|
|
69
|
-
type: 'prose',
|
|
70
|
-
text: 'Add never overwrites a file, and `--dry-run` shows what it would write. Component commands read Core, so install `@astryxdesign/core` in the package first ({@link generic:quick-start}).',
|
|
71
|
-
},
|
|
72
|
-
],
|
|
73
|
-
},
|
|
74
|
-
],
|
|
75
|
-
};
|