@valbuild/tanstack 0.124.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 (50) hide show
  1. package/LICENSE.md +7 -0
  2. package/README.md +380 -0
  3. package/client/dist/valbuild-tanstack-client.cjs.d.ts +2 -0
  4. package/client/dist/valbuild-tanstack-client.cjs.dev.js +288 -0
  5. package/client/dist/valbuild-tanstack-client.cjs.js +7 -0
  6. package/client/dist/valbuild-tanstack-client.cjs.prod.js +288 -0
  7. package/client/dist/valbuild-tanstack-client.esm.js +280 -0
  8. package/client/package.json +4 -0
  9. package/dist/ValOverlayContext-87cb022d.esm.js +284 -0
  10. package/dist/ValOverlayContext-abd6ab9a.cjs.prod.js +292 -0
  11. package/dist/ValOverlayContext-d3bfacb1.cjs.dev.js +292 -0
  12. package/dist/createForOfIteratorHelper-0324e063.cjs.prod.js +157 -0
  13. package/dist/createForOfIteratorHelper-485c2ce1.esm.js +151 -0
  14. package/dist/createForOfIteratorHelper-e75681d7.cjs.dev.js +157 -0
  15. package/dist/declarations/src/ValApp.d.ts +6 -0
  16. package/dist/declarations/src/ValImage.d.ts +24 -0
  17. package/dist/declarations/src/ValModulesClient.d.ts +34 -0
  18. package/dist/declarations/src/ValProvider.d.ts +6 -0
  19. package/dist/declarations/src/ValTypes.d.ts +4 -0
  20. package/dist/declarations/src/client/index.d.ts +1 -0
  21. package/dist/declarations/src/client/initValClient.d.ts +27 -0
  22. package/dist/declarations/src/decodeValPathsOfString.d.ts +2 -0
  23. package/dist/declarations/src/external_exempt_from_val_quickjs.d.ts +41 -0
  24. package/dist/declarations/src/getUnpatchedUnencodedVal.d.ts +3 -0
  25. package/dist/declarations/src/index.d.ts +2 -0
  26. package/dist/declarations/src/initVal.d.ts +74 -0
  27. package/dist/declarations/src/server/index.d.ts +5 -0
  28. package/dist/declarations/src/server/initValContent.d.ts +122 -0
  29. package/dist/declarations/src/server/initValMcp.d.ts +27 -0
  30. package/dist/declarations/src/server/initValServer.d.ts +41 -0
  31. package/dist/declarations/src/server/valDraftMode.d.ts +49 -0
  32. package/dist/declarations/src/version.d.ts +1 -0
  33. package/dist/routeFromVal-6693e037.cjs.prod.js +218 -0
  34. package/dist/routeFromVal-728295a0.esm.js +212 -0
  35. package/dist/routeFromVal-a9147ceb.cjs.dev.js +218 -0
  36. package/dist/valbuild-tanstack.cjs.d.ts +2 -0
  37. package/dist/valbuild-tanstack.cjs.dev.js +2005 -0
  38. package/dist/valbuild-tanstack.cjs.js +7 -0
  39. package/dist/valbuild-tanstack.cjs.prod.js +2005 -0
  40. package/dist/valbuild-tanstack.esm.js +1950 -0
  41. package/dist/version-1a88fd21.cjs.dev.js +229 -0
  42. package/dist/version-5ac70ccf.cjs.prod.js +229 -0
  43. package/dist/version-ac8df696.esm.js +225 -0
  44. package/package.json +84 -0
  45. package/server/dist/valbuild-tanstack-server.cjs.d.ts +2 -0
  46. package/server/dist/valbuild-tanstack-server.cjs.dev.js +1032 -0
  47. package/server/dist/valbuild-tanstack-server.cjs.js +7 -0
  48. package/server/dist/valbuild-tanstack-server.cjs.prod.js +1032 -0
  49. package/server/dist/valbuild-tanstack-server.esm.js +1005 -0
  50. package/server/package.json +4 -0
@@ -0,0 +1,1005 @@
1
+ import { _ as _objectSpread2, a as _slicedToArray, d as _defineProperty } from '../../dist/createForOfIteratorHelper-485c2ce1.esm.js';
2
+ import { Internal } from '@valbuild/core';
3
+ import { createValApiRouter, createValServer } from '@valbuild/server';
4
+ import { _ as _asyncToGenerator, a as _regenerator, V as VERSION } from '../../dist/version-ac8df696.esm.js';
5
+ import { b as initValRouteFromVal, g as getJsonEntryStegaRoot, i as isJsonValuesRecordSchema, a as getValRouteUrlFromVal, _ as _typeof } from '../../dist/routeFromVal-728295a0.esm.js';
6
+ import { stegaEncode, SET_AUTO_TAG_JSX_ENABLED } from '@valbuild/react/stega';
7
+ import { VAL_SESSION_COOKIE } from '@valbuild/shared/internal';
8
+ import { initValMcp as initValMcp$1 } from '@valbuild/mcp';
9
+ import '@valbuild/shared/client';
10
+
11
+ /**
12
+ * The cookie that says a request is previewing unpublished content.
13
+ *
14
+ * Next has `draftMode()` for this; TanStack Start has no such notion, so Val
15
+ * brings its own. Deliberately NOT the thing that grants access: every draft
16
+ * read also carries the Val session cookie, which is a signed JWT the server
17
+ * verifies, and a request with this cookie and no session gets published
18
+ * content and a 401 in the log. So this is a mode switch, not a credential —
19
+ * which is why an ordinary cookie is enough.
20
+ */
21
+ var VAL_DRAFT_MODE_COOKIE = "val_draft_mode";
22
+ var ENABLED = "1";
23
+
24
+ /**
25
+ * Reading and writing the draft-mode flag for the current request.
26
+ *
27
+ * Handed to `createValServer` as its callbacks, and exported so an app can ask
28
+ * the same question its loaders ask.
29
+ */
30
+
31
+ /**
32
+ * The draft-mode flag, read from and written to the current request.
33
+ *
34
+ * TanStack's request helpers resolve the current request out of async local
35
+ * storage, so this only works where there IS one: a server route handler, a
36
+ * server function, or an SSR render. Everywhere else — a client navigation, a
37
+ * build-time render — it answers "off", which is the right answer: there is no
38
+ * session to authorize a draft read either.
39
+ *
40
+ * The import is dynamic for the same reason it is in `isValEnabled`: this
41
+ * module is reachable from the package's server entry, and pulling TanStack's
42
+ * server half in eagerly would put it in front of anything that merely
43
+ * type-imports from here.
44
+ */
45
+ function valDraftMode() {
46
+ return {
47
+ isEnabled: function isEnabled() {
48
+ return _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee() {
49
+ var _yield$import, getCookie;
50
+ return _regenerator().w(function (_context) {
51
+ while (1) switch (_context.p = _context.n) {
52
+ case 0:
53
+ _context.p = 0;
54
+ _context.n = 1;
55
+ return import('@tanstack/react-start/server');
56
+ case 1:
57
+ _yield$import = _context.v;
58
+ getCookie = _yield$import.getCookie;
59
+ return _context.a(2, getCookie(VAL_DRAFT_MODE_COOKIE) === ENABLED);
60
+ case 2:
61
+ _context.p = 2;
62
+ _context.v;
63
+ return _context.a(2, false);
64
+ }
65
+ }, _callee, null, [[0, 2]]);
66
+ }))();
67
+ },
68
+ enable: function enable() {
69
+ return _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2() {
70
+ var _yield$import2, setCookie, getRequest;
71
+ return _regenerator().w(function (_context2) {
72
+ while (1) switch (_context2.n) {
73
+ case 0:
74
+ _context2.n = 1;
75
+ return import('@tanstack/react-start/server');
76
+ case 1:
77
+ _yield$import2 = _context2.v;
78
+ setCookie = _yield$import2.setCookie;
79
+ getRequest = _yield$import2.getRequest;
80
+ setCookie(VAL_DRAFT_MODE_COOKIE, ENABLED, {
81
+ httpOnly: true,
82
+ sameSite: "lax",
83
+ path: "/",
84
+ // Not `secure` unconditionally: the Studio is used over http on
85
+ // localhost, and a Secure cookie is silently dropped there — which
86
+ // looks exactly like draft mode refusing to turn on.
87
+ secure: isSecureRequest(getRequest)
88
+ });
89
+ case 2:
90
+ return _context2.a(2);
91
+ }
92
+ }, _callee2);
93
+ }))();
94
+ },
95
+ disable: function disable() {
96
+ return _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3() {
97
+ var _yield$import3, deleteCookie;
98
+ return _regenerator().w(function (_context3) {
99
+ while (1) switch (_context3.n) {
100
+ case 0:
101
+ _context3.n = 1;
102
+ return import('@tanstack/react-start/server');
103
+ case 1:
104
+ _yield$import3 = _context3.v;
105
+ deleteCookie = _yield$import3.deleteCookie;
106
+ deleteCookie(VAL_DRAFT_MODE_COOKIE, {
107
+ path: "/"
108
+ });
109
+ case 2:
110
+ return _context3.a(2);
111
+ }
112
+ }, _callee3);
113
+ }))();
114
+ }
115
+ };
116
+ }
117
+ function isSecureRequest(getRequest) {
118
+ try {
119
+ return new URL(getRequest().url).protocol === "https:";
120
+ } catch (_unused2) {
121
+ return false;
122
+ }
123
+ }
124
+
125
+ /**
126
+ * The Val Enable cookie, as seen by the current request.
127
+ *
128
+ * Separate from draft mode: enabling Val is what makes the Studio overlay mount
129
+ * at all, and draft mode is what makes the content it shows be the unpublished
130
+ * one. The Studio turns the first on for the browser and the second on per
131
+ * preview.
132
+ */
133
+ function hasValEnableCookieOnServer() {
134
+ return _hasValEnableCookieOnServer.apply(this, arguments);
135
+ }
136
+ function _hasValEnableCookieOnServer() {
137
+ _hasValEnableCookieOnServer = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4() {
138
+ var _yield$import4, getCookie;
139
+ return _regenerator().w(function (_context4) {
140
+ while (1) switch (_context4.p = _context4.n) {
141
+ case 0:
142
+ _context4.p = 0;
143
+ _context4.n = 1;
144
+ return import('@tanstack/react-start/server');
145
+ case 1:
146
+ _yield$import4 = _context4.v;
147
+ getCookie = _yield$import4.getCookie;
148
+ return _context4.a(2, getCookie(Internal.VAL_ENABLE_COOKIE_NAME) === "true");
149
+ case 2:
150
+ _context4.p = 2;
151
+ _context4.v;
152
+ return _context4.a(2, false);
153
+ }
154
+ }, _callee4, null, [[0, 2]]);
155
+ }));
156
+ return _hasValEnableCookieOnServer.apply(this, arguments);
157
+ }
158
+
159
+ /**
160
+ * The Val API, as a handler you can mount on a TanStack Start server route.
161
+ *
162
+ * `createValApiRouter` already speaks the platform's own vocabulary — it takes
163
+ * a `Request` and hands back a `ValServerGenericResult` — so all this adds is
164
+ * the conversion to a `Response`, which for Next needed `NextResponse` and here
165
+ * does not need anything.
166
+ */
167
+ var initValApiHandler = function initValApiHandler(valModules, config, draftMode, formatter) {
168
+ var route = "/api/val"; // TODO: get from config
169
+ var coreVersion = Internal.VERSION.core;
170
+ if (!coreVersion) {
171
+ throw new Error("Could not get @valbuild/core package version");
172
+ }
173
+ var tanstackVersion = VERSION;
174
+ if (!tanstackVersion) {
175
+ throw new Error("Could not get @valbuild/tanstack package version");
176
+ }
177
+ return createValApiRouter(route, createValServer(valModules, route, _objectSpread2({
178
+ versions: {
179
+ /*
180
+ * Reported as `next` because that is the field the wire contract has.
181
+ *
182
+ * `Versions` in `@valbuild/server` names the framework half of the
183
+ * pair `next`, and admin.val.build reads it. Renaming it is a change
184
+ * to a published contract with a server on the other end, so the
185
+ * TanStack package fills the same field rather than adding one
186
+ * nothing reads.
187
+ */
188
+ next: tanstackVersion,
189
+ core: coreVersion
190
+ }
191
+ }, config), config, {
192
+ isEnabled: function isEnabled() {
193
+ return draftMode.isEnabled();
194
+ },
195
+ onEnable: function onEnable() {
196
+ return draftMode.enable();
197
+ },
198
+ onDisable: function onDisable() {
199
+ return draftMode.disable();
200
+ }
201
+ }, formatter), function (valRes) {
202
+ var headers = new Headers();
203
+ var valResHeaders = "headers" in valRes && valRes.headers || {};
204
+ for (var key in valResHeaders) {
205
+ var value = valResHeaders[key];
206
+ if (typeof value === "string") {
207
+ headers.set(key, value);
208
+ }
209
+ }
210
+ if ("cookies" in valRes && valRes.cookies) {
211
+ for (var _i = 0, _Object$entries = Object.entries(valRes.cookies); _i < _Object$entries.length; _i++) {
212
+ var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
213
+ cookieName = _Object$entries$_i[0],
214
+ cookie = _Object$entries$_i[1];
215
+ headers.append("Set-Cookie", serializeCookie(cookieName, cookie));
216
+ }
217
+ }
218
+ if ("json" in valRes) {
219
+ headers.set("Content-Type", "application/json");
220
+ return new Response(JSON.stringify(valRes.json), {
221
+ headers: headers,
222
+ status: valRes.status
223
+ });
224
+ }
225
+ if (valRes.status === 302) {
226
+ headers.set("Location", valRes.redirectTo);
227
+ /*
228
+ * Built by hand rather than with `Response.redirect`.
229
+ *
230
+ * `Response.redirect` produces an immutable response whose headers
231
+ * cannot be added to, and the redirect that enables Val is precisely
232
+ * the one that has to set cookies on its way out.
233
+ */
234
+ return new Response(null, {
235
+ status: valRes.status,
236
+ headers: headers
237
+ });
238
+ }
239
+ return new Response("body" in valRes ? valRes.body : null, {
240
+ headers: headers,
241
+ status: valRes.status
242
+ });
243
+ });
244
+ };
245
+
246
+ /**
247
+ * One `Set-Cookie` header value.
248
+ *
249
+ * `value` is nullable because clearing a cookie is expressed as a null value
250
+ * rather than a separate op — which is also why a falsy value gets `Max-Age=0`
251
+ * below when no explicit expiry was given.
252
+ */
253
+
254
+ function serializeCookie(name, cookie) {
255
+ var _options$path;
256
+ var options = cookie.options;
257
+ /*
258
+ * `Path=/` unless told otherwise — the default is not "the whole site".
259
+ *
260
+ * A `Set-Cookie` with no `Path` defaults to the DIRECTORY of the request
261
+ * that set it, and every cookie Val sets is set by a response from
262
+ * `/api/val/...`. So `val_enable` — which the page reads from
263
+ * `document.cookie` to decide whether to mount the Studio overlay — was
264
+ * scoped to `/api/val` and invisible on the site itself: enabling Val
265
+ * appeared to do nothing at all. Next's `NextResponse` normalises this for
266
+ * the Next package; a plain `Response` does not.
267
+ */
268
+ var path = (_options$path = options === null || options === void 0 ? void 0 : options.path) !== null && _options$path !== void 0 ? _options$path : "/";
269
+ return "".concat(name, "=").concat(encodeURIComponent(cookie.value || "")) + "".concat(options !== null && options !== void 0 && options.httpOnly ? "; HttpOnly" : "") + "".concat(options !== null && options !== void 0 && options.secure ? "; Secure" : "") + "".concat(options !== null && options !== void 0 && options.sameSite ? "; SameSite=".concat(options.sameSite) : "") + "; Path=".concat(path) + "".concat(options !== null && options !== void 0 && options.expires ? "; Expires=".concat(options.expires.toISOString()) : "".concat(!cookie.value ? "; Max-Age=0" : ""));
270
+ }
271
+ function initValServer(valModules, config, opts) {
272
+ var _opts$draftMode;
273
+ var draftMode = (_opts$draftMode = opts === null || opts === void 0 ? void 0 : opts.draftMode) !== null && _opts$draftMode !== void 0 ? _opts$draftMode : valDraftMode();
274
+ return {
275
+ valApiHandler: initValApiHandler(valModules, config, draftMode, opts === null || opts === void 0 ? void 0 : opts.formatter),
276
+ draftMode: draftMode
277
+ };
278
+ }
279
+
280
+ /*
281
+ * NOTE: no `SET_RSC(true)` here, unlike the Next package.
282
+ *
283
+ * That flag marks elements as having been rendered by a React Server Component
284
+ * — a tree the browser cannot re-render, only re-request. A TanStack Start page
285
+ * is server-RENDERED and then hydrated, so every element it produces is a
286
+ * normal client element and the distinction does not exist.
287
+ */
288
+ var initFetchValStega = function initFetchValStega(config, valApiEndpoints, valServerPromise, isEnabled, getHeaders, getCookies) {
289
+ return function (selector) {
290
+ var exec = /*#__PURE__*/function () {
291
+ var _ref = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee() {
292
+ var enabled, headers, cookies, host, _cookies, valServer, treeRes, modules, _t, _t2, _t3;
293
+ return _regenerator().w(function (_context) {
294
+ while (1) switch (_context.p = _context.n) {
295
+ case 0:
296
+ enabled = false;
297
+ _context.p = 1;
298
+ _context.n = 2;
299
+ return isEnabled();
300
+ case 2:
301
+ enabled = _context.v;
302
+ _context.n = 4;
303
+ break;
304
+ case 3:
305
+ _context.p = 3;
306
+ _t = _context.v;
307
+ console.error("Val: could not check if Val is enabled! This might be due to an error reading draft mode. fetchVal can only be used server-side (in a loader, a server function, or a server route). Use useVal in components.", _t);
308
+ case 4:
309
+ if (!enabled) {
310
+ _context.n = 17;
311
+ break;
312
+ }
313
+ SET_AUTO_TAG_JSX_ENABLED(true);
314
+ _context.p = 5;
315
+ _context.n = 6;
316
+ return getHeaders();
317
+ case 6:
318
+ headers = _context.v;
319
+ if (!(typeof headers.get !== "function")) {
320
+ _context.n = 7;
321
+ break;
322
+ }
323
+ throw new Error("Invalid headers");
324
+ case 7:
325
+ _context.n = 9;
326
+ break;
327
+ case 8:
328
+ _context.p = 8;
329
+ _t2 = _context.v;
330
+ console.error("Val: could not read headers! fetchVal can only be used server-side (in a loader, a server function, or a server route). Use useVal in components.", _t2);
331
+ headers = null;
332
+ case 9:
333
+ _context.p = 9;
334
+ _context.n = 10;
335
+ return getCookies();
336
+ case 10:
337
+ cookies = _context.v;
338
+ _context.n = 12;
339
+ break;
340
+ case 11:
341
+ _context.p = 11;
342
+ _t3 = _context.v;
343
+ console.error("Val: could not read cookies! fetchVal can only be used server-side (in a loader, a server function, or a server route). Use useVal in components.", _t3);
344
+ cookies = null;
345
+ case 12:
346
+ host = headers && getHost(headers);
347
+ if (!(host && cookies)) {
348
+ _context.n = 17;
349
+ break;
350
+ }
351
+ _context.n = 13;
352
+ return valServerPromise;
353
+ case 13:
354
+ valServer = _context.v;
355
+ _context.n = 14;
356
+ return valServer["/sources/~"]["PUT"]({
357
+ path: "/",
358
+ query: {
359
+ validate_sources: true,
360
+ validate_binary_files: false,
361
+ exclude_patches: false,
362
+ // The server-side read uses the legacy "server applies patches"
363
+ // path, same as the Next package's.
364
+ apply_patches: undefined,
365
+ /*
366
+ * The caller's own staged work, and nobody else's.
367
+ *
368
+ * A draft render cannot name its group ids — it has no client
369
+ * state — so it asks for "mine" and the server resolves them from
370
+ * the session. Without this a preview shows base + every pending
371
+ * patch on the branch, so one person's half-finished edit appears
372
+ * in another person's draft.
373
+ *
374
+ * `patch_id` stays `undefined`: naming an explicit list is for a
375
+ * caller that already knows what it wants, and it would override
376
+ * the resolution rather than intersect with it.
377
+ */
378
+ patch_id: undefined,
379
+ own_patch_groups_only: true
380
+ },
381
+ cookies: _defineProperty({}, VAL_SESSION_COOKIE, (_cookies = cookies) === null || _cookies === void 0 || (_cookies = _cookies.get(VAL_SESSION_COOKIE)) === null || _cookies === void 0 ? void 0 : _cookies.value)
382
+ });
383
+ case 14:
384
+ treeRes = _context.v;
385
+ if (!(treeRes.status === 200)) {
386
+ _context.n = 15;
387
+ break;
388
+ }
389
+ modules = treeRes.json.modules;
390
+ return _context.a(2, stegaEncode(selector, {
391
+ disabled: !enabled,
392
+ getModule: function getModule(path) {
393
+ var module = modules[path];
394
+ if (module) {
395
+ return module.source;
396
+ }
397
+ }
398
+ }));
399
+ case 15:
400
+ if (!(treeRes.status === 401)) {
401
+ _context.n = 16;
402
+ break;
403
+ }
404
+ console.warn("Val: authentication error: ", treeRes.json.message);
405
+ _context.n = 17;
406
+ break;
407
+ case 16:
408
+ throw Error(JSON.stringify(treeRes.json, null, 2));
409
+ case 17:
410
+ return _context.a(2, stegaEncode(selector, {
411
+ disabled: !enabled
412
+ }));
413
+ }
414
+ }, _callee, null, [[9, 11], [5, 8], [1, 3]]);
415
+ }));
416
+ return function exec() {
417
+ return _ref.apply(this, arguments);
418
+ };
419
+ }();
420
+ return exec()["catch"](function (err) {
421
+ console.error("Val: failed to fetch ", err);
422
+ return stegaEncode(selector, {});
423
+ });
424
+ };
425
+ };
426
+ function getHost(headers) {
427
+ var _headers$get;
428
+ var host = headers === null || headers === void 0 ? void 0 : headers.get("host");
429
+ var proto = "https";
430
+ if ((headers === null || headers === void 0 ? void 0 : headers.get("x-forwarded-proto")) === "http") {
431
+ proto = "http";
432
+ } else if (headers !== null && headers !== void 0 && (_headers$get = headers.get("referer")) !== null && _headers$get !== void 0 && _headers$get.startsWith("http://")) {
433
+ proto = "http";
434
+ } else if (host !== null && host !== void 0 && host.startsWith("localhost")) {
435
+ proto = "http";
436
+ }
437
+ if (host && proto) {
438
+ return "".concat(proto, "://").concat(host);
439
+ }
440
+ return null;
441
+ }
442
+
443
+ // TODO: remove
444
+ // function getValAuthHeaders(cookies: {
445
+ // get(name: string): { name: string; value: string } | undefined;
446
+ // }): Record<string, string> {
447
+ // try {
448
+ // const session = cookies.get(Internal.VAL_SESSION_COOKIE);
449
+ // if (session) {
450
+ // return {
451
+ // Cookie: `${Internal.VAL_SESSION_COOKIE}=${encodeURIComponent(
452
+ // session.value
453
+ // )}`,
454
+ // };
455
+ // }
456
+ // return {};
457
+ // } catch (err) {
458
+ // console.error(
459
+ // "Val: could not read cookies! fetchVal can only be used server-side (in a loader, a server function, or a server route). Use useVal in components.",
460
+ // err
461
+ // );
462
+ // return {};
463
+ // }
464
+ // }
465
+
466
+ var initFetchValRouteStega = function initFetchValRouteStega(config, valApiEndpoints, valServerPromise, isEnabled, getHeaders, getCookies) {
467
+ return /*#__PURE__*/function () {
468
+ var _ref2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2(selector, params) {
469
+ var resolvedParams, path, schema, source, url, enabled, draft, content, fetchVal, val, route, _t5;
470
+ return _regenerator().w(function (_context2) {
471
+ while (1) switch (_context2.p = _context2.n) {
472
+ case 0:
473
+ _context2.n = 1;
474
+ return Promise.resolve(params);
475
+ case 1:
476
+ resolvedParams = _context2.v;
477
+ path = selector && Internal.getValPath(selector);
478
+ schema = selector && Internal.getSchema(selector); // `.jsonValues()` router: map params → the entry key and load ONLY that
479
+ // entry's backing `*.val.json`, instead of eagerly resolving the whole
480
+ // record via `fetchVal`.
481
+ if (!isJsonValuesRecordSchema(schema)) {
482
+ _context2.n = 11;
483
+ break;
484
+ }
485
+ source = selector && Internal.getSource(selector);
486
+ url = getValRouteUrlFromVal(resolvedParams, "fetchValRoute", path, schema, source);
487
+ if (url) {
488
+ _context2.n = 2;
489
+ break;
490
+ }
491
+ return _context2.a(2, null);
492
+ case 2:
493
+ enabled = false;
494
+ _context2.p = 3;
495
+ _context2.n = 4;
496
+ return isEnabled();
497
+ case 4:
498
+ enabled = _context2.v;
499
+ _context2.n = 6;
500
+ break;
501
+ case 5:
502
+ _context2.p = 5;
503
+ _context2.v;
504
+ case 6:
505
+ draft = {
506
+ status: "unavailable"
507
+ };
508
+ if (!(enabled && path)) {
509
+ _context2.n = 8;
510
+ break;
511
+ }
512
+ SET_AUTO_TAG_JSX_ENABLED(true);
513
+ _context2.n = 7;
514
+ return loadDraftJsonEntry(valServerPromise, getCookies, path, url);
515
+ case 7:
516
+ draft = _context2.v;
517
+ case 8:
518
+ _context2.n = 9;
519
+ return resolveDraftOrCommittedEntry(draft, function () {
520
+ return loadJsonEntryContent(source, url);
521
+ });
522
+ case 9:
523
+ content = _context2.v;
524
+ if (!(content === undefined)) {
525
+ _context2.n = 10;
526
+ break;
527
+ }
528
+ return _context2.a(2, null);
529
+ case 10:
530
+ return _context2.a(2, stegaEncode(content, {
531
+ disabled: !enabled,
532
+ root: getJsonEntryStegaRoot(selector, url)
533
+ }));
534
+ case 11:
535
+ fetchVal = initFetchValStega(config, valApiEndpoints, valServerPromise, isEnabled, getHeaders, getCookies);
536
+ _t5 = selector;
537
+ if (!_t5) {
538
+ _context2.n = 13;
539
+ break;
540
+ }
541
+ _context2.n = 12;
542
+ return fetchVal(selector);
543
+ case 12:
544
+ _t5 = _context2.v;
545
+ case 13:
546
+ val = _t5;
547
+ route = initValRouteFromVal(resolvedParams, "fetchValRoute", path, schema, val);
548
+ return _context2.a(2, route);
549
+ }
550
+ }, _callee2, null, [[3, 5]]);
551
+ }));
552
+ return function (_x, _x2) {
553
+ return _ref2.apply(this, arguments);
554
+ };
555
+ }();
556
+ };
557
+
558
+ /**
559
+ * Resolves a single `.jsonValues()` entry's content by key from a module's local
560
+ * source markers (one dynamic import). Returns `undefined` when the key is
561
+ * missing or its marker has no runtime thunk (transport marker / draft entry).
562
+ */
563
+ function loadJsonEntryContent(_x3, _x4) {
564
+ return _loadJsonEntryContent.apply(this, arguments);
565
+ }
566
+ /**
567
+ * Loads a single `.jsonValues()` entry's DRAFT content via the in-process
568
+ * `/json` endpoint (which replays pending patches). Returns `undefined` when the
569
+ * entry has no draft content to serve — the caller then falls back to the
570
+ * locally-bundled committed content.
571
+ */
572
+ /**
573
+ * What the draft state says about an entry.
574
+ *
575
+ * The three cases have to stay distinct: `absent` is an ANSWER — the entry is not
576
+ * there in the draft state, e.g. a pending patch removed it — while `unavailable`
577
+ * means we could not ask. Collapsing them into `undefined` is what made a
578
+ * draft-deleted entry keep rendering its committed content: the caller could not
579
+ * tell "it is gone" from "ask the committed source instead".
580
+ */
581
+ /**
582
+ * The slice of `ValServer` the single-entry readers actually use. Narrower than
583
+ * `ValServer` on purpose: it says what the dependency IS, and it lets a test
584
+ * drive these readers with a one-route fake instead of casting a partial object
585
+ * to the whole server type.
586
+ */
587
+ function _loadJsonEntryContent() {
588
+ _loadJsonEntryContent = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee5(source, key) {
589
+ var marker, thunk;
590
+ return _regenerator().w(function (_context5) {
591
+ while (1) switch (_context5.n) {
592
+ case 0:
593
+ if (!(!source || _typeof(source) !== "object")) {
594
+ _context5.n = 1;
595
+ break;
596
+ }
597
+ return _context5.a(2, undefined);
598
+ case 1:
599
+ marker = source[key];
600
+ if (Internal.isJson(marker)) {
601
+ _context5.n = 2;
602
+ break;
603
+ }
604
+ return _context5.a(2, undefined);
605
+ case 2:
606
+ thunk = Internal.getJsonImport(marker);
607
+ if (thunk) {
608
+ _context5.n = 3;
609
+ break;
610
+ }
611
+ return _context5.a(2, undefined);
612
+ case 3:
613
+ _context5.n = 4;
614
+ return thunk();
615
+ case 4:
616
+ return _context5.a(2, _context5.v["default"]);
617
+ }
618
+ }, _callee5);
619
+ }));
620
+ return _loadJsonEntryContent.apply(this, arguments);
621
+ }
622
+ /**
623
+ * Picks the content a draft-aware single-entry read should render.
624
+ *
625
+ * The rule the two callers share: the draft state WINS when it has an answer —
626
+ * including the answer "this entry is gone" — and the committed content is used
627
+ * only when there is no draft answer to be had (Val disabled, or we could not
628
+ * ask). Returning `undefined` means "render nothing"; both callers turn that into
629
+ * a null/undefined result.
630
+ */
631
+ function resolveDraftOrCommittedEntry(_x5, _x6) {
632
+ return _resolveDraftOrCommittedEntry.apply(this, arguments);
633
+ }
634
+ function _resolveDraftOrCommittedEntry() {
635
+ _resolveDraftOrCommittedEntry = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee6(draft, loadCommitted) {
636
+ return _regenerator().w(function (_context6) {
637
+ while (1) switch (_context6.n) {
638
+ case 0:
639
+ if (!(draft.status === "content")) {
640
+ _context6.n = 1;
641
+ break;
642
+ }
643
+ return _context6.a(2, draft.content);
644
+ case 1:
645
+ if (!(draft.status === "absent")) {
646
+ _context6.n = 2;
647
+ break;
648
+ }
649
+ return _context6.a(2, undefined);
650
+ case 2:
651
+ return _context6.a(2, loadCommitted());
652
+ }
653
+ }, _callee6);
654
+ }));
655
+ return _resolveDraftOrCommittedEntry.apply(this, arguments);
656
+ }
657
+ function loadDraftJsonEntry(_x7, _x8, _x9, _x0) {
658
+ return _loadDraftJsonEntry.apply(this, arguments);
659
+ } // The (loosened) content type a single `.jsonValues()` entry resolves to.
660
+ function _loadDraftJsonEntry() {
661
+ _loadDraftJsonEntry = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee7(valServerPromise, getCookies, moduleFilePath, key) {
662
+ var _cookies3;
663
+ var cookies, valServer, res;
664
+ return _regenerator().w(function (_context7) {
665
+ while (1) switch (_context7.p = _context7.n) {
666
+ case 0:
667
+ _context7.p = 0;
668
+ _context7.n = 1;
669
+ return getCookies();
670
+ case 1:
671
+ cookies = _context7.v;
672
+ _context7.n = 3;
673
+ break;
674
+ case 2:
675
+ _context7.p = 2;
676
+ _context7.v;
677
+ return _context7.a(2, {
678
+ status: "unavailable"
679
+ });
680
+ case 3:
681
+ _context7.n = 4;
682
+ return valServerPromise;
683
+ case 4:
684
+ valServer = _context7.v;
685
+ _context7.n = 5;
686
+ return valServer["/json"]["GET"]({
687
+ query: {
688
+ path: moduleFilePath,
689
+ key: key,
690
+ keys: undefined,
691
+ // single-entry shape
692
+ offset: undefined,
693
+ limit: undefined,
694
+ apply_patches: true,
695
+ /*
696
+ * Scoped the same way the module content beside it is.
697
+ *
698
+ * A draft page renders both, and this call was unscoped — so one page
699
+ * showed base + the caller's group for its modules and base + EVERY
700
+ * pending patch on the branch for any `jsonValues` entry, including other
701
+ * authors' half-finished edits. See the same flag on `/sources/~` above.
702
+ */
703
+ own_patch_groups_only: true
704
+ },
705
+ cookies: _defineProperty({}, VAL_SESSION_COOKIE, (_cookies3 = cookies) === null || _cookies3 === void 0 || (_cookies3 = _cookies3.get(VAL_SESSION_COOKIE)) === null || _cookies3 === void 0 ? void 0 : _cookies3.value)
706
+ });
707
+ case 5:
708
+ res = _context7.v;
709
+ if (!(res.status === 200 && "content" in res.json)) {
710
+ _context7.n = 6;
711
+ break;
712
+ }
713
+ return _context7.a(2, {
714
+ status: "content",
715
+ content: res.json.content
716
+ });
717
+ case 6:
718
+ if (!(res.status === 401)) {
719
+ _context7.n = 7;
720
+ break;
721
+ }
722
+ console.warn("Val: authentication error: ", res.json.message);
723
+ return _context7.a(2, {
724
+ status: "unavailable"
725
+ });
726
+ case 7:
727
+ if (!(res.status === 404)) {
728
+ _context7.n = 8;
729
+ break;
730
+ }
731
+ return _context7.a(2, {
732
+ status: "absent"
733
+ });
734
+ case 8:
735
+ console.error("Val: could not load draft JSON entry: ", "message" in res.json ? res.json.message : "status ".concat(res.status));
736
+ return _context7.a(2, {
737
+ status: "unavailable"
738
+ });
739
+ }
740
+ }, _callee7, null, [[0, 2]]);
741
+ }));
742
+ return _loadDraftJsonEntry.apply(this, arguments);
743
+ }
744
+ /**
745
+ * Resolves ONE `.jsonValues()` entry by key, loading only that entry instead of
746
+ * the whole record — the runtime-scaling counterpart to the eager `fetchVal`.
747
+ *
748
+ * Production (Val disabled): resolves the entry's lazy import thunk from the
749
+ * locally-bundled module. One dynamic import, no server round-trip.
750
+ *
751
+ * Enabled (draft mode): reads the entry through `/json`, which replays pending
752
+ * patches, so uncommitted Studio edits show up. Falls back to the local thunk if
753
+ * the draft read yields nothing.
754
+ */
755
+ var initFetchValKeyStega = function initFetchValKeyStega(valServerPromise, isEnabled, getCookies) {
756
+ return /*#__PURE__*/function () {
757
+ var _ref3 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3(selector, key) {
758
+ var enabled, source, moduleFilePath, draft, content;
759
+ return _regenerator().w(function (_context3) {
760
+ while (1) switch (_context3.p = _context3.n) {
761
+ case 0:
762
+ enabled = false;
763
+ _context3.p = 1;
764
+ _context3.n = 2;
765
+ return isEnabled();
766
+ case 2:
767
+ enabled = _context3.v;
768
+ _context3.n = 4;
769
+ break;
770
+ case 3:
771
+ _context3.p = 3;
772
+ _context3.v;
773
+ case 4:
774
+ source = selector && Internal.getSource(selector);
775
+ moduleFilePath = selector && Internal.getValPath(selector);
776
+ draft = {
777
+ status: "unavailable"
778
+ };
779
+ if (!(enabled && moduleFilePath)) {
780
+ _context3.n = 6;
781
+ break;
782
+ }
783
+ SET_AUTO_TAG_JSX_ENABLED(true);
784
+ _context3.n = 5;
785
+ return loadDraftJsonEntry(valServerPromise, getCookies, moduleFilePath, key);
786
+ case 5:
787
+ draft = _context3.v;
788
+ case 6:
789
+ _context3.n = 7;
790
+ return resolveDraftOrCommittedEntry(draft, function () {
791
+ return loadJsonEntryContent(source, key);
792
+ });
793
+ case 7:
794
+ content = _context3.v;
795
+ if (!(content === undefined)) {
796
+ _context3.n = 8;
797
+ break;
798
+ }
799
+ return _context3.a(2, undefined);
800
+ case 8:
801
+ return _context3.a(2, stegaEncode(content, {
802
+ disabled: !enabled,
803
+ root: getJsonEntryStegaRoot(selector, key)
804
+ }));
805
+ }
806
+ }, _callee3, null, [[1, 3]]);
807
+ }));
808
+ return function (_x1, _x10) {
809
+ return _ref3.apply(this, arguments);
810
+ };
811
+ }();
812
+ };
813
+ var initFetchValRouteUrl = function initFetchValRouteUrl(config, valApiEndpoints, valServerPromise, isEnabled, getHeaders, getCookies) {
814
+ return /*#__PURE__*/function () {
815
+ var _ref4 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4(selector, params) {
816
+ var fetchVal, resolvedParams, path, schema, val, route, _t7, _t8;
817
+ return _regenerator().w(function (_context4) {
818
+ while (1) switch (_context4.n) {
819
+ case 0:
820
+ fetchVal = initFetchValStega(config, valApiEndpoints, valServerPromise, isEnabled, getHeaders, getCookies);
821
+ if (!(params === undefined)) {
822
+ _context4.n = 1;
823
+ break;
824
+ }
825
+ _t7 = undefined;
826
+ _context4.n = 3;
827
+ break;
828
+ case 1:
829
+ _context4.n = 2;
830
+ return Promise.resolve(params);
831
+ case 2:
832
+ _t7 = _context4.v;
833
+ case 3:
834
+ resolvedParams = _t7;
835
+ path = selector && Internal.getValPath(selector);
836
+ schema = selector && Internal.getSchema(selector);
837
+ _t8 = selector;
838
+ if (!_t8) {
839
+ _context4.n = 5;
840
+ break;
841
+ }
842
+ _context4.n = 4;
843
+ return fetchVal(selector);
844
+ case 4:
845
+ _t8 = _context4.v;
846
+ case 5:
847
+ val = _t8;
848
+ route = getValRouteUrlFromVal(resolvedParams, "fetchValRouteUrl", path, schema, val);
849
+ return _context4.a(2, route);
850
+ }
851
+ }, _callee4);
852
+ }));
853
+ return function (_x11, _x12) {
854
+ return _ref4.apply(this, arguments);
855
+ };
856
+ }();
857
+ };
858
+ var valApiEndpoints = "/api/val";
859
+
860
+ /**
861
+ * The request's headers, as the readers above want them.
862
+ *
863
+ * TanStack resolves the current request out of async local storage, so there
864
+ * is nothing to pass in — and nothing to read outside a request, which is what
865
+ * the throw is: the callers catch it and fall back to published content.
866
+ */
867
+ function requestHeaders() {
868
+ return _requestHeaders.apply(this, arguments);
869
+ }
870
+ /** The request's cookies, in the `{ name, value }` shape the readers want. */
871
+ function _requestHeaders() {
872
+ _requestHeaders = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee8() {
873
+ var _yield$import, getRequestHeaders, headers;
874
+ return _regenerator().w(function (_context8) {
875
+ while (1) switch (_context8.n) {
876
+ case 0:
877
+ _context8.n = 1;
878
+ return import('@tanstack/react-start/server');
879
+ case 1:
880
+ _yield$import = _context8.v;
881
+ getRequestHeaders = _yield$import.getRequestHeaders;
882
+ headers = getRequestHeaders();
883
+ return _context8.a(2, {
884
+ get: function get(name) {
885
+ var _headers$get2;
886
+ return (_headers$get2 = headers.get(name)) !== null && _headers$get2 !== void 0 ? _headers$get2 : null;
887
+ }
888
+ });
889
+ }
890
+ }, _callee8);
891
+ }));
892
+ return _requestHeaders.apply(this, arguments);
893
+ }
894
+ function requestCookies() {
895
+ return _requestCookies.apply(this, arguments);
896
+ }
897
+ /**
898
+ * Val's content readers for the server side of a TanStack Start app.
899
+ *
900
+ * Use them where the server runs: a route `loader` during SSR, a
901
+ * `createServerFn`, or a server route handler. In the browser — a client
902
+ * navigation re-running a loader, say — there is no request to read draft
903
+ * state from, so they resolve the published content, which is the same answer
904
+ * the visitor would get.
905
+ *
906
+ * @example
907
+ * // src/val/server.ts
908
+ * import { initValContent } from "@valbuild/tanstack/server";
909
+ * import { config } from "../val.config";
910
+ * import valModules from "../val.modules";
911
+ *
912
+ * export const {
913
+ * fetchValStega: fetchVal,
914
+ * fetchValRouteStega: fetchValRoute,
915
+ * } = initValContent(config, valModules);
916
+ */
917
+ function _requestCookies() {
918
+ _requestCookies = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee9() {
919
+ var _yield$import2, getCookie;
920
+ return _regenerator().w(function (_context9) {
921
+ while (1) switch (_context9.n) {
922
+ case 0:
923
+ _context9.n = 1;
924
+ return import('@tanstack/react-start/server');
925
+ case 1:
926
+ _yield$import2 = _context9.v;
927
+ getCookie = _yield$import2.getCookie;
928
+ return _context9.a(2, {
929
+ get: function get(name) {
930
+ var value = getCookie(name);
931
+ return value === undefined ? undefined : {
932
+ name: name,
933
+ value: value
934
+ };
935
+ }
936
+ });
937
+ }
938
+ }, _callee9);
939
+ }));
940
+ return _requestCookies.apply(this, arguments);
941
+ }
942
+ function initValContent(config, valModules, opts) {
943
+ var _opts$draftMode;
944
+ var coreVersion = Internal.VERSION.core;
945
+ if (!coreVersion) {
946
+ throw new Error("Could not get @valbuild/core package version");
947
+ }
948
+ var tanstackVersion = VERSION;
949
+ if (!tanstackVersion) {
950
+ throw new Error("Could not get @valbuild/tanstack package version");
951
+ }
952
+ var draftMode = (_opts$draftMode = opts === null || opts === void 0 ? void 0 : opts.draftMode) !== null && _opts$draftMode !== void 0 ? _opts$draftMode : valDraftMode();
953
+ var isEnabled = function isEnabled() {
954
+ return draftMode.isEnabled();
955
+ };
956
+ var valServerPromise = createValServer(valModules, valApiEndpoints, _objectSpread2({
957
+ versions: {
958
+ // `next` is the field name in the wire contract; see initValServer.
959
+ next: tanstackVersion,
960
+ core: coreVersion
961
+ }
962
+ }, config), config, {
963
+ isEnabled: isEnabled,
964
+ onEnable: function onEnable() {
965
+ return draftMode.enable();
966
+ },
967
+ onDisable: function onDisable() {
968
+ return draftMode.disable();
969
+ }
970
+ });
971
+ return {
972
+ fetchValStega: initFetchValStega(config, valApiEndpoints,
973
+ // TODO: get from config
974
+ valServerPromise, isEnabled, requestHeaders, requestCookies),
975
+ fetchValKeyStega: initFetchValKeyStega(valServerPromise, isEnabled, requestCookies),
976
+ fetchValRouteStega: initFetchValRouteStega(config, valApiEndpoints, valServerPromise, isEnabled, requestHeaders, requestCookies),
977
+ fetchValRouteUrl: initFetchValRouteUrl(config, valApiEndpoints, valServerPromise, isEnabled, requestHeaders, requestCookies)
978
+ };
979
+ }
980
+
981
+ /**
982
+ * Val's tools over MCP, bound to this package.
983
+ *
984
+ * The MCP endpoint itself — the tools, the request guards, the access-token
985
+ * verification — lives in `@valbuild/mcp`, which knows nothing about any
986
+ * framework. All that is left here is the one thing this package can answer and
987
+ * that one cannot: which version of `@valbuild/tanstack` is running, which
988
+ * `initHandlerOptions` insists on before it will build a proxy-mode config.
989
+ *
990
+ * The version goes in the `next` field because that is the field name in the
991
+ * wire contract; see `initValServer`.
992
+ */
993
+ function initValMcp(valModules, config, opts) {
994
+ var tanstackVersion = VERSION;
995
+ if (!tanstackVersion) {
996
+ throw new Error("Could not get @valbuild/tanstack package version");
997
+ }
998
+ return initValMcp$1(valModules, config, _objectSpread2(_objectSpread2({}, opts), {}, {
999
+ versions: {
1000
+ next: tanstackVersion
1001
+ }
1002
+ }));
1003
+ }
1004
+
1005
+ export { VAL_DRAFT_MODE_COOKIE, hasValEnableCookieOnServer, initValContent, initValMcp, initValServer, valDraftMode };