effect-start 0.11.1 → 0.12.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.
@@ -1,13 +1,18 @@
1
1
  import type { PlatformError } from "@effect/platform/Error"
2
2
  import * as FileSystem from "@effect/platform/FileSystem"
3
3
  import * as Effect from "effect/Effect"
4
+ import * as Function from "effect/Function"
5
+ import * as Schema from "effect/Schema"
4
6
  import * as NPath from "node:path"
5
7
  import * as FileRouter from "./FileRouter.ts"
8
+ import * as FileRouterPattern from "./FileRouterPattern.ts"
6
9
  import * as Route from "./Route.ts"
10
+ import * as Router from "./Router.ts"
11
+ import * as SchemaExtra from "./SchemaExtra.ts"
7
12
 
8
13
  export function validateRouteModule(
9
14
  module: unknown,
10
- ): boolean {
15
+ ): module is FileRouter.RouteModule {
11
16
  if (typeof module !== "object" || module === null) {
12
17
  return false
13
18
  }
@@ -17,37 +22,77 @@ export function validateRouteModule(
17
22
  return Route.isRouteSet(module.default)
18
23
  }
19
24
 
25
+ export function generatePathParamsSchema(
26
+ segments: ReadonlyArray<FileRouterPattern.Segment>,
27
+ ): Schema.Struct<any> | null {
28
+ const fields: Record<
29
+ PropertyKey,
30
+ Schema.Schema.Any | Schema.PropertySignature.All
31
+ > = {}
32
+
33
+ for (const segment of segments) {
34
+ if (
35
+ segment._tag === "ParamSegment"
36
+ || segment._tag === "RestSegment"
37
+ ) {
38
+ fields[segment.name] = segment.optional
39
+ ? Function.pipe(Schema.String, Schema.optional)
40
+ : Schema.String
41
+ }
42
+ }
43
+
44
+ if (Object.keys(fields).length === 0) {
45
+ return null
46
+ }
47
+
48
+ return Schema.Struct(fields)
49
+ }
50
+
20
51
  /**
21
52
  * Validates all route modules in the given route handles.
22
53
  */
54
+
23
55
  export function validateRouteModules(
24
56
  routesPath: string,
25
57
  handles: FileRouter.OrderedRouteHandles,
26
- ): Effect.Effect<void, never, never> {
58
+ ): Effect.Effect<void, PlatformError, FileSystem.FileSystem> {
27
59
  return Effect.gen(function*() {
60
+ const fs = yield* FileSystem.FileSystem
28
61
  const routeHandles = handles.filter(h => h.handle === "route")
29
62
 
30
63
  for (const handle of routeHandles) {
31
64
  const routeModulePath = NPath.resolve(routesPath, handle.modulePath)
32
- yield* Effect
33
- .tryPromise({
34
- try: async () => import(routeModulePath),
35
- catch: (error) =>
36
- Effect.logWarning(
37
- `Failed to validate route module ${routeModulePath}: ${error}`,
38
- ),
39
- })
40
- .pipe(
41
- Effect.catchAll((logEffect) => logEffect),
42
- Effect.tap((module) => {
43
- if (!validateRouteModule(module)) {
44
- return Effect.logWarning(
45
- `Route module ${routeModulePath} should export default Route`,
46
- )
47
- }
48
- return Effect.void
49
- }),
65
+ const expectedSchema = generatePathParamsSchema(handle.segments)
66
+
67
+ const fileExists = yield* fs.exists(routeModulePath)
68
+ if (!fileExists) {
69
+ continue
70
+ }
71
+
72
+ const module = yield* Effect.promise(() => import(routeModulePath))
73
+
74
+ if (!validateRouteModule(module)) {
75
+ yield* Effect.logWarning(
76
+ `Route module ${routeModulePath} should export default Route`,
50
77
  )
78
+ continue
79
+ }
80
+
81
+ const routeSet = module.default
82
+ const userSchema = routeSet.schema?.PathParams
83
+
84
+ if (
85
+ expectedSchema
86
+ && userSchema
87
+ && !SchemaExtra.schemaEqual(userSchema, expectedSchema)
88
+ ) {
89
+ const relativeFilePath = NPath.relative(process.cwd(), routeModulePath)
90
+ yield* Effect.logError(
91
+ `Route '${relativeFilePath}' has incorrect PathParams schema, expected schemaPathParams(${
92
+ SchemaExtra.formatSchemaCode(expectedSchema)
93
+ })`,
94
+ )
95
+ }
51
96
  }
52
97
  })
53
98
  }
@@ -154,7 +199,7 @@ export const routes = ${routesArray} as const
154
199
  */
155
200
  export function update(
156
201
  routesPath: string,
157
- manifestPath = "_manifest.ts",
202
+ manifestPath = "manifest.ts",
158
203
  ): Effect.Effect<void, PlatformError, FileSystem.FileSystem> {
159
204
  return Effect.gen(function*() {
160
205
  manifestPath = NPath.resolve(routesPath, manifestPath)
@@ -184,7 +229,7 @@ export function update(
184
229
 
185
230
  export function dump(
186
231
  routesPath: string,
187
- manifestPath = "_manifest.ts",
232
+ manifestPath = "manifest.ts",
188
233
  ): Effect.Effect<void, PlatformError, FileSystem.FileSystem> {
189
234
  return Effect.gen(function*() {
190
235
  manifestPath = NPath.resolve(routesPath, manifestPath)
package/src/Route.ts CHANGED
@@ -48,8 +48,7 @@ type Self =
48
48
  */
49
49
  | RouteModule
50
50
  /**
51
- * Called directly from exported function.
52
- * Disencouraged but possible.
51
+ * Called directly from exported function. Don't do it.
53
52
  *
54
53
  * @example
55
54
  * ```ts
@@ -264,11 +264,11 @@ t.describe("Router", () => {
264
264
  t.test("infers never for routes without requirements", () => {
265
265
  const router = Router.mount("/hello", Route.text("Hello"))
266
266
 
267
- type RouterError = Router.RouterBuilder.Error<typeof router>
268
- type RouterContext = Router.RouterBuilder.Context<typeof router>
267
+ type RouterError = Router.Router.Error<typeof router>
268
+ type RouterRequirements = Router.Router.Requirements<typeof router>
269
269
 
270
270
  const _checkError: RouterError = undefined as never
271
- const _checkContext: RouterContext = undefined as never
271
+ const _checkRequirements: RouterRequirements = undefined as never
272
272
 
273
273
  t.expect(true).toBe(true)
274
274
  })
@@ -283,7 +283,7 @@ t.describe("Router", () => {
283
283
  Route.text(Effect.fail(new MyError())),
284
284
  )
285
285
 
286
- type RouterError = Router.RouterBuilder.Error<typeof router>
286
+ type RouterError = Router.Router.Error<typeof router>
287
287
 
288
288
  const _checkError: MyError extends RouterError ? true : false = true
289
289
 
@@ -306,9 +306,10 @@ t.describe("Router", () => {
306
306
  ),
307
307
  )
308
308
 
309
- type RouterContext = Router.RouterBuilder.Context<typeof router>
309
+ type RouterRequirements = Router.Router.Requirements<typeof router>
310
310
 
311
- const _checkContext: MyService extends RouterContext ? true : false = true
311
+ const _checkRequirements: MyService extends RouterRequirements ? true
312
+ : false = true
312
313
 
313
314
  t.expect(true).toBe(true)
314
315
  })
@@ -325,7 +326,7 @@ t.describe("Router", () => {
325
326
  .mount("/a", Route.text(Effect.fail(new ErrorA())))
326
327
  .mount("/b", Route.text(Effect.fail(new ErrorB())))
327
328
 
328
- type RouterError = Router.RouterBuilder.Error<typeof router>
329
+ type RouterError = Router.Router.Error<typeof router>
329
330
 
330
331
  const _checkA: ErrorA extends RouterError ? true : false = true
331
332
  const _checkB: ErrorB extends RouterError ? true : false = true
@@ -363,54 +364,12 @@ t.describe("Router", () => {
363
364
  ),
364
365
  )
365
366
 
366
- type RouterContext = Router.RouterBuilder.Context<typeof router>
367
+ type RouterRequirements = Router.Router.Requirements<typeof router>
367
368
 
368
- const _checkA: ServiceA extends RouterContext ? true : false = true
369
- const _checkB: ServiceB extends RouterContext ? true : false = true
369
+ const _checkA: ServiceA extends RouterRequirements ? true : false = true
370
+ const _checkB: ServiceB extends RouterRequirements ? true : false = true
370
371
 
371
372
  t.expect(true).toBe(true)
372
373
  })
373
374
  })
374
-
375
- t.describe("fromManifest", () => {
376
- t.test("loads routes from manifest", async () => {
377
- const manifest: Router.RouterManifest = {
378
- routes: [
379
- {
380
- path: "/test",
381
- load: () => Promise.resolve({ default: Route.text("Test") }),
382
- },
383
- ],
384
- }
385
-
386
- const router = await Effect.runPromise(Router.fromManifest(manifest))
387
-
388
- t.expect(router.entries).toHaveLength(1)
389
- t.expect(router.entries[0].path).toBe("/test")
390
- })
391
-
392
- t.test("loads layers from manifest", async () => {
393
- const layer = Route.layer(
394
- Route.html(function*(c) {
395
- const inner = yield* c.next()
396
- return `<wrap>${inner}</wrap>`
397
- }),
398
- )
399
-
400
- const manifest: Router.RouterManifest = {
401
- routes: [
402
- {
403
- path: "/test",
404
- load: () => Promise.resolve({ default: Route.text("Test") }),
405
- layers: [() => Promise.resolve({ default: layer })],
406
- },
407
- ],
408
- }
409
-
410
- const router = await Effect.runPromise(Router.fromManifest(manifest))
411
-
412
- t.expect(router.entries).toHaveLength(1)
413
- t.expect(router.entries[0].layers).toHaveLength(1)
414
- })
415
- })
416
375
  })
package/src/Router.ts CHANGED
@@ -1,12 +1,14 @@
1
- import * as Context from "effect/Context"
2
1
  import * as Data from "effect/Data"
3
- import * as Effect from "effect/Effect"
4
- import * as Function from "effect/Function"
5
- import * as Layer from "effect/Layer"
6
2
  import * as Pipeable from "effect/Pipeable"
7
3
  import * as Predicate from "effect/Predicate"
8
- import * as FileRouter from "./FileRouter.ts"
9
- import * as Route from "./Route"
4
+ import * as Route from "./Route.ts"
5
+
6
+ type RouterModule = typeof import("./Router.ts")
7
+
8
+ type Self =
9
+ | Router.Any
10
+ | RouterModule
11
+ | undefined
10
12
 
11
13
  export type RouterErrorReason =
12
14
  | "UnsupportedPattern"
@@ -18,85 +20,26 @@ export class RouterError extends Data.TaggedError("RouterError")<{
18
20
  message: string
19
21
  }> {}
20
22
 
21
- export type ServerModule = {
22
- default: Route.RouteSet.Default
23
- }
24
-
25
- export type LazyRoute = {
26
- path: `/${string}`
27
- load: () => Promise<ServerModule>
28
- layers?: ReadonlyArray<() => Promise<unknown>>
29
- }
30
-
31
- export type RouterManifest = {
32
- routes: readonly LazyRoute[]
33
- layers?: any[]
34
- }
35
-
36
- export type RouterContext = RouterManifest
37
-
38
- export class Router extends Context.Tag("effect-start/Router")<
39
- Router,
40
- RouterContext
41
- >() {}
42
-
43
- export function layer(
44
- manifest: RouterManifest,
45
- ): Layer.Layer<Router, never, never> {
46
- return Layer.effect(
47
- Router,
48
- Effect.gen(function*() {
49
- return {
50
- ...manifest,
51
- }
52
- }),
53
- )
54
- }
55
-
56
- export const layerFiles = FileRouter.layer
57
-
58
- export function layerPromise(
59
- load: () => Promise<RouterManifest>,
60
- ): Layer.Layer<Router, never, never> {
61
- return Layer.unwrapEffect(
62
- Effect.gen(function*() {
63
- const importedModule = yield* Function.pipe(
64
- Effect.promise(() => load()),
65
- Effect.orDie,
66
- )
67
-
68
- return layer(importedModule)
69
- }),
70
- )
71
- }
72
-
73
- const RouterBuilderTypeId: unique symbol = Symbol.for(
74
- "effect-start/RouterBuilder",
23
+ const TypeId: unique symbol = Symbol.for(
24
+ "effect-start/Router",
75
25
  )
76
26
 
77
- type RouterModule = typeof import("./Router.ts")
78
-
79
- type Self =
80
- | RouterBuilder<any, any>
81
- | RouterModule
82
- | undefined
83
-
84
27
  export type RouterEntry = {
85
28
  path: `/${string}`
86
29
  route: Route.RouteSet.Default
87
30
  layers: Route.RouteLayer[]
88
31
  }
89
32
 
90
- type RouterBuilderMethods = {
33
+ type Methods = {
91
34
  use: typeof use
92
35
  mount: typeof mount
93
36
  }
94
37
 
95
- export interface RouterBuilder<
38
+ export interface Router<
96
39
  out E = never,
97
40
  out R = never,
98
- > extends Pipeable.Pipeable, RouterBuilderMethods {
99
- [RouterBuilderTypeId]: typeof RouterBuilderTypeId
41
+ > extends Pipeable.Pipeable, Methods {
42
+ [TypeId]: typeof TypeId
100
43
  readonly entries: readonly RouterEntry[]
101
44
  readonly globalLayers: readonly Route.RouteLayer[]
102
45
  readonly mounts: Record<`/${string}`, Route.RouteSet.Default>
@@ -104,18 +47,17 @@ export interface RouterBuilder<
104
47
  readonly _R: () => R
105
48
  }
106
49
 
107
- export namespace RouterBuilder {
108
- export type Any = RouterBuilder<any, any>
109
-
110
- export type Error<T> = T extends RouterBuilder<infer E, any> ? E : never
111
- export type Context<T> = T extends RouterBuilder<any, infer R> ? R : never
50
+ export namespace Router {
51
+ export type Any = Router<any, any>
52
+ export type Error<T> = T extends Router<infer E, any> ? E : never
53
+ export type Requirements<T> = T extends Router<any, infer R> ? R : never
112
54
  }
113
55
 
114
- const RouterBuilderProto: RouterBuilderMethods & {
115
- [RouterBuilderTypeId]: typeof RouterBuilderTypeId
56
+ const Proto: Methods & {
57
+ [TypeId]: typeof TypeId
116
58
  pipe: Pipeable.Pipeable["pipe"]
117
59
  } = {
118
- [RouterBuilderTypeId]: RouterBuilderTypeId,
60
+ [TypeId]: TypeId,
119
61
 
120
62
  pipe() {
121
63
  return Pipeable.pipeArguments(this, arguments)
@@ -143,17 +85,17 @@ function addRoute<
143
85
  RouteE,
144
86
  RouteR,
145
87
  >(
146
- builder: RouterBuilder<E, R>,
88
+ builder: Router<E, R>,
147
89
  path: `/${string}`,
148
90
  route: Route.RouteSet.Default,
149
- ): RouterBuilder<E | RouteE, R | RouteR> {
91
+ ): Router<E | RouteE, R | RouteR> {
150
92
  const existingEntry = builder.entries.find((e) => e.path === path)
151
93
  if (existingEntry) {
152
94
  const updatedEntry: RouterEntry = {
153
95
  ...existingEntry,
154
96
  route: Route.merge(existingEntry.route, route),
155
97
  }
156
- return makeBuilder(
98
+ return make(
157
99
  builder.entries.map((e) => (e.path === path ? updatedEntry : e)),
158
100
  builder.globalLayers,
159
101
  )
@@ -165,18 +107,17 @@ function addRoute<
165
107
  layers: [...builder.globalLayers],
166
108
  }
167
109
 
168
- return makeBuilder([...builder.entries, newEntry], builder.globalLayers)
110
+ return make([...builder.entries, newEntry], builder.globalLayers)
169
111
  }
170
112
 
171
113
  function addGlobalLayer<E, R>(
172
- builder: RouterBuilder<E, R>,
114
+ builder: Router<E, R>,
173
115
  layerRoute: Route.RouteLayer,
174
- ): RouterBuilder<E, R> {
116
+ ): Router<E, R> {
175
117
  const newGlobalLayers = [...builder.globalLayers, layerRoute]
176
- return makeBuilder(builder.entries, newGlobalLayers)
118
+ return make(builder.entries, newGlobalLayers)
177
119
  }
178
120
 
179
-
180
121
  function findMatchingLayerRoutes(
181
122
  route: Route.Route.Default,
182
123
  layers: readonly Route.RouteLayer[],
@@ -244,10 +185,10 @@ function applyLayersToRouteSet(
244
185
  } as unknown as Route.RouteSet.Default
245
186
  }
246
187
 
247
- function makeBuilder<E, R>(
188
+ export function make<E, R>(
248
189
  entries: readonly RouterEntry[],
249
190
  globalLayers: readonly Route.RouteLayer[] = [],
250
- ): RouterBuilder<E, R> {
191
+ ): Router<E, R> {
251
192
  const mounts: Record<`/${string}`, Route.RouteSet.Default> = {}
252
193
 
253
194
  for (const entry of entries) {
@@ -256,15 +197,18 @@ function makeBuilder<E, R>(
256
197
  }
257
198
  }
258
199
 
259
- return Object.assign(Object.create(RouterBuilderProto), {
260
- entries,
261
- globalLayers,
262
- mounts,
263
- })
200
+ return Object.assign(
201
+ Object.create(Proto),
202
+ {
203
+ entries,
204
+ globalLayers,
205
+ mounts,
206
+ },
207
+ )
264
208
  }
265
209
 
266
- export function isRouterBuilder(input: unknown): input is RouterBuilder.Any {
267
- return Predicate.hasProperty(input, RouterBuilderTypeId)
210
+ export function isRouter(input: unknown): input is Router.Any {
211
+ return Predicate.hasProperty(input, TypeId)
268
212
  }
269
213
 
270
214
  export function use<
@@ -272,13 +216,14 @@ export function use<
272
216
  >(
273
217
  this: S,
274
218
  layerRoute: Route.RouteLayer,
275
- ): S extends RouterBuilder<infer E, infer R> ? RouterBuilder<E, R>
276
- : RouterBuilder<never, never>
219
+ ): S extends Router<infer E, infer R> ? Router<E, R>
220
+ : Router<never, never>
277
221
  {
278
- const builder = isRouterBuilder(this)
222
+ const router = isRouter(this)
279
223
  ? this
280
- : makeBuilder<never, never>([], [])
281
- return addGlobalLayer(builder, layerRoute) as any
224
+ : make<never, never>([], [])
225
+
226
+ return addGlobalLayer(router, layerRoute) as any
282
227
  }
283
228
 
284
229
  export function mount<
@@ -289,49 +234,22 @@ export function mount<
289
234
  this: S,
290
235
  path: `/${string}`,
291
236
  route: Route.RouteSet<Routes, Schemas>,
292
- ): S extends RouterBuilder<infer E, infer R> ? RouterBuilder<
237
+ ): S extends Router<infer E, infer R> ? Router<
293
238
  E | ExtractRouteSetError<Route.RouteSet<Routes, Schemas>>,
294
239
  R | ExtractRouteSetContext<Route.RouteSet<Routes, Schemas>>
295
240
  >
296
- : RouterBuilder<
241
+ : Router<
297
242
  ExtractRouteSetError<Route.RouteSet<Routes, Schemas>>,
298
243
  ExtractRouteSetContext<Route.RouteSet<Routes, Schemas>>
299
244
  >
300
245
  {
301
- const builder = isRouterBuilder(this)
246
+ const router = isRouter(this)
302
247
  ? this
303
- : makeBuilder<never, never>([], [])
304
- return addRoute(builder, path, route as Route.RouteSet.Default) as any
305
- }
248
+ : make<never, never>([], [])
306
249
 
307
- export function fromManifest(
308
- manifest: RouterManifest,
309
- ): Effect.Effect<RouterBuilder.Any> {
310
- return Effect.gen(function*() {
311
- const loadedEntries = yield* Effect.forEach(
312
- manifest.routes,
313
- (lazyRoute) =>
314
- Effect.gen(function*() {
315
- const routeModule = yield* Effect.promise(() => lazyRoute.load())
316
- const layerModules = lazyRoute.layers
317
- ? yield* Effect.forEach(
318
- lazyRoute.layers,
319
- (loadLayer) => Effect.promise(() => loadLayer()),
320
- )
321
- : []
322
-
323
- const layers = layerModules
324
- .map((m: any) => m.default)
325
- .filter(Route.isRouteLayer)
326
-
327
- return {
328
- path: lazyRoute.path,
329
- route: routeModule.default,
330
- layers,
331
- }
332
- }),
333
- )
334
-
335
- return makeBuilder(loadedEntries, [])
336
- })
250
+ return addRoute(
251
+ router,
252
+ path,
253
+ route as Route.RouteSet.Default,
254
+ ) as any
337
255
  }
@@ -0,0 +1,102 @@
1
+ import * as Function from "effect/Function"
2
+ import * as Schema from "effect/Schema"
3
+ import * as SchemaAST from "effect/SchemaAST"
4
+
5
+ export function getBaseSchemaAST(schema: Schema.Schema.Any): SchemaAST.AST {
6
+ let current = schema.ast
7
+
8
+ while (
9
+ SchemaAST.isRefinement(current) || SchemaAST.isTransformation(current)
10
+ ) {
11
+ current = current.from
12
+ }
13
+
14
+ return current
15
+ }
16
+
17
+ export function isOptional(schema: Schema.Schema.Any): boolean {
18
+ const ast = schema.ast
19
+
20
+ if (ast._tag === "Union") {
21
+ return ast.types.some((t: SchemaAST.AST) => t._tag === "UndefinedKeyword")
22
+ }
23
+
24
+ return false
25
+ }
26
+
27
+ export function schemaEqual(
28
+ userSchema: Schema.Struct<any> | undefined,
29
+ expectedSchema: Schema.Struct<any> | null,
30
+ ): boolean {
31
+ if (!userSchema && !expectedSchema) {
32
+ return true
33
+ }
34
+ if (!userSchema || !expectedSchema) {
35
+ return false
36
+ }
37
+
38
+ const userFields = userSchema.fields
39
+ const expectedFields = expectedSchema.fields
40
+
41
+ const userKeys = Object.keys(userFields).sort()
42
+ const expectedKeys = Object.keys(expectedFields).sort()
43
+
44
+ if (userKeys.length !== expectedKeys.length) {
45
+ return false
46
+ }
47
+
48
+ for (let i = 0; i < userKeys.length; i++) {
49
+ if (userKeys[i] !== expectedKeys[i]) {
50
+ return false
51
+ }
52
+ }
53
+
54
+ for (const key of userKeys) {
55
+ const userFieldSchema = userFields[key]
56
+ const expectedFieldSchema = expectedFields[key]
57
+
58
+ const userOptional = isOptional(userFieldSchema)
59
+ const expectedOptional = isOptional(expectedFieldSchema)
60
+
61
+ if (userOptional !== expectedOptional) {
62
+ return false
63
+ }
64
+
65
+ const userBaseAST = getBaseSchemaAST(userFieldSchema)
66
+ const expectedBaseAST = getBaseSchemaAST(expectedFieldSchema)
67
+
68
+ if (userBaseAST._tag !== expectedBaseAST._tag) {
69
+ return false
70
+ }
71
+ }
72
+
73
+ return true
74
+ }
75
+
76
+ export function getSchemaTypeName(schema: Schema.Schema.Any): string {
77
+ const baseAST = getBaseSchemaAST(schema)
78
+ switch (baseAST._tag) {
79
+ case "StringKeyword":
80
+ return "Schema.String"
81
+ case "NumberKeyword":
82
+ return "Schema.Number"
83
+ case "BooleanKeyword":
84
+ return "Schema.Boolean"
85
+ default:
86
+ return "Schema.String"
87
+ }
88
+ }
89
+
90
+ export function formatSchemaCode(schema: Schema.Struct<any>): string {
91
+ const fields = schema.fields
92
+ const fieldStrings: string[] = []
93
+
94
+ for (const [key, fieldSchema] of Object.entries(fields)) {
95
+ const optional = isOptional(fieldSchema)
96
+ const typeName = getSchemaTypeName(fieldSchema)
97
+ const fieldStr = optional ? `${key}?: ${typeName}` : `${key}: ${typeName}`
98
+ fieldStrings.push(fieldStr)
99
+ }
100
+
101
+ return `{ ${fieldStrings.join(", ")} }`
102
+ }
package/src/Start.ts CHANGED
@@ -67,7 +67,7 @@ export function serve<ROut, E>(
67
67
  | HttpClient.HttpClient
68
68
  | HttpRouter.Default
69
69
  | FileSystem.FileSystem
70
- | BunHttpServer.BunServer
70
+ | BunHttpServer.BunHttpServer
71
71
  >
72
72
  }>,
73
73
  ) {
@@ -79,7 +79,7 @@ export function serve<ROut, E>(
79
79
  )
80
80
 
81
81
  return Function.pipe(
82
- BunHttpServer.layerRoutes(),
82
+ BunHttpServer.layerFileRouter(),
83
83
  HttpServer.withLogAddress,
84
84
  Layer.provide(appLayer),
85
85
  Layer.provide([