effect-start 0.14.0 → 0.16.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 (87) hide show
  1. package/package.json +8 -9
  2. package/src/Commander.test.ts +507 -245
  3. package/src/ContentNegotiation.test.ts +603 -0
  4. package/src/ContentNegotiation.ts +542 -0
  5. package/src/Entity.test.ts +592 -0
  6. package/src/Entity.ts +362 -0
  7. package/src/FileRouter.ts +16 -12
  8. package/src/{FileRouterCodegen.test.ts → FileRouterCodegen.todo.ts} +384 -219
  9. package/src/FileRouterCodegen.ts +6 -6
  10. package/src/FileRouterPattern.test.ts +93 -62
  11. package/src/FileRouter_files.test.ts +5 -5
  12. package/src/FileRouter_path.test.ts +121 -69
  13. package/src/FileRouter_tree.test.ts +62 -56
  14. package/src/FileSystemExtra.test.ts +46 -30
  15. package/src/Http.test.ts +319 -0
  16. package/src/Http.ts +167 -0
  17. package/src/HttpAppExtra.test.ts +39 -20
  18. package/src/HttpAppExtra.ts +0 -1
  19. package/src/HttpUtils.test.ts +35 -18
  20. package/src/HttpUtils.ts +2 -0
  21. package/src/PathPattern.test.ts +648 -0
  22. package/src/PathPattern.ts +485 -0
  23. package/src/Route.ts +266 -1069
  24. package/src/RouteBody.test.ts +234 -0
  25. package/src/RouteBody.ts +193 -0
  26. package/src/RouteHook.test.ts +40 -0
  27. package/src/RouteHook.ts +106 -0
  28. package/src/RouteHttp.test.ts +2906 -0
  29. package/src/RouteHttp.ts +427 -0
  30. package/src/RouteHttpTracer.ts +92 -0
  31. package/src/RouteMount.test.ts +481 -0
  32. package/src/RouteMount.ts +470 -0
  33. package/src/RouteSchema.test.ts +427 -0
  34. package/src/RouteSchema.ts +423 -0
  35. package/src/RouteTree.test.ts +494 -0
  36. package/src/RouteTree.ts +219 -0
  37. package/src/RouteTrie.test.ts +322 -0
  38. package/src/RouteTrie.ts +224 -0
  39. package/src/RouterPattern.test.ts +569 -548
  40. package/src/RouterPattern.ts +7 -7
  41. package/src/Start.ts +3 -3
  42. package/src/StreamExtra.ts +21 -1
  43. package/src/TuplePathPattern.ts +64 -0
  44. package/src/Values.test.ts +263 -0
  45. package/src/Values.ts +76 -0
  46. package/src/bun/BunBundle.test.ts +36 -42
  47. package/src/bun/BunBundle.ts +2 -2
  48. package/src/bun/BunBundle_imports.test.ts +4 -6
  49. package/src/bun/BunHttpServer.test.ts +183 -6
  50. package/src/bun/BunHttpServer.ts +72 -32
  51. package/src/bun/BunHttpServer_web.ts +18 -6
  52. package/src/bun/BunImportTrackerPlugin.test.ts +3 -3
  53. package/src/bun/BunRoute.test.ts +124 -442
  54. package/src/bun/BunRoute.ts +146 -286
  55. package/src/{BundleHttp.test.ts → bundler/BundleHttp.test.ts} +34 -60
  56. package/src/{BundleHttp.ts → bundler/BundleHttp.ts} +1 -2
  57. package/src/client/index.ts +1 -1
  58. package/src/{Effect_HttpRouter.test.ts → effect/HttpRouter.test.ts} +69 -90
  59. package/src/experimental/EncryptedCookies.test.ts +125 -64
  60. package/src/experimental/SseHttpResponse.ts +0 -1
  61. package/src/hyper/Hyper.ts +89 -0
  62. package/src/{HyperHtml.test.ts → hyper/HyperHtml.test.ts} +13 -13
  63. package/src/{HyperHtml.ts → hyper/HyperHtml.ts} +2 -2
  64. package/src/{jsx.d.ts → hyper/jsx.d.ts} +1 -1
  65. package/src/index.ts +3 -4
  66. package/src/middlewares/BasicAuthMiddleware.test.ts +29 -19
  67. package/src/{NodeFileSystem.ts → node/FileSystem.ts} +6 -2
  68. package/src/testing/TestHttpClient.test.ts +26 -26
  69. package/src/testing/TestLogger.test.ts +27 -14
  70. package/src/testing/TestLogger.ts +15 -9
  71. package/src/x/datastar/Datastar.test.ts +47 -48
  72. package/src/x/datastar/Datastar.ts +1 -1
  73. package/src/x/tailwind/TailwindPlugin.test.ts +56 -58
  74. package/src/x/tailwind/plugin.ts +1 -1
  75. package/src/FileHttpRouter.test.ts +0 -239
  76. package/src/FileHttpRouter.ts +0 -194
  77. package/src/Hyper.ts +0 -194
  78. package/src/Route.test.ts +0 -1370
  79. package/src/RouteRender.ts +0 -40
  80. package/src/Router.test.ts +0 -375
  81. package/src/Router.ts +0 -255
  82. package/src/bun/BunRoute_bundles.test.ts +0 -219
  83. /package/src/{Bundle.ts → bundler/Bundle.ts} +0 -0
  84. /package/src/{BundleFiles.ts → bundler/BundleFiles.ts} +0 -0
  85. /package/src/{HyperNode.ts → hyper/HyperNode.ts} +0 -0
  86. /package/src/{jsx-runtime.ts → hyper/jsx-runtime.ts} +0 -0
  87. /package/src/{NodeUtils.ts → node/Utils.ts} +0 -0
@@ -6,8 +6,6 @@ import * as Schema from "effect/Schema"
6
6
  import * as NPath from "node:path"
7
7
  import * as FileRouter from "./FileRouter.ts"
8
8
  import * as FileRouterPattern from "./FileRouterPattern.ts"
9
- import * as Route from "./Route.ts"
10
- import * as Router from "./Router.ts"
11
9
  import * as SchemaExtra from "./SchemaExtra.ts"
12
10
 
13
11
  export function validateRouteModule(
@@ -16,10 +14,13 @@ export function validateRouteModule(
16
14
  if (typeof module !== "object" || module === null) {
17
15
  return false
18
16
  }
17
+
19
18
  if (!("default" in module)) {
20
19
  return false
21
20
  }
22
- return Route.isRouteSet(module.default)
21
+
22
+ // TODO: verify we're exporting a proper shape
23
+ return true
23
24
  }
24
25
 
25
26
  export function generatePathParamsSchema(
@@ -79,7 +80,8 @@ export function validateRouteModules(
79
80
  }
80
81
 
81
82
  const routeSet = module.default
82
- const userSchema = routeSet.schema?.PathParams
83
+ // extract user schema
84
+ const userSchema = undefined
83
85
 
84
86
  if (
85
87
  expectedSchema
@@ -187,8 +189,6 @@ export function generateCode(
187
189
 
188
190
  return `${header}
189
191
 
190
- import type { Router } from "${routerModuleId}"
191
-
192
192
  export const routes = ${routesArray} as const
193
193
  `
194
194
  }
@@ -1,71 +1,100 @@
1
- import * as t from "bun:test"
1
+ import * as test from "bun:test"
2
2
  import * as FileRouterPattern from "./FileRouterPattern.ts"
3
3
 
4
- t.it("empty path", () => {
5
- t.expect(FileRouterPattern.parse("")).toEqual([])
6
- t.expect(FileRouterPattern.parse("/")).toEqual([])
4
+ test.it("empty path", () => {
5
+ test
6
+ .expect(FileRouterPattern.parse(""))
7
+ .toEqual([])
8
+ test
9
+ .expect(FileRouterPattern.parse("/"))
10
+ .toEqual([])
7
11
  })
8
12
 
9
- t.it("groups", () => {
10
- t.expect(FileRouterPattern.parse("(admin)")).toEqual([
11
- { _tag: "GroupSegment", name: "admin" },
12
- ])
13
- t.expect(FileRouterPattern.parse("/(admin)/users")).toEqual([
14
- { _tag: "GroupSegment", name: "admin" },
15
- { _tag: "LiteralSegment", value: "users" },
16
- ])
17
- t.expect(FileRouterPattern.parse("(auth)/login/(step1)")).toEqual([
18
- { _tag: "GroupSegment", name: "auth" },
19
- { _tag: "LiteralSegment", value: "login" },
20
- { _tag: "GroupSegment", name: "step1" },
21
- ])
13
+ test.it("groups", () => {
14
+ test
15
+ .expect(FileRouterPattern.parse("(admin)"))
16
+ .toEqual([
17
+ { _tag: "GroupSegment", name: "admin" },
18
+ ])
19
+ test
20
+ .expect(FileRouterPattern.parse("/(admin)/users"))
21
+ .toEqual([
22
+ { _tag: "GroupSegment", name: "admin" },
23
+ { _tag: "LiteralSegment", value: "users" },
24
+ ])
25
+ test
26
+ .expect(FileRouterPattern.parse("(auth)/login/(step1)"))
27
+ .toEqual([
28
+ { _tag: "GroupSegment", name: "auth" },
29
+ { _tag: "LiteralSegment", value: "login" },
30
+ { _tag: "GroupSegment", name: "step1" },
31
+ ])
22
32
  })
23
33
 
24
- t.it("handle files parsed as Literal", () => {
25
- t.expect(FileRouterPattern.parse("route.ts")).toEqual([
26
- { _tag: "LiteralSegment", value: "route.ts" },
27
- ])
28
- t.expect(FileRouterPattern.parse("/api/route.js")).toEqual([
29
- { _tag: "LiteralSegment", value: "api" },
30
- { _tag: "LiteralSegment", value: "route.js" },
31
- ])
32
- t.expect(FileRouterPattern.parse("layer.tsx")).toEqual([
33
- { _tag: "LiteralSegment", value: "layer.tsx" },
34
- ])
35
- t.expect(FileRouterPattern.parse("/blog/layer.jsx")).toEqual([
36
- { _tag: "LiteralSegment", value: "blog" },
37
- { _tag: "LiteralSegment", value: "layer.jsx" },
38
- ])
34
+ test.it("handle files parsed as Literal", () => {
35
+ test
36
+ .expect(FileRouterPattern.parse("route.ts"))
37
+ .toEqual([
38
+ { _tag: "LiteralSegment", value: "route.ts" },
39
+ ])
40
+ test
41
+ .expect(FileRouterPattern.parse("/api/route.js"))
42
+ .toEqual([
43
+ { _tag: "LiteralSegment", value: "api" },
44
+ { _tag: "LiteralSegment", value: "route.js" },
45
+ ])
46
+ test
47
+ .expect(FileRouterPattern.parse("layer.tsx"))
48
+ .toEqual([
49
+ { _tag: "LiteralSegment", value: "layer.tsx" },
50
+ ])
51
+ test
52
+ .expect(FileRouterPattern.parse("/blog/layer.jsx"))
53
+ .toEqual([
54
+ { _tag: "LiteralSegment", value: "blog" },
55
+ { _tag: "LiteralSegment", value: "layer.jsx" },
56
+ ])
39
57
  })
40
58
 
41
- t.it("params and rest", () => {
42
- t.expect(FileRouterPattern.parse("users/[userId]/posts")).toEqual([
43
- { _tag: "LiteralSegment", value: "users" },
44
- { _tag: "ParamSegment", name: "userId" },
45
- { _tag: "LiteralSegment", value: "posts" },
46
- ])
47
-
48
- t.expect(FileRouterPattern.parse("api/[[...path]]")).toEqual([
49
- { _tag: "LiteralSegment", value: "api" },
50
- { _tag: "RestSegment", name: "path", optional: true },
51
- ])
59
+ test.it("params and rest", () => {
60
+ test
61
+ .expect(FileRouterPattern.parse("users/[userId]/posts"))
62
+ .toEqual([
63
+ { _tag: "LiteralSegment", value: "users" },
64
+ { _tag: "ParamSegment", name: "userId" },
65
+ { _tag: "LiteralSegment", value: "posts" },
66
+ ])
67
+ test
68
+ .expect(FileRouterPattern.parse("api/[[...path]]"))
69
+ .toEqual([
70
+ { _tag: "LiteralSegment", value: "api" },
71
+ { _tag: "RestSegment", name: "path", optional: true },
72
+ ])
52
73
  })
53
74
 
54
- t.it("invalid paths", () => {
55
- t.expect(() => FileRouterPattern.parse("$...")).toThrow()
56
- t.expect(() => FileRouterPattern.parse("invalid%char")).toThrow()
57
- t.expect(() => FileRouterPattern.parse("path with spaces")).toThrow()
75
+ test.it("invalid paths", () => {
76
+ test
77
+ .expect(() => FileRouterPattern.parse("$..."))
78
+ .toThrow()
79
+ test
80
+ .expect(() => FileRouterPattern.parse("invalid%char"))
81
+ .toThrow()
82
+ test
83
+ .expect(() => FileRouterPattern.parse("path with spaces"))
84
+ .toThrow()
58
85
  })
59
86
 
60
- t.it("segments with extensions (literal with dots)", () => {
61
- t.expect(FileRouterPattern.parse("events.json/route.ts")).toEqual([
62
- { _tag: "LiteralSegment", value: "events.json" },
63
- { _tag: "LiteralSegment", value: "route.ts" },
64
- ])
87
+ test.it("segments with extensions (literal with dots)", () => {
88
+ test
89
+ .expect(FileRouterPattern.parse("events.json/route.ts"))
90
+ .toEqual([
91
+ { _tag: "LiteralSegment", value: "events.json" },
92
+ { _tag: "LiteralSegment", value: "route.ts" },
93
+ ])
65
94
  })
66
95
 
67
- t.it("formatSegment", () => {
68
- t
96
+ test.it("formatSegment", () => {
97
+ test
69
98
  .expect(
70
99
  FileRouterPattern.formatSegment({
71
100
  _tag: "LiteralSegment",
@@ -73,31 +102,33 @@ t.it("formatSegment", () => {
73
102
  }),
74
103
  )
75
104
  .toBe("users")
76
- t
105
+ test
77
106
  .expect(
78
107
  FileRouterPattern.formatSegment({ _tag: "ParamSegment", name: "id" }),
79
108
  )
80
109
  .toBe("[id]")
81
- t
110
+ test
82
111
  .expect(
83
112
  FileRouterPattern.formatSegment({ _tag: "GroupSegment", name: "admin" }),
84
113
  )
85
114
  .toBe("(admin)")
86
- t
115
+ test
87
116
  .expect(
88
117
  FileRouterPattern.formatSegment({ _tag: "RestSegment", name: "path" }),
89
118
  )
90
119
  .toBe("[...path]")
91
120
  })
92
121
 
93
- t.it("format", () => {
94
- t.expect(FileRouterPattern.format([])).toBe("/")
95
- t
122
+ test.it("format", () => {
123
+ test
124
+ .expect(FileRouterPattern.format([]))
125
+ .toBe("/")
126
+ test
96
127
  .expect(
97
128
  FileRouterPattern.format([{ _tag: "LiteralSegment", value: "users" }]),
98
129
  )
99
130
  .toBe("/users")
100
- t
131
+ test
101
132
  .expect(
102
133
  FileRouterPattern.format([
103
134
  { _tag: "GroupSegment", name: "admin" },
@@ -105,7 +136,7 @@ t.it("format", () => {
105
136
  ]),
106
137
  )
107
138
  .toBe("/(admin)/users")
108
- t
139
+ test
109
140
  .expect(
110
141
  FileRouterPattern.format([
111
142
  { _tag: "LiteralSegment", value: "users" },
@@ -1,4 +1,4 @@
1
- import * as t from "bun:test"
1
+ import * as test from "bun:test"
2
2
  import { MemoryFileSystem } from "effect-memfs"
3
3
  import * as Effect from "effect/Effect"
4
4
  import * as FileRouter from "./FileRouter.ts"
@@ -15,13 +15,13 @@ const Files = {
15
15
 
16
16
  const effect = effectFn()
17
17
 
18
- t.it("walks routes", () =>
18
+ test.it("walks routes", () =>
19
19
  effect(function*() {
20
20
  const files = yield* FileRouter.walkRoutesDirectory("/routes").pipe(
21
21
  Effect.provide(MemoryFileSystem.layerWith(Files)),
22
22
  )
23
23
 
24
- t
24
+ test
25
25
  .expect(
26
26
  files.map(v => v.modulePath),
27
27
  )
@@ -35,7 +35,7 @@ t.it("walks routes", () =>
35
35
  ])
36
36
  }))
37
37
 
38
- t.it("walks routes with rest", () =>
38
+ test.it("walks routes with rest", () =>
39
39
  effect(function*() {
40
40
  const files = yield* FileRouter.walkRoutesDirectory("/routes").pipe(
41
41
  Effect.provide(
@@ -47,7 +47,7 @@ t.it("walks routes with rest", () =>
47
47
  ),
48
48
  )
49
49
 
50
- t
50
+ test
51
51
  .expect(
52
52
  files.map(v => v.modulePath),
53
53
  )
@@ -1,93 +1,145 @@
1
- import * as t from "bun:test"
1
+ import * as test from "bun:test"
2
2
  import * as FileRouter from "./FileRouter.ts"
3
3
 
4
- t.it("empty path", () => {
5
- t.expect(FileRouter.parse("")).toEqual([])
6
- t.expect(FileRouter.parse("/")).toEqual([])
4
+ test.it("empty path", () => {
5
+ test
6
+ .expect(FileRouter.parse(""))
7
+ .toEqual([])
8
+ test
9
+ .expect(FileRouter.parse("/"))
10
+ .toEqual([])
7
11
  })
8
12
 
9
- t.it("groups", () => {
10
- t.expect(FileRouter.parse("(admin)")).toEqual([
11
- { _tag: "GroupSegment", name: "admin" },
12
- ])
13
- t.expect(FileRouter.parse("/(admin)/users")).toEqual([
14
- { _tag: "GroupSegment", name: "admin" },
15
- { _tag: "LiteralSegment", value: "users" },
16
- ])
17
- t.expect(FileRouter.parse("(auth)/login/(step1)")).toEqual([
18
- { _tag: "GroupSegment", name: "auth" },
19
- { _tag: "LiteralSegment", value: "login" },
20
- { _tag: "GroupSegment", name: "step1" },
21
- ])
13
+ test.it("groups", () => {
14
+ test
15
+ .expect(FileRouter.parse("(admin)"))
16
+ .toEqual([
17
+ { _tag: "GroupSegment", name: "admin" },
18
+ ])
19
+ test
20
+ .expect(FileRouter.parse("/(admin)/users"))
21
+ .toEqual([
22
+ { _tag: "GroupSegment", name: "admin" },
23
+ { _tag: "LiteralSegment", value: "users" },
24
+ ])
25
+ test
26
+ .expect(FileRouter.parse("(auth)/login/(step1)"))
27
+ .toEqual([
28
+ { _tag: "GroupSegment", name: "auth" },
29
+ { _tag: "LiteralSegment", value: "login" },
30
+ { _tag: "GroupSegment", name: "step1" },
31
+ ])
22
32
  })
23
33
 
24
- t.it("handle files parsed as Literal", () => {
25
- t.expect(FileRouter.parse("route.ts")).toEqual([
26
- { _tag: "LiteralSegment", value: "route.ts" },
27
- ])
28
- t.expect(FileRouter.parse("/api/route.js")).toEqual([
29
- { _tag: "LiteralSegment", value: "api" },
30
- { _tag: "LiteralSegment", value: "route.js" },
31
- ])
32
- t.expect(FileRouter.parse("layer.tsx")).toEqual([
33
- { _tag: "LiteralSegment", value: "layer.tsx" },
34
- ])
35
- t.expect(FileRouter.parse("/blog/layer.jsx")).toEqual([
36
- { _tag: "LiteralSegment", value: "blog" },
37
- { _tag: "LiteralSegment", value: "layer.jsx" },
38
- ])
34
+ test.it("handle files parsed as Literal", () => {
35
+ test
36
+ .expect(FileRouter.parse("route.ts"))
37
+ .toEqual([
38
+ { _tag: "LiteralSegment", value: "route.ts" },
39
+ ])
40
+ test
41
+ .expect(FileRouter.parse("/api/route.js"))
42
+ .toEqual([
43
+ { _tag: "LiteralSegment", value: "api" },
44
+ { _tag: "LiteralSegment", value: "route.js" },
45
+ ])
46
+ test
47
+ .expect(FileRouter.parse("layer.tsx"))
48
+ .toEqual([
49
+ { _tag: "LiteralSegment", value: "layer.tsx" },
50
+ ])
51
+ test
52
+ .expect(FileRouter.parse("/blog/layer.jsx"))
53
+ .toEqual([
54
+ { _tag: "LiteralSegment", value: "blog" },
55
+ { _tag: "LiteralSegment", value: "layer.jsx" },
56
+ ])
39
57
  })
40
58
 
41
- t.it("parseRoute extracts handle from Literal", () => {
59
+ test.it("parseRoute extracts handle from Literal", () => {
42
60
  const route = FileRouter.parseRoute("users/route.tsx")
43
- t.expect(route.handle).toBe("route")
44
- t.expect(route.routePath).toBe("/users")
45
- t.expect(route.segments).toEqual([
46
- { _tag: "LiteralSegment", value: "users" },
47
- ])
61
+ test
62
+ .expect(route.handle)
63
+ .toBe("route")
64
+ test
65
+ .expect(route.routePath)
66
+ .toBe("/users")
67
+ test
68
+ .expect(route.segments)
69
+ .toEqual([
70
+ { _tag: "LiteralSegment", value: "users" },
71
+ ])
48
72
 
49
73
  const layer = FileRouter.parseRoute("api/layer.ts")
50
- t.expect(layer.handle).toBe("layer")
51
- t.expect(layer.routePath).toBe("/api")
74
+ test
75
+ .expect(layer.handle)
76
+ .toBe("layer")
77
+ test
78
+ .expect(layer.routePath)
79
+ .toBe("/api")
52
80
  })
53
81
 
54
- t.it("parseRoute with groups", () => {
82
+ test.it("parseRoute with groups", () => {
55
83
  const route = FileRouter.parseRoute("(admin)/users/route.tsx")
56
- t.expect(route.handle).toBe("route")
57
- t.expect(route.routePath).toBe("/users")
58
- t.expect(route.segments).toEqual([
59
- { _tag: "GroupSegment", name: "admin" },
60
- { _tag: "LiteralSegment", value: "users" },
61
- ])
84
+ test
85
+ .expect(route.handle)
86
+ .toBe("route")
87
+ test
88
+ .expect(route.routePath)
89
+ .toBe("/users")
90
+ test
91
+ .expect(route.segments)
92
+ .toEqual([
93
+ { _tag: "GroupSegment", name: "admin" },
94
+ { _tag: "LiteralSegment", value: "users" },
95
+ ])
62
96
  })
63
97
 
64
- t.it("parseRoute with params and rest", () => {
98
+ test.it("parseRoute with params and rest", () => {
65
99
  const route = FileRouter.parseRoute("users/[userId]/posts/route.tsx")
66
- t.expect(route.handle).toBe("route")
67
- t.expect(route.routePath).toBe("/users/[userId]/posts")
68
- t.expect(route.segments).toEqual([
69
- { _tag: "LiteralSegment", value: "users" },
70
- { _tag: "ParamSegment", name: "userId" },
71
- { _tag: "LiteralSegment", value: "posts" },
72
- ])
100
+ test
101
+ .expect(route.handle)
102
+ .toBe("route")
103
+ test
104
+ .expect(route.routePath)
105
+ .toBe("/users/[userId]/posts")
106
+ test
107
+ .expect(route.segments)
108
+ .toEqual([
109
+ { _tag: "LiteralSegment", value: "users" },
110
+ { _tag: "ParamSegment", name: "userId" },
111
+ { _tag: "LiteralSegment", value: "posts" },
112
+ ])
73
113
 
74
114
  const rest = FileRouter.parseRoute("api/[[...path]]/route.ts")
75
- t.expect(rest.handle).toBe("route")
76
- t.expect(rest.segments).toEqual([
77
- { _tag: "LiteralSegment", value: "api" },
78
- { _tag: "RestSegment", name: "path", optional: true },
79
- ])
115
+ test
116
+ .expect(rest.handle)
117
+ .toBe("route")
118
+ test
119
+ .expect(rest.segments)
120
+ .toEqual([
121
+ { _tag: "LiteralSegment", value: "api" },
122
+ { _tag: "RestSegment", name: "path", optional: true },
123
+ ])
80
124
  })
81
125
 
82
- t.it("invalid paths", () => {
83
- t.expect(() => FileRouter.parse("$...")).toThrow()
84
- t.expect(() => FileRouter.parse("invalid%char")).toThrow()
85
- t.expect(() => FileRouter.parse("path with spaces")).toThrow()
126
+ test.it("invalid paths", () => {
127
+ test
128
+ .expect(() => FileRouter.parse("$..."))
129
+ .toThrow()
130
+ test
131
+ .expect(() => FileRouter.parse("invalid%char"))
132
+ .toThrow()
133
+ test
134
+ .expect(() => FileRouter.parse("path with spaces"))
135
+ .toThrow()
86
136
  })
87
137
 
88
- t.it("segments with extensions (literal with dots)", () => {
89
- t.expect(FileRouter.parse("events.json/route.ts")).toEqual([
90
- { _tag: "LiteralSegment", value: "events.json" },
91
- { _tag: "LiteralSegment", value: "route.ts" },
92
- ])
138
+ test.it("segments with extensions (literal with dots)", () => {
139
+ test
140
+ .expect(FileRouter.parse("events.json/route.ts"))
141
+ .toEqual([
142
+ { _tag: "LiteralSegment", value: "events.json" },
143
+ { _tag: "LiteralSegment", value: "route.ts" },
144
+ ])
93
145
  })
@@ -1,7 +1,7 @@
1
- import * as t from "bun:test"
1
+ import * as test from "bun:test"
2
2
  import * as FileRouter from "./FileRouter.ts"
3
3
 
4
- t.it("tree with root only", () => {
4
+ test.it("tree with root only", () => {
5
5
  const handles = [
6
6
  "route.tsx",
7
7
  "layer.tsx",
@@ -9,31 +9,35 @@ t.it("tree with root only", () => {
9
9
  .map(FileRouter.parseRoute)
10
10
  const tree = FileRouter.treeFromRouteHandles(handles)
11
11
 
12
- t.expect(tree).toEqual({
13
- path: "/",
14
- handles: [
15
- t.expect.objectContaining({
16
- handle: "route",
17
- }),
18
- t.expect.objectContaining({
19
- handle: "layer",
20
- }),
21
- ],
22
- })
12
+ test
13
+ .expect(tree)
14
+ .toEqual({
15
+ path: "/",
16
+ handles: [
17
+ test.expect.objectContaining({
18
+ handle: "route",
19
+ }),
20
+ test.expect.objectContaining({
21
+ handle: "layer",
22
+ }),
23
+ ],
24
+ })
23
25
  })
24
26
 
25
- t.it("tree without root", () => {
27
+ test.it("tree without root", () => {
26
28
  const handles = []
27
29
  .map(FileRouter.parseRoute)
28
30
  const tree = FileRouter.treeFromRouteHandles(handles)
29
31
 
30
- t.expect(tree).toEqual({
31
- path: "/",
32
- handles: [],
33
- })
32
+ test
33
+ .expect(tree)
34
+ .toEqual({
35
+ path: "/",
36
+ handles: [],
37
+ })
34
38
  })
35
39
 
36
- t.it("deep tree", () => {
40
+ test.it("deep tree", () => {
37
41
  const handles = [
38
42
  "users/route.tsx",
39
43
  "users/layer.tsx",
@@ -43,41 +47,43 @@ t.it("deep tree", () => {
43
47
  .map(FileRouter.parseRoute)
44
48
  const tree = FileRouter.treeFromRouteHandles(handles)
45
49
 
46
- t.expect(tree).toEqual({
47
- path: "/",
48
- handles: [
49
- t.expect.objectContaining({
50
- handle: "layer",
51
- }),
52
- ],
53
- children: [
54
- {
55
- path: "/users",
56
- handles: [
57
- t.expect.objectContaining({
58
- handle: "route",
59
- }),
60
- t.expect.objectContaining({
61
- handle: "layer",
62
- }),
63
- ],
64
- children: [
65
- {
66
- path: "/[userId]",
67
- handles: [
68
- t.expect.objectContaining({
69
- handle: "route",
70
- }),
71
- ],
72
- },
73
- ],
74
- },
75
- ],
76
- })
50
+ test
51
+ .expect(tree)
52
+ .toEqual({
53
+ path: "/",
54
+ handles: [
55
+ test.expect.objectContaining({
56
+ handle: "layer",
57
+ }),
58
+ ],
59
+ children: [
60
+ {
61
+ path: "/users",
62
+ handles: [
63
+ test.expect.objectContaining({
64
+ handle: "route",
65
+ }),
66
+ test.expect.objectContaining({
67
+ handle: "layer",
68
+ }),
69
+ ],
70
+ children: [
71
+ {
72
+ path: "/[userId]",
73
+ handles: [
74
+ test.expect.objectContaining({
75
+ handle: "route",
76
+ }),
77
+ ],
78
+ },
79
+ ],
80
+ },
81
+ ],
82
+ })
77
83
  })
78
84
 
79
- t.it("throws on overlapping routes from groups", () => {
80
- t
85
+ test.it("throws on overlapping routes from groups", () => {
86
+ test
81
87
  .expect(() => {
82
88
  const handles = [
83
89
  "(admin)/users/route.tsx",
@@ -92,8 +98,8 @@ t.it("throws on overlapping routes from groups", () => {
92
98
  .toThrow("Conflicting routes detected at path /users")
93
99
  })
94
100
 
95
- t.it("throws on overlapping routes with same path", () => {
96
- t
101
+ test.it("throws on overlapping routes with same path", () => {
102
+ test
97
103
  .expect(() => {
98
104
  const handles = [
99
105
  "about/route.tsx",
@@ -108,8 +114,8 @@ t.it("throws on overlapping routes with same path", () => {
108
114
  .toThrow("Conflicting routes detected at path /about")
109
115
  })
110
116
 
111
- t.it("allows route and layer at same path", () => {
112
- t
117
+ test.it("allows route and layer at same path", () => {
118
+ test
113
119
  .expect(() => {
114
120
  const handles = [
115
121
  "users/route.tsx",