@astryxdesign/cli 0.3.0-canary.fbc60c5 → 0.3.0-canary.fcbc342
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 +8 -8
- package/api/blog/blog.doc.mjs +2 -2
- package/api/build/build.doc.mjs +1 -1
- package/api/component/component.doc.mjs +1 -1
- package/api/discover/discover.doc.mjs +2 -2
- package/api/docs/docs.doc.mjs +2 -2
- package/api/doctor/doctor.doc.mjs +3 -3
- package/api/hook/hook.doc.mjs +1 -1
- package/api/init/init.doc.mjs +1 -1
- package/api/integration/summarizeIssues.doc.mjs +1 -1
- package/api/integration/validateIntegration.doc.mjs +1 -1
- package/api/json/assertResponse.doc.mjs +2 -2
- package/api/json/isError.doc.mjs +1 -1
- package/api/json/parseResponse.doc.mjs +2 -2
- package/api/layout/layoutCheck.doc.mjs +1 -1
- package/api/layout/layoutExpand.doc.mjs +1 -1
- package/api/layout/layoutGrammar.doc.mjs +1 -1
- package/api/swizzle/swizzle.doc.mjs +1 -1
- package/api/template/template.test.mjs +38 -13
- package/api/theme/listThemes.doc.mjs +2 -2
- package/api/theme/themeAdd.doc.mjs +1 -1
- package/api/theme/themeBuild.doc.mjs +3 -3
- package/api/theme/themeList.doc.mjs +2 -2
- package/api/upgrade/upgrade.doc.mjs +1 -1
- package/assets/codemods/transforms/next/__tests__/next-codemods.test.mjs +92 -0
- package/assets/codemods/transforms/next/index.mjs +11 -1
- package/assets/codemods/transforms/next/rename-dropdown-menu-radio-dot-target.mjs +152 -0
- package/assets/codemods/transforms/v0.3.0/__tests__/migrate-grid-minchildwidth-to-columns.test.mjs +82 -0
- package/assets/codemods/transforms/v0.3.0/__tests__/migrate-table-rowexpansion-to-tree.test.mjs +201 -0
- package/assets/codemods/transforms/v0.3.0/index.mjs +8 -0
- package/assets/codemods/transforms/v0.3.0/migrate-grid-minchildwidth-to-columns.mjs +38 -2
- package/assets/codemods/transforms/v0.3.0/migrate-table-rowexpansion-to-tree.mjs +214 -0
- package/assets/docs/browser-support.doc.mjs +6 -6
- package/assets/docs/getting-started.doc.mjs +3 -3
- package/assets/docs/icons.doc.mjs +3 -3
- package/assets/docs/illustrations.doc.mjs +2 -2
- package/assets/docs/internationalization.doc.mjs +1 -1
- package/assets/docs/layout.doc.dense.mjs +1 -1
- package/assets/docs/migration.doc.mjs +1 -1
- package/assets/docs/principles.doc.mjs +1 -1
- package/assets/docs/styling-libraries.doc.mjs +1 -1
- package/assets/docs/styling.doc.mjs +4 -4
- package/assets/docs/theme.doc.mjs +3 -3
- package/assets/docs/typography.doc.mjs +2 -2
- package/assets/templates/blocks/components/AspectRatio/AspectRatioCircleImage.tsx +1 -1
- package/assets/templates/blocks/components/AspectRatio/AspectRatioImageGallery.tsx +1 -1
- package/assets/templates/blocks/components/AspectRatio/AspectRatioShowcase.tsx +3 -3
- package/assets/templates/blocks/components/AspectRatio/AspectRatioSquareImage.tsx +1 -1
- package/assets/templates/blocks/components/AspectRatio/AspectRatioWidescreen.tsx +1 -1
- package/assets/templates/blocks/components/Avatar/AvatarFallbackChain.tsx +6 -6
- package/assets/templates/blocks/components/Avatar/AvatarGroup.tsx +5 -5
- package/assets/templates/blocks/components/Avatar/AvatarInteractive.tsx +2 -2
- package/assets/templates/blocks/components/Avatar/AvatarShowcase.tsx +4 -4
- package/assets/templates/blocks/components/Avatar/AvatarTooltip.tsx +4 -4
- package/assets/templates/blocks/components/Avatar/AvatarUserCard.tsx +3 -3
- package/assets/templates/blocks/components/Avatar/AvatarWithImage.tsx +4 -4
- package/assets/templates/blocks/components/Avatar/AvatarWithStatus.tsx +3 -3
- package/assets/templates/blocks/components/ChatComposerDrawer/ChatComposerDrawerAttachments.tsx +5 -5
- package/assets/templates/blocks/components/Lightbox/LightboxGallery.tsx +4 -4
- package/assets/templates/blocks/components/Lightbox/LightboxShowcase.tsx +1 -1
- package/assets/templates/blocks/components/Lightbox/LightboxVideo.tsx +1 -1
- package/assets/templates/blocks/components/Lightbox/LightboxZoom.tsx +2 -2
- package/assets/templates/blocks/components/MediaTheme/MediaThemeImageOverlay.tsx +1 -1
- package/assets/templates/blocks/components/MediaTheme/MediaThemeLightScrim.tsx +1 -1
- package/assets/templates/blocks/components/MediaTheme/MediaThemeShowcase.tsx +1 -1
- package/assets/templates/blocks/components/Overlay/OverlayBottomStrip.tsx +1 -1
- package/assets/templates/blocks/components/Overlay/OverlayHoverReveal.tsx +1 -1
- package/assets/templates/blocks/components/Overlay/OverlayShowcase.tsx +1 -1
- package/assets/templates/blocks/components/Stepper/StepperHorizontal.doc.mjs +14 -0
- package/assets/templates/blocks/components/Stepper/StepperHorizontal.tsx +24 -0
- package/assets/templates/blocks/components/Stepper/StepperIndicatorModes.doc.mjs +14 -0
- package/assets/templates/blocks/components/Stepper/StepperIndicatorModes.tsx +68 -0
- package/assets/templates/blocks/components/Stepper/StepperMultiStepForm.doc.mjs +14 -0
- package/assets/templates/blocks/components/Stepper/StepperMultiStepForm.tsx +92 -0
- package/assets/templates/blocks/components/Stepper/StepperOnTrackVertical.doc.mjs +14 -0
- package/assets/templates/blocks/components/Stepper/StepperOnTrackVertical.tsx +41 -0
- package/assets/templates/blocks/components/Stepper/StepperShowcase.doc.mjs +15 -0
- package/assets/templates/blocks/components/Stepper/StepperShowcase.tsx +25 -0
- package/assets/templates/blocks/components/Stepper/StepperStatus.doc.mjs +14 -0
- package/assets/templates/blocks/components/Stepper/StepperStatus.tsx +50 -0
- package/assets/templates/blocks/components/Stepper/StepperVerticalOnboarding.doc.mjs +14 -0
- package/assets/templates/blocks/components/Stepper/StepperVerticalOnboarding.tsx +40 -0
- package/assets/templates/blocks/components/Table/TableRowExpansionTable.tsx +61 -58
- package/assets/templates/blocks/components/TextArea/TextAreaStates.tsx +1 -1
- package/assets/templates/blocks/components/TopNav/TopNavMegaMenu.tsx +1 -1
- package/assets/templates/pages/centered-hero/page.tsx +1 -1
- package/assets/templates/pages/classic-gallery/page.tsx +10 -10
- package/assets/templates/pages/detail-page/page.tsx +5 -5
- package/assets/templates/pages/form-two-column/page.tsx +1 -1
- package/assets/templates/pages/gallery-hero/page.tsx +3 -3
- package/assets/templates/pages/library/page.tsx +30 -30
- package/assets/templates/pages/login/page.tsx +1 -2
- package/assets/templates/pages/login-card/page.tsx +1 -2
- package/assets/templates/pages/login-split/page.tsx +5 -6
- package/assets/templates/pages/login-sso/page.tsx +2 -3
- package/assets/templates/pages/mixed-gallery/page.tsx +5 -5
- package/assets/templates/pages/payment-form/page.tsx +3 -3
- package/assets/templates/pages/product-detail/page.tsx +7 -7
- package/assets/templates/pages/product-gallery/page.tsx +6 -6
- package/assets/templates/pages/shell-top-nav/page.tsx +2 -2
- package/assets/templates/pages/side-gallery/page.tsx +9 -9
- package/assets/templates/pages/table-page-chart/page.tsx +6 -6
- package/assets/templates/pages/theme-showcase/page.tsx +6 -6
- package/assets/templates/themes/neutral/neutralTheme.ts +4 -1
- package/authoring/codemod/codemod.doc.mjs +2 -2
- package/authoring/config/config.doc.mjs +1 -1
- package/authoring/doctypes/base/type.ts +21 -0
- package/authoring/doctypes/command/command.doc.mjs +2 -2
- package/authoring/doctypes/component/component.doc.mjs +7 -7
- package/authoring/doctypes/enum/enum.doc.mjs +2 -2
- package/authoring/doctypes/function/function.doc.mjs +3 -3
- package/authoring/doctypes/hook/hook.doc.mjs +3 -3
- package/authoring/doctypes/reference/reference.doc.mjs +3 -3
- package/authoring/doctypes/schema/schema.doc.mjs +1 -1
- package/authoring/doctypes/template/template.doc.mjs +3 -3
- package/clients/cli/commands/build-theme.registry.test.mjs +14 -1
- package/clients/cli/commands/build.doc.mjs +1 -1
- package/clients/cli/commands/component.doc.mjs +1 -1
- package/clients/cli/commands/doctor.doc.mjs +2 -2
- package/clients/cli/commands/layout-expand.doc.mjs +1 -1
- package/clients/cli/commands/layout.doc.mjs +1 -1
- package/clients/cli/commands/manifest.doc.mjs +3 -3
- package/clients/cli/commands/search.doc.mjs +1 -1
- package/clients/cli/commands/theme-add.doc.mjs +1 -1
- package/clients/cli/commands/theme-build.doc.mjs +1 -1
- package/clients/cli/commands/theme-list.doc.mjs +1 -1
- package/clients/cli/commands/theme.doc.mjs +2 -2
- package/clients/cli/commands/validate-integration.doc.mjs +2 -2
- package/foundation/agent-docs/agent-docs.mjs +3 -4
- package/foundation/agent-docs/agent-docs.test.mjs +8 -0
- package/foundation/discovery/template-adapter.d.mts +6 -3
- package/foundation/discovery/template-adapter.mjs +33 -13
- package/foundation/response/response-types.doc.mjs +7 -7
- package/foundation/response/response.doc.mjs +5 -5
- package/package.json +9 -9
package/README.md
CHANGED
|
@@ -72,7 +72,7 @@ Options:
|
|
|
72
72
|
| `search` | Search components, hooks, docs, and templates in one ranked list |
|
|
73
73
|
| `swizzle` | Copy component source for customization |
|
|
74
74
|
| `template` | Inject a page or block template |
|
|
75
|
-
| `theme` | Theme tools
|
|
75
|
+
| `theme` | Theme tools: build, export, and manage themes |
|
|
76
76
|
| `upgrade` | Run codemods to migrate between versions |
|
|
77
77
|
| `validate-integration` | Validate an Astryx integration package (manifest + contributions) |
|
|
78
78
|
|
|
@@ -385,7 +385,7 @@ Every response has a `type` discriminant. The full set is below (generated from
|
|
|
385
385
|
|
|
386
386
|
| Type | What `data` carries |
|
|
387
387
|
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
388
|
-
| `component.list` | The component catalog grouped by category: `detail` (the level
|
|
388
|
+
| `component.list` | The component catalog grouped by category: `detail` (the level: names \| compact \| full) and `components`, the grouped map of names+package, brief entries, or a full ComponentDoc per entry. |
|
|
389
389
|
| `component.detail` | One component's authored ComponentDoc plus ownership metadata (owner package, import specifier, and whether source is available). |
|
|
390
390
|
| `component.detail.props` | Just one component's props table (ComponentPropDoc[]). |
|
|
391
391
|
| `component.detail.source` | One component's source file, as {component, source}. |
|
|
@@ -393,12 +393,12 @@ Every response has a `type` discriminant. The full set is below (generated from
|
|
|
393
393
|
| `component.detail.blocks` | One component's example blocks, as {component, showcase, examples, related} of BlockEntry. |
|
|
394
394
|
| `docs.list` | All reference-doc topics as DocsListEntry[] ({topic, description}), in discovery order. |
|
|
395
395
|
| `docs.detail` | One topic's full ReferenceDoc, with token-ref blocks inlined. |
|
|
396
|
-
| `docs.detail.section` | A single ReferenceSection of a topic
|
|
397
|
-
| `blog.list` | The feed URL plus every post parsed from the RSS feed
|
|
396
|
+
| `docs.detail.section` | A single ReferenceSection of a topic: the first whose title contains the section query. |
|
|
397
|
+
| `blog.list` | The feed URL plus every post parsed from the RSS feed, each with slug, title, description, date, type, authors, link, and plaintext URL. |
|
|
398
398
|
| `blog.detail` | One post's metadata plus the feed URL and the post's full plaintext body. |
|
|
399
399
|
| `discover.list` | The configured external packages (name, category, components, version, description); when empty it carries meta.configured to tell "nothing configured" from "nothing discovered". |
|
|
400
400
|
| `discover.detail` | A single external package entry, for an @scope/name query. |
|
|
401
|
-
| `discover.detail.doc` | The validated ComponentDoc for one external component
|
|
401
|
+
| `discover.detail.doc` | The validated ComponentDoc for one external component: an @scope/name/Component query, or a free-text term resolving to exactly one component. |
|
|
402
402
|
| `discover.search` | The echoed query plus the matching {package, component} pairs, when a free-text term matches several components. |
|
|
403
403
|
| `search` | The echoed query plus a ranked SearchResultEntry[] (domain, name, score, reason, description, follow-up command, and import path where relevant). |
|
|
404
404
|
| `build.help` | A marker (`playbook: true`) that the renderer expands into the how-to-build-a-page workflow; emitted when no query is given. |
|
|
@@ -409,15 +409,15 @@ Every response has a `type` discriminant. The full set is below (generated from
|
|
|
409
409
|
| `template.show` | The resolved template's raw source plus its description, kind, and the component names it composes. |
|
|
410
410
|
| `template.skeleton` | A layout skeleton (structural tags with spatial annotations) plus the template's description and the components it composes. |
|
|
411
411
|
| `template.copy` | A scaffold receipt: template id, output directory, written file name, and file count. |
|
|
412
|
-
| `hook.list` | The hook catalog grouped by category: `detail` (the level
|
|
412
|
+
| `hook.list` | The hook catalog grouped by category: `detail` (the level: names \| compact \| full) and `components`, the grouped map of hook names, brief entries, or a full HookDoc per entry. |
|
|
413
413
|
| `hook.detail` | One hook's full authored HookDoc. |
|
|
414
414
|
| `hook.detail.params` | Just one hook's parameters table (HookParamDoc[]). |
|
|
415
415
|
| `theme.build` | A theme build receipt: name, token- and component-override counts, output size, the written outputs {css, js, dts, and variantsDts when applicable}, and any validation warnings. |
|
|
416
416
|
| `theme.build.check` | The --check receipt: theme name, an upToDate flag, the stale outputs (each {path, reason: missing \| outdated}), and the full list of checked paths. Writes nothing. |
|
|
417
|
-
| `theme.list` | Every bundled theme as a ThemeListEntry[]
|
|
417
|
+
| `theme.list` | Every bundled theme as a ThemeListEntry[]: each with slug, displayName, description, and a maintained flag. |
|
|
418
418
|
| `theme.add` | A scaffold receipt: resolved slug, displayName, maintained flag, outputDir (relative to cwd), the theme entry file, its exportName, and the files written. |
|
|
419
419
|
| `upgrade.list` | Every available codemod, oldest→newest, as {name, title, version, optional}; returned for --list without running anything. |
|
|
420
|
-
| `upgrade.status` | A short-circuit outcome with no codemods run
|
|
420
|
+
| `upgrade.status` | A short-circuit outcome with no codemods run (up_to_date, no_codemods, or config_fixable), each carrying the agent-docs summary. |
|
|
421
421
|
| `upgrade.run` | The run receipt: from/to versions, codemod count, integrations processed, the agent-docs summary, and (apply mode) filesChanged, transformsApplied, and per-codemod errors. |
|
|
422
422
|
| `manifest` | The self-describing CLI capability manifest: name, version, apiVersion, global options, the command tree (args, options, json flag, response types, examples), the jsonSupported allowlist, and the flat responseTypes index. |
|
|
423
423
|
| `doctor` | The health-check report: `checks` (each with id, label, status: pass \| warn \| fail \| info, a message, and a fix when not passing) plus a `summary` of counts per status. |
|
package/api/blog/blog.doc.mjs
CHANGED
|
@@ -14,7 +14,7 @@ export const doc = {
|
|
|
14
14
|
displayName: 'blog()',
|
|
15
15
|
summary: 'List blog posts, or read one, from the published RSS feed.',
|
|
16
16
|
description:
|
|
17
|
-
'Reads the design system blog the same way any feed reader does
|
|
17
|
+
'Reads the design system blog the same way any feed reader does, over the ' +
|
|
18
18
|
"published RSS feed, never the blog's source files. With no slug it lists every " +
|
|
19
19
|
"post parsed from the feed; with a slug it reads that post's full plaintext body " +
|
|
20
20
|
'via the .txt alternate the feed advertises. Both envelopes carry feedUrl so a ' +
|
|
@@ -35,7 +35,7 @@ export const doc = {
|
|
|
35
35
|
{
|
|
36
36
|
type: 'blog.list',
|
|
37
37
|
description:
|
|
38
|
-
'The feed URL plus every post parsed from the feed
|
|
38
|
+
'The feed URL plus every post parsed from the feed, each with slug, title, description, date, type, authors, link, and its plaintext URL.',
|
|
39
39
|
},
|
|
40
40
|
{
|
|
41
41
|
type: 'blog.detail',
|
package/api/build/build.doc.mjs
CHANGED
|
@@ -54,7 +54,7 @@ export const doc = {
|
|
|
54
54
|
{
|
|
55
55
|
type: 'build.help',
|
|
56
56
|
description:
|
|
57
|
-
'Emitted when the query is omitted
|
|
57
|
+
'Emitted when the query is omitted: a pure marker (`data.playbook: true`) that the command renderer expands into the page-building workflow prose.',
|
|
58
58
|
},
|
|
59
59
|
{
|
|
60
60
|
type: 'build.kit',
|
|
@@ -108,7 +108,7 @@ export const doc = {
|
|
|
108
108
|
{
|
|
109
109
|
type: 'component.list',
|
|
110
110
|
description:
|
|
111
|
-
"The catalog grouped by category. data.detail is the level ('names' | 'compact' | 'full') and data.components is the grouped map
|
|
111
|
+
"The catalog grouped by category. data.detail is the level ('names' | 'compact' | 'full') and data.components is the grouped map: names+package, brief entries, or full ComponentDoc per entry.",
|
|
112
112
|
},
|
|
113
113
|
{
|
|
114
114
|
type: 'component.detail',
|
|
@@ -15,7 +15,7 @@ export const doc = {
|
|
|
15
15
|
summary: 'Browse and search components from configured external packages.',
|
|
16
16
|
description:
|
|
17
17
|
'Explores components contributed by configured external packages and integrations ' +
|
|
18
|
-
'
|
|
18
|
+
'the ones that declare a components root. With no query it lists those packages; ' +
|
|
19
19
|
'an @scope/name query browses one package; @scope/name/Component (or a free-text ' +
|
|
20
20
|
"term that resolves to a single component) returns that component's validated doc; " +
|
|
21
21
|
'a free-text term with several matches returns the candidate list.',
|
|
@@ -68,7 +68,7 @@ export const doc = {
|
|
|
68
68
|
{
|
|
69
69
|
type: 'discover.detail.doc',
|
|
70
70
|
description:
|
|
71
|
-
'The validated ComponentDoc for one external component
|
|
71
|
+
'The validated ComponentDoc for one external component: an @scope/name/Component query, or a free-text term that resolves to exactly one component.',
|
|
72
72
|
},
|
|
73
73
|
{
|
|
74
74
|
type: 'discover.search',
|
package/api/docs/docs.doc.mjs
CHANGED
|
@@ -13,7 +13,7 @@ export const doc = {
|
|
|
13
13
|
name: 'docs',
|
|
14
14
|
displayName: 'docs()',
|
|
15
15
|
summary:
|
|
16
|
-
'Read the reference docs
|
|
16
|
+
'Read the reference docs: list every topic, one topic, or a single section of a topic.',
|
|
17
17
|
description:
|
|
18
18
|
'Routes on its arguments: no topic lists every reference-doc topic; a topic ' +
|
|
19
19
|
'returns that full ReferenceDoc (with token-ref blocks inlined); a topic ' +
|
|
@@ -75,7 +75,7 @@ export const doc = {
|
|
|
75
75
|
{
|
|
76
76
|
type: 'docs.detail.section',
|
|
77
77
|
description:
|
|
78
|
-
'A single ReferenceSection of the topic
|
|
78
|
+
'A single ReferenceSection of the topic: the first whose title contains the section query.',
|
|
79
79
|
},
|
|
80
80
|
],
|
|
81
81
|
throws: [
|
|
@@ -14,10 +14,10 @@ export const doc = {
|
|
|
14
14
|
displayName: 'doctor()',
|
|
15
15
|
summary: 'Read-only project + environment health check.',
|
|
16
16
|
description:
|
|
17
|
-
'Runs a series of side-effect-free diagnostics
|
|
17
|
+
'Runs a series of side-effect-free diagnostics: Node version, ' +
|
|
18
18
|
'@astryxdesign/core install and version alignment with the CLI, installed ' +
|
|
19
19
|
'themes and wiring, astryx.config validity, agent docs, core peer ' +
|
|
20
|
-
'dependencies, and the detected package manager
|
|
20
|
+
'dependencies, and the detected package manager, and returns a structured ' +
|
|
21
21
|
'report. It only reads (never installs, writes, or mutates), so it is safe ' +
|
|
22
22
|
'as a CI gate and for agents to invoke.',
|
|
23
23
|
importPath: '@astryxdesign/cli/api',
|
|
@@ -34,7 +34,7 @@ export const doc = {
|
|
|
34
34
|
{
|
|
35
35
|
type: 'doctor',
|
|
36
36
|
description:
|
|
37
|
-
'The diagnostic report: `data.checks
|
|
37
|
+
'The diagnostic report: `data.checks`, each with a stable id, label, `status` (`pass` | `warn` | `fail` | `info`), a one-line message, and a `fix` when the status is not `pass`; plus `data.summary` with counts per status.',
|
|
38
38
|
},
|
|
39
39
|
],
|
|
40
40
|
examples: [
|
package/api/hook/hook.doc.mjs
CHANGED
|
@@ -70,7 +70,7 @@ export const doc = {
|
|
|
70
70
|
{
|
|
71
71
|
type: 'hook.list',
|
|
72
72
|
description:
|
|
73
|
-
"The catalog grouped by category. data.detail is the level ('names' | 'compact' | 'full') and data.components is the grouped map
|
|
73
|
+
"The catalog grouped by category. data.detail is the level ('names' | 'compact' | 'full') and data.components is the grouped map: hook names, brief entries, or full HookDoc per entry.",
|
|
74
74
|
},
|
|
75
75
|
{
|
|
76
76
|
type: 'hook.detail',
|
package/api/init/init.doc.mjs
CHANGED
|
@@ -69,7 +69,7 @@ export const doc = {
|
|
|
69
69
|
{
|
|
70
70
|
type: 'init.remove',
|
|
71
71
|
description:
|
|
72
|
-
'Confirmation that the managed agent-docs block was removed (`data.removed: true`)
|
|
72
|
+
'Confirmation that the managed agent-docs block was removed (`data.removed: true`), returned when `removeAgents` is set.',
|
|
73
73
|
},
|
|
74
74
|
],
|
|
75
75
|
throws: [
|
|
@@ -17,7 +17,7 @@ export const doc = {
|
|
|
17
17
|
'Tally integration issues by severity into error and warning counts.',
|
|
18
18
|
description:
|
|
19
19
|
'A synchronous helper that reduces an AstryxIntegrationIssue[] (as returned ' +
|
|
20
|
-
'by validateIntegration) to counts of errors and warnings
|
|
20
|
+
'by validateIntegration) to counts of errors and warnings: the seam a ' +
|
|
21
21
|
'caller uses to decide an exit code or print a summary line. Issues of any ' +
|
|
22
22
|
'other severity are ignored.',
|
|
23
23
|
importPath: '@astryxdesign/cli/api',
|
|
@@ -45,7 +45,7 @@ export const doc = {
|
|
|
45
45
|
{
|
|
46
46
|
type: 'integration.validate',
|
|
47
47
|
description:
|
|
48
|
-
'The result envelope: `data.name` and `data.version` of the validated package (both null when no local manifest is found), plus `data.issues
|
|
48
|
+
'The result envelope: `data.name` and `data.version` of the validated package (both null when no local manifest is found), plus `data.issues`, an AstryxIntegrationIssue[] of {code, severity: `warning` | `error`, message}.',
|
|
49
49
|
},
|
|
50
50
|
],
|
|
51
51
|
examples: [
|
|
@@ -27,7 +27,7 @@ export const doc = {
|
|
|
27
27
|
name: 'raw',
|
|
28
28
|
type: 'unknown',
|
|
29
29
|
description:
|
|
30
|
-
'The CLI stdout to parse
|
|
30
|
+
'The CLI stdout to parse: a JSON string, or an object that was already parsed.',
|
|
31
31
|
required: true,
|
|
32
32
|
},
|
|
33
33
|
{
|
|
@@ -42,7 +42,7 @@ export const doc = {
|
|
|
42
42
|
{
|
|
43
43
|
type: 'any',
|
|
44
44
|
description:
|
|
45
|
-
'The parsed envelope, guaranteed at runtime to carry the requested `type`. The published signature is untyped
|
|
45
|
+
'The parsed envelope, guaranteed at runtime to carry the requested `type`. The published signature is untyped; cast to the matching *Response type for typed access.',
|
|
46
46
|
},
|
|
47
47
|
],
|
|
48
48
|
throws: [
|
package/api/json/isError.doc.mjs
CHANGED
|
@@ -14,7 +14,7 @@ export const doc = {
|
|
|
14
14
|
displayName: 'isError()',
|
|
15
15
|
summary: 'Did the CLI return an error envelope?',
|
|
16
16
|
description:
|
|
17
|
-
'Tests a parsed response for an `error` key. Branch on this before touching `data
|
|
17
|
+
'Tests a parsed response for an `error` key. Branch on this before touching `data`: ' +
|
|
18
18
|
'and prefer the stable `code` field over matching the human-readable message, which is ' +
|
|
19
19
|
'not a contract. Note this returns a plain boolean, not a TypeScript type predicate, so ' +
|
|
20
20
|
'it does not narrow on its own: cast to the matching *Response type to get typed access.',
|
|
@@ -26,7 +26,7 @@ export const doc = {
|
|
|
26
26
|
name: 'raw',
|
|
27
27
|
type: 'unknown',
|
|
28
28
|
description:
|
|
29
|
-
'The CLI stdout to parse
|
|
29
|
+
'The CLI stdout to parse: a JSON string, or an object that was already parsed.',
|
|
30
30
|
required: true,
|
|
31
31
|
},
|
|
32
32
|
],
|
|
@@ -34,7 +34,7 @@ export const doc = {
|
|
|
34
34
|
{
|
|
35
35
|
type: 'any',
|
|
36
36
|
description:
|
|
37
|
-
'The { type, data, meta? } envelope, or a CLIError envelope. The published signature is intentionally untyped
|
|
37
|
+
'The { type, data, meta? } envelope, or a CLIError envelope. The published signature is intentionally untyped; narrow it by casting to the matching *Response type exported from @astryxdesign/cli/json.',
|
|
38
38
|
},
|
|
39
39
|
],
|
|
40
40
|
throws: [
|
|
@@ -18,7 +18,7 @@ export const doc = {
|
|
|
18
18
|
'The validator behind `astryx layout check`. Parses and validates a compressed XLE/XLO ' +
|
|
19
19
|
'expression without generating any TSX, and echoes it back in both canonical surfaces ' +
|
|
20
20
|
'(compact and outline). Validation failures are reported in the layout.check envelope ' +
|
|
21
|
-
'(valid: false) with line/col and suggestions
|
|
21
|
+
'(valid: false) with line/col and suggestions (not thrown) so callers can lint an ' +
|
|
22
22
|
'expression and surface fixes.',
|
|
23
23
|
importPath: '@astryxdesign/cli/api',
|
|
24
24
|
signature:
|
|
@@ -16,7 +16,7 @@ export const doc = {
|
|
|
16
16
|
summary: 'Expand a validated layout expression into XDS TSX.',
|
|
17
17
|
description:
|
|
18
18
|
'The generator behind `astryx layout expand`. Parses and validates a compressed XLE/XLO ' +
|
|
19
|
-
'expression, then expands it into ready-to-use XDS TSX
|
|
19
|
+
'expression, then expands it into ready-to-use XDS TSX, auto-routing structural children ' +
|
|
20
20
|
'into the right slots, scaffolding typed useState for interactive controls, and splicing or ' +
|
|
21
21
|
'importing any referenced template blocks. Returns the code (and metadata) in a layout.expand ' +
|
|
22
22
|
'envelope, optionally writing it to a path within cwd.',
|
|
@@ -15,7 +15,7 @@ export const doc = {
|
|
|
15
15
|
displayName: 'layoutGrammar()',
|
|
16
16
|
summary: 'Return the XLE/XLO grammar cheatsheet for this install.',
|
|
17
17
|
description:
|
|
18
|
-
'The reference behind `astryx layout grammar
|
|
18
|
+
'The reference behind `astryx layout grammar`: the agent cheatsheet for writing XLE/XLO ' +
|
|
19
19
|
"layout expressions, with the alias table generated from this branch's registry rather than " +
|
|
20
20
|
'hand-maintained, so short names always reflect the components actually installed.',
|
|
21
21
|
importPath: '@astryxdesign/cli/api',
|
|
@@ -88,7 +88,7 @@ export const doc = {
|
|
|
88
88
|
},
|
|
89
89
|
{
|
|
90
90
|
code: 'ERR_AMBIGUOUS_COMPONENT',
|
|
91
|
-
when: 'more than one package provides the component
|
|
91
|
+
when: 'more than one package provides the component; choose one with package',
|
|
92
92
|
},
|
|
93
93
|
{
|
|
94
94
|
code: 'ERR_NO_SOURCE',
|
|
@@ -4,36 +4,35 @@ import {describe, it, expect} from 'vitest';
|
|
|
4
4
|
import {stripTemplateAssetRefs, template} from './template.mjs';
|
|
5
5
|
|
|
6
6
|
describe('stripTemplateAssetRefs', () => {
|
|
7
|
-
it('replaces a
|
|
7
|
+
it('replaces a /template-assets image path with an inline data URI', () => {
|
|
8
8
|
const src =
|
|
9
|
-
"const hero = '
|
|
9
|
+
"const hero = '/template-assets/colorful-home-horizontal-1.png';";
|
|
10
10
|
const out = stripTemplateAssetRefs(src);
|
|
11
|
-
expect(out).not.toContain('
|
|
11
|
+
expect(out).not.toContain('/template-assets/');
|
|
12
12
|
expect(out).toContain('data:image/svg+xml,');
|
|
13
13
|
});
|
|
14
14
|
|
|
15
|
-
it('replaces a
|
|
16
|
-
const src =
|
|
17
|
-
'src="https://lookaside.facebook.com/assets/astryx/avatar-profile-05.jpg"';
|
|
15
|
+
it('replaces a /template-assets block-avatar image path', () => {
|
|
16
|
+
const src = 'src="/template-assets/avatar-profile-05.jpg"';
|
|
18
17
|
const out = stripTemplateAssetRefs(src);
|
|
19
|
-
expect(out).not.toContain('
|
|
18
|
+
expect(out).not.toContain('/template-assets/');
|
|
20
19
|
expect(out).toContain('data:image/svg+xml,');
|
|
21
20
|
});
|
|
22
21
|
|
|
23
|
-
it('replaces every
|
|
22
|
+
it('replaces every /template-assets reference, not just the first', () => {
|
|
24
23
|
const src = [
|
|
25
|
-
"'
|
|
26
|
-
"'
|
|
27
|
-
"'
|
|
24
|
+
"'/template-assets/colorful-home-horizontal-1.png'",
|
|
25
|
+
"'/template-assets/illustrative-horizontal-3.png'",
|
|
26
|
+
"'/template-assets/moody-scene-horizontal-1.png'",
|
|
28
27
|
].join('\n');
|
|
29
28
|
const out = stripTemplateAssetRefs(src);
|
|
30
|
-
expect(out).not.toContain('
|
|
29
|
+
expect(out).not.toContain('/template-assets/');
|
|
31
30
|
expect(out.match(/data:image\/svg\+xml,/g)).toHaveLength(3);
|
|
32
31
|
});
|
|
33
32
|
|
|
34
33
|
it('preserves surrounding source structure', () => {
|
|
35
34
|
const src =
|
|
36
|
-
"const data = [{src: '
|
|
35
|
+
"const data = [{src: '/template-assets/x.png', alt: 'X'}];";
|
|
37
36
|
const out = stripTemplateAssetRefs(src);
|
|
38
37
|
expect(out).toContain("alt: 'X'");
|
|
39
38
|
expect(out).toContain('const data = [{src:');
|
|
@@ -53,6 +52,32 @@ describe('stripTemplateAssetRefs', () => {
|
|
|
53
52
|
const out = stripTemplateAssetRefs(src);
|
|
54
53
|
expect(out).toBe(src);
|
|
55
54
|
});
|
|
55
|
+
|
|
56
|
+
it('strips a /template-assets .mp4 source to an empty string, not the image data URI (#4780)', () => {
|
|
57
|
+
const src = "src: '/template-assets/Nature-1.mp4',";
|
|
58
|
+
const out = stripTemplateAssetRefs(src);
|
|
59
|
+
expect(out).toBe("src: '',");
|
|
60
|
+
expect(out).not.toContain('data:image/svg+xml,');
|
|
61
|
+
expect(out).not.toContain('/template-assets/');
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('strips other video extensions (.webm, .mov, .ogv) the same way', () => {
|
|
65
|
+
for (const ext of ['webm', 'mov', 'ogv']) {
|
|
66
|
+
const src = `src: '/template-assets/clip.${ext}',`;
|
|
67
|
+
const out = stripTemplateAssetRefs(src);
|
|
68
|
+
expect(out).toBe("src: '',");
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('still replaces an adjacent image reference with the placeholder when a video reference is also present', () => {
|
|
73
|
+
const src = [
|
|
74
|
+
"poster: '/template-assets/Nature-1-poster.jpg',",
|
|
75
|
+
"src: '/template-assets/Nature-1.mp4',",
|
|
76
|
+
].join('\n');
|
|
77
|
+
const out = stripTemplateAssetRefs(src);
|
|
78
|
+
expect(out).toContain('data:image/svg+xml,');
|
|
79
|
+
expect(out).toContain("src: '',");
|
|
80
|
+
});
|
|
56
81
|
});
|
|
57
82
|
|
|
58
83
|
describe('template --skeleton component extraction (prefix-agnostic)', () => {
|
|
@@ -16,7 +16,7 @@ export const doc = {
|
|
|
16
16
|
displayName: 'listThemes()',
|
|
17
17
|
summary: 'Read the bundled-theme manifest and return its raw entries.',
|
|
18
18
|
description:
|
|
19
|
-
"The shared data layer behind theme list/add
|
|
19
|
+
"The shared data layer behind theme list/add: reads the CLI's bundled-theme manifest " +
|
|
20
20
|
'(templates/themes/manifest.json, generated by scripts/generate-cli-themes.mjs) and returns ' +
|
|
21
21
|
'the parsed entries. themeList() projects this into the theme.list envelope; themeAdd() ' +
|
|
22
22
|
'resolves a slug against it. Returns synchronously.',
|
|
@@ -28,7 +28,7 @@ export const doc = {
|
|
|
28
28
|
{
|
|
29
29
|
type: 'BundledTheme[]',
|
|
30
30
|
description:
|
|
31
|
-
'The parsed themes array from the bundle manifest
|
|
31
|
+
'The parsed themes array from the bundle manifest: each BundledTheme has slug, displayName, description, maintained, entry, exportName, and files. Empty when the manifest has not been generated.',
|
|
32
32
|
},
|
|
33
33
|
],
|
|
34
34
|
throws: [
|
|
@@ -16,7 +16,7 @@ export const doc = {
|
|
|
16
16
|
summary: 'Scaffold a bundled theme into a project as editable source.',
|
|
17
17
|
description:
|
|
18
18
|
"Copies a bundled theme's source (from the CLI's templates/themes/<slug>) into the " +
|
|
19
|
-
"consumer's project so they own it
|
|
19
|
+
"consumer's project so they own it, no theme package needed. Writes are staged to temp " +
|
|
20
20
|
'files then renamed, rolling back partials on failure so a failed write never leaves a ' +
|
|
21
21
|
'half-written theme. Returns a theme.add receipt describing where the files landed and how ' +
|
|
22
22
|
'to import them.',
|
|
@@ -20,7 +20,7 @@ export const doc = {
|
|
|
20
20
|
'emits the exact CSS the <Theme> runtime does), writes a scoped CSS file, a JS module ' +
|
|
21
21
|
'that re-exports the built theme, and a .d.ts (plus an optional .variants.d.ts when the ' +
|
|
22
22
|
'theme adds custom prop values). With {check: true} it writes nothing and instead compares ' +
|
|
23
|
-
'each output against disk, returning the drift
|
|
23
|
+
'each output against disk, returning the drift: the CI guard for committed, generated theme CSS.',
|
|
24
24
|
importPath: '@astryxdesign/cli/api',
|
|
25
25
|
signature:
|
|
26
26
|
'themeBuild(file: string, options?: {out?: string, check?: boolean}, ctx?: {cwd?: string}): Promise<ThemeBuildResponse | ThemeBuildCheckResponse | null>',
|
|
@@ -51,7 +51,7 @@ export const doc = {
|
|
|
51
51
|
name: 'options.check',
|
|
52
52
|
type: 'boolean',
|
|
53
53
|
description:
|
|
54
|
-
'Compile in memory and compare each output against what is on disk instead of writing
|
|
54
|
+
'Compile in memory and compare each output against what is on disk instead of writing: the CI drift guard.',
|
|
55
55
|
default: 'false',
|
|
56
56
|
},
|
|
57
57
|
{
|
|
@@ -86,7 +86,7 @@ export const doc = {
|
|
|
86
86
|
},
|
|
87
87
|
{
|
|
88
88
|
code: 'ERR_CORE_NOT_FOUND',
|
|
89
|
-
when: '@astryxdesign/core/theme cannot be imported
|
|
89
|
+
when: '@astryxdesign/core/theme cannot be imported; a built, resolvable @astryxdesign/core is required',
|
|
90
90
|
},
|
|
91
91
|
{
|
|
92
92
|
code: 'ERR_WRITE_FAILED',
|
|
@@ -15,7 +15,7 @@ export const doc = {
|
|
|
15
15
|
displayName: 'themeList()',
|
|
16
16
|
summary: 'List the themes bundled with this CLI build.',
|
|
17
17
|
description:
|
|
18
|
-
'Projects the bundled-theme manifest into the theme.list envelope
|
|
18
|
+
'Projects the bundled-theme manifest into the theme.list envelope: the themes that themeAdd ' +
|
|
19
19
|
'can scaffold. A pure projection of the manifest read by listThemes(); no I/O beyond that read, ' +
|
|
20
20
|
'and it returns synchronously.',
|
|
21
21
|
importPath: '@astryxdesign/cli/api',
|
|
@@ -26,7 +26,7 @@ export const doc = {
|
|
|
26
26
|
{
|
|
27
27
|
type: 'theme.list',
|
|
28
28
|
description:
|
|
29
|
-
'Every bundled theme as a ThemeListEntry[]
|
|
29
|
+
'Every bundled theme as a ThemeListEntry[]: each entry has slug, displayName, description, and a maintained flag.',
|
|
30
30
|
},
|
|
31
31
|
],
|
|
32
32
|
throws: [
|
|
@@ -86,7 +86,7 @@ export const doc = {
|
|
|
86
86
|
{
|
|
87
87
|
type: 'upgrade.list',
|
|
88
88
|
description:
|
|
89
|
-
'Every available codemod, oldest→newest, as {name, title, version, optional}
|
|
89
|
+
'Every available codemod, oldest→newest, as {name, title, version, optional}, returned when `list` is set; nothing is run.',
|
|
90
90
|
},
|
|
91
91
|
{
|
|
92
92
|
type: 'upgrade.status',
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file Unit tests for the staged (next-release) codemods.
|
|
5
|
+
*
|
|
6
|
+
* Mirrors v0.3.0/__tests__/next-codemods.test.mjs, which covers the codemods
|
|
7
|
+
* after promotion. Keeping a copy here means a staged transform is tested from
|
|
8
|
+
* the day it is written rather than the day it is released.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import {describe, expect, it} from 'vitest';
|
|
12
|
+
import jscodeshift from 'jscodeshift';
|
|
13
|
+
|
|
14
|
+
const j = jscodeshift.withParser('tsx');
|
|
15
|
+
const api = {jscodeshift: j, stats: () => {}, report: () => {}};
|
|
16
|
+
|
|
17
|
+
async function apply(name, source) {
|
|
18
|
+
const {default: transform} = await import(`../${name}.mjs`);
|
|
19
|
+
return transform({source, path: 'test.tsx'}, api) ?? source;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const TRANSFORM = 'rename-dropdown-menu-radio-dot-target';
|
|
23
|
+
|
|
24
|
+
describe('rename-dropdown-menu-radio-dot-target', () => {
|
|
25
|
+
it('renames the theme target key in a defineTheme components map', async () => {
|
|
26
|
+
const input = `import {defineTheme} from '@astryxdesign/core/theme';
|
|
27
|
+
export const theme = defineTheme({
|
|
28
|
+
name: 'brand',
|
|
29
|
+
components: {
|
|
30
|
+
'dropdown-menu-radio-dot': {base: {backgroundColor: 'var(--color-accent)'}},
|
|
31
|
+
},
|
|
32
|
+
});`;
|
|
33
|
+
const output = await apply(TRANSFORM, input);
|
|
34
|
+
expect(output).toContain("'radio-indicator-dot':");
|
|
35
|
+
// The old name survives only inside the TODO comment the rename attaches.
|
|
36
|
+
expect(output).not.toContain("'dropdown-menu-radio-dot':");
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('warns that the new target is app-wide, not menu-only', async () => {
|
|
40
|
+
const input = `const components = {
|
|
41
|
+
'dropdown-menu-radio-dot': {base: {width: '10px'}},
|
|
42
|
+
};`;
|
|
43
|
+
const output = await apply(TRANSFORM, input);
|
|
44
|
+
// The rename cannot preserve scope — there is no menu-only dot element
|
|
45
|
+
// left — so the author has to decide, and must be told.
|
|
46
|
+
expect(output).toContain('TODO(astryx upgrade)');
|
|
47
|
+
expect(output).toContain('EVERY radio dot');
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('renames the rendered class inside a selector string', async () => {
|
|
51
|
+
const input = `const sel = '.astryx-dropdown-menu-radio-dot';
|
|
52
|
+
const nested = '.astryx-dropdown-menu-radio .astryx-dropdown-menu-radio-dot';`;
|
|
53
|
+
const output = await apply(TRANSFORM, input);
|
|
54
|
+
expect(output).toContain("'.astryx-radio-indicator-dot'");
|
|
55
|
+
expect(output).toContain(
|
|
56
|
+
'.astryx-dropdown-menu-radio .astryx-radio-indicator-dot',
|
|
57
|
+
);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('renames the class inside a template literal', async () => {
|
|
61
|
+
const input =
|
|
62
|
+
'const css = `.astryx-dropdown-menu-radio-dot { background: ${c}; }`;';
|
|
63
|
+
const output = await apply(TRANSFORM, input);
|
|
64
|
+
expect(output).toContain('.astryx-radio-indicator-dot {');
|
|
65
|
+
expect(output).not.toContain('astryx-dropdown-menu-radio-dot');
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('leaves the surviving dropdown-menu-radio target alone', async () => {
|
|
69
|
+
// Only the DOT target was removed; the circle still carries the
|
|
70
|
+
// menu-specific target, so a theme keyed on it must not be rewritten.
|
|
71
|
+
const input = `const components = {
|
|
72
|
+
'dropdown-menu-radio': {base: {borderWidth: '2px'}},
|
|
73
|
+
};`;
|
|
74
|
+
const output = await apply(TRANSFORM, input);
|
|
75
|
+
expect(output).toContain("'dropdown-menu-radio'");
|
|
76
|
+
expect(output).not.toContain('radio-indicator');
|
|
77
|
+
expect(output).not.toContain('TODO(astryx upgrade)');
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('is a no-op on files that never mention the target', async () => {
|
|
81
|
+
const input = `const components = {button: {base: {fontWeight: '600'}}};`;
|
|
82
|
+
expect(await apply(TRANSFORM, input)).toBe(input);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('is idempotent', async () => {
|
|
86
|
+
const input = `const components = {
|
|
87
|
+
'dropdown-menu-radio-dot': {base: {width: '10px'}},
|
|
88
|
+
};`;
|
|
89
|
+
const once = await apply(TRANSFORM, input);
|
|
90
|
+
expect(await apply(TRANSFORM, once)).toBe(once);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
@@ -7,4 +7,14 @@
|
|
|
7
7
|
* this file into the resolved version folder.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
import renameDropdownMenuRadioDotTarget, {
|
|
11
|
+
meta as renameDropdownMenuRadioDotTargetMeta,
|
|
12
|
+
} from './rename-dropdown-menu-radio-dot-target.mjs';
|
|
13
|
+
|
|
14
|
+
export default [
|
|
15
|
+
{
|
|
16
|
+
name: 'rename-dropdown-menu-radio-dot-target',
|
|
17
|
+
transform: renameDropdownMenuRadioDotTarget,
|
|
18
|
+
meta: renameDropdownMenuRadioDotTargetMeta,
|
|
19
|
+
},
|
|
20
|
+
];
|