effect-start 0.14.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/package.json +8 -9
  2. package/src/Commander.test.ts +507 -245
  3. package/src/ContentNegotiation.test.ts +500 -0
  4. package/src/ContentNegotiation.ts +535 -0
  5. package/src/FileRouter.ts +16 -12
  6. package/src/{FileRouterCodegen.test.ts → FileRouterCodegen.todo.ts} +384 -219
  7. package/src/FileRouterCodegen.ts +6 -6
  8. package/src/FileRouterPattern.test.ts +93 -62
  9. package/src/FileRouter_files.test.ts +5 -5
  10. package/src/FileRouter_path.test.ts +121 -69
  11. package/src/FileRouter_tree.test.ts +62 -56
  12. package/src/FileSystemExtra.test.ts +46 -30
  13. package/src/Http.test.ts +24 -0
  14. package/src/Http.ts +25 -0
  15. package/src/HttpAppExtra.test.ts +39 -20
  16. package/src/HttpAppExtra.ts +0 -1
  17. package/src/HttpUtils.test.ts +35 -18
  18. package/src/HttpUtils.ts +2 -0
  19. package/src/PathPattern.test.ts +648 -0
  20. package/src/PathPattern.ts +483 -0
  21. package/src/Route.ts +258 -1073
  22. package/src/RouteBody.test.ts +182 -0
  23. package/src/RouteBody.ts +106 -0
  24. package/src/RouteHook.test.ts +40 -0
  25. package/src/RouteHook.ts +105 -0
  26. package/src/RouteHttp.test.ts +443 -0
  27. package/src/RouteHttp.ts +219 -0
  28. package/src/RouteMount.test.ts +468 -0
  29. package/src/RouteMount.ts +313 -0
  30. package/src/RouteSchema.test.ts +81 -0
  31. package/src/RouteSchema.ts +44 -0
  32. package/src/RouteTree.test.ts +346 -0
  33. package/src/RouteTree.ts +165 -0
  34. package/src/RouteTrie.test.ts +322 -0
  35. package/src/RouteTrie.ts +224 -0
  36. package/src/RouterPattern.test.ts +569 -548
  37. package/src/RouterPattern.ts +7 -7
  38. package/src/Start.ts +3 -3
  39. package/src/TuplePathPattern.ts +64 -0
  40. package/src/Values.ts +16 -0
  41. package/src/bun/BunBundle.test.ts +36 -42
  42. package/src/bun/BunBundle.ts +2 -2
  43. package/src/bun/BunBundle_imports.test.ts +4 -6
  44. package/src/bun/BunHttpServer.test.ts +183 -6
  45. package/src/bun/BunHttpServer.ts +56 -32
  46. package/src/bun/BunHttpServer_web.ts +18 -6
  47. package/src/bun/BunImportTrackerPlugin.test.ts +3 -3
  48. package/src/bun/BunRoute.ts +29 -210
  49. package/src/{BundleHttp.test.ts → bundler/BundleHttp.test.ts} +34 -60
  50. package/src/{BundleHttp.ts → bundler/BundleHttp.ts} +1 -2
  51. package/src/client/index.ts +1 -1
  52. package/src/{Effect_HttpRouter.test.ts → effect/HttpRouter.test.ts} +69 -90
  53. package/src/experimental/EncryptedCookies.test.ts +125 -64
  54. package/src/experimental/SseHttpResponse.ts +0 -1
  55. package/src/hyper/Hyper.ts +89 -0
  56. package/src/{HyperHtml.test.ts → hyper/HyperHtml.test.ts} +13 -13
  57. package/src/{HyperHtml.ts → hyper/HyperHtml.ts} +2 -2
  58. package/src/{jsx.d.ts → hyper/jsx.d.ts} +1 -1
  59. package/src/index.ts +2 -4
  60. package/src/middlewares/BasicAuthMiddleware.test.ts +29 -19
  61. package/src/{NodeFileSystem.ts → node/FileSystem.ts} +6 -2
  62. package/src/testing/TestHttpClient.test.ts +26 -26
  63. package/src/testing/TestLogger.test.ts +27 -11
  64. package/src/x/datastar/Datastar.test.ts +47 -48
  65. package/src/x/datastar/Datastar.ts +1 -1
  66. package/src/x/tailwind/TailwindPlugin.test.ts +56 -58
  67. package/src/x/tailwind/plugin.ts +1 -1
  68. package/src/FileHttpRouter.test.ts +0 -239
  69. package/src/FileHttpRouter.ts +0 -194
  70. package/src/Hyper.ts +0 -194
  71. package/src/Route.test.ts +0 -1370
  72. package/src/RouteRender.ts +0 -40
  73. package/src/Router.test.ts +0 -375
  74. package/src/Router.ts +0 -255
  75. package/src/bun/BunRoute.test.ts +0 -480
  76. package/src/bun/BunRoute_bundles.test.ts +0 -219
  77. /package/src/{Bundle.ts → bundler/Bundle.ts} +0 -0
  78. /package/src/{BundleFiles.ts → bundler/BundleFiles.ts} +0 -0
  79. /package/src/{HyperNode.ts → hyper/HyperNode.ts} +0 -0
  80. /package/src/{jsx-runtime.ts → hyper/jsx-runtime.ts} +0 -0
  81. /package/src/{NodeUtils.ts → node/Utils.ts} +0 -0
@@ -1,3 +1,4 @@
1
+ // @ts-nocheck
1
2
  import * as HttpApp from "@effect/platform/HttpApp"
2
3
  import * as HttpServer from "@effect/platform/HttpServer"
3
4
  import * as HttpServerError from "@effect/platform/HttpServerError"
@@ -14,7 +15,11 @@ import * as Layer from "effect/Layer"
14
15
  import * as Option from "effect/Option"
15
16
  import type * as Scope from "effect/Scope"
16
17
  import * as FileRouter from "../FileRouter.ts"
18
+ import * as PathPattern from "../PathPattern.ts"
17
19
  import * as Random from "../Random.ts"
20
+ import * as Route from "../Route.ts"
21
+ import * as RouteHttp from "../RouteHttp.ts"
22
+ import * as RouteTree from "../RouteTree.ts"
18
23
  import EmptyHTML from "./_empty.html"
19
24
  import {
20
25
  makeResponse,
@@ -158,12 +163,60 @@ export const make = (
158
163
  })
159
164
  })
160
165
 
166
+ /**
167
+ * Provides HttpServer using BunHttpServer under the hood.
168
+ */
161
169
  export const layer = (
162
170
  options?: ServeOptions,
163
- ): Layer.Layer<BunHttpServer> =>
164
- Layer.scoped(BunHttpServer, make(options ?? {}))
171
+ ): Layer.Layer<HttpServer.HttpServer | BunHttpServer> =>
172
+ Layer.provideMerge(
173
+ Layer.scoped(HttpServer.HttpServer, makeBunServer),
174
+ Layer.scoped(BunHttpServer, make(options ?? {})),
175
+ )
176
+
177
+ /**
178
+ * Registers routes provided via {@link Route.layer}
179
+ */
180
+ export function layerAuto() {
181
+ return Layer.unwrapEffect(
182
+ Effect.gen(function*() {
183
+ const bunServer = yield* BunHttpServer
184
+ const routes = yield* Effect.serviceOption(Route.Routes)
185
+
186
+ if (Option.isSome(routes)) {
187
+ return layerRoutes(routes.value)
188
+ } else {
189
+ return Layer.empty
190
+ }
191
+ }),
192
+ )
193
+ }
165
194
 
166
- export const makeHttpServer: Effect.Effect<
195
+ /**
196
+ * Register routes in Bun.serve.
197
+ */
198
+ export function layerRoutes(
199
+ tree: RouteTree.RouteTree,
200
+ ): Layer.Layer<never, never, BunHttpServer> {
201
+ return Layer.effectDiscard(
202
+ Effect.gen(function*() {
203
+ const bunServer = yield* BunHttpServer
204
+ const routes: BunRoute.BunRoutes = {}
205
+ for (const [path, handler] of RouteHttp.walkHandles(tree)) {
206
+ for (const bunPath of PathPattern.toBun(path)) {
207
+ routes[bunPath] = handler
208
+ }
209
+ }
210
+
211
+ // TODO: think how can we define routes upfront rather
212
+ // than add them after startup?
213
+ // now that we have Rooutes.Route thats should be possible
214
+ bunServer.addRoutes(routes)
215
+ }),
216
+ )
217
+ }
218
+
219
+ const makeBunServer: Effect.Effect<
167
220
  HttpServer.HttpServer,
168
221
  never,
169
222
  Scope.Scope | BunHttpServer
@@ -228,35 +281,6 @@ export const makeHttpServer: Effect.Effect<
228
281
  })
229
282
  })
230
283
 
231
- export const layerServer = (
232
- options?: ServeOptions,
233
- ): Layer.Layer<HttpServer.HttpServer | BunHttpServer> =>
234
- Layer.provideMerge(
235
- Layer.scoped(HttpServer.HttpServer, makeHttpServer),
236
- layer(options ?? {}),
237
- )
238
-
239
- /**
240
- * Adds routes from {@like FileRouter.FileRouter} to Bun Server.
241
- *
242
- * It ain't clean but it works until we figure out interfaces
243
- * for other servers.
244
- */
245
- export function layerFileRouter() {
246
- return Layer.effectDiscard(
247
- Effect.gen(function*() {
248
- const bunServer = yield* BunHttpServer
249
- const manifest = yield* Effect.serviceOption(FileRouter.FileRouter)
250
-
251
- if (Option.isSome(manifest)) {
252
- const router = yield* FileRouter.fromManifest(manifest.value)
253
- const bunRoutes = yield* BunRoute.routesFromRouter(router)
254
- bunServer.addRoutes(bunRoutes)
255
- }
256
- }),
257
- )
258
- }
259
-
260
284
  const removeHost = (url: string) => {
261
285
  if (url[0] === "/") {
262
286
  return url
@@ -37,18 +37,30 @@ export class ServerRequestImpl extends Inspectable.Class
37
37
  {
38
38
  readonly [HttpServerRequest.TypeId]: HttpServerRequest.TypeId
39
39
  readonly [HttpIncomingMessage.TypeId]: HttpIncomingMessage.TypeId
40
+ readonly source: Request
41
+ resolve: (response: Response) => void
42
+ readonly url: string
43
+ private bunServer: BunServerInstance<WebSocketContext>
44
+ headersOverride?: Headers.Headers
45
+ private remoteAddressOverride?: string
40
46
 
41
47
  constructor(
42
- readonly source: Request,
43
- public resolve: (response: Response) => void,
44
- readonly url: string,
45
- private bunServer: BunServerInstance<WebSocketContext>,
46
- public headersOverride?: Headers.Headers,
47
- private remoteAddressOverride?: string,
48
+ source: Request,
49
+ resolve: (response: Response) => void,
50
+ url: string,
51
+ bunServer: BunServerInstance<WebSocketContext>,
52
+ headersOverride?: Headers.Headers,
53
+ remoteAddressOverride?: string,
48
54
  ) {
49
55
  super()
50
56
  this[HttpServerRequest.TypeId] = HttpServerRequest.TypeId
51
57
  this[HttpIncomingMessage.TypeId] = HttpIncomingMessage.TypeId
58
+ this.source = source
59
+ this.resolve = resolve
60
+ this.url = url
61
+ this.bunServer = bunServer
62
+ this.headersOverride = headersOverride
63
+ this.remoteAddressOverride = remoteAddressOverride
52
64
  }
53
65
 
54
66
  toJSON(): unknown {
@@ -1,4 +1,4 @@
1
- import * as t from "bun:test"
1
+ import * as test from "bun:test"
2
2
  import * as BunImportTrackerPlugin from "./BunImportTrackerPlugin.ts"
3
3
  import * as BunVirtualFilesPlugin from "./BunVirtualFilesPlugin.ts"
4
4
 
@@ -27,7 +27,7 @@ export const message = "Hello, World!"
27
27
  `,
28
28
  }
29
29
 
30
- t.it("virtual import", async () => {
30
+ test.it("virtual import", async () => {
31
31
  const trackerPlugin = BunImportTrackerPlugin.make({
32
32
  baseDir: Bun.fileURLToPath(import.meta.resolve("../..")),
33
33
  })
@@ -42,7 +42,7 @@ t.it("virtual import", async () => {
42
42
  ],
43
43
  })
44
44
 
45
- t
45
+ test
46
46
  .expect(
47
47
  [...trackerPlugin.state.entries()],
48
48
  )
@@ -1,49 +1,44 @@
1
- import * as HttpApp from "@effect/platform/HttpApp"
1
+ // @ts-nocheck
2
2
  import * as HttpServerRequest from "@effect/platform/HttpServerRequest"
3
3
  import * as HttpServerResponse from "@effect/platform/HttpServerResponse"
4
4
  import type * as Bun from "bun"
5
5
  import * as Array from "effect/Array"
6
6
  import * as Effect from "effect/Effect"
7
- import * as Function from "effect/Function"
8
7
  import * as Option from "effect/Option"
9
8
  import * as Predicate from "effect/Predicate"
10
- import type * as Runtime from "effect/Runtime"
11
- import * as HttpAppExtra from "../HttpAppExtra.ts"
12
- import * as HttpUtils from "../HttpUtils.ts"
13
- import * as HyperHtml from "../HyperHtml.ts"
9
+ import * as Hyper from "../hyper/Hyper.ts"
10
+ import * as HyperHtml from "../hyper/HyperHtml.ts"
14
11
  import * as Random from "../Random.ts"
15
12
  import * as Route from "../Route.ts"
16
- import * as Router from "../Router.ts"
17
- import * as RouteRender from "../RouteRender.ts"
18
13
  import * as RouterPattern from "../RouterPattern.ts"
19
14
  import * as BunHttpServer from "./BunHttpServer.ts"
20
15
 
21
- const TypeId: unique symbol = Symbol.for("effect-start/BunRoute")
16
+ const BunHandlerTypeId: unique symbol = Symbol.for("effect-start/BunHandler")
22
17
 
23
18
  const INTERNAL_FETCH_HEADER = "x-effect-start-internal-fetch"
24
19
 
25
- export type BunRoute =
26
- & Route.Route
20
+ export type BunHandler =
21
+ & Route.RouteHandler<string, Router.RouterError, BunHttpServer.BunHttpServer>
27
22
  & {
28
- [TypeId]: typeof TypeId
29
- // Prefix because Bun.serve routes ignore everything after `*` in wildcard patterns.
30
- // A suffix like `/*~internal` would match the same as `/*`, shadowing the internal route.
23
+ [BunHandlerTypeId]: typeof BunHandlerTypeId
31
24
  internalPathPrefix: string
32
25
  load: () => Promise<Bun.HTMLBundle>
33
26
  }
34
27
 
35
- export function html(
28
+ export function isBunHandler(input: unknown): input is BunHandler {
29
+ return typeof input === "function"
30
+ && Predicate.hasProperty(input, BunHandlerTypeId)
31
+ }
32
+
33
+ export function bundle(
36
34
  load: () => Promise<Bun.HTMLBundle | { default: Bun.HTMLBundle }>,
37
- ): BunRoute {
35
+ ): BunHandler {
38
36
  const internalPathPrefix = `/.BunRoute-${Random.token(6)}`
39
37
 
40
- const handler: Route.RouteHandler<
41
- HttpServerResponse.HttpServerResponse,
42
- Router.RouterError,
43
- BunHttpServer.BunHttpServer
44
- > = (context) =>
38
+ const handler = (context: Route.RouteContext, next: Route.RouteNext) =>
45
39
  Effect.gen(function*() {
46
- const originalRequest = context.request.source as Request
40
+ const request = yield* HttpServerRequest.HttpServerRequest
41
+ const originalRequest = request.source as Request
47
42
 
48
43
  if (
49
44
  originalRequest.headers.get(INTERNAL_FETCH_HEADER) === "true"
@@ -91,13 +86,13 @@ export function html(
91
86
  }),
92
87
  })
93
88
 
94
- const children = yield* context.next<Router.RouterError, never>()
89
+ const children = yield* next()
95
90
  let childrenHtml = ""
96
91
  if (children != null) {
97
92
  if (HttpServerResponse.isServerResponse(children)) {
98
93
  const webResponse = HttpServerResponse.toWeb(children)
99
94
  childrenHtml = yield* Effect.promise(() => webResponse.text())
100
- } else if (Route.isGenericJsxObject(children)) {
95
+ } else if (Hyper.isGenericJsxObject(children)) {
101
96
  childrenHtml = HyperHtml.renderToString(children)
102
97
  } else {
103
98
  childrenHtml = String(children)
@@ -105,81 +100,19 @@ export function html(
105
100
  }
106
101
 
107
102
  html = html.replace(/%yield%/g, childrenHtml)
108
- html = html.replace(/%slots\.(\w+)%/g, (_, name) =>
109
- context.slots[name] ?? "")
103
+ html = html.replace(
104
+ /%slots\.(\w+)%/g,
105
+ (_, name) => context.slots[name] ?? "",
106
+ )
110
107
 
111
- return HttpServerResponse
112
- .html(html)
108
+ return html
113
109
  })
114
110
 
115
- const route = Route.make({
116
- method: "*",
117
- media: "text/html",
118
- handler,
119
- schemas: {},
120
- })
121
-
122
- const bunRoute: BunRoute = Object.assign(
123
- Object.create(route),
124
- {
125
- [TypeId]: TypeId,
126
- internalPathPrefix,
127
- load: () => load().then(mod => "default" in mod ? mod.default : mod),
128
- set: [],
129
- },
130
- )
131
-
132
- bunRoute.set.push(bunRoute)
133
-
134
- return bunRoute
135
- }
136
-
137
- export function isBunRoute(input: unknown): input is BunRoute {
138
- return Predicate.hasProperty(input, TypeId)
139
- }
140
-
141
- function makeHandler(routes: Route.Route.Default[]) {
142
- return Effect.gen(function*() {
143
- const request = yield* HttpServerRequest.HttpServerRequest
144
- const accept = request.headers.accept ?? ""
145
-
146
- let selectedRoute: Route.Route.Default | undefined
147
-
148
- if (accept.includes("application/json")) {
149
- selectedRoute = routes.find((r) => r.media === "application/json")
150
- }
151
- if (!selectedRoute && accept.includes("text/plain")) {
152
- selectedRoute = routes.find((r) => r.media === "text/plain")
153
- }
154
- if (
155
- !selectedRoute
156
- && (accept.includes("text/html")
157
- || accept.includes("*/*")
158
- || !accept)
159
- ) {
160
- selectedRoute = routes.find((r) => r.media === "text/html")
161
- }
162
- if (!selectedRoute) {
163
- selectedRoute = routes[0]
164
- }
165
-
166
- if (!selectedRoute) {
167
- return HttpServerResponse.empty({ status: 406 })
168
- }
169
-
170
- const context: Route.RouteContext = {
171
- request,
172
- get url() {
173
- return HttpUtils.makeUrlFromRequest(request)
174
- },
175
- slots: {},
176
- next: () => Effect.void,
177
- }
178
-
179
- return yield* RouteRender.render(selectedRoute, context).pipe(
180
- Effect.catchAllCause((cause) => HttpAppExtra.renderError(cause, accept)),
181
- )
182
- })
111
+ return Object.assign(handler, {
112
+ [BunHandlerTypeId]: BunHandlerTypeId,
113
+ internalPathPrefix,
114
+ load: () => load().then(mod => "default" in mod ? mod.default : mod),
115
+ }) as BunHandler
183
116
  }
184
117
 
185
118
  type BunServerFetchHandler = (
@@ -249,120 +182,6 @@ export function validateBunPattern(
249
182
  return Option.none()
250
183
  }
251
184
 
252
- /**
253
- * Converts a RouterBuilder into Bun-compatible routes passed to {@link Bun.serve}.
254
- *
255
- * For BunRoutes (HtmlBundle), creates two routes:
256
- * - An internal route at `${path}~BunRoute-${nonce}:${path}` holding the actual HtmlBundle
257
- * - A proxy route at the original path that forwards requests to the internal route
258
- *
259
- * This allows middleware to be attached to the proxy route while Bun handles
260
- * the HtmlBundle natively on the internal route.
261
- */
262
- export function routesFromRouter(
263
- router: Router.Router.Any,
264
- runtime?: Runtime.Runtime<BunHttpServer.BunHttpServer>,
265
- ): Effect.Effect<BunRoutes, Router.RouterError, BunHttpServer.BunHttpServer> {
266
- return Effect.gen(function*() {
267
- const rt = runtime ?? (yield* Effect.runtime<BunHttpServer.BunHttpServer>())
268
- const result: BunRoutes = {}
269
-
270
- for (const entry of router.entries) {
271
- const { path, route: routeSet, layers } = entry
272
-
273
- const validationError = validateBunPattern(path)
274
- if (Option.isSome(validationError)) {
275
- return yield* Effect.fail(validationError.value)
276
- }
277
-
278
- for (const route of routeSet.set) {
279
- if (isBunRoute(route)) {
280
- const bundle = yield* Effect.promise(() => route.load())
281
- const bunPaths = RouterPattern.toBun(path)
282
- for (const bunPath of bunPaths) {
283
- const internalPath = `${route.internalPathPrefix}${bunPath}`
284
- result[internalPath] = bundle
285
- }
286
- }
287
- }
288
-
289
- for (const layer of layers) {
290
- for (const route of layer.set) {
291
- if (isBunRoute(route)) {
292
- const bundle = yield* Effect.promise(() => route.load())
293
- const bunPaths = RouterPattern.toBun(path)
294
- for (const bunPath of bunPaths) {
295
- const internalPath = `${route.internalPathPrefix}${bunPath}`
296
- result[internalPath] = bundle
297
- }
298
- }
299
- }
300
- }
301
- }
302
-
303
- for (const path of Object.keys(router.mounts)) {
304
- const routeSet = router.mounts[path]
305
-
306
- const validationError = validateBunPattern(path)
307
- if (Option.isSome(validationError)) {
308
- continue
309
- }
310
-
311
- const httpPaths = RouterPattern.toBun(path as Route.RoutePattern)
312
-
313
- const byMethod = new Map<Route.RouteMethod, Route.Route.Default[]>()
314
- for (const route of routeSet.set) {
315
- const existing = byMethod.get(route.method) ?? []
316
- existing.push(route)
317
- byMethod.set(route.method, existing)
318
- }
319
-
320
- const entry = router.entries.find((e) => e.path === path)
321
- const allMiddleware = (entry?.layers ?? [])
322
- .map((layer) => layer.httpMiddleware)
323
- .filter((m): m is Route.HttpMiddlewareFunction => m !== undefined)
324
-
325
- for (const [method, routes] of byMethod) {
326
- let httpApp: HttpApp.Default<any, any> = makeHandler(routes)
327
-
328
- for (const middleware of allMiddleware) {
329
- httpApp = middleware(httpApp)
330
- }
331
-
332
- const webHandler = HttpApp.toWebHandlerRuntime(rt)(httpApp)
333
- const handler: BunServerFetchHandler = (request) => {
334
- const url = new URL(request.url)
335
- if (url.pathname.startsWith("/.BunRoute-")) {
336
- return new Response(
337
- "Internal routing error: BunRoute internal path was not matched. "
338
- + "This indicates the HTMLBundle route was not registered. Please report a bug.",
339
- { status: 500 },
340
- )
341
- }
342
- return webHandler(request)
343
- }
344
-
345
- for (const httpPath of httpPaths) {
346
- if (method === "*") {
347
- if (!(httpPath in result)) {
348
- result[httpPath] = handler
349
- }
350
- } else {
351
- const existing = result[httpPath]
352
- if (isMethodHandlers(existing)) {
353
- existing[method] = handler
354
- } else if (!(httpPath in result)) {
355
- result[httpPath] = { [method]: handler }
356
- }
357
- }
358
- }
359
- }
360
- }
361
-
362
- return result
363
- })
364
- }
365
-
366
185
  export const isHTMLBundle = (handle: any) => {
367
186
  return (
368
187
  typeof handle === "object"
@@ -1,14 +1,14 @@
1
1
  import * as HttpRouter from "@effect/platform/HttpRouter"
2
2
  import * as HttpServerResponse from "@effect/platform/HttpServerResponse"
3
- import * as t from "bun:test"
3
+ import * as test from "bun:test"
4
4
  import * as Effect from "effect/Effect"
5
5
  import * as Layer from "effect/Layer"
6
- import IndexHtml from "../static/react-dashboard.html" with { type: "file" }
7
- import * as BunBundle from "./bun/BunBundle.ts"
6
+ import IndexHtml from "../../static/react-dashboard.html" with { type: "file" }
7
+ import * as BunBundle from "../bun/BunBundle.ts"
8
+ import { effectFn } from "../testing"
9
+ import * as TestHttpClient from "../testing/TestHttpClient.ts"
8
10
  import * as Bundle from "./Bundle.ts"
9
11
  import * as BundleHttp from "./BundleHttp.ts"
10
- import { effectFn } from "./testing"
11
- import * as TestHttpClient from "./testing/TestHttpClient.ts"
12
12
 
13
13
  const effect = effectFn(
14
14
  Layer.effect(
@@ -17,7 +17,7 @@ const effect = effectFn(
17
17
  ),
18
18
  )
19
19
 
20
- t.it("entrypoint with specific uri", () =>
20
+ test.it("entrypoint with specific uri", () =>
21
21
  effect(function*() {
22
22
  const App = HttpRouter.empty.pipe(
23
23
  HttpRouter.get(
@@ -28,19 +28,15 @@ t.it("entrypoint with specific uri", () =>
28
28
  const Client = TestHttpClient.make(App)
29
29
 
30
30
  const dashboardRes = yield* Client.get("/react-dashboard")
31
- t
32
- .expect(
33
- dashboardRes.status,
34
- )
31
+ test
32
+ .expect(dashboardRes.status)
35
33
  .toBe(200)
36
- t
37
- .expect(
38
- yield* dashboardRes.text,
39
- )
34
+ test
35
+ .expect(yield* dashboardRes.text)
40
36
  .toStartWith("<!DOCTYPE html>")
41
37
  }))
42
38
 
43
- t.it("entrypoint without uri parameter", () =>
39
+ test.it("entrypoint without uri parameter", () =>
44
40
  effect(function*() {
45
41
  const App = HttpRouter.empty.pipe(
46
42
  HttpRouter.get(
@@ -68,10 +64,8 @@ t.it("entrypoint without uri parameter", () =>
68
64
  () => HttpServerResponse.empty({ status: 404 }),
69
65
  ),
70
66
  )
71
- t
72
- .expect(
73
- indexRes.status,
74
- )
67
+ test
68
+ .expect(indexRes.status)
75
69
  .toBe(404)
76
70
 
77
71
  const indexPathRes = yield* Client.get("/index").pipe(
@@ -80,22 +74,16 @@ t.it("entrypoint without uri parameter", () =>
80
74
  () => HttpServerResponse.empty({ status: 404 }),
81
75
  ),
82
76
  )
83
- t
84
- .expect(
85
- indexPathRes.status,
86
- )
77
+ test
78
+ .expect(indexPathRes.status)
87
79
  .toBe(404)
88
80
 
89
81
  const dashboardRes = yield* Client.get("/react-dashboard")
90
- t
91
- .expect(
92
- dashboardRes.status,
93
- )
82
+ test
83
+ .expect(dashboardRes.status)
94
84
  .toBe(200)
95
- t
96
- .expect(
97
- yield* dashboardRes.text,
98
- )
85
+ test
86
+ .expect(yield* dashboardRes.text)
99
87
  .toStartWith("<!DOCTYPE html>")
100
88
 
101
89
  const nonexistentRes = yield* Client.get("/nonexistent").pipe(
@@ -104,14 +92,12 @@ t.it("entrypoint without uri parameter", () =>
104
92
  () => HttpServerResponse.empty({ status: 404 }),
105
93
  ),
106
94
  )
107
- t
108
- .expect(
109
- nonexistentRes.status,
110
- )
95
+ test
96
+ .expect(nonexistentRes.status)
111
97
  .toBe(404)
112
98
  }))
113
99
 
114
- t.it("withEntrypoints middleware", () =>
100
+ test.it("withEntrypoints middleware", () =>
115
101
  effect(function*() {
116
102
  const fallbackApp = Effect.succeed(
117
103
  HttpServerResponse.text("Fallback", { status: 404 }),
@@ -121,38 +107,26 @@ t.it("withEntrypoints middleware", () =>
121
107
  const Client = TestHttpClient.make(App)
122
108
 
123
109
  const rootRes = yield* Client.get("/")
124
- t
125
- .expect(
126
- rootRes.status,
127
- )
110
+ test
111
+ .expect(rootRes.status)
128
112
  .toBe(404)
129
- t
130
- .expect(
131
- yield* rootRes.text,
132
- )
113
+ test
114
+ .expect(yield* rootRes.text)
133
115
  .toBe("Fallback")
134
116
 
135
117
  const dashboardRes = yield* Client.get("/react-dashboard")
136
- t
137
- .expect(
138
- dashboardRes.status,
139
- )
118
+ test
119
+ .expect(dashboardRes.status)
140
120
  .toBe(200)
141
- t
142
- .expect(
143
- yield* dashboardRes.text,
144
- )
121
+ test
122
+ .expect(yield* dashboardRes.text)
145
123
  .toStartWith("<!DOCTYPE html>")
146
124
 
147
125
  const nonexistentRes = yield* Client.get("/nonexistent")
148
- t
149
- .expect(
150
- nonexistentRes.status,
151
- )
126
+ test
127
+ .expect(nonexistentRes.status)
152
128
  .toBe(404)
153
- t
154
- .expect(
155
- yield* nonexistentRes.text,
156
- )
129
+ test
130
+ .expect(yield* nonexistentRes.text)
157
131
  .toBe("Fallback")
158
132
  }))
@@ -12,9 +12,8 @@ import * as Scope from "effect/Scope"
12
12
  import * as Stream from "effect/Stream"
13
13
  import * as NPath from "node:path"
14
14
  import * as NUrl from "node:url"
15
+ import * as SseHttpResponse from "../experimental/SseHttpResponse.ts"
15
16
  import * as Bundle from "./Bundle.ts"
16
- import * as SseHttpResponse from "./experimental/SseHttpResponse.ts"
17
-
18
17
 
19
18
  const DefaultBundleEndpoint = "/_bundle"
20
19
 
@@ -10,7 +10,7 @@
10
10
  import type {
11
11
  BundleEvent,
12
12
  BundleManifest,
13
- } from "../Bundle.ts"
13
+ } from "../bundler/Bundle.ts"
14
14
  import { showBuildError } from "./Overlay.ts"
15
15
  import * as ScrollState from "./ScrollState.ts"
16
16