effect-start 0.20.1 → 0.22.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/README.md +1 -4
- package/dist/Cookies.js +392 -0
- package/dist/FileSystem.js +131 -0
- package/dist/Socket.js +37 -0
- package/package.json +39 -40
- package/src/Commander.ts +73 -130
- package/src/ContentNegotiation.ts +68 -100
- package/src/Cookies.ts +408 -0
- package/src/Development.ts +48 -63
- package/src/Effectify.ts +222 -206
- package/src/Entity.ts +59 -86
- package/src/FilePathPattern.ts +5 -5
- package/src/FileRouter.ts +38 -63
- package/src/FileRouterCodegen.ts +64 -56
- package/src/FileSystem.ts +390 -0
- package/src/Http.ts +17 -50
- package/src/PathPattern.ts +33 -41
- package/src/PlatformError.ts +29 -50
- package/src/PlatformRuntime.ts +39 -47
- package/src/Route.ts +68 -187
- package/src/RouteBody.ts +45 -161
- package/src/RouteHook.ts +22 -45
- package/src/RouteHttp.ts +88 -142
- package/src/RouteHttpTracer.ts +25 -26
- package/src/RouteMount.ts +100 -238
- package/src/RouteSchema.ts +67 -201
- package/src/RouteSse.ts +28 -82
- package/src/RouteTree.ts +31 -79
- package/src/RouteTrie.ts +13 -32
- package/src/SchemaExtra.ts +3 -5
- package/src/Socket.ts +51 -0
- package/src/Start.ts +20 -21
- package/src/StreamExtra.ts +93 -96
- package/src/TuplePathPattern.ts +54 -43
- package/src/Unique.ts +9 -15
- package/src/Values.ts +26 -30
- package/src/bun/BunBundle.ts +27 -73
- package/src/bun/BunImportTrackerPlugin.ts +67 -65
- package/src/bun/BunRoute.ts +12 -31
- package/src/bun/BunRuntime.ts +3 -10
- package/src/bun/BunServer.ts +50 -60
- package/src/bun/BunVirtualFilesPlugin.ts +1 -4
- package/src/bun/_BunEnhancedResolve.ts +17 -42
- package/src/bun/_empty.html +0 -1
- package/src/bundler/Bundle.ts +20 -36
- package/src/bundler/BundleFiles.ts +36 -56
- package/src/client/Overlay.ts +1 -2
- package/src/client/ScrollState.ts +5 -9
- package/src/client/index.ts +10 -13
- package/src/datastar/actions/fetch.ts +29 -48
- package/src/datastar/actions/peek.ts +1 -5
- package/src/datastar/actions/setAll.ts +2 -2
- package/src/datastar/actions/toggleAll.ts +2 -2
- package/src/datastar/attributes/attr.ts +17 -18
- package/src/datastar/attributes/bind.ts +41 -61
- package/src/datastar/attributes/class.ts +2 -5
- package/src/datastar/attributes/computed.ts +2 -10
- package/src/datastar/attributes/effect.ts +1 -2
- package/src/datastar/attributes/indicator.ts +2 -8
- package/src/datastar/attributes/init.ts +2 -10
- package/src/datastar/attributes/jsonSignals.ts +1 -6
- package/src/datastar/attributes/on.ts +4 -13
- package/src/datastar/attributes/onIntersect.ts +10 -22
- package/src/datastar/attributes/onInterval.ts +2 -10
- package/src/datastar/attributes/onSignalPatch.ts +18 -28
- package/src/datastar/attributes/ref.ts +1 -2
- package/src/datastar/attributes/show.ts +1 -2
- package/src/datastar/attributes/signals.ts +1 -5
- package/src/datastar/attributes/style.ts +6 -12
- package/src/datastar/attributes/text.ts +1 -2
- package/src/datastar/engine.ts +102 -158
- package/src/datastar/index.ts +2 -2
- package/src/datastar/utils.ts +16 -51
- package/src/datastar/watchers/patchElements.ts +35 -93
- package/src/datastar/watchers/patchSignals.ts +1 -2
- package/src/experimental/EncryptedCookies.ts +81 -175
- package/src/experimental/index.ts +0 -1
- package/src/hyper/Hyper.ts +14 -33
- package/src/hyper/HyperHtml.ts +13 -10
- package/src/hyper/HyperNode.ts +2 -7
- package/src/hyper/HyperRoute.ts +2 -5
- package/src/hyper/jsx-runtime.ts +2 -10
- package/src/hyper/jsx.d.ts +171 -440
- package/src/lint/plugin.js +276 -0
- package/src/node/NodeFileSystem.ts +140 -202
- package/src/node/NodeUtils.ts +1 -3
- package/src/testing/TestLogger.ts +9 -22
- package/src/testing/index.ts +0 -1
- package/src/testing/utils.ts +30 -31
- package/src/x/cloudflare/CloudflareTunnel.ts +53 -65
- package/src/x/datastar/Datastar.ts +3 -10
- package/src/x/datastar/index.ts +1 -3
- package/src/x/datastar/jsx-datastar.d.ts +1 -4
- package/src/x/tailwind/TailwindPlugin.ts +119 -112
- package/src/x/tailwind/compile.ts +10 -33
- package/src/x/tailwind/plugin.ts +2 -2
- 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/src/Entity.ts
CHANGED
|
@@ -24,10 +24,7 @@ export type Headers = {
|
|
|
24
24
|
[header: string]: string | null | undefined
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
export interface Entity<
|
|
28
|
-
T = unknown,
|
|
29
|
-
E = never,
|
|
30
|
-
> extends Pipeable.Pipeable {
|
|
27
|
+
export interface Entity<T = unknown, E = never> extends Pipeable.Pipeable {
|
|
31
28
|
readonly [TypeId]: TypeId
|
|
32
29
|
readonly body: T
|
|
33
30
|
readonly headers: Headers
|
|
@@ -39,18 +36,21 @@ export interface Entity<
|
|
|
39
36
|
*/
|
|
40
37
|
readonly url: string | undefined
|
|
41
38
|
readonly status: number | undefined
|
|
42
|
-
readonly text: T extends string
|
|
39
|
+
readonly text: T extends string
|
|
40
|
+
? Effect.Effect<T, ParseResult.ParseError | E>
|
|
43
41
|
: Effect.Effect<string, ParseResult.ParseError | E>
|
|
44
|
-
readonly json: [T] extends [Effect.Effect<infer A, any, any>]
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
42
|
+
readonly json: [T] extends [Effect.Effect<infer A, any, any>]
|
|
43
|
+
? Effect.Effect<
|
|
44
|
+
A extends string | Uint8Array | ArrayBuffer ? unknown : A,
|
|
45
|
+
ParseResult.ParseError | E
|
|
46
|
+
>
|
|
48
47
|
: [T] extends [Stream.Stream<any, any, any>]
|
|
49
48
|
? Effect.Effect<unknown, ParseResult.ParseError | E>
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
49
|
+
: [T] extends [string | Uint8Array | ArrayBuffer]
|
|
50
|
+
? Effect.Effect<unknown, ParseResult.ParseError | E>
|
|
51
|
+
: [T] extends [Values.Json]
|
|
52
|
+
? Effect.Effect<T, ParseResult.ParseError | E>
|
|
53
|
+
: Effect.Effect<unknown, ParseResult.ParseError | E>
|
|
54
54
|
readonly bytes: Effect.Effect<Uint8Array, ParseResult.ParseError | E>
|
|
55
55
|
readonly stream: T extends Stream.Stream<infer A, infer E1, any>
|
|
56
56
|
? Stream.Stream<A, ParseResult.ParseError | E | E1>
|
|
@@ -82,9 +82,7 @@ function getText(
|
|
|
82
82
|
): Effect.Effect<string, ParseResult.ParseError | unknown> {
|
|
83
83
|
const v = self.body
|
|
84
84
|
if (StreamExtra.isStream(v)) {
|
|
85
|
-
return Stream.mkString(
|
|
86
|
-
Stream.decodeText(v as Stream.Stream<Uint8Array, unknown, never>),
|
|
87
|
-
)
|
|
85
|
+
return Stream.mkString(Stream.decodeText(v as Stream.Stream<Uint8Array, unknown, never>))
|
|
88
86
|
}
|
|
89
87
|
if (Effect.isEffect(v)) {
|
|
90
88
|
return Effect.flatMap(
|
|
@@ -201,63 +199,53 @@ function getBytes(
|
|
|
201
199
|
function getStream<A, E1, E2>(
|
|
202
200
|
self: Entity<Stream.Stream<A, E1, never>, E2>,
|
|
203
201
|
): Stream.Stream<A, ParseResult.ParseError | E1 | E2>
|
|
204
|
-
function getStream<T, E>(
|
|
205
|
-
|
|
206
|
-
): Stream.Stream<Uint8Array, ParseResult.ParseError | E>
|
|
207
|
-
function getStream(
|
|
208
|
-
self: Entity<unknown, unknown>,
|
|
209
|
-
): Stream.Stream<unknown, unknown> {
|
|
202
|
+
function getStream<T, E>(self: Entity<T, E>): Stream.Stream<Uint8Array, ParseResult.ParseError | E>
|
|
203
|
+
function getStream(self: Entity<unknown, unknown>): Stream.Stream<unknown, unknown> {
|
|
210
204
|
const v = self.body
|
|
211
205
|
if (StreamExtra.isStream(v)) {
|
|
212
206
|
return v as Stream.Stream<unknown, unknown, never>
|
|
213
207
|
}
|
|
214
208
|
if (Effect.isEffect(v)) {
|
|
215
209
|
return Stream.unwrap(
|
|
216
|
-
Effect.map(
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
return Stream.fromEffect(getBytes(make(inner)))
|
|
223
|
-
},
|
|
224
|
-
),
|
|
210
|
+
Effect.map(v as Effect.Effect<unknown, unknown, never>, (inner) => {
|
|
211
|
+
if (isEntity(inner)) {
|
|
212
|
+
return inner.stream
|
|
213
|
+
}
|
|
214
|
+
return Stream.fromEffect(getBytes(make(inner)))
|
|
215
|
+
}),
|
|
225
216
|
)
|
|
226
217
|
}
|
|
227
218
|
return Stream.fromEffect(getBytes(self))
|
|
228
219
|
}
|
|
229
220
|
|
|
230
|
-
const Proto: Proto = Object.defineProperties(
|
|
231
|
-
|
|
232
|
-
{
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
value: function(this: Entity) {
|
|
236
|
-
return Pipeable.pipeArguments(this, arguments)
|
|
237
|
-
},
|
|
221
|
+
const Proto: Proto = Object.defineProperties(Object.create(null), {
|
|
222
|
+
[TypeId]: { value: TypeId },
|
|
223
|
+
pipe: {
|
|
224
|
+
value: function (this: Entity) {
|
|
225
|
+
return Pipeable.pipeArguments(this, arguments)
|
|
238
226
|
},
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
227
|
+
},
|
|
228
|
+
text: {
|
|
229
|
+
get(this: Entity<unknown, unknown>) {
|
|
230
|
+
return getText(this)
|
|
243
231
|
},
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
232
|
+
},
|
|
233
|
+
json: {
|
|
234
|
+
get(this: Entity<unknown, unknown>) {
|
|
235
|
+
return getJson(this)
|
|
248
236
|
},
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
237
|
+
},
|
|
238
|
+
bytes: {
|
|
239
|
+
get(this: Entity<unknown, unknown>) {
|
|
240
|
+
return getBytes(this)
|
|
253
241
|
},
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
242
|
+
},
|
|
243
|
+
stream: {
|
|
244
|
+
get(this: Entity<unknown, unknown>) {
|
|
245
|
+
return getStream(this)
|
|
258
246
|
},
|
|
259
247
|
},
|
|
260
|
-
)
|
|
248
|
+
})
|
|
261
249
|
|
|
262
250
|
export function isEntity(input: unknown): input is Entity {
|
|
263
251
|
return Predicate.hasProperty(input, TypeId)
|
|
@@ -278,42 +266,30 @@ export function make<A extends Uint8Array | string, E>(
|
|
|
278
266
|
options?: Options,
|
|
279
267
|
): Entity<Stream.Stream<A, E, never>, E>
|
|
280
268
|
export function make<T>(body: T, options?: Options): Entity<T, never>
|
|
281
|
-
export function make(
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
body,
|
|
289
|
-
headers: options?.headers ?? {},
|
|
290
|
-
url: options?.url,
|
|
291
|
-
status: options?.status,
|
|
292
|
-
},
|
|
293
|
-
)
|
|
269
|
+
export function make(body: unknown, options?: Options): Entity<unknown, unknown> {
|
|
270
|
+
return Object.assign(Object.create(Proto), {
|
|
271
|
+
body,
|
|
272
|
+
headers: options?.headers ?? {},
|
|
273
|
+
url: options?.url,
|
|
274
|
+
status: options?.status,
|
|
275
|
+
})
|
|
294
276
|
}
|
|
295
277
|
|
|
296
|
-
export function effect<A, E, R>(
|
|
297
|
-
body: Effect.Effect<Entity<A> | A, E, R>,
|
|
298
|
-
): Entity<A, E> {
|
|
278
|
+
export function effect<A, E, R>(body: Effect.Effect<Entity<A> | A, E, R>): Entity<A, E> {
|
|
299
279
|
return make(body) as unknown as Entity<A, E>
|
|
300
280
|
}
|
|
301
281
|
|
|
302
|
-
export function resolve<A, E>(
|
|
303
|
-
entity: Entity<A, E>,
|
|
304
|
-
): Effect.Effect<Entity<A, E>, E, never> {
|
|
282
|
+
export function resolve<A, E>(entity: Entity<A, E>): Effect.Effect<Entity<A, E>, E, never> {
|
|
305
283
|
const body = entity.body
|
|
306
284
|
if (Effect.isEffect(body)) {
|
|
307
|
-
return Effect.map(
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
? inner as Entity<A, E>
|
|
312
|
-
: make(inner as A, {
|
|
285
|
+
return Effect.map(body as Effect.Effect<Entity<A> | A, E, never>, (inner) =>
|
|
286
|
+
isEntity(inner)
|
|
287
|
+
? (inner as Entity<A, E>)
|
|
288
|
+
: (make(inner as A, {
|
|
313
289
|
status: entity.status,
|
|
314
290
|
headers: entity.headers,
|
|
315
291
|
url: entity.url,
|
|
316
|
-
}) as Entity<A, E
|
|
292
|
+
}) as Entity<A, E>),
|
|
317
293
|
)
|
|
318
294
|
}
|
|
319
295
|
return Effect.succeed(entity)
|
|
@@ -349,10 +325,7 @@ export function length(self: Entity): number | undefined {
|
|
|
349
325
|
return undefined
|
|
350
326
|
}
|
|
351
327
|
|
|
352
|
-
function mismatch(
|
|
353
|
-
expected: Schema.Schema.Any,
|
|
354
|
-
actual: unknown,
|
|
355
|
-
): ParseResult.ParseError {
|
|
328
|
+
function mismatch(expected: Schema.Schema.Any, actual: unknown): ParseResult.ParseError {
|
|
356
329
|
return new ParseResult.ParseError({
|
|
357
330
|
issue: new ParseResult.Type(expected.ast, actual),
|
|
358
331
|
})
|
package/src/FilePathPattern.ts
CHANGED
|
@@ -10,9 +10,9 @@ export type Segment =
|
|
|
10
10
|
| { _tag: "LiteralSegment"; value: string }
|
|
11
11
|
| { _tag: "InvalidSegment"; value: string }
|
|
12
12
|
|
|
13
|
-
export function segments(pattern: string): Segment
|
|
13
|
+
export function segments(pattern: string): Array<Segment> {
|
|
14
14
|
const parts = pattern.split("/").filter(Boolean)
|
|
15
|
-
const result: Segment
|
|
15
|
+
const result: Array<Segment> = []
|
|
16
16
|
|
|
17
17
|
for (const part of parts) {
|
|
18
18
|
if (/^\(\w+\)$/.test(part)) {
|
|
@@ -37,7 +37,7 @@ export type ValidationError = {
|
|
|
37
37
|
message: string
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
export type ValidationResult = Either.Either<Segment
|
|
40
|
+
export type ValidationResult = Either.Either<Array<Segment>, ValidationError>
|
|
41
41
|
|
|
42
42
|
export function validate(pattern: string): ValidationResult {
|
|
43
43
|
const segs = segments(pattern)
|
|
@@ -63,7 +63,7 @@ export function validate(pattern: string): ValidationResult {
|
|
|
63
63
|
return Either.right(segs)
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
export function format(segs: Segment
|
|
66
|
+
export function format(segs: Array<Segment>): `/${string}` {
|
|
67
67
|
const parts = segs.map((seg) => {
|
|
68
68
|
switch (seg._tag) {
|
|
69
69
|
case "GroupSegment":
|
|
@@ -92,7 +92,7 @@ export function toPathPattern(
|
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
const segs = result.right
|
|
95
|
-
const pathParts: string
|
|
95
|
+
const pathParts: Array<string> = []
|
|
96
96
|
|
|
97
97
|
for (const seg of segs) {
|
|
98
98
|
switch (seg._tag) {
|
package/src/FileRouter.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as FileSystem from "
|
|
1
|
+
import * as FileSystem from "./FileSystem.ts"
|
|
2
2
|
import * as Data from "effect/Data"
|
|
3
3
|
import * as Effect from "effect/Effect"
|
|
4
4
|
import * as Either from "effect/Either"
|
|
@@ -17,10 +17,7 @@ import * as Route from "./Route.ts"
|
|
|
17
17
|
import * as RouteTree from "./RouteTree.ts"
|
|
18
18
|
|
|
19
19
|
export class FileRouterError extends Data.TaggedError("FileRouterError")<{
|
|
20
|
-
reason:
|
|
21
|
-
| "Import"
|
|
22
|
-
| "Conflict"
|
|
23
|
-
| "FileSystem"
|
|
20
|
+
reason: "Import" | "Conflict" | "FileSystem"
|
|
24
21
|
cause?: unknown
|
|
25
22
|
path?: string
|
|
26
23
|
}> {}
|
|
@@ -32,23 +29,18 @@ export type RouteModule = {
|
|
|
32
29
|
export type LazyRouteModule = () => Promise<RouteModule>
|
|
33
30
|
|
|
34
31
|
export type FileRoutes = {
|
|
35
|
-
[path: PathPattern.PathPattern]: [
|
|
36
|
-
LazyRouteModule,
|
|
37
|
-
...LazyRouteModule[],
|
|
38
|
-
]
|
|
32
|
+
[path: PathPattern.PathPattern]: [LazyRouteModule, ...LazyRouteModule[]]
|
|
39
33
|
}
|
|
40
34
|
|
|
41
35
|
export type Segment = FilePathPattern.Segment
|
|
42
36
|
|
|
43
37
|
export type FileRoute = {
|
|
44
|
-
handle:
|
|
45
|
-
| "route"
|
|
46
|
-
| "layer"
|
|
38
|
+
handle: "route" | "layer"
|
|
47
39
|
// eg. `/about/route.tsx`, `/users/[userId]/route.tsx`, `/(admin)/users/route.tsx`
|
|
48
40
|
modulePath: `/${string}`
|
|
49
41
|
// eg. `/about`, `/users/[userId]`, `/users` (groups stripped)
|
|
50
42
|
routePath: `/${string}`
|
|
51
|
-
segments: Segment
|
|
43
|
+
segments: Array<Segment>
|
|
52
44
|
}
|
|
53
45
|
|
|
54
46
|
/**
|
|
@@ -58,19 +50,17 @@ export type FileRoute = {
|
|
|
58
50
|
* - users/[userId]/route.tsx
|
|
59
51
|
* - [[rest]]/route.tsx
|
|
60
52
|
*/
|
|
61
|
-
export type OrderedFileRoutes = FileRoute
|
|
53
|
+
export type OrderedFileRoutes = Array<FileRoute>
|
|
62
54
|
|
|
63
55
|
const ROUTE_PATH_REGEX = /^\/?(.*\/?)(?:route|layer)\.(jsx?|tsx?)$/
|
|
64
56
|
|
|
65
|
-
export function parseRoute(
|
|
66
|
-
path: string,
|
|
67
|
-
): FileRoute | null {
|
|
57
|
+
export function parseRoute(path: string): FileRoute | null {
|
|
68
58
|
const segs = FilePathPattern.segments(path)
|
|
69
59
|
|
|
70
60
|
const lastSeg = segs.at(-1)
|
|
71
|
-
const handleMatch =
|
|
72
|
-
&& lastSeg.value.match(/^(route|layer)\.(tsx?|jsx?)$/)
|
|
73
|
-
const handle = handleMatch ? handleMatch[1] as "route" | "layer" : null
|
|
61
|
+
const handleMatch =
|
|
62
|
+
lastSeg?._tag === "LiteralSegment" && lastSeg.value.match(/^(route|layer)\.(tsx?|jsx?)$/)
|
|
63
|
+
const handle = handleMatch ? (handleMatch[1] as "route" | "layer") : null
|
|
74
64
|
|
|
75
65
|
if (!handle) {
|
|
76
66
|
return null
|
|
@@ -78,9 +68,7 @@ export function parseRoute(
|
|
|
78
68
|
|
|
79
69
|
const pathSegments = segs.slice(0, -1)
|
|
80
70
|
|
|
81
|
-
const validated = FilePathPattern.validate(
|
|
82
|
-
FilePathPattern.format(pathSegments),
|
|
83
|
-
)
|
|
71
|
+
const validated = FilePathPattern.validate(FilePathPattern.format(pathSegments))
|
|
84
72
|
if (Either.isLeft(validated)) {
|
|
85
73
|
return null
|
|
86
74
|
}
|
|
@@ -90,9 +78,7 @@ export function parseRoute(
|
|
|
90
78
|
return null
|
|
91
79
|
}
|
|
92
80
|
|
|
93
|
-
const routePathSegments = pathSegments.filter(
|
|
94
|
-
(seg) => seg._tag !== "GroupSegment",
|
|
95
|
-
)
|
|
81
|
+
const routePathSegments = pathSegments.filter((seg) => seg._tag !== "GroupSegment")
|
|
96
82
|
const routePath = FilePathPattern.format(routePathSegments)
|
|
97
83
|
|
|
98
84
|
return {
|
|
@@ -103,9 +89,7 @@ export function parseRoute(
|
|
|
103
89
|
}
|
|
104
90
|
}
|
|
105
91
|
|
|
106
|
-
function importModule<T>(
|
|
107
|
-
load: () => Promise<T>,
|
|
108
|
-
): Effect.Effect<T, FileRouterError> {
|
|
92
|
+
function importModule<T>(load: () => Promise<T>): Effect.Effect<T, FileRouterError> {
|
|
109
93
|
return Effect.tryPromise({
|
|
110
94
|
try: () => load(),
|
|
111
95
|
catch: (cause) => new FileRouterError({ reason: "Import", cause }),
|
|
@@ -127,12 +111,13 @@ export function layer(
|
|
|
127
111
|
| (() => Promise<{ default: FileRoutes }>)
|
|
128
112
|
| { load: () => Promise<{ default: FileRoutes }>; path: string },
|
|
129
113
|
) {
|
|
130
|
-
const options =
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
114
|
+
const options =
|
|
115
|
+
typeof loadOrOptions === "function"
|
|
116
|
+
? {
|
|
117
|
+
load: loadOrOptions,
|
|
118
|
+
path: NPath.join(NodeUtils.getEntrypoint(), "routes"),
|
|
119
|
+
}
|
|
120
|
+
: loadOrOptions
|
|
136
121
|
let treePath = options.path
|
|
137
122
|
if (treePath.startsWith("file://")) {
|
|
138
123
|
treePath = NUrl.fileURLToPath(treePath)
|
|
@@ -147,7 +132,7 @@ export function layer(
|
|
|
147
132
|
|
|
148
133
|
return Layer.scoped(
|
|
149
134
|
Route.Routes,
|
|
150
|
-
Effect.gen(function*() {
|
|
135
|
+
Effect.gen(function* () {
|
|
151
136
|
// Generate routes file before loading
|
|
152
137
|
yield* FileRouterCodegen.update(routesPath, treeFilename)
|
|
153
138
|
|
|
@@ -158,12 +143,8 @@ export function layer(
|
|
|
158
143
|
// Watch for changes (only when Development service is available)
|
|
159
144
|
yield* Function.pipe(
|
|
160
145
|
Development.stream(),
|
|
161
|
-
Stream.filter(e =>
|
|
162
|
-
|
|
163
|
-
),
|
|
164
|
-
Stream.runForEach(() =>
|
|
165
|
-
FileRouterCodegen.update(routesPath, treeFilename)
|
|
166
|
-
),
|
|
146
|
+
Stream.filter((e) => e._tag !== "Reload" && e.path.startsWith(relativeRoutesPath)),
|
|
147
|
+
Stream.runForEach(() => FileRouterCodegen.update(routesPath, treeFilename)),
|
|
167
148
|
Effect.fork,
|
|
168
149
|
)
|
|
169
150
|
|
|
@@ -172,25 +153,19 @@ export function layer(
|
|
|
172
153
|
)
|
|
173
154
|
}
|
|
174
155
|
|
|
175
|
-
export function fromFileRoutes(
|
|
176
|
-
|
|
177
|
-
): Effect.Effect<RouteTree.RouteTree> {
|
|
178
|
-
return Effect.gen(function*() {
|
|
156
|
+
export function fromFileRoutes(fileRoutes: FileRoutes): Effect.Effect<RouteTree.RouteTree> {
|
|
157
|
+
return Effect.gen(function* () {
|
|
179
158
|
const mounts: RouteTree.InputRouteMap = {}
|
|
180
159
|
|
|
181
160
|
for (const [path, loaders] of Object.entries(fileRoutes)) {
|
|
182
|
-
const modules = yield* Effect.forEach(
|
|
183
|
-
loaders,
|
|
184
|
-
(loader) => Effect.promise(() => loader()),
|
|
185
|
-
)
|
|
161
|
+
const modules = yield* Effect.forEach(loaders, (loader) => Effect.promise(() => loader()))
|
|
186
162
|
|
|
187
|
-
const allRoutes: RouteTree.RouteTuple =
|
|
188
|
-
[] as unknown as RouteTree.RouteTuple
|
|
163
|
+
const allRoutes: RouteTree.RouteTuple = [] as unknown as RouteTree.RouteTuple
|
|
189
164
|
|
|
190
165
|
for (const m of modules) {
|
|
191
166
|
if (Route.isRouteSet(m.default)) {
|
|
192
167
|
for (const route of m.default) {
|
|
193
|
-
;(allRoutes as any
|
|
168
|
+
;(allRoutes as Array<any>).push(route)
|
|
194
169
|
}
|
|
195
170
|
}
|
|
196
171
|
}
|
|
@@ -209,7 +184,7 @@ export function walkRoutesDirectory(
|
|
|
209
184
|
PlatformError.PlatformError | FileRouterError,
|
|
210
185
|
FileSystem.FileSystem
|
|
211
186
|
> {
|
|
212
|
-
return Effect.gen(function*() {
|
|
187
|
+
return Effect.gen(function* () {
|
|
213
188
|
const fs = yield* FileSystem.FileSystem
|
|
214
189
|
const files = yield* fs.readDirectory(dir, { recursive: true })
|
|
215
190
|
|
|
@@ -218,13 +193,13 @@ export function walkRoutesDirectory(
|
|
|
218
193
|
}
|
|
219
194
|
|
|
220
195
|
export function getFileRoutes(
|
|
221
|
-
paths: string
|
|
196
|
+
paths: Array<string>,
|
|
222
197
|
): Effect.Effect<OrderedFileRoutes, FileRouterError> {
|
|
223
|
-
return Effect.gen(function*() {
|
|
198
|
+
return Effect.gen(function* () {
|
|
224
199
|
const routes = paths
|
|
225
|
-
.map(f => f.match(ROUTE_PATH_REGEX))
|
|
200
|
+
.map((f) => f.match(ROUTE_PATH_REGEX))
|
|
226
201
|
.filter(Boolean)
|
|
227
|
-
.map(v => {
|
|
202
|
+
.map((v) => {
|
|
228
203
|
const path = v![0]
|
|
229
204
|
try {
|
|
230
205
|
return parseRoute(path)
|
|
@@ -241,16 +216,16 @@ export function getFileRoutes(
|
|
|
241
216
|
|
|
242
217
|
return (
|
|
243
218
|
// rest is a dominant factor (routes with rest come last)
|
|
244
|
-
(+aHasRest - +bHasRest) * 1000
|
|
219
|
+
(+aHasRest - +bHasRest) * 1000 +
|
|
245
220
|
// depth is reversed for rest
|
|
246
|
-
|
|
221
|
+
(aDepth - bDepth) * (1 - 2 * +aHasRest) +
|
|
247
222
|
// lexicographic comparison as tiebreaker
|
|
248
|
-
|
|
223
|
+
a.modulePath.localeCompare(b.modulePath) * 0.001
|
|
249
224
|
)
|
|
250
225
|
})
|
|
251
226
|
|
|
252
227
|
// Detect conflicting routes at the same path
|
|
253
|
-
const routesByPath = new Map<string, FileRoute
|
|
228
|
+
const routesByPath = new Map<string, Array<FileRoute>>()
|
|
254
229
|
for (const route of routes) {
|
|
255
230
|
const existing = routesByPath.get(route.routePath) || []
|
|
256
231
|
existing.push(route)
|
|
@@ -258,7 +233,7 @@ export function getFileRoutes(
|
|
|
258
233
|
}
|
|
259
234
|
|
|
260
235
|
for (const [path, pathRoutes] of routesByPath) {
|
|
261
|
-
const routeHandles = pathRoutes.filter(h => h.handle === "route")
|
|
236
|
+
const routeHandles = pathRoutes.filter((h) => h.handle === "route")
|
|
262
237
|
|
|
263
238
|
if (routeHandles.length > 1) {
|
|
264
239
|
yield* new FileRouterError({ reason: "Conflict", path })
|