@timber-js/app 0.2.0-alpha.101 → 0.2.0-alpha.103
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/dist/_chunks/{actions-BsfxK6yu.js → actions-n9qTlpmY.js} +7 -10
- package/dist/_chunks/actions-n9qTlpmY.js.map +1 -0
- package/dist/_chunks/{build-output-helper-DXnW0qjz.js → build-output-helper-5TK2Emwp.js} +1 -1
- package/dist/_chunks/{build-output-helper-DXnW0qjz.js.map → build-output-helper-5TK2Emwp.js.map} +1 -1
- package/dist/_chunks/{define-k32T6NL2.js → define-Btmz9B20.js} +3 -3
- package/dist/_chunks/{define-k32T6NL2.js.map → define-Btmz9B20.js.map} +1 -1
- package/dist/_chunks/{define-B-Q_UMOD.js → define-Dn98bPbb.js} +3 -3
- package/dist/_chunks/{define-B-Q_UMOD.js.map → define-Dn98bPbb.js.map} +1 -1
- package/dist/_chunks/{format-Bcn-Iv1x.js → format-CYBGxKtc.js} +1 -1
- package/dist/_chunks/{format-Bcn-Iv1x.js.map → format-CYBGxKtc.js.map} +1 -1
- package/dist/_chunks/{handler-store-B-lqaGyh.js → handler-store-B_df5Npe.js} +1 -1
- package/dist/_chunks/{handler-store-B-lqaGyh.js.map → handler-store-B_df5Npe.js.map} +1 -1
- package/dist/_chunks/{logger-0m8MsKdc.js → logger-DDmK5skc.js} +2 -2
- package/dist/_chunks/{logger-0m8MsKdc.js.map → logger-DDmK5skc.js.map} +1 -1
- package/dist/_chunks/merge-search-params-Cm_KIWDX.js +41 -0
- package/dist/_chunks/merge-search-params-Cm_KIWDX.js.map +1 -0
- package/dist/_chunks/{metadata-routes-BU684ls2.js → metadata-routes-Cjmvi3rQ.js} +1 -1
- package/dist/_chunks/{metadata-routes-BU684ls2.js.map → metadata-routes-Cjmvi3rQ.js.map} +1 -1
- package/dist/_chunks/{navigation-root-yx917rG0.js → navigation-root-2ypaZQDx.js} +2 -2
- package/dist/_chunks/{navigation-root-yx917rG0.js.map → navigation-root-2ypaZQDx.js.map} +1 -1
- package/dist/_chunks/{registry-I2ss-lvy.js → registry-DB93kT5c.js} +1 -1
- package/dist/_chunks/{registry-I2ss-lvy.js.map → registry-DB93kT5c.js.map} +1 -1
- package/dist/_chunks/{router-ref-h3-UaCQv.js → router-ref-TkUdmqtM.js} +2 -2
- package/dist/_chunks/{router-ref-h3-UaCQv.js.map → router-ref-TkUdmqtM.js.map} +1 -1
- package/dist/_chunks/{schema-bridge-Cxu4l-7p.js → schema-bridge-C3xl_vfb.js} +1 -1
- package/dist/_chunks/{schema-bridge-Cxu4l-7p.js.map → schema-bridge-C3xl_vfb.js.map} +1 -1
- package/dist/_chunks/{segment-classify-BjfuctV2.js → segment-classify-CnfLLvir.js} +1 -1
- package/dist/_chunks/{segment-classify-BjfuctV2.js.map → segment-classify-CnfLLvir.js.map} +1 -1
- package/dist/_chunks/{segment-context-Dx_OizxD.js → segment-context-Dc-GbSTe.js} +1 -1
- package/dist/_chunks/{segment-context-Dx_OizxD.js.map → segment-context-Dc-GbSTe.js.map} +1 -1
- package/dist/_chunks/{ssr-data-B4CdH7rE.js → ssr-data-DzuI0bIV.js} +1 -1
- package/dist/_chunks/{ssr-data-B4CdH7rE.js.map → ssr-data-DzuI0bIV.js.map} +1 -1
- package/dist/_chunks/{stale-reload-Bab885FO.js → stale-reload-D6FlD3xn.js} +1 -1
- package/dist/_chunks/{stale-reload-Bab885FO.js.map → stale-reload-D6FlD3xn.js.map} +1 -1
- package/dist/_chunks/{tracing-C8V-YGsP.js → tracing-DvKLzCFa.js} +1 -1
- package/dist/_chunks/{tracing-C8V-YGsP.js.map → tracing-DvKLzCFa.js.map} +1 -1
- package/dist/_chunks/{use-query-states-B2XTqxDR.js → use-query-states-B-cLl8mx.js} +2 -2
- package/dist/_chunks/{use-query-states-B2XTqxDR.js.map → use-query-states-B-cLl8mx.js.map} +1 -1
- package/dist/_chunks/{use-segment-params-DlsOX1YS.js → use-segment-params-07V1TIxL.js} +3 -3
- package/dist/_chunks/{use-segment-params-DlsOX1YS.js.map → use-segment-params-07V1TIxL.js.map} +1 -1
- package/dist/_chunks/{merge-search-params-BphMdht_.js → validation-DfyuMoK2.js} +2 -40
- package/dist/_chunks/validation-DfyuMoK2.js.map +1 -0
- package/dist/_chunks/{walkers-Tg0Alwcg.js → walkers-DQn5NNrf.js} +4 -4
- package/dist/_chunks/{walkers-Tg0Alwcg.js.map → walkers-DQn5NNrf.js.map} +1 -1
- package/dist/_chunks/{warnings-Cg47l5sk.js → warnings-B30wpfaS.js} +2 -2
- package/dist/_chunks/{warnings-Cg47l5sk.js.map → warnings-B30wpfaS.js.map} +1 -1
- package/dist/adapters/cloudflare.js +1 -1
- package/dist/adapters/nitro.js +1 -1
- package/dist/cache/index.js +3 -3
- package/dist/client/error-boundary.js +2 -2
- package/dist/client/index.js +10 -117
- package/dist/client/index.js.map +1 -1
- package/dist/client/internal.js +7 -7
- package/dist/client/use-cookie.d.ts +4 -0
- package/dist/client/use-cookie.d.ts.map +1 -1
- package/dist/codec.js +1 -1
- package/dist/cookies/define-cookie.d.ts +5 -45
- package/dist/cookies/define-cookie.d.ts.map +1 -1
- package/dist/cookies/index.js +252 -1
- package/dist/cookies/index.js.map +1 -1
- package/dist/fonts/ast.d.ts.map +1 -1
- package/dist/index.js +89 -45
- package/dist/index.js.map +1 -1
- package/dist/routing/index.js +2 -2
- package/dist/search-params/index.js +3 -3
- package/dist/segment-params/index.js +1 -1
- package/dist/server/index.js +3 -3
- package/dist/server/internal.js +7 -7
- package/dist/server/request-context.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/client/index.ts +0 -9
- package/src/client/use-cookie.ts +2 -2
- package/src/cookies/define-cookie.ts +100 -166
- package/src/fonts/ast.ts +64 -27
- package/src/server/request-context.ts +1 -8
- package/dist/_chunks/actions-BsfxK6yu.js.map +0 -1
- package/dist/_chunks/chunk-Cfpv9whK.js +0 -32
- package/dist/_chunks/define-cookie-BjpIt4UC.js +0 -194
- package/dist/_chunks/define-cookie-BjpIt4UC.js.map +0 -1
- package/dist/_chunks/merge-search-params-BphMdht_.js.map +0 -1
package/dist/cookies/index.js
CHANGED
|
@@ -1,4 +1,255 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { n as fromSchema } from "../_chunks/schema-bridge-C3xl_vfb.js";
|
|
2
|
+
import { t as assertValidCookieName } from "../_chunks/validation-DfyuMoK2.js";
|
|
3
|
+
import { n as getSsrData } from "../_chunks/ssr-data-DzuI0bIV.js";
|
|
4
|
+
import { useSyncExternalStore } from "react";
|
|
5
|
+
import { getCookieJar } from "@timber-js/app/server";
|
|
6
|
+
//#region src/client/use-cookie.ts
|
|
7
|
+
/**
|
|
8
|
+
* useCookie — reactive client-side cookie hook.
|
|
9
|
+
*
|
|
10
|
+
* Uses useSyncExternalStore for SSR-safe, reactive cookie access.
|
|
11
|
+
* All components reading the same cookie name re-render on change.
|
|
12
|
+
* No cross-tab sync (intentional — see design/29-cookies.md).
|
|
13
|
+
*
|
|
14
|
+
* See design/29-cookies.md §"useCookie(name) Hook"
|
|
15
|
+
*/
|
|
16
|
+
/** Per-name subscriber sets. */
|
|
17
|
+
var listeners = /* @__PURE__ */ new Map();
|
|
18
|
+
/** Parse a cookie name from document.cookie. */
|
|
19
|
+
function getCookieValue(name) {
|
|
20
|
+
if (typeof document === "undefined") return void 0;
|
|
21
|
+
const match = document.cookie.match(new RegExp("(?:^|;\\s*)" + name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") + "\\s*=\\s*([^;]*)"));
|
|
22
|
+
return match ? decodeURIComponent(match[1]) : void 0;
|
|
23
|
+
}
|
|
24
|
+
/** Serialize options into a cookie string suffix. */
|
|
25
|
+
function serializeOptions(options) {
|
|
26
|
+
if (!options) return "; Path=/; SameSite=Lax";
|
|
27
|
+
const parts = [];
|
|
28
|
+
parts.push(`Path=${options.path ?? "/"}`);
|
|
29
|
+
if (options.domain) parts.push(`Domain=${options.domain}`);
|
|
30
|
+
if (options.maxAge !== void 0) parts.push(`Max-Age=${options.maxAge}`);
|
|
31
|
+
if (options.expires) parts.push(`Expires=${options.expires.toUTCString()}`);
|
|
32
|
+
const sameSite = options.sameSite ?? "lax";
|
|
33
|
+
parts.push(`SameSite=${sameSite.charAt(0).toUpperCase()}${sameSite.slice(1)}`);
|
|
34
|
+
if (options.secure) parts.push("Secure");
|
|
35
|
+
return "; " + parts.join("; ");
|
|
36
|
+
}
|
|
37
|
+
/** Notify all subscribers for a given cookie name. */
|
|
38
|
+
function notify(name) {
|
|
39
|
+
const subs = listeners.get(name);
|
|
40
|
+
if (subs) for (const fn of subs) fn();
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Notify useCookie subscribers that a cookie value changed.
|
|
44
|
+
* Called by defineCookie's imperative client .set()/.delete() methods
|
|
45
|
+
* so mounted useCookie() consumers re-render.
|
|
46
|
+
*
|
|
47
|
+
* @internal — framework use only
|
|
48
|
+
*/
|
|
49
|
+
function notifyCookieChange(name) {
|
|
50
|
+
notify(name);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Reactive hook for reading/writing a client-side cookie.
|
|
54
|
+
*
|
|
55
|
+
* Returns `[value, setCookie, deleteCookie]`:
|
|
56
|
+
* - `value`: current cookie value (string | undefined)
|
|
57
|
+
* - `setCookie`: sets the cookie and triggers re-renders
|
|
58
|
+
* - `deleteCookie`: deletes the cookie and triggers re-renders
|
|
59
|
+
*
|
|
60
|
+
* @param name - Cookie name.
|
|
61
|
+
* @param defaultOptions - Default options for setCookie calls.
|
|
62
|
+
*/
|
|
63
|
+
function useCookie(name, defaultOptions) {
|
|
64
|
+
const subscribe = (callback) => {
|
|
65
|
+
let subs = listeners.get(name);
|
|
66
|
+
if (!subs) {
|
|
67
|
+
subs = /* @__PURE__ */ new Set();
|
|
68
|
+
listeners.set(name, subs);
|
|
69
|
+
}
|
|
70
|
+
subs.add(callback);
|
|
71
|
+
return () => {
|
|
72
|
+
subs.delete(callback);
|
|
73
|
+
if (subs.size === 0) listeners.delete(name);
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
const getSnapshot = () => getCookieValue(name);
|
|
77
|
+
const getServerSnapshot = () => getSsrData()?.cookies.get(name);
|
|
78
|
+
const value = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
|
|
79
|
+
assertValidCookieName(name);
|
|
80
|
+
const setCookie = (newValue, options) => {
|
|
81
|
+
if (typeof newValue !== "string") throw new Error(`[timber] useCookie(${JSON.stringify(name)}): value must be a string, got ${typeof newValue}.\n To store a JSON-serializable value, use defineCookie + jsonCookieCodec from\n '@timber-js/app/cookies' and call its useCookie() hook instead.`);
|
|
82
|
+
const merged = {
|
|
83
|
+
...defaultOptions,
|
|
84
|
+
...options
|
|
85
|
+
};
|
|
86
|
+
document.cookie = `${name}=${encodeURIComponent(newValue)}${serializeOptions(merged)}`;
|
|
87
|
+
notify(name);
|
|
88
|
+
};
|
|
89
|
+
const deleteCookie = () => {
|
|
90
|
+
const path = defaultOptions?.path ?? "/";
|
|
91
|
+
const domain = defaultOptions?.domain;
|
|
92
|
+
let cookieStr = `${name}=; Max-Age=0; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Path=${path}`;
|
|
93
|
+
if (domain) cookieStr += `; Domain=${domain}`;
|
|
94
|
+
document.cookie = cookieStr;
|
|
95
|
+
notify(name);
|
|
96
|
+
};
|
|
97
|
+
return [
|
|
98
|
+
value,
|
|
99
|
+
setCookie,
|
|
100
|
+
deleteCookie
|
|
101
|
+
];
|
|
102
|
+
}
|
|
103
|
+
//#endregion
|
|
104
|
+
//#region src/cookies/define-cookie.ts
|
|
105
|
+
/**
|
|
106
|
+
* Try to get the server cookie jar. Returns null if we're in the client
|
|
107
|
+
* environment (stub throws) or if there's no request context.
|
|
108
|
+
*
|
|
109
|
+
* On the server, getCookieJar() throws "outside of a request context" if
|
|
110
|
+
* called without an ALS store — this is a real error and is re-thrown.
|
|
111
|
+
* The client stub throws a different message — that's caught and returns null.
|
|
112
|
+
*/
|
|
113
|
+
function tryGetServerCookieJar() {
|
|
114
|
+
try {
|
|
115
|
+
return getCookieJar();
|
|
116
|
+
} catch (e) {
|
|
117
|
+
if (e instanceof Error && e.message.includes("outside of a request context")) throw e;
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/** Write a cookie via document.cookie and notify useCookie subscribers. */
|
|
122
|
+
function setClientCookie(name, value, options) {
|
|
123
|
+
const parts = [`${name}=${encodeURIComponent(value)}`];
|
|
124
|
+
const path = options?.path ?? "/";
|
|
125
|
+
parts.push(`Path=${path}`);
|
|
126
|
+
if (options?.domain) parts.push(`Domain=${options.domain}`);
|
|
127
|
+
if (options?.maxAge !== void 0) parts.push(`Max-Age=${options.maxAge}`);
|
|
128
|
+
if (options?.expires) parts.push(`Expires=${options.expires.toUTCString()}`);
|
|
129
|
+
const sameSite = options?.sameSite ?? "lax";
|
|
130
|
+
parts.push(`SameSite=${sameSite.charAt(0).toUpperCase()}${sameSite.slice(1)}`);
|
|
131
|
+
if (options?.secure) parts.push("Secure");
|
|
132
|
+
document.cookie = parts.join("; ");
|
|
133
|
+
notifyCookieChange(name);
|
|
134
|
+
}
|
|
135
|
+
/** Delete a cookie via document.cookie and notify useCookie subscribers. */
|
|
136
|
+
function deleteClientCookie(name, options) {
|
|
137
|
+
const path = options?.path ?? "/";
|
|
138
|
+
const domain = options?.domain;
|
|
139
|
+
let cookieStr = `${name}=; Max-Age=0; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Path=${path}`;
|
|
140
|
+
if (domain) cookieStr += `; Domain=${domain}`;
|
|
141
|
+
document.cookie = cookieStr;
|
|
142
|
+
notifyCookieChange(name);
|
|
143
|
+
}
|
|
144
|
+
function resolveCodec(codecOrSchema) {
|
|
145
|
+
if (typeof codecOrSchema.parse === "function" && typeof codecOrSchema.serialize === "function") return codecOrSchema;
|
|
146
|
+
if (typeof codecOrSchema === "object" && codecOrSchema !== null && "~standard" in codecOrSchema) return fromSchema(codecOrSchema);
|
|
147
|
+
throw new Error("[timber] defineCookie: codec must be a Codec<T> (with parse/serialize methods) or a Standard Schema object (Zod, Valibot, ArkType).");
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Define a typed cookie.
|
|
151
|
+
*
|
|
152
|
+
* ```ts
|
|
153
|
+
* import { defineCookie } from '@timber-js/app/cookies';
|
|
154
|
+
* import { z } from 'zod/v4';
|
|
155
|
+
*
|
|
156
|
+
* // httpOnly: false — client methods available
|
|
157
|
+
* export const themeCookie = defineCookie('theme', {
|
|
158
|
+
* codec: z.enum(['light', 'dark', 'system']).default('system'),
|
|
159
|
+
* httpOnly: false,
|
|
160
|
+
* maxAge: 60 * 60 * 24 * 365,
|
|
161
|
+
* });
|
|
162
|
+
*
|
|
163
|
+
* // Server or client
|
|
164
|
+
* const theme = themeCookie.get();
|
|
165
|
+
* themeCookie.set('dark');
|
|
166
|
+
*
|
|
167
|
+
* // Client hook
|
|
168
|
+
* const [theme, setTheme] = themeCookie.useCookie();
|
|
169
|
+
*
|
|
170
|
+
* // httpOnly: true (default) — server-only, no client methods
|
|
171
|
+
* export const sessionCookie = defineCookie('session', {
|
|
172
|
+
* codec: z.string(),
|
|
173
|
+
* });
|
|
174
|
+
* sessionCookie.get(); // works on server
|
|
175
|
+
* sessionCookie.useCookie(); // TS error — httpOnly cookie
|
|
176
|
+
* ```
|
|
177
|
+
*/
|
|
178
|
+
function defineCookie(name, options) {
|
|
179
|
+
const { codec: codecOrSchema, ...cookieOpts } = options;
|
|
180
|
+
const codec = resolveCodec(codecOrSchema);
|
|
181
|
+
const resolvedOptions = { ...cookieOpts };
|
|
182
|
+
const isHttpOnly = options.httpOnly !== false;
|
|
183
|
+
function getClientOpts() {
|
|
184
|
+
return {
|
|
185
|
+
path: resolvedOptions.path,
|
|
186
|
+
domain: resolvedOptions.domain,
|
|
187
|
+
maxAge: resolvedOptions.maxAge,
|
|
188
|
+
expires: resolvedOptions.expires,
|
|
189
|
+
sameSite: resolvedOptions.sameSite,
|
|
190
|
+
secure: resolvedOptions.secure
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
const base = {
|
|
194
|
+
name,
|
|
195
|
+
options: resolvedOptions,
|
|
196
|
+
codec,
|
|
197
|
+
get() {
|
|
198
|
+
const serverJar = tryGetServerCookieJar();
|
|
199
|
+
if (serverJar) return codec.parse(serverJar.get(name));
|
|
200
|
+
if (isHttpOnly) throw new Error(`[timber] defineCookie('${name}').get() cannot be used with httpOnly cookies — the browser cannot access them. Set httpOnly: false to enable client access.`);
|
|
201
|
+
const raw = getCookieValue(name);
|
|
202
|
+
return codec.parse(raw);
|
|
203
|
+
},
|
|
204
|
+
set(value) {
|
|
205
|
+
const serverJar = tryGetServerCookieJar();
|
|
206
|
+
if (serverJar) {
|
|
207
|
+
const serialized = codec.serialize(value);
|
|
208
|
+
if (serialized === null) serverJar.delete(name, {
|
|
209
|
+
path: resolvedOptions.path,
|
|
210
|
+
domain: resolvedOptions.domain
|
|
211
|
+
});
|
|
212
|
+
else serverJar.set(name, serialized, resolvedOptions);
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
if (isHttpOnly) throw new Error(`[timber] defineCookie('${name}').set() cannot be used with httpOnly cookies — the browser cannot access them. Set httpOnly: false to enable client access.`);
|
|
216
|
+
const serialized = codec.serialize(value);
|
|
217
|
+
if (serialized === null) deleteClientCookie(name, getClientOpts());
|
|
218
|
+
else setClientCookie(name, serialized, getClientOpts());
|
|
219
|
+
},
|
|
220
|
+
delete() {
|
|
221
|
+
const serverJar = tryGetServerCookieJar();
|
|
222
|
+
if (serverJar) {
|
|
223
|
+
serverJar.delete(name, {
|
|
224
|
+
path: resolvedOptions.path,
|
|
225
|
+
domain: resolvedOptions.domain
|
|
226
|
+
});
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
if (isHttpOnly) throw new Error(`[timber] defineCookie('${name}').delete() cannot be used with httpOnly cookies — the browser cannot access them. Set httpOnly: false to enable client access.`);
|
|
230
|
+
deleteClientCookie(name, getClientOpts());
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
if (isHttpOnly) return base;
|
|
234
|
+
return {
|
|
235
|
+
...base,
|
|
236
|
+
useCookie() {
|
|
237
|
+
const [raw, setRaw, deleteRaw] = useCookie(name, getClientOpts());
|
|
238
|
+
const parsed = codec.parse(raw);
|
|
239
|
+
const setTyped = (value) => {
|
|
240
|
+
const serialized = codec.serialize(value);
|
|
241
|
+
if (serialized === null) deleteRaw();
|
|
242
|
+
else setRaw(serialized);
|
|
243
|
+
};
|
|
244
|
+
return [
|
|
245
|
+
parsed,
|
|
246
|
+
setTyped,
|
|
247
|
+
deleteRaw
|
|
248
|
+
];
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
//#endregion
|
|
2
253
|
//#region src/cookies/json-cookie.ts
|
|
3
254
|
/**
|
|
4
255
|
* Build a CookieCodec that JSON-encodes the value. The framework's
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/cookies/json-cookie.ts"],"sourcesContent":["/**\n * jsonCookieCodec — Codec helper for storing JSON-serializable values in\n * cookies.\n *\n * The codec is intentionally minimal: `JSON.stringify` on serialize,\n * `JSON.parse` on parse. The framework handles the URL encoding /\n * decoding around it (see design/29-cookies.md §\"Encoding Contract\"):\n *\n * defineCookie.setCookie(value)\n * → codec.serialize: JSON.stringify → '{\"a\":1}'\n * → cookies().set: encodeURIComponent → '%7B%22a%22%3A1%7D'\n * → wire: Set-Cookie: prefs=%7B%22a%22%3A1%7D\n *\n * defineCookie.getCookie()\n * → wire: Cookie: prefs=%7B%22a%22%3A1%7D\n * → parseCookieHeader: decodeURIComponent → '{\"a\":1}'\n * → codec.parse: JSON.parse → { a: 1 }\n *\n * The same chain works on the client: `useCookie` auto-encodes on writes\n * and auto-decodes on reads, so `jsonCookieCodec` composes with both the\n * server `defineCookie` methods and the client `useCookie` hook with no\n * environment-specific branches.\n *\n * Parsing is total: any non-JSON value (or `undefined`) returns the\n * supplied default. This matches the \"never crash on user-controlled\n * cookie input\" semantics that `fromSchema` uses for typed search params.\n *\n * ```ts\n * import { defineCookie, jsonCookieCodec } from '@timber-js/app/cookies';\n *\n * interface Prefs { lang: string; fontSize: number }\n *\n * export const prefsCookie = defineCookie('prefs', {\n * codec: jsonCookieCodec<Prefs>({ lang: 'en', fontSize: 16 }),\n * httpOnly: false,\n * maxAge: 60 * 60 * 24 * 365,\n * });\n *\n * await prefsCookie.setCookie({ lang: 'fr', fontSize: 18 });\n * ```\n */\n\nimport type { Codec } from '../codec.js';\n\n/**\n * Build a CookieCodec that JSON-encodes the value. The framework's\n * cookie write path then URL-encodes the JSON string into a valid\n * `cookie-octet` form, and the read path reverses both transforms.\n *\n * @param defaultValue - Returned by `parse` when the cookie is missing\n * or the stored value cannot be JSON-parsed. Optional — if omitted,\n * `parse` returns `undefined` on missing/malformed input.\n *\n * The default is **deep-cloned** on every fallback return via\n * `structuredClone`, so mutating the parsed result in one request\n * cannot leak into later requests that fall back to the same\n * default. This matters for long-lived server processes where a\n * codec is defined once at module load and shared across all\n * requests — without the clone, a user doing\n * `const prefs = prefsCookie.get(); prefs.lang = 'fr'` on a missing\n * cookie would mutate the module-level default and poison every\n * later fallback. See the \"shared mutable default\" regression test\n * in `tests/define-cookie.test.ts`.\n */\nexport function jsonCookieCodec<T>(defaultValue?: T): Codec<T> {\n // Resolve the fallback at call time, not capture time, so every\n // fallback return produces a fresh deep copy. structuredClone handles\n // nested objects, arrays, dates, maps, sets — everything\n // JSON-serializable plus more. For primitives and undefined,\n // structuredClone is effectively a no-op.\n const cloneDefault = (): T => {\n if (defaultValue === undefined || defaultValue === null) {\n return defaultValue as T;\n }\n // structuredClone is a Node built-in since Node 17, available in\n // all supported runtimes.\n return structuredClone(defaultValue);\n };\n\n return {\n parse(value: string | string[] | undefined): T {\n if (value === undefined || value === '') {\n return cloneDefault();\n }\n // Cookies are single-valued by name; defensively pick the last\n // entry if a Codec consumer somehow passes an array.\n const raw = Array.isArray(value) ? value[value.length - 1] : value;\n if (raw === undefined || raw === '') {\n return cloneDefault();\n }\n try {\n return JSON.parse(raw) as T;\n } catch {\n return cloneDefault();\n }\n },\n\n serialize(value: T): string | null {\n if (value === null || value === undefined) {\n return null;\n }\n return JSON.stringify(value);\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAgEA,SAAgB,gBAAmB,cAA4B;CAM7D,MAAM,qBAAwB;AAC5B,MAAI,iBAAiB,KAAA,KAAa,iBAAiB,KACjD,QAAO;AAIT,SAAO,gBAAgB,aAAa;;AAGtC,QAAO;EACL,MAAM,OAAyC;AAC7C,OAAI,UAAU,KAAA,KAAa,UAAU,GACnC,QAAO,cAAc;GAIvB,MAAM,MAAM,MAAM,QAAQ,MAAM,GAAG,MAAM,MAAM,SAAS,KAAK;AAC7D,OAAI,QAAQ,KAAA,KAAa,QAAQ,GAC/B,QAAO,cAAc;AAEvB,OAAI;AACF,WAAO,KAAK,MAAM,IAAI;WAChB;AACN,WAAO,cAAc;;;EAIzB,UAAU,OAAyB;AACjC,OAAI,UAAU,QAAQ,UAAU,KAAA,EAC9B,QAAO;AAET,UAAO,KAAK,UAAU,MAAM;;EAE/B"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/client/use-cookie.ts","../../src/cookies/define-cookie.ts","../../src/cookies/json-cookie.ts"],"sourcesContent":["/**\n * useCookie — reactive client-side cookie hook.\n *\n * Uses useSyncExternalStore for SSR-safe, reactive cookie access.\n * All components reading the same cookie name re-render on change.\n * No cross-tab sync (intentional — see design/29-cookies.md).\n *\n * See design/29-cookies.md §\"useCookie(name) Hook\"\n */\n\nimport { useSyncExternalStore } from 'react';\nimport { getSsrData } from './ssr-data.js';\nimport { assertValidCookieName } from '../cookies/validation.js';\n\n// ─── Types ────────────────────────────────────────────────────────────────\n\nexport interface ClientCookieOptions {\n /** URL path scope. Default: '/'. */\n path?: string;\n /** Domain scope. Default: omitted (current domain). */\n domain?: string;\n /** Max age in seconds. */\n maxAge?: number;\n /** Expiration date. */\n expires?: Date;\n /** Cross-site policy. Default: 'lax'. */\n sameSite?: 'strict' | 'lax' | 'none';\n /** Only send over HTTPS. Default: true in production. */\n secure?: boolean;\n}\n\nexport type CookieSetter = (value: string, options?: ClientCookieOptions) => void;\n\n// ─── Module-Level Cookie Store ────────────────────────────────────────────\n\ntype Listener = () => void;\n\n/** Per-name subscriber sets. */\nconst listeners = new Map<string, Set<Listener>>();\n\n/** Parse a cookie name from document.cookie. */\nexport function getCookieValue(name: string): string | undefined {\n if (typeof document === 'undefined') return undefined;\n const match = document.cookie.match(\n new RegExp('(?:^|;\\\\s*)' + name.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&') + '\\\\s*=\\\\s*([^;]*)')\n );\n return match ? decodeURIComponent(match[1]) : undefined;\n}\n\n/** Serialize options into a cookie string suffix. */\nexport function serializeOptions(options?: ClientCookieOptions): string {\n if (!options) return '; Path=/; SameSite=Lax';\n const parts: string[] = [];\n parts.push(`Path=${options.path ?? '/'}`);\n if (options.domain) parts.push(`Domain=${options.domain}`);\n if (options.maxAge !== undefined) parts.push(`Max-Age=${options.maxAge}`);\n if (options.expires) parts.push(`Expires=${options.expires.toUTCString()}`);\n const sameSite = options.sameSite ?? 'lax';\n parts.push(`SameSite=${sameSite.charAt(0).toUpperCase()}${sameSite.slice(1)}`);\n if (options.secure) parts.push('Secure');\n return '; ' + parts.join('; ');\n}\n\n/** Notify all subscribers for a given cookie name. */\nfunction notify(name: string): void {\n const subs = listeners.get(name);\n if (subs) {\n for (const fn of subs) fn();\n }\n}\n\n/**\n * Notify useCookie subscribers that a cookie value changed.\n * Called by defineCookie's imperative client .set()/.delete() methods\n * so mounted useCookie() consumers re-render.\n *\n * @internal — framework use only\n */\nexport function notifyCookieChange(name: string): void {\n notify(name);\n}\n\n// ─── Hook ─────────────────────────────────────────────────────────────────\n\n/**\n * Reactive hook for reading/writing a client-side cookie.\n *\n * Returns `[value, setCookie, deleteCookie]`:\n * - `value`: current cookie value (string | undefined)\n * - `setCookie`: sets the cookie and triggers re-renders\n * - `deleteCookie`: deletes the cookie and triggers re-renders\n *\n * @param name - Cookie name.\n * @param defaultOptions - Default options for setCookie calls.\n */\nexport function useCookie(\n name: string,\n defaultOptions?: ClientCookieOptions\n): [value: string | undefined, setCookie: CookieSetter, deleteCookie: () => void] {\n const subscribe = (callback: Listener): (() => void) => {\n let subs = listeners.get(name);\n if (!subs) {\n subs = new Set();\n listeners.set(name, subs);\n }\n subs.add(callback);\n return () => {\n subs!.delete(callback);\n if (subs!.size === 0) listeners.delete(name);\n };\n };\n\n const getSnapshot = (): string | undefined => getCookieValue(name);\n const getServerSnapshot = (): string | undefined => getSsrData()?.cookies.get(name);\n\n const value = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n\n // Validate the name once per hook instance — names are typically\n // stable string literals, so this catches the bug at first render\n // rather than on every write. Throws via `assertValidCookieName` with\n // a precise error if the name violates RFC 7230 token rules.\n assertValidCookieName(name);\n\n const setCookie: CookieSetter = (newValue: string, options?: ClientCookieOptions) => {\n if (typeof newValue !== 'string') {\n throw new Error(\n `[timber] useCookie(${JSON.stringify(name)}): value must be a string, got ${typeof newValue}.\\n` +\n ` To store a JSON-serializable value, use defineCookie + jsonCookieCodec from\\n` +\n ` '@timber-js/app/cookies' and call its useCookie() hook instead.`\n );\n }\n const merged = { ...defaultOptions, ...options };\n // Auto-encode mirrors the server's `cookies().set()` contract:\n // values are URL-encoded on write, URL-decoded on read, so the\n // logical bytes round-trip losslessly. See design/29-cookies.md\n // §\"Encoding Contract\".\n document.cookie = `${name}=${encodeURIComponent(newValue)}${serializeOptions(merged)}`;\n notify(name);\n };\n\n const deleteCookie = (): void => {\n const path = defaultOptions?.path ?? '/';\n const domain = defaultOptions?.domain;\n let cookieStr = `${name}=; Max-Age=0; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Path=${path}`;\n if (domain) cookieStr += `; Domain=${domain}`;\n document.cookie = cookieStr;\n notify(name);\n };\n\n return [value, setCookie, deleteCookie];\n}\n","/**\n * defineCookie — typed cookie definitions.\n *\n * Bundles name + codec + options into a reusable CookieDefinition<T>\n * with sync .get(), .set(), .delete() isomorphic methods (server + client)\n * and a .useCookie() client hook.\n *\n * Environment detection is call-time: on the server, getCookieJar() is\n * used directly (ALS-backed). On the client, document.cookie helpers\n * and the useCookie hook are used. No registration pattern — imports\n * resolve via the shims plugin (client bundle gets a stub for\n * @timber-js/app/server).\n *\n * Standard Schema objects (Zod, Valibot, ArkType) are auto-detected in\n * the codec option — no explicit fromSchema() wrapper needed.\n *\n * See design/29-cookies.md §\"Typed Cookies with Schema Validation\"\n */\n\nimport type { CookieOptions } from '../server/cookie-context.js';\nimport type { ClientCookieOptions } from '../client/use-cookie.js';\n\n// ─── Types ────────────────────────────────────────────────────────────────\n\nimport type { Codec } from '../codec.js';\nimport type { StandardSchemaV1 } from '../schema-bridge.js';\n\n/**\n * A codec that converts between string cookie values and typed values.\n * Type alias for the shared Codec<T> protocol.\n */\nexport type CookieCodec<T> = Codec<T>;\n\n/** Options for defineCookie: codec + CookieOptions merged. */\nexport interface DefineCookieOptions<T, HttpOnly extends boolean = boolean> extends CookieOptions {\n /**\n * Codec for parsing/serializing the cookie value.\n * Accepts a Codec<T> or a Standard Schema object (Zod, Valibot, ArkType)\n * which is auto-wrapped via fromSchema.\n */\n codec: CookieCodec<T> | StandardSchemaV1<T>;\n /**\n * Prevent client-side JS access. Default: true.\n * When true (or omitted), client methods (useCookie, get/set/delete on\n * client) are omitted from the return type and throw at runtime.\n */\n httpOnly?: HttpOnly;\n}\n\n/**\n * Server-only cookie definition. Returned when httpOnly is true or omitted.\n * Client methods are absent from the type — accessing them is a TS error.\n */\nexport interface ServerOnlyCookieDefinition<T> {\n readonly name: string;\n readonly options: CookieOptions;\n readonly codec: CookieCodec<T>;\n\n /** Read the typed value. Sync, isomorphic (server + client). */\n get(): T;\n /** Set the typed value. Sync, isomorphic (server + client). */\n set(value: T): void;\n /** Delete the cookie. Sync, isomorphic (server + client). */\n delete(): void;\n}\n\n/**\n * Full cookie definition with client methods. Returned when httpOnly: false.\n */\nexport interface CookieDefinition<T> extends ServerOnlyCookieDefinition<T> {\n /** Client: React hook for reading/writing this cookie. Returns [value, setter, deleter]. */\n useCookie(): [T, (value: T) => void, () => void];\n}\n\n// ─── Direct Imports (no registration) ─────────────────────────────────────\n//\n// Server: getCookieJar is imported from @timber-js/app/server. In the client\n// bundle, the shims plugin replaces @timber-js/app/server with a stub module\n// where getCookieJar throws on call. We detect the environment at call time\n// by trying getCookieJar() — if it throws the stub error, we fall through\n// to the client path.\n//\n// Client: useCookie, getCookieValue, notifyCookieChange\n// are imported from use-cookie.ts. These are safe in all environments (no\n// node:async_hooks dependency).\n//\n// Schema: fromSchema is a pure function — safe in all environments.\n\nimport { getCookieJar } from '@timber-js/app/server';\nimport { fromSchema } from '../schema-bridge.js';\nimport {\n useCookie as useRawCookie,\n notifyCookieChange,\n getCookieValue,\n} from '../client/use-cookie.js';\n\n// ─── Environment Detection ────────────────────────────────────────────────\n\n/**\n * Try to get the server cookie jar. Returns null if we're in the client\n * environment (stub throws) or if there's no request context.\n *\n * On the server, getCookieJar() throws \"outside of a request context\" if\n * called without an ALS store — this is a real error and is re-thrown.\n * The client stub throws a different message — that's caught and returns null.\n */\nfunction tryGetServerCookieJar(): ReturnType<typeof getCookieJar> | null {\n try {\n return getCookieJar();\n } catch (e) {\n // Server-side \"no request context\" error — re-throw as a real bug.\n if (e instanceof Error && e.message.includes('outside of a request context')) {\n throw e;\n }\n // Client stub error or other — fall through to client path.\n return null;\n }\n}\n\n// ─── Client Cookie Helpers ────────────────────────────────────────────────\n\n/** Write a cookie via document.cookie and notify useCookie subscribers. */\nfunction setClientCookie(name: string, value: string, options?: ClientCookieOptions): void {\n const parts: string[] = [`${name}=${encodeURIComponent(value)}`];\n const path = options?.path ?? '/';\n parts.push(`Path=${path}`);\n if (options?.domain) parts.push(`Domain=${options.domain}`);\n if (options?.maxAge !== undefined) parts.push(`Max-Age=${options.maxAge}`);\n if (options?.expires) parts.push(`Expires=${options.expires.toUTCString()}`);\n const sameSite = options?.sameSite ?? 'lax';\n parts.push(`SameSite=${sameSite.charAt(0).toUpperCase()}${sameSite.slice(1)}`);\n if (options?.secure) parts.push('Secure');\n document.cookie = parts.join('; ');\n notifyCookieChange(name);\n}\n\n/** Delete a cookie via document.cookie and notify useCookie subscribers. */\nfunction deleteClientCookie(name: string, options?: ClientCookieOptions): void {\n const path = options?.path ?? '/';\n const domain = options?.domain;\n let cookieStr = `${name}=; Max-Age=0; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Path=${path}`;\n if (domain) cookieStr += `; Domain=${domain}`;\n document.cookie = cookieStr;\n notifyCookieChange(name);\n}\n\n// ─── Standard Schema Auto-Detection ───────────────────────────────────────\n\nfunction resolveCodec<T>(codecOrSchema: CookieCodec<T> | StandardSchemaV1<T>): CookieCodec<T> {\n // If it has parse + serialize, it's already a Codec\n if (\n typeof (codecOrSchema as Codec<T>).parse === 'function' &&\n typeof (codecOrSchema as Codec<T>).serialize === 'function'\n ) {\n return codecOrSchema as CookieCodec<T>;\n }\n\n // Auto-detect Standard Schema\n if (typeof codecOrSchema === 'object' && codecOrSchema !== null && '~standard' in codecOrSchema) {\n return fromSchema(codecOrSchema as StandardSchemaV1<unknown>) as CookieCodec<T>;\n }\n\n throw new Error(\n '[timber] defineCookie: codec must be a Codec<T> (with parse/serialize methods) ' +\n 'or a Standard Schema object (Zod, Valibot, ArkType).'\n );\n}\n\n// ─── Factory ──────────────────────────────────────────────────────────────\n\n/**\n * Define a typed cookie.\n *\n * ```ts\n * import { defineCookie } from '@timber-js/app/cookies';\n * import { z } from 'zod/v4';\n *\n * // httpOnly: false — client methods available\n * export const themeCookie = defineCookie('theme', {\n * codec: z.enum(['light', 'dark', 'system']).default('system'),\n * httpOnly: false,\n * maxAge: 60 * 60 * 24 * 365,\n * });\n *\n * // Server or client\n * const theme = themeCookie.get();\n * themeCookie.set('dark');\n *\n * // Client hook\n * const [theme, setTheme] = themeCookie.useCookie();\n *\n * // httpOnly: true (default) — server-only, no client methods\n * export const sessionCookie = defineCookie('session', {\n * codec: z.string(),\n * });\n * sessionCookie.get(); // works on server\n * sessionCookie.useCookie(); // TS error — httpOnly cookie\n * ```\n */\nexport function defineCookie<T, HttpOnly extends boolean = true>(\n name: string,\n options: DefineCookieOptions<T, HttpOnly>\n): HttpOnly extends false ? CookieDefinition<T> : ServerOnlyCookieDefinition<T> {\n const { codec: codecOrSchema, ...cookieOpts } = options;\n const codec = resolveCodec(codecOrSchema);\n const resolvedOptions: CookieOptions = { ...cookieOpts };\n const isHttpOnly = options.httpOnly !== false; // default true\n\n function getClientOpts(): ClientCookieOptions {\n return {\n path: resolvedOptions.path,\n domain: resolvedOptions.domain,\n maxAge: resolvedOptions.maxAge,\n expires: resolvedOptions.expires,\n sameSite: resolvedOptions.sameSite,\n secure: resolvedOptions.secure,\n };\n }\n\n const base: ServerOnlyCookieDefinition<T> = {\n name,\n options: resolvedOptions,\n codec,\n\n get(): T {\n const serverJar = tryGetServerCookieJar();\n if (serverJar) {\n return codec.parse(serverJar.get(name));\n }\n // Client path\n if (isHttpOnly) {\n throw new Error(\n `[timber] defineCookie('${name}').get() cannot be used with httpOnly cookies — ` +\n `the browser cannot access them. Set httpOnly: false to enable client access.`\n );\n }\n const raw = getCookieValue(name);\n return codec.parse(raw);\n },\n\n set(value: T): void {\n const serverJar = tryGetServerCookieJar();\n if (serverJar) {\n const serialized = codec.serialize(value);\n if (serialized === null) {\n serverJar.delete(name, {\n path: resolvedOptions.path,\n domain: resolvedOptions.domain,\n });\n } else {\n serverJar.set(name, serialized, resolvedOptions);\n }\n return;\n }\n // Client path\n if (isHttpOnly) {\n throw new Error(\n `[timber] defineCookie('${name}').set() cannot be used with httpOnly cookies — ` +\n `the browser cannot access them. Set httpOnly: false to enable client access.`\n );\n }\n const serialized = codec.serialize(value);\n if (serialized === null) {\n deleteClientCookie(name, getClientOpts());\n } else {\n setClientCookie(name, serialized, getClientOpts());\n }\n },\n\n delete(): void {\n const serverJar = tryGetServerCookieJar();\n if (serverJar) {\n serverJar.delete(name, {\n path: resolvedOptions.path,\n domain: resolvedOptions.domain,\n });\n return;\n }\n // Client path\n if (isHttpOnly) {\n throw new Error(\n `[timber] defineCookie('${name}').delete() cannot be used with httpOnly cookies — ` +\n `the browser cannot access them. Set httpOnly: false to enable client access.`\n );\n }\n deleteClientCookie(name, getClientOpts());\n },\n };\n\n if (isHttpOnly) {\n return base as HttpOnly extends false ? CookieDefinition<T> : ServerOnlyCookieDefinition<T>;\n }\n\n // httpOnly: false — add useCookie client hook\n const full: CookieDefinition<T> = {\n ...base,\n\n useCookie(): [T, (value: T) => void, () => void] {\n const clientOpts = getClientOpts();\n const [raw, setRaw, deleteRaw] = useRawCookie(name, clientOpts);\n const parsed = codec.parse(raw);\n\n const setTyped = (value: T): void => {\n const serialized = codec.serialize(value);\n if (serialized === null) {\n deleteRaw();\n } else {\n setRaw(serialized);\n }\n };\n\n return [parsed, setTyped, deleteRaw];\n },\n };\n\n return full as HttpOnly extends false ? CookieDefinition<T> : ServerOnlyCookieDefinition<T>;\n}\n","/**\n * jsonCookieCodec — Codec helper for storing JSON-serializable values in\n * cookies.\n *\n * The codec is intentionally minimal: `JSON.stringify` on serialize,\n * `JSON.parse` on parse. The framework handles the URL encoding /\n * decoding around it (see design/29-cookies.md §\"Encoding Contract\"):\n *\n * defineCookie.setCookie(value)\n * → codec.serialize: JSON.stringify → '{\"a\":1}'\n * → cookies().set: encodeURIComponent → '%7B%22a%22%3A1%7D'\n * → wire: Set-Cookie: prefs=%7B%22a%22%3A1%7D\n *\n * defineCookie.getCookie()\n * → wire: Cookie: prefs=%7B%22a%22%3A1%7D\n * → parseCookieHeader: decodeURIComponent → '{\"a\":1}'\n * → codec.parse: JSON.parse → { a: 1 }\n *\n * The same chain works on the client: `useCookie` auto-encodes on writes\n * and auto-decodes on reads, so `jsonCookieCodec` composes with both the\n * server `defineCookie` methods and the client `useCookie` hook with no\n * environment-specific branches.\n *\n * Parsing is total: any non-JSON value (or `undefined`) returns the\n * supplied default. This matches the \"never crash on user-controlled\n * cookie input\" semantics that `fromSchema` uses for typed search params.\n *\n * ```ts\n * import { defineCookie, jsonCookieCodec } from '@timber-js/app/cookies';\n *\n * interface Prefs { lang: string; fontSize: number }\n *\n * export const prefsCookie = defineCookie('prefs', {\n * codec: jsonCookieCodec<Prefs>({ lang: 'en', fontSize: 16 }),\n * httpOnly: false,\n * maxAge: 60 * 60 * 24 * 365,\n * });\n *\n * await prefsCookie.setCookie({ lang: 'fr', fontSize: 18 });\n * ```\n */\n\nimport type { Codec } from '../codec.js';\n\n/**\n * Build a CookieCodec that JSON-encodes the value. The framework's\n * cookie write path then URL-encodes the JSON string into a valid\n * `cookie-octet` form, and the read path reverses both transforms.\n *\n * @param defaultValue - Returned by `parse` when the cookie is missing\n * or the stored value cannot be JSON-parsed. Optional — if omitted,\n * `parse` returns `undefined` on missing/malformed input.\n *\n * The default is **deep-cloned** on every fallback return via\n * `structuredClone`, so mutating the parsed result in one request\n * cannot leak into later requests that fall back to the same\n * default. This matters for long-lived server processes where a\n * codec is defined once at module load and shared across all\n * requests — without the clone, a user doing\n * `const prefs = prefsCookie.get(); prefs.lang = 'fr'` on a missing\n * cookie would mutate the module-level default and poison every\n * later fallback. See the \"shared mutable default\" regression test\n * in `tests/define-cookie.test.ts`.\n */\nexport function jsonCookieCodec<T>(defaultValue?: T): Codec<T> {\n // Resolve the fallback at call time, not capture time, so every\n // fallback return produces a fresh deep copy. structuredClone handles\n // nested objects, arrays, dates, maps, sets — everything\n // JSON-serializable plus more. For primitives and undefined,\n // structuredClone is effectively a no-op.\n const cloneDefault = (): T => {\n if (defaultValue === undefined || defaultValue === null) {\n return defaultValue as T;\n }\n // structuredClone is a Node built-in since Node 17, available in\n // all supported runtimes.\n return structuredClone(defaultValue);\n };\n\n return {\n parse(value: string | string[] | undefined): T {\n if (value === undefined || value === '') {\n return cloneDefault();\n }\n // Cookies are single-valued by name; defensively pick the last\n // entry if a Codec consumer somehow passes an array.\n const raw = Array.isArray(value) ? value[value.length - 1] : value;\n if (raw === undefined || raw === '') {\n return cloneDefault();\n }\n try {\n return JSON.parse(raw) as T;\n } catch {\n return cloneDefault();\n }\n },\n\n serialize(value: T): string | null {\n if (value === null || value === undefined) {\n return null;\n }\n return JSON.stringify(value);\n },\n };\n}\n"],"mappings":"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"}
|
package/dist/fonts/ast.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ast.d.ts","sourceRoot":"","sources":["../../src/fonts/ast.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAgB,MAAM,YAAY,CAAC;AAIhE,UAAU,OAAO;IACf,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAiID;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CA4DhF;AAiCD;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CA4CpF;AAID;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAc/F;AAmDD;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAAC,IAAI,EAAE,OAAO,GAAG,gBAAgB,GAAG,IAAI,CAGtF;AAED;;GAEG;AACH,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,OAAO,GAAG,eAAe,GAAG,IAAI,CAGpF;AA8GD,kEAAkE;AAClE,MAAM,WAAW,WAAW;IAC1B,kEAAkE;IAClE,SAAS,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB,+BAA+B;IAC/B,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC;IAC7B,4EAA4E;IAC5E,UAAU,EAAE,OAAO,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;CACtD;AAED,kEAAkE;AAClE,MAAM,WAAW,YAAY;IAC3B,6CAA6C;IAC7C,OAAO,EAAE,WAAW,CAAC;IACrB;;;OAGG;IACH,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,wEAAwE;IACxE,UAAU,EAAE,OAAO,CAAC;IACpB;;;;;OAKG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAC;IACb,uDAAuD;IACvD,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,sEAAsE;AACtE,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,0DAA0D;IAC1D,mBAAmB,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3D,qDAAqD;IACrD,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B;;;OAGG;IACH,WAAW,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpE;
|
|
1
|
+
{"version":3,"file":"ast.d.ts","sourceRoot":"","sources":["../../src/fonts/ast.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAgB,MAAM,YAAY,CAAC;AAIhE,UAAU,OAAO;IACf,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAiID;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CA4DhF;AAiCD;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CA4CpF;AAID;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAc/F;AAmDD;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAAC,IAAI,EAAE,OAAO,GAAG,gBAAgB,GAAG,IAAI,CAGtF;AAED;;GAEG;AACH,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,OAAO,GAAG,eAAe,GAAG,IAAI,CAGpF;AA8GD,kEAAkE;AAClE,MAAM,WAAW,WAAW;IAC1B,kEAAkE;IAClE,SAAS,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB,+BAA+B;IAC/B,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC;IAC7B,4EAA4E;IAC5E,UAAU,EAAE,OAAO,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;CACtD;AAED,kEAAkE;AAClE,MAAM,WAAW,YAAY;IAC3B,6CAA6C;IAC7C,OAAO,EAAE,WAAW,CAAC;IACrB;;;OAGG;IACH,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,wEAAwE;IACxE,UAAU,EAAE,OAAO,CAAC;IACpB;;;;;OAKG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAC;IACb,uDAAuD;IACvD,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,sEAAsE;AACtE,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,0DAA0D;IAC1D,mBAAmB,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3D,qDAAqD;IACrD,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B;;;OAGG;IACH,WAAW,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpE;AAkFD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAgIrE"}
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { t as formatSize } from "./_chunks/format-Bcn-Iv1x.js";
|
|
1
|
+
import { n as setViteServer } from "./_chunks/warnings-B30wpfaS.js";
|
|
2
|
+
import { h as swallow } from "./_chunks/logger-DDmK5skc.js";
|
|
3
|
+
import { i as scanRoutes, n as collectInterceptionRewrites, r as generateRouteMap, t as collectLeafRoutes } from "./_chunks/walkers-DQn5NNrf.js";
|
|
4
|
+
import { t as formatSize } from "./_chunks/format-CYBGxKtc.js";
|
|
6
5
|
import { dirname, extname, join, normalize, resolve } from "node:path";
|
|
7
6
|
import { createRequire } from "node:module";
|
|
8
7
|
import react, { reactCompilerPreset } from "@vitejs/plugin-react";
|
|
@@ -15,6 +14,37 @@ import { createHash, randomUUID } from "node:crypto";
|
|
|
15
14
|
import { parseAst } from "vite";
|
|
16
15
|
import { performance as performance$1 } from "node:perf_hooks";
|
|
17
16
|
import http from "node:http";
|
|
17
|
+
//#region \0rolldown/runtime.js
|
|
18
|
+
var __defProp = Object.defineProperty;
|
|
19
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
20
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
21
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
22
|
+
var __esmMin = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
23
|
+
var __exportAll = (all, no_symbols) => {
|
|
24
|
+
let target = {};
|
|
25
|
+
for (var name in all) __defProp(target, name, {
|
|
26
|
+
get: all[name],
|
|
27
|
+
enumerable: true
|
|
28
|
+
});
|
|
29
|
+
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
30
|
+
return target;
|
|
31
|
+
};
|
|
32
|
+
var __copyProps = (to, from, except, desc) => {
|
|
33
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
34
|
+
key = keys[i];
|
|
35
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
36
|
+
get: ((k) => from[k]).bind(null, key),
|
|
37
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
return to;
|
|
41
|
+
};
|
|
42
|
+
var __toCommonJS = (mod) => __hasOwnProp.call(mod, "module.exports") ? mod["module.exports"] : __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
43
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, { get: (a, b) => (typeof require !== "undefined" ? require : a)[b] }) : x)(function(x) {
|
|
44
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
45
|
+
throw Error("Calling `require` for \"" + x + "\" in an environment that doesn't expose the `require` function. See https://rolldown.rs/in-depth/bundling-cjs#require-external-modules for more details.");
|
|
46
|
+
});
|
|
47
|
+
//#endregion
|
|
18
48
|
//#region src/plugins/content.ts
|
|
19
49
|
var CONFIG_FILE_NAMES$1 = [
|
|
20
50
|
"content-collections.ts",
|
|
@@ -3356,6 +3386,24 @@ var LOCAL_FONT_SOURCES = new Set([
|
|
|
3356
3386
|
"@timber-js/app/fonts/local",
|
|
3357
3387
|
"next/font/local"
|
|
3358
3388
|
]);
|
|
3389
|
+
function isImportDeclaration(node) {
|
|
3390
|
+
return node.type === "ImportDeclaration";
|
|
3391
|
+
}
|
|
3392
|
+
function isVariableDeclaration(node) {
|
|
3393
|
+
return node.type === "VariableDeclaration";
|
|
3394
|
+
}
|
|
3395
|
+
function isExpressionStatement(node) {
|
|
3396
|
+
return node.type === "ExpressionStatement";
|
|
3397
|
+
}
|
|
3398
|
+
function isExportNamedDeclaration(node) {
|
|
3399
|
+
return node.type === "ExportNamedDeclaration";
|
|
3400
|
+
}
|
|
3401
|
+
function isCallExpression(node) {
|
|
3402
|
+
return node.type === "CallExpression";
|
|
3403
|
+
}
|
|
3404
|
+
function isIdentifier(node) {
|
|
3405
|
+
return node.type === "Identifier";
|
|
3406
|
+
}
|
|
3359
3407
|
/**
|
|
3360
3408
|
* Parse a full source file and find all font imports and call sites.
|
|
3361
3409
|
*
|
|
@@ -3371,7 +3419,7 @@ function findFontCallSites(source) {
|
|
|
3371
3419
|
const bindings = [];
|
|
3372
3420
|
const importNodesToRemove = [];
|
|
3373
3421
|
for (const stmt of program.body) {
|
|
3374
|
-
if (stmt
|
|
3422
|
+
if (!isImportDeclaration(stmt)) continue;
|
|
3375
3423
|
const importDecl = stmt;
|
|
3376
3424
|
const specSource = importDecl.source.value;
|
|
3377
3425
|
let provider = null;
|
|
@@ -3391,8 +3439,8 @@ function findFontCallSites(source) {
|
|
|
3391
3439
|
importNode: importDecl
|
|
3392
3440
|
});
|
|
3393
3441
|
importNodesToRemove.push({
|
|
3394
|
-
start:
|
|
3395
|
-
end:
|
|
3442
|
+
start: stmt.start,
|
|
3443
|
+
end: stmt.end
|
|
3396
3444
|
});
|
|
3397
3445
|
}
|
|
3398
3446
|
if (bindings.length === 0) return null;
|
|
@@ -3400,39 +3448,36 @@ function findFontCallSites(source) {
|
|
|
3400
3448
|
const callSites = [];
|
|
3401
3449
|
let dynamicCall = null;
|
|
3402
3450
|
for (const stmt of program.body) {
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
dynamicCall = `${calleeName}(${source.slice(argStart, argEnd)})`;
|
|
3416
|
-
}
|
|
3417
|
-
continue;
|
|
3451
|
+
const effectiveStmt = isExportNamedDeclaration(stmt) && stmt.declaration ? stmt.declaration : stmt;
|
|
3452
|
+
if (isVariableDeclaration(effectiveStmt)) for (const declarator of effectiveStmt.declarations) {
|
|
3453
|
+
if (!declarator.init) continue;
|
|
3454
|
+
if (!isCallExpression(declarator.init)) continue;
|
|
3455
|
+
const call = declarator.init;
|
|
3456
|
+
const site = matchCallExpression(call, bindingsByName, source);
|
|
3457
|
+
if (!site) continue;
|
|
3458
|
+
if (site === "dynamic") {
|
|
3459
|
+
if (!dynamicCall && isIdentifier(call.callee)) {
|
|
3460
|
+
const argStart = call.arguments[0].start;
|
|
3461
|
+
const argEnd = call.arguments[0].end;
|
|
3462
|
+
dynamicCall = `${call.callee.name}(${source.slice(argStart, argEnd)})`;
|
|
3418
3463
|
}
|
|
3419
|
-
|
|
3420
|
-
const { line, column } = offsetToLineColumn(source, call.start);
|
|
3421
|
-
callSites.push({
|
|
3422
|
-
binding: site.binding,
|
|
3423
|
-
assignedName,
|
|
3424
|
-
configNode: site.configNode,
|
|
3425
|
-
replaceStart: call.start,
|
|
3426
|
-
replaceEnd: call.end,
|
|
3427
|
-
line,
|
|
3428
|
-
column
|
|
3429
|
-
});
|
|
3464
|
+
continue;
|
|
3430
3465
|
}
|
|
3466
|
+
const assignedName = isIdentifier(declarator.id) ? declarator.id.name : null;
|
|
3467
|
+
const { line, column } = offsetToLineColumn(source, call.start);
|
|
3468
|
+
callSites.push({
|
|
3469
|
+
binding: site.binding,
|
|
3470
|
+
assignedName,
|
|
3471
|
+
configNode: site.configNode,
|
|
3472
|
+
replaceStart: call.start,
|
|
3473
|
+
replaceEnd: call.end,
|
|
3474
|
+
line,
|
|
3475
|
+
column
|
|
3476
|
+
});
|
|
3431
3477
|
}
|
|
3432
|
-
if (
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
const call = exprStmt.expression;
|
|
3478
|
+
if (isExpressionStatement(effectiveStmt)) {
|
|
3479
|
+
if (isCallExpression(effectiveStmt.expression)) {
|
|
3480
|
+
const call = effectiveStmt.expression;
|
|
3436
3481
|
const site = matchCallExpression(call, bindingsByName, source);
|
|
3437
3482
|
if (site && site !== "dynamic") {
|
|
3438
3483
|
const { line, column } = offsetToLineColumn(source, call.start);
|
|
@@ -3440,16 +3485,15 @@ function findFontCallSites(source) {
|
|
|
3440
3485
|
binding: site.binding,
|
|
3441
3486
|
assignedName: null,
|
|
3442
3487
|
configNode: site.configNode,
|
|
3443
|
-
replaceStart:
|
|
3444
|
-
replaceEnd:
|
|
3488
|
+
replaceStart: effectiveStmt.start,
|
|
3489
|
+
replaceEnd: effectiveStmt.end,
|
|
3445
3490
|
line,
|
|
3446
3491
|
column
|
|
3447
3492
|
});
|
|
3448
|
-
} else if (site === "dynamic" && !dynamicCall) {
|
|
3449
|
-
const calleeName = call.callee.name;
|
|
3493
|
+
} else if (site === "dynamic" && !dynamicCall && isIdentifier(call.callee)) {
|
|
3450
3494
|
const argStart = call.arguments[0].start;
|
|
3451
3495
|
const argEnd = call.arguments[0].end;
|
|
3452
|
-
dynamicCall = `${
|
|
3496
|
+
dynamicCall = `${call.callee.name}(${source.slice(argStart, argEnd)})`;
|
|
3453
3497
|
}
|
|
3454
3498
|
}
|
|
3455
3499
|
}
|
|
@@ -3523,7 +3567,7 @@ function walkForNestedFontCalls(node, bindings, source, out, isNested) {
|
|
|
3523
3567
|
* if the callee doesn't match any font binding.
|
|
3524
3568
|
*/
|
|
3525
3569
|
function matchCallExpression(call, bindings, _source) {
|
|
3526
|
-
if (call.callee
|
|
3570
|
+
if (!isIdentifier(call.callee)) return null;
|
|
3527
3571
|
const calleeName = call.callee.name;
|
|
3528
3572
|
const binding = bindings.get(calleeName);
|
|
3529
3573
|
if (!binding) return null;
|
|
@@ -7132,6 +7176,6 @@ function timber(config) {
|
|
|
7132
7176
|
];
|
|
7133
7177
|
}
|
|
7134
7178
|
//#endregion
|
|
7135
|
-
export { timber as default, timber, defineConfig };
|
|
7179
|
+
export { timber as default, timber, defineConfig, __exportAll as t };
|
|
7136
7180
|
|
|
7137
7181
|
//# sourceMappingURL=index.js.map
|