@astryxdesign/cli 0.6.3-canary.ea2f048 → 0.6.3-canary.ebaebc4
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 +2 -1
- 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 +37 -24
- package/api/docs/_adapter.mjs +169 -83
- package/api/docs/compiled-topics.test.mjs +78 -0
- package/api/docs/detail/detail.mjs +14 -63
- package/api/docs/detail/section/section.d.mts +1 -1
- package/api/docs/detail/section/section.mjs +44 -20
- package/api/docs/detail/section/section.test.mjs +41 -0
- package/api/docs/docs.d.mts +7 -2
- package/api/docs/docs.doc.mjs +27 -10
- package/api/docs/docs.mjs +16 -9
- package/api/docs/docs.test.mjs +6 -0
- package/api/docs/docs.type.d.mts +40 -3
- package/api/docs/docs.type.mjs +36 -8
- package/api/docs/index/index.d.mts +18 -0
- package/api/docs/index/index.mjs +32 -0
- package/api/docs/index/index.test.mjs +62 -0
- package/api/docs/integrationDocs.test.mjs +106 -0
- package/api/doctor/doctor.d.mts +48 -0
- package/api/doctor/doctor.mjs +232 -0
- package/api/doctor/doctor.test.mjs +196 -0
- 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 +5 -3
- 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 +49 -7
- package/api/integration/pack-check.test.mjs +249 -0
- 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 +20 -6
- package/api/theme/build/build.test.mjs +127 -0
- package/api/theme/palette/generate/generate.mjs +1 -1
- package/api/theme/palette/generate/generator.d.mts +10 -13
- package/api/theme/palette/generate/generator.mjs +7 -3
- package/api/theme/theme.type.d.mts +170 -11
- package/api/theme/theme.type.mjs +94 -27
- package/api/upgrade/_adapter.mjs +71 -5
- package/api/upgrade/project-context.test.mjs +272 -0
- package/api/upgrade/upgrade.doc.mjs +4 -3
- package/api/upgrade/upgrade.type.d.mts +5 -5
- package/api/upgrade/upgrade.type.mjs +11 -11
- package/assets/codemods/integration-discovery.mjs +40 -2
- package/assets/codemods/integration-discovery.test.mjs +58 -0
- package/assets/codemods/transforms/v0.3.0/__tests__/unwrap-authoring-factories.test.mjs +27 -5
- package/assets/codemods/transforms/v0.3.0/unwrap-authoring-factories.mjs +20 -5
- package/assets/docs/README.md +9 -0
- package/assets/docs/authoring.doc.mjs +14 -0
- package/assets/docs/cli-integrations.doc.mjs +86 -15
- package/assets/docs/styling-libraries.doc.mjs +1 -1
- package/assets/docs/working-with-ai.doc.mjs +1 -1
- package/authoring/_shared/contract.ts +22 -0
- package/authoring/codemod/codemod.doc.mjs +6 -1
- package/authoring/codemod/parse.d.mts +8 -8
- package/authoring/codemod/parse.mjs +8 -6
- 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 +788 -23
- package/authoring/doctypes/_schema.mjs +492 -39
- package/authoring/doctypes/base/graph-fields.doc.d.mts +9 -0
- package/authoring/doctypes/base/graph-fields.doc.mjs +62 -0
- package/authoring/doctypes/base/type.ts +40 -0
- package/authoring/doctypes/command/command.doc.mjs +3 -2
- package/authoring/doctypes/command/parse.d.mts +2 -2
- package/authoring/doctypes/command/parse.mjs +1 -1
- package/authoring/doctypes/command/type.ts +3 -2
- package/authoring/doctypes/component/component.doc.mjs +6 -3
- package/authoring/doctypes/component/parse.d.mts +2 -2
- package/authoring/doctypes/component/parse.mjs +1 -1
- package/authoring/doctypes/component/type.ts +4 -3
- package/authoring/doctypes/enum/parse.d.mts +2 -2
- package/authoring/doctypes/enum/parse.mjs +1 -1
- package/authoring/doctypes/enum/type.ts +3 -1
- package/authoring/doctypes/function/function.doc.mjs +4 -0
- package/authoring/doctypes/function/parse.d.mts +2 -2
- package/authoring/doctypes/function/parse.mjs +1 -1
- package/authoring/doctypes/function/type.ts +6 -2
- package/authoring/doctypes/hook/hook.doc.mjs +4 -0
- package/authoring/doctypes/hook/parse.d.mts +2 -2
- package/authoring/doctypes/hook/parse.mjs +1 -1
- package/authoring/doctypes/hook/type.ts +3 -2
- package/authoring/doctypes/legacy.d.mts +8 -6
- package/authoring/doctypes/legacy.mjs +5 -4
- package/authoring/doctypes/load-contract.test.mjs +207 -0
- package/authoring/doctypes/namespace/namespace.doc.d.mts +9 -0
- package/authoring/doctypes/namespace/namespace.doc.mjs +132 -0
- package/authoring/doctypes/namespace/parse.d.mts +12 -0
- package/authoring/doctypes/namespace/parse.mjs +25 -0
- package/authoring/doctypes/namespace/parse.test.mjs +165 -0
- package/authoring/doctypes/namespace/type.ts +71 -0
- package/authoring/doctypes/parse.d.mts +20 -18
- package/authoring/doctypes/parse.mjs +16 -10
- package/authoring/doctypes/parse.test.mjs +77 -3
- package/authoring/doctypes/reference/parse.d.mts +2 -2
- package/authoring/doctypes/reference/parse.mjs +8 -5
- package/authoring/doctypes/reference/reference.doc.mjs +17 -4
- package/authoring/doctypes/reference/type.ts +51 -5
- package/authoring/doctypes/schema/parse.d.mts +2 -2
- package/authoring/doctypes/schema/parse.mjs +1 -1
- package/authoring/doctypes/schema/type.ts +3 -2
- package/authoring/doctypes/template/parse.d.mts +92 -1
- package/authoring/doctypes/template/parse.mjs +36 -2
- package/authoring/doctypes/template/parse.test.mjs +8 -2
- package/authoring/doctypes/template/template.doc.mjs +4 -0
- package/authoring/doctypes/template/type.ts +5 -2
- package/authoring/doctypes/types.ts +10 -9
- 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/identity/identity.doc.d.mts +9 -0
- package/authoring/identity/identity.doc.mjs +61 -0
- package/authoring/identity/type.ts +132 -0
- package/authoring/index.d.mts +1 -0
- package/authoring/index.d.ts +49 -17
- package/authoring/index.mjs +1 -0
- package/authoring/integration/integration.doc.mjs +13 -6
- package/authoring/integration/parse.d.mts +2 -2
- package/authoring/integration/parse.mjs +1 -1
- package/authoring/integration/parse.test.mjs +10 -1
- package/authoring/integration/schema.d.mts +6 -4
- package/authoring/integration/schema.mjs +9 -3
- package/authoring/integration/type.ts +23 -6
- package/authoring/shadcn/receipt.d.mts +6 -6
- package/clients/cli/commands/docs.doc.mjs +13 -3
- package/clients/cli/commands/docs.mjs +121 -21
- package/clients/cli/commands/docs.test.mjs +88 -0
- package/clients/cli/commands/integration-authoring.test.mjs +13 -9
- package/clients/cli/commands/theme-palette-generate.doc.mjs +8 -4
- package/clients/cli/commands/upgrade.doc.mjs +2 -2
- package/clients/cli/formatters/index.mjs +162 -1
- package/clients/cli/formatters/index.test.mjs +91 -0
- package/clients/cli/lib/manifest.mjs +7 -2
- package/foundation/config/project.mjs +21 -6
- package/foundation/discovery/authoring-self-docs.d.mts +69 -0
- package/foundation/discovery/authoring-self-docs.mjs +214 -0
- package/foundation/discovery/authoring-self-docs.test.mjs +154 -0
- package/foundation/discovery/component-discovery.d.mts +1 -1
- package/foundation/discovery/component-discovery.mjs +2 -1
- package/foundation/discovery/docs-discovery.d.mts +11 -4
- package/foundation/discovery/docs-discovery.mjs +208 -88
- package/foundation/discovery/docs-discovery.test.mjs +279 -13
- package/foundation/discovery/docs-output-budget.d.mts +28 -0
- package/foundation/discovery/docs-output-budget.mjs +50 -0
- package/foundation/discovery/docs-section-key.d.mts +98 -0
- package/foundation/discovery/docs-section-key.mjs +221 -0
- package/foundation/discovery/docs-section-key.test.mjs +224 -0
- package/foundation/discovery/template-adapter.mjs +2 -1
- package/foundation/discovery/theming-targets.test.mjs +4 -0
- package/foundation/doc-compiler/compile.d.mts +162 -0
- package/foundation/doc-compiler/compile.mjs +262 -0
- package/foundation/doc-compiler/doc-compiler.test.mjs +687 -0
- package/foundation/doc-compiler/ir.d.mts +9 -0
- package/foundation/doc-compiler/ir.mjs +287 -0
- package/foundation/doc-compiler/lenses.d.mts +33 -0
- package/foundation/doc-compiler/lenses.mjs +127 -0
- package/foundation/identity/provider-identity.d.mts +90 -0
- package/foundation/identity/provider-identity.mjs +320 -0
- package/foundation/identity/provider-identity.test.mjs +254 -0
- package/foundation/identity/providers.d.mts +7 -0
- package/foundation/identity/providers.mjs +16 -0
- package/foundation/integrations/autolink.mjs +12 -5
- package/foundation/integrations/integration-warnings.mjs +6 -0
- package/foundation/integrations/integrations.d.mts +46 -2
- package/foundation/integrations/integrations.mjs +167 -8
- package/foundation/integrations/integrations.test.mjs +384 -1
- package/foundation/integrations/provider-conflicts.test.mjs +125 -0
- package/foundation/integrations/validate-contributions.d.mts +2 -0
- package/foundation/integrations/validate-contributions.mjs +10 -0
- package/foundation/response/json-contract.test.mjs +46 -17
- package/foundation/response/response-types.doc.mjs +6 -1
- package/package.json +9 -11
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
|
+
* astryx --json theme build <file> -> theme.build
|
|
12
|
+
* astryx --json theme build <file> --check -> theme.build.check
|
|
13
|
+
* astryx --json theme build <a> <b> … -> theme.build.batch
|
|
14
|
+
* astryx --json theme list -> theme.list
|
|
15
|
+
* astryx --json theme add <slug> -> theme.add
|
|
16
|
+
* astryx --json theme template -> theme.template
|
|
17
|
+
* astryx --json theme targets [filter] -> theme.targets
|
|
18
|
+
* astryx --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
|
+
* astryx --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
|
+
* astryx --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
|
+
* astryx --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
|
+
* astryx --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
|
+
* astryx --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
|
+
* astryx --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
|
+
* astryx --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
|
|
106
|
-
* and is not connected to runtime theme values.
|
|
105
|
+
* A color an author pins at one stop of one mode, constraining generation.
|
|
107
106
|
* @typedef {object} TonalPaletteAnchor
|
|
108
107
|
* @property {'light' | 'dark'} mode Mode containing the anchored stop.
|
|
109
108
|
* @property {number} stop Existing requested stop where the anchor applies.
|
|
110
|
-
* @property {string} color
|
|
109
|
+
* @property {string} color sRGB hex the stop is pulled toward: three or six
|
|
110
|
+
* digits, with or without `#`; the generator normalizes it.
|
|
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,12 +116,16 @@
|
|
|
116
116
|
*/
|
|
117
117
|
|
|
118
118
|
/**
|
|
119
|
+
* One requested family: a seed color and the constraints applied to its ramp.
|
|
119
120
|
* @typedef {object} TonalPaletteFamilyInput
|
|
120
|
-
* @property {string} id
|
|
121
|
-
*
|
|
122
|
-
* @property {string}
|
|
123
|
-
*
|
|
124
|
-
* @property {
|
|
121
|
+
* @property {string} id Lower-kebab-case key for the family in the generated
|
|
122
|
+
* palette. `black` and `white` are reserved for the standalone values.
|
|
123
|
+
* @property {string} seed sRGB hex the ramp is generated from: three or six
|
|
124
|
+
* digits, with or without `#`; the generator normalizes it.
|
|
125
|
+
* @property {string} [name] Display name for review artifacts; defaults to `id`.
|
|
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.
|
|
125
129
|
*/
|
|
126
130
|
|
|
127
131
|
/**
|
|
@@ -130,6 +134,9 @@
|
|
|
130
134
|
* @property {number} [vibrancy] Chroma control from 0 (most muted) through 50
|
|
131
135
|
* (default) to 100 (most vivid).
|
|
132
136
|
* @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`.
|
|
133
140
|
* @property {'light-only' | 'dark-only' | 'light-and-dark'} [modeStrategy]
|
|
134
141
|
* @property {number[]} [stops] Ordered stops shared by every requested family;
|
|
135
142
|
* defaults to 0 through 100 in increments of 5. Decimal stops are supported,
|
|
@@ -137,6 +144,8 @@
|
|
|
137
144
|
*/
|
|
138
145
|
|
|
139
146
|
/**
|
|
147
|
+
* A generated palette candidate. The palette is still subject to author review
|
|
148
|
+
* and is not connected to runtime theme values.
|
|
140
149
|
* @typedef {object} TonalPaletteCandidate
|
|
141
150
|
* @property {1} schemaVersion
|
|
142
151
|
* @property {'candidate'} status
|
|
@@ -148,10 +157,68 @@
|
|
|
148
157
|
*/
|
|
149
158
|
|
|
150
159
|
/**
|
|
151
|
-
*
|
|
160
|
+
* Per-ramp evidence recorded for one family in one mode.
|
|
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>
|
|
152
219
|
* @typedef {object} ThemePaletteGenerateResponse
|
|
153
220
|
* @property {'theme.palette.generate'} type
|
|
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:
|
|
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: TonalPaletteGenerationReceipt}} data
|
|
155
222
|
*/
|
|
156
223
|
|
|
157
224
|
// Make this a module so the @typedefs above are importable as types via
|
package/api/upgrade/_adapter.mjs
CHANGED
|
@@ -33,7 +33,10 @@ 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 {
|
|
36
|
+
import {
|
|
37
|
+
loadIntegrations,
|
|
38
|
+
markProviderConflicts,
|
|
39
|
+
} from '../../foundation/integrations/integrations.mjs';
|
|
37
40
|
import {warnOnIntegrationIssues} from '../../foundation/integrations/integration-warnings.mjs';
|
|
38
41
|
import {logger} from '../logger.mjs';
|
|
39
42
|
|
|
@@ -308,6 +311,15 @@ export async function runCoreCodemods(versionManifests, {apply, path: srcPath, c
|
|
|
308
311
|
});
|
|
309
312
|
}
|
|
310
313
|
|
|
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
|
+
|
|
311
323
|
/**
|
|
312
324
|
* Load the consumer project's config + integrations. Throws on invalid config;
|
|
313
325
|
* the run leaf decides between the config_fixable preview and a hard abort.
|
|
@@ -321,11 +333,65 @@ export async function loadProjectContext(cwd, extraIntegrationSpecs = []) {
|
|
|
321
333
|
// cache entry; ordinary Project discovery remains cached by default.
|
|
322
334
|
const project = await Project.load(cwd, {fresh: true});
|
|
323
335
|
const postCodemodHooks = project.config.hooks?.postCodemod ?? [];
|
|
324
|
-
const
|
|
325
|
-
|
|
326
|
-
|
|
336
|
+
const configuredSpecs = new Set(project.integrations ?? []);
|
|
337
|
+
// Configured packages come from Project, which has already resolved provider
|
|
338
|
+
// identity over configured, autolinked, and local packages. Loading them
|
|
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,
|
|
327
383
|
]);
|
|
328
|
-
|
|
384
|
+
// Claimants leave by package directory, not object identity: the pass can
|
|
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
|
+
);
|
|
329
395
|
return {postCodemodHooks, integrations};
|
|
330
396
|
}
|
|
331
397
|
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file `loadProjectContext` agrees with Project on provider identity, so
|
|
5
|
+
* `astryx upgrade` never runs codemods from a package Project set aside.
|
|
6
|
+
*
|
|
7
|
+
* Fixtures live under a repo-local temp dir, not /tmp, because Vite refuses to
|
|
8
|
+
* dynamically import a module from outside the project root.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import {afterEach, beforeEach, describe, expect, it} from 'vitest';
|
|
12
|
+
import * as fs from 'node:fs';
|
|
13
|
+
import * as path from 'node:path';
|
|
14
|
+
import {loadProjectContext, selectIntegrationCodemodsFor} from './_adapter.mjs';
|
|
15
|
+
|
|
16
|
+
let tmpDir;
|
|
17
|
+
let originalCwd;
|
|
18
|
+
|
|
19
|
+
beforeEach(() => {
|
|
20
|
+
originalCwd = process.cwd();
|
|
21
|
+
tmpDir = fs.mkdtempSync(path.join(process.cwd(), '.astryx-upgrade-context-'));
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
afterEach(() => {
|
|
25
|
+
process.chdir(originalCwd);
|
|
26
|
+
fs.rmSync(tmpDir, {recursive: true, force: true});
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Install an integration package that ships one 0.2.0 codemod.
|
|
31
|
+
* @param {string} name
|
|
32
|
+
* @param {string} version
|
|
33
|
+
* @param {Record<string, unknown>} [manifest]
|
|
34
|
+
*/
|
|
35
|
+
function installWithCodemod(name, version, manifest = {}) {
|
|
36
|
+
const pkgDir = path.join(tmpDir, 'node_modules', ...name.split('/'));
|
|
37
|
+
const codemodDir = path.join(pkgDir, 'codemods', '0.2.0');
|
|
38
|
+
fs.mkdirSync(codemodDir, {recursive: true});
|
|
39
|
+
fs.writeFileSync(path.join(pkgDir, 'package.json'), JSON.stringify({name, version}));
|
|
40
|
+
fs.writeFileSync(
|
|
41
|
+
path.join(pkgDir, 'astryx.integration.mjs'),
|
|
42
|
+
`export default ${JSON.stringify({codemods: './codemods', ...manifest})};\n`,
|
|
43
|
+
);
|
|
44
|
+
fs.writeFileSync(
|
|
45
|
+
path.join(codemodDir, 'rename.mjs'),
|
|
46
|
+
"export default {type: 'code', title: 'Rename', transform: file => file.source};\n",
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** @param {string[]} integrations */
|
|
51
|
+
function configure(integrations) {
|
|
52
|
+
fs.writeFileSync(
|
|
53
|
+
path.join(tmpDir, 'astryx.config.mjs'),
|
|
54
|
+
`export default ${JSON.stringify({integrations})};\n`,
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
describe('loadProjectContext provider identity', () => {
|
|
59
|
+
it('keeps codemods from a configured package the authored package sets aside', async () => {
|
|
60
|
+
installWithCodemod('@acme/widgets', '1.0.0');
|
|
61
|
+
configure(['@acme/widgets']);
|
|
62
|
+
fs.writeFileSync(
|
|
63
|
+
path.join(tmpDir, 'package.json'),
|
|
64
|
+
JSON.stringify({name: '@acme/renamed', version: '2.0.0-dev'}),
|
|
65
|
+
);
|
|
66
|
+
fs.writeFileSync(
|
|
67
|
+
path.join(tmpDir, 'astryx.integration.mjs'),
|
|
68
|
+
"export default {providerId: '@acme/widgets'};\n",
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
const {integrations} = await loadProjectContext(tmpDir);
|
|
72
|
+
expect(
|
|
73
|
+
integrations.map(integration => [
|
|
74
|
+
integration.name,
|
|
75
|
+
Boolean(integration.__providerConflict),
|
|
76
|
+
]),
|
|
77
|
+
).toEqual([['@acme/widgets', true]]);
|
|
78
|
+
expect(
|
|
79
|
+
await selectIntegrationCodemodsFor(integrations, '0.1.0', '0.3.0'),
|
|
80
|
+
).toEqual([]);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('still selects codemods from a configured package nothing else claims', async () => {
|
|
84
|
+
installWithCodemod('@acme/widgets', '1.0.0');
|
|
85
|
+
configure(['@acme/widgets']);
|
|
86
|
+
fs.writeFileSync(path.join(tmpDir, 'package.json'), JSON.stringify({name: 'consumer'}));
|
|
87
|
+
|
|
88
|
+
const {integrations} = await loadProjectContext(tmpDir);
|
|
89
|
+
const selected = await selectIntegrationCodemodsFor(integrations, '0.1.0', '0.3.0');
|
|
90
|
+
expect(selected.map(entry => entry.version)).toEqual(['0.2.0']);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it('sets aside an --integration extra that claims a configured provider ID', async () => {
|
|
94
|
+
installWithCodemod('@acme/widgets', '1.0.0');
|
|
95
|
+
installWithCodemod('@acme/other', '1.0.0', {providerId: '@acme/widgets'});
|
|
96
|
+
configure(['@acme/widgets']);
|
|
97
|
+
fs.writeFileSync(path.join(tmpDir, 'package.json'), JSON.stringify({name: 'consumer'}));
|
|
98
|
+
// `--integration` specs resolve from the process cwd, as they always have.
|
|
99
|
+
process.chdir(tmpDir);
|
|
100
|
+
|
|
101
|
+
const {integrations} = await loadProjectContext(tmpDir, ['@acme/other']);
|
|
102
|
+
expect(
|
|
103
|
+
integrations.map(integration => [
|
|
104
|
+
integration.name,
|
|
105
|
+
integration.__providerConflict?.claimedBy ?? null,
|
|
106
|
+
]),
|
|
107
|
+
).toEqual([
|
|
108
|
+
['@acme/widgets', null],
|
|
109
|
+
['@acme/other', '@acme/widgets'],
|
|
110
|
+
]);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it('runs the installed copy of a package that lists itself, not its work in progress', async () => {
|
|
114
|
+
installWithCodemod('@acme/widgets', '1.0.0');
|
|
115
|
+
configure(['@acme/widgets']);
|
|
116
|
+
fs.writeFileSync(
|
|
117
|
+
path.join(tmpDir, 'package.json'),
|
|
118
|
+
JSON.stringify({name: '@acme/widgets', version: '3.0.0-dev'}),
|
|
119
|
+
);
|
|
120
|
+
fs.writeFileSync(
|
|
121
|
+
path.join(tmpDir, 'astryx.integration.mjs'),
|
|
122
|
+
"export default {codemods: './codemods'};\n",
|
|
123
|
+
);
|
|
124
|
+
fs.mkdirSync(path.join(tmpDir, 'codemods', '0.2.0'), {recursive: true});
|
|
125
|
+
fs.writeFileSync(
|
|
126
|
+
path.join(tmpDir, 'codemods', '0.2.0', 'local-wip.mjs'),
|
|
127
|
+
"export default {type: 'code', title: 'Local WIP', transform: file => file.source};\n",
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
const {integrations} = await loadProjectContext(tmpDir);
|
|
131
|
+
expect(
|
|
132
|
+
integrations.map(integration => [
|
|
133
|
+
integration.name,
|
|
134
|
+
integration.version,
|
|
135
|
+
Boolean(integration.__local),
|
|
136
|
+
Boolean(integration.__providerConflict),
|
|
137
|
+
]),
|
|
138
|
+
).toEqual([['@acme/widgets', '1.0.0', false, false]]);
|
|
139
|
+
const selected = JSON.stringify(
|
|
140
|
+
await selectIntegrationCodemodsFor(integrations, '0.1.0', '0.3.0'),
|
|
141
|
+
);
|
|
142
|
+
expect(selected).toContain('rename');
|
|
143
|
+
expect(selected).not.toContain('local-wip');
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it('runs the installed copy when the authored package is named with --integration', async () => {
|
|
147
|
+
installWithCodemod('@acme/widgets', '1.0.0');
|
|
148
|
+
configure([]);
|
|
149
|
+
fs.writeFileSync(
|
|
150
|
+
path.join(tmpDir, 'package.json'),
|
|
151
|
+
JSON.stringify({name: '@acme/widgets', version: '3.0.0-dev'}),
|
|
152
|
+
);
|
|
153
|
+
fs.writeFileSync(
|
|
154
|
+
path.join(tmpDir, 'astryx.integration.mjs'),
|
|
155
|
+
"export default {codemods: './codemods'};\n",
|
|
156
|
+
);
|
|
157
|
+
fs.mkdirSync(path.join(tmpDir, 'codemods', '0.2.0'), {recursive: true});
|
|
158
|
+
fs.writeFileSync(
|
|
159
|
+
path.join(tmpDir, 'codemods', '0.2.0', 'local-wip.mjs'),
|
|
160
|
+
"export default {type: 'code', title: 'Local WIP', transform: file => file.source};\n",
|
|
161
|
+
);
|
|
162
|
+
process.chdir(tmpDir);
|
|
163
|
+
|
|
164
|
+
const {integrations} = await loadProjectContext(tmpDir, ['@acme/widgets']);
|
|
165
|
+
expect(
|
|
166
|
+
integrations.map(integration => [
|
|
167
|
+
integration.name,
|
|
168
|
+
integration.version,
|
|
169
|
+
Boolean(integration.__local),
|
|
170
|
+
integration.__providerConflict?.claimedBy ?? null,
|
|
171
|
+
]),
|
|
172
|
+
).toEqual([['@acme/widgets', '1.0.0', false, null]]);
|
|
173
|
+
const selected = JSON.stringify(
|
|
174
|
+
await selectIntegrationCodemodsFor(integrations, '0.1.0', '0.3.0'),
|
|
175
|
+
);
|
|
176
|
+
expect(selected).toContain('rename');
|
|
177
|
+
expect(selected).not.toContain('local-wip');
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it("sets aside an --integration extra that claims an autolinked package's ID", async () => {
|
|
181
|
+
installWithCodemod('@acme/a', '1.0.0');
|
|
182
|
+
installWithCodemod('@acme/b', '1.0.0', {providerId: '@acme/a'});
|
|
183
|
+
configure([]);
|
|
184
|
+
fs.writeFileSync(
|
|
185
|
+
path.join(tmpDir, 'package.json'),
|
|
186
|
+
JSON.stringify({name: 'consumer', dependencies: {'@acme/a': '1.0.0'}}),
|
|
187
|
+
);
|
|
188
|
+
process.chdir(tmpDir);
|
|
189
|
+
|
|
190
|
+
const {integrations} = await loadProjectContext(tmpDir, ['@acme/b']);
|
|
191
|
+
expect(
|
|
192
|
+
integrations.map(integration => [
|
|
193
|
+
integration.name,
|
|
194
|
+
integration.__providerConflict?.claimedBy ?? null,
|
|
195
|
+
]),
|
|
196
|
+
).toEqual([['@acme/b', '@acme/a']]);
|
|
197
|
+
expect(
|
|
198
|
+
await selectIntegrationCodemodsFor(integrations, '0.1.0', '0.3.0'),
|
|
199
|
+
).toEqual([]);
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
it('runs an autolinked package the user names with --integration', async () => {
|
|
203
|
+
installWithCodemod('@acme/a', '1.0.0');
|
|
204
|
+
fs.writeFileSync(
|
|
205
|
+
path.join(tmpDir, 'package.json'),
|
|
206
|
+
JSON.stringify({name: 'consumer', dependencies: {'@acme/a': '1.0.0'}}),
|
|
207
|
+
);
|
|
208
|
+
process.chdir(tmpDir);
|
|
209
|
+
|
|
210
|
+
const {integrations} = await loadProjectContext(tmpDir, ['@acme/a']);
|
|
211
|
+
expect(
|
|
212
|
+
integrations.map(integration => [
|
|
213
|
+
integration.name,
|
|
214
|
+
integration.__providerConflict?.claimedBy ?? null,
|
|
215
|
+
]),
|
|
216
|
+
).toEqual([['@acme/a', null]]);
|
|
217
|
+
const selected = await selectIntegrationCodemodsFor(integrations, '0.1.0', '0.3.0');
|
|
218
|
+
expect(selected.map(entry => entry.version)).toEqual(['0.2.0']);
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
it('never reports a claimant that every other command uses as set aside', async () => {
|
|
222
|
+
installWithCodemod('@acme/widgets', '1.0.0');
|
|
223
|
+
installWithCodemod('@acme/renamed', '2.0.0', {providerId: '@acme/widgets'});
|
|
224
|
+
configure(['@acme/widgets']);
|
|
225
|
+
fs.writeFileSync(
|
|
226
|
+
path.join(tmpDir, 'package.json'),
|
|
227
|
+
JSON.stringify({
|
|
228
|
+
name: '@acme/widgets',
|
|
229
|
+
version: '3.0.0-dev',
|
|
230
|
+
dependencies: {'@acme/renamed': '2.0.0'},
|
|
231
|
+
}),
|
|
232
|
+
);
|
|
233
|
+
fs.writeFileSync(
|
|
234
|
+
path.join(tmpDir, 'astryx.integration.mjs'),
|
|
235
|
+
"export default {providerId: '@acme/widgets-next'};\n",
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
const {integrations} = await loadProjectContext(tmpDir);
|
|
239
|
+
expect(
|
|
240
|
+
integrations.map(integration => [
|
|
241
|
+
integration.name,
|
|
242
|
+
integration.version,
|
|
243
|
+
integration.__providerConflict?.claimedBy ?? null,
|
|
244
|
+
]),
|
|
245
|
+
).toEqual([['@acme/widgets', '1.0.0', null]]);
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
it("sets aside an --integration extra that claims the authored package's ID", async () => {
|
|
249
|
+
installWithCodemod('@acme/widgets', '1.0.0');
|
|
250
|
+
configure([]);
|
|
251
|
+
fs.writeFileSync(
|
|
252
|
+
path.join(tmpDir, 'package.json'),
|
|
253
|
+
JSON.stringify({name: '@acme/renamed', version: '2.0.0-dev'}),
|
|
254
|
+
);
|
|
255
|
+
fs.writeFileSync(
|
|
256
|
+
path.join(tmpDir, 'astryx.integration.mjs'),
|
|
257
|
+
"export default {providerId: '@acme/widgets'};\n",
|
|
258
|
+
);
|
|
259
|
+
process.chdir(tmpDir);
|
|
260
|
+
|
|
261
|
+
const {integrations} = await loadProjectContext(tmpDir, ['@acme/widgets']);
|
|
262
|
+
expect(
|
|
263
|
+
integrations.map(integration => [
|
|
264
|
+
integration.name,
|
|
265
|
+
integration.__providerConflict?.claimedBy ?? null,
|
|
266
|
+
]),
|
|
267
|
+
).toEqual([['@acme/widgets', '@acme/renamed']]);
|
|
268
|
+
expect(
|
|
269
|
+
await selectIntegrationCodemodsFor(integrations, '0.1.0', '0.3.0'),
|
|
270
|
+
).toEqual([]);
|
|
271
|
+
});
|
|
272
|
+
});
|
|
@@ -16,8 +16,9 @@ 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 path, including
|
|
20
|
-
'integration guidance changes
|
|
19
|
+
'rendered managed agent-docs block on every migration path, including ' +
|
|
20
|
+
'same-Core integration guidance changes; list and registry-only modes do not ' +
|
|
21
|
+
'run migration reconciliation. Dry-run previews without writing; `apply` ' +
|
|
21
22
|
'writes the prepared block only after selected codemods and hooks succeed. ' +
|
|
22
23
|
'Core codemods run before ' +
|
|
23
24
|
'the config is loaded so a config codemod can repair an otherwise-invalid ' +
|
|
@@ -68,7 +69,7 @@ export const doc = {
|
|
|
68
69
|
name: 'options.integration',
|
|
69
70
|
type: 'string[]',
|
|
70
71
|
description:
|
|
71
|
-
'Explicit integration
|
|
72
|
+
'Explicit integration specifiers to process. Resolved beneath node_modules; absolute paths and `.` or `..` segments are rejected.',
|
|
72
73
|
},
|
|
73
74
|
{
|
|
74
75
|
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
|
+
* astryx --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
|
+
* astryx --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
|
+
* astryx --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
|
+
* astryx --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 specifiers resolved beneath node_modules; absolute paths and `.` or `..` segments are rejected.
|
|
215
215
|
*/
|
|
216
216
|
integration?: string[] | undefined;
|
|
217
217
|
/**
|