@voltro/ui-shadcn 0.77.0 → 0.78.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.
Files changed (2) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -39,6 +39,54 @@ _Changes staged for the next release accumulate here (rolled up from
39
39
 
40
40
  ---
41
41
 
42
+ ## [0.78.0] — 2026-09-22
43
+
44
+ ### ⚠ BREAKING
45
+
46
+ - **A file migration declares whether it runs before or after the schema apply** — `@voltro/database`, `@voltro/cli`
47
+
48
+ `migration({ … })` now requires `phase: 'before-schema' | 'after-schema'`. `'before-schema'` is the order every file migration has always run in — first, before the planner diffs declared against live — and is unchanged. The new `'after-schema'` phase runs LAST in the same job, once the plan has been applied and the plugin steps and change triggers have converged, which is where a body that needs the new shape belongs: a back-fill into a table the same deploy creates could previously only meet its own `skipUnless` guard, be recorded, and never run again. Both phases run under the same failure gate in `voltro migrate`, `voltro db apply`, `voltro db files` and the `voltro dev` auto-migrate; `voltro db apply --plan` refuses a pending `before-schema` migration as before and applies a pending `after-schema` one. Migration: run `voltro update` (the codemod adds `phase: 'before-schema'` to every existing migration), or add the field by hand.
49
+
50
+ ### Added
51
+
52
+ - **A migrate run names a skip the same run makes permanent** — `@voltro/database`, `@voltro/cli`
53
+
54
+ A `before-schema` file migration that stops at `ctx.skipUnless` because a schema object is absent is recorded as applied and never offered again — so when the plan computed immediately afterwards CREATES that object, the skip could never have been anything else. `voltro db apply`, `voltro migrate` and the `voltro dev` auto-migrate now say so, naming the objects the body found missing that the plan goes on to create and the phase that would have run it. The objects are measured from the `ctx.schema` existence questions the body actually asked, not read out of the skip reason, so a body that skips for a reason unrelated to the schema is not reported. Nothing is refused: by the time both facts exist the migration is already recorded.
55
+
56
+ ### Fixed
57
+
58
+ - **`latest` waits for the whole release, the dashboard included** — `@voltro/cli`
59
+
60
+ Every `@voltro/*` package of a release carries the same version, and `@voltro/dashboard` is published from its own repository once the rest are on the registry — so for the length of that run the release existed for every package but one, while `latest` already named it. Measured across the three releases before this change: the dashboard landed 8m43s, 9m00s and 8m17s after `@voltro/cli`. An installation started in that window against the newest published version bumps every pin and then fails with `ERR_PNPM_NO_MATCHING_VERSION` on the one package that does not have it yet. The release now holds the `latest` tag until every package of the lockstep set is downloadable — the dashboard is waited for exactly like a tarball that has not reached the CDN — so the newest published version is one that can be installed whole. Until it is complete, `latest` stays on the previous release rather than naming a partial one. An update that names an explicit version can still start mid-release, because a version resolves the moment its own package uploads; `voltro update --wait` remains the way to cover that.
61
+ - **A migration body guarding on `schema.tableExists` runs in a database-free test** — `@voltro/database`, `@voltro/runtime`
62
+
63
+ A file migration whose first statement is the guard the docs recommend — `ctx.skipUnless(ctx.schema.tableExists('…'), '…')` — could not be driven over the in-memory store: `skipUnless` worked without a SQL client, but its predicate was a `ctx.schema` call and every one of those refused, so the only way to test such a body was to split the guard out of `up`. A migration context built without a client now answers the two read-only probes the store can answer honestly about itself — `schema.tableExists` from the store's own table map, `schema.columnExists` from the keys the held rows carry — through the new optional `DataStore.storedTables()` capability, which `InMemoryDataStore` and its transaction view implement. A table that is present and empty exists; `columnExists` on an empty table refuses rather than answering `false`, because it holds no evidence either way. `schema.snapshot`, `schema.indexExists`, `schema.foreignKeyExists` and every schema change still refuse — a store has no catalog, and a fabricated answer is one a migration would branch on — and each refusal now names what to do instead.
64
+
65
+ Two more fixes on the same surface, both found by running a PROMISE-form body through the guard rather than only an Effect one. `skipUnless` reached the runner wrapped in a `FiberFailure`, so the migration FAILED instead of being recorded as skipped. And a `ctx.schema` call from a Promise body inside a transactional migration asked the pool for a connection instead of using the transaction's, which on a single-connection dialect is the connection the transaction is holding — the migration hung forever. Every `ctx.schema` member now executes on the store's own connection, so both body shapes reach the same outcome on every dialect.
66
+ - **A storage change no longer reads as `text → text` in a migration plan** — `@voltro/cli`, `@voltro/database`
67
+
68
+ A change to a column's storage PARAMETERS — a text length, a decimal precision — keeps the column's type, so the planned operation carries the same type on both sides. Two readers rendered that as the type change it is not: the plan row showed `tier text → text`, which is indistinguishable from a no-op, and the rolling-deploy advisory said "the new text type can reject their writes", which names nothing to act on. Both now say the storage is what moves, and the advisory's remedy is the one that applies — widen now, narrow in a later deploy once every writer produces values that fit. The numbers were never lost: the operation's reason carries them (`text length 65535 → 16`, with the count query for a narrowing) and still does. Reachable for an ordinary edit: adding `.oneOf([...])` to an existing unbounded `text()` column renders a bounded column on every dialect that can express a width, measured on MySQL and MariaDB.
69
+ - **TypeScript 7 removed thirteen tsconfig options, not the three we named** — `@voltro/cli`
70
+
71
+ The TypeScript 7 upgrade note named three removed tsconfig options. A workspace that followed it hit a fourth — `"esModuleInterop": false`, in twelve of its configs, where the ones that set `true` typechecked cleanly so only part of the workspace failed. Adding a fourth bullet would have left nine more waiting, so the set was measured instead: every boolean option TypeScript 6.0.3 accepts, written into a tsconfig in both spellings, plus every value of every enum option, typechecked against TypeScript 7.0.2. Thirteen are refused, in two shapes — an option whose value alone is gone (`esModuleInterop=false`, `allowSyntheticDefaultImports=false`, `alwaysStrict=false`, `target=ES5`, `module=AMD`/`System`/`UMD`, `moduleResolution=node10`/`Classic`) and one removed outright (`downlevelIteration`, `outFile`, `baseUrl`). A new note carries all of them with their replacements and three `git grep` lines that find every occurrence at once, and it fires only for a config that actually carries one — the accepted spelling stays quiet. It also says the thing the codes cannot: TS5108 covers several unrelated removals, so what identifies a case is the option and value in the message, not the code. The framework's own templates carry none of the thirteen; checked, not assumed.
72
+
73
+ The gate matches a PATTERN rather than a literal, which is new for a codemod that reads config: JSON permits whitespace wherever a token boundary allows, so `"esModuleInterop" : false` and a literal list of spellings disagree — and a spelling the list forgets is silence from the gate, which reads as nothing to do.
74
+ - **Workflow submission rows carry one identity shape again** — `@voltro/cli`, `@voltro/workflow`
75
+
76
+ Starts of a workflow with a declared concurrency limit wrote their internal submission row with an identity prefix one character shorter than the one every other start path writes, so `_voltro_workflow_submissions` ended up holding an identity shape nothing declared. That is not cosmetic: pool release recovery pages this table by id under the database's own collation, and the two shapes sort in one order there and the opposite order in the serving process — measured on MariaDB with `utf8mb3_general_ci`, where a census over a mixed page stopped at the row that crosses the shapes and left every pooled permit held. All start paths now mint a new identity through one function. The one other shape this table holds is deliberate — a retry request reuses its own content-addressed identity so a retried reservation finds its own row — and recovery tolerates it. Rows written by earlier versions keep their identity and are read normally; nothing needs to be migrated.
77
+
78
+ ---
79
+
80
+ ## [0.77.1] — 2026-09-22
81
+
82
+ ### Fixed
83
+
84
+ - **A built page no longer claims it was generated by `voltro dev`** — `@voltro/cli`
85
+
86
+ `voltro dev`, `voltro build` and `voltro start` share one shell generator, and it headed every generated file with ``GENERATED BY `voltro dev` — do not edit; will be overwritten on next boot.`` whoever called it. `voltro build` runs Vite with the generated shell as its template, so that line travelled into `dist/` and was readable in the page source of every deployed site — wrong about the command, and wrong about the promise, because nothing overwrites a deployed tree on a boot. The writing command is now passed in and the banner names it: a built page says `voltro build` and `will be overwritten on next build`. The parameter is required, so a future caller has to decide rather than silently inheriting the development wording.
87
+
88
+ ---
89
+
42
90
  ## [0.77.0] — 2026-09-22
43
91
 
44
92
  ### ⚠ BREAKING
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voltro/ui-shadcn",
3
- "version": "0.77.0",
3
+ "version": "0.78.0",
4
4
  "description": "Voltro's first-party shadcn/ui kit: Tailwind v4 design tokens (light + dark), 30+ primitives, layout compositions, styled widgets for the @voltro/ui seam, and the canonical theme/language preference-cookie helpers.",
5
5
  "keywords": [
6
6
  "voltro",
@@ -52,7 +52,7 @@
52
52
  "@radix-ui/react-toggle-group": "^1.1.19",
53
53
  "@shikijs/langs": "^4.4.3",
54
54
  "@shikijs/themes": "^4.4.3",
55
- "@voltro/ui": "0.77.0",
55
+ "@voltro/ui": "0.78.0",
56
56
  "class-variance-authority": "^0.7.1",
57
57
  "clsx": "^2.1.1",
58
58
  "shiki": "^4.4.3",