@astryxdesign/cli 0.1.2-canary.05be2c6 → 0.1.2-canary.071c5bf
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1 -0
- package/README.md +55 -49
- package/docs/principles.doc.dense.mjs +2 -2
- package/docs/principles.doc.mjs +0 -4
- package/docs/principles.doc.zh.mjs +2 -2
- package/package.json +7 -7
- package/src/api/doctor.mjs +3 -3
- package/src/api/index.mjs +0 -1
- package/src/codemods/transforms/{v0.1.0 → v0.0.15}/drop-xds-prefix-imports.mjs +4 -15
- package/src/codemods/transforms/v0.0.15/index.mjs +13 -0
- package/src/codemods/transforms/v0.1.0/index.mjs +0 -46
- package/src/commands/agent-docs.mjs +1 -4
- package/src/commands/build-theme.mjs +0 -117
- package/src/index.mjs +0 -1
- package/src/lib/error-codes.mjs +0 -8
- package/templates/blocks/components/DropdownMenu/DropdownMenuShowcase.tsx +6 -0
- package/templates/blocks/components/DropdownMenuItem/DropdownMenuItemShowcase.tsx +5 -1
- package/templates/blocks/components/HoverCard/HoverCardInteractiveContent.doc.mjs +1 -1
- package/templates/blocks/components/HoverCard/HoverCardInteractiveContent.tsx +4 -9
- package/templates/blocks/components/Lightbox/LightboxShowcase.tsx +3 -4
- package/templates/blocks/components/MoreMenu/MoreMenuShowcase.tsx +6 -0
- package/templates/blocks/components/TreeListBranches/TreeListBranchesShowcase.doc.mjs +14 -0
- package/templates/blocks/components/TreeListBranches/TreeListBranchesShowcase.tsx +64 -0
- package/templates/blocks/components/TreeListItem/TreeListItemShowcase.doc.mjs +14 -0
- package/templates/blocks/components/TreeListItem/TreeListItemShowcase.tsx +60 -0
- package/templates/pages/shell-side-nav/page.tsx +1 -0
- package/docs/layout.doc.dense.mjs +0 -90
- package/docs/layout.doc.mjs +0 -160
- package/src/api/blog.mjs +0 -192
- package/src/api/blog.test.mjs +0 -144
- package/src/codemods/transforms/v0.1.0/__tests__/migrate-xds-css-surfaces.test.mjs +0 -67
- package/src/codemods/transforms/v0.1.0/__tests__/migrate-xds-declare-module.test.mjs +0 -61
- package/src/codemods/transforms/v0.1.0/__tests__/v0.1.0-ordering.test.mjs +0 -104
- package/src/codemods/transforms/v0.1.0/migrate-xds-css-surfaces.mjs +0 -77
- package/src/codemods/transforms/v0.1.0/migrate-xds-declare-module.mjs +0 -78
- package/src/commands/blog.mjs +0 -60
- package/src/commands/build-theme.watch.test.mjs +0 -157
- package/src/lib/site.mjs +0 -20
- package/templates/blocks/components/AvatarStatusDot/AvatarStatusDotVariants.doc.mjs +0 -14
- package/templates/blocks/components/AvatarStatusDot/AvatarStatusDotVariants.tsx +0 -28
- package/templates/blocks/components/Blockquote/BlockquoteTestimonials.doc.mjs +0 -14
- package/templates/blocks/components/Blockquote/BlockquoteTestimonials.tsx +0 -34
- package/templates/blocks/components/Blockquote/BlockquoteWithCite.doc.mjs +0 -14
- package/templates/blocks/components/Blockquote/BlockquoteWithCite.tsx +0 -21
- package/templates/blocks/components/BreadcrumbItem/BreadcrumbItemBasic.doc.mjs +0 -14
- package/templates/blocks/components/BreadcrumbItem/BreadcrumbItemBasic.tsx +0 -15
- package/templates/blocks/components/ButtonGroup/ButtonGroupBasic.doc.mjs +0 -14
- package/templates/blocks/components/ButtonGroup/ButtonGroupBasic.tsx +0 -16
- package/templates/blocks/components/ChatDictationButton/ChatDictationButtonBasic.doc.mjs +0 -19
- package/templates/blocks/components/ChatDictationButton/ChatDictationButtonBasic.tsx +0 -34
- package/templates/blocks/components/CheckboxListItem/CheckboxListItemBasic.doc.mjs +0 -14
- package/templates/blocks/components/CheckboxListItem/CheckboxListItemBasic.tsx +0 -30
- package/templates/blocks/components/CollapsibleGroup/CollapsibleGroupAccordion.doc.mjs +0 -14
- package/templates/blocks/components/CollapsibleGroup/CollapsibleGroupAccordion.tsx +0 -31
- package/templates/blocks/components/CommandPaletteEmpty/CommandPaletteEmptyBasic.doc.mjs +0 -14
- package/templates/blocks/components/CommandPaletteEmpty/CommandPaletteEmptyBasic.tsx +0 -26
- package/templates/blocks/components/CommandPaletteFooter/CommandPaletteFooterBasic.doc.mjs +0 -14
- package/templates/blocks/components/CommandPaletteFooter/CommandPaletteFooterBasic.tsx +0 -32
- package/templates/blocks/components/CommandPaletteGroup/CommandPaletteGroupBasic.doc.mjs +0 -18
- package/templates/blocks/components/CommandPaletteGroup/CommandPaletteGroupBasic.tsx +0 -32
- package/templates/blocks/components/CommandPaletteItem/CommandPaletteItemBasic.doc.mjs +0 -14
- package/templates/blocks/components/CommandPaletteItem/CommandPaletteItemBasic.tsx +0 -27
- package/templates/blocks/components/ContextMenu/ContextMenuBasic.doc.mjs +0 -14
- package/templates/blocks/components/ContextMenu/ContextMenuBasic.tsx +0 -32
- package/templates/blocks/components/DateRangeInput/DateRangeInputWithPresets.doc.mjs +0 -14
- package/templates/blocks/components/DateRangeInput/DateRangeInputWithPresets.tsx +0 -46
- package/templates/blocks/components/DateRangeInput/DateRangeInputWithValidation.doc.mjs +0 -14
- package/templates/blocks/components/DateRangeInput/DateRangeInputWithValidation.tsx +0 -52
- package/templates/blocks/components/DateTimeInput/DateTimeInputWithValidation.doc.mjs +0 -14
- package/templates/blocks/components/DateTimeInput/DateTimeInputWithValidation.tsx +0 -43
- package/templates/blocks/components/DialogHeader/DialogHeaderBasic.doc.mjs +0 -14
- package/templates/blocks/components/DialogHeader/DialogHeaderBasic.tsx +0 -30
- package/templates/blocks/components/DropdownMenuItem/DropdownMenuItemBasic.doc.mjs +0 -14
- package/templates/blocks/components/DropdownMenuItem/DropdownMenuItemBasic.tsx +0 -27
- package/templates/blocks/components/FieldLabel/FieldLabelBasic.doc.mjs +0 -14
- package/templates/blocks/components/FieldLabel/FieldLabelBasic.tsx +0 -20
- package/templates/blocks/components/FieldStatus/FieldStatusBasic.doc.mjs +0 -14
- package/templates/blocks/components/FieldStatus/FieldStatusBasic.tsx +0 -23
- package/templates/blocks/components/FileInput/FileInputBasic.doc.mjs +0 -14
- package/templates/blocks/components/FileInput/FileInputBasic.tsx +0 -22
- package/templates/blocks/components/GridSpan/GridSpanColumns.doc.mjs +0 -14
- package/templates/blocks/components/GridSpan/GridSpanColumns.tsx +0 -38
- package/templates/blocks/components/HStack/HStackBasic.doc.mjs +0 -14
- package/templates/blocks/components/HStack/HStackBasic.tsx +0 -16
- package/templates/blocks/components/Hooks/useKeyboardHintHookUsage.doc.mjs +0 -14
- package/templates/blocks/components/Hooks/useKeyboardHintHookUsage.tsx +0 -57
- package/templates/blocks/components/InputGroup/InputGroupBasic.doc.mjs +0 -14
- package/templates/blocks/components/InputGroup/InputGroupBasic.tsx +0 -27
- package/templates/blocks/components/LayoutContent/LayoutContentBasic.doc.mjs +0 -23
- package/templates/blocks/components/LayoutContent/LayoutContentBasic.tsx +0 -40
- package/templates/blocks/components/LayoutFooter/LayoutFooterActions.doc.mjs +0 -22
- package/templates/blocks/components/LayoutFooter/LayoutFooterActions.tsx +0 -41
- package/templates/blocks/components/LayoutHeader/LayoutHeaderWithActions.doc.mjs +0 -23
- package/templates/blocks/components/LayoutHeader/LayoutHeaderWithActions.tsx +0 -40
- package/templates/blocks/components/LayoutPanel/LayoutPanelNavigation.doc.mjs +0 -22
- package/templates/blocks/components/LayoutPanel/LayoutPanelNavigation.tsx +0 -37
- package/templates/blocks/components/Lightbox/LightboxGallery.doc.mjs +0 -14
- package/templates/blocks/components/Lightbox/LightboxGallery.tsx +0 -53
- package/templates/blocks/components/Lightbox/LightboxVideo.doc.mjs +0 -14
- package/templates/blocks/components/Lightbox/LightboxVideo.tsx +0 -27
- package/templates/blocks/components/Lightbox/LightboxZoom.doc.mjs +0 -14
- package/templates/blocks/components/Lightbox/LightboxZoom.tsx +0 -33
- package/templates/blocks/components/MetadataListItem/MetadataListItemBasic.doc.mjs +0 -14
- package/templates/blocks/components/MetadataListItem/MetadataListItemBasic.tsx +0 -19
- package/templates/blocks/components/MobileNavToggle/MobileNavToggleBasic.doc.mjs +0 -23
- package/templates/blocks/components/MobileNavToggle/MobileNavToggleBasic.tsx +0 -42
- package/templates/blocks/components/NavIcon/NavIconBasic.doc.mjs +0 -14
- package/templates/blocks/components/NavIcon/NavIconBasic.tsx +0 -16
- package/templates/blocks/components/RadioListItem/RadioListItemBasic.doc.mjs +0 -14
- package/templates/blocks/components/RadioListItem/RadioListItemBasic.tsx +0 -30
- package/templates/blocks/components/Resizable/ResizableSidebar.doc.mjs +0 -25
- package/templates/blocks/components/Resizable/ResizableSidebar.tsx +0 -67
- package/templates/blocks/components/SegmentedControlItem/SegmentedControlItemBasic.doc.mjs +0 -14
- package/templates/blocks/components/SegmentedControlItem/SegmentedControlItemBasic.tsx +0 -21
- package/templates/blocks/components/SelectorOption/SelectorOptionBasic.doc.mjs +0 -14
- package/templates/blocks/components/SelectorOption/SelectorOptionBasic.tsx +0 -39
- package/templates/blocks/components/SideNavCollapseButton/SideNavCollapseButtonBasic.doc.mjs +0 -14
- package/templates/blocks/components/SideNavCollapseButton/SideNavCollapseButtonBasic.tsx +0 -55
- package/templates/blocks/components/SideNavHeading/SideNavHeadingBasic.doc.mjs +0 -14
- package/templates/blocks/components/SideNavHeading/SideNavHeadingBasic.tsx +0 -38
- package/templates/blocks/components/SideNavItem/SideNavItemBasic.doc.mjs +0 -14
- package/templates/blocks/components/SideNavItem/SideNavItemBasic.tsx +0 -49
- package/templates/blocks/components/SideNavSection/SideNavSectionBasic.doc.mjs +0 -14
- package/templates/blocks/components/SideNavSection/SideNavSectionBasic.tsx +0 -71
- package/templates/blocks/components/StackItem/StackItemFill.doc.mjs +0 -14
- package/templates/blocks/components/StackItem/StackItemFill.tsx +0 -28
- package/templates/blocks/components/Tab/TabWithSelectedIcon.doc.mjs +0 -13
- package/templates/blocks/components/Tab/TabWithSelectedIcon.tsx +0 -39
- package/templates/blocks/components/TabMenu/TabMenuBasic.doc.mjs +0 -14
- package/templates/blocks/components/TabMenu/TabMenuBasic.tsx +0 -23
- package/templates/blocks/components/ToggleButtonGroup/ToggleButtonGroupVertical.doc.mjs +0 -14
- package/templates/blocks/components/ToggleButtonGroup/ToggleButtonGroupVertical.tsx +0 -47
- package/templates/blocks/components/TopNavHeading/TopNavHeadingBasic.doc.mjs +0 -14
- package/templates/blocks/components/TopNavHeading/TopNavHeadingBasic.tsx +0 -22
- package/templates/blocks/components/TopNavItem/TopNavItemBasic.doc.mjs +0 -14
- package/templates/blocks/components/TopNavItem/TopNavItemBasic.tsx +0 -21
- package/templates/blocks/components/TopNavMegaMenu/TopNavMegaMenuBasic.doc.mjs +0 -20
- package/templates/blocks/components/TopNavMegaMenu/TopNavMegaMenuBasic.tsx +0 -46
- package/templates/blocks/components/TopNavMegaMenuFeaturedCard/TopNavMegaMenuFeaturedCardBasic.doc.mjs +0 -14
- package/templates/blocks/components/TopNavMegaMenuFeaturedCard/TopNavMegaMenuFeaturedCardBasic.tsx +0 -16
- package/templates/blocks/components/TopNavMegaMenuItem/TopNavMegaMenuItemBasic.doc.mjs +0 -14
- package/templates/blocks/components/TopNavMegaMenuItem/TopNavMegaMenuItemBasic.tsx +0 -26
- package/templates/blocks/components/TopNavMenu/TopNavMenuBasic.doc.mjs +0 -14
- package/templates/blocks/components/TopNavMenu/TopNavMenuBasic.tsx +0 -43
- package/templates/blocks/components/TypeaheadItem/TypeaheadItemBasic.doc.mjs +0 -14
- package/templates/blocks/components/TypeaheadItem/TypeaheadItemBasic.tsx +0 -43
- package/templates/blocks/components/VStack/VStackBasic.doc.mjs +0 -14
- package/templates/blocks/components/VStack/VStackBasic.tsx +0 -20
- package/templates/pages/kanban-board/page.tsx +0 -729
- package/templates/pages/kanban-board/template.doc.mjs +0 -12
- /package/src/codemods/transforms/{v0.1.0 → v0.0.15}/__tests__/drop-xds-prefix-imports.test.mjs +0 -0
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -62,7 +62,8 @@ Options:
|
|
|
62
62
|
| `upgrade` | Run codemods to migrate between versions |
|
|
63
63
|
| `theme build` | Compile a defineTheme file to production CSS and JS |
|
|
64
64
|
| `discover` | Discover external packages and components |
|
|
65
|
-
| `
|
|
65
|
+
| `gap-report` | Report a gap when a component doesn't meet your needs |
|
|
66
|
+
| `doctor` | Diagnose your XDS setup and report problems with fixes (CI-friendly via exit code) |
|
|
66
67
|
|
|
67
68
|
### Global options
|
|
68
69
|
|
|
@@ -160,6 +161,7 @@ if (isError(result)) {
|
|
|
160
161
|
| `ERR_INVALID_VERSION` | A `--from`/`--to` value was not a valid semver string. |
|
|
161
162
|
| `ERR_DEP_MISSING` | A required external dependency (e.g. jscodeshift) is missing. |
|
|
162
163
|
| `ERR_GH_CLI` | GitHub CLI (`gh`) is not installed or not authenticated. |
|
|
164
|
+
| `ERR_GAP_REPORT_FAILED` | Filing a gap report failed (disabled, or the integration errored). |
|
|
163
165
|
|
|
164
166
|
## Capability manifest (agent discovery)
|
|
165
167
|
|
|
@@ -170,7 +172,7 @@ discriminators each command can emit. Think of it as an OpenAPI spec for the CLI
|
|
|
170
172
|
|
|
171
173
|
```bash
|
|
172
174
|
astryx manifest --json # dedicated surface — type: "manifest"
|
|
173
|
-
|
|
175
|
+
xds --json # bare invocation — embeds the same payload under data.manifest
|
|
174
176
|
```
|
|
175
177
|
|
|
176
178
|
Shape:
|
|
@@ -180,7 +182,7 @@ Shape:
|
|
|
180
182
|
"apiVersion": 1,
|
|
181
183
|
"type": "manifest",
|
|
182
184
|
"data": {
|
|
183
|
-
"name": "
|
|
185
|
+
"name": "xds",
|
|
184
186
|
"version": "0.0.14",
|
|
185
187
|
"description": "Design system CLI — components, themes, and tooling",
|
|
186
188
|
"globalOptions": [
|
|
@@ -247,14 +249,14 @@ the `JSON_SUPPORTED` allowlist and a small declarative `RESPONSE_TYPES` map in
|
|
|
247
249
|
`src/lib/manifest.mjs`, guarded by a drift test (`manifest.test.mjs`) so adding a
|
|
248
250
|
command without describing it fails CI.
|
|
249
251
|
|
|
250
|
-
**Backwards-compat:** the bare `
|
|
252
|
+
**Backwards-compat:** the bare `xds --json` envelope keeps `type: "help"` and its
|
|
251
253
|
original shallow fields (`name`, `version`, `commands` as a `string[]` of names,
|
|
252
254
|
`jsonSupported`); the full structured manifest is additive under `data.manifest`.
|
|
253
255
|
For the standalone manifest envelope (`type: "manifest"`), use `astryx manifest --json`.
|
|
254
256
|
|
|
255
257
|
## Programmatic API
|
|
256
258
|
|
|
257
|
-
The same logic that powers `
|
|
259
|
+
The same logic that powers `xds --json` is available as importable, type-safe functions:
|
|
258
260
|
|
|
259
261
|
```typescript
|
|
260
262
|
import {
|
|
@@ -267,20 +269,20 @@ import {
|
|
|
267
269
|
AstryxError,
|
|
268
270
|
} from '@astryxdesign/cli/api';
|
|
269
271
|
|
|
270
|
-
// Same result as:
|
|
272
|
+
// Same result as: xds --json component Button
|
|
271
273
|
const btn = await component('Button');
|
|
272
274
|
btn.type; // 'component.detail'
|
|
273
275
|
btn.data.name; // 'Button' (typed as ComponentDoc)
|
|
274
276
|
|
|
275
|
-
// Same result as:
|
|
277
|
+
// Same result as: xds --json component --list
|
|
276
278
|
const list = await component(undefined, {list: true});
|
|
277
279
|
list.data; // Record<string, string[]>
|
|
278
280
|
|
|
279
|
-
// Same result as:
|
|
281
|
+
// Same result as: xds --json docs principles
|
|
280
282
|
const principles = await docs('principles');
|
|
281
|
-
principles.data.title; // 'Principles'
|
|
283
|
+
principles.data.title; // 'XDS Principles'
|
|
282
284
|
|
|
283
|
-
// Same result as:
|
|
285
|
+
// Same result as: xds --json hook useMediaQuery
|
|
284
286
|
const useMediaQuery = await hook('useMediaQuery');
|
|
285
287
|
useMediaQuery.data.params; // typed as HookParamDoc[]
|
|
286
288
|
|
|
@@ -294,7 +296,7 @@ try {
|
|
|
294
296
|
}
|
|
295
297
|
```
|
|
296
298
|
|
|
297
|
-
The CLI command handlers are thin wrappers around these functions: they parse args, call the API, then format the output (JSON or text). This guarantees that `@astryxdesign/cli/api` and `
|
|
299
|
+
The CLI command handlers are thin wrappers around these functions: they parse args, call the API, then format the output (JSON or text). This guarantees that `@astryxdesign/cli/api` and `xds --json` always return identical data.
|
|
298
300
|
|
|
299
301
|
### Consumer utilities
|
|
300
302
|
|
|
@@ -324,41 +326,43 @@ detail.data.name; // already narrowed
|
|
|
324
326
|
|
|
325
327
|
Every response has a `type` string that uniquely identifies it:
|
|
326
328
|
|
|
327
|
-
| Command
|
|
328
|
-
|
|
|
329
|
-
| `
|
|
330
|
-
| `
|
|
331
|
-
| `
|
|
332
|
-
| `
|
|
333
|
-
| `
|
|
334
|
-
| `
|
|
335
|
-
| `
|
|
336
|
-
| `
|
|
337
|
-
| `
|
|
338
|
-
| `
|
|
339
|
-
| `
|
|
340
|
-
| `
|
|
341
|
-
| `
|
|
342
|
-
| `
|
|
343
|
-
| `
|
|
344
|
-
| `
|
|
345
|
-
| `
|
|
346
|
-
| `
|
|
347
|
-
| `
|
|
348
|
-
| `
|
|
349
|
-
| `
|
|
350
|
-
| `
|
|
351
|
-
| `
|
|
352
|
-
| `
|
|
353
|
-
| `
|
|
354
|
-
| `
|
|
355
|
-
| `
|
|
356
|
-
| `
|
|
357
|
-
| `
|
|
358
|
-
| `
|
|
359
|
-
| `
|
|
360
|
-
|
|
|
361
|
-
|
|
|
329
|
+
| Command | Type | Response |
|
|
330
|
+
| ---------------------------------------------- | --------------------------- | --------------------------------- |
|
|
331
|
+
| `xds --json component [--list]` | `component.list` | `ComponentListResponse` |
|
|
332
|
+
| `xds --json component --list --detail compact` | `component.brief` | `ComponentBriefResponse` |
|
|
333
|
+
| `xds --json component --list --detail full` | `component.full` | `ComponentFullResponse` |
|
|
334
|
+
| `xds --json component <name>` | `component.detail` | `ComponentDetailResponse` |
|
|
335
|
+
| `xds --json component <name> --props` | `component.detail.props` | `ComponentDetailPropsResponse` |
|
|
336
|
+
| `xds --json component <name> --source` | `component.detail.source` | `ComponentDetailSourceResponse` |
|
|
337
|
+
| `xds --json component <name> --showcase` | `component.detail.showcase` | `ComponentDetailShowcaseResponse` |
|
|
338
|
+
| `xds --json component <name> --blocks` | `component.detail.blocks` | `ComponentDetailBlocksResponse` |
|
|
339
|
+
| `xds --json discover` | `discover.list` | `DiscoverListResponse` |
|
|
340
|
+
| `xds --json discover @scope/name` | `discover.detail` | `DiscoverDetailResponse` |
|
|
341
|
+
| `xds --json discover @scope/name/Comp` | `discover.detail.doc` | `DiscoverDetailDocResponse` |
|
|
342
|
+
| `xds --json discover <search>` | `discover.search` | `DiscoverSearchResponse` |
|
|
343
|
+
| `xds --json docs` | `docs.list` | `DocsListResponse` |
|
|
344
|
+
| `xds --json docs <topic>` | `docs.detail` | `DocsDetailResponse` |
|
|
345
|
+
| `xds --json docs <topic> <section>` | `docs.detail.section` | `DocsDetailSectionResponse` |
|
|
346
|
+
| `xds --json template [--list]` | `template.list` | `TemplateListResponse` |
|
|
347
|
+
| `xds --json template <name>` | `template.show` | `TemplateShowResponse` |
|
|
348
|
+
| `xds --json template <name> --skeleton` | `template.skeleton` | `TemplateSkeletonResponse` |
|
|
349
|
+
| `xds --json template <name> [path]` | `template.copy` | `TemplateCopyResponse` |
|
|
350
|
+
| `xds --json hook [--list]` | `hook.list` | `HookListResponse` |
|
|
351
|
+
| `xds --json hook --list --detail compact` | `hook.brief` | `HookBriefResponse` |
|
|
352
|
+
| `xds --json hook --list --detail full` | `hook.full` | `HookFullResponse` |
|
|
353
|
+
| `xds --json hook <name>` | `hook.detail` | `HookDetailResponse` |
|
|
354
|
+
| `xds --json hook <name> --params` | `hook.detail.params` | `HookDetailParamsResponse` |
|
|
355
|
+
| `xds --json search <query>` | `search` | `SearchResponse` |
|
|
356
|
+
| `xds --json swizzle [--list]` | `swizzle.list` | `SwizzleListResponse` |
|
|
357
|
+
| `xds --json swizzle <component>` | `swizzle.copy` | `SwizzleCopyResponse` |
|
|
358
|
+
| `xds --json theme build <file>` | `theme.build` | `ThemeBuildResponse` |
|
|
359
|
+
| `xds --json upgrade --list` | `upgrade.list` | `UpgradeListResponse` |
|
|
360
|
+
| `xds --json upgrade [--apply]` | `upgrade.run` | `UpgradeRunResponse` |
|
|
361
|
+
| `xds --json gap-report --list-categories` | `gap-report.categories` | `GapReportCategoriesResponse` |
|
|
362
|
+
| `xds --json gap-report --component X ...` | `gap-report.file` | `GapReportFileResponse` |
|
|
363
|
+
| `xds --json doctor` | `doctor` | `DoctorResponse` |
|
|
364
|
+
| any error | — | `CLIError` |
|
|
365
|
+
| unsupported command | — | `CLIUnsupportedError` |
|
|
362
366
|
|
|
363
367
|
## Doctor
|
|
364
368
|
|
|
@@ -379,7 +383,7 @@ astryx doctor — diagnosing your setup
|
|
|
379
383
|
@astryxdesign/core v0.0.14 is in step with @astryxdesign/cli v0.0.14.
|
|
380
384
|
⚠ Theme packages
|
|
381
385
|
No @astryxdesign/theme-* packages are installed.
|
|
382
|
-
→ fix: Install a theme, e.g. `npm install @astryxdesign/theme-neutral`, then import its CSS or set
|
|
386
|
+
→ fix: Install a theme, e.g. `npm install @astryxdesign/theme-neutral`, then import its CSS or set xds.theme.
|
|
383
387
|
ℹ astryx.config.mjs
|
|
384
388
|
No astryx.config.mjs found — using defaults.
|
|
385
389
|
ℹ AI agent docs
|
|
@@ -404,7 +408,7 @@ No failures — but review the ⚠ warnings above when you can.
|
|
|
404
408
|
| Version alignment | pass / warn / info | Installed `@astryxdesign/core` is in step with `@astryxdesign/cli` |
|
|
405
409
|
| Theme packages | pass / warn | An `@astryxdesign/theme-*` package is installed and a theme is wired |
|
|
406
410
|
| astryx.config.mjs | pass / fail / info | Config (if present) loads cleanly with a valid shape |
|
|
407
|
-
| AI agent docs | pass / warn / info | Agent docs exist and contain the
|
|
411
|
+
| AI agent docs | pass / warn / info | Agent docs exist and contain the XDS section markers |
|
|
408
412
|
| Peer dependencies | pass / warn / info | `@astryxdesign/core`'s peer deps (react, …) are installed |
|
|
409
413
|
| Package manager | info | Reports the detected package manager |
|
|
410
414
|
|
|
@@ -430,6 +434,8 @@ export default {
|
|
|
430
434
|
templates: {
|
|
431
435
|
get: async id => fetchTemplateFromAPI(id),
|
|
432
436
|
},
|
|
433
|
-
|
|
437
|
+
gapReport: {
|
|
438
|
+
url: 'https://your-api.com/gaps',
|
|
439
|
+
},
|
|
434
440
|
};
|
|
435
441
|
```
|
|
@@ -6,9 +6,9 @@ export const docsDense = {
|
|
|
6
6
|
description: 'core design principles + rules for the design system',
|
|
7
7
|
sections: [
|
|
8
8
|
{ title: 'Philosophy', content: [{ type: 'list', items: ['components over primitives', 'semantic tokens over hardcoded values', 'theme-agnostic code', 'open internals'] }] },
|
|
9
|
-
{ title: 'Rules', content: [{ type: 'list', items: ['use components', '
|
|
9
|
+
{ title: 'Rules', content: [{ type: 'list', items: ['use components', 'StyleX or Tailwind for styling', 'semantic tokens only', 'CSS vars for colors', 'controlled form inputs', 'useLinkComponent() for navigation'] }] },
|
|
10
10
|
{ title: 'Styling', content: [{ type: 'prose', text: 'xstyle prop for component overrides. StyleX or Tailwind for layout. See astryx docs styling.' }] },
|
|
11
|
-
{ title: 'Anti-Patterns', content: [{ type: 'list', items: ['no inline styles on raw elements', 'no hardcoded colors — use tokens or Tailwind semantic classes', 'no hardcoded spacing', 'no hardcoded <a> — use useLinkComponent()', '
|
|
11
|
+
{ title: 'Anti-Patterns', content: [{ type: 'list', items: ['no inline styles on raw elements', 'no hardcoded colors — use tokens or Tailwind semantic classes', 'no hardcoded spacing', 'no hardcoded <a> — use useLinkComponent()', 'read docs before inventing props'] }] },
|
|
12
12
|
{ title: 'Tokens', content: [{ type: 'prose', text: 'run npx astryx docs tokens for full reference' }] },
|
|
13
13
|
],
|
|
14
14
|
};
|
package/docs/principles.doc.mjs
CHANGED
|
@@ -39,8 +39,6 @@ export const docs = {
|
|
|
39
39
|
style: 'ordered',
|
|
40
40
|
items: [
|
|
41
41
|
'Use components for everything they cover',
|
|
42
|
-
'Layout is frame-first: pick the shell and budget regions before writing content (see \`npx astryx docs layout\`)',
|
|
43
|
-
'Dense data renders as rows (Table, List/Item), edge-to-edge with dividers; Card is for widgets, galleries, and settings groups',
|
|
44
42
|
'StyleX or Tailwind for custom styling; both are first-class (see \`npx astryx docs styling\`)',
|
|
45
43
|
'Semantic tokens, not hardcoded values (see \`npx astryx docs tokens\`)',
|
|
46
44
|
'CSS custom properties for colors, not hex values',
|
|
@@ -76,8 +74,6 @@ export const docs = {
|
|
|
76
74
|
'Hardcoded colors (#fff). Use var(--color-*) or Tailwind semantic classes (text-primary, bg-surface)',
|
|
77
75
|
'Hardcoded spacing (16px). Use spacing tokens or Tailwind spacing utilities',
|
|
78
76
|
'Hardcoded <a> elements. Use useLinkComponent() so consumers can swap in their framework router via LinkProvider',
|
|
79
|
-
'Wrapping every list item or page section in a Card. Decide the frame first; dense data renders as rows (see \`npx astryx docs layout\`)',
|
|
80
|
-
'Badge as decoration. Reserve Badge for counts and enumerated states; use StatusDot or Token for status',
|
|
81
77
|
'Inventing props. Read component docs first',
|
|
82
78
|
],
|
|
83
79
|
},
|
|
@@ -6,9 +6,9 @@ export const docsZh = {
|
|
|
6
6
|
description: 'XDS 核心设计原则和规则。',
|
|
7
7
|
sections: [
|
|
8
8
|
{ title: '设计哲学', content: [{ type: 'list', items: ['组件优于原始元素 — 优先使用 XDS 组件', '语义化令牌优于硬编码值', '主题无关的代码 — 深色模式自动生效', '开放的内部机制 — 所有基础组件均可导出和组合'] }] },
|
|
9
|
-
{ title: '规则', content: [{ type: 'list', items: ['所有支持的场景都使用 XDS 组件', '
|
|
9
|
+
{ title: '规则', content: [{ type: 'list', items: ['所有支持的场景都使用 XDS 组件', '使用 StyleX 或 Tailwind 进行样式设置', '使用语义化令牌,不使用硬编码值', '使用 CSS 变量设置颜色,不使用十六进制值', '表单输入为受控组件(value + onChange)', '使用 useLinkComponent() 进行导航'] }] },
|
|
10
10
|
{ title: '样式方法', content: [{ type: 'prose', text: '组件覆盖使用 xstyle 属性。布局使用 StyleX 或 Tailwind。详见 astryx docs styling。' }] },
|
|
11
|
-
{ title: '反模式', content: [{ type: 'list', items: ['不要在原始元素上使用内联样式', '不要硬编码颜色 — 使用令牌或 Tailwind 语义类', '不要硬编码间距', '不要硬编码 <a> 元素 — 使用 useLinkComponent()', '
|
|
11
|
+
{ title: '反模式', content: [{ type: 'list', items: ['不要在原始元素上使用内联样式', '不要硬编码颜色 — 使用令牌或 Tailwind 语义类', '不要硬编码间距', '不要硬编码 <a> 元素 — 使用 useLinkComponent()', '不要自创属性。先阅读组件文档'] }] },
|
|
12
12
|
{ title: '设计令牌', content: [{ type: 'prose', text: '运行 npx astryx docs tokens 查看完整参考' }] },
|
|
13
13
|
],
|
|
14
14
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astryxdesign/cli",
|
|
3
|
-
"version": "0.1.2-canary.
|
|
3
|
+
"version": "0.1.2-canary.071c5bf",
|
|
4
4
|
"displayName": "CLI",
|
|
5
5
|
"description": "Scaffold projects, browse templates, generate themes, and get agent-ready docs from the command line.",
|
|
6
6
|
"author": "Meta Open Source",
|
|
@@ -75,9 +75,9 @@
|
|
|
75
75
|
"zod": "^4.4.3"
|
|
76
76
|
},
|
|
77
77
|
"peerDependencies": {
|
|
78
|
-
"@astryxdesign/core": "0.1.2-canary.
|
|
79
|
-
"@astryxdesign/lab": "0.1.2-canary.
|
|
80
|
-
"@astryxdesign/theme-neutral": "0.1.2-canary.
|
|
78
|
+
"@astryxdesign/core": "0.1.2-canary.071c5bf",
|
|
79
|
+
"@astryxdesign/lab": "0.1.2-canary.071c5bf",
|
|
80
|
+
"@astryxdesign/theme-neutral": "0.1.2-canary.071c5bf",
|
|
81
81
|
"gpt-tokenizer": "^2.0.0"
|
|
82
82
|
},
|
|
83
83
|
"peerDependenciesMeta": {
|
|
@@ -92,9 +92,9 @@
|
|
|
92
92
|
}
|
|
93
93
|
},
|
|
94
94
|
"devDependencies": {
|
|
95
|
-
"@astryxdesign/core": "0.1.2-canary.
|
|
96
|
-
"@astryxdesign/lab": "0.1.2-canary.
|
|
97
|
-
"@astryxdesign/theme-neutral": "0.1.2-canary.
|
|
95
|
+
"@astryxdesign/core": "0.1.2-canary.071c5bf",
|
|
96
|
+
"@astryxdesign/lab": "0.1.2-canary.071c5bf",
|
|
97
|
+
"@astryxdesign/theme-neutral": "0.1.2-canary.071c5bf",
|
|
98
98
|
"gpt-tokenizer": "^2.0.0"
|
|
99
99
|
},
|
|
100
100
|
"scripts": {
|
package/src/api/doctor.mjs
CHANGED
|
@@ -240,7 +240,7 @@ export function checkThemes(ctx) {
|
|
|
240
240
|
label: 'Theme packages',
|
|
241
241
|
status: 'warn',
|
|
242
242
|
message: 'No @astryxdesign/theme-* packages are installed.',
|
|
243
|
-
fix: 'Install a theme, e.g. `npm install @astryxdesign/theme-neutral`, then import its CSS or set
|
|
243
|
+
fix: 'Install a theme, e.g. `npm install @astryxdesign/theme-neutral`, then import its CSS or set xds.theme.',
|
|
244
244
|
};
|
|
245
245
|
}
|
|
246
246
|
|
|
@@ -354,7 +354,7 @@ export function checkAgentDocs(ctx) {
|
|
|
354
354
|
label: 'AI agent docs',
|
|
355
355
|
status: 'warn',
|
|
356
356
|
message: `Agent docs present (${present.join(', ')}) but no Astryx section markers found.`,
|
|
357
|
-
fix: 'Add the
|
|
357
|
+
fix: 'Add the XDS section to your agent docs with `astryx init --features agents`.',
|
|
358
358
|
};
|
|
359
359
|
}
|
|
360
360
|
|
|
@@ -362,7 +362,7 @@ export function checkAgentDocs(ctx) {
|
|
|
362
362
|
id: 'agent-docs',
|
|
363
363
|
label: 'AI agent docs',
|
|
364
364
|
status: 'pass',
|
|
365
|
-
message: `
|
|
365
|
+
message: `XDS agent docs section present in ${withMarkers.join(', ')}.`,
|
|
366
366
|
};
|
|
367
367
|
}
|
|
368
368
|
|
package/src/api/index.mjs
CHANGED
|
@@ -21,7 +21,6 @@
|
|
|
21
21
|
|
|
22
22
|
export {component} from './component.mjs';
|
|
23
23
|
export {docs} from './docs.mjs';
|
|
24
|
-
export {blog} from './blog.mjs';
|
|
25
24
|
export {discover} from './discover.mjs';
|
|
26
25
|
export {template} from './template.mjs';
|
|
27
26
|
export {themeAdd, listThemes} from './theme-add.mjs';
|
|
@@ -4,23 +4,12 @@
|
|
|
4
4
|
* @file Codemod: Drop the `XDS` prefix from @xds/core imports and their usages
|
|
5
5
|
*
|
|
6
6
|
* Part of the XDS-prefix migration (P2380608025). Rewrites consumer code from
|
|
7
|
-
* the prefixed names to
|
|
7
|
+
* the prefixed names to the bare compatibility aliases shipped in P1:
|
|
8
8
|
*
|
|
9
9
|
* XDSButton -> Button
|
|
10
10
|
* XDSButtonProps -> ButtonProps
|
|
11
11
|
* useXDSTheme -> useTheme
|
|
12
12
|
* useXDSToast -> useToast
|
|
13
|
-
* XDSIconRegistry-> IconRegistry
|
|
14
|
-
*
|
|
15
|
-
* Mandatory in v0.1.0: the prefixed compatibility aliases (which made both
|
|
16
|
-
* prefixed and bare names valid during the 0.0.x compat window) were dropped
|
|
17
|
-
* in v0.1.0, so the un-prefixing is now required for code to keep type-
|
|
18
|
-
* checking against @astryxdesign/core.
|
|
19
|
-
*
|
|
20
|
-
* Ordering: within the v0.1.0 manifest this runs BEFORE
|
|
21
|
-
* migrate-xds-module-specifiers so it still matches `@xds/core` imports (its
|
|
22
|
-
* source matcher) and un-prefixes the identifiers first; the specifier codemod
|
|
23
|
-
* then rewrites the module paths `@xds/*` -> `@astryxdesign/*`.
|
|
24
13
|
*
|
|
25
14
|
* Safety: this codemod ONLY renames identifiers that are imported from
|
|
26
15
|
* `@xds/core` (bare or subpath, e.g. `@xds/core/Button`). It tracks the local
|
|
@@ -47,9 +36,9 @@ export const meta = {
|
|
|
47
36
|
title: 'Drop XDS prefix from @xds/core imports (XDSButton -> Button)',
|
|
48
37
|
description:
|
|
49
38
|
'Rewrites @xds/core imports and their usages from the prefixed names ' +
|
|
50
|
-
'(XDSButton, useXDSTheme,
|
|
51
|
-
'
|
|
52
|
-
'
|
|
39
|
+
'(XDSButton, useXDSTheme, XDSButtonProps) to the bare compatibility ' +
|
|
40
|
+
'aliases (Button, useTheme, ButtonProps). Only renames bindings imported ' +
|
|
41
|
+
'from @xds/core, leaving unrelated identifiers untouched.',
|
|
53
42
|
pr: '#2880',
|
|
54
43
|
};
|
|
55
44
|
|
|
@@ -34,6 +34,10 @@ import migrateSelectorChildrenToRenderOption, {
|
|
|
34
34
|
meta as migrateSelectorChildrenToRenderOptionMeta,
|
|
35
35
|
} from './migrate-selector-children-to-render-option.mjs';
|
|
36
36
|
|
|
37
|
+
import dropXdsPrefixImports, {
|
|
38
|
+
meta as dropXdsPrefixImportsMeta,
|
|
39
|
+
} from './drop-xds-prefix-imports.mjs';
|
|
40
|
+
|
|
37
41
|
export default [
|
|
38
42
|
{
|
|
39
43
|
name: 'rename-date-picker-to-input',
|
|
@@ -71,4 +75,13 @@ export default [
|
|
|
71
75
|
transform: migrateSelectorChildrenToRenderOption,
|
|
72
76
|
meta: migrateSelectorChildrenToRenderOptionMeta,
|
|
73
77
|
},
|
|
78
|
+
{
|
|
79
|
+
// XDS-prefix migration (P2380608025). Optional + not tied to a version
|
|
80
|
+
// bump: consumers run it explicitly during their migration, e.g.
|
|
81
|
+
// astryx upgrade --codemod drop-xds-prefix-imports --codemod-only --apply
|
|
82
|
+
name: 'drop-xds-prefix-imports',
|
|
83
|
+
transform: dropXdsPrefixImports,
|
|
84
|
+
meta: dropXdsPrefixImportsMeta,
|
|
85
|
+
optional: true,
|
|
86
|
+
},
|
|
74
87
|
];
|
|
@@ -6,60 +6,14 @@
|
|
|
6
6
|
* Lists all codemods for the v0.1.0 release in the order they should run.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import dropXdsPrefixImports, {
|
|
10
|
-
meta as dropXdsPrefixImportsMeta,
|
|
11
|
-
} from './drop-xds-prefix-imports.mjs';
|
|
12
|
-
|
|
13
9
|
import migrateXdsModuleSpecifiers, {
|
|
14
10
|
meta as migrateXdsModuleSpecifiersMeta,
|
|
15
11
|
} from './migrate-xds-module-specifiers.mjs';
|
|
16
12
|
|
|
17
|
-
import migrateXdsDeclareModule, {
|
|
18
|
-
meta as migrateXdsDeclareModuleMeta,
|
|
19
|
-
} from './migrate-xds-declare-module.mjs';
|
|
20
|
-
|
|
21
|
-
import migrateXdsCssSurfaces, {
|
|
22
|
-
meta as migrateXdsCssSurfacesMeta,
|
|
23
|
-
} from './migrate-xds-css-surfaces.mjs';
|
|
24
|
-
|
|
25
13
|
export default [
|
|
26
|
-
{
|
|
27
|
-
// XDS-prefix migration (P2380608025). Mandatory in v0.1.0: the release
|
|
28
|
-
// dropped the prefixed compatibility aliases (useXDSTheme, XDSButton,
|
|
29
|
-
// XDSIconRegistry, ...), so consumers upgrading from 0.0.x MUST rewrite
|
|
30
|
-
// prefixed imports to their bare names.
|
|
31
|
-
//
|
|
32
|
-
// Ordered BEFORE migrate-xds-module-specifiers so it sees `@xds/core`
|
|
33
|
-
// imports (its source matcher) and un-prefixes the identifiers first;
|
|
34
|
-
// the specifier codemod then rewrites the paths to `@astryxdesign/core`.
|
|
35
|
-
// The runner preserves this array order (see runner.mjs).
|
|
36
|
-
name: 'drop-xds-prefix-imports',
|
|
37
|
-
transform: dropXdsPrefixImports,
|
|
38
|
-
meta: dropXdsPrefixImportsMeta,
|
|
39
|
-
},
|
|
40
14
|
{
|
|
41
15
|
name: 'migrate-xds-module-specifiers',
|
|
42
16
|
transform: migrateXdsModuleSpecifiers,
|
|
43
17
|
meta: migrateXdsModuleSpecifiersMeta,
|
|
44
18
|
},
|
|
45
|
-
{
|
|
46
|
-
// Cleans up TypeScript `declare module "@xds/core/..."` augmentations,
|
|
47
|
-
// which reference the package by string specifier and so are dead after
|
|
48
|
-
// the scope rename. Mandatory in v0.1.0. Ordered AFTER the specifier
|
|
49
|
-
// codemod: it uses the same @xds -> @astryxdesign mapping and repairs an
|
|
50
|
-
// adjacent surface the specifier codemod does not visit (module-decl ids
|
|
51
|
-
// are not import/export/require sources).
|
|
52
|
-
name: 'migrate-xds-declare-module',
|
|
53
|
-
transform: migrateXdsDeclareModule,
|
|
54
|
-
meta: migrateXdsDeclareModuleMeta,
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
// Rewrites consumer CSS surfaces broken by the v0.1.0 DOM-namespace rename
|
|
58
|
-
// (core no longer dual-emits `xds-*`): the `.xds-*` class-selector prefix,
|
|
59
|
-
// `[data-xds-*]` attribute selectors, and `@layer xds-*` layer names all
|
|
60
|
-
// become their `astryx-*` forms. Mandatory in v0.1.0.
|
|
61
|
-
name: 'migrate-xds-css-surfaces',
|
|
62
|
-
transform: migrateXdsCssSurfaces,
|
|
63
|
-
meta: migrateXdsCssSurfacesMeta,
|
|
64
|
-
},
|
|
65
19
|
];
|
|
@@ -180,9 +180,6 @@ export function generateCompressedIndex(version, {coreDir, runPrefix = getRunPre
|
|
|
180
180
|
// Rules — the top error-preventers.
|
|
181
181
|
lines.push('RULES:');
|
|
182
182
|
lines.push('- No <div> — components do all layout/spacing. Full page → AppShell; sidebar nav → SideNav.');
|
|
183
|
-
lines.push('- Frame first: pick the shell (AppShell / Layout+LayoutPanel) and budget regions in px BEFORE writing content (`astryx docs layout`).');
|
|
184
|
-
lines.push('- Dense data = rows (Table, List/Item) edge-to-edge — never Card-wrapped list items. Card = dashboard widgets, galleries, settings groups only.');
|
|
185
|
-
lines.push('- Status → StatusDot/Token; Badge only for counts and enumerated states, never decoration.');
|
|
186
183
|
// Styling guidance tailored to the project's configured system — never
|
|
187
184
|
// recommend a path that isn't compiled here (xstyle needs the StyleX compiler;
|
|
188
185
|
// utilities need Tailwind). Tokens are always the source of truth.
|
|
@@ -210,7 +207,7 @@ export function generateCompressedIndex(version, {coreDir, runPrefix = getRunPre
|
|
|
210
207
|
.sort();
|
|
211
208
|
if (topics.length > 0) lines.push(` docs <topic> ${topics.join(', ')}`);
|
|
212
209
|
}
|
|
213
|
-
lines.push(' swizzle <Name> eject component source
|
|
210
|
+
lines.push(' swizzle <Name> eject component source (--gap reports why)');
|
|
214
211
|
lines.push(' upgrade --apply run after any @astryxdesign/core bump');
|
|
215
212
|
lines.push(MARKER_END);
|
|
216
213
|
|
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
import * as fs from 'node:fs';
|
|
16
16
|
import * as path from 'node:path';
|
|
17
17
|
import {pathToFileURL, fileURLToPath} from 'node:url';
|
|
18
|
-
import {spawn} from 'node:child_process';
|
|
19
18
|
import {createJiti} from 'jiti';
|
|
20
19
|
import {getRunPrefix} from '../utils/package-manager.mjs';
|
|
21
20
|
import {
|
|
@@ -598,104 +597,6 @@ function validatePrivateVars(themeDef) {
|
|
|
598
597
|
return errors;
|
|
599
598
|
}
|
|
600
599
|
|
|
601
|
-
/**
|
|
602
|
-
* Path to this CLI's real entry (bin/astryx.mjs), resolved from this module's
|
|
603
|
-
* location (src/commands/build-theme.mjs → ../../bin/astryx.mjs). Used to
|
|
604
|
-
* re-invoke `theme build` as a child process in watch mode.
|
|
605
|
-
*/
|
|
606
|
-
function resolveCliBin() {
|
|
607
|
-
const commandsDir = path.dirname(fileURLToPath(import.meta.url));
|
|
608
|
-
return path.resolve(commandsDir, '../../bin/astryx.mjs');
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
/**
|
|
612
|
-
* Run a single `theme build` as a child process, reusing the exact
|
|
613
|
-
* single-build code path (and its error handling) rather than duplicating it.
|
|
614
|
-
* Resolves with the child's exit code; never rejects.
|
|
615
|
-
*
|
|
616
|
-
* @param {string} file - The theme file argument, as the user passed it.
|
|
617
|
-
* @param {object} options - Parsed command options (only `out` is forwarded).
|
|
618
|
-
* @returns {Promise<number>}
|
|
619
|
-
*/
|
|
620
|
-
function runThemeBuildOnceChild(file, options) {
|
|
621
|
-
const cliBin = resolveCliBin();
|
|
622
|
-
const args = [cliBin, 'theme', 'build', file];
|
|
623
|
-
if (options.out) args.push('--out', options.out);
|
|
624
|
-
return new Promise(resolve => {
|
|
625
|
-
const child = spawn(process.execPath, args, {
|
|
626
|
-
stdio: 'inherit',
|
|
627
|
-
env: process.env,
|
|
628
|
-
});
|
|
629
|
-
child.on('close', code => resolve(code ?? 0));
|
|
630
|
-
child.on('error', () => resolve(1));
|
|
631
|
-
});
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
/**
|
|
635
|
-
* Watch a theme file and rebuild on change. Runs an initial build, then
|
|
636
|
-
* rebuilds (debounced) whenever the file changes, until interrupted with
|
|
637
|
-
* Ctrl-C. Each rebuild runs in a child process so a build error (which the
|
|
638
|
-
* single-build path reports via a hard exit) is contained and the watcher
|
|
639
|
-
* keeps running.
|
|
640
|
-
*
|
|
641
|
-
* @param {string} file - The theme file argument, as the user passed it.
|
|
642
|
-
* @param {string} filePath - Absolute path to the theme file.
|
|
643
|
-
* @param {object} options - Parsed command options.
|
|
644
|
-
* @returns {Promise<void>} Resolves when the watcher is stopped (Ctrl-C).
|
|
645
|
-
*/
|
|
646
|
-
async function runThemeBuildWatch(file, filePath, options) {
|
|
647
|
-
const rel = path.relative(process.cwd(), filePath);
|
|
648
|
-
|
|
649
|
-
// Initial build.
|
|
650
|
-
await runThemeBuildOnceChild(file, options);
|
|
651
|
-
|
|
652
|
-
humanLog(`\n👀 Watching ${rel} for changes — press Ctrl-C to stop.`);
|
|
653
|
-
|
|
654
|
-
let building = false;
|
|
655
|
-
let queued = false;
|
|
656
|
-
let debounce = null;
|
|
657
|
-
|
|
658
|
-
const rebuild = async () => {
|
|
659
|
-
if (building) {
|
|
660
|
-
// Coalesce changes that land mid-build into a single follow-up run.
|
|
661
|
-
queued = true;
|
|
662
|
-
return;
|
|
663
|
-
}
|
|
664
|
-
building = true;
|
|
665
|
-
humanLog(`\n♻️ Change detected — rebuilding ${rel}...`);
|
|
666
|
-
await runThemeBuildOnceChild(file, options);
|
|
667
|
-
building = false;
|
|
668
|
-
humanLog(`\n👀 Watching ${rel} for changes — press Ctrl-C to stop.`);
|
|
669
|
-
if (queued) {
|
|
670
|
-
queued = false;
|
|
671
|
-
rebuild();
|
|
672
|
-
}
|
|
673
|
-
};
|
|
674
|
-
|
|
675
|
-
// Some editors replace the file (rename) rather than writing in place, which
|
|
676
|
-
// can drop the watch. Watch the containing directory and filter to our file
|
|
677
|
-
// so edits survive atomic-save/rename.
|
|
678
|
-
const watchDir = path.dirname(filePath);
|
|
679
|
-
const baseName = path.basename(filePath);
|
|
680
|
-
const watcher = fs.watch(watchDir, (_eventType, changed) => {
|
|
681
|
-
if (changed && changed !== baseName) return;
|
|
682
|
-
clearTimeout(debounce);
|
|
683
|
-
// Debounce: editors often emit several events per save.
|
|
684
|
-
debounce = setTimeout(rebuild, 100);
|
|
685
|
-
});
|
|
686
|
-
|
|
687
|
-
await new Promise(resolve => {
|
|
688
|
-
const stop = () => {
|
|
689
|
-
clearTimeout(debounce);
|
|
690
|
-
watcher.close();
|
|
691
|
-
humanLog('\nStopped watching.');
|
|
692
|
-
resolve();
|
|
693
|
-
};
|
|
694
|
-
process.once('SIGINT', stop);
|
|
695
|
-
process.once('SIGTERM', stop);
|
|
696
|
-
});
|
|
697
|
-
}
|
|
698
|
-
|
|
699
600
|
export function registerTheme(program) {
|
|
700
601
|
const theme = program
|
|
701
602
|
.command('theme')
|
|
@@ -720,10 +621,6 @@ export function registerTheme(program) {
|
|
|
720
621
|
.command('build <file>')
|
|
721
622
|
.description('Compile a defineTheme file to CSS + JS')
|
|
722
623
|
.option('-o, --out <path>', 'Output CSS file path')
|
|
723
|
-
.option(
|
|
724
|
-
'-w, --watch',
|
|
725
|
-
'Rebuild automatically when the theme file changes (Ctrl-C to stop)',
|
|
726
|
-
)
|
|
727
624
|
.action(async (file, options) => {
|
|
728
625
|
const filePath = path.resolve(process.cwd(), file);
|
|
729
626
|
const json = program.opts().json || false;
|
|
@@ -733,20 +630,6 @@ export function registerTheme(program) {
|
|
|
733
630
|
return;
|
|
734
631
|
}
|
|
735
632
|
|
|
736
|
-
// Watch mode: run an initial build, then rebuild on every change to the
|
|
737
|
-
// theme file. Watch is a human-interactive, long-running mode — it is not
|
|
738
|
-
// supported in --json (machine) mode, which expects a single envelope.
|
|
739
|
-
if (options.watch) {
|
|
740
|
-
if (json) {
|
|
741
|
-
cliError('--watch is not supported with --json', {
|
|
742
|
-
code: ERROR_CODES.ERR_THEME_INVALID,
|
|
743
|
-
});
|
|
744
|
-
return;
|
|
745
|
-
}
|
|
746
|
-
await runThemeBuildWatch(file, filePath, options);
|
|
747
|
-
return;
|
|
748
|
-
}
|
|
749
|
-
|
|
750
633
|
if (!json) humanLog(`\nBuilding theme from ${path.relative(process.cwd(), filePath)}...`);
|
|
751
634
|
|
|
752
635
|
// Extract theme definition
|
package/src/index.mjs
CHANGED
|
@@ -245,7 +245,6 @@ const commands = [
|
|
|
245
245
|
{name: 'init', path: './commands/init.mjs', register: 'registerInit'},
|
|
246
246
|
{name: 'component', path: './commands/component/index.mjs', register: 'registerComponent'},
|
|
247
247
|
{name: 'docs', path: './commands/docs.mjs', register: 'registerDocs'},
|
|
248
|
-
{name: 'blog', path: './commands/blog.mjs', register: 'registerBlog'},
|
|
249
248
|
{name: 'swizzle', path: './commands/swizzle.mjs', register: 'registerSwizzle'},
|
|
250
249
|
// agent-docs folded into init — functions still importable from agent-docs.mjs
|
|
251
250
|
{name: 'template', path: './commands/template.mjs', register: 'registerTemplate'},
|