effect-start 0.20.0 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +6 -6
- package/src/ContentNegotiation.ts +8 -9
- package/src/Cookies.ts +429 -0
- package/src/Development.ts +1 -1
- package/src/FileRouter.ts +1 -1
- package/src/FileRouterCodegen.ts +1 -1
- package/src/FileSystem.ts +403 -0
- package/src/PlatformError.ts +3 -3
- package/src/Socket.ts +48 -0
- package/src/Start.ts +1 -2
- package/src/bun/BunServer.ts +58 -32
- package/src/bundler/BundleFiles.ts +1 -1
- package/src/experimental/EncryptedCookies.ts +3 -34
- package/src/experimental/index.ts +0 -1
- package/src/hyper/HyperHtml.ts +4 -0
- package/src/node/NodeFileSystem.ts +2 -16
- package/src/testing/index.ts +0 -1
- package/src/x/cloudflare/CloudflareTunnel.ts +28 -23
- package/src/HttpAppExtra.ts +0 -478
- package/src/HttpUtils.ts +0 -17
- package/src/bun/BunPlatformHttpServer.ts +0 -88
- package/src/bun/BunServerRequest.ts +0 -396
- package/src/bundler/BundleHttp.ts +0 -259
- package/src/experimental/SseHttpResponse.ts +0 -55
- package/src/middlewares/BasicAuthMiddleware.ts +0 -36
- package/src/middlewares/index.ts +0 -1
- package/src/testing/TestHttpClient.ts +0 -148
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "effect-start",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"exports": {
|
|
@@ -34,11 +34,6 @@
|
|
|
34
34
|
"types": "./dist/x/tailwind/plugin.d.ts",
|
|
35
35
|
"default": "./dist/x/tailwind/plugin.js"
|
|
36
36
|
},
|
|
37
|
-
"./middlewares": {
|
|
38
|
-
"bun": "./src/middlewares/index.ts",
|
|
39
|
-
"types": "./dist/middlewares/index.d.ts",
|
|
40
|
-
"default": "./dist/middlewares/index.js"
|
|
41
|
-
},
|
|
42
37
|
"./Unique": {
|
|
43
38
|
"bun": "./src/Unique.ts",
|
|
44
39
|
"types": "./dist/Unique.d.ts",
|
|
@@ -49,6 +44,11 @@
|
|
|
49
44
|
"types": "./dist/FileRouter.d.ts",
|
|
50
45
|
"default": "./dist/FileRouter.js"
|
|
51
46
|
},
|
|
47
|
+
"./FileSystem": {
|
|
48
|
+
"bun": "./src/FileSystem.ts",
|
|
49
|
+
"types": "./dist/FileSystem.d.ts",
|
|
50
|
+
"default": "./dist/FileSystem.js"
|
|
51
|
+
},
|
|
52
52
|
"./experimental": {
|
|
53
53
|
"bun": "./src/experimental/index.ts",
|
|
54
54
|
"types": "./dist/experimental/index.d.ts",
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
* Based on {@link https://github.com/jshttp/negotiator}
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import type * as Headers from "@effect/platform/Headers"
|
|
7
6
|
|
|
8
7
|
interface ParsedSpec {
|
|
9
8
|
value: string
|
|
@@ -506,37 +505,37 @@ export function charset(accept: string, available?: string[]): string[] {
|
|
|
506
505
|
}
|
|
507
506
|
|
|
508
507
|
export function headerMedia(
|
|
509
|
-
headers: Headers
|
|
508
|
+
headers: Headers,
|
|
510
509
|
available?: string[],
|
|
511
510
|
): string[] {
|
|
512
|
-
const accept = headers
|
|
511
|
+
const accept = headers.get("accept")
|
|
513
512
|
if (!accept) return []
|
|
514
513
|
return media(accept, available)
|
|
515
514
|
}
|
|
516
515
|
|
|
517
516
|
export function headerLanguage(
|
|
518
|
-
headers: Headers
|
|
517
|
+
headers: Headers,
|
|
519
518
|
available?: string[],
|
|
520
519
|
): string[] {
|
|
521
|
-
const accept = headers
|
|
520
|
+
const accept = headers.get("accept-language")
|
|
522
521
|
if (!accept) return []
|
|
523
522
|
return language(accept, available)
|
|
524
523
|
}
|
|
525
524
|
|
|
526
525
|
export function headerEncoding(
|
|
527
|
-
headers: Headers
|
|
526
|
+
headers: Headers,
|
|
528
527
|
available?: string[],
|
|
529
528
|
): string[] {
|
|
530
|
-
const accept = headers
|
|
529
|
+
const accept = headers.get("accept-encoding")
|
|
531
530
|
if (!accept) return []
|
|
532
531
|
return encoding(accept, available)
|
|
533
532
|
}
|
|
534
533
|
|
|
535
534
|
export function headerCharset(
|
|
536
|
-
headers: Headers
|
|
535
|
+
headers: Headers,
|
|
537
536
|
available?: string[],
|
|
538
537
|
): string[] {
|
|
539
|
-
const accept = headers
|
|
538
|
+
const accept = headers.get("accept-charset")
|
|
540
539
|
if (!accept) return []
|
|
541
540
|
return charset(accept, available)
|
|
542
541
|
}
|
package/src/Cookies.ts
ADDED
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Minimal Cookies management adapted from @effect/platform
|
|
3
|
+
* We'll aim for full compatbility when it stabilizes.
|
|
4
|
+
*/
|
|
5
|
+
import * as Duration from "effect/Duration"
|
|
6
|
+
import * as Inspectable from "effect/Inspectable"
|
|
7
|
+
import * as Option from "effect/Option"
|
|
8
|
+
import * as Pipeable from "effect/Pipeable"
|
|
9
|
+
import * as Predicate from "effect/Predicate"
|
|
10
|
+
import type * as Types from "effect/Types"
|
|
11
|
+
|
|
12
|
+
export const TypeId: unique symbol = Symbol.for(
|
|
13
|
+
"effect-start/Cookies",
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
export type TypeId = typeof TypeId
|
|
17
|
+
|
|
18
|
+
export const isCookies = (u: unknown): u is Cookies =>
|
|
19
|
+
Predicate.hasProperty(u, TypeId)
|
|
20
|
+
|
|
21
|
+
export interface Cookies extends Pipeable.Pipeable, Inspectable.Inspectable {
|
|
22
|
+
readonly [TypeId]: TypeId
|
|
23
|
+
readonly cookies: Record<string, Cookie>
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const CookieTypeId: unique symbol = Symbol.for(
|
|
27
|
+
"effect-start/Cookies/Cookie",
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
export type CookieTypeId = typeof CookieTypeId
|
|
31
|
+
|
|
32
|
+
export interface Cookie extends Inspectable.Inspectable {
|
|
33
|
+
readonly [CookieTypeId]: CookieTypeId
|
|
34
|
+
readonly name: string
|
|
35
|
+
readonly value: string
|
|
36
|
+
readonly valueEncoded: string
|
|
37
|
+
readonly options?: {
|
|
38
|
+
readonly domain?: string | undefined
|
|
39
|
+
readonly expires?: Date | undefined
|
|
40
|
+
readonly maxAge?: Duration.DurationInput | undefined
|
|
41
|
+
readonly path?: string | undefined
|
|
42
|
+
readonly priority?: "low" | "medium" | "high" | undefined
|
|
43
|
+
readonly httpOnly?: boolean | undefined
|
|
44
|
+
readonly secure?: boolean | undefined
|
|
45
|
+
readonly partitioned?: boolean | undefined
|
|
46
|
+
readonly sameSite?:
|
|
47
|
+
// send with top-level navigations and GET requests from third-party sites
|
|
48
|
+
| "lax"
|
|
49
|
+
// only send with same-site requests
|
|
50
|
+
| "strict"
|
|
51
|
+
// send with all requests (requires Secure)
|
|
52
|
+
| "none"
|
|
53
|
+
| undefined
|
|
54
|
+
} | undefined
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const CookiesProto: Omit<Cookies, "cookies"> = {
|
|
58
|
+
[TypeId]: TypeId,
|
|
59
|
+
...Inspectable.BaseProto,
|
|
60
|
+
toJSON(this: Cookies) {
|
|
61
|
+
return {
|
|
62
|
+
_id: "effect-start/Cookies",
|
|
63
|
+
cookies: Object.fromEntries(
|
|
64
|
+
Object.entries(this.cookies).map(([k, v]) => [k, v.toJSON()]),
|
|
65
|
+
),
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
pipe() {
|
|
69
|
+
return Pipeable.pipeArguments(this, arguments)
|
|
70
|
+
},
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const CookieProto = {
|
|
74
|
+
[CookieTypeId]: CookieTypeId,
|
|
75
|
+
...Inspectable.BaseProto,
|
|
76
|
+
toJSON(this: Cookie) {
|
|
77
|
+
return {
|
|
78
|
+
_id: "effect-start/Cookies/Cookie",
|
|
79
|
+
name: this.name,
|
|
80
|
+
value: this.value,
|
|
81
|
+
options: this.options,
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const makeCookiesFromRecord = (
|
|
87
|
+
cookies: Record<string, Cookie>,
|
|
88
|
+
): Cookies => {
|
|
89
|
+
const self = Object.create(CookiesProto)
|
|
90
|
+
self.cookies = cookies
|
|
91
|
+
return self
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const cookieFromParts = (
|
|
95
|
+
name: string,
|
|
96
|
+
value: string,
|
|
97
|
+
valueEncoded: string,
|
|
98
|
+
options?: Cookie["options"],
|
|
99
|
+
): Cookie =>
|
|
100
|
+
Object.assign(Object.create(CookieProto), {
|
|
101
|
+
name,
|
|
102
|
+
value,
|
|
103
|
+
valueEncoded,
|
|
104
|
+
options,
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
export const empty: Cookies = makeCookiesFromRecord({})
|
|
108
|
+
|
|
109
|
+
export const fromIterable = (cookies: Iterable<Cookie>): Cookies => {
|
|
110
|
+
const record: Record<string, Cookie> = {}
|
|
111
|
+
for (const cookie of cookies) {
|
|
112
|
+
record[cookie.name] = cookie
|
|
113
|
+
}
|
|
114
|
+
return makeCookiesFromRecord(record)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export const fromSetCookie = (
|
|
118
|
+
headers: Iterable<string> | string,
|
|
119
|
+
): Cookies => {
|
|
120
|
+
const arrayHeaders = typeof headers === "string" ? [headers] : headers
|
|
121
|
+
const cookies: Array<Cookie> = []
|
|
122
|
+
for (const header of arrayHeaders) {
|
|
123
|
+
const cookie = parseSetCookie(header.trim())
|
|
124
|
+
if (Option.isSome(cookie)) {
|
|
125
|
+
cookies.push(cookie.value)
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return fromIterable(cookies)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export const unsafeMakeCookie = (
|
|
132
|
+
name: string,
|
|
133
|
+
value: string,
|
|
134
|
+
options?: Cookie["options"] | undefined,
|
|
135
|
+
): Cookie => cookieFromParts(name, value, encodeURIComponent(value), options)
|
|
136
|
+
|
|
137
|
+
export const isEmpty = (self: Cookies): boolean => {
|
|
138
|
+
for (const _ in self.cookies) return false
|
|
139
|
+
return true
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export const get = (
|
|
143
|
+
self: Cookies,
|
|
144
|
+
name: string,
|
|
145
|
+
): Option.Option<Cookie> =>
|
|
146
|
+
name in self.cookies ? Option.some(self.cookies[name]) : Option.none()
|
|
147
|
+
|
|
148
|
+
export const getValue = (
|
|
149
|
+
self: Cookies,
|
|
150
|
+
name: string,
|
|
151
|
+
): Option.Option<string> =>
|
|
152
|
+
Option.map(get(self, name), (cookie) => cookie.value)
|
|
153
|
+
|
|
154
|
+
export const setCookie = (self: Cookies, cookie: Cookie): Cookies =>
|
|
155
|
+
makeCookiesFromRecord({ ...self.cookies, [cookie.name]: cookie })
|
|
156
|
+
|
|
157
|
+
export const unsafeSet = (
|
|
158
|
+
self: Cookies,
|
|
159
|
+
name: string,
|
|
160
|
+
value: string,
|
|
161
|
+
options?: Cookie["options"],
|
|
162
|
+
): Cookies => setCookie(self, unsafeMakeCookie(name, value, options))
|
|
163
|
+
|
|
164
|
+
export const unsafeSetAll = (
|
|
165
|
+
self: Cookies,
|
|
166
|
+
cookies: Iterable<
|
|
167
|
+
readonly [name: string, value: string, options?: Cookie["options"]]
|
|
168
|
+
>,
|
|
169
|
+
): Cookies => {
|
|
170
|
+
const record: Record<string, Cookie> = { ...self.cookies }
|
|
171
|
+
for (const [name, value, options] of cookies) {
|
|
172
|
+
record[name] = unsafeMakeCookie(name, value, options)
|
|
173
|
+
}
|
|
174
|
+
return makeCookiesFromRecord(record)
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export const remove = (self: Cookies, name: string): Cookies => {
|
|
178
|
+
const { [name]: _, ...rest } = self.cookies
|
|
179
|
+
return makeCookiesFromRecord(rest)
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export const merge = (self: Cookies, that: Cookies): Cookies =>
|
|
183
|
+
makeCookiesFromRecord({ ...self.cookies, ...that.cookies })
|
|
184
|
+
|
|
185
|
+
export function serializeCookie(self: Cookie): string {
|
|
186
|
+
let str = self.name + "=" + self.valueEncoded
|
|
187
|
+
|
|
188
|
+
if (self.options === undefined) {
|
|
189
|
+
return str
|
|
190
|
+
}
|
|
191
|
+
const options = self.options
|
|
192
|
+
|
|
193
|
+
if (options.maxAge !== undefined) {
|
|
194
|
+
const maxAge = Duration.toSeconds(options.maxAge)
|
|
195
|
+
str += "; Max-Age=" + Math.trunc(maxAge)
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (options.domain !== undefined) {
|
|
199
|
+
str += "; Domain=" + options.domain
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (options.path !== undefined) {
|
|
203
|
+
str += "; Path=" + options.path
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (options.priority !== undefined) {
|
|
207
|
+
switch (options.priority) {
|
|
208
|
+
case "low":
|
|
209
|
+
str += "; Priority=Low"
|
|
210
|
+
break
|
|
211
|
+
case "medium":
|
|
212
|
+
str += "; Priority=Medium"
|
|
213
|
+
break
|
|
214
|
+
case "high":
|
|
215
|
+
str += "; Priority=High"
|
|
216
|
+
break
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
if (options.expires !== undefined) {
|
|
221
|
+
str += "; Expires=" + options.expires.toUTCString()
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (options.httpOnly) {
|
|
225
|
+
str += "; HttpOnly"
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (options.secure) {
|
|
229
|
+
str += "; Secure"
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
if (options.partitioned) {
|
|
233
|
+
str += "; Partitioned"
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
if (options.sameSite !== undefined) {
|
|
237
|
+
switch (options.sameSite) {
|
|
238
|
+
case "lax":
|
|
239
|
+
str += "; SameSite=Lax"
|
|
240
|
+
break
|
|
241
|
+
case "strict":
|
|
242
|
+
str += "; SameSite=Strict"
|
|
243
|
+
break
|
|
244
|
+
case "none":
|
|
245
|
+
str += "; SameSite=None"
|
|
246
|
+
break
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
return str
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export const toCookieHeader = (self: Cookies): string =>
|
|
254
|
+
Object
|
|
255
|
+
.values(self.cookies)
|
|
256
|
+
.map((cookie) => `${cookie.name}=${cookie.valueEncoded}`)
|
|
257
|
+
.join("; ")
|
|
258
|
+
|
|
259
|
+
export const toRecord = (self: Cookies): Record<string, string> => {
|
|
260
|
+
const record: Record<string, string> = {}
|
|
261
|
+
for (const cookie of Object.values(self.cookies)) {
|
|
262
|
+
record[cookie.name] = cookie.value
|
|
263
|
+
}
|
|
264
|
+
return record
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
export const toSetCookieHeaders = (self: Cookies): Array<string> =>
|
|
268
|
+
Object.values(self.cookies).map(serializeCookie)
|
|
269
|
+
|
|
270
|
+
export function parseHeader(header: string): Record<string, string> {
|
|
271
|
+
const result: Record<string, string> = {}
|
|
272
|
+
|
|
273
|
+
const strLen = header.length
|
|
274
|
+
let pos = 0
|
|
275
|
+
let terminatorPos = 0
|
|
276
|
+
|
|
277
|
+
while (true) {
|
|
278
|
+
if (terminatorPos === strLen) break
|
|
279
|
+
terminatorPos = header.indexOf(";", pos)
|
|
280
|
+
if (terminatorPos === -1) terminatorPos = strLen
|
|
281
|
+
|
|
282
|
+
let eqIdx = header.indexOf("=", pos)
|
|
283
|
+
if (eqIdx === -1) break
|
|
284
|
+
if (eqIdx > terminatorPos) {
|
|
285
|
+
pos = terminatorPos + 1
|
|
286
|
+
continue
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
const key = header.substring(pos, eqIdx++).trim()
|
|
290
|
+
if (result[key] === undefined) {
|
|
291
|
+
const val = header.charCodeAt(eqIdx) === 0x22
|
|
292
|
+
? header.substring(eqIdx + 1, terminatorPos - 1).trim()
|
|
293
|
+
: header.substring(eqIdx, terminatorPos).trim()
|
|
294
|
+
|
|
295
|
+
result[key] = !(val.indexOf("%") === -1)
|
|
296
|
+
? tryDecodeURIComponent(val)
|
|
297
|
+
: val
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
pos = terminatorPos + 1
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
return result
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// eslint-disable-next-line no-control-regex
|
|
307
|
+
const fieldContentRegExp = /^[\u0009\u0020-\u007e\u0080-\u00ff]+$/
|
|
308
|
+
|
|
309
|
+
function parseSetCookie(header: string): Option.Option<Cookie> {
|
|
310
|
+
const parts = header
|
|
311
|
+
.split(";")
|
|
312
|
+
.map((_) => _.trim())
|
|
313
|
+
.filter((_) => _ !== "")
|
|
314
|
+
if (parts.length === 0) {
|
|
315
|
+
return Option.none()
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
const firstEqual = parts[0].indexOf("=")
|
|
319
|
+
if (firstEqual === -1) {
|
|
320
|
+
return Option.none()
|
|
321
|
+
}
|
|
322
|
+
const name = parts[0].slice(0, firstEqual)
|
|
323
|
+
if (!fieldContentRegExp.test(name)) {
|
|
324
|
+
return Option.none()
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
const valueEncoded = parts[0].slice(firstEqual + 1)
|
|
328
|
+
const value = tryDecodeURIComponent(valueEncoded)
|
|
329
|
+
|
|
330
|
+
if (parts.length === 1) {
|
|
331
|
+
return Option.some(cookieFromParts(name, value, valueEncoded))
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
const options: Types.Mutable<Cookie["options"]> = {}
|
|
335
|
+
|
|
336
|
+
for (let i = 1; i < parts.length; i++) {
|
|
337
|
+
const part = parts[i]
|
|
338
|
+
const equalIndex = part.indexOf("=")
|
|
339
|
+
const key = equalIndex === -1 ? part : part.slice(0, equalIndex).trim()
|
|
340
|
+
const value = equalIndex === -1
|
|
341
|
+
? undefined
|
|
342
|
+
: part.slice(equalIndex + 1).trim()
|
|
343
|
+
|
|
344
|
+
switch (key.toLowerCase()) {
|
|
345
|
+
case "domain": {
|
|
346
|
+
if (value === undefined) break
|
|
347
|
+
const domain = value.trim().replace(/^\./, "")
|
|
348
|
+
if (domain) options.domain = domain
|
|
349
|
+
break
|
|
350
|
+
}
|
|
351
|
+
case "expires": {
|
|
352
|
+
if (value === undefined) break
|
|
353
|
+
const date = new Date(value)
|
|
354
|
+
if (!isNaN(date.getTime())) options.expires = date
|
|
355
|
+
break
|
|
356
|
+
}
|
|
357
|
+
case "max-age": {
|
|
358
|
+
if (value === undefined) break
|
|
359
|
+
const maxAge = parseInt(value, 10)
|
|
360
|
+
if (!isNaN(maxAge)) options.maxAge = Duration.seconds(maxAge)
|
|
361
|
+
break
|
|
362
|
+
}
|
|
363
|
+
case "path": {
|
|
364
|
+
if (value === undefined) break
|
|
365
|
+
if (value[0] === "/") options.path = value
|
|
366
|
+
break
|
|
367
|
+
}
|
|
368
|
+
case "priority": {
|
|
369
|
+
if (value === undefined) break
|
|
370
|
+
switch (value.toLowerCase()) {
|
|
371
|
+
case "low":
|
|
372
|
+
options.priority = "low"
|
|
373
|
+
break
|
|
374
|
+
case "medium":
|
|
375
|
+
options.priority = "medium"
|
|
376
|
+
break
|
|
377
|
+
case "high":
|
|
378
|
+
options.priority = "high"
|
|
379
|
+
break
|
|
380
|
+
}
|
|
381
|
+
break
|
|
382
|
+
}
|
|
383
|
+
case "httponly": {
|
|
384
|
+
options.httpOnly = true
|
|
385
|
+
break
|
|
386
|
+
}
|
|
387
|
+
case "secure": {
|
|
388
|
+
options.secure = true
|
|
389
|
+
break
|
|
390
|
+
}
|
|
391
|
+
case "partitioned": {
|
|
392
|
+
options.partitioned = true
|
|
393
|
+
break
|
|
394
|
+
}
|
|
395
|
+
case "samesite": {
|
|
396
|
+
if (value === undefined) break
|
|
397
|
+
switch (value.toLowerCase()) {
|
|
398
|
+
case "lax":
|
|
399
|
+
options.sameSite = "lax"
|
|
400
|
+
break
|
|
401
|
+
case "strict":
|
|
402
|
+
options.sameSite = "strict"
|
|
403
|
+
break
|
|
404
|
+
case "none":
|
|
405
|
+
options.sameSite = "none"
|
|
406
|
+
break
|
|
407
|
+
}
|
|
408
|
+
break
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
return Option.some(
|
|
414
|
+
cookieFromParts(
|
|
415
|
+
name,
|
|
416
|
+
value,
|
|
417
|
+
valueEncoded,
|
|
418
|
+
Object.keys(options).length > 0 ? options : undefined,
|
|
419
|
+
),
|
|
420
|
+
)
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
const tryDecodeURIComponent = (str: string): string => {
|
|
424
|
+
try {
|
|
425
|
+
return decodeURIComponent(str)
|
|
426
|
+
} catch {
|
|
427
|
+
return str
|
|
428
|
+
}
|
|
429
|
+
}
|
package/src/Development.ts
CHANGED
package/src/FileRouter.ts
CHANGED
package/src/FileRouterCodegen.ts
CHANGED