@valbuild/tanstack 0.125.0 → 0.126.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 CHANGED
@@ -1,5 +1,127 @@
1
1
  # @valbuild/tanstack
2
2
 
3
+ ## 0.126.0
4
+
5
+ ### Patch Changes
6
+
7
+ - [#652](https://github.com/valbuild/val/pull/652) [`f2fe70d`](https://github.com/valbuild/val/commit/f2fe70dab2b65000dfaf289f09c70b4a8291467a) Thanks [@freekh](https://github.com/freekh)! - `s.union` is now `s.discriminatedUnion` and `s.enum`.
8
+
9
+ `s.union` did two unrelated jobs and worked out which one you meant from its
10
+ first argument: a string key meant a tagged union of objects, literal schemas
11
+ meant a set of allowed strings. Those are now two schemas with two names.
12
+
13
+ ```ts
14
+ // A fixed set of strings — presents as a dropdown
15
+ s.enum("primary", "secondary", "ghost"); // Schema<"primary" | "secondary" | "ghost">
16
+
17
+ // One of several object shapes, told apart by a tag field
18
+ s.discriminatedUnion(
19
+ "type",
20
+ s.object({ type: s.literal("hero"), heading: s.string() }),
21
+ s.object({ type: s.literal("quote"), text: s.string() }),
22
+ );
23
+ ```
24
+
25
+ `s.enum` takes the strings directly, so the `s.literal(...)` wrapper is gone.
26
+
27
+ **`s.union` still works** — it is deprecated, and it builds exactly the schema
28
+ above, so nothing has to change today:
29
+
30
+ ```ts
31
+ s.union(s.literal("one"), s.literal("two")); // → s.enum("one", "two")
32
+ s.union("type", pageA, pageB); // → s.discriminatedUnion("type", pageA, pageB)
33
+ ```
34
+
35
+ The two are different kinds of node, and that is the reason for the split. A
36
+ discriminated union is a container: the selected variant's fields are the fields
37
+ being edited, and everything that walks a schema descends through it. An enum is
38
+ a leaf — a string with a closed domain — so nothing recurses into it. Told apart
39
+ only by the shape of `key`, every consumer had to re-derive which one it was
40
+ holding; each now has its own serialized type (`"discriminated-union"` and
41
+ `"enum"`) and Val Studio has a field per kind rather than one field that
42
+ branches.
43
+
44
+ Two behaviour changes fall out of the split, both of them fixes:
45
+
46
+ - A value that is not a string at all now fails an enum's validation with a
47
+ type error. `s.union` of literals only ever checked the value against its
48
+ literals when the value WAS a string, so a number or an object where an enum
49
+ was declared validated clean.
50
+ - An enum field now shows its validation errors in Val Studio where the field
51
+ is opened on its own — the module editor and the canvas's fields column — and
52
+ gets the compact error layout inside an inline list row. It is a leaf now, so
53
+ it goes through the same error rendering as every other leaf field; the string
54
+ union bypassed it and showed nothing in those places.
55
+
56
+ Several latent crashes in the old `s.union` are fixed on the way past, all of
57
+ them cases where it threw a `TypeError` instead of reporting:
58
+
59
+ - A required discriminated union holding `null` now reports a type error rather
60
+ than throwing, and resolving a path underneath a nullable one that is `null`
61
+ gives the error the API promises instead of a crash.
62
+ - `s.literal("")` is a legal discriminator tag, and `s.enum("")` a legal value.
63
+ Both used to be treated as absent by a truthiness check — in path resolution,
64
+ in stega encoding, and in the message that lists a union's valid tags. The
65
+ editor's dropdowns handle them too: an empty value is reserved by the select
66
+ component and had to be mapped around.
67
+ - A variant that omits the discriminator entirely is now reported as the schema
68
+ error it is, instead of throwing while the check looked for it.
69
+ - An enum's value is now indexed for search, like every other string leaf. The
70
+ old string union was never indexed at all, so searching for one of its values
71
+ could not find the field.
72
+ - A nullable discriminated union set to `null` no longer renders a spinner that
73
+ never resolves.
74
+
75
+ `s.discriminatedUnion` also requires at least one variant, as `s.enum` requires
76
+ at least one value: a union with nothing to select is not a thing to write, and
77
+ everything downstream reads the first variant where it needs any.
78
+
79
+ If you read serialized schemas yourself, that is the breaking part: `type` is no
80
+ longer `"union"`, an enum carries `values: string[]` instead of a `key` plus
81
+ `items` of literal schemas, and `UnionSchema` is no longer a class.
82
+ `SerializedUnionSchema`, `SerializedStringUnionSchema`,
83
+ `SerializedObjectUnionSchema` and `UnionSchema` remain as deprecated type
84
+ aliases.
85
+
86
+ - [#661](https://github.com/valbuild/val/pull/661) [`171208a`](https://github.com/valbuild/val/commit/171208a20177e68ed5a8b1a6fdaabfe893a6aa5f) Thanks [@freekh](https://github.com/freekh)! - Every schema method now has a worked `@example` in its JSDoc, so hovering it in
87
+ your editor shows what to write.
88
+
89
+ That covers the whole builder surface — `.describe()`, `.validate()`,
90
+ `.nullable()`, `.readonly()`, `.hidden()`, `.preview()`, `.render()`, and the
91
+ per-type methods such as `.minLength()`, `.regexp()`, `.raw()`, `.multiline()`,
92
+ `.from()` / `.to()`, `.remote()`, `.jsonValues()` and `.external()` — as well as
93
+ `c.define()`, `c.json()`, `c.external()` and the `val` helpers (`val.attrs`,
94
+ `val.raw`, `val.unstable_getPath` and friends).
95
+
96
+ One of the examples corrected a real trap: a custom validator returns
97
+ `false | string`, so the natural-looking
98
+
99
+ ```ts
100
+ s.string().validate((val) => val.trim() === val || "No surrounding spaces");
101
+ ```
102
+
103
+ does not type check — `||` yields `true`, and `true` is not one of the two
104
+ answers. Write it as a ternary instead:
105
+
106
+ ```ts
107
+ s.string().validate((val) =>
108
+ val.trim() === val ? false : "No surrounding spaces",
109
+ );
110
+ ```
111
+
112
+ The examples are checked in CI, not just written: one test asks the TypeScript
113
+ checker for the doc each method actually resolves to and fails if it has no
114
+ `@example`, and another compiles every example it finds.
115
+
116
+ - Updated dependencies [[`719ad6b`](https://github.com/valbuild/val/commit/719ad6b607bcf136d0dbde9e90bf4b8a843561a4), [`9830277`](https://github.com/valbuild/val/commit/9830277e9aaca8da3030f629c2656ec58da47e45), [`64bfd0a`](https://github.com/valbuild/val/commit/64bfd0a6c85832ea5169b53e47087f22e193df36), [`7782979`](https://github.com/valbuild/val/commit/7782979e9b52f2015a6e72dc981e630d4f8c78e2), [`5bfd630`](https://github.com/valbuild/val/commit/5bfd630b63dee2189e238f20fe72ecc5537160f7), [`ccbcda6`](https://github.com/valbuild/val/commit/ccbcda60b3e3c465071229ae1ba28ac735483e63), [`f2fe70d`](https://github.com/valbuild/val/commit/f2fe70dab2b65000dfaf289f09c70b4a8291467a), [`5c18c99`](https://github.com/valbuild/val/commit/5c18c99ecc84651f82123481fc042063db953833), [`755e1a3`](https://github.com/valbuild/val/commit/755e1a3953775cb8d2c2dce87d6810d3dc329640), [`c6b1ec8`](https://github.com/valbuild/val/commit/c6b1ec84f1883750a4cfe5f70470b177621e971f), [`656f680`](https://github.com/valbuild/val/commit/656f680043c640f678625a64e690389ab23a0a69), [`610a041`](https://github.com/valbuild/val/commit/610a0414b120b521f38a2eb1182b3778bf778b2b), [`171208a`](https://github.com/valbuild/val/commit/171208a20177e68ed5a8b1a6fdaabfe893a6aa5f)]:
117
+ - @valbuild/ui@0.126.0
118
+ - @valbuild/shared@0.126.0
119
+ - @valbuild/server@0.126.0
120
+ - @valbuild/core@0.126.0
121
+ - @valbuild/react@0.126.0
122
+ - @valbuild/language-server@0.126.0
123
+ - @valbuild/mcp@0.126.0
124
+
3
125
  ## 0.125.0
4
126
 
5
127
  ### Minor Changes
package/README.md CHANGED
@@ -374,7 +374,7 @@ SDK of your choice. See [`@valbuild/mcp`](https://www.npmjs.com/package/@valbuil
374
374
  ## Schema reference
375
375
 
376
376
  The schema types — `s.string()`, `s.richtext()`, `s.image()`, `s.record()`,
377
- `s.union()`, `s.keyOf()`, `s.route()`, and the rest — are the same in every Val
377
+ `s.discriminatedUnion()`, `s.keyOf()`, `s.route()`, and the rest — are the same in every Val
378
378
  package and are documented in full at
379
379
  [val.build/docs](https://val.build/docs) and in
380
380
  [`@valbuild/next`'s README](https://github.com/valbuild/val/blob/main/packages/next/README.md#schema-types).
@@ -20,6 +20,10 @@ export declare const initVal: (config?: ValConfig) => InitVal & {
20
20
  *
21
21
  * Not needed for the `suspend` prop on ValProvider, which detects the cookie
22
22
  * client-side; reserve it for advanced server-side conditionals.
23
+ *
24
+ * @example
25
+ * // In a server function, a server route handler, or during SSR:
26
+ * const enabled = await isValEnabled();
23
27
  */
24
28
  isValEnabled: typeof isValEnabled;
25
29
  val: ValConstructor & {
@@ -34,10 +38,22 @@ export declare const initVal: (config?: ValConfig) => InitVal & {
34
38
  *
35
39
  * This method is primarily intended for tooling and other advanced use cases
36
40
  * outside of the actual application.
41
+ *
42
+ * @example
43
+ * import pageVal from "./page.val";
44
+ * const page = val.unstable_getUnpatchedUnencodedVal(pageVal);
37
45
  */
38
46
  unstable_getUnpatchedUnencodedVal: typeof getUnpatchedUnencodedVal;
39
47
  /**
40
48
  * Convert any object that is encoded with Val stega encoding back to the original values
49
+ *
50
+ * Use it wherever an encoded string would break something: a `key`, a
51
+ * comparison, a URL, anything sent to an API.
52
+ *
53
+ * @example
54
+ * import pageVal from "./page.val";
55
+ * const page = useVal(pageVal);
56
+ * const slug = val.raw(page.slug);
41
57
  */
42
58
  raw: typeof raw;
43
59
  /**
@@ -46,12 +62,30 @@ export declare const initVal: (config?: ValConfig) => InitVal & {
46
62
  * This is typically used to manually set the data-val-path attribute for visual editing on any element.
47
63
  *
48
64
  * @example
49
- * const page = useVal(pageVal)
50
- * <a href={page.url.href} {...val.attrs(page)}>
51
- * {page.url.label}
52
- * </a>
65
+ * import pageVal from "./page.val";
66
+ * function PageLink() {
67
+ * const page = useVal(pageVal);
68
+ * return (
69
+ * <a href={page.url.href} {...val.attrs(page)}>
70
+ * {page.url.label}
71
+ * </a>
72
+ * );
73
+ * }
53
74
  */
54
75
  attrs: typeof attrs;
76
+ /**
77
+ * The Val paths encoded into a single stega encoded string, or `undefined`
78
+ * when there are none.
79
+ *
80
+ * `val.attrs` is what an element usually wants; this is the lower-level
81
+ * read, for when you need the paths themselves. Unstable: the shape of a
82
+ * path is not part of the public API yet.
83
+ *
84
+ * @example
85
+ * import pageVal from "./page.val";
86
+ * const page = useVal(pageVal);
87
+ * const paths = val.unstable_decodeValPathsOfString(page.title);
88
+ */
55
89
  unstable_decodeValPathsOfString: typeof decodeValPathsOfString;
56
90
  };
57
91
  /**
@@ -69,6 +103,21 @@ export declare const initVal: (config?: ValConfig) => InitVal & {
69
103
  * });
70
104
  */
71
105
  tanstackRouter: ValRouter;
106
+ /**
107
+ * A router for pages that are NOT in this application: the keys of the record
108
+ * are whole URLs, not route paths of your site.
109
+ *
110
+ * It is what `s.route()` links to when the destination is somewhere else -
111
+ * a campaign site, a docs host, a social profile.
112
+ *
113
+ * @example
114
+ * const links = s.record(s.object({ title: s.string() }));
115
+ * export default c.define(
116
+ * "/content/external.val.ts",
117
+ * links.router(externalPageRouter),
118
+ * { "https://val.build": { title: "Val" } },
119
+ * );
120
+ */
72
121
  externalPageRouter: ValRouter;
73
122
  };
74
123
  export {};
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var version = require('./version-6eeefb70.cjs.dev.js');
5
+ var version = require('./version-1a220586.cjs.dev.js');
6
6
  var createForOfIteratorHelper = require('./createForOfIteratorHelper-e75681d7.cjs.dev.js');
7
7
  var core = require('@valbuild/core');
8
8
  var stega = require('@valbuild/react/stega');
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var version = require('./version-803e9fd4.cjs.prod.js');
5
+ var version = require('./version-1837c67c.cjs.prod.js');
6
6
  var createForOfIteratorHelper = require('./createForOfIteratorHelper-0324e063.cjs.prod.js');
7
7
  var core = require('@valbuild/core');
8
8
  var stega = require('@valbuild/react/stega');
@@ -1,4 +1,4 @@
1
- import { _ as _asyncToGenerator, a as _regenerator, V as VERSION$1 } from './version-9b3ce6c3.esm.js';
1
+ import { _ as _asyncToGenerator, a as _regenerator, V as VERSION$1 } from './version-a7a1374a.esm.js';
2
2
  import { _ as _objectSpread2, a as _slicedToArray, b as _createForOfIteratorHelper } from './createForOfIteratorHelper-485c2ce1.esm.js';
3
3
  import { Internal as Internal$1, initVal as initVal$1, DEFAULT_CONTENT_HOST } from '@valbuild/core';
4
4
  import * as core from '@valbuild/core';
@@ -152,7 +152,7 @@ var packageJson = {
152
152
  "tanstack-router",
153
153
  "react"
154
154
  ],
155
- version: "0.125.0",
155
+ version: "0.126.0",
156
156
  scripts: {
157
157
  typecheck: "tsc --noEmit",
158
158
  test: "jest"
@@ -152,7 +152,7 @@ var packageJson = {
152
152
  "tanstack-router",
153
153
  "react"
154
154
  ],
155
- version: "0.125.0",
155
+ version: "0.126.0",
156
156
  scripts: {
157
157
  typecheck: "tsc --noEmit",
158
158
  test: "jest"
@@ -150,7 +150,7 @@ var packageJson = {
150
150
  "tanstack-router",
151
151
  "react"
152
152
  ],
153
- version: "0.125.0",
153
+ version: "0.126.0",
154
154
  scripts: {
155
155
  typecheck: "tsc --noEmit",
156
156
  test: "jest"
package/package.json CHANGED
@@ -14,7 +14,7 @@
14
14
  "tanstack-router",
15
15
  "react"
16
16
  ],
17
- "version": "0.125.0",
17
+ "version": "0.126.0",
18
18
  "main": "dist/valbuild-tanstack.cjs.js",
19
19
  "module": "dist/valbuild-tanstack.esm.js",
20
20
  "exports": {
@@ -42,13 +42,13 @@
42
42
  "exports": true
43
43
  },
44
44
  "dependencies": {
45
- "@valbuild/core": "0.125.0",
46
- "@valbuild/language-server": "0.125.0",
47
- "@valbuild/mcp": "0.125.0",
48
- "@valbuild/react": "0.125.0",
49
- "@valbuild/server": "0.125.0",
50
- "@valbuild/shared": "0.125.0",
51
- "@valbuild/ui": "0.125.0"
45
+ "@valbuild/core": "0.126.0",
46
+ "@valbuild/language-server": "0.126.0",
47
+ "@valbuild/mcp": "0.126.0",
48
+ "@valbuild/react": "0.126.0",
49
+ "@valbuild/shared": "0.126.0",
50
+ "@valbuild/server": "0.126.0",
51
+ "@valbuild/ui": "0.126.0"
52
52
  },
53
53
  "devDependencies": {
54
54
  "@tanstack/react-router": "^1.170.33",
@@ -5,7 +5,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  var createForOfIteratorHelper = require('../../dist/createForOfIteratorHelper-e75681d7.cjs.dev.js');
6
6
  var core = require('@valbuild/core');
7
7
  var server = require('@valbuild/server');
8
- var version = require('../../dist/version-6eeefb70.cjs.dev.js');
8
+ var version = require('../../dist/version-1a220586.cjs.dev.js');
9
9
  var routeFromVal = require('../../dist/routeFromVal-a9147ceb.cjs.dev.js');
10
10
  var stega = require('@valbuild/react/stega');
11
11
  var internal = require('@valbuild/shared/internal');
@@ -5,7 +5,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  var createForOfIteratorHelper = require('../../dist/createForOfIteratorHelper-0324e063.cjs.prod.js');
6
6
  var core = require('@valbuild/core');
7
7
  var server = require('@valbuild/server');
8
- var version = require('../../dist/version-803e9fd4.cjs.prod.js');
8
+ var version = require('../../dist/version-1837c67c.cjs.prod.js');
9
9
  var routeFromVal = require('../../dist/routeFromVal-6693e037.cjs.prod.js');
10
10
  var stega = require('@valbuild/react/stega');
11
11
  var internal = require('@valbuild/shared/internal');
@@ -1,7 +1,7 @@
1
1
  import { _ as _objectSpread2, a as _slicedToArray, d as _defineProperty } from '../../dist/createForOfIteratorHelper-485c2ce1.esm.js';
2
2
  import { Internal } from '@valbuild/core';
3
3
  import { createValApiRouter, createValServer } from '@valbuild/server';
4
- import { _ as _asyncToGenerator, a as _regenerator, V as VERSION } from '../../dist/version-9b3ce6c3.esm.js';
4
+ import { _ as _asyncToGenerator, a as _regenerator, V as VERSION } from '../../dist/version-a7a1374a.esm.js';
5
5
  import { b as initValRouteFromVal, g as getJsonEntryStegaRoot, i as isJsonValuesRecordSchema, a as getValRouteUrlFromVal, _ as _typeof } from '../../dist/routeFromVal-728295a0.esm.js';
6
6
  import { stegaEncode, SET_AUTO_TAG_JSX_ENABLED } from '@valbuild/react/stega';
7
7
  import { VAL_SESSION_COOKIE } from '@valbuild/shared/internal';