@getvitops/cli 0.6.0 → 0.8.0
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 +296 -0
- package/README.md +6 -0
- package/dist/cli.mjs +1 -0
- package/dist/cli.mjs.map +1 -1
- package/package.json +5 -4
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
# @getvitops/cli
|
|
2
|
+
|
|
3
|
+
## 0.8.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- a334049: Make the semantic icon mapping reachable, and fail the build on unresolvable names.
|
|
8
|
+
|
|
9
|
+
`generateIconInclude()` — declare the semantic icon names a site needs plus which sets to draw
|
|
10
|
+
them from, get back the `include` map that keeps the bundle to just those glyphs — already existed
|
|
11
|
+
but was unreachable: it lived in `@getvitops/core/src/utils/`, which the package doesn't export.
|
|
12
|
+
It has moved to `@getvitops/utils` (a build-time concern, in the build-time utilities package),
|
|
13
|
+
which `@getvitops/astro` re-exports wholesale. So from `astro.config.mjs`:
|
|
14
|
+
|
|
15
|
+
```js
|
|
16
|
+
import { generateIconInclude } from '@getvitops/astro';
|
|
17
|
+
import icon from 'astro-icon';
|
|
18
|
+
|
|
19
|
+
integrations: [
|
|
20
|
+
icon({
|
|
21
|
+
include: generateIconInclude({
|
|
22
|
+
ui: 'fa7-solid',
|
|
23
|
+
brand: 'simple-icons',
|
|
24
|
+
semantic: ['menu', 'close', 'search', 'github'],
|
|
25
|
+
}),
|
|
26
|
+
}),
|
|
27
|
+
];
|
|
28
|
+
// → { "fa7-solid": ["bars","xmark","magnifying-glass"], "simple-icons": ["github"] }
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Swapping `ui` to `'lucide'` yields `{ lucide: ["menu","x","search"] }` from the same declaration —
|
|
32
|
+
which is the point: the semantic names are what your markup commits to, and the set is a config
|
|
33
|
+
choice. The output shape is the `include` both `astro-icon` and `astro-iconset` accept, so the
|
|
34
|
+
mapping doesn't tie you to either.
|
|
35
|
+
|
|
36
|
+
**Unresolvable names are now a build error.** Previously they were skipped silently, so swapping
|
|
37
|
+
sets appeared to succeed and the gaps surfaced as missing glyphs in production. The error names
|
|
38
|
+
every offender; an unknown set name throws too, listing the known sets.
|
|
39
|
+
|
|
40
|
+
Also fixes `@getvitops/create`'s emdash template, which pinned `@getvitops/astro: ^0.4.0` — a range
|
|
41
|
+
that stopped resolving when astro joined the fixed group at 0.7.0, so scaffolded projects were
|
|
42
|
+
stuck on the old line.
|
|
43
|
+
|
|
44
|
+
- 58cb3d7: Fix two wrong paths in the live-editor manifest, and surface token-namespace collisions.
|
|
45
|
+
|
|
46
|
+
**`validate()` now returns `warnings: string[]`** alongside `ok`/`data`/`errors`, for configs that
|
|
47
|
+
parse and generate but won't behave as authored. `vitops validate` prints them. The field is always
|
|
48
|
+
present, so existing code reading `ok`/`errors` is unaffected.
|
|
49
|
+
|
|
50
|
+
The first warning covers a collision the flat `--<prop>-<name>` grammar allows: a `patterns.radii`
|
|
51
|
+
key named after a pattern claims the same variable. The example config hits it —
|
|
52
|
+
`patterns.radii.card` and the `card` pattern both want `--br-card`:
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
! patterns.radii.card collides with the "card" pattern on --br-card;
|
|
56
|
+
the pattern's override hook wins — rename the radius
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**`design-manifest.json` reverse-index fixes** (affects the live editor's edit-to-config mapping):
|
|
60
|
+
- Numeric colour steps mapped to `colors.palette.<hue>.seed`. The seed regenerates the whole ramp,
|
|
61
|
+
so every step of a hue collapsed onto one path and editing two steps would silently keep one.
|
|
62
|
+
They now map to `colors.palette.<hue>.anchors.<n>` — the schema's step → colour override.
|
|
63
|
+
- `--br-<name>` resolved to `patterns.radii.<name>` even when a pattern owned the variable. Radii
|
|
64
|
+
are now applied last and only where a pattern hasn't claimed it, matching what the CSS actually
|
|
65
|
+
does.
|
|
66
|
+
|
|
67
|
+
### Patch Changes
|
|
68
|
+
|
|
69
|
+
- 611f340: `.cta` now defaults to the `ui-primary` role instead of `brand-primary`.
|
|
70
|
+
|
|
71
|
+
The three tiers of one interaction family had split colour lineage: `:where(button, .btn)` and
|
|
72
|
+
`:where(a, .link)` resolved to `ui-primary` while `.cta` alone used `brand-primary`. For a project
|
|
73
|
+
whose brand and UI hues differ, that meant the focus ring changed colour depending on which tier
|
|
74
|
+
you tabbed onto.
|
|
75
|
+
|
|
76
|
+
Semantically the ui role is also the better fit — `brand-*` is identity, `ui-*` is the interface
|
|
77
|
+
responding to you, and a CTA's prominence already comes from its fill, weight and padding rather
|
|
78
|
+
than from borrowing the brand hue. Keeping brand as an explicit opt-in means a genuine brand moment
|
|
79
|
+
still carries signal, and a rebrand restyles brand surfaces instead of silently restyling every
|
|
80
|
+
form's submit button.
|
|
81
|
+
|
|
82
|
+
**Migration:** none if `brand-primary` and `ui-primary` map to the same hue (the common case, and
|
|
83
|
+
true of the example config). If they differ and you want the previous colour, add the new
|
|
84
|
+
`.cta-brand-primary` variant — `brand-primary` has been added to `cta.roles`, so a brand-coloured
|
|
85
|
+
CTA is reachable as a class rather than being unavailable.
|
|
86
|
+
|
|
87
|
+
- 46b129d: Make the dark-mode flip reachable outside Bricks.
|
|
88
|
+
|
|
89
|
+
The dark functional-token block was emitted under `:root[data-brx-theme="dark"]` only.
|
|
90
|
+
`data-brx-theme` is Bricks' own attribute — Bricks sets it, nothing else does — so on every other
|
|
91
|
+
target the dark flip was unreachable. In particular the shipped `<color-scheme-toggle>` web
|
|
92
|
+
component writes `documentElement.dataset.theme` (i.e. `data-theme`), so clicking "Dark" set an
|
|
93
|
+
attribute no rule matched and the page stayed light.
|
|
94
|
+
|
|
95
|
+
The block now matches `:root[data-brx-theme="dark"], :root[data-theme="dark"]`, which fixes the
|
|
96
|
+
component everywhere without changing what Bricks already does. No migration needed.
|
|
97
|
+
|
|
98
|
+
Note this covers the _explicit_ choice only. There is still no `prefers-color-scheme` block, so the
|
|
99
|
+
toggle's "System" position resolves to light. Adding one would flip every existing consumer site
|
|
100
|
+
dark for dark-OS users, which is a product decision rather than a bug fix.
|
|
101
|
+
|
|
102
|
+
- aa2863d: Persist the colour scheme across navigations, and drop the UA body margin.
|
|
103
|
+
|
|
104
|
+
**The colour scheme now sticks.** `<color-scheme-toggle>` records the explicit choice in
|
|
105
|
+
`localStorage` (`vitops-color-scheme`) and restores it on load. Previously every navigation reset
|
|
106
|
+
to System — the component defaulted to `system` on each page and its `disconnectedCallback` even
|
|
107
|
+
deleted the attribute on unmount, so the scheme was per-page state rather than a user preference.
|
|
108
|
+
Choosing System clears the key, so a visitor can go back to following their OS.
|
|
109
|
+
|
|
110
|
+
`<Head />` from `@getvitops/astro` now also emits a tiny synchronous script that applies the stored
|
|
111
|
+
value **before first paint**. Without it the persisted choice would still work, but every page
|
|
112
|
+
would render light and flip once the deferred element bundle upgraded. A test asserts the storage
|
|
113
|
+
key stays in step between the two (they can't share an import: core exports only prebuilt bundles,
|
|
114
|
+
and the Head script must be a literal in the emitted HTML).
|
|
115
|
+
|
|
116
|
+
**`body { margin: 0 }`** is now part of the framework. The UA's 8px margin offset every full-bleed
|
|
117
|
+
surface — sticky headers and `bg-*` bands rendered inset with a sliver of canvas around them, since
|
|
118
|
+
the framework owns page gutters through `.centered`'s `--gutter`. This is the only UA reset the
|
|
119
|
+
framework makes; it deliberately still ships no general reset (no global `box-sizing` change),
|
|
120
|
+
which would silently reflow existing layouts.
|
|
121
|
+
|
|
122
|
+
**Migration:** if you were compensating for the body margin with a negative offset or your own
|
|
123
|
+
`body { margin: 0 }`, you can drop it. Sites relying on the 8px inset will need to add their own
|
|
124
|
+
padding.
|
|
125
|
+
|
|
126
|
+
- Updated dependencies
|
|
127
|
+
- @getvitops/generator@0.8.0
|
|
128
|
+
- @getvitops/utils@0.8.0
|
|
129
|
+
|
|
130
|
+
## 0.7.0
|
|
131
|
+
|
|
132
|
+
### Minor Changes
|
|
133
|
+
|
|
134
|
+
- 44de07f: Split the button pattern into two tiers named by intent: `.cta` (persuasion) and `.btn`
|
|
135
|
+
(affordance).
|
|
136
|
+
|
|
137
|
+
**Breaking: a bare `<button>` is no longer a filled brand-primary button.** It now renders as a
|
|
138
|
+
quiet interactive control — geometry, cursor, subtle hover, focus ring — with no fill, no
|
|
139
|
+
`font-weight: 600`, and no shadow.
|
|
140
|
+
|
|
141
|
+
**Migration:** add `class="cta"` to any button that should stay prominent. Submit buttons, hero
|
|
142
|
+
actions, and anything driving a conversion are the usual candidates; dialog closes, toolbar
|
|
143
|
+
buttons, icon buttons and toggles should keep the new default. If you want the old behaviour
|
|
144
|
+
globally, set `patterns.items.btn` in your `design-system.json` back to the previous filled base.
|
|
145
|
+
|
|
146
|
+
New in this release:
|
|
147
|
+
- **`.cta`** — filled, bolder, roomier, lifts on hover. It is a class, not an element rule, so it
|
|
148
|
+
finally works on `<a>` — which is what a call to action usually is, since it navigates. Role
|
|
149
|
+
variants: `.cta-{success,danger,warning,info}`.
|
|
150
|
+
- **`.btn`** — the affordance tier. Emitted as one zero-specificity `:where(button, .btn)` rule, so
|
|
151
|
+
a bare `<button>` gets it with no class, `.btn` carries it to any other tag, and any explicit
|
|
152
|
+
class (including `.cta`, or a component's own class) overrides it without `!important`.
|
|
153
|
+
- **`:where(a, .link)`** — the link pattern now pairs its element with a class the same way.
|
|
154
|
+
- A pattern may now set **both `element` and `class`**, emitting one combined
|
|
155
|
+
`:where(<element>, .<class>)` rule. This is the general mechanism behind the above.
|
|
156
|
+
- A pattern may declare **`fill: true|false`** to state whether states and role variants drive
|
|
157
|
+
`background-color` (plus `on-solid` text) or `color`, instead of relying on the previous
|
|
158
|
+
inference from the pattern's name and base declarations. Existing configs are unaffected — the
|
|
159
|
+
old inference is still the fallback.
|
|
160
|
+
|
|
161
|
+
**Breaking: `chip` is retired as vocabulary.** The two small-label patterns are now split by
|
|
162
|
+
behaviour, not size: **`badge`** is a _static_ label (status, count, category) and **`tag`** is an
|
|
163
|
+
_editable and/or dismissable_ one (e.g. entries in a filter list).
|
|
164
|
+
- `.chip-list` → **`.tag-list`**, and its `--*-chip-list` / `--chip-list-focus-color` tokens →
|
|
165
|
+
`--*-tag-list` / `--tag-list-focus-color`.
|
|
166
|
+
- `.chip-list__chip` and `.chip-list__chip-remove` are **removed**. A tag list is a list of tags, so
|
|
167
|
+
its items are now the existing `.tag` / `.tag__remove` — which also means they pick up tag role
|
|
168
|
+
variants. **Migration:** replace `<span class="chip-list__chip">x <button
|
|
169
|
+
class="chip-list__chip-remove">` with `<span class="tag">x <button class="tag__remove">`. Note the
|
|
170
|
+
items change appearance: `.tag` is outlined (border + neutral text) where the old chip was filled
|
|
171
|
+
with `--color-surface-muted`.
|
|
172
|
+
- The `radii.chip` primitive is **removed** from the example config; it was only ever an alias of
|
|
173
|
+
`--br-tag`. Consumers who set `--br-chip` should use `--br-tag`.
|
|
174
|
+
|
|
175
|
+
**Pattern geometry now resolves through the group alias layer.** Every grouped pattern already
|
|
176
|
+
emitted `--<prop>-<name>-group` aliases (e.g. `--br-btn-group: var(--br-control)`), but most
|
|
177
|
+
patterns bypassed them and hard-coded `var(--br-control, …)` into the rule. `btn`, `cta`, `badge`,
|
|
178
|
+
`tag`, `card` and `status` now reference the alias and restate only their deviations via
|
|
179
|
+
`overrides`, so the whole chain — `--p-btn` → `--p-btn-group` → `--p-control` → `--p-default` — is
|
|
180
|
+
live CSS custom properties, inspectable and editable in the browser. Computed values are unchanged.
|
|
181
|
+
|
|
182
|
+
Also fixed:
|
|
183
|
+
- Role variants on element patterns were emitted at specificity 0-1-1 (`button.danger`), which
|
|
184
|
+
outranked any plain class. They now emit as `:where(button, .btn).danger, .btn-danger` — both at
|
|
185
|
+
class specificity, and reachable from a non-`<button>` host.
|
|
186
|
+
- The `link` pattern declared `default_role: "brand-primary"` while hard-coding a `ui-primary` base
|
|
187
|
+
colour, so hovering shifted hue instead of intensifying. Its `default_role` is now `ui-primary`.
|
|
188
|
+
- `@getvitops/astro`'s `FormRenderer` defaulted its submit button to `class="btn btn-primary"`, a
|
|
189
|
+
class that never existed and a role that is not emitted; it now defaults to `.cta`.
|
|
190
|
+
- The Tailwind bundle is no longer assembled during `css` / `bricks` builds, where it was computed
|
|
191
|
+
and discarded (it also read every framework partial off disk).
|
|
192
|
+
|
|
193
|
+
- 44de07f: Shared toolchain version + changelogs that reach consumers.
|
|
194
|
+
- **`@getvitops/astro` now shares the toolchain version** (`core`/`generator`/`utils`/`cli`/`vite`),
|
|
195
|
+
so it moves from its own `0.4.x` line onto the group's. The number changes; the package does not —
|
|
196
|
+
install it at the same version as `@getvitops/cli`. It was already being bumped on every toolchain
|
|
197
|
+
release by its dependency updates, and it depends on core, generator, utils _and_ vite, so a
|
|
198
|
+
separate version line cost the same churn while leaving the compatible pairing implicit. The
|
|
199
|
+
lockstep is load-bearing: the generator ships a snapshot of core's CSS + web-component bundles
|
|
200
|
+
while the Astro integration copies the _installed_ core's bundles, so mismatched versions can leave
|
|
201
|
+
the CSS and the components disagreeing.
|
|
202
|
+
|
|
203
|
+
- **Every package now ships its `CHANGELOG.md` in the published tarball.** npm does not include
|
|
204
|
+
changelogs by default, so none of this history previously reached anyone who installed the
|
|
205
|
+
packages. Per-package history now reads from `node_modules/@getvitops/<pkg>/CHANGELOG.md`;
|
|
206
|
+
curated toolchain-level release notes live in the repo's root `CHANGELOG.md`.
|
|
207
|
+
|
|
208
|
+
### Patch Changes
|
|
209
|
+
|
|
210
|
+
- @getvitops/generator@0.7.0
|
|
211
|
+
- @getvitops/utils@0.7.0
|
|
212
|
+
|
|
213
|
+
## 0.6.0
|
|
214
|
+
|
|
215
|
+
### Minor Changes
|
|
216
|
+
|
|
217
|
+
- 2cc847d: Package-resident agent skill + `vitops docs`:
|
|
218
|
+
- `@getvitops/cli` now ships the `vitops-design-system` agent skill inside the package
|
|
219
|
+
(`skill/SKILL.md`). `vitops agents` no longer emits a generated skill into the repo — it
|
|
220
|
+
symlinks `.agents/skills/` and `.claude/skills/` entries to the installed package (logical
|
|
221
|
+
`node_modules/@getvitops/cli/skill` target, surviving version bumps) and writes the
|
|
222
|
+
AGENTS.md pointer block. Old generated-skill directories are migrated automatically;
|
|
223
|
+
`--docs-dir` keeps the emit-files layout.
|
|
224
|
+
- New `vitops docs [topic]` command prints reference docs to stdout, rendered live from the
|
|
225
|
+
project's `design-system.json` (topics: classes, authoring, formats, color, scales,
|
|
226
|
+
patterns, elements; `--all` concatenates).
|
|
227
|
+
- `renderSkill()` removed from `@getvitops/generator` (superseded by the packaged skill).
|
|
228
|
+
|
|
229
|
+
### Patch Changes
|
|
230
|
+
|
|
231
|
+
- Updated dependencies [2cc847d]
|
|
232
|
+
- @getvitops/generator@0.6.0
|
|
233
|
+
- @getvitops/utils@0.6.0
|
|
234
|
+
|
|
235
|
+
## 0.5.0
|
|
236
|
+
|
|
237
|
+
### Minor Changes
|
|
238
|
+
|
|
239
|
+
- Ship design-system context to downstream agents:
|
|
240
|
+
- JSON Schema descriptions: every `design-system.json` and site-config field now carries a
|
|
241
|
+
`description` (authored in the zod schemas via `desc()`), emitted into `schema.json` /
|
|
242
|
+
`site.schema.json` for editor hovers and agent consumption.
|
|
243
|
+
- New generated OKF docs: `authoring.md` (field reference walked from the JSON Schema),
|
|
244
|
+
`formats.md` (tailwind vs css vs bricks, including the TW_CLASH utilities Tailwind
|
|
245
|
+
provides natively), and `concepts/{color,scales,patterns}.md` (seeded OKLCH colour
|
|
246
|
+
system, fluid modular scales, pattern token cascade + override hooks).
|
|
247
|
+
- `vitops agents` now emits a generated `vitops-design-system` agent skill into
|
|
248
|
+
`.agents/skills/vitops-design-system/` (SKILL.md + the docs bundle as `references/`,
|
|
249
|
+
with an idempotent `.claude/skills/` symlink) and writes a compact pointer block into
|
|
250
|
+
`AGENTS.md`. Pass `--docs-dir` for the legacy docs-only layout.
|
|
251
|
+
- `TW_CLASH` and `BASE_HOOK` are exported from `@getvitops/generator`.
|
|
252
|
+
|
|
253
|
+
### Patch Changes
|
|
254
|
+
|
|
255
|
+
- Updated dependencies
|
|
256
|
+
- @getvitops/generator@0.5.0
|
|
257
|
+
- @getvitops/utils@0.5.0
|
|
258
|
+
|
|
259
|
+
## 0.4.0
|
|
260
|
+
|
|
261
|
+
### Patch Changes
|
|
262
|
+
|
|
263
|
+
- Updated dependencies [d7e6491]
|
|
264
|
+
- @getvitops/utils@0.4.0
|
|
265
|
+
- @getvitops/generator@0.4.0
|
|
266
|
+
|
|
267
|
+
## 0.3.0
|
|
268
|
+
|
|
269
|
+
### Patch Changes
|
|
270
|
+
|
|
271
|
+
- Updated dependencies
|
|
272
|
+
- @getvitops/utils@0.3.0
|
|
273
|
+
- @getvitops/generator@0.3.0
|
|
274
|
+
|
|
275
|
+
## 0.2.1
|
|
276
|
+
|
|
277
|
+
### Patch Changes
|
|
278
|
+
|
|
279
|
+
- Updated dependencies [d28aae7]
|
|
280
|
+
- @getvitops/generator@0.2.1
|
|
281
|
+
- @getvitops/utils@0.2.1
|
|
282
|
+
|
|
283
|
+
## 0.2.0
|
|
284
|
+
|
|
285
|
+
### Minor Changes
|
|
286
|
+
|
|
287
|
+
- d35515e: Add `vitops agents` — writes a managed, marker-delimited block into a consumer's `AGENTS.md`
|
|
288
|
+
(or `--out CLAUDE.md`) so AI coding agents can discover the CLI and the design-system class/element
|
|
289
|
+
vocabulary. Idempotent (re-run to update between the `<!-- vitops:start -->`/`<!-- vitops:end -->`
|
|
290
|
+
markers) and also emits the OKF docs bundle it points at (`--docs-dir`, default `.vitops/docs`).
|
|
291
|
+
|
|
292
|
+
### Patch Changes
|
|
293
|
+
|
|
294
|
+
- Updated dependencies
|
|
295
|
+
- @getvitops/generator@0.2.0
|
|
296
|
+
- @getvitops/utils@0.2.0
|
package/README.md
CHANGED
|
@@ -113,3 +113,9 @@ layout still works: `vitops agents --docs-dir .vitops/docs` writes the full docs
|
|
|
113
113
|
and points the AGENTS.md block at them (no skill link).
|
|
114
114
|
|
|
115
115
|
Powered by [`@getvitops/generator`](https://www.npmjs.com/package/@getvitops/generator).
|
|
116
|
+
|
|
117
|
+
## Changelog
|
|
118
|
+
|
|
119
|
+
This package's history: [`CHANGELOG.md`](./CHANGELOG.md) (shipped in the npm tarball, so it
|
|
120
|
+
also reads from `node_modules/@getvitops/cli/CHANGELOG.md`). `@getvitops/core`, `generator`,
|
|
121
|
+
`utils`, `cli`, `vite` and `astro` share one version and are released together.
|
package/dist/cli.mjs
CHANGED
package/dist/cli.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.mjs","names":[],"sources":["../src/agents.ts","../src/cli.ts"],"sourcesContent":["/**\n * Side-effect-free helpers for the `vitops agents` / `vitops docs` commands.\n * Kept out of cli.ts (which runs main() on import) so they are unit-testable.\n */\nimport {\n existsSync,\n lstatSync,\n mkdirSync,\n readFileSync,\n readlinkSync,\n rmSync,\n symlinkSync,\n} from 'node:fs';\nimport { dirname, join, parse, relative, resolve } from 'node:path';\n\nexport const SKILL_NAME = 'vitops-design-system';\n\n/** Marker the 0.5.0-era generated skill carried; lets us migrate that layout. */\nexport const GENERATED_MARKER = '<!-- GENERATED by @getvitops/cli';\n\n/**\n * `vitops docs` topics → docs-bundle paths (as returned by `generateDocs`).\n * Order is the `--all` concatenation order.\n */\nexport const TOPICS: Record<string, { path: string; summary: string }> = {\n classes: {\n path: 'css/classes.md',\n summary: 'CSS framework class vocabulary (colour, type, space, layout, animation, patterns)',\n },\n authoring: {\n path: 'authoring.md',\n summary: 'every design-system.json field, rendered from the JSON Schema',\n },\n formats: {\n path: 'formats.md',\n summary: \"tailwind vs css vs bricks: what's emitted vs what the platform provides\",\n },\n color: {\n path: 'concepts/color.md',\n summary: 'seeded OKLCH scales, functional tokens, automatic dark mode',\n },\n scales: {\n path: 'concepts/scales.md',\n summary: 'fluid modular type & space scales',\n },\n patterns: {\n path: 'concepts/patterns.md',\n summary: 'pattern CSS: token cascade, override hooks, states, role variants',\n },\n elements: {\n path: 'bricks/elements.md',\n summary: 'Bricks Builder custom elements, controls, defaults',\n },\n};\n\n/**\n * Find the installed package's skill directory by walking up from `cwd` looking\n * for `node_modules/@getvitops/cli/skill/SKILL.md`. Returns the LOGICAL path\n * (through the `node_modules/@getvitops/cli` link, unresolved) or null.\n *\n * Deliberately not derived from import.meta.url: under pnpm the running module's\n * URL is the realpath in `node_modules/.pnpm/@getvitops+cli@<version>/…`, which\n * changes on every version bump — a symlink to it would dangle after upgrades.\n * The logical path is recreated by the package manager on every install, so a\n * link through it always resolves to the currently installed version.\n */\nexport function findSkillTarget(cwd: string): string | null {\n let dir = resolve(cwd);\n const { root } = parse(dir);\n for (;;) {\n const skillDir = join(dir, 'node_modules', '@getvitops', 'cli', 'skill');\n if (existsSync(join(skillDir, 'SKILL.md'))) return skillDir;\n if (dir === root) return null;\n dir = dirname(dir);\n }\n}\n\n/**\n * Idempotently symlink `linkPath` → `targetDir` (relative target). Replaces a\n * stale symlink; migrates a real directory left by the old emitting `vitops\n * agents` (identified by GENERATED_MARKER in its SKILL.md); refuses to clobber\n * anything else. Returns a warning string, or null on success / no-op.\n */\nexport function linkSkill(linkPath: string, targetDir: string): string | null {\n const target = relative(dirname(linkPath), resolve(targetDir));\n try {\n const st = lstatSync(linkPath, { throwIfNoEntry: false });\n if (st && !st.isSymbolicLink()) {\n const oldSkill = join(linkPath, 'SKILL.md');\n const isGenerated =\n st.isDirectory() &&\n existsSync(oldSkill) &&\n readFileSync(oldSkill, 'utf8').includes(GENERATED_MARKER);\n if (!isGenerated)\n return `left ${linkPath} alone (exists and is not a symlink) — link it to ${targetDir} yourself if wanted`;\n rmSync(linkPath, { recursive: true }); // old generated skill layout → replace\n } else if (st) {\n if (readlinkSync(linkPath) === target) return null;\n rmSync(linkPath);\n } else {\n mkdirSync(dirname(linkPath), { recursive: true });\n }\n symlinkSync(target, linkPath);\n return null;\n } catch (err) {\n return `could not symlink ${linkPath}: ${(err as Error).message}`;\n }\n}\n","#!/usr/bin/env node\n/**\n * `vitops` — CLI for the Vitops design-system generator.\n *\n * vitops generate --input <json> --format <bricks|css|tailwind[,…]> --out <dir>\n * vitops init [--out design-system.json] [--force]\n * vitops validate <design-system.json>\n * vitops favicon --input <svg|png> --out <dir> [--low-res <svg|png>]\n * vitops agents [--input <json>] [--out AGENTS.md] [--docs-dir <dir>]\n * vitops docs [topic] [--input <json>] [--all]\n *\n * Thin wrapper over @getvitops/generator (generation) and @getvitops/utils (favicons).\n * Every client brings their own consumer-editable design-system.json.\n */\nimport { parseArgs } from 'node:util';\nimport { writeFileSync, existsSync, readFileSync, mkdirSync } from 'node:fs';\nimport { resolve, join, dirname } from 'node:path';\nimport { createRequire } from 'node:module';\nimport {\n generate,\n validate,\n defaultConfig,\n generateDocs,\n SCHEMA_URL,\n type Format,\n type DesignSystem,\n} from '@getvitops/generator';\nimport { generateFavicons } from '@getvitops/utils';\nimport { findSkillTarget, linkSkill, SKILL_NAME, TOPICS } from './agents.ts';\n\nconst FORMATS = new Set<Format>(['bricks', 'css', 'tailwind']);\n\nconst HELP = `vitops — generate design-system outputs from a design-system.json\n\nUsage:\n vitops generate [options] Generate platform output from a config\n vitops init [options] Scaffold a starter design-system.json\n vitops validate <file> Validate a config against the schema\n vitops favicon [options] Generate a favicon set from a source image\n vitops agents [options] Link the design-system agent skill + AGENTS.md pointer\n vitops docs [topic] Print live design-system reference docs to stdout\n\nGenerate options:\n -i, --input <path> Config file (default: ./design-system.json)\n -f, --format <list> bricks | css | tailwind (comma-separated; default: bricks)\n -o, --out <dir> Output directory (default: ./dist)\n\nInit options:\n -o, --out <path> Where to write (default: ./design-system.json)\n --force Overwrite an existing file\n\nFavicon options:\n -i, --input <path> Source SVG or PNG (required)\n -o, --out <dir> Output directory (default: ./public)\n --low-res <path> Optional simplified source for the 16px icon\n\nAgents options:\n -i, --input <path> Config file (default: ./design-system.json; validated if present)\n -o, --out <path> Doc file to update, idempotently (default: ./AGENTS.md)\n --docs-dir <dir> Legacy layout: write the docs bundle as files to this dir\n instead of linking the packaged skill\n\nDocs options:\n <topic> classes | authoring | formats | color | scales | patterns | elements\n (no topic: list topics with summaries)\n -i, --input <path> Config file (default: ./design-system.json)\n --all Print every topic, concatenated\n\nCommon:\n -h, --help Show this help\n`;\n\nfunction fail(msg: string): never {\n console.error(`✖ ${msg}`);\n process.exit(1);\n}\n\nasync function cmdGenerate(argv: string[]) {\n const { values } = parseArgs({\n args: argv,\n options: {\n input: { type: 'string', short: 'i', default: 'design-system.json' },\n format: { type: 'string', short: 'f', default: 'bricks' },\n out: { type: 'string', short: 'o', default: 'dist' },\n },\n allowPositionals: false,\n });\n const input = resolve(values.input as string);\n if (!existsSync(input)) fail(`config not found: ${input}`);\n const formats = (values.format as string)\n .split(',')\n .map((f) => f.trim())\n .filter(Boolean);\n for (const f of formats)\n if (!FORMATS.has(f as Format))\n fail(`unknown format \"${f}\" (expected: bricks | css | tailwind)`);\n\n for (const format of formats as Format[]) {\n try {\n const res = await generate({ input, format, outDir: values.out as string });\n console.log(`✓ ${format} → ${res.outDir} (${res.written.length} paths)`);\n } catch (err) {\n fail((err as Error).message);\n }\n }\n}\n\nfunction cmdInit(argv: string[]) {\n const { values } = parseArgs({\n args: argv,\n options: {\n out: { type: 'string', short: 'o', default: 'design-system.json' },\n force: { type: 'boolean', default: false },\n },\n allowPositionals: false,\n });\n const out = resolve(values.out as string);\n if (existsSync(out) && !values.force) fail(`${out} already exists (use --force to overwrite)`);\n writeFileSync(out, JSON.stringify(defaultConfig(), null, 2) + '\\n');\n console.log(`✓ wrote ${out}`);\n console.log(\n ` Edit it, then: vitops generate --input ${values.out} --format tailwind --out src/styles`,\n );\n console.log(` Editors read the \"$schema\" (${SCHEMA_URL}) for autocomplete + validation.`);\n}\n\nfunction cmdValidate(argv: string[]) {\n const { values, positionals } = parseArgs({\n args: argv,\n options: { input: { type: 'string', short: 'i' } },\n allowPositionals: true,\n });\n const path = resolve((positionals[0] ?? values.input ?? 'design-system.json') as string);\n if (!existsSync(path)) fail(`config not found: ${path}`);\n let raw: unknown;\n try {\n raw = JSON.parse(readFileSync(path, 'utf8'));\n } catch (err) {\n fail(`could not parse JSON: ${(err as Error).message}`);\n }\n const result = validate(raw);\n if (result.ok) {\n console.log(`✓ ${path} is valid`);\n return;\n }\n console.error(`✖ ${path} is invalid:`);\n for (const e of result.errors) console.error(` • ${e.path.join('.') || '(root)'}: ${e.message}`);\n process.exit(1);\n}\n\nasync function cmdFavicon(argv: string[]) {\n const { values } = parseArgs({\n args: argv,\n options: {\n input: { type: 'string', short: 'i' },\n out: { type: 'string', short: 'o', default: 'public' },\n 'low-res': { type: 'string' },\n },\n allowPositionals: false,\n });\n if (!values.input) fail('favicon: --input <svg|png> is required');\n const source = resolve(values.input as string);\n if (!existsSync(source)) fail(`source not found: ${source}`);\n try {\n const written = await generateFavicons({\n source,\n outputDir: values.out as string,\n ...(values['low-res'] ? { lowResSource: resolve(values['low-res'] as string) } : {}),\n });\n console.log(`✓ favicons → ${values.out} (${written.length} files)`);\n } catch (err) {\n fail((err as Error).message);\n }\n}\n\n// Read + parse + validate a design-system.json, or exit with a message.\nfunction loadConfig(path: string): DesignSystem {\n if (!existsSync(path)) fail(`config not found: ${path}`);\n let raw: unknown;\n try {\n raw = JSON.parse(readFileSync(path, 'utf8'));\n } catch (err) {\n fail(`could not parse JSON: ${(err as Error).message}`);\n }\n const result = validate(raw);\n if (!result.ok) {\n console.error(`✖ ${path} is invalid:`);\n for (const e of result.errors)\n console.error(` • ${e.path.join('.') || '(root)'}: ${e.message}`);\n process.exit(1);\n }\n return result.data;\n}\n\n// This CLI's own version (dist/cli.mjs → package-root package.json).\nfunction cliVersion(): string {\n try {\n return (\n JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version ??\n '0.0.0'\n );\n } catch {\n return '0.0.0';\n }\n}\n\n// The framework asset root shipped inside @getvitops/generator (holds the Bricks\n// PHP that generateDocs reads for the element reference).\nfunction generatorAssetsDir(): string {\n const pkg = createRequire(import.meta.url).resolve('@getvitops/generator/package.json');\n return join(dirname(pkg), 'assets');\n}\n\nconst AGENTS_START = '<!-- vitops:start -->';\nconst AGENTS_END = '<!-- vitops:end -->';\n\n/** Print a live reference doc (rendered from the project's config) to stdout. */\nfunction cmdDocs(argv: string[]) {\n const { values, positionals } = parseArgs({\n args: argv,\n options: {\n input: { type: 'string', short: 'i', default: 'design-system.json' },\n all: { type: 'boolean', default: false },\n },\n allowPositionals: true,\n });\n const topic = positionals[0];\n const topicList = () =>\n Object.entries(TOPICS)\n .map(([name, t]) => ` ${name.padEnd(10)} ${t.summary}`)\n .join('\\n');\n if (!topic && !values.all) {\n console.log(\n `vitops docs <topic> — print a live design-system reference to stdout\\n\\nTopics:\\n${topicList()}\\n\\nAlso: vitops docs --all (every topic, concatenated)`,\n );\n return;\n }\n if (topic && !TOPICS[topic]) fail(`unknown topic \"${topic}\". Valid topics:\\n${topicList()}`);\n const ds = loadConfig(resolve(values.input as string));\n const docs = generateDocs(ds, generatorAssetsDir());\n const paths = values.all\n ? Object.values(TOPICS).map((t) => t.path)\n : [TOPICS[topic as string]!.path];\n process.stdout.write(paths.map((p) => docs[p]).join('\\n'));\n}\n\nfunction cmdAgents(argv: string[]) {\n const { values } = parseArgs({\n args: argv,\n options: {\n input: { type: 'string', short: 'i', default: 'design-system.json' },\n out: { type: 'string', short: 'o', default: 'AGENTS.md' },\n 'docs-dir': { type: 'string' },\n },\n allowPositionals: false,\n });\n const inputRel = values.input as string;\n // The command is pure wiring: validate the config when present (fail on an\n // invalid one), but don't require it — docs are rendered live by `vitops docs`.\n let ds: DesignSystem | null = null;\n if (existsSync(resolve(inputRel))) ds = loadConfig(resolve(inputRel));\n else console.warn(` ⚠ ${inputRel} not found — run \\`vitops init\\` to scaffold one`);\n\n // Explicit --docs-dir = legacy layout: write the docs bundle as files, no skill.\n const legacyDocsDir = values['docs-dir'] as string | undefined;\n let summary: string;\n let pointer: string[];\n\n if (legacyDocsDir) {\n if (!ds) fail(`--docs-dir needs a config to render docs from (${inputRel} not found)`);\n let docs: Record<string, string> = {};\n try {\n docs = generateDocs(ds, generatorAssetsDir());\n } catch (err) {\n fail(`could not generate docs: ${(err as Error).message}`);\n }\n for (const [rel, content] of Object.entries(docs)) {\n const p = resolve(legacyDocsDir, rel);\n mkdirSync(dirname(p), { recursive: true });\n writeFileSync(p, content);\n }\n summary = `wrote ${Object.keys(docs).length} docs to ${legacyDocsDir}/`;\n pointer = [\n 'Prefer the framework’s utility + component classes over hand-written CSS.',\n `Reference docs (regenerate with \\`vitops agents --docs-dir ${legacyDocsDir}\\`): \\`${legacyDocsDir}/css/classes.md\\`,`,\n `\\`${legacyDocsDir}/authoring.md\\`, \\`${legacyDocsDir}/formats.md\\`, \\`${legacyDocsDir}/bricks/elements.md\\`.`,\n ];\n } else {\n // Link the packaged skill (ships inside @getvitops/cli) into the agent\n // discovery locations; nothing is generated into the repo.\n const target = findSkillTarget(process.cwd());\n if (target) {\n for (const dir of ['.agents', '.claude']) {\n const warn = linkSkill(resolve(dir, 'skills', SKILL_NAME), target);\n if (warn) console.warn(` ⚠ ${warn}`);\n }\n summary = `linked {.agents,.claude}/skills/${SKILL_NAME} → ${target}`;\n } else {\n console.warn(\n ` ⚠ could not find node_modules/@getvitops/cli/skill — install @getvitops/cli as a devDependency, then re-run \\`vitops agents\\``,\n );\n summary = 'no skill linked';\n }\n pointer = [\n 'Prefer the framework’s utility + component classes over hand-written CSS.',\n `Full design-system context lives in the \\`${SKILL_NAME}\\` skill (linked from`,\n '`.agents/skills/` and `.claude/skills/` into the installed `@getvitops/cli`;',\n 're-link with `vitops agents` if the links are deleted — they survive version',\n 'bumps). Reference docs print live, from this project’s config, via:',\n '',\n ...Object.entries(TOPICS).map(([name, t]) => `- \\`vitops docs ${name}\\` — ${t.summary}`),\n ];\n }\n\n const block = [\n AGENTS_START,\n '## Vitops design system',\n '',\n `Styled with the Vitops design system (\\`@getvitops/*\\`); tokens live in \\`${inputRel}\\`.`,\n 'Generate output with the CLI:',\n '',\n '- `vitops generate --format tailwind --out src/styles` — Tailwind v4 / Astro',\n '- `vitops generate --format css --out dist` — standalone CSS',\n '- `vitops generate --format bricks --out <theme>/dist` — WordPress / Bricks',\n '- `vitops init` · `vitops validate` · `vitops favicon`',\n '',\n ...pointer,\n '',\n `<!-- regenerate: vitops agents · @getvitops/cli@${cliVersion()} -->`,\n AGENTS_END,\n ].join('\\n');\n\n const outPath = resolve(values.out as string);\n let next: string;\n let action: string;\n if (existsSync(outPath)) {\n const cur = readFileSync(outPath, 'utf8');\n const s = cur.indexOf(AGENTS_START);\n const e = cur.indexOf(AGENTS_END);\n if (s !== -1 && e !== -1 && e > s) {\n next = cur.slice(0, s) + block + cur.slice(e + AGENTS_END.length);\n action = 'updated block in';\n } else {\n next = cur.replace(/\\s*$/, '') + '\\n\\n' + block + '\\n';\n action = 'appended block to';\n }\n } else {\n mkdirSync(dirname(outPath), { recursive: true });\n next = block + '\\n';\n action = 'created';\n }\n writeFileSync(outPath, next);\n console.log(`✓ ${action} ${values.out} + ${summary}`);\n}\n\nasync function main() {\n const [command, ...rest] = process.argv.slice(2);\n if (!command || command === '-h' || command === '--help' || command === 'help') {\n console.log(HELP);\n return;\n }\n switch (command) {\n case 'generate':\n return cmdGenerate(rest);\n case 'init':\n return cmdInit(rest);\n case 'validate':\n return cmdValidate(rest);\n case 'favicon':\n return cmdFavicon(rest);\n case 'agents':\n return cmdAgents(rest);\n case 'docs':\n return cmdDocs(rest);\n default:\n fail(\n `unknown command \"${command}\" (expected: generate | init | validate | favicon | agents | docs). Try: vitops --help`,\n );\n }\n}\n\nmain().catch((err) => fail((err as Error).message));\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cli.mjs","names":[],"sources":["../src/agents.ts","../src/cli.ts"],"sourcesContent":["/**\n * Side-effect-free helpers for the `vitops agents` / `vitops docs` commands.\n * Kept out of cli.ts (which runs main() on import) so they are unit-testable.\n */\nimport {\n existsSync,\n lstatSync,\n mkdirSync,\n readFileSync,\n readlinkSync,\n rmSync,\n symlinkSync,\n} from 'node:fs';\nimport { dirname, join, parse, relative, resolve } from 'node:path';\n\nexport const SKILL_NAME = 'vitops-design-system';\n\n/** Marker the 0.5.0-era generated skill carried; lets us migrate that layout. */\nexport const GENERATED_MARKER = '<!-- GENERATED by @getvitops/cli';\n\n/**\n * `vitops docs` topics → docs-bundle paths (as returned by `generateDocs`).\n * Order is the `--all` concatenation order.\n */\nexport const TOPICS: Record<string, { path: string; summary: string }> = {\n classes: {\n path: 'css/classes.md',\n summary: 'CSS framework class vocabulary (colour, type, space, layout, animation, patterns)',\n },\n authoring: {\n path: 'authoring.md',\n summary: 'every design-system.json field, rendered from the JSON Schema',\n },\n formats: {\n path: 'formats.md',\n summary: \"tailwind vs css vs bricks: what's emitted vs what the platform provides\",\n },\n color: {\n path: 'concepts/color.md',\n summary: 'seeded OKLCH scales, functional tokens, automatic dark mode',\n },\n scales: {\n path: 'concepts/scales.md',\n summary: 'fluid modular type & space scales',\n },\n patterns: {\n path: 'concepts/patterns.md',\n summary: 'pattern CSS: token cascade, override hooks, states, role variants',\n },\n elements: {\n path: 'bricks/elements.md',\n summary: 'Bricks Builder custom elements, controls, defaults',\n },\n};\n\n/**\n * Find the installed package's skill directory by walking up from `cwd` looking\n * for `node_modules/@getvitops/cli/skill/SKILL.md`. Returns the LOGICAL path\n * (through the `node_modules/@getvitops/cli` link, unresolved) or null.\n *\n * Deliberately not derived from import.meta.url: under pnpm the running module's\n * URL is the realpath in `node_modules/.pnpm/@getvitops+cli@<version>/…`, which\n * changes on every version bump — a symlink to it would dangle after upgrades.\n * The logical path is recreated by the package manager on every install, so a\n * link through it always resolves to the currently installed version.\n */\nexport function findSkillTarget(cwd: string): string | null {\n let dir = resolve(cwd);\n const { root } = parse(dir);\n for (;;) {\n const skillDir = join(dir, 'node_modules', '@getvitops', 'cli', 'skill');\n if (existsSync(join(skillDir, 'SKILL.md'))) return skillDir;\n if (dir === root) return null;\n dir = dirname(dir);\n }\n}\n\n/**\n * Idempotently symlink `linkPath` → `targetDir` (relative target). Replaces a\n * stale symlink; migrates a real directory left by the old emitting `vitops\n * agents` (identified by GENERATED_MARKER in its SKILL.md); refuses to clobber\n * anything else. Returns a warning string, or null on success / no-op.\n */\nexport function linkSkill(linkPath: string, targetDir: string): string | null {\n const target = relative(dirname(linkPath), resolve(targetDir));\n try {\n const st = lstatSync(linkPath, { throwIfNoEntry: false });\n if (st && !st.isSymbolicLink()) {\n const oldSkill = join(linkPath, 'SKILL.md');\n const isGenerated =\n st.isDirectory() &&\n existsSync(oldSkill) &&\n readFileSync(oldSkill, 'utf8').includes(GENERATED_MARKER);\n if (!isGenerated)\n return `left ${linkPath} alone (exists and is not a symlink) — link it to ${targetDir} yourself if wanted`;\n rmSync(linkPath, { recursive: true }); // old generated skill layout → replace\n } else if (st) {\n if (readlinkSync(linkPath) === target) return null;\n rmSync(linkPath);\n } else {\n mkdirSync(dirname(linkPath), { recursive: true });\n }\n symlinkSync(target, linkPath);\n return null;\n } catch (err) {\n return `could not symlink ${linkPath}: ${(err as Error).message}`;\n }\n}\n","#!/usr/bin/env node\n/**\n * `vitops` — CLI for the Vitops design-system generator.\n *\n * vitops generate --input <json> --format <bricks|css|tailwind[,…]> --out <dir>\n * vitops init [--out design-system.json] [--force]\n * vitops validate <design-system.json>\n * vitops favicon --input <svg|png> --out <dir> [--low-res <svg|png>]\n * vitops agents [--input <json>] [--out AGENTS.md] [--docs-dir <dir>]\n * vitops docs [topic] [--input <json>] [--all]\n *\n * Thin wrapper over @getvitops/generator (generation) and @getvitops/utils (favicons).\n * Every client brings their own consumer-editable design-system.json.\n */\nimport { parseArgs } from 'node:util';\nimport { writeFileSync, existsSync, readFileSync, mkdirSync } from 'node:fs';\nimport { resolve, join, dirname } from 'node:path';\nimport { createRequire } from 'node:module';\nimport {\n generate,\n validate,\n defaultConfig,\n generateDocs,\n SCHEMA_URL,\n type Format,\n type DesignSystem,\n} from '@getvitops/generator';\nimport { generateFavicons } from '@getvitops/utils';\nimport { findSkillTarget, linkSkill, SKILL_NAME, TOPICS } from './agents.ts';\n\nconst FORMATS = new Set<Format>(['bricks', 'css', 'tailwind']);\n\nconst HELP = `vitops — generate design-system outputs from a design-system.json\n\nUsage:\n vitops generate [options] Generate platform output from a config\n vitops init [options] Scaffold a starter design-system.json\n vitops validate <file> Validate a config against the schema\n vitops favicon [options] Generate a favicon set from a source image\n vitops agents [options] Link the design-system agent skill + AGENTS.md pointer\n vitops docs [topic] Print live design-system reference docs to stdout\n\nGenerate options:\n -i, --input <path> Config file (default: ./design-system.json)\n -f, --format <list> bricks | css | tailwind (comma-separated; default: bricks)\n -o, --out <dir> Output directory (default: ./dist)\n\nInit options:\n -o, --out <path> Where to write (default: ./design-system.json)\n --force Overwrite an existing file\n\nFavicon options:\n -i, --input <path> Source SVG or PNG (required)\n -o, --out <dir> Output directory (default: ./public)\n --low-res <path> Optional simplified source for the 16px icon\n\nAgents options:\n -i, --input <path> Config file (default: ./design-system.json; validated if present)\n -o, --out <path> Doc file to update, idempotently (default: ./AGENTS.md)\n --docs-dir <dir> Legacy layout: write the docs bundle as files to this dir\n instead of linking the packaged skill\n\nDocs options:\n <topic> classes | authoring | formats | color | scales | patterns | elements\n (no topic: list topics with summaries)\n -i, --input <path> Config file (default: ./design-system.json)\n --all Print every topic, concatenated\n\nCommon:\n -h, --help Show this help\n`;\n\nfunction fail(msg: string): never {\n console.error(`✖ ${msg}`);\n process.exit(1);\n}\n\nasync function cmdGenerate(argv: string[]) {\n const { values } = parseArgs({\n args: argv,\n options: {\n input: { type: 'string', short: 'i', default: 'design-system.json' },\n format: { type: 'string', short: 'f', default: 'bricks' },\n out: { type: 'string', short: 'o', default: 'dist' },\n },\n allowPositionals: false,\n });\n const input = resolve(values.input as string);\n if (!existsSync(input)) fail(`config not found: ${input}`);\n const formats = (values.format as string)\n .split(',')\n .map((f) => f.trim())\n .filter(Boolean);\n for (const f of formats)\n if (!FORMATS.has(f as Format))\n fail(`unknown format \"${f}\" (expected: bricks | css | tailwind)`);\n\n for (const format of formats as Format[]) {\n try {\n const res = await generate({ input, format, outDir: values.out as string });\n console.log(`✓ ${format} → ${res.outDir} (${res.written.length} paths)`);\n } catch (err) {\n fail((err as Error).message);\n }\n }\n}\n\nfunction cmdInit(argv: string[]) {\n const { values } = parseArgs({\n args: argv,\n options: {\n out: { type: 'string', short: 'o', default: 'design-system.json' },\n force: { type: 'boolean', default: false },\n },\n allowPositionals: false,\n });\n const out = resolve(values.out as string);\n if (existsSync(out) && !values.force) fail(`${out} already exists (use --force to overwrite)`);\n writeFileSync(out, JSON.stringify(defaultConfig(), null, 2) + '\\n');\n console.log(`✓ wrote ${out}`);\n console.log(\n ` Edit it, then: vitops generate --input ${values.out} --format tailwind --out src/styles`,\n );\n console.log(` Editors read the \"$schema\" (${SCHEMA_URL}) for autocomplete + validation.`);\n}\n\nfunction cmdValidate(argv: string[]) {\n const { values, positionals } = parseArgs({\n args: argv,\n options: { input: { type: 'string', short: 'i' } },\n allowPositionals: true,\n });\n const path = resolve((positionals[0] ?? values.input ?? 'design-system.json') as string);\n if (!existsSync(path)) fail(`config not found: ${path}`);\n let raw: unknown;\n try {\n raw = JSON.parse(readFileSync(path, 'utf8'));\n } catch (err) {\n fail(`could not parse JSON: ${(err as Error).message}`);\n }\n const result = validate(raw);\n for (const w of result.warnings) console.warn(` ! ${w}`);\n if (result.ok) {\n console.log(`✓ ${path} is valid`);\n return;\n }\n console.error(`✖ ${path} is invalid:`);\n for (const e of result.errors) console.error(` • ${e.path.join('.') || '(root)'}: ${e.message}`);\n process.exit(1);\n}\n\nasync function cmdFavicon(argv: string[]) {\n const { values } = parseArgs({\n args: argv,\n options: {\n input: { type: 'string', short: 'i' },\n out: { type: 'string', short: 'o', default: 'public' },\n 'low-res': { type: 'string' },\n },\n allowPositionals: false,\n });\n if (!values.input) fail('favicon: --input <svg|png> is required');\n const source = resolve(values.input as string);\n if (!existsSync(source)) fail(`source not found: ${source}`);\n try {\n const written = await generateFavicons({\n source,\n outputDir: values.out as string,\n ...(values['low-res'] ? { lowResSource: resolve(values['low-res'] as string) } : {}),\n });\n console.log(`✓ favicons → ${values.out} (${written.length} files)`);\n } catch (err) {\n fail((err as Error).message);\n }\n}\n\n// Read + parse + validate a design-system.json, or exit with a message.\nfunction loadConfig(path: string): DesignSystem {\n if (!existsSync(path)) fail(`config not found: ${path}`);\n let raw: unknown;\n try {\n raw = JSON.parse(readFileSync(path, 'utf8'));\n } catch (err) {\n fail(`could not parse JSON: ${(err as Error).message}`);\n }\n const result = validate(raw);\n if (!result.ok) {\n console.error(`✖ ${path} is invalid:`);\n for (const e of result.errors)\n console.error(` • ${e.path.join('.') || '(root)'}: ${e.message}`);\n process.exit(1);\n }\n return result.data;\n}\n\n// This CLI's own version (dist/cli.mjs → package-root package.json).\nfunction cliVersion(): string {\n try {\n return (\n JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version ??\n '0.0.0'\n );\n } catch {\n return '0.0.0';\n }\n}\n\n// The framework asset root shipped inside @getvitops/generator (holds the Bricks\n// PHP that generateDocs reads for the element reference).\nfunction generatorAssetsDir(): string {\n const pkg = createRequire(import.meta.url).resolve('@getvitops/generator/package.json');\n return join(dirname(pkg), 'assets');\n}\n\nconst AGENTS_START = '<!-- vitops:start -->';\nconst AGENTS_END = '<!-- vitops:end -->';\n\n/** Print a live reference doc (rendered from the project's config) to stdout. */\nfunction cmdDocs(argv: string[]) {\n const { values, positionals } = parseArgs({\n args: argv,\n options: {\n input: { type: 'string', short: 'i', default: 'design-system.json' },\n all: { type: 'boolean', default: false },\n },\n allowPositionals: true,\n });\n const topic = positionals[0];\n const topicList = () =>\n Object.entries(TOPICS)\n .map(([name, t]) => ` ${name.padEnd(10)} ${t.summary}`)\n .join('\\n');\n if (!topic && !values.all) {\n console.log(\n `vitops docs <topic> — print a live design-system reference to stdout\\n\\nTopics:\\n${topicList()}\\n\\nAlso: vitops docs --all (every topic, concatenated)`,\n );\n return;\n }\n if (topic && !TOPICS[topic]) fail(`unknown topic \"${topic}\". Valid topics:\\n${topicList()}`);\n const ds = loadConfig(resolve(values.input as string));\n const docs = generateDocs(ds, generatorAssetsDir());\n const paths = values.all\n ? Object.values(TOPICS).map((t) => t.path)\n : [TOPICS[topic as string]!.path];\n process.stdout.write(paths.map((p) => docs[p]).join('\\n'));\n}\n\nfunction cmdAgents(argv: string[]) {\n const { values } = parseArgs({\n args: argv,\n options: {\n input: { type: 'string', short: 'i', default: 'design-system.json' },\n out: { type: 'string', short: 'o', default: 'AGENTS.md' },\n 'docs-dir': { type: 'string' },\n },\n allowPositionals: false,\n });\n const inputRel = values.input as string;\n // The command is pure wiring: validate the config when present (fail on an\n // invalid one), but don't require it — docs are rendered live by `vitops docs`.\n let ds: DesignSystem | null = null;\n if (existsSync(resolve(inputRel))) ds = loadConfig(resolve(inputRel));\n else console.warn(` ⚠ ${inputRel} not found — run \\`vitops init\\` to scaffold one`);\n\n // Explicit --docs-dir = legacy layout: write the docs bundle as files, no skill.\n const legacyDocsDir = values['docs-dir'] as string | undefined;\n let summary: string;\n let pointer: string[];\n\n if (legacyDocsDir) {\n if (!ds) fail(`--docs-dir needs a config to render docs from (${inputRel} not found)`);\n let docs: Record<string, string> = {};\n try {\n docs = generateDocs(ds, generatorAssetsDir());\n } catch (err) {\n fail(`could not generate docs: ${(err as Error).message}`);\n }\n for (const [rel, content] of Object.entries(docs)) {\n const p = resolve(legacyDocsDir, rel);\n mkdirSync(dirname(p), { recursive: true });\n writeFileSync(p, content);\n }\n summary = `wrote ${Object.keys(docs).length} docs to ${legacyDocsDir}/`;\n pointer = [\n 'Prefer the framework’s utility + component classes over hand-written CSS.',\n `Reference docs (regenerate with \\`vitops agents --docs-dir ${legacyDocsDir}\\`): \\`${legacyDocsDir}/css/classes.md\\`,`,\n `\\`${legacyDocsDir}/authoring.md\\`, \\`${legacyDocsDir}/formats.md\\`, \\`${legacyDocsDir}/bricks/elements.md\\`.`,\n ];\n } else {\n // Link the packaged skill (ships inside @getvitops/cli) into the agent\n // discovery locations; nothing is generated into the repo.\n const target = findSkillTarget(process.cwd());\n if (target) {\n for (const dir of ['.agents', '.claude']) {\n const warn = linkSkill(resolve(dir, 'skills', SKILL_NAME), target);\n if (warn) console.warn(` ⚠ ${warn}`);\n }\n summary = `linked {.agents,.claude}/skills/${SKILL_NAME} → ${target}`;\n } else {\n console.warn(\n ` ⚠ could not find node_modules/@getvitops/cli/skill — install @getvitops/cli as a devDependency, then re-run \\`vitops agents\\``,\n );\n summary = 'no skill linked';\n }\n pointer = [\n 'Prefer the framework’s utility + component classes over hand-written CSS.',\n `Full design-system context lives in the \\`${SKILL_NAME}\\` skill (linked from`,\n '`.agents/skills/` and `.claude/skills/` into the installed `@getvitops/cli`;',\n 're-link with `vitops agents` if the links are deleted — they survive version',\n 'bumps). Reference docs print live, from this project’s config, via:',\n '',\n ...Object.entries(TOPICS).map(([name, t]) => `- \\`vitops docs ${name}\\` — ${t.summary}`),\n ];\n }\n\n const block = [\n AGENTS_START,\n '## Vitops design system',\n '',\n `Styled with the Vitops design system (\\`@getvitops/*\\`); tokens live in \\`${inputRel}\\`.`,\n 'Generate output with the CLI:',\n '',\n '- `vitops generate --format tailwind --out src/styles` — Tailwind v4 / Astro',\n '- `vitops generate --format css --out dist` — standalone CSS',\n '- `vitops generate --format bricks --out <theme>/dist` — WordPress / Bricks',\n '- `vitops init` · `vitops validate` · `vitops favicon`',\n '',\n ...pointer,\n '',\n `<!-- regenerate: vitops agents · @getvitops/cli@${cliVersion()} -->`,\n AGENTS_END,\n ].join('\\n');\n\n const outPath = resolve(values.out as string);\n let next: string;\n let action: string;\n if (existsSync(outPath)) {\n const cur = readFileSync(outPath, 'utf8');\n const s = cur.indexOf(AGENTS_START);\n const e = cur.indexOf(AGENTS_END);\n if (s !== -1 && e !== -1 && e > s) {\n next = cur.slice(0, s) + block + cur.slice(e + AGENTS_END.length);\n action = 'updated block in';\n } else {\n next = cur.replace(/\\s*$/, '') + '\\n\\n' + block + '\\n';\n action = 'appended block to';\n }\n } else {\n mkdirSync(dirname(outPath), { recursive: true });\n next = block + '\\n';\n action = 'created';\n }\n writeFileSync(outPath, next);\n console.log(`✓ ${action} ${values.out} + ${summary}`);\n}\n\nasync function main() {\n const [command, ...rest] = process.argv.slice(2);\n if (!command || command === '-h' || command === '--help' || command === 'help') {\n console.log(HELP);\n return;\n }\n switch (command) {\n case 'generate':\n return cmdGenerate(rest);\n case 'init':\n return cmdInit(rest);\n case 'validate':\n return cmdValidate(rest);\n case 'favicon':\n return cmdFavicon(rest);\n case 'agents':\n return cmdAgents(rest);\n case 'docs':\n return cmdDocs(rest);\n default:\n fail(\n `unknown command \"${command}\" (expected: generate | init | validate | favicon | agents | docs). Try: vitops --help`,\n );\n }\n}\n\nmain().catch((err) => fail((err as Error).message));\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getvitops/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "CLI for the Vitops design-system generator: generate, init, and validate a design-system.json.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bin": {
|
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
10
|
"dist",
|
|
11
|
-
"skill"
|
|
11
|
+
"skill",
|
|
12
|
+
"CHANGELOG.md"
|
|
12
13
|
],
|
|
13
14
|
"type": "module",
|
|
14
15
|
"exports": {
|
|
@@ -21,8 +22,8 @@
|
|
|
21
22
|
"access": "public"
|
|
22
23
|
},
|
|
23
24
|
"dependencies": {
|
|
24
|
-
"@getvitops/generator": "0.
|
|
25
|
-
"@getvitops/utils": "0.
|
|
25
|
+
"@getvitops/generator": "0.8.0",
|
|
26
|
+
"@getvitops/utils": "0.8.0"
|
|
26
27
|
},
|
|
27
28
|
"devDependencies": {
|
|
28
29
|
"vitest": "^4.1.9"
|