@astryxdesign/cli 0.6.3-canary.f22695a → 0.6.3
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 +1 -2
- package/api/build/build.type.d.mts +2 -2
- package/api/build/build.type.mjs +2 -2
- package/api/component/component.type.d.mts +6 -6
- package/api/component/component.type.mjs +19 -19
- package/api/discover/discover.type.d.mts +4 -4
- package/api/discover/discover.type.mjs +10 -10
- package/api/docs/_adapter.d.mts +24 -37
- package/api/docs/_adapter.mjs +83 -169
- package/api/docs/detail/detail.mjs +63 -14
- package/api/docs/detail/section/section.d.mts +1 -1
- package/api/docs/detail/section/section.mjs +20 -44
- package/api/docs/detail/section/section.test.mjs +0 -41
- package/api/docs/docs.d.mts +2 -7
- package/api/docs/docs.doc.mjs +10 -27
- package/api/docs/docs.mjs +9 -16
- package/api/docs/docs.test.mjs +0 -6
- package/api/docs/docs.type.d.mts +3 -40
- package/api/docs/docs.type.mjs +8 -36
- package/api/docs/integrationDocs.test.mjs +0 -106
- package/api/doctor/doctor.d.mts +0 -48
- package/api/doctor/doctor.mjs +0 -232
- package/api/doctor/doctor.test.mjs +0 -196
- package/api/hook/hook.type.d.mts +3 -3
- package/api/hook/hook.type.mjs +11 -11
- package/api/hook/list/list.d.mts +1 -1
- package/api/integration/add-contribution.mjs +3 -5
- package/api/integration/add-contribution.test.mjs +4 -4
- package/api/integration/integration-authoring.type.d.mts +1 -1
- package/api/integration/pack-check.mjs +7 -49
- package/api/integration/pack-check.test.mjs +0 -249
- package/api/search/search.d.mts +1 -1
- package/api/search/search.mjs +5 -5
- package/api/search/search.type.d.mts +2 -2
- package/api/search/search.type.mjs +1 -1
- package/api/swizzle/swizzle.type.d.mts +2 -2
- package/api/swizzle/swizzle.type.mjs +2 -2
- package/api/template/template.d.mts +1 -1
- package/api/template/template.type.d.mts +6 -6
- package/api/template/template.type.mjs +12 -12
- package/api/theme/build/build.mjs +6 -20
- package/api/theme/build/build.test.mjs +0 -127
- package/api/theme/palette/generate/generate.mjs +1 -1
- package/api/theme/palette/generate/generator.d.mts +13 -10
- package/api/theme/palette/generate/generator.mjs +3 -7
- package/api/theme/theme.type.d.mts +11 -170
- package/api/theme/theme.type.mjs +27 -94
- package/api/upgrade/_adapter.mjs +5 -71
- package/api/upgrade/upgrade.doc.mjs +3 -4
- package/api/upgrade/upgrade.type.d.mts +5 -5
- package/api/upgrade/upgrade.type.mjs +11 -11
- package/assets/codemods/integration-discovery.mjs +2 -40
- package/assets/codemods/integration-discovery.test.mjs +0 -58
- package/assets/codemods/transforms/v0.3.0/__tests__/unwrap-authoring-factories.test.mjs +5 -27
- package/assets/codemods/transforms/v0.3.0/unwrap-authoring-factories.mjs +5 -20
- package/assets/docs/README.md +0 -9
- package/assets/docs/cli-integrations.doc.mjs +15 -86
- package/assets/docs/styling-libraries.doc.mjs +1 -1
- package/assets/docs/working-with-ai.doc.mjs +1 -1
- package/assets/templates/blocks/components/Toolbar/ToolbarTableFilter.doc.mjs +3 -19
- package/assets/templates/blocks/components/Toolbar/ToolbarTableFilter.tsx +65 -383
- package/authoring/_shared/contract.ts +0 -22
- package/authoring/codemod/codemod.doc.mjs +1 -6
- package/authoring/codemod/parse.d.mts +8 -8
- package/authoring/codemod/parse.mjs +6 -8
- package/authoring/config/parse.d.mts +13 -13
- package/authoring/config/parse.mjs +8 -8
- package/authoring/config/type.ts +3 -3
- package/authoring/debug/parse.d.mts +5 -5
- package/authoring/debug/parse.mjs +3 -3
- package/authoring/doctypes/_schema.d.mts +23 -788
- package/authoring/doctypes/_schema.mjs +39 -492
- package/authoring/doctypes/base/type.ts +0 -40
- package/authoring/doctypes/command/command.doc.mjs +2 -3
- package/authoring/doctypes/command/parse.d.mts +2 -2
- package/authoring/doctypes/command/parse.mjs +1 -1
- package/authoring/doctypes/command/type.ts +2 -3
- package/authoring/doctypes/component/component.doc.mjs +3 -6
- package/authoring/doctypes/component/parse.d.mts +2 -2
- package/authoring/doctypes/component/parse.mjs +1 -1
- package/authoring/doctypes/component/type.ts +3 -4
- package/authoring/doctypes/enum/parse.d.mts +2 -2
- package/authoring/doctypes/enum/parse.mjs +1 -1
- package/authoring/doctypes/enum/type.ts +1 -3
- package/authoring/doctypes/function/function.doc.mjs +0 -4
- package/authoring/doctypes/function/parse.d.mts +2 -2
- package/authoring/doctypes/function/parse.mjs +1 -1
- package/authoring/doctypes/function/type.ts +2 -6
- package/authoring/doctypes/hook/hook.doc.mjs +0 -4
- package/authoring/doctypes/hook/parse.d.mts +2 -2
- package/authoring/doctypes/hook/parse.mjs +1 -1
- package/authoring/doctypes/hook/type.ts +2 -3
- package/authoring/doctypes/legacy.d.mts +6 -8
- package/authoring/doctypes/legacy.mjs +4 -5
- package/authoring/doctypes/parse.d.mts +18 -20
- package/authoring/doctypes/parse.mjs +10 -16
- package/authoring/doctypes/parse.test.mjs +3 -77
- package/authoring/doctypes/reference/parse.d.mts +2 -2
- package/authoring/doctypes/reference/parse.mjs +5 -8
- package/authoring/doctypes/reference/reference.doc.mjs +4 -17
- package/authoring/doctypes/reference/type.ts +5 -51
- package/authoring/doctypes/schema/parse.d.mts +2 -2
- package/authoring/doctypes/schema/parse.mjs +1 -1
- package/authoring/doctypes/schema/type.ts +2 -3
- package/authoring/doctypes/template/parse.d.mts +1 -92
- package/authoring/doctypes/template/parse.mjs +2 -36
- package/authoring/doctypes/template/parse.test.mjs +2 -8
- package/authoring/doctypes/template/template.doc.mjs +0 -4
- package/authoring/doctypes/template/type.ts +2 -5
- package/authoring/doctypes/types.ts +9 -10
- package/authoring/gap-report/parse.d.mts +10 -10
- package/authoring/gap-report/parse.mjs +6 -6
- package/authoring/gap-report/type.ts +1 -1
- package/authoring/index.d.mts +0 -1
- package/authoring/index.d.ts +17 -49
- package/authoring/index.mjs +0 -1
- package/authoring/integration/integration.doc.mjs +6 -13
- package/authoring/integration/parse.d.mts +2 -2
- package/authoring/integration/parse.mjs +1 -1
- package/authoring/integration/parse.test.mjs +1 -10
- package/authoring/integration/schema.d.mts +4 -6
- package/authoring/integration/schema.mjs +3 -9
- package/authoring/integration/type.ts +6 -23
- package/authoring/shadcn/receipt.d.mts +6 -6
- package/clients/cli/commands/docs.doc.mjs +3 -13
- package/clients/cli/commands/docs.mjs +21 -121
- package/clients/cli/commands/docs.test.mjs +0 -88
- package/clients/cli/commands/integration-authoring.test.mjs +9 -13
- package/clients/cli/commands/theme-palette-generate.doc.mjs +4 -8
- package/clients/cli/commands/upgrade.doc.mjs +2 -2
- package/clients/cli/formatters/index.mjs +1 -162
- package/clients/cli/formatters/index.test.mjs +0 -91
- package/clients/cli/lib/manifest.mjs +2 -7
- package/foundation/config/project.mjs +6 -21
- package/foundation/discovery/component-discovery.d.mts +1 -1
- package/foundation/discovery/component-discovery.mjs +1 -2
- package/foundation/discovery/docs-discovery.d.mts +4 -11
- package/foundation/discovery/docs-discovery.mjs +88 -208
- package/foundation/discovery/docs-discovery.test.mjs +13 -279
- package/foundation/discovery/template-adapter.mjs +1 -2
- package/foundation/integrations/autolink.mjs +5 -12
- package/foundation/integrations/integration-warnings.mjs +0 -6
- package/foundation/integrations/integrations.d.mts +2 -46
- package/foundation/integrations/integrations.mjs +8 -167
- package/foundation/integrations/integrations.test.mjs +1 -384
- package/foundation/integrations/validate-contributions.d.mts +0 -2
- package/foundation/integrations/validate-contributions.mjs +0 -10
- package/foundation/response/json-contract.test.mjs +17 -46
- package/foundation/response/response-types.doc.mjs +1 -6
- package/package.json +11 -9
- package/api/docs/compiled-topics.test.mjs +0 -78
- package/api/docs/index/index.d.mts +0 -18
- package/api/docs/index/index.mjs +0 -32
- package/api/docs/index/index.test.mjs +0 -62
- package/api/upgrade/project-context.test.mjs +0 -272
- package/assets/docs/authoring.doc.mjs +0 -14
- package/assets/templates/blocks/components/Timer/TimerFormats.doc.mjs +0 -14
- package/assets/templates/blocks/components/Timer/TimerFormats.tsx +0 -34
- package/assets/templates/blocks/components/Timer/TimerInline.doc.mjs +0 -14
- package/assets/templates/blocks/components/Timer/TimerInline.tsx +0 -14
- package/assets/templates/blocks/components/Timer/TimerShowcase.doc.mjs +0 -13
- package/assets/templates/blocks/components/Timer/TimerShowcase.tsx +0 -47
- package/assets/templates/blocks/components/Timer/TimerTypography.doc.mjs +0 -14
- package/assets/templates/blocks/components/Timer/TimerTypography.tsx +0 -31
- package/authoring/doctypes/base/graph-fields.doc.d.mts +0 -9
- package/authoring/doctypes/base/graph-fields.doc.mjs +0 -62
- package/authoring/doctypes/load-contract.test.mjs +0 -207
- package/authoring/doctypes/namespace/namespace.doc.d.mts +0 -9
- package/authoring/doctypes/namespace/namespace.doc.mjs +0 -132
- package/authoring/doctypes/namespace/parse.d.mts +0 -12
- package/authoring/doctypes/namespace/parse.mjs +0 -25
- package/authoring/doctypes/namespace/parse.test.mjs +0 -165
- package/authoring/doctypes/namespace/type.ts +0 -71
- package/authoring/identity/identity.doc.d.mts +0 -9
- package/authoring/identity/identity.doc.mjs +0 -61
- package/authoring/identity/type.ts +0 -132
- package/foundation/discovery/authoring-self-docs.d.mts +0 -69
- package/foundation/discovery/authoring-self-docs.mjs +0 -214
- package/foundation/discovery/authoring-self-docs.test.mjs +0 -154
- package/foundation/discovery/docs-output-budget.d.mts +0 -28
- package/foundation/discovery/docs-output-budget.mjs +0 -50
- package/foundation/discovery/docs-section-key.d.mts +0 -98
- package/foundation/discovery/docs-section-key.mjs +0 -221
- package/foundation/discovery/docs-section-key.test.mjs +0 -224
- package/foundation/doc-compiler/compile.d.mts +0 -162
- package/foundation/doc-compiler/compile.mjs +0 -262
- package/foundation/doc-compiler/doc-compiler.test.mjs +0 -687
- package/foundation/doc-compiler/ir.d.mts +0 -9
- package/foundation/doc-compiler/ir.mjs +0 -287
- package/foundation/doc-compiler/lenses.d.mts +0 -33
- package/foundation/doc-compiler/lenses.mjs +0 -127
- package/foundation/identity/provider-identity.d.mts +0 -90
- package/foundation/identity/provider-identity.mjs +0 -320
- package/foundation/identity/provider-identity.test.mjs +0 -254
- package/foundation/identity/providers.d.mts +0 -7
- package/foundation/identity/providers.mjs +0 -16
- package/foundation/integrations/provider-conflicts.test.mjs +0 -125
package/api/theme/theme.type.mjs
CHANGED
|
@@ -6,23 +6,23 @@
|
|
|
6
6
|
* directly (functions own their types); the public `@astryxdesign/cli/api`
|
|
7
7
|
* surface re-exports them via types/theme.d.ts, so consumers see the same names.
|
|
8
8
|
*
|
|
9
|
-
* Invocation
|
|
9
|
+
* Invocation -> type discriminator
|
|
10
10
|
* ------------------------------------------------------------------
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* (file not found / parse error)
|
|
11
|
+
* xds --json theme build <file> -> theme.build
|
|
12
|
+
* xds --json theme build <file> --check -> theme.build.check
|
|
13
|
+
* xds --json theme build <a> <b> … -> theme.build.batch
|
|
14
|
+
* xds --json theme list -> theme.list
|
|
15
|
+
* xds --json theme add <slug> -> theme.add
|
|
16
|
+
* xds --json theme template -> theme.template
|
|
17
|
+
* xds --json theme targets [filter] -> theme.targets
|
|
18
|
+
* xds --json theme palette generate <file> -> theme.palette.generate
|
|
19
|
+
* (file not found / parse error) -> CLIError
|
|
20
20
|
*
|
|
21
21
|
* @position api — colocated typedefs for api/theme/{theme,build,add,list,template,targets,_adapter}
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
|
-
*
|
|
25
|
+
* xds --json theme build <file>
|
|
26
26
|
* @typedef {object} ThemeBuildResponse
|
|
27
27
|
* @property {'theme.build'} type
|
|
28
28
|
* `warnings` are defects the theme author should fix. `notices` are advisories
|
|
@@ -32,14 +32,14 @@
|
|
|
32
32
|
*/
|
|
33
33
|
|
|
34
34
|
/**
|
|
35
|
-
*
|
|
35
|
+
* xds --json theme build <file> --check
|
|
36
36
|
* @typedef {object} ThemeBuildCheckResponse
|
|
37
37
|
* @property {'theme.build.check'} type
|
|
38
38
|
* @property {{name: string, upToDate: boolean, stale: Array<{path: string, reason: 'missing' | 'outdated'}>, checked: string[]}} data
|
|
39
39
|
*/
|
|
40
40
|
|
|
41
41
|
/**
|
|
42
|
-
*
|
|
42
|
+
* xds --json theme build <a> <b> … — several themes in one invocation. Each
|
|
43
43
|
* result carries the file as it was passed and the receipt a single-file build
|
|
44
44
|
* would have returned (null when that theme produced no CSS). One file still
|
|
45
45
|
* returns the bare theme.build / theme.build.check envelope.
|
|
@@ -59,21 +59,21 @@
|
|
|
59
59
|
*/
|
|
60
60
|
|
|
61
61
|
/**
|
|
62
|
-
*
|
|
62
|
+
* xds --json theme list
|
|
63
63
|
* @typedef {object} ThemeListResponse
|
|
64
64
|
* @property {'theme.list'} type
|
|
65
65
|
* @property {ThemeListEntry[]} data
|
|
66
66
|
*/
|
|
67
67
|
|
|
68
68
|
/**
|
|
69
|
-
*
|
|
69
|
+
* xds --json theme add <slug>
|
|
70
70
|
* @typedef {object} ThemeAddResponse
|
|
71
71
|
* @property {'theme.add'} type
|
|
72
72
|
* @property {{slug: string, displayName: string, maintained: boolean, package: string, outputDir: string, entry: string, exportName: string, files: string[]}} data
|
|
73
73
|
*/
|
|
74
74
|
|
|
75
75
|
/**
|
|
76
|
-
*
|
|
76
|
+
* xds --json theme template
|
|
77
77
|
* `written: false` with `reason: 'exists'` is a success: the command is safe to
|
|
78
78
|
* re-run, and an edited template is the consumer's file to keep.
|
|
79
79
|
* @typedef {object} ThemeTemplateResponse
|
|
@@ -95,19 +95,19 @@
|
|
|
95
95
|
*/
|
|
96
96
|
|
|
97
97
|
/**
|
|
98
|
-
*
|
|
98
|
+
* xds --json theme targets [filter]
|
|
99
99
|
* @typedef {object} ThemeTargetsResponse
|
|
100
100
|
* @property {'theme.targets'} type
|
|
101
101
|
* @property {{filter: string | null, componentCount: number, targets: ThemeTargetEntry[]}} data
|
|
102
102
|
*/
|
|
103
103
|
|
|
104
104
|
/**
|
|
105
|
-
* A
|
|
105
|
+
* A generated palette candidate. The palette is still subject to author review
|
|
106
|
+
* and is not connected to runtime theme values.
|
|
106
107
|
* @typedef {object} TonalPaletteAnchor
|
|
107
108
|
* @property {'light' | 'dark'} mode Mode containing the anchored stop.
|
|
108
109
|
* @property {number} stop Existing requested stop where the anchor applies.
|
|
109
|
-
* @property {string} color
|
|
110
|
-
* digits, with or without `#`; the generator normalizes it.
|
|
110
|
+
* @property {string} color
|
|
111
111
|
* @property {'exact' | 'bounded' | 'flexible'} policy `exact` preserves the
|
|
112
112
|
* chosen color at that stop; `bounded` permits adjustment within `maxDeltaE`;
|
|
113
113
|
* `flexible` treats the color as guidance and blends toward it.
|
|
@@ -116,16 +116,12 @@
|
|
|
116
116
|
*/
|
|
117
117
|
|
|
118
118
|
/**
|
|
119
|
-
* One requested family: a seed color and the constraints applied to its ramp.
|
|
120
119
|
* @typedef {object} TonalPaletteFamilyInput
|
|
121
|
-
* @property {string} id
|
|
122
|
-
*
|
|
123
|
-
* @property {string}
|
|
124
|
-
*
|
|
125
|
-
* @property {
|
|
126
|
-
* @property {'chromatic' | 'neutral'} [kind] `neutral` derives the ramp from
|
|
127
|
-
* `neutralProfile` instead of the seed hue; defaults to `chromatic`.
|
|
128
|
-
* @property {TonalPaletteAnchor[]} [anchors] Colors pinned at specific stops.
|
|
120
|
+
* @property {string} id
|
|
121
|
+
* @property {string} seed
|
|
122
|
+
* @property {string} [name]
|
|
123
|
+
* @property {'chromatic' | 'neutral'} [kind]
|
|
124
|
+
* @property {TonalPaletteAnchor[]} [anchors]
|
|
129
125
|
*/
|
|
130
126
|
|
|
131
127
|
/**
|
|
@@ -134,9 +130,6 @@
|
|
|
134
130
|
* @property {number} [vibrancy] Chroma control from 0 (most muted) through 50
|
|
135
131
|
* (default) to 100 (most vivid).
|
|
136
132
|
* @property {'neutral-v1' | 'warm-v1' | 'cool-v1' | 'custom'} [neutralProfile]
|
|
137
|
-
* Hue treatment for `neutral` families: `neutral-v1` is fully achromatic,
|
|
138
|
-
* `warm-v1` and `cool-v1` add a slight tint, and `custom` derives the hue from
|
|
139
|
-
* the family's own seed. Defaults to `neutral-v1`.
|
|
140
133
|
* @property {'light-only' | 'dark-only' | 'light-and-dark'} [modeStrategy]
|
|
141
134
|
* @property {number[]} [stops] Ordered stops shared by every requested family;
|
|
142
135
|
* defaults to 0 through 100 in increments of 5. Decimal stops are supported,
|
|
@@ -144,8 +137,6 @@
|
|
|
144
137
|
*/
|
|
145
138
|
|
|
146
139
|
/**
|
|
147
|
-
* A generated palette candidate. The palette is still subject to author review
|
|
148
|
-
* and is not connected to runtime theme values.
|
|
149
140
|
* @typedef {object} TonalPaletteCandidate
|
|
150
141
|
* @property {1} schemaVersion
|
|
151
142
|
* @property {'candidate'} status
|
|
@@ -157,68 +148,10 @@
|
|
|
157
148
|
*/
|
|
158
149
|
|
|
159
150
|
/**
|
|
160
|
-
*
|
|
161
|
-
* @typedef {object} TonalPaletteRampDiagnostics
|
|
162
|
-
* @property {boolean} monotonic Whether luminance rises across every stop.
|
|
163
|
-
* @property {number} minimumAdjacentDeltaE Smallest perceptual gap between
|
|
164
|
-
* neighboring stops; a small value means two stops read as one color.
|
|
165
|
-
* @property {number} maximumAdjacentDeltaE Largest gap between neighboring stops.
|
|
166
|
-
* @property {number} maximumHueDrift Largest hue distance, in degrees, between
|
|
167
|
-
* a stop and the family's reference hue.
|
|
168
|
-
* @property {'blue-to-purple' | 'yellow-to-brown' | null} hueIdentityRisk Named
|
|
169
|
-
* drift the ramp is at risk of, or `null`.
|
|
170
|
-
* @property {number[]} gamutMappedStops Stops whose ideal color fell outside
|
|
171
|
-
* sRGB and was mapped back into it.
|
|
172
|
-
* @property {Array<TonalPaletteAnchor & {generatedColor: string, deltaE: number}>} anchors
|
|
173
|
-
* Each anchor with the color the stop received after its policy was applied
|
|
174
|
-
* and the perceptual distance that color still has from the requested target.
|
|
175
|
-
*/
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* Cross-family evidence for one mode, sampled at the stop nearest 50.
|
|
179
|
-
* @typedef {object} TonalPaletteCoordinationDiagnostics
|
|
180
|
-
* @property {'light' | 'dark'} mode Mode these samples come from.
|
|
181
|
-
* @property {number} stop Sampled stop.
|
|
182
|
-
* @property {[string, string] | null} closestFamilies The two chromatic
|
|
183
|
-
* families hardest to tell apart, or `null` with fewer than two.
|
|
184
|
-
* @property {number | null} minimumFamilyDeltaE Perceptual distance between them.
|
|
185
|
-
* @property {string | null} strongestFamily Most saturated family at this stop.
|
|
186
|
-
* @property {string | null} weakestFamily Least saturated family at this stop.
|
|
187
|
-
* @property {number | null} chromaRatio Strongest chroma over weakest; a large
|
|
188
|
-
* ratio means the families are unbalanced.
|
|
189
|
-
*/
|
|
190
|
-
|
|
191
|
-
/**
|
|
192
|
-
* The request as the generator resolved it, with every default filled in.
|
|
193
|
-
* @typedef {object} TonalPaletteNormalizedRequest
|
|
194
|
-
* @property {'astryx-oklch-v1'} recipe
|
|
195
|
-
* @property {number} vibrancy
|
|
196
|
-
* @property {'neutral-v1' | 'warm-v1' | 'cool-v1' | 'custom'} neutralProfile
|
|
197
|
-
* @property {'light-only' | 'dark-only' | 'light-and-dark'} modeStrategy
|
|
198
|
-
* @property {number[]} stops
|
|
199
|
-
* @property {Array<{id: string, name: string, seed: string, kind: 'chromatic' | 'neutral', anchors: TonalPaletteAnchor[]}>} families
|
|
200
|
-
*/
|
|
201
|
-
|
|
202
|
-
/**
|
|
203
|
-
* The detached receipt written beside a candidate. It records what was asked
|
|
204
|
-
* for and what the generator observed, so a candidate can be traced back to
|
|
205
|
-
* its request without rerunning generation.
|
|
206
|
-
* @typedef {object} TonalPaletteGenerationReceipt
|
|
207
|
-
* @property {1} schemaVersion
|
|
208
|
-
* @property {'astryx-oklch-v1'} recipe Recipe that produced the candidate.
|
|
209
|
-
* @property {string} candidateSha256 SHA-256 over the candidate bytes as written.
|
|
210
|
-
* @property {{version: string, sha256: string}} [preview] Present when preview
|
|
211
|
-
* content was generated for the request, even if no file was written because
|
|
212
|
-
* the target already exists.
|
|
213
|
-
* @property {TonalPaletteNormalizedRequest} request
|
|
214
|
-
* @property {{families: Record<string, {light?: TonalPaletteRampDiagnostics, dark?: TonalPaletteRampDiagnostics}>, coordination: TonalPaletteCoordinationDiagnostics[]}} diagnostics
|
|
215
|
-
*/
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* astryx --json theme palette generate <config>
|
|
151
|
+
* xds --json theme palette generate <config>
|
|
219
152
|
* @typedef {object} ThemePaletteGenerateResponse
|
|
220
153
|
* @property {'theme.palette.generate'} type
|
|
221
|
-
* @property {{recipe: 'astryx-oklch-v1', status: 'candidate', familyCount: number, stopCount: number, modes: string[], output: string | null, receipt: string | null, preview: string | null, written: boolean, reason: 'exists' | null, candidate: TonalPaletteCandidate, generationReceipt:
|
|
154
|
+
* @property {{recipe: 'astryx-oklch-v1', status: 'candidate', familyCount: number, stopCount: number, modes: string[], output: string | null, receipt: string | null, preview: string | null, written: boolean, reason: 'exists' | null, candidate: TonalPaletteCandidate, generationReceipt: Record<string, unknown>}} data
|
|
222
155
|
*/
|
|
223
156
|
|
|
224
157
|
// Make this a module so the @typedefs above are importable as types via
|
package/api/upgrade/_adapter.mjs
CHANGED
|
@@ -33,10 +33,7 @@ import {
|
|
|
33
33
|
} from '../../foundation/agent-docs/agent-docs.mjs';
|
|
34
34
|
import {formatCliCommand} from '../../foundation/env/package-manager.mjs';
|
|
35
35
|
import {Project} from '../../foundation/config/project.mjs';
|
|
36
|
-
import {
|
|
37
|
-
loadIntegrations,
|
|
38
|
-
markProviderConflicts,
|
|
39
|
-
} from '../../foundation/integrations/integrations.mjs';
|
|
36
|
+
import {loadIntegrations} from '../../foundation/integrations/integrations.mjs';
|
|
40
37
|
import {warnOnIntegrationIssues} from '../../foundation/integrations/integration-warnings.mjs';
|
|
41
38
|
import {logger} from '../logger.mjs';
|
|
42
39
|
|
|
@@ -311,15 +308,6 @@ export async function runCoreCodemods(versionManifests, {apply, path: srcPath, c
|
|
|
311
308
|
});
|
|
312
309
|
}
|
|
313
310
|
|
|
314
|
-
/**
|
|
315
|
-
* One installed package at one version; two specs that reach it share this.
|
|
316
|
-
* @param {{name: string, version?: string}} integration
|
|
317
|
-
* @returns {string}
|
|
318
|
-
*/
|
|
319
|
-
function packageIdentity(integration) {
|
|
320
|
-
return `${integration.name}\u0000${integration.version ?? ''}`;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
311
|
/**
|
|
324
312
|
* Load the consumer project's config + integrations. Throws on invalid config;
|
|
325
313
|
* the run leaf decides between the config_fixable preview and a hard abort.
|
|
@@ -333,65 +321,11 @@ export async function loadProjectContext(cwd, extraIntegrationSpecs = []) {
|
|
|
333
321
|
// cache entry; ordinary Project discovery remains cached by default.
|
|
334
322
|
const project = await Project.load(cwd, {fresh: true});
|
|
335
323
|
const postCodemodHooks = project.config.hooks?.postCodemod ?? [];
|
|
336
|
-
const
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
// again here would let upgrade run codemods from a package Project set aside.
|
|
340
|
-
const configured = project.loadedIntegrations.filter(
|
|
341
|
-
integration =>
|
|
342
|
-
!integration.__autolinked && configuredSpecs.has(integration.__spec),
|
|
343
|
-
);
|
|
344
|
-
// A package that lists itself runs its installed copy's released codemods,
|
|
345
|
-
// never the work in progress being authored, so that copy stands in for it.
|
|
346
|
-
const local = project.loadedIntegrations.find(
|
|
347
|
-
integration => integration.__local,
|
|
348
|
-
);
|
|
349
|
-
const selfListed = local != null && configured.includes(local);
|
|
350
|
-
if (local != null && selfListed && project.configPath) {
|
|
351
|
-
const installed = await loadIntegrations([local.__spec], {
|
|
352
|
-
cwd: path.dirname(project.configPath),
|
|
353
|
-
resolveProviders: false,
|
|
354
|
-
});
|
|
355
|
-
configured.splice(configured.indexOf(local), 1, ...installed);
|
|
356
|
-
}
|
|
357
|
-
const extraSpecs = uniqueFiles(extraIntegrationSpecs ?? []).filter(
|
|
358
|
-
spec => !configuredSpecs.has(spec),
|
|
359
|
-
);
|
|
360
|
-
const extras =
|
|
361
|
-
extraSpecs.length === 0
|
|
362
|
-
? []
|
|
363
|
-
: await loadIntegrations(extraSpecs, {resolveProviders: false});
|
|
364
|
-
// Naming the package being authored with --integration asks for its
|
|
365
|
-
// installed copy too, so the local package must not claim against it.
|
|
366
|
-
const localStandsIn =
|
|
367
|
-
local != null &&
|
|
368
|
-
(selfListed || extras.some(extra => extra.name === local.name));
|
|
369
|
-
// Autolinked packages and the package being authored join the pass only as
|
|
370
|
-
// claimants: every other command uses them for their provider IDs, but
|
|
371
|
-
// upgrade has never run their codemods and still does not. An extra that
|
|
372
|
-
// names one of them opts it in, so the extra stands in for that claimant.
|
|
373
|
-
const extraIdentities = new Set(extras.map(packageIdentity));
|
|
374
|
-
const claimantsOnly = project.loadedIntegrations.filter(
|
|
375
|
-
integration =>
|
|
376
|
-
(integration.__autolinked || (integration.__local && !localStandsIn)) &&
|
|
377
|
-
!extraIdentities.has(packageIdentity(integration)),
|
|
378
|
-
);
|
|
379
|
-
const resolved = markProviderConflicts([
|
|
380
|
-
...configured,
|
|
381
|
-
...claimantsOnly,
|
|
382
|
-
...extras,
|
|
324
|
+
const integrationSpecs = uniqueFiles([
|
|
325
|
+
...(project.integrations ?? []),
|
|
326
|
+
...(extraIntegrationSpecs ?? []),
|
|
383
327
|
]);
|
|
384
|
-
|
|
385
|
-
// return one as a new conflict entry, and upgrade must not warn that a
|
|
386
|
-
// package every other command uses contributes nothing.
|
|
387
|
-
const claimantDirs = new Set(
|
|
388
|
-
claimantsOnly.map(integration => integration.__packageDir),
|
|
389
|
-
);
|
|
390
|
-
const integrations = resolved.filter(
|
|
391
|
-
integration =>
|
|
392
|
-
integration.__packageDir == null ||
|
|
393
|
-
!claimantDirs.has(integration.__packageDir),
|
|
394
|
-
);
|
|
328
|
+
const integrations = await loadIntegrations(integrationSpecs);
|
|
395
329
|
return {postCodemodHooks, integrations};
|
|
396
330
|
}
|
|
397
331
|
|
|
@@ -16,9 +16,8 @@ export const doc = {
|
|
|
16
16
|
description:
|
|
17
17
|
'Migrates project source from a previous Astryx version to the currently ' +
|
|
18
18
|
'installed one by running the registered codemods, and compares the fully ' +
|
|
19
|
-
'rendered managed agent-docs block on every
|
|
20
|
-
'
|
|
21
|
-
'run migration reconciliation. Dry-run previews without writing; `apply` ' +
|
|
19
|
+
'rendered managed agent-docs block on every path, including same-Core ' +
|
|
20
|
+
'integration guidance changes. Dry-run previews without writing; `apply` ' +
|
|
22
21
|
'writes the prepared block only after selected codemods and hooks succeed. ' +
|
|
23
22
|
'Core codemods run before ' +
|
|
24
23
|
'the config is loaded so a config codemod can repair an otherwise-invalid ' +
|
|
@@ -69,7 +68,7 @@ export const doc = {
|
|
|
69
68
|
name: 'options.integration',
|
|
70
69
|
type: 'string[]',
|
|
71
70
|
description:
|
|
72
|
-
'Explicit integration
|
|
71
|
+
'Explicit integration package names / file paths to process.',
|
|
73
72
|
},
|
|
74
73
|
{
|
|
75
74
|
name: 'options.path',
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// DO NOT EDIT — run `pnpm sync:api-types` to regenerate.
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* xds --json upgrade --list
|
|
6
6
|
*/
|
|
7
7
|
export type UpgradeListResponse = {
|
|
8
8
|
type: "upgrade.list";
|
|
@@ -121,14 +121,14 @@ export type RegistryCompositionSummary = {
|
|
|
121
121
|
items: RegistryCompositionItemSummary[];
|
|
122
122
|
};
|
|
123
123
|
/**
|
|
124
|
-
*
|
|
124
|
+
* xds --json upgrade --registry [--apply]
|
|
125
125
|
*/
|
|
126
126
|
export type UpgradeRegistryResponse = {
|
|
127
127
|
type: "upgrade.registry";
|
|
128
128
|
data: RegistryCompositionSummary;
|
|
129
129
|
};
|
|
130
130
|
/**
|
|
131
|
-
*
|
|
131
|
+
* xds --json upgrade [--apply]
|
|
132
132
|
*/
|
|
133
133
|
export type UpgradeRunResponse = {
|
|
134
134
|
type: "upgrade.run";
|
|
@@ -150,7 +150,7 @@ export type UpgradeRunResponse = {
|
|
|
150
150
|
};
|
|
151
151
|
};
|
|
152
152
|
/**
|
|
153
|
-
*
|
|
153
|
+
* xds --json upgrade — short-circuit status results.
|
|
154
154
|
*
|
|
155
155
|
* - `up_to_date`: `--from` is >= installed target and `--force` was not passed.
|
|
156
156
|
* - `no_codemods`: no codemods (core or integration) apply to the range.
|
|
@@ -211,7 +211,7 @@ export type UpgradeOptions = {
|
|
|
211
211
|
*/
|
|
212
212
|
skipCodemod?: string[] | undefined;
|
|
213
213
|
/**
|
|
214
|
-
* Explicit integration
|
|
214
|
+
* Explicit integration package names / file paths.
|
|
215
215
|
*/
|
|
216
216
|
integration?: string[] | undefined;
|
|
217
217
|
/**
|
|
@@ -4,17 +4,17 @@
|
|
|
4
4
|
* @file Colocated types for the `upgrade` command — source of truth for the
|
|
5
5
|
* upgrade command JSON responses. Re-exported by `types/upgrade.d.ts`.
|
|
6
6
|
*
|
|
7
|
-
* Invocation
|
|
7
|
+
* Invocation -> type discriminator
|
|
8
8
|
* ------------------------------------------------------------------
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* (version detection failure)
|
|
9
|
+
* xds --json upgrade --list -> upgrade.list
|
|
10
|
+
* xds --json upgrade [--apply] -> upgrade.run
|
|
11
|
+
* xds --json upgrade --registry [--apply] -> upgrade.registry
|
|
12
|
+
* xds --json upgrade (status short-circuit) -> upgrade.status
|
|
13
|
+
* (version detection failure) -> CLIError
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
17
|
+
* xds --json upgrade --list
|
|
18
18
|
* @typedef {object} UpgradeListResponse
|
|
19
19
|
* @property {'upgrade.list'} type
|
|
20
20
|
* @property {UpgradeListEntry[]} data
|
|
@@ -88,14 +88,14 @@
|
|
|
88
88
|
*/
|
|
89
89
|
|
|
90
90
|
/**
|
|
91
|
-
*
|
|
91
|
+
* xds --json upgrade --registry [--apply]
|
|
92
92
|
* @typedef {object} UpgradeRegistryResponse
|
|
93
93
|
* @property {'upgrade.registry'} type
|
|
94
94
|
* @property {RegistryCompositionSummary} data
|
|
95
95
|
*/
|
|
96
96
|
|
|
97
97
|
/**
|
|
98
|
-
*
|
|
98
|
+
* xds --json upgrade [--apply]
|
|
99
99
|
* @typedef {object} UpgradeRunResponse
|
|
100
100
|
* @property {'upgrade.run'} type
|
|
101
101
|
* @property {object} data
|
|
@@ -112,7 +112,7 @@
|
|
|
112
112
|
*/
|
|
113
113
|
|
|
114
114
|
/**
|
|
115
|
-
*
|
|
115
|
+
* xds --json upgrade — short-circuit status results.
|
|
116
116
|
*
|
|
117
117
|
* - `up_to_date`: `--from` is >= installed target and `--force` was not passed.
|
|
118
118
|
* - `no_codemods`: no codemods (core or integration) apply to the range.
|
|
@@ -135,7 +135,7 @@
|
|
|
135
135
|
* @property {boolean} [force] Run codemods even if `from` >= installed.
|
|
136
136
|
* @property {string} [codemod] Run a single named transform.
|
|
137
137
|
* @property {string[]} [skipCodemod] Exclude named codemods (re-run past a failure).
|
|
138
|
-
* @property {string[]} [integration] Explicit integration
|
|
138
|
+
* @property {string[]} [integration] Explicit integration package names / file paths.
|
|
139
139
|
* @property {string} [path] Source directory to scan (default `./src`).
|
|
140
140
|
* @property {boolean} [installDeps] Auto-install jscodeshift without prompting.
|
|
141
141
|
* @property {boolean} [registry] Reconcile only ShadCN-copied compositions; `from` is not required.
|
|
@@ -32,40 +32,6 @@ import {semverCompare} from '../../foundation/env/semver.mjs';
|
|
|
32
32
|
/** File extensions recognized as codemod modules. */
|
|
33
33
|
const CODEMOD_EXTENSIONS = ['.ts', '.mjs', '.js'];
|
|
34
34
|
|
|
35
|
-
/**
|
|
36
|
-
* Directories never walked for codemods: a test directory beside a transform is
|
|
37
|
-
* the natural place to put its test, and every file found here is loaded and
|
|
38
|
-
* validated as a codemod.
|
|
39
|
-
*/
|
|
40
|
-
const SKIP_DIRS = new Set([
|
|
41
|
-
'node_modules',
|
|
42
|
-
'.git',
|
|
43
|
-
'__tests__',
|
|
44
|
-
'__fixtures__',
|
|
45
|
-
]);
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Whether a file name is a test or fixture rather than a codemod.
|
|
49
|
-
*
|
|
50
|
-
* The trap this closes: EVERY `.ts`/`.mjs`/`.js` under a version folder used to
|
|
51
|
-
* be loaded as a codemod, so a test file colocated with its transform failed
|
|
52
|
-
* validation and — because a definition error is a hard error — took every
|
|
53
|
-
* codemod in that package's version with it. `astryx upgrade` then applied no
|
|
54
|
-
* transforms and reported success, which is the worst shape a failure can take.
|
|
55
|
-
*
|
|
56
|
-
* Core's own codemods never hit this: they are enumerated in a registry, and
|
|
57
|
-
* their colocated tests are simply not in it. Only integrations are discovered
|
|
58
|
-
* by walking a directory, so only integrations carry the landmine — which is why
|
|
59
|
-
* this is a loader fix and not a documentation one. It protects the integrations
|
|
60
|
-
* that already exist, which no authoring tool can reach.
|
|
61
|
-
*
|
|
62
|
-
* @param {string} name a file's base name
|
|
63
|
-
* @returns {boolean}
|
|
64
|
-
*/
|
|
65
|
-
function isTestFile(name) {
|
|
66
|
-
return /\.(test|spec)\.[^.]+$/.test(name) || /\.fixture\.[^.]+$/.test(name);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
35
|
/**
|
|
70
36
|
* Recursively collect codemod module files under a version folder. Returns
|
|
71
37
|
* entries of {id, file} where id is the extension-less relative path
|
|
@@ -83,18 +49,14 @@ function collectCodemodFiles(versionDir) {
|
|
|
83
49
|
for (const entry of entries) {
|
|
84
50
|
const full = path.join(dir, entry.name);
|
|
85
51
|
if (entry.isDirectory()) {
|
|
86
|
-
if (
|
|
52
|
+
if (entry.name === 'node_modules' || entry.name === '.git') continue;
|
|
87
53
|
walk(full);
|
|
88
54
|
continue;
|
|
89
55
|
}
|
|
90
56
|
const ext = path.extname(entry.name);
|
|
91
57
|
if (!CODEMOD_EXTENSIONS.includes(ext)) continue;
|
|
92
|
-
if (isTestFile(entry.name)) continue;
|
|
93
58
|
const rel = path.relative(versionDir, full);
|
|
94
|
-
const id = rel
|
|
95
|
-
.slice(0, rel.length - ext.length)
|
|
96
|
-
.split(path.sep)
|
|
97
|
-
.join('/');
|
|
59
|
+
const id = rel.slice(0, rel.length - ext.length).split(path.sep).join('/');
|
|
98
60
|
out.push({id, file: full});
|
|
99
61
|
}
|
|
100
62
|
}
|
|
@@ -221,61 +221,3 @@ describe('integration codemod discovery', () => {
|
|
|
221
221
|
).rejects.toThrow(/across versions/i);
|
|
222
222
|
});
|
|
223
223
|
});
|
|
224
|
-
|
|
225
|
-
describe('test files beside a codemod', () => {
|
|
226
|
-
// The incident this closes: every .ts/.mjs/.js under a version folder was
|
|
227
|
-
// loaded AND VALIDATED as a codemod, so a test file colocated with its
|
|
228
|
-
// transform failed validation — and because a definition error is a hard
|
|
229
|
-
// error, it took every codemod in that version with it. `astryx upgrade`
|
|
230
|
-
// then applied nothing and reported success. Core is immune because its own
|
|
231
|
-
// codemods are enumerated in a registry rather than discovered by walking a
|
|
232
|
-
// directory, so its colocated tests are simply never visited. Only
|
|
233
|
-
// integrations carry the landmine.
|
|
234
|
-
const TRANSFORM = `
|
|
235
|
-
export default {
|
|
236
|
-
type: 'code',
|
|
237
|
-
title: 'Drop foo',
|
|
238
|
-
transform: (file) => file.source.replace(/foo/g, 'bar'),
|
|
239
|
-
};
|
|
240
|
-
`;
|
|
241
|
-
// Not a codemod: no default export of the right shape. Loading it throws.
|
|
242
|
-
const A_TEST = `
|
|
243
|
-
import {describe, it, expect} from 'vitest';
|
|
244
|
-
describe('drop-foo', () => {
|
|
245
|
-
it('drops foo', () => expect(1).toBe(1));
|
|
246
|
-
});
|
|
247
|
-
`;
|
|
248
|
-
|
|
249
|
-
it.each([
|
|
250
|
-
['a .test. sibling', '0.2.0/drop-foo.test.mjs'],
|
|
251
|
-
['a .spec. sibling', '0.2.0/drop-foo.spec.mjs'],
|
|
252
|
-
['a fixture sibling', '0.2.0/drop-foo.fixture.mjs'],
|
|
253
|
-
['a __tests__ directory', '0.2.0/__tests__/drop-foo.mjs'],
|
|
254
|
-
['a __fixtures__ directory', '0.2.0/__fixtures__/input.mjs'],
|
|
255
|
-
])('ignores %s and still discovers the codemod', async (_label, testPath) => {
|
|
256
|
-
scaffold({'0.2.0/drop-foo.mjs': TRANSFORM, [testPath]: A_TEST});
|
|
257
|
-
|
|
258
|
-
const project = await Project.load(tmpDir);
|
|
259
|
-
const byVersion = await discoverIntegrationCodemods(
|
|
260
|
-
project.loadedIntegrations,
|
|
261
|
-
);
|
|
262
|
-
|
|
263
|
-
expect([...byVersion.keys()]).toEqual(['0.2.0']);
|
|
264
|
-
expect(byVersion.get('0.2.0').map(entry => entry.id)).toEqual(['drop-foo']);
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
it('a nested helper directory is still walked', async () => {
|
|
268
|
-
// Only test and fixture names are skipped. A package that organises its
|
|
269
|
-
// transforms into subdirectories keeps working.
|
|
270
|
-
scaffold({'0.2.0/imports/drop-foo.mjs': TRANSFORM});
|
|
271
|
-
|
|
272
|
-
const project = await Project.load(tmpDir);
|
|
273
|
-
const byVersion = await discoverIntegrationCodemods(
|
|
274
|
-
project.loadedIntegrations,
|
|
275
|
-
);
|
|
276
|
-
|
|
277
|
-
expect(byVersion.get('0.2.0').map(entry => entry.id)).toEqual([
|
|
278
|
-
'imports/drop-foo',
|
|
279
|
-
]);
|
|
280
|
-
});
|
|
281
|
-
});
|
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
import {describe, it, expect} from 'vitest';
|
|
4
4
|
|
|
5
5
|
async function applyTransform(source, path = 'test.ts') {
|
|
6
|
-
const {default: transform} =
|
|
7
|
-
await import('../unwrap-authoring-factories.mjs');
|
|
6
|
+
const {default: transform} = await import('../unwrap-authoring-factories.mjs');
|
|
8
7
|
const jscodeshift = (await import('jscodeshift')).default;
|
|
9
8
|
const j = jscodeshift.withParser('tsx');
|
|
10
9
|
const api = {jscodeshift: j, stats: () => {}, report: () => {}};
|
|
@@ -19,7 +18,7 @@ export default createConfig({integrations: ['@acme/widgets']});
|
|
|
19
18
|
`;
|
|
20
19
|
const output = await applyTransform(input);
|
|
21
20
|
expect(output).not.toContain('createConfig');
|
|
22
|
-
expect(output).toContain(
|
|
21
|
+
expect(output).toContain("export default {");
|
|
23
22
|
expect(output).toContain("integrations: ['@acme/widgets']");
|
|
24
23
|
expect(output).not.toContain('type:');
|
|
25
24
|
});
|
|
@@ -133,34 +132,13 @@ export default createComponentDoc();
|
|
|
133
132
|
expect(output).toContain("type: 'component'");
|
|
134
133
|
});
|
|
135
134
|
|
|
136
|
-
it('leaves same-named factories from unrelated packages unchanged', async () => {
|
|
137
|
-
const input = `import {createConfig} from '@acme/eslint';
|
|
138
|
-
export default createConfig({strict: true});
|
|
139
|
-
`;
|
|
140
|
-
expect(await applyTransform(input)).toBe(input);
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
it('keeps an unrelated same-named import when another factory is migrated', async () => {
|
|
144
|
-
const input = `import {createConfig as createLintConfig} from '@acme/eslint';
|
|
145
|
-
import {createDoc} from '@astryxdesign/cli/doc';
|
|
146
|
-
export const lintConfig = createLintConfig({strict: true});
|
|
147
|
-
export const doc = createDoc({name: 'Theming', description: 'How theming works.'});
|
|
148
|
-
`;
|
|
149
|
-
const output = await applyTransform(input);
|
|
150
|
-
expect(output).toContain(
|
|
151
|
-
"import {createConfig as createLintConfig} from '@acme/eslint'",
|
|
152
|
-
);
|
|
153
|
-
expect(output).toContain('createLintConfig({strict: true})');
|
|
154
|
-
expect(output).not.toContain('createDoc');
|
|
155
|
-
expect(output).toContain("type: 'generic'");
|
|
156
|
-
});
|
|
157
|
-
|
|
158
135
|
it('is a no-op when no authoring factory is imported', async () => {
|
|
159
136
|
const input = `import {Button} from '@astryxdesign/core';
|
|
160
137
|
export default Button;
|
|
161
138
|
`;
|
|
162
|
-
const {default: transform} =
|
|
163
|
-
|
|
139
|
+
const {default: transform} = await import(
|
|
140
|
+
'../unwrap-authoring-factories.mjs'
|
|
141
|
+
);
|
|
164
142
|
const jscodeshift = (await import('jscodeshift')).default;
|
|
165
143
|
const j = jscodeshift.withParser('tsx');
|
|
166
144
|
const api = {jscodeshift: j, stats: () => {}, report: () => {}};
|