basalt-ui 2.0.0 → 2.0.2
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 +16 -0
- package/MIGRATING.md +44 -14
- package/agent/skills/basalt-app/SKILL.md +1 -1
- package/dist/cli/config.d.ts +14 -0
- package/dist/cli/config.d.ts.map +1 -1
- package/dist/cli/config.js +6 -0
- package/dist/cli/doctor-upgrade.d.ts +12 -0
- package/dist/cli/doctor-upgrade.d.ts.map +1 -1
- package/dist/cli/doctor-upgrade.js +46 -1
- package/dist/cli/doctor.d.ts +2 -1
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +36 -4
- package/dist/cli/index.d.ts +20 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +43 -5
- package/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +7 -1
- package/dist/cli/sync.d.ts.map +1 -1
- package/dist/cli/sync.js +5 -0
- package/dist/tokens/core.d.ts +12 -11
- package/dist/tokens/core.d.ts.map +1 -1
- package/dist/tokens/core.js +9 -1
- package/llms.txt +2 -2
- package/package.json +4 -4
- package/src/cli/config.ts +22 -0
- package/src/cli/doctor-upgrade.ts +65 -0
- package/src/cli/doctor.ts +47 -5
- package/src/cli/index.ts +62 -3
- package/src/cli/init.ts +10 -1
- package/src/cli/sync.ts +6 -0
- package/src/tokens/core.ts +25 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
## [2.0.2](https://github.com/jkrumm/basalt-ui/compare/v2.0.1...v2.0.2) (2026-10-14)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* keep the brand symbol out of keyof a groupTokens result ([27f44d3](https://github.com/jkrumm/basalt-ui/commit/27f44d3da50f07f9adb5b850edc86e8e388d0550))
|
|
7
|
+
* make doctor and sync monorepo-aware ([eafb701](https://github.com/jkrumm/basalt-ui/commit/eafb7013d07a7935b393c70553e11d2a57f01c71))
|
|
8
|
+
* throw a clear error for a group not built by groupTokens ([7c0dc44](https://github.com/jkrumm/basalt-ui/commit/7c0dc447e2faff22561166f66d6e449be511981c))
|
|
9
|
+
|
|
10
|
+
## [2.0.1](https://github.com/jkrumm/basalt-ui/compare/v2.0.0...v2.0.1) (2026-10-14)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* close argo friction rows 1-3 ([41627c3](https://github.com/jkrumm/basalt-ui/commit/41627c328ad278fc303ca9317cada2d2ab5f99a4))
|
|
16
|
+
|
|
1
17
|
# [2.0.0](https://github.com/jkrumm/basalt-ui/compare/v1.41.0...v2.0.0) (2026-10-14)
|
|
2
18
|
|
|
3
19
|
|
package/MIGRATING.md
CHANGED
|
@@ -66,18 +66,18 @@ There is one row per SURFACE, not per export, and a surface earns a row once any
|
|
|
66
66
|
shipped lefthook preset both changed in 1.30.0 with no row that owned them — which is how a
|
|
67
67
|
consumer read this index, found nothing, and diffed a KPI row that had silently gone 4-up → 2-up.
|
|
68
68
|
|
|
69
|
-
| Surface | 1.27.0 | 1.28.0 | 1.29.0 | 1.30.0 | 1.30.1 | 1.30.2 | 1.31.0 | 1.32.0 | 1.32.1 | 1.33.0 | 1.34.0 | 1.34.1 | 1.35.0 | 1.36.0 | 1.36.1 | 1.37.0 | 1.37.1 | 1.38.0 | 1.38.1 | 1.39.0 | 1.40.0 | 1.40.1 | 1.40.2 | 1.40.3 | 1.41.0 | 2.0.0 | Unreleased |
|
|
70
|
-
| ----------------------------- | ------------------------------------------------------------ | -------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | --------------------------------------------------------------------- | ------ | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ---------------------------------- | ------ | ------ | -------------------------------------------------------------------------------------------- | ------ | ------ | ------ | ------ | ------ | ----------------------------------------------- | ------ | ------ | ------ | ------ | ------------------------------------------------------------ | ---------- | --- | --- |
|
|
71
|
-
| **tokens** (`./tokens`) | — | `--vx-divider` → `rgba()` on both schemes (§ Shell) | `--vx-space-touch-target` added (§ Additions) | eight spacing numbers (§ Chrome) | — | — | `--vx-hit` replaces the touch vars; `SIZE_CLASSES` (§ 1.31.0) | — | `SIZE_CLASSES`/`CONTAINER_CLASSES` actually exported (§ Fixes) | `CONTAINER_GRID_BREAKPOINTS`; `raw-breakpoint` trusts it (§ 1.33.0) | `CONTAINER_KEYS` (§ 1.34.0) | — | — | — | — | — | — | — | | `appShellInset` 20 → 16 (§ 1.38.1) | — | — | — | — | — | — | — | — |
|
|
72
|
-
| **charts** (`./charts`) | — | phone tier, `curve`, formatters, `state`, log axis (§ preamble) | `ChartState.empty: string`, `AxisBottomNumeric` (§ Additions) | responsive `height`, `legend.maxRows` (§ Charts) | `height` reaches the kinds; `maxRows` beats the `fill` fit (§ Charts) | — | container-class tier + `height` keys (§ 1.31.0) | — | `ResponsiveChartHeight` `sm` → key (§ Container recipes) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — |
|
|
73
|
-
| **shell** (`.`) | — | scrollport, region seams, **the brand left the sidebar** (§§ scrollport, brand, Shell) | `PageTitle`, `BasaltDevDock`, `useBreakpoint` (§ Additions) | More popover, aside pill, the responsive gutter, `useBasaltSpacing` (§ Chrome) | — | — | `theme.breakpoints` derived, `useSizeClass`, `data-basalt-host`, `useBreakpoint` on notice (§ 1.31.0) | `useBreakpoint` removal → 1.33.0; `useSizeClass` is shell-only (§ 1.32.0) | shell-less `shell/` gutter, `AppShell` breakpoints, `useSizeClass` for overlays (§§ Shell-less, `useSizeClass`) | — | `useBreakpoint` removed (§ 1.34.0) | — | — | `useCoarsePointer()` (§ `useCoarsePointer()`) | — | — | — | — | | content gutter 16, block 8 from `sm` (§ 1.38.1) | — | — | — | — | — | — | — | — |
|
|
74
|
-
| **controls** (`./controls`) | `NumberFilter`, `field.number` (§ Controls) | sheet renders panel rows; `PanelRow`, `SliderControl` (§ `basalt-ui/controls`) | — | — | — | — | — | — | — | `NumberFilter clearable`; `createSearchStore` `resets` (§ State and controls) | — | — | — | `FormSection`/`FormRow`/`FormGroup`/`FormActions` move here (§ The form layout moves) | — | — | — | — | — | — | — | — | — | — | — | — | — |
|
|
75
|
-
| **forms** (`./forms`) | — | `field` → `inputProps`, **`inputProps` drops `key`**, the layout tier (§ `inputProps`) | `field` DELETED — and the `--fix` recipe no longer works (§ Consolidation) | — | — | — | — | — | `FormGroup` row no longer stretches (§ Fixes) | — | — | — | — | the layout + `useForm`/`schemaResolver` deprecated, removed 1.37.0 (§ The form layout moves) | — | — | — | — | — | — | — | — | — | — | — | — | — |
|
|
76
|
-
| **data** (`./data/table`) | — | root is a `<div>`, row selection, `getItemKey` required (§ `basalt-ui/data`) | `./data` + `./query` + `./connectivity` dropped (§ Consolidation) | — | — | — | — | — | `renderCard` documented (§ `renderCard`) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — |
|
|
77
|
-
| **dashboard** (`.`) | `StatCard`: `unit`, `breakdown`, delta format (§ `StatCard`) | `StatGroup`, `WidgetGrid`, query-aware `StatCard` — additive | — | **the column law keys on the CONTAINER; `cols={4}` is 2-up at `sm`** (§ Dashboard) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — |
|
|
78
|
-
| **toolchain** (`./configs/*`) | — | — | the shipped lefthook preset's `check-theme` BROKE — the CLI resolver stopped ascending (§ CLI) | the preset's default bin, and the `root:` recipe (§ Toolchain) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — |
|
|
79
|
-
| **CLI** (`basalt-ui`) | — | — | **resolver stops relocating; `doctor` loses 6 of 10 checks** (§ CLI) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | the managed block moves `CLAUDE.md` → `AGENTS.md` (§ 1.41.0) | — | — |
|
|
80
|
-
| **guards** | five rules → `error` (§ Guards) | six new ids at `warn` (§ preamble) | `query-dual-import` retired in 1.29.1 (§ Guards) | four rules → `error` (§ Guards) | — | — | — | `raw-breakpoint`: the container-grid answer, `error` at 1.33.0 (§ 1.32.0) | `FormRow`/`FormGroup` homes in both lanes; `basalt-main` dropped (§ Fixes) | C1 + breakpoint pairs → `error`; `unknown-vx-token` `warn` (§ Guards) | — | — | — | `unknown-vx-token` → `error`; the token factories throw (§ Guards) | — | — | — | — | — | — | — | — | — | — | — | — | — |
|
|
69
|
+
| Surface | 1.27.0 | 1.28.0 | 1.29.0 | 1.30.0 | 1.30.1 | 1.30.2 | 1.31.0 | 1.32.0 | 1.32.1 | 1.33.0 | 1.34.0 | 1.34.1 | 1.35.0 | 1.36.0 | 1.36.1 | 1.37.0 | 1.37.1 | 1.38.0 | 1.38.1 | 1.39.0 | 1.40.0 | 1.40.1 | 1.40.2 | 1.40.3 | 1.41.0 | 2.0.0 | 2.0.1 | 2.0.2 | Unreleased |
|
|
70
|
+
| ----------------------------- | ------------------------------------------------------------ | -------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | --------------------------------------------------------------------- | ------ | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ---------------------------------- | ------ | ------ | -------------------------------------------------------------------------------------------- | ------ | ------ | ------ | ------ | ------ | ----------------------------------------------- | ------ | ------ | ------ | ------ | ------------------------------------------------------------ | ---------- | --- | --- | --- | --- |
|
|
71
|
+
| **tokens** (`./tokens`) | — | `--vx-divider` → `rgba()` on both schemes (§ Shell) | `--vx-space-touch-target` added (§ Additions) | eight spacing numbers (§ Chrome) | — | — | `--vx-hit` replaces the touch vars; `SIZE_CLASSES` (§ 1.31.0) | — | `SIZE_CLASSES`/`CONTAINER_CLASSES` actually exported (§ Fixes) | `CONTAINER_GRID_BREAKPOINTS`; `raw-breakpoint` trusts it (§ 1.33.0) | `CONTAINER_KEYS` (§ 1.34.0) | — | — | — | — | — | — | — | | `appShellInset` 20 → 16 (§ 1.38.1) | — | — | — | — | — | — | — | — | — | — |
|
|
72
|
+
| **charts** (`./charts`) | — | phone tier, `curve`, formatters, `state`, log axis (§ preamble) | `ChartState.empty: string`, `AxisBottomNumeric` (§ Additions) | responsive `height`, `legend.maxRows` (§ Charts) | `height` reaches the kinds; `maxRows` beats the `fill` fit (§ Charts) | — | container-class tier + `height` keys (§ 1.31.0) | — | `ResponsiveChartHeight` `sm` → key (§ Container recipes) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — |
|
|
73
|
+
| **shell** (`.`) | — | scrollport, region seams, **the brand left the sidebar** (§§ scrollport, brand, Shell) | `PageTitle`, `BasaltDevDock`, `useBreakpoint` (§ Additions) | More popover, aside pill, the responsive gutter, `useBasaltSpacing` (§ Chrome) | — | — | `theme.breakpoints` derived, `useSizeClass`, `data-basalt-host`, `useBreakpoint` on notice (§ 1.31.0) | `useBreakpoint` removal → 1.33.0; `useSizeClass` is shell-only (§ 1.32.0) | shell-less `shell/` gutter, `AppShell` breakpoints, `useSizeClass` for overlays (§§ Shell-less, `useSizeClass`) | — | `useBreakpoint` removed (§ 1.34.0) | — | — | `useCoarsePointer()` (§ `useCoarsePointer()`) | — | — | — | — | | content gutter 16, block 8 from `sm` (§ 1.38.1) | — | — | — | — | — | — | — | — | — | — |
|
|
74
|
+
| **controls** (`./controls`) | `NumberFilter`, `field.number` (§ Controls) | sheet renders panel rows; `PanelRow`, `SliderControl` (§ `basalt-ui/controls`) | — | — | — | — | — | — | — | `NumberFilter clearable`; `createSearchStore` `resets` (§ State and controls) | — | — | — | `FormSection`/`FormRow`/`FormGroup`/`FormActions` move here (§ The form layout moves) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — |
|
|
75
|
+
| **forms** (`./forms`) | — | `field` → `inputProps`, **`inputProps` drops `key`**, the layout tier (§ `inputProps`) | `field` DELETED — and the `--fix` recipe no longer works (§ Consolidation) | — | — | — | — | — | `FormGroup` row no longer stretches (§ Fixes) | — | — | — | — | the layout + `useForm`/`schemaResolver` deprecated, removed 1.37.0 (§ The form layout moves) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — |
|
|
76
|
+
| **data** (`./data/table`) | — | root is a `<div>`, row selection, `getItemKey` required (§ `basalt-ui/data`) | `./data` + `./query` + `./connectivity` dropped (§ Consolidation) | — | — | — | — | — | `renderCard` documented (§ `renderCard`) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — |
|
|
77
|
+
| **dashboard** (`.`) | `StatCard`: `unit`, `breakdown`, delta format (§ `StatCard`) | `StatGroup`, `WidgetGrid`, query-aware `StatCard` — additive | — | **the column law keys on the CONTAINER; `cols={4}` is 2-up at `sm`** (§ Dashboard) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — |
|
|
78
|
+
| **toolchain** (`./configs/*`) | — | — | the shipped lefthook preset's `check-theme` BROKE — the CLI resolver stopped ascending (§ CLI) | the preset's default bin, and the `root:` recipe (§ Toolchain) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — |
|
|
79
|
+
| **CLI** (`basalt-ui`) | — | — | **resolver stops relocating; `doctor` loses 6 of 10 checks** (§ CLI) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | the managed block moves `CLAUDE.md` → `AGENTS.md` (§ 1.41.0) | — | — | — | — |
|
|
80
|
+
| **guards** | five rules → `error` (§ Guards) | six new ids at `warn` (§ preamble) | `query-dual-import` retired in 1.29.1 (§ Guards) | four rules → `error` (§ Guards) | — | — | — | `raw-breakpoint`: the container-grid answer, `error` at 1.33.0 (§ 1.32.0) | `FormRow`/`FormGroup` homes in both lanes; `basalt-main` dropped (§ Fixes) | C1 + breakpoint pairs → `error`; `unknown-vx-token` `warn` (§ Guards) | — | — | — | `unknown-vx-token` → `error`; the token factories throw (§ Guards) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — |
|
|
81
81
|
|
|
82
82
|
---
|
|
83
83
|
|
|
@@ -88,8 +88,10 @@ Contract: `docs/V2-SPEC.md`. Every removal and move is one row, grouped by area.
|
|
|
88
88
|
### Upgrading from 1.x
|
|
89
89
|
|
|
90
90
|
1. Go to `1.41.0` first and clear its deprecations: 2.0 retires the lifecycle, so nothing deprecated survives.
|
|
91
|
-
2. Install `basalt-ui@2` and the now-required peers (§ Subpaths, peers and gates); delete
|
|
92
|
-
`@mantine
|
|
91
|
+
2. Install `basalt-ui@2` and the now-required peers (§ Subpaths, peers and gates); delete only the
|
|
92
|
+
`@mantine/{core,notifications,spotlight}/styles.layer.css` imports, because `basalt-ui/styles.css`
|
|
93
|
+
`@import`s exactly those three. Keep every extension package's layer CSS (`@mantine/dates`,
|
|
94
|
+
`@mantine/schedule`, …) imported AFTER `basalt-ui/styles.css`.
|
|
93
95
|
3. Replace the hand-built root (providers, `QueryClient`, router) with `BasaltProvider` +
|
|
94
96
|
`createBasaltRouter` (§ Provider and wiring).
|
|
95
97
|
4. Rewrite imports by area, using the tables below. A `move` changes only the specifier.
|
|
@@ -990,6 +992,34 @@ optional, subpath-required peers.
|
|
|
990
992
|
_Nothing yet. Author the next section under this heading as `## Unreleased — <title>`; the
|
|
991
993
|
release renames it and opens a new one here._
|
|
992
994
|
|
|
995
|
+
## 2.0.2
|
|
996
|
+
|
|
997
|
+
_Nothing to migrate in this release._
|
|
998
|
+
|
|
999
|
+
## 2.0.1
|
|
1000
|
+
|
|
1001
|
+
_Nothing to migrate in this release._
|
|
1002
|
+
|
|
1003
|
+
## Next patch — doctor reads the peers and the config
|
|
1004
|
+
|
|
1005
|
+
- `doctor` gains `exact-peers`: for each exact-pinned peer of the installed basalt-ui (the three
|
|
1006
|
+
`@fontsource-variable/*`, `motion`, `remend`, …) it compares your installed version and prints a
|
|
1007
|
+
one-line `bun add <pkg>@<version>` fix on a mismatch. `bun add` accepts the mismatch silently.
|
|
1008
|
+
The three font peers now pin `5.3.0`.
|
|
1009
|
+
- `doctor` gains `config-keys`: a key in the package.json `basalt` object that the config does not
|
|
1010
|
+
read fails with its fix. `basalt.chartMissingAriaLabel` is gone with its guard kind; `ariaLabel`
|
|
1011
|
+
is required on a chart now, so delete the key.
|
|
1012
|
+
- Corrected the § 2.0 "Upgrading from 1.x" step 2: delete only the core, notifications and
|
|
1013
|
+
spotlight layer imports; extension packages (`@mantine/dates`, `@mantine/schedule`) stay, after
|
|
1014
|
+
`basalt-ui/styles.css`.
|
|
1015
|
+
- `doctor` and `sync` are monorepo-aware. The manifest, `.claude/` and the AGENTS block stay at the
|
|
1016
|
+
install root; the app-scoped half (`tsconfig-base`, `app-wiring`, the `src/main.tsx`,
|
|
1017
|
+
`src/lib/nav.tsx` and `src/routes/__root.tsx` seeds) targets the app package: `basalt.app`
|
|
1018
|
+
(relative path, e.g. `"apps/dashboard"`) in the root package.json, else the one workspace package
|
|
1019
|
+
that depends on basalt-ui and has `src/main.tsx` or `index.html`, else the cwd. Two candidates
|
|
1020
|
+
fail with a message naming `basalt.app`. `doctor` run inside the app package finds the root
|
|
1021
|
+
manifest, and warns about a router seed an earlier `sync` left at the root — delete it.
|
|
1022
|
+
|
|
993
1023
|
## 2.0.0
|
|
994
1024
|
|
|
995
1025
|
_Nothing to migrate in this release._
|
|
@@ -26,7 +26,7 @@ declare module '@tanstack/react-router' {
|
|
|
26
26
|
createRoot(document.getElementById('root')!).render(<BasaltProvider router={router} />)
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
3.
|
|
29
|
+
3. Import extension layer CSS (`@mantine/dates` for `basalt-ui/controls-dates`, `@mantine/schedule`) after `basalt-ui/styles.css` (core must precede them in `@layer mantine`).
|
|
30
30
|
4. Install the peers of each subpath you import: read its `Install: bun add …` line in `node_modules/basalt-ui/llms.txt`; a subpath with no `Install:` line needs only the required peers listed at the top of that file.
|
|
31
31
|
5. In `vite.config.ts` spread `...basaltViteConfig({ port, apiTarget })` and register, in this order, `plugins: [tanstackRouter({ target: 'react', autoCodeSplitting: true }), react(), ...basaltAppPlugin({ name, description })]`. Run `bun add -d @tanstack/router-plugin` and import `tanstackRouter` from `@tanstack/router-plugin/vite`.
|
|
32
32
|
6. Run `vite build` once so the plugin writes `src/routeTree.gen.ts`; commit it (`tsc -b` fails without it).
|
package/dist/cli/config.d.ts
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
import type { GuardKind, GuardSeverity } from '../guard/index.js';
|
|
2
2
|
/** Shape of the optional `"basalt"` key in a consumer's package.json. */
|
|
3
3
|
export type BasaltConfig = {
|
|
4
|
+
/**
|
|
5
|
+
* The Vite app's directory relative to the install root, for a workspace monorepo whose manifest,
|
|
6
|
+
* `.claude/` and AGENTS block live at the root. App-scoped checks (`tsconfig-base`, `app-wiring`)
|
|
7
|
+
* and the router seeds target it. Default: the single workspace package that depends on basalt-ui
|
|
8
|
+
* and has a Vite entry, else the root itself.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* { app: 'apps/dashboard' }
|
|
12
|
+
*/
|
|
13
|
+
app?: string;
|
|
4
14
|
/** Source roots to scan. Default: `['src']`. Set explicitly for a monorepo layout. */
|
|
5
15
|
roots?: string[];
|
|
6
16
|
/** Files exempt from the scan (they ARE the palette source). Default: argo's exempt set. */
|
|
@@ -165,4 +175,8 @@ export declare const DEFAULT_ROOTS: string[];
|
|
|
165
175
|
* "matches zero files" break this derivation exists to prevent.
|
|
166
176
|
*/
|
|
167
177
|
export declare function resolveRoots(cfg: BasaltConfig): string[];
|
|
178
|
+
/** Every `BasaltConfig` key, as data for `doctor`'s `config-keys` (a test pins it to the type). */
|
|
179
|
+
export declare const BASALT_CONFIG_KEYS: (keyof BasaltConfig)[];
|
|
180
|
+
/** Keys removed from `BasaltConfig`, with the reason `doctor` prints. */
|
|
181
|
+
export declare const RETIRED_CONFIG_KEYS: Readonly<Record<string, string>>;
|
|
168
182
|
//# sourceMappingURL=config.d.ts.map
|
package/dist/cli/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/cli/config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAExD,yEAAyE;AACzE,MAAM,MAAM,YAAY,GAAG;IACzB,sFAAsF;IACtF,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,4FAA4F;IAC5F,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB;;;;;;;;;OASG;IACH,OAAO,CAAC,EAAE,SAAS,GAAG,aAAa,CAAA;IACnC;;;;;;;;;OASG;IACH,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,uGAAuG;IACvG,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IACvB;wFACoF;IACpF,QAAQ,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC,CAAA;IACpD,6FAA6F;IAC7F,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC3B,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAC7B;;;;;;;OAOG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B;;;;;OAKG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB;;;;;;;;;;;;;;;OAeG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC,CAAA;IACzD;;;;;;;;;OASG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAC3B,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,EAAE,GAAG;IAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAE5E,8EAA8E;AAC9E,wBAAgB,eAAe,CAAC,KAAK,EAAE,eAAe,GAAG,SAAS,GAAG,MAAM,EAAE,CAG5E;AAED,mFAAmF;AACnF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,eAAe,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAGlF;AAED,eAAO,MAAM,YAAY,QAAQ,CAAA;AACjC,eAAO,MAAM,aAAa,UAAiB,CAAA;AAE3C;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,YAAY,GAAG,MAAM,EAAE,CAExD"}
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/cli/config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAExD,yEAAyE;AACzE,MAAM,MAAM,YAAY,GAAG;IACzB;;;;;;;;OAQG;IACH,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,sFAAsF;IACtF,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,4FAA4F;IAC5F,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB;;;;;;;;;OASG;IACH,OAAO,CAAC,EAAE,SAAS,GAAG,aAAa,CAAA;IACnC;;;;;;;;;OASG;IACH,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,uGAAuG;IACvG,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IACvB;wFACoF;IACpF,QAAQ,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC,CAAA;IACpD,6FAA6F;IAC7F,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC3B,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAC7B;;;;;;;OAOG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B;;;;;OAKG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB;;;;;;;;;;;;;;;OAeG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC,CAAA;IACzD;;;;;;;;;OASG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAC3B,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,EAAE,GAAG;IAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAE5E,8EAA8E;AAC9E,wBAAgB,eAAe,CAAC,KAAK,EAAE,eAAe,GAAG,SAAS,GAAG,MAAM,EAAE,CAG5E;AAED,mFAAmF;AACnF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,eAAe,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAGlF;AAED,eAAO,MAAM,YAAY,QAAQ,CAAA;AACjC,eAAO,MAAM,aAAa,UAAiB,CAAA;AAE3C;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,YAAY,GAAG,MAAM,EAAE,CAExD;AAED,mGAAmG;AACnG,eAAO,MAAM,kBAAkB,EAIf,CAAC,MAAM,YAAY,CAAC,EAAE,CAAA;AAEtC,yEAAyE;AACzE,eAAO,MAAM,mBAAmB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAEhE,CAAA"}
|
package/dist/cli/config.js
CHANGED
|
@@ -11,9 +11,15 @@ const DEFAULT_ROOTS = [DEFAULT_ROOT];
|
|
|
11
11
|
function resolveRoots(cfg) {
|
|
12
12
|
return cfg.roots?.length ? cfg.roots : DEFAULT_ROOTS;
|
|
13
13
|
}
|
|
14
|
+
const BASALT_CONFIG_KEYS = "app roots exempt profile include spacingSteps severity forbiddenAccents accentHue rawRadius rawSurface cardWithBorder offSystemSurfaceVar mantineShadeIndex rawHtmlLayout inlineSpacing inlineDisplay rawMotionValue rawFormControl sub16InputFont seriesModulePath exemptRules aiMajorSkewReason".split(" ");
|
|
15
|
+
const RETIRED_CONFIG_KEYS = {
|
|
16
|
+
chartMissingAriaLabel: "its guard kind is gone in 2.0 (`ariaLabel` is required on a chart now)"
|
|
17
|
+
};
|
|
14
18
|
export {
|
|
19
|
+
BASALT_CONFIG_KEYS,
|
|
15
20
|
DEFAULT_ROOT,
|
|
16
21
|
DEFAULT_ROOTS,
|
|
22
|
+
RETIRED_CONFIG_KEYS,
|
|
17
23
|
exemptRulePaths,
|
|
18
24
|
exemptRuleReason,
|
|
19
25
|
resolveRoots
|
|
@@ -28,4 +28,16 @@ export declare function seedTsconfigExtends(cwd: string): string | null;
|
|
|
28
28
|
* proves nothing.
|
|
29
29
|
*/
|
|
30
30
|
export declare function appWiringCheck(cwd: string): Check;
|
|
31
|
+
/**
|
|
32
|
+
* `config-keys`: a key in package.json's `basalt` object that `BasaltConfig` does not declare is
|
|
33
|
+
* silently ignored, so a key retired in 2.0 keeps looking configured. Reads the raw file, not
|
|
34
|
+
* `readBasaltConfig`, which is typed and would hide the very keys this looks for.
|
|
35
|
+
*/
|
|
36
|
+
export declare function unknownConfigKeysCheck(cwd: string): Check;
|
|
37
|
+
/**
|
|
38
|
+
* `exact-peers`: basalt-ui pins some peers to one exact version, and `bun add` accepts any other
|
|
39
|
+
* version without a word. Compares each installed one against the install's declared pin; a peer
|
|
40
|
+
* that is not installed is not this check's business (optional peers are legitimately absent).
|
|
41
|
+
*/
|
|
42
|
+
export declare function exactPeersCheck(cwd: string, install: BasaltInstall): Check;
|
|
31
43
|
//# sourceMappingURL=doctor-upgrade.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor-upgrade.d.ts","sourceRoot":"","sources":["../../src/cli/doctor-upgrade.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"doctor-upgrade.d.ts","sourceRoot":"","sources":["../../src/cli/doctor-upgrade.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAE5C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAE5C,MAAM,MAAM,KAAK,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAA;AAgB9D,wEAAwE;AACxE,eAAO,MAAM,YAAY,GAAI,GAAG,MAAM,KAAG,MACc,CAAA;AA+CvD,uFAAuF;AACvF,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAqBpD;AA+CD,4FAA4F;AAC5F,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,KAAK,CAyBhF;AA4CD,mGAAmG;AACnG,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,YAAY,EACjB,OAAO,EAAE,aAAa,GACrB,KAAK,CA8BP;AAUD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkC9D;AAoDD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CA+BjD;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAezD;AAaD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,KAAK,CAwB1E"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import { dirname, relative, resolve } from "node:path";
|
|
4
|
+
import { BASALT_CONFIG_KEYS, RETIRED_CONFIG_KEYS } from "./config.js";
|
|
4
5
|
import { parseJsonc, readIfExists, scannableFiles } from "./index.js";
|
|
5
6
|
const guarded = (id, run) => {
|
|
6
7
|
try {
|
|
@@ -259,11 +260,55 @@ function appWiringCheck(cwd) {
|
|
|
259
260
|
};
|
|
260
261
|
});
|
|
261
262
|
}
|
|
263
|
+
function unknownConfigKeysCheck(cwd) {
|
|
264
|
+
return guarded("config-keys", () => {
|
|
265
|
+
const raw = readIfExists(resolve(cwd, "package.json"));
|
|
266
|
+
const block = raw === null ? null : JSON.parse(raw).basalt;
|
|
267
|
+
if (typeof block !== "object" || block === null || Array.isArray(block)) return null;
|
|
268
|
+
const known = new Set(BASALT_CONFIG_KEYS);
|
|
269
|
+
const unknown = Object.keys(block).filter((k) => !known.has(k));
|
|
270
|
+
if (unknown.length === 0) return null;
|
|
271
|
+
const named = unknown.map(
|
|
272
|
+
(k) => `basalt.${k} (${RETIRED_CONFIG_KEYS[k] ?? "not a basalt key"})`
|
|
273
|
+
);
|
|
274
|
+
return {
|
|
275
|
+
fail: `config-keys: package.json sets keys basalt-ui does not read: ${named.join("; ")}. Fix: delete each key.`
|
|
276
|
+
};
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
const EXACT_VERSION = /^\d+\.\d+\.\d+$/;
|
|
280
|
+
function installedVersion(cwd, pkg) {
|
|
281
|
+
for (let dir = cwd; ; dir = dirname(dir)) {
|
|
282
|
+
const raw = readIfExists(resolve(dir, "node_modules", pkg, "package.json"));
|
|
283
|
+
if (raw !== null) return JSON.parse(raw).version ?? null;
|
|
284
|
+
if (dirname(dir) === dir) return null;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
function exactPeersCheck(cwd, install) {
|
|
288
|
+
const id = "exact-peers";
|
|
289
|
+
if (install.dir === null)
|
|
290
|
+
return { skip: `${id}: basalt-ui does not resolve, so its peers cannot be read.` };
|
|
291
|
+
const dir = install.dir;
|
|
292
|
+
return guarded(id, () => {
|
|
293
|
+
const raw = readIfExists(resolve(dir, "package.json"));
|
|
294
|
+
const peers = (raw === null ? {} : JSON.parse(raw).peerDependencies) ?? {};
|
|
295
|
+
const off = Object.entries(peers).filter(([, range]) => EXACT_VERSION.test(range)).flatMap(([pkg, pin]) => {
|
|
296
|
+
const have = installedVersion(cwd, pkg);
|
|
297
|
+
return have === null || have === pin ? [] : [`${pkg}@${have} (basalt-ui pins ${pin}): \`bun add ${pkg}@${pin}\``];
|
|
298
|
+
});
|
|
299
|
+
if (off.length === 0) return null;
|
|
300
|
+
return {
|
|
301
|
+
fail: `${id}: installed peers differ from basalt-ui's exact pins. Fix: ${off.join("; ")}.`
|
|
302
|
+
};
|
|
303
|
+
});
|
|
304
|
+
}
|
|
262
305
|
export {
|
|
263
306
|
appWiringCheck,
|
|
264
307
|
droppedSubpathsCheck,
|
|
308
|
+
exactPeersCheck,
|
|
265
309
|
retiredLintRulesCheck,
|
|
266
310
|
seedTsconfigExtends,
|
|
267
311
|
tsconfigBaseCheck,
|
|
268
|
-
tsconfigFile
|
|
312
|
+
tsconfigFile,
|
|
313
|
+
unknownConfigKeysCheck
|
|
269
314
|
};
|
package/dist/cli/doctor.d.ts
CHANGED
|
@@ -22,7 +22,8 @@ export type DoctorResult = {
|
|
|
22
22
|
* 4. `oxlint-preset`: `.oxlintrc.json` extends the shipped preset AND that path resolves.
|
|
23
23
|
* 7. `ai-major-parity`: the `ai` major agrees across this package.json's dependency fields
|
|
24
24
|
* (exempt via `basalt.aiMajorSkewReason`; a stale reason warns).
|
|
25
|
-
* 8-
|
|
25
|
+
* 8-13. `tsconfig-base`, `retired-lint-rules`, `dropped-subpaths`, `app-wiring`, `exact-peers`,
|
|
26
|
+
* `config-keys` (./doctor-upgrade);
|
|
26
27
|
* a check that cannot run is SKIPPED and exits non-zero.
|
|
27
28
|
*
|
|
28
29
|
* Warning (non-fatal):
|
package/dist/cli/doctor.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":"AAyDA,MAAM,MAAM,YAAY,GAAG;IACzB,+CAA+C;IAC/C,YAAY,EAAE,MAAM,CAAA;IACpB,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,CAAA;IAChB;;;;;OAKG;IACH,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AA8CD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,MAAM,CAAC,aAAa,GAAE,MAAsB,EAAE,KAAK,GAAE,MAAM,EAAO,GAAG,MAAM,CAsU1F"}
|
package/dist/cli/doctor.js
CHANGED
|
@@ -19,7 +19,9 @@ import {
|
|
|
19
19
|
readBasaltConfig,
|
|
20
20
|
readIfExists,
|
|
21
21
|
readManifest,
|
|
22
|
+
resolveAppDir,
|
|
22
23
|
resolveProjectDir,
|
|
24
|
+
ROUTER_SEED_DESTS,
|
|
23
25
|
sameFile,
|
|
24
26
|
scannableFiles,
|
|
25
27
|
scanBlock,
|
|
@@ -29,8 +31,10 @@ import { resolveRoots } from "./config.js";
|
|
|
29
31
|
import {
|
|
30
32
|
appWiringCheck,
|
|
31
33
|
droppedSubpathsCheck,
|
|
34
|
+
exactPeersCheck,
|
|
32
35
|
retiredLintRulesCheck,
|
|
33
|
-
tsconfigBaseCheck
|
|
36
|
+
tsconfigBaseCheck,
|
|
37
|
+
unknownConfigKeysCheck
|
|
34
38
|
} from "./doctor-upgrade.js";
|
|
35
39
|
import { findManifestAbove, parentInstallAdvice } from "./sync.js";
|
|
36
40
|
function isSameFile(a, b) {
|
|
@@ -72,7 +76,12 @@ function resolveAiMajorSkewReason(cfg) {
|
|
|
72
76
|
function doctor(invocationCwd = process.cwd(), flags = []) {
|
|
73
77
|
if (conflictingProfileFlags("doctor", flags)) return 1;
|
|
74
78
|
const project = resolveProjectDir(invocationCwd);
|
|
75
|
-
const
|
|
79
|
+
const aboveRoot = project.relocatedFrom === null && !existsSync(resolve(project.dir, MANIFEST_PATH)) ? findManifestAbove(project.dir) : null;
|
|
80
|
+
const insideApp = aboveRoot !== null && (() => {
|
|
81
|
+
const app2 = resolveAppDir(aboveRoot);
|
|
82
|
+
return !("error" in app2) && app2.dir === project.dir;
|
|
83
|
+
})();
|
|
84
|
+
const cwd = insideApp && aboveRoot !== null ? aboveRoot : project.dir;
|
|
76
85
|
const cfg = readBasaltConfig(cwd);
|
|
77
86
|
const result = { hardFailures: 0, warnings: 0, skipped: 0 };
|
|
78
87
|
const lines = [`
|
|
@@ -97,6 +106,11 @@ basalt-ui doctor \u2014 ${cwd}
|
|
|
97
106
|
lines.push(` \u2192 BASALT_CWD relocated from ${project.relocatedFrom} to ${cwd}.
|
|
98
107
|
`);
|
|
99
108
|
}
|
|
109
|
+
if (insideApp)
|
|
110
|
+
lines.push(` \u2192 ${project.dir} is the app package; checking the install root ${cwd}.
|
|
111
|
+
`);
|
|
112
|
+
const app = resolveAppDir(cwd);
|
|
113
|
+
const appDir = "error" in app ? cwd : app.dir;
|
|
100
114
|
const profile = declaredProfile(cfg, flags);
|
|
101
115
|
if (profile === "tokens-only") {
|
|
102
116
|
lines.push(
|
|
@@ -118,6 +132,19 @@ basalt-ui doctor \u2014 ${cwd}
|
|
|
118
132
|
fail(`${MANIFEST_PATH} missing \u2014 run \`basalt-ui init\` to scaffold the consumer repo`);
|
|
119
133
|
}
|
|
120
134
|
const install = findBasaltInstall(cwd);
|
|
135
|
+
if ("error" in app) {
|
|
136
|
+
fail(`app-dir: ${app.error}`);
|
|
137
|
+
} else if (app.rel !== "") {
|
|
138
|
+
pass(`app-dir: the app is ${app.rel} (agent layer and manifest stay at the install root)`);
|
|
139
|
+
const ledger = readManifest(cwd).files;
|
|
140
|
+
for (const seed of Object.values(ROUTER_SEED_DESTS)) {
|
|
141
|
+
if (ledger[seed] !== void 0 && existsSync(resolve(cwd, seed))) {
|
|
142
|
+
warn(
|
|
143
|
+
`app-dir: ${seed} was seeded at the install root by an earlier \`sync\`, but the app is ${app.rel} \u2014 it is dead code there. Delete it (\`sync\` seeds ${app.rel}/${seed} instead).`
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
121
148
|
const manifestVersion = profile === "tokens-only" ? void 0 : readManifest(cwd).basaltVersion;
|
|
122
149
|
const at = install.dir === null ? "" : `${relative(cwd, install.dir)} (${install.version})`;
|
|
123
150
|
if (install.dir === null) {
|
|
@@ -253,7 +280,7 @@ basalt-ui doctor \u2014 ${cwd}
|
|
|
253
280
|
);
|
|
254
281
|
} else {
|
|
255
282
|
const upgrade = [
|
|
256
|
-
["tsconfig-base: tsconfig.json extends the shipped preset", tsconfigBaseCheck(
|
|
283
|
+
["tsconfig-base: tsconfig.json extends the shipped preset", tsconfigBaseCheck(appDir)],
|
|
257
284
|
[
|
|
258
285
|
"retired-lint-rules: .oxlintrc.json sets no retired basalt/* rule",
|
|
259
286
|
retiredLintRulesCheck(cwd, install)
|
|
@@ -264,7 +291,12 @@ basalt-ui doctor \u2014 ${cwd}
|
|
|
264
291
|
],
|
|
265
292
|
[
|
|
266
293
|
"app-wiring: the entry mounts BasaltProvider and the router tree is generated",
|
|
267
|
-
appWiringCheck(
|
|
294
|
+
appWiringCheck(appDir)
|
|
295
|
+
],
|
|
296
|
+
["exact-peers: installed exact-pinned peers match basalt-ui", exactPeersCheck(cwd, install)],
|
|
297
|
+
[
|
|
298
|
+
"config-keys: the basalt config block sets only keys basalt-ui reads",
|
|
299
|
+
unknownConfigKeysCheck(cwd)
|
|
268
300
|
]
|
|
269
301
|
];
|
|
270
302
|
for (const [ok, check] of upgrade) {
|
package/dist/cli/index.d.ts
CHANGED
|
@@ -199,6 +199,22 @@ export declare const ROUTER_SEED_DESTS: {
|
|
|
199
199
|
readonly root: "src/routes/__root.tsx";
|
|
200
200
|
readonly main: "src/main.tsx";
|
|
201
201
|
};
|
|
202
|
+
/** A router seed's dest, relative to the install root: under the app dir when it is not the root. */
|
|
203
|
+
export declare function routerSeedDest(appRel: string, seed: keyof typeof ROUTER_SEED_DESTS): string;
|
|
204
|
+
/** The app directory a command's app-scoped half targets: `rel` is '' when it is the install root. */
|
|
205
|
+
export type AppResolution = {
|
|
206
|
+
dir: string;
|
|
207
|
+
rel: string;
|
|
208
|
+
} | {
|
|
209
|
+
error: string;
|
|
210
|
+
};
|
|
211
|
+
/**
|
|
212
|
+
* Where the Vite app lives relative to the install root `root` (manifest, `.claude/`, AGENTS block).
|
|
213
|
+
* ONE resolution for `doctor`, `sync` and `init`, in order: `basalt.app` in the root package.json;
|
|
214
|
+
* else the single workspace package that depends on basalt-ui AND has a Vite entry; else `root`
|
|
215
|
+
* itself (a single-package app). Two such packages is an error — the choice is not inferable.
|
|
216
|
+
*/
|
|
217
|
+
export declare function resolveAppDir(root: string): AppResolution;
|
|
202
218
|
/**
|
|
203
219
|
* Where the seed engine is running relative to the consumer's git repo — decides which
|
|
204
220
|
* repo-root-shaped seeds are safe to write. `init`/`sync` compute it once per run via
|
|
@@ -214,6 +230,10 @@ export type PlacementFlags = {
|
|
|
214
230
|
/** Absolute path of the detected repo root. Meaningful only when `isPackageRepoRoot` is false —
|
|
215
231
|
* otherwise it equals the package dir and is never read. */
|
|
216
232
|
repoRoot: string;
|
|
233
|
+
/** The app directory relative to the install root ('' = the root itself); see {@link resolveAppDir}. */
|
|
234
|
+
appRel: string;
|
|
235
|
+
/** Non-null when the app directory is ambiguous or invalid: commands refuse rather than guess. */
|
|
236
|
+
appError: string | null;
|
|
217
237
|
};
|
|
218
238
|
/** The default placement — today's single-package-at-repo-root behaviour, unconditionally. */
|
|
219
239
|
export declare const ROOT_PLACEMENT: PlacementFlags;
|
package/dist/cli/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/index.js
CHANGED
|
@@ -351,6 +351,37 @@ const ROUTER_SEED_DESTS = {
|
|
|
351
351
|
root: "src/routes/__root.tsx",
|
|
352
352
|
main: "src/main.tsx"
|
|
353
353
|
};
|
|
354
|
+
function routerSeedDest(appRel, seed) {
|
|
355
|
+
return appRel === "" ? ROUTER_SEED_DESTS[seed] : `${appRel}/${ROUTER_SEED_DESTS[seed]}`;
|
|
356
|
+
}
|
|
357
|
+
const appRelative = (root, dir) => relativePosix(root, dir).replace(/^\.\/?/, "");
|
|
358
|
+
const hasViteEntry = (dir) => existsSync(resolve(dir, "src/main.tsx")) || existsSync(resolve(dir, "index.html"));
|
|
359
|
+
function resolveAppDir(root) {
|
|
360
|
+
const self = { dir: root, rel: "" };
|
|
361
|
+
const explicit = readBasaltConfig(root).app;
|
|
362
|
+
if (explicit !== void 0) {
|
|
363
|
+
const dir = resolve(root, explicit);
|
|
364
|
+
const rel = appRelative(root, dir);
|
|
365
|
+
if (rel.startsWith("..") || !existsSync(resolve(dir, "package.json"))) {
|
|
366
|
+
return {
|
|
367
|
+
error: `basalt.app "${explicit}" must be a directory with a package.json inside ${root}.`
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
return dir === root ? self : { dir, rel };
|
|
371
|
+
}
|
|
372
|
+
const candidates = collectWorkspacePackages(root).packages.filter(
|
|
373
|
+
(pkg) => pkg.dir !== root && hasDependency(pkg.dir, "basalt-ui") && hasViteEntry(pkg.dir)
|
|
374
|
+
);
|
|
375
|
+
if (candidates.length === 0) return self;
|
|
376
|
+
const [only] = candidates;
|
|
377
|
+
if (candidates.length === 1 && only !== void 0) {
|
|
378
|
+
return { dir: only.dir, rel: appRelative(root, only.dir) };
|
|
379
|
+
}
|
|
380
|
+
const names = candidates.map((pkg) => appRelative(root, pkg.dir)).join(", ");
|
|
381
|
+
return {
|
|
382
|
+
error: `${candidates.length} workspace packages depend on basalt-ui and have a Vite entry (${names}) \u2014 cannot tell which is the app. Set \`basalt.app\` (e.g. \`"basalt": { "app": "apps/web" }\`) in the root package.json.`
|
|
383
|
+
};
|
|
384
|
+
}
|
|
354
385
|
function hasDependency(cwd, pkgName) {
|
|
355
386
|
try {
|
|
356
387
|
const pkg = JSON.parse(readFileSync(resolve(cwd, "package.json"), "utf8"));
|
|
@@ -363,7 +394,9 @@ function hasDependency(cwd, pkgName) {
|
|
|
363
394
|
}
|
|
364
395
|
const ROOT_PLACEMENT = {
|
|
365
396
|
isPackageRepoRoot: true,
|
|
366
|
-
repoRoot: ""
|
|
397
|
+
repoRoot: "",
|
|
398
|
+
appRel: "",
|
|
399
|
+
appError: null
|
|
367
400
|
};
|
|
368
401
|
function findRepoRoot(dir) {
|
|
369
402
|
let current = dir;
|
|
@@ -384,9 +417,12 @@ function oxlintBinResolves(dir) {
|
|
|
384
417
|
}
|
|
385
418
|
function resolvePlacement(cwd) {
|
|
386
419
|
const repoRoot = findRepoRoot(cwd);
|
|
420
|
+
const app = resolveAppDir(cwd);
|
|
387
421
|
return {
|
|
388
422
|
isPackageRepoRoot: repoRoot === cwd,
|
|
389
|
-
repoRoot
|
|
423
|
+
repoRoot,
|
|
424
|
+
appRel: "error" in app ? "" : app.rel,
|
|
425
|
+
appError: "error" in app ? app.error : null
|
|
390
426
|
};
|
|
391
427
|
}
|
|
392
428
|
function managedFiles(placement = ROOT_PLACEMENT) {
|
|
@@ -480,7 +516,7 @@ pre-commit:
|
|
|
480
516
|
`
|
|
481
517
|
};
|
|
482
518
|
const rootRoute = {
|
|
483
|
-
dest:
|
|
519
|
+
dest: routerSeedDest(placement.appRel, "root"),
|
|
484
520
|
mode: "seed",
|
|
485
521
|
source: "agent/templates/__root.tpl",
|
|
486
522
|
render: (ctx) => {
|
|
@@ -490,13 +526,13 @@ pre-commit:
|
|
|
490
526
|
}
|
|
491
527
|
};
|
|
492
528
|
const navModule = {
|
|
493
|
-
dest:
|
|
529
|
+
dest: routerSeedDest(placement.appRel, "nav"),
|
|
494
530
|
mode: "seed",
|
|
495
531
|
source: "agent/templates/nav.tpl",
|
|
496
532
|
render: (ctx) => readSource(ctx.pkgRoot, "agent/templates/nav.tpl")
|
|
497
533
|
};
|
|
498
534
|
const mainEntry = {
|
|
499
|
-
dest:
|
|
535
|
+
dest: routerSeedDest(placement.appRel, "main"),
|
|
500
536
|
mode: "seed",
|
|
501
537
|
source: "agent/templates/main.tpl",
|
|
502
538
|
render: (ctx) => readSource(ctx.pkgRoot, "agent/templates/main.tpl")
|
|
@@ -1002,11 +1038,13 @@ export {
|
|
|
1002
1038
|
relativePosix,
|
|
1003
1039
|
renderContext,
|
|
1004
1040
|
reportPrune,
|
|
1041
|
+
resolveAppDir,
|
|
1005
1042
|
resolveGuardConfig,
|
|
1006
1043
|
resolvePlacement,
|
|
1007
1044
|
resolveProjectDir,
|
|
1008
1045
|
retiredManagedDests,
|
|
1009
1046
|
rootsNotices,
|
|
1047
|
+
routerSeedDest,
|
|
1010
1048
|
run,
|
|
1011
1049
|
sameFile,
|
|
1012
1050
|
scanBlock,
|
package/dist/cli/init.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAmB,aAAa,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAmB,aAAa,EAAE,MAAM,SAAS,CAAA;AA6D7D,yGAAyG;AACzG,wBAAgB,IAAI,CAAC,GAAG,GAAE,MAAsB,EAAE,aAAa,GAAE,aAAkB,GAAG,MAAM,CA0L3F"}
|
package/dist/cli/init.js
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
declaredProfile,
|
|
7
7
|
readBasaltConfig,
|
|
8
8
|
ROUTER_SEED_DESTS,
|
|
9
|
+
routerSeedDest,
|
|
9
10
|
findBasaltInstall,
|
|
10
11
|
managedFiles,
|
|
11
12
|
mergeOxlintExtends,
|
|
@@ -47,6 +48,11 @@ function init(cwd = process.cwd(), scaffoldFlags = {}) {
|
|
|
47
48
|
`\u26A0 basalt-ui init: basalt-ui does not resolve from ${cwd} or any directory above it \u2014 the seeded \`extends\` paths and CI steps are being written against the repo root by assumption. Install basalt-ui here (or at the repo root) and re-run \`basalt-ui init\` so they resolve.`
|
|
48
49
|
);
|
|
49
50
|
}
|
|
51
|
+
const appError = resolvePlacement(cwd).appError;
|
|
52
|
+
if (appError !== null) {
|
|
53
|
+
console.error(`\u2716 basalt-ui init: ${appError}`);
|
|
54
|
+
return 1;
|
|
55
|
+
}
|
|
50
56
|
const rootsState = reconcileRoots(cwd, { write: true });
|
|
51
57
|
const ctx = renderContext(cwd);
|
|
52
58
|
const lintScript = `oxlint . && ${ctx.vars.BASALT_BIN} check-theme`;
|
|
@@ -74,7 +80,7 @@ function init(cwd = process.cwd(), scaffoldFlags = {}) {
|
|
|
74
80
|
const manifest = readManifest(cwd);
|
|
75
81
|
const placement = resolvePlacement(cwd);
|
|
76
82
|
const tokensOnly = declaredProfile(readBasaltConfig(cwd), []) === "tokens-only";
|
|
77
|
-
const routerSeeds = Object.
|
|
83
|
+
const routerSeeds = Object.keys(ROUTER_SEED_DESTS).map((seed) => routerSeedDest(placement.appRel, seed));
|
|
78
84
|
const files = managedFiles(placement).filter((f) => !(tokensOnly && routerSeeds.includes(f.dest)));
|
|
79
85
|
const writtenFiles = [];
|
|
80
86
|
const keptFiles = [];
|
package/dist/cli/sync.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/cli/sync.ts"],"names":[],"mappings":"AAwCA,gGAAgG;AAChG,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAGjE;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,mGAAmG;IACnG,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAC1B,CAAA;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAKrF;AAED,qFAAqF;AACrF,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQ5D;AAED;;;;;;;;;GASG;AACH,wBAAgB,IAAI,CAAC,IAAI,GAAE,WAAgB,EAAE,aAAa,GAAE,MAAsB,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/cli/sync.ts"],"names":[],"mappings":"AAwCA,gGAAgG;AAChG,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAGjE;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,mGAAmG;IACnG,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAC1B,CAAA;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAKrF;AAED,qFAAqF;AACrF,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQ5D;AAED;;;;;;;;;GASG;AACH,wBAAgB,IAAI,CAAC,IAAI,GAAE,WAAgB,EAAE,aAAa,GAAE,MAAsB,GAAG,MAAM,CAgM1F"}
|
package/dist/cli/sync.js
CHANGED
|
@@ -63,6 +63,11 @@ function sync(opts = {}, invocationCwd = process.cwd()) {
|
|
|
63
63
|
);
|
|
64
64
|
return 0;
|
|
65
65
|
}
|
|
66
|
+
const appError = resolvePlacement(cwd).appError;
|
|
67
|
+
if (appError !== null) {
|
|
68
|
+
console.error(`\u2716 basalt-ui sync: ${appError}`);
|
|
69
|
+
return 1;
|
|
70
|
+
}
|
|
66
71
|
if (!existsSync(resolve(cwd, MANIFEST_PATH))) {
|
|
67
72
|
const elsewhere = findManifestAbove(cwd);
|
|
68
73
|
const wouldWrite = managedFiles(resolvePlacement(cwd)).length;
|
package/dist/tokens/core.d.ts
CHANGED
|
@@ -190,18 +190,19 @@ export declare function seriesTokens<const T extends SeriesMap>(map: T, prefix?:
|
|
|
190
190
|
* not the widened SeriesMap, enabling downstream exact-key checks in groupTokens / seriesTokens).
|
|
191
191
|
*/
|
|
192
192
|
export declare function defineSeries<const T extends SeriesMap>(map: T): T;
|
|
193
|
-
|
|
194
|
-
|
|
193
|
+
declare const GROUP_REF: unique symbol;
|
|
194
|
+
/** A `var(--vx-<name>-<key>)` ref minted by `groupTokens`. The brand lives on the VALUES, so it never shows up in `keyof` the group. */
|
|
195
|
+
export type GroupRef = string & {
|
|
196
|
+
readonly [GROUP_REF]: true;
|
|
197
|
+
};
|
|
195
198
|
/**
|
|
196
|
-
*
|
|
197
|
-
*
|
|
198
|
-
*
|
|
199
|
+
* What `groupTokens` returns. `BuildPaletteOpts.groups` takes these, so the `${name}-` key that
|
|
200
|
+
* emits the variables and the one that references them come from one call and cannot be spelled
|
|
201
|
+
* two ways. A bare series map (object values) and a plain string record (unbranded values) are
|
|
202
|
+
* both rejected; the runtime payload sits under the non-enumerable {@link SERIES_GROUP} symbol.
|
|
199
203
|
*/
|
|
200
204
|
export type SeriesGroup = {
|
|
201
|
-
readonly [
|
|
202
|
-
readonly prefix: string;
|
|
203
|
-
readonly map: SeriesMap;
|
|
204
|
-
};
|
|
205
|
+
readonly [key: string]: GroupRef;
|
|
205
206
|
};
|
|
206
207
|
/**
|
|
207
208
|
* Build a single namespaced group's token refs (`var(--vx-<name>-<key>)`).
|
|
@@ -210,8 +211,8 @@ export type SeriesGroup = {
|
|
|
210
211
|
* error at the call site rather than a silent `Record<string, string>` widening.
|
|
211
212
|
*/
|
|
212
213
|
export declare function groupTokens<const T extends SeriesMap>(name: string, map: T): {
|
|
213
|
-
[K in keyof T]:
|
|
214
|
-
}
|
|
214
|
+
readonly [K in keyof T]: GroupRef;
|
|
215
|
+
};
|
|
215
216
|
/**
|
|
216
217
|
* The attribute + values the per-scheme blocks key off. Defaults reproduce Mantine's own toggle
|
|
217
218
|
* (`data-mantine-color-scheme` = `dark` / `light`), so a consumer only names the axis it differs
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../src/tokens/core.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAYH,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAUvE,OAAO,EAAE,EAAE,EAAE,CAAC,EAAE,MAAM,WAAW,CAAA;AAMjC,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AACnF,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAM5D,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AACxC,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAO7C,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AACzC,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAI5C,OAAO,EACL,iBAAiB,EACjB,0BAA0B,EAC1B,cAAc,EACd,qBAAqB,EACrB,YAAY,GACb,MAAM,gBAAgB,CAAA;AACvB,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAEpD,wFAAwF;AACxF,MAAM,MAAM,SAAS,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAEvD,8FAA8F;AAC9F,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;AAEjD;;;;;;GAMG;AACH,eAAO,MAAM,KAAK,GAAI,OAAO,MAAM,EAAE,GAAG,MAAM,KAAG,MACoB,CAAA;AA6DrE,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA4Jb;;;;;OAKG;;IAEH;;wDAEoD;;CAE5C,CAAA;AAEV;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,WAAW;IACtB;;;;;OAKG;;CAEK,CAAA;AAOV;;;;;;;;GAQG;AACH,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAExC;AAwbD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,KAAK,CAAC,CAAC,SAAS,SAAS,EACpD,GAAG,EAAE,CAAC,EACN,MAAM,SAAK,GACV;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,MAAM;CAAE,CAQ5B;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,CAAC,CAAC,SAAS,SAAS,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAEjE;
|
|
1
|
+
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../src/tokens/core.ts"],"names":[],"mappings":"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"}
|
package/dist/tokens/core.js
CHANGED
|
@@ -596,7 +596,15 @@ function buildPaletteCss(opts = {}, data = buildPaletteData()) {
|
|
|
596
596
|
const derived = extraDerived ? `${derivedBlock}
|
|
597
597
|
${extraDerived}` : derivedBlock;
|
|
598
598
|
const side = (s) => {
|
|
599
|
-
const extra = groups.map((group) =>
|
|
599
|
+
const extra = groups.map((group) => {
|
|
600
|
+
const payload = group[SERIES_GROUP];
|
|
601
|
+
if (!payload) {
|
|
602
|
+
throw new Error(
|
|
603
|
+
"BuildPaletteOpts.groups: every group must come from groupTokens(name, map)"
|
|
604
|
+
);
|
|
605
|
+
}
|
|
606
|
+
return groupSide(payload.prefix, payload.map, s);
|
|
607
|
+
}).join("\n");
|
|
600
608
|
const framework = frameworkPrimitives(s, data, legacyAliases);
|
|
601
609
|
return extra ? `${framework}
|
|
602
610
|
${extra}` : framework;
|
package/llms.txt
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# basalt-ui v2.0.
|
|
1
|
+
# basalt-ui v2.0.2
|
|
2
2
|
# Opinionated framework for Mantine-based React apps — theme, app shell, TanStack Charts, toolchain presets
|
|
3
3
|
#
|
|
4
4
|
# Entry points: use the exact import specifier below; do not guess.
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
# A subpath's `Install:` line is its required peers; `OptionalPeers:` are import()-only, install on use.
|
|
14
14
|
|
|
15
15
|
Package: basalt-ui
|
|
16
|
-
Version: 2.0.
|
|
16
|
+
Version: 2.0.2
|
|
17
17
|
|
|
18
18
|
## basalt-ui
|
|
19
19
|
Import: import { ... } from 'basalt-ui'
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "basalt-ui",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.2",
|
|
4
4
|
"description": "Opinionated framework for Mantine-based React apps — theme, app shell, TanStack Charts, toolchain presets",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"charts",
|
|
@@ -165,9 +165,9 @@
|
|
|
165
165
|
},
|
|
166
166
|
"peerDependencies": {
|
|
167
167
|
"@ai-sdk/provider": "^4.0.26",
|
|
168
|
-
"@fontsource-variable/hubot-sans": "5.
|
|
169
|
-
"@fontsource-variable/jetbrains-mono": "5.
|
|
170
|
-
"@fontsource-variable/nunito-sans": "5.
|
|
168
|
+
"@fontsource-variable/hubot-sans": "5.3.0",
|
|
169
|
+
"@fontsource-variable/jetbrains-mono": "5.3.0",
|
|
170
|
+
"@fontsource-variable/nunito-sans": "5.3.0",
|
|
171
171
|
"@mantine/core": "^9.7.0",
|
|
172
172
|
"@mantine/dates": "^9.7.0",
|
|
173
173
|
"@mantine/form": "^9.7.0",
|
package/src/cli/config.ts
CHANGED
|
@@ -4,6 +4,16 @@ import type { GuardKind, GuardSeverity } from '../guard'
|
|
|
4
4
|
|
|
5
5
|
/** Shape of the optional `"basalt"` key in a consumer's package.json. */
|
|
6
6
|
export type BasaltConfig = {
|
|
7
|
+
/**
|
|
8
|
+
* The Vite app's directory relative to the install root, for a workspace monorepo whose manifest,
|
|
9
|
+
* `.claude/` and AGENTS block live at the root. App-scoped checks (`tsconfig-base`, `app-wiring`)
|
|
10
|
+
* and the router seeds target it. Default: the single workspace package that depends on basalt-ui
|
|
11
|
+
* and has a Vite entry, else the root itself.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* { app: 'apps/dashboard' }
|
|
15
|
+
*/
|
|
16
|
+
app?: string
|
|
7
17
|
/** Source roots to scan. Default: `['src']`. Set explicitly for a monorepo layout. */
|
|
8
18
|
roots?: string[]
|
|
9
19
|
/** Files exempt from the scan (they ARE the palette source). Default: argo's exempt set. */
|
|
@@ -178,3 +188,15 @@ export const DEFAULT_ROOTS = [DEFAULT_ROOT]
|
|
|
178
188
|
export function resolveRoots(cfg: BasaltConfig): string[] {
|
|
179
189
|
return cfg.roots?.length ? cfg.roots : DEFAULT_ROOTS
|
|
180
190
|
}
|
|
191
|
+
|
|
192
|
+
/** Every `BasaltConfig` key, as data for `doctor`'s `config-keys` (a test pins it to the type). */
|
|
193
|
+
export const BASALT_CONFIG_KEYS = (
|
|
194
|
+
'app roots exempt profile include spacingSteps severity forbiddenAccents accentHue rawRadius rawSurface ' +
|
|
195
|
+
'cardWithBorder offSystemSurfaceVar mantineShadeIndex rawHtmlLayout inlineSpacing inlineDisplay ' +
|
|
196
|
+
'rawMotionValue rawFormControl sub16InputFont seriesModulePath exemptRules aiMajorSkewReason'
|
|
197
|
+
).split(' ') as (keyof BasaltConfig)[]
|
|
198
|
+
|
|
199
|
+
/** Keys removed from `BasaltConfig`, with the reason `doctor` prints. */
|
|
200
|
+
export const RETIRED_CONFIG_KEYS: Readonly<Record<string, string>> = {
|
|
201
|
+
chartMissingAriaLabel: 'its guard kind is gone in 2.0 (`ariaLabel` is required on a chart now)',
|
|
202
|
+
}
|
|
@@ -6,6 +6,7 @@ import { existsSync, readFileSync, writeFileSync } from 'node:fs'
|
|
|
6
6
|
import { createRequire } from 'node:module'
|
|
7
7
|
import { dirname, relative, resolve } from 'node:path'
|
|
8
8
|
|
|
9
|
+
import { BASALT_CONFIG_KEYS, RETIRED_CONFIG_KEYS } from './config'
|
|
9
10
|
import type { BasaltConfig } from './config'
|
|
10
11
|
import { parseJsonc, readIfExists, scannableFiles } from './index'
|
|
11
12
|
import type { BasaltInstall } from './index'
|
|
@@ -390,3 +391,67 @@ export function appWiringCheck(cwd: string): Check {
|
|
|
390
391
|
}
|
|
391
392
|
})
|
|
392
393
|
}
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* `config-keys`: a key in package.json's `basalt` object that `BasaltConfig` does not declare is
|
|
397
|
+
* silently ignored, so a key retired in 2.0 keeps looking configured. Reads the raw file, not
|
|
398
|
+
* `readBasaltConfig`, which is typed and would hide the very keys this looks for.
|
|
399
|
+
*/
|
|
400
|
+
export function unknownConfigKeysCheck(cwd: string): Check {
|
|
401
|
+
return guarded('config-keys', () => {
|
|
402
|
+
const raw = readIfExists(resolve(cwd, 'package.json'))
|
|
403
|
+
const block = raw === null ? null : (JSON.parse(raw) as { basalt?: unknown }).basalt
|
|
404
|
+
if (typeof block !== 'object' || block === null || Array.isArray(block)) return null
|
|
405
|
+
const known = new Set<string>(BASALT_CONFIG_KEYS)
|
|
406
|
+
const unknown = Object.keys(block).filter((k) => !known.has(k))
|
|
407
|
+
if (unknown.length === 0) return null
|
|
408
|
+
const named = unknown.map(
|
|
409
|
+
(k) => `basalt.${k} (${RETIRED_CONFIG_KEYS[k] ?? 'not a basalt key'})`,
|
|
410
|
+
)
|
|
411
|
+
return {
|
|
412
|
+
fail: `config-keys: package.json sets keys basalt-ui does not read: ${named.join('; ')}. Fix: delete each key.`,
|
|
413
|
+
}
|
|
414
|
+
})
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
const EXACT_VERSION = /^\d+\.\d+\.\d+$/
|
|
418
|
+
|
|
419
|
+
/** `node_modules/<pkg>/package.json`'s version, searching `cwd` then every ancestor. */
|
|
420
|
+
function installedVersion(cwd: string, pkg: string): string | null {
|
|
421
|
+
for (let dir = cwd; ; dir = dirname(dir)) {
|
|
422
|
+
const raw = readIfExists(resolve(dir, 'node_modules', pkg, 'package.json'))
|
|
423
|
+
if (raw !== null) return (JSON.parse(raw) as { version?: string }).version ?? null
|
|
424
|
+
if (dirname(dir) === dir) return null
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
* `exact-peers`: basalt-ui pins some peers to one exact version, and `bun add` accepts any other
|
|
430
|
+
* version without a word. Compares each installed one against the install's declared pin; a peer
|
|
431
|
+
* that is not installed is not this check's business (optional peers are legitimately absent).
|
|
432
|
+
*/
|
|
433
|
+
export function exactPeersCheck(cwd: string, install: BasaltInstall): Check {
|
|
434
|
+
const id = 'exact-peers'
|
|
435
|
+
if (install.dir === null)
|
|
436
|
+
return { skip: `${id}: basalt-ui does not resolve, so its peers cannot be read.` }
|
|
437
|
+
const dir = install.dir
|
|
438
|
+
return guarded(id, () => {
|
|
439
|
+
const raw = readIfExists(resolve(dir, 'package.json'))
|
|
440
|
+
const peers =
|
|
441
|
+
(raw === null
|
|
442
|
+
? {}
|
|
443
|
+
: (JSON.parse(raw) as { peerDependencies?: Record<string, string> }).peerDependencies) ?? {}
|
|
444
|
+
const off = Object.entries(peers)
|
|
445
|
+
.filter(([, range]) => EXACT_VERSION.test(range))
|
|
446
|
+
.flatMap(([pkg, pin]) => {
|
|
447
|
+
const have = installedVersion(cwd, pkg)
|
|
448
|
+
return have === null || have === pin
|
|
449
|
+
? []
|
|
450
|
+
: [`${pkg}@${have} (basalt-ui pins ${pin}): \`bun add ${pkg}@${pin}\``]
|
|
451
|
+
})
|
|
452
|
+
if (off.length === 0) return null
|
|
453
|
+
return {
|
|
454
|
+
fail: `${id}: installed peers differ from basalt-ui's exact pins. Fix: ${off.join('; ')}.`,
|
|
455
|
+
}
|
|
456
|
+
})
|
|
457
|
+
}
|
package/src/cli/doctor.ts
CHANGED
|
@@ -26,7 +26,9 @@ import {
|
|
|
26
26
|
readBasaltConfig,
|
|
27
27
|
readIfExists,
|
|
28
28
|
readManifest,
|
|
29
|
+
resolveAppDir,
|
|
29
30
|
resolveProjectDir,
|
|
31
|
+
ROUTER_SEED_DESTS,
|
|
30
32
|
sameFile,
|
|
31
33
|
scannableFiles,
|
|
32
34
|
scanBlock,
|
|
@@ -36,8 +38,10 @@ import { resolveRoots } from './config'
|
|
|
36
38
|
import {
|
|
37
39
|
appWiringCheck,
|
|
38
40
|
droppedSubpathsCheck,
|
|
41
|
+
exactPeersCheck,
|
|
39
42
|
retiredLintRulesCheck,
|
|
40
43
|
tsconfigBaseCheck,
|
|
44
|
+
unknownConfigKeysCheck,
|
|
41
45
|
} from './doctor-upgrade'
|
|
42
46
|
import type { Check } from './doctor-upgrade'
|
|
43
47
|
import { findManifestAbove, parentInstallAdvice } from './sync'
|
|
@@ -120,7 +124,8 @@ function resolveAiMajorSkewReason(cfg: BasaltConfig): {
|
|
|
120
124
|
* 4. `oxlint-preset`: `.oxlintrc.json` extends the shipped preset AND that path resolves.
|
|
121
125
|
* 7. `ai-major-parity`: the `ai` major agrees across this package.json's dependency fields
|
|
122
126
|
* (exempt via `basalt.aiMajorSkewReason`; a stale reason warns).
|
|
123
|
-
* 8-
|
|
127
|
+
* 8-13. `tsconfig-base`, `retired-lint-rules`, `dropped-subpaths`, `app-wiring`, `exact-peers`,
|
|
128
|
+
* `config-keys` (./doctor-upgrade);
|
|
124
129
|
* a check that cannot run is SKIPPED and exits non-zero.
|
|
125
130
|
*
|
|
126
131
|
* Warning (non-fatal):
|
|
@@ -132,7 +137,18 @@ function resolveAiMajorSkewReason(cfg: BasaltConfig): {
|
|
|
132
137
|
export function doctor(invocationCwd: string = process.cwd(), flags: string[] = []): number {
|
|
133
138
|
if (conflictingProfileFlags('doctor', flags)) return 1
|
|
134
139
|
const project = resolveProjectDir(invocationCwd)
|
|
135
|
-
|
|
140
|
+
// Inside the app package of a monorepo the manifest is above: read the install root instead.
|
|
141
|
+
const aboveRoot =
|
|
142
|
+
project.relocatedFrom === null && !existsSync(resolve(project.dir, MANIFEST_PATH))
|
|
143
|
+
? findManifestAbove(project.dir)
|
|
144
|
+
: null
|
|
145
|
+
const insideApp =
|
|
146
|
+
aboveRoot !== null &&
|
|
147
|
+
(() => {
|
|
148
|
+
const app = resolveAppDir(aboveRoot)
|
|
149
|
+
return !('error' in app) && app.dir === project.dir
|
|
150
|
+
})()
|
|
151
|
+
const cwd = insideApp && aboveRoot !== null ? aboveRoot : project.dir
|
|
136
152
|
const cfg = readBasaltConfig(cwd)
|
|
137
153
|
const result: DoctorResult = { hardFailures: 0, warnings: 0, skipped: 0 }
|
|
138
154
|
const lines: string[] = [`\nbasalt-ui doctor — ${cwd}\n`]
|
|
@@ -157,6 +173,11 @@ export function doctor(invocationCwd: string = process.cwd(), flags: string[] =
|
|
|
157
173
|
lines.push(` → BASALT_CWD relocated from ${project.relocatedFrom} to ${cwd}.\n`)
|
|
158
174
|
}
|
|
159
175
|
|
|
176
|
+
if (insideApp)
|
|
177
|
+
lines.push(` → ${project.dir} is the app package; checking the install root ${cwd}.\n`)
|
|
178
|
+
|
|
179
|
+
const app = resolveAppDir(cwd)
|
|
180
|
+
const appDir = 'error' in app ? cwd : app.dir
|
|
160
181
|
const profile = declaredProfile(cfg, flags)
|
|
161
182
|
if (profile === 'tokens-only') {
|
|
162
183
|
lines.push(
|
|
@@ -189,6 +210,22 @@ export function doctor(invocationCwd: string = process.cwd(), flags: string[] =
|
|
|
189
210
|
|
|
190
211
|
const install = findBasaltInstall(cwd)
|
|
191
212
|
|
|
213
|
+
// ── App placement: the agent layer is at the root, the app is where `resolveAppDir` says ────
|
|
214
|
+
if ('error' in app) {
|
|
215
|
+
fail(`app-dir: ${app.error}`)
|
|
216
|
+
} else if (app.rel !== '') {
|
|
217
|
+
pass(`app-dir: the app is ${app.rel} (agent layer and manifest stay at the install root)`)
|
|
218
|
+
const ledger = readManifest(cwd).files
|
|
219
|
+
for (const seed of Object.values(ROUTER_SEED_DESTS)) {
|
|
220
|
+
if (ledger[seed] !== undefined && existsSync(resolve(cwd, seed))) {
|
|
221
|
+
warn(
|
|
222
|
+
`app-dir: ${seed} was seeded at the install root by an earlier \`sync\`, but the app is ` +
|
|
223
|
+
`${app.rel} — it is dead code there. Delete it (\`sync\` seeds ${app.rel}/${seed} instead).`,
|
|
224
|
+
)
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
192
229
|
// ── Hard check 2: install matches the manifest, and doctor says WHERE (the AGENTS-block's claim)
|
|
193
230
|
const manifestVersion = profile === 'tokens-only' ? undefined : readManifest(cwd).basaltVersion
|
|
194
231
|
const at = install.dir === null ? '' : `${relative(cwd, install.dir)} (${install.version})`
|
|
@@ -370,14 +407,14 @@ export function doctor(invocationCwd: string = process.cwd(), flags: string[] =
|
|
|
370
407
|
pass('ai-major-parity: this package.json declares no ai dependency — nothing to compare')
|
|
371
408
|
}
|
|
372
409
|
|
|
373
|
-
// ── Hard checks 8-
|
|
410
|
+
// ── Hard checks 8-13: strictness and the 1.x → 2.0 upgrade path (./doctor-upgrade) ──────────
|
|
374
411
|
if (profile === 'tokens-only') {
|
|
375
412
|
pass(
|
|
376
413
|
'tsconfig-base / retired-lint-rules / dropped-subpaths / app-wiring: n/a — a tokens-only consumer',
|
|
377
414
|
)
|
|
378
415
|
} else {
|
|
379
416
|
const upgrade: [string, Check][] = [
|
|
380
|
-
['tsconfig-base: tsconfig.json extends the shipped preset', tsconfigBaseCheck(
|
|
417
|
+
['tsconfig-base: tsconfig.json extends the shipped preset', tsconfigBaseCheck(appDir)],
|
|
381
418
|
[
|
|
382
419
|
'retired-lint-rules: .oxlintrc.json sets no retired basalt/* rule',
|
|
383
420
|
retiredLintRulesCheck(cwd, install),
|
|
@@ -388,7 +425,12 @@ export function doctor(invocationCwd: string = process.cwd(), flags: string[] =
|
|
|
388
425
|
],
|
|
389
426
|
[
|
|
390
427
|
'app-wiring: the entry mounts BasaltProvider and the router tree is generated',
|
|
391
|
-
appWiringCheck(
|
|
428
|
+
appWiringCheck(appDir),
|
|
429
|
+
],
|
|
430
|
+
['exact-peers: installed exact-pinned peers match basalt-ui', exactPeersCheck(cwd, install)],
|
|
431
|
+
[
|
|
432
|
+
'config-keys: the basalt config block sets only keys basalt-ui reads',
|
|
433
|
+
unknownConfigKeysCheck(cwd),
|
|
392
434
|
],
|
|
393
435
|
]
|
|
394
436
|
for (const [ok, check] of upgrade) {
|
package/src/cli/index.ts
CHANGED
|
@@ -654,6 +654,56 @@ export const ROUTER_SEED_DESTS = {
|
|
|
654
654
|
main: 'src/main.tsx',
|
|
655
655
|
} as const
|
|
656
656
|
|
|
657
|
+
/** A router seed's dest, relative to the install root: under the app dir when it is not the root. */
|
|
658
|
+
export function routerSeedDest(appRel: string, seed: keyof typeof ROUTER_SEED_DESTS): string {
|
|
659
|
+
return appRel === '' ? ROUTER_SEED_DESTS[seed] : `${appRel}/${ROUTER_SEED_DESTS[seed]}`
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
/** The app directory a command's app-scoped half targets: `rel` is '' when it is the install root. */
|
|
663
|
+
export type AppResolution = { dir: string; rel: string } | { error: string }
|
|
664
|
+
|
|
665
|
+
/** `dir` relative to `root` without relativePosix's leading `./` ('' for the root itself). */
|
|
666
|
+
const appRelative = (root: string, dir: string): string =>
|
|
667
|
+
relativePosix(root, dir).replace(/^\.\/?/, '')
|
|
668
|
+
|
|
669
|
+
const hasViteEntry = (dir: string): boolean =>
|
|
670
|
+
existsSync(resolve(dir, 'src/main.tsx')) || existsSync(resolve(dir, 'index.html'))
|
|
671
|
+
|
|
672
|
+
/**
|
|
673
|
+
* Where the Vite app lives relative to the install root `root` (manifest, `.claude/`, AGENTS block).
|
|
674
|
+
* ONE resolution for `doctor`, `sync` and `init`, in order: `basalt.app` in the root package.json;
|
|
675
|
+
* else the single workspace package that depends on basalt-ui AND has a Vite entry; else `root`
|
|
676
|
+
* itself (a single-package app). Two such packages is an error — the choice is not inferable.
|
|
677
|
+
*/
|
|
678
|
+
export function resolveAppDir(root: string): AppResolution {
|
|
679
|
+
const self = { dir: root, rel: '' }
|
|
680
|
+
const explicit = readBasaltConfig(root).app
|
|
681
|
+
if (explicit !== undefined) {
|
|
682
|
+
const dir = resolve(root, explicit)
|
|
683
|
+
const rel = appRelative(root, dir)
|
|
684
|
+
if (rel.startsWith('..') || !existsSync(resolve(dir, 'package.json'))) {
|
|
685
|
+
return {
|
|
686
|
+
error: `basalt.app "${explicit}" must be a directory with a package.json inside ${root}.`,
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
return dir === root ? self : { dir, rel }
|
|
690
|
+
}
|
|
691
|
+
const candidates = collectWorkspacePackages(root).packages.filter(
|
|
692
|
+
(pkg) => pkg.dir !== root && hasDependency(pkg.dir, 'basalt-ui') && hasViteEntry(pkg.dir),
|
|
693
|
+
)
|
|
694
|
+
if (candidates.length === 0) return self
|
|
695
|
+
const [only] = candidates
|
|
696
|
+
if (candidates.length === 1 && only !== undefined) {
|
|
697
|
+
return { dir: only.dir, rel: appRelative(root, only.dir) }
|
|
698
|
+
}
|
|
699
|
+
const names = candidates.map((pkg) => appRelative(root, pkg.dir)).join(', ')
|
|
700
|
+
return {
|
|
701
|
+
error:
|
|
702
|
+
`${candidates.length} workspace packages depend on basalt-ui and have a Vite entry (${names}) — ` +
|
|
703
|
+
'cannot tell which is the app. Set `basalt.app` (e.g. `"basalt": { "app": "apps/web" }`) in the root package.json.',
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
|
|
657
707
|
/** True when `pkgName` appears in the consumer's dependencies, devDependencies, or peerDependencies. */
|
|
658
708
|
function hasDependency(cwd: string, pkgName: string): boolean {
|
|
659
709
|
try {
|
|
@@ -687,12 +737,18 @@ export type PlacementFlags = {
|
|
|
687
737
|
/** Absolute path of the detected repo root. Meaningful only when `isPackageRepoRoot` is false —
|
|
688
738
|
* otherwise it equals the package dir and is never read. */
|
|
689
739
|
repoRoot: string
|
|
740
|
+
/** The app directory relative to the install root ('' = the root itself); see {@link resolveAppDir}. */
|
|
741
|
+
appRel: string
|
|
742
|
+
/** Non-null when the app directory is ambiguous or invalid: commands refuse rather than guess. */
|
|
743
|
+
appError: string | null
|
|
690
744
|
}
|
|
691
745
|
|
|
692
746
|
/** The default placement — today's single-package-at-repo-root behaviour, unconditionally. */
|
|
693
747
|
export const ROOT_PLACEMENT: PlacementFlags = {
|
|
694
748
|
isPackageRepoRoot: true,
|
|
695
749
|
repoRoot: '',
|
|
750
|
+
appRel: '',
|
|
751
|
+
appError: null,
|
|
696
752
|
}
|
|
697
753
|
|
|
698
754
|
/**
|
|
@@ -725,9 +781,12 @@ export function oxlintBinResolves(dir: string): boolean {
|
|
|
725
781
|
/** Resolve a run's placement flags once, from the consumer cwd. */
|
|
726
782
|
export function resolvePlacement(cwd: string): PlacementFlags {
|
|
727
783
|
const repoRoot = findRepoRoot(cwd)
|
|
784
|
+
const app = resolveAppDir(cwd)
|
|
728
785
|
return {
|
|
729
786
|
isPackageRepoRoot: repoRoot === cwd,
|
|
730
787
|
repoRoot,
|
|
788
|
+
appRel: 'error' in app ? '' : app.rel,
|
|
789
|
+
appError: 'error' in app ? app.error : null,
|
|
731
790
|
}
|
|
732
791
|
}
|
|
733
792
|
|
|
@@ -854,7 +913,7 @@ export function managedFiles(placement: PlacementFlags = ROOT_PLACEMENT): Manage
|
|
|
854
913
|
|
|
855
914
|
/** TanStack Router root route with QueryClient context wiring (seed — consumer-owned after init). */
|
|
856
915
|
const rootRoute: ManagedFile = {
|
|
857
|
-
dest:
|
|
916
|
+
dest: routerSeedDest(placement.appRel, 'root'),
|
|
858
917
|
mode: 'seed',
|
|
859
918
|
source: 'agent/templates/__root.tpl',
|
|
860
919
|
render: (ctx) => {
|
|
@@ -866,7 +925,7 @@ export function managedFiles(placement: PlacementFlags = ROOT_PLACEMENT): Manage
|
|
|
866
925
|
|
|
867
926
|
/** The leaf `NAV` module `__root.tsx` imports (seed — consumer-owned after init). */
|
|
868
927
|
const navModule: ManagedFile = {
|
|
869
|
-
dest:
|
|
928
|
+
dest: routerSeedDest(placement.appRel, 'nav'),
|
|
870
929
|
mode: 'seed',
|
|
871
930
|
source: 'agent/templates/nav.tpl',
|
|
872
931
|
render: (ctx) => readSource(ctx.pkgRoot, 'agent/templates/nav.tpl'),
|
|
@@ -874,7 +933,7 @@ export function managedFiles(placement: PlacementFlags = ROOT_PLACEMENT): Manage
|
|
|
874
933
|
|
|
875
934
|
/** The 2.0 entry: mounts the router and declares the `Register` augmentation `defineNav` needs. */
|
|
876
935
|
const mainEntry: ManagedFile = {
|
|
877
|
-
dest:
|
|
936
|
+
dest: routerSeedDest(placement.appRel, 'main'),
|
|
878
937
|
mode: 'seed',
|
|
879
938
|
source: 'agent/templates/main.tpl',
|
|
880
939
|
render: (ctx) => readSource(ctx.pkgRoot, 'agent/templates/main.tpl'),
|
package/src/cli/init.ts
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
declaredProfile,
|
|
14
14
|
readBasaltConfig,
|
|
15
15
|
ROUTER_SEED_DESTS,
|
|
16
|
+
routerSeedDest,
|
|
16
17
|
findBasaltInstall,
|
|
17
18
|
managedFiles,
|
|
18
19
|
mergeOxlintExtends,
|
|
@@ -82,6 +83,12 @@ export function init(cwd: string = process.cwd(), scaffoldFlags: ScaffoldFlags =
|
|
|
82
83
|
)
|
|
83
84
|
}
|
|
84
85
|
|
|
86
|
+
const appError = resolvePlacement(cwd).appError
|
|
87
|
+
if (appError !== null) {
|
|
88
|
+
console.error(`✖ basalt-ui init: ${appError}`)
|
|
89
|
+
return 1
|
|
90
|
+
}
|
|
91
|
+
|
|
85
92
|
const rootsState = reconcileRoots(cwd, { write: true })
|
|
86
93
|
|
|
87
94
|
// Built AFTER the roots patch — every roots-derived template variable reads the key just written.
|
|
@@ -120,7 +127,9 @@ export function init(cwd: string = process.cwd(), scaffoldFlags: ScaffoldFlags =
|
|
|
120
127
|
const placement = resolvePlacement(cwd)
|
|
121
128
|
// A tokens-only consumer has no use for the Mantine/React scaffolds (doctor skips them there too).
|
|
122
129
|
const tokensOnly = declaredProfile(readBasaltConfig(cwd), []) === 'tokens-only'
|
|
123
|
-
const routerSeeds: string[] =
|
|
130
|
+
const routerSeeds: string[] = (
|
|
131
|
+
Object.keys(ROUTER_SEED_DESTS) as (keyof typeof ROUTER_SEED_DESTS)[]
|
|
132
|
+
).map((seed) => routerSeedDest(placement.appRel, seed))
|
|
124
133
|
const files = managedFiles(placement).filter((f) => !(tokensOnly && routerSeeds.includes(f.dest)))
|
|
125
134
|
|
|
126
135
|
const writtenFiles: string[] = []
|
package/src/cli/sync.ts
CHANGED
|
@@ -101,6 +101,12 @@ export function sync(opts: SyncOptions = {}, invocationCwd: string = process.cwd
|
|
|
101
101
|
return 0
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
+
const appError = resolvePlacement(cwd).appError
|
|
105
|
+
if (appError !== null) {
|
|
106
|
+
console.error(`✖ basalt-ui sync: ${appError}`)
|
|
107
|
+
return 1
|
|
108
|
+
}
|
|
109
|
+
|
|
104
110
|
// Refuse BEFORE reconcileRoots, which writes `basalt.roots` into package.json.
|
|
105
111
|
if (!existsSync(resolve(cwd, MANIFEST_PATH))) {
|
|
106
112
|
const elsewhere = findManifestAbove(cwd)
|
package/src/tokens/core.ts
CHANGED
|
@@ -820,15 +820,23 @@ export function defineSeries<const T extends SeriesMap>(map: T): T {
|
|
|
820
820
|
/** Runtime key of the {@link SeriesGroup} brand. */
|
|
821
821
|
const SERIES_GROUP: unique symbol = Symbol('basalt.series-group')
|
|
822
822
|
|
|
823
|
-
|
|
824
|
-
* The brand `groupTokens` puts on its return value. `BuildPaletteOpts.groups` takes these, so the
|
|
825
|
-
* `${name}-` key that emits the variables and the one that references them come from one call and
|
|
826
|
-
* cannot be spelled two ways.
|
|
827
|
-
*/
|
|
828
|
-
export type SeriesGroup = {
|
|
823
|
+
type GroupPayload = {
|
|
829
824
|
readonly [SERIES_GROUP]: { readonly prefix: string; readonly map: SeriesMap }
|
|
830
825
|
}
|
|
831
826
|
|
|
827
|
+
declare const GROUP_REF: unique symbol
|
|
828
|
+
|
|
829
|
+
/** A `var(--vx-<name>-<key>)` ref minted by `groupTokens`. The brand lives on the VALUES, so it never shows up in `keyof` the group. */
|
|
830
|
+
export type GroupRef = string & { readonly [GROUP_REF]: true }
|
|
831
|
+
|
|
832
|
+
/**
|
|
833
|
+
* What `groupTokens` returns. `BuildPaletteOpts.groups` takes these, so the `${name}-` key that
|
|
834
|
+
* emits the variables and the one that references them come from one call and cannot be spelled
|
|
835
|
+
* two ways. A bare series map (object values) and a plain string record (unbranded values) are
|
|
836
|
+
* both rejected; the runtime payload sits under the non-enumerable {@link SERIES_GROUP} symbol.
|
|
837
|
+
*/
|
|
838
|
+
export type SeriesGroup = { readonly [key: string]: GroupRef }
|
|
839
|
+
|
|
832
840
|
/**
|
|
833
841
|
* Build a single namespaced group's token refs (`var(--vx-<name>-<key>)`).
|
|
834
842
|
*
|
|
@@ -838,12 +846,12 @@ export type SeriesGroup = {
|
|
|
838
846
|
export function groupTokens<const T extends SeriesMap>(
|
|
839
847
|
name: string,
|
|
840
848
|
map: T,
|
|
841
|
-
): { [K in keyof T]:
|
|
849
|
+
): { readonly [K in keyof T]: GroupRef } {
|
|
842
850
|
const refs = seriesTokens(map, `${name}-`)
|
|
843
851
|
// Non-enumerable, symbol-keyed: a series key can never collide with the brand, and
|
|
844
852
|
// `Object.keys(refs)` still lists exactly the series.
|
|
845
853
|
Object.defineProperty(refs, SERIES_GROUP, { value: { prefix: `${name}-`, map } })
|
|
846
|
-
return refs as { [K in keyof T]:
|
|
854
|
+
return refs as { readonly [K in keyof T]: GroupRef }
|
|
847
855
|
}
|
|
848
856
|
|
|
849
857
|
/**
|
|
@@ -1024,7 +1032,15 @@ export function buildPaletteCss(
|
|
|
1024
1032
|
const derived = extraDerived ? `${derivedBlock}\n${extraDerived}` : derivedBlock
|
|
1025
1033
|
const side = (s: Side): string => {
|
|
1026
1034
|
const extra = groups
|
|
1027
|
-
.map((group) =>
|
|
1035
|
+
.map((group) => {
|
|
1036
|
+
const payload = (group as unknown as Partial<GroupPayload>)[SERIES_GROUP]
|
|
1037
|
+
if (!payload) {
|
|
1038
|
+
throw new Error(
|
|
1039
|
+
'BuildPaletteOpts.groups: every group must come from groupTokens(name, map)',
|
|
1040
|
+
)
|
|
1041
|
+
}
|
|
1042
|
+
return groupSide(payload.prefix, payload.map, s)
|
|
1043
|
+
})
|
|
1028
1044
|
.join('\n')
|
|
1029
1045
|
const framework = frameworkPrimitives(s, data, legacyAliases)
|
|
1030
1046
|
return extra ? `${framework}\n${extra}` : framework
|