effect-start 0.18.0 → 0.20.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 (203) hide show
  1. package/README.md +3 -3
  2. package/dist/Development.d.ts +8 -3
  3. package/dist/Development.js +14 -7
  4. package/dist/Effectify.d.ts +212 -0
  5. package/dist/Effectify.js +19 -0
  6. package/dist/FilePathPattern.d.ts +29 -0
  7. package/dist/FilePathPattern.js +86 -0
  8. package/dist/FileRouter.d.ts +39 -41
  9. package/dist/FileRouter.js +104 -158
  10. package/dist/FileRouterCodegen.d.ts +7 -8
  11. package/dist/FileRouterCodegen.js +97 -66
  12. package/dist/PlatformError.d.ts +46 -0
  13. package/dist/PlatformError.js +43 -0
  14. package/dist/PlatformRuntime.d.ts +27 -0
  15. package/dist/PlatformRuntime.js +51 -0
  16. package/dist/Route.d.ts +6 -2
  17. package/dist/Route.js +22 -0
  18. package/dist/RouteBody.d.ts +1 -1
  19. package/dist/RouteHttp.d.ts +1 -1
  20. package/dist/RouteHttp.js +12 -19
  21. package/dist/RouteMount.d.ts +2 -1
  22. package/dist/Start.d.ts +33 -6
  23. package/dist/Start.js +31 -13
  24. package/dist/Unique.d.ts +50 -0
  25. package/dist/Unique.js +187 -0
  26. package/dist/bun/BunHttpServer.js +5 -6
  27. package/dist/bun/BunPlatformHttpServer.d.ts +10 -0
  28. package/dist/bun/BunPlatformHttpServer.js +53 -0
  29. package/dist/bun/BunRoute.d.ts +4 -6
  30. package/dist/bun/BunRoute.js +10 -18
  31. package/dist/bun/BunRuntime.d.ts +2 -1
  32. package/dist/bun/BunRuntime.js +10 -5
  33. package/dist/bun/BunServer.d.ts +33 -0
  34. package/dist/bun/BunServer.js +133 -0
  35. package/dist/bun/BunServerRequest.d.ts +60 -0
  36. package/dist/bun/BunServerRequest.js +252 -0
  37. package/dist/bun/index.d.ts +1 -1
  38. package/dist/bun/index.js +1 -1
  39. package/dist/datastar/actions/fetch.d.ts +30 -0
  40. package/dist/datastar/actions/fetch.js +411 -0
  41. package/dist/datastar/actions/peek.d.ts +1 -0
  42. package/dist/datastar/actions/peek.js +14 -0
  43. package/dist/datastar/actions/setAll.d.ts +1 -0
  44. package/dist/datastar/actions/setAll.js +13 -0
  45. package/dist/datastar/actions/toggleAll.d.ts +1 -0
  46. package/dist/datastar/actions/toggleAll.js +13 -0
  47. package/dist/datastar/attributes/attr.d.ts +1 -0
  48. package/dist/datastar/attributes/attr.js +49 -0
  49. package/dist/datastar/attributes/bind.d.ts +1 -0
  50. package/dist/datastar/attributes/bind.js +183 -0
  51. package/dist/datastar/attributes/class.d.ts +1 -0
  52. package/dist/datastar/attributes/class.js +50 -0
  53. package/dist/datastar/attributes/computed.d.ts +1 -0
  54. package/dist/datastar/attributes/computed.js +27 -0
  55. package/dist/datastar/attributes/effect.d.ts +1 -0
  56. package/dist/datastar/attributes/effect.js +10 -0
  57. package/dist/datastar/attributes/indicator.d.ts +1 -0
  58. package/dist/datastar/attributes/indicator.js +32 -0
  59. package/dist/datastar/attributes/init.d.ts +1 -0
  60. package/dist/datastar/attributes/init.js +27 -0
  61. package/dist/datastar/attributes/jsonSignals.d.ts +1 -0
  62. package/dist/datastar/attributes/jsonSignals.js +31 -0
  63. package/dist/datastar/attributes/on.d.ts +1 -0
  64. package/dist/datastar/attributes/on.js +59 -0
  65. package/dist/datastar/attributes/onIntersect.d.ts +1 -0
  66. package/dist/datastar/attributes/onIntersect.js +54 -0
  67. package/dist/datastar/attributes/onInterval.d.ts +1 -0
  68. package/dist/datastar/attributes/onInterval.js +31 -0
  69. package/dist/datastar/attributes/onSignalPatch.d.ts +1 -0
  70. package/dist/datastar/attributes/onSignalPatch.js +44 -0
  71. package/dist/datastar/attributes/ref.d.ts +1 -0
  72. package/dist/datastar/attributes/ref.js +11 -0
  73. package/dist/datastar/attributes/show.d.ts +1 -0
  74. package/dist/datastar/attributes/show.js +32 -0
  75. package/dist/datastar/attributes/signals.d.ts +1 -0
  76. package/dist/datastar/attributes/signals.js +18 -0
  77. package/dist/datastar/attributes/style.d.ts +1 -0
  78. package/dist/datastar/attributes/style.js +56 -0
  79. package/dist/datastar/attributes/text.d.ts +1 -0
  80. package/dist/datastar/attributes/text.js +27 -0
  81. package/dist/datastar/engine.d.ts +156 -0
  82. package/dist/datastar/engine.js +971 -0
  83. package/dist/datastar/index.d.ts +24 -0
  84. package/dist/datastar/index.js +24 -0
  85. package/dist/datastar/load.d.ts +24 -0
  86. package/dist/datastar/load.js +24 -0
  87. package/dist/datastar/utils.d.ts +51 -0
  88. package/dist/datastar/utils.js +205 -0
  89. package/dist/datastar/watchers/patchElements.d.ts +1 -0
  90. package/dist/datastar/watchers/patchElements.js +420 -0
  91. package/dist/datastar/watchers/patchSignals.d.ts +1 -0
  92. package/dist/datastar/watchers/patchSignals.js +15 -0
  93. package/dist/index.d.ts +1 -0
  94. package/dist/index.js +1 -0
  95. package/dist/node/Effectify.d.ts +209 -0
  96. package/dist/node/Effectify.js +19 -0
  97. package/dist/node/FileSystem.d.ts +3 -5
  98. package/dist/node/FileSystem.js +42 -62
  99. package/dist/node/NodeFileSystem.d.ts +7 -0
  100. package/dist/node/NodeFileSystem.js +420 -0
  101. package/dist/node/NodeUtils.d.ts +2 -0
  102. package/dist/node/NodeUtils.js +20 -0
  103. package/dist/node/PlatformError.d.ts +46 -0
  104. package/dist/node/PlatformError.js +43 -0
  105. package/dist/testing/TestLogger.js +1 -1
  106. package/dist/x/tailwind/plugin.js +1 -1
  107. package/package.json +18 -7
  108. package/src/Development.ts +36 -40
  109. package/src/Effectify.ts +269 -0
  110. package/src/FilePathPattern.ts +115 -0
  111. package/src/FileRouter.ts +178 -255
  112. package/src/FileRouterCodegen.ts +135 -92
  113. package/src/PlatformError.ts +117 -0
  114. package/src/PlatformRuntime.ts +108 -0
  115. package/src/Route.ts +31 -2
  116. package/src/RouteBody.ts +1 -1
  117. package/src/RouteHttp.ts +15 -29
  118. package/src/RouteMount.ts +1 -1
  119. package/src/Start.ts +61 -27
  120. package/src/Unique.ts +232 -0
  121. package/src/bun/BunPlatformHttpServer.ts +88 -0
  122. package/src/bun/BunRoute.ts +14 -24
  123. package/src/bun/BunRuntime.ts +21 -5
  124. package/src/bun/BunServer.ts +228 -0
  125. package/src/bun/index.ts +1 -1
  126. package/src/datastar/README.md +18 -0
  127. package/src/datastar/actions/fetch.ts +609 -0
  128. package/src/datastar/actions/peek.ts +17 -0
  129. package/src/datastar/actions/setAll.ts +20 -0
  130. package/src/datastar/actions/toggleAll.ts +20 -0
  131. package/src/datastar/attributes/attr.ts +50 -0
  132. package/src/datastar/attributes/bind.ts +220 -0
  133. package/src/datastar/attributes/class.ts +57 -0
  134. package/src/datastar/attributes/computed.ts +33 -0
  135. package/src/datastar/attributes/effect.ts +11 -0
  136. package/src/datastar/attributes/indicator.ts +39 -0
  137. package/src/datastar/attributes/init.ts +35 -0
  138. package/src/datastar/attributes/jsonSignals.ts +38 -0
  139. package/src/datastar/attributes/on.ts +71 -0
  140. package/src/datastar/attributes/onIntersect.ts +65 -0
  141. package/src/datastar/attributes/onInterval.ts +39 -0
  142. package/src/datastar/attributes/onSignalPatch.ts +63 -0
  143. package/src/datastar/attributes/ref.ts +12 -0
  144. package/src/datastar/attributes/show.ts +33 -0
  145. package/src/datastar/attributes/signals.ts +22 -0
  146. package/src/datastar/attributes/style.ts +63 -0
  147. package/src/datastar/attributes/text.ts +30 -0
  148. package/src/datastar/engine.ts +1341 -0
  149. package/src/datastar/index.ts +25 -0
  150. package/src/datastar/utils.ts +286 -0
  151. package/src/datastar/watchers/patchElements.ts +554 -0
  152. package/src/datastar/watchers/patchSignals.ts +15 -0
  153. package/src/index.ts +1 -0
  154. package/src/node/{FileSystem.ts → NodeFileSystem.ts} +59 -97
  155. package/src/node/{Utils.ts → NodeUtils.ts} +2 -0
  156. package/src/testing/TestLogger.ts +1 -1
  157. package/src/x/tailwind/plugin.ts +1 -1
  158. package/dist/Random.d.ts +0 -5
  159. package/dist/Random.js +0 -49
  160. package/src/Commander.test.ts +0 -1639
  161. package/src/ContentNegotiation.test.ts +0 -603
  162. package/src/Development.test.ts +0 -119
  163. package/src/Entity.test.ts +0 -592
  164. package/src/FileRouterCodegen.todo.ts +0 -1133
  165. package/src/FileRouterPattern.test.ts +0 -147
  166. package/src/FileRouterPattern.ts +0 -59
  167. package/src/FileRouter_files.test.ts +0 -64
  168. package/src/FileRouter_path.test.ts +0 -145
  169. package/src/FileRouter_tree.test.ts +0 -132
  170. package/src/Http.test.ts +0 -319
  171. package/src/HttpAppExtra.test.ts +0 -103
  172. package/src/HttpUtils.test.ts +0 -85
  173. package/src/PathPattern.test.ts +0 -648
  174. package/src/Random.ts +0 -59
  175. package/src/RouteBody.test.ts +0 -232
  176. package/src/RouteHook.test.ts +0 -40
  177. package/src/RouteHttp.test.ts +0 -2909
  178. package/src/RouteMount.test.ts +0 -481
  179. package/src/RouteSchema.test.ts +0 -427
  180. package/src/RouteSse.test.ts +0 -249
  181. package/src/RouteTree.test.ts +0 -494
  182. package/src/RouteTrie.test.ts +0 -322
  183. package/src/RouterPattern.test.ts +0 -676
  184. package/src/RouterPattern.ts +0 -416
  185. package/src/StartApp.ts +0 -47
  186. package/src/Values.test.ts +0 -263
  187. package/src/bun/BunBundle.test.ts +0 -268
  188. package/src/bun/BunBundle_imports.test.ts +0 -48
  189. package/src/bun/BunHttpServer.test.ts +0 -251
  190. package/src/bun/BunHttpServer.ts +0 -306
  191. package/src/bun/BunImportTrackerPlugin.test.ts +0 -77
  192. package/src/bun/BunRoute.test.ts +0 -162
  193. package/src/bundler/BundleHttp.test.ts +0 -132
  194. package/src/effect/HttpRouter.test.ts +0 -548
  195. package/src/experimental/EncryptedCookies.test.ts +0 -488
  196. package/src/hyper/HyperHtml.test.ts +0 -209
  197. package/src/hyper/HyperRoute.test.tsx +0 -197
  198. package/src/middlewares/BasicAuthMiddleware.test.ts +0 -84
  199. package/src/testing/TestHttpClient.test.ts +0 -83
  200. package/src/testing/TestLogger.test.ts +0 -51
  201. package/src/x/datastar/Datastar.test.ts +0 -266
  202. package/src/x/tailwind/TailwindPlugin.test.ts +0 -333
  203. /package/src/bun/{BunHttpServer_web.ts → BunServerRequest.ts} +0 -0
@@ -1,676 +0,0 @@
1
- import * as test from "bun:test"
2
- import * as RouterPattern from "./RouterPattern.ts"
3
-
4
- test.describe("Segments", () => {
5
- test.it("literal path", () => {
6
- test
7
- .expectTypeOf<RouterPattern.Segments<"/">>()
8
- .toEqualTypeOf<[]>()
9
- test
10
- .expectTypeOf<RouterPattern.Segments<"/about">>()
11
- .toEqualTypeOf<[RouterPattern.LiteralSegment<"about">]>()
12
- test
13
- .expectTypeOf<RouterPattern.Segments<"/users/profile">>()
14
- .toEqualTypeOf<[
15
- RouterPattern.LiteralSegment<"users">,
16
- RouterPattern.LiteralSegment<"profile">,
17
- ]>()
18
- })
19
-
20
- test.it("simple param [param]", () => {
21
- test
22
- .expectTypeOf<RouterPattern.Segments<"/users/[id]">>()
23
- .toEqualTypeOf<[
24
- RouterPattern.LiteralSegment<"users">,
25
- RouterPattern.ParamSegment<"id", false>,
26
- ]>()
27
- test
28
- .expectTypeOf<RouterPattern.Segments<"/[category]/[product]">>()
29
- .toEqualTypeOf<[
30
- RouterPattern.ParamSegment<"category", false>,
31
- RouterPattern.ParamSegment<"product", false>,
32
- ]>()
33
- })
34
-
35
- test.it("optional param [[param]]", () => {
36
- test
37
- .expectTypeOf<RouterPattern.Segments<"/users/[[id]]">>()
38
- .toEqualTypeOf<[
39
- RouterPattern.LiteralSegment<"users">,
40
- RouterPattern.ParamSegment<"id", true>,
41
- ]>()
42
- })
43
-
44
- test.it("rest param [...param]", () => {
45
- test
46
- .expectTypeOf<RouterPattern.Segments<"/docs/[...path]">>()
47
- .toEqualTypeOf<[
48
- RouterPattern.LiteralSegment<"docs">,
49
- RouterPattern.RestSegment<"path", false>,
50
- ]>()
51
- })
52
-
53
- test.it("optional rest param [[...param]]", () => {
54
- test
55
- .expectTypeOf<RouterPattern.Segments<"/[[...frontend]]">>()
56
- .toEqualTypeOf<[RouterPattern.RestSegment<"frontend", true>]>()
57
- test
58
- .expectTypeOf<RouterPattern.Segments<"/app/[[...slug]]">>()
59
- .toEqualTypeOf<[
60
- RouterPattern.LiteralSegment<"app">,
61
- RouterPattern.RestSegment<"slug", true>,
62
- ]>()
63
- })
64
-
65
- test.it("param with prefix pk_[id]", () => {
66
- test
67
- .expectTypeOf<RouterPattern.Segments<"/keys/pk_[id]">>()
68
- .toEqualTypeOf<[
69
- RouterPattern.LiteralSegment<"keys">,
70
- RouterPattern.ParamSegment<"id", false, "pk_">,
71
- ]>()
72
- })
73
-
74
- test.it("param with suffix [id].json", () => {
75
- test
76
- .expectTypeOf<RouterPattern.Segments<"/api/[id].json">>()
77
- .toEqualTypeOf<[
78
- RouterPattern.LiteralSegment<"api">,
79
- RouterPattern.ParamSegment<"id", false, "", ".json">,
80
- ]>()
81
- })
82
-
83
- test.it("param with prefix and suffix file_[id].txt", () => {
84
- test
85
- .expectTypeOf<RouterPattern.Segments<"/files/file_[id].txt">>()
86
- .toEqualTypeOf<[
87
- RouterPattern.LiteralSegment<"files">,
88
- RouterPattern.ParamSegment<"id", false, "file_", ".txt">,
89
- ]>()
90
- })
91
-
92
- test.it("param with prefix and suffix prefix_[id]_suffix", () => {
93
- test
94
- .expectTypeOf<RouterPattern.Segments<"/prefix_[id]_suffix">>()
95
- .toEqualTypeOf<
96
- [RouterPattern.ParamSegment<"id", false, "prefix_", "_suffix">]
97
- >()
98
- })
99
-
100
- test.it("malformed segment pk_[id]foo → undefined (suffix without delimiter)", () => {
101
- test
102
- .expectTypeOf<RouterPattern.Segments<"/pk_[id]foo">>()
103
- .toEqualTypeOf<[undefined]>()
104
- })
105
-
106
- test.it("no delimiter prefix/suffix → Literal", () => {
107
- test
108
- .expectTypeOf<RouterPattern.Segments<"/pk[id]foo">>()
109
- .toEqualTypeOf<[RouterPattern.LiteralSegment<"pk[id]foo">]>()
110
- })
111
- })
112
-
113
- test.describe(`${RouterPattern.toColon.name}`, () => {
114
- test.it("literal path unchanged", () => {
115
- test
116
- .expect(RouterPattern.toColon("/"))
117
- .toEqual(["/"])
118
- test
119
- .expect(RouterPattern.toColon("/about"))
120
- .toEqual(["/about"])
121
- test
122
- .expect(RouterPattern.toColon("/users/profile"))
123
- .toEqual(["/users/profile"])
124
- })
125
-
126
- test.it("param [param] -> :param", () => {
127
- test
128
- .expect(RouterPattern.toColon("/users/[id]"))
129
- .toEqual(["/users/:id"])
130
- test
131
- .expect(RouterPattern.toColon("/[category]/[product]"))
132
- .toEqual(["/:category/:product"])
133
- })
134
-
135
- test.it("optional param [[param]] -> :param?", () => {
136
- test
137
- .expect(RouterPattern.toColon("/users/[[id]]"))
138
- .toEqual(["/users/:id?"])
139
- test
140
- .expect(RouterPattern.toColon("/[[lang]]/about"))
141
- .toEqual(["/:lang?/about"])
142
- })
143
-
144
- test.it("rest [...param] -> *", () => {
145
- test
146
- .expect(RouterPattern.toColon("/docs/[...path]"))
147
- .toEqual(["/docs/*"])
148
- test
149
- .expect(RouterPattern.toColon("/files/[...rest]"))
150
- .toEqual(["/files/*"])
151
- })
152
-
153
- test.it("optional rest [[...param]] -> two routes", () => {
154
- test
155
- .expect(RouterPattern.toColon("/[[...frontend]]"))
156
- .toEqual(["/", "/*"])
157
- test
158
- .expect(RouterPattern.toColon("/app/[[...slug]]"))
159
- .toEqual(["/app", "/app/*"])
160
- test
161
- .expect(RouterPattern.toColon("/docs/[[...path]]"))
162
- .toEqual(["/docs", "/docs/*"])
163
- })
164
-
165
- test.it("param with prefix pk_[id] -> pk_:id", () => {
166
- test
167
- .expect(RouterPattern.toColon("/keys/pk_[id]"))
168
- .toEqual(["/keys/pk_:id"])
169
- test
170
- .expect(RouterPattern.toColon("/sk_[key]"))
171
- .toEqual(["/sk_:key"])
172
- })
173
-
174
- test.it("param with suffix [name].json -> :name.json", () => {
175
- test
176
- .expect(RouterPattern.toColon("/api/[id].json"))
177
- .toEqual(["/api/:id.json"])
178
- })
179
-
180
- test.it("param with prefix and suffix", () => {
181
- test
182
- .expect(RouterPattern.toColon("/files/file_[id].txt"))
183
- .toEqual(["/files/file_:id.txt"])
184
- })
185
- })
186
-
187
- test.describe(`${RouterPattern.toBun.name}`, () => {
188
- test.it("literal path unchanged", () => {
189
- test
190
- .expect(RouterPattern.toBun("/"))
191
- .toEqual(["/"])
192
- test
193
- .expect(RouterPattern.toBun("/about"))
194
- .toEqual(["/about"])
195
- })
196
-
197
- test.it("param [param] -> :param", () => {
198
- test
199
- .expect(RouterPattern.toBun("/users/[id]"))
200
- .toEqual(["/users/:id"])
201
- })
202
-
203
- test.it("optional param [[param]] -> two routes", () => {
204
- test
205
- .expect(RouterPattern.toBun("/users/[[id]]"))
206
- .toEqual(["/users", "/users/:id"])
207
- test
208
- .expect(RouterPattern.toBun("/[[id]]"))
209
- .toEqual(["/", "/:id"])
210
- })
211
-
212
- test.it("rest param [...param] -> *", () => {
213
- test
214
- .expect(RouterPattern.toBun("/docs/[...path]"))
215
- .toEqual(["/docs/*"])
216
- })
217
-
218
- test.it("optional rest param [[...param]] -> two routes", () => {
219
- test
220
- .expect(RouterPattern.toBun("/docs/[[...path]]"))
221
- .toEqual(["/docs", "/docs/*"])
222
- test
223
- .expect(RouterPattern.toBun("/[[...path]]"))
224
- .toEqual(["/", "/*"])
225
- })
226
- })
227
-
228
- test.describe(`${RouterPattern.toExpress.name}`, () => {
229
- test.it("literal path unchanged", () => {
230
- test
231
- .expect(RouterPattern.toExpress("/"))
232
- .toEqual(["/"])
233
- test
234
- .expect(RouterPattern.toExpress("/about"))
235
- .toEqual(["/about"])
236
- })
237
-
238
- test.it("param [param] -> :param", () => {
239
- test
240
- .expect(RouterPattern.toExpress("/users/[id]"))
241
- .toEqual(["/users/:id"])
242
- })
243
-
244
- test.it("optional param [[param]] -> {/:param}", () => {
245
- test
246
- .expect(RouterPattern.toExpress("/users/[[id]]"))
247
- .toEqual(["/users{/:id}"])
248
- test
249
- .expect(RouterPattern.toExpress("/[[lang]]/about"))
250
- .toEqual(["/{/:lang}/about"])
251
- })
252
-
253
- test.it("rest [...param] -> /*param", () => {
254
- test
255
- .expect(RouterPattern.toExpress("/docs/[...path]"))
256
- .toEqual(["/docs/*path"])
257
- test
258
- .expect(RouterPattern.toExpress("/files/[...rest]"))
259
- .toEqual(["/files/*rest"])
260
- })
261
-
262
- test.it("optional rest [[...param]] -> two routes", () => {
263
- test
264
- .expect(RouterPattern.toExpress("/[[...frontend]]"))
265
- .toEqual(["/", "/*frontend"])
266
- test
267
- .expect(RouterPattern.toExpress("/app/[[...slug]]"))
268
- .toEqual(["/app", "/app/*slug"])
269
- })
270
-
271
- test.it("param with prefix pk_[id] -> pk_:id", () => {
272
- test
273
- .expect(RouterPattern.toExpress("/keys/pk_[id]"))
274
- .toEqual(["/keys/pk_:id"])
275
- })
276
- })
277
-
278
- test.describe(`${RouterPattern.toEffect.name}`, () => {
279
- test.it("literal path unchanged", () => {
280
- test
281
- .expect(RouterPattern.toEffect("/"))
282
- .toEqual(["/"])
283
- test
284
- .expect(RouterPattern.toEffect("/about"))
285
- .toEqual(["/about"])
286
- })
287
-
288
- test.it("param [param] -> :param", () => {
289
- test
290
- .expect(RouterPattern.toEffect("/users/[id]"))
291
- .toEqual(["/users/:id"])
292
- })
293
-
294
- test.it("optional param [[param]] -> :param?", () => {
295
- test
296
- .expect(RouterPattern.toEffect("/users/[[id]]"))
297
- .toEqual(["/users/:id?"])
298
- })
299
-
300
- test.it("rest [...param] -> *", () => {
301
- test
302
- .expect(RouterPattern.toEffect("/docs/[...path]"))
303
- .toEqual(["/docs/*"])
304
- })
305
-
306
- test.it("optional rest [[...param]] -> two routes", () => {
307
- test
308
- .expect(RouterPattern.toEffect("/[[...frontend]]"))
309
- .toEqual(["/", "/*"])
310
- test
311
- .expect(RouterPattern.toEffect("/app/[[...slug]]"))
312
- .toEqual(["/app", "/app/*"])
313
- })
314
-
315
- test.it("param with prefix pk_[id] -> pk_:id", () => {
316
- test
317
- .expect(RouterPattern.toEffect("/keys/pk_[id]"))
318
- .toEqual(["/keys/pk_:id"])
319
- })
320
- })
321
-
322
- test.describe(`${RouterPattern.toURLPattern.name}`, () => {
323
- test.it("literal path unchanged", () => {
324
- test
325
- .expect(RouterPattern.toURLPattern("/"))
326
- .toEqual(["/"])
327
- test
328
- .expect(RouterPattern.toURLPattern("/about"))
329
- .toEqual(["/about"])
330
- })
331
-
332
- test.it("param [param] -> :param", () => {
333
- test
334
- .expect(RouterPattern.toURLPattern("/users/[id]"))
335
- .toEqual(["/users/:id"])
336
- })
337
-
338
- test.it("optional param [[param]] -> :param?", () => {
339
- test
340
- .expect(RouterPattern.toURLPattern("/users/[[id]]"))
341
- .toEqual(["/users/:id?"])
342
- })
343
-
344
- test.it("rest [...param] -> :param+", () => {
345
- test
346
- .expect(RouterPattern.toURLPattern("/docs/[...path]"))
347
- .toEqual(["/docs/:path+"])
348
- })
349
-
350
- test.it("optional rest [[...param]] -> :param*", () => {
351
- test
352
- .expect(RouterPattern.toURLPattern("/[[...frontend]]"))
353
- .toEqual(["/:frontend*"])
354
- test
355
- .expect(RouterPattern.toURLPattern("/app/[[...slug]]"))
356
- .toEqual(["/app/:slug*"])
357
- })
358
-
359
- test.it("param with prefix pk_[id] -> pk_:id", () => {
360
- test
361
- .expect(RouterPattern.toURLPattern("/keys/pk_[id]"))
362
- .toEqual(["/keys/pk_:id"])
363
- })
364
- })
365
-
366
- test.describe(`${RouterPattern.toRemix.name}`, () => {
367
- test.it("literal path unchanged", () => {
368
- test
369
- .expect(RouterPattern.toRemix("/"))
370
- .toEqual(["/"])
371
- test
372
- .expect(RouterPattern.toRemix("/about"))
373
- .toEqual(["/about"])
374
- })
375
-
376
- test.it("param [param] -> $param", () => {
377
- test
378
- .expect(RouterPattern.toRemix("/users/[id]"))
379
- .toEqual(["/users/$id"])
380
- })
381
-
382
- test.it("optional param [[param]] -> ($param)", () => {
383
- test
384
- .expect(RouterPattern.toRemix("/users/[[id]]"))
385
- .toEqual(["/users/($id)"])
386
- })
387
-
388
- test.it("rest [...param] -> $", () => {
389
- test
390
- .expect(RouterPattern.toRemix("/docs/[...path]"))
391
- .toEqual(["/docs/$"])
392
- })
393
-
394
- test.it("optional rest [[...param]] -> two routes", () => {
395
- test
396
- .expect(RouterPattern.toRemix("/[[...frontend]]"))
397
- .toEqual(["/", "$"])
398
- test
399
- .expect(RouterPattern.toRemix("/app/[[...slug]]"))
400
- .toEqual(["/app", "/app/$"])
401
- })
402
-
403
- test.it("param with prefix pk_[id] -> pk_$id (not officially supported)", () => {
404
- test
405
- .expect(RouterPattern.toRemix("/keys/pk_[id]"))
406
- .toEqual(["/keys/pk_$id"])
407
- })
408
- })
409
-
410
- test.describe(`${RouterPattern.format.name}`, () => {
411
- test.it("empty segments", () => {
412
- test
413
- .expect(RouterPattern.format([]))
414
- .toBe("/")
415
- })
416
-
417
- test.it("literal segments", () => {
418
- test
419
- .expect(
420
- RouterPattern.format([{ _tag: "LiteralSegment", value: "users" }]),
421
- )
422
- .toBe("/users")
423
- test
424
- .expect(RouterPattern.format([
425
- { _tag: "LiteralSegment", value: "users" },
426
- { _tag: "LiteralSegment", value: "profile" },
427
- ]))
428
- .toBe("/users/profile")
429
- })
430
-
431
- test.it("param segments", () => {
432
- test
433
- .expect(RouterPattern.format([{ _tag: "ParamSegment", name: "id" }]))
434
- .toBe("/[id]")
435
- test
436
- .expect(RouterPattern.format([{
437
- _tag: "ParamSegment",
438
- name: "id",
439
- optional: true,
440
- }]))
441
- .toBe("/[[id]]")
442
- })
443
-
444
- test.it("param with prefix/suffix", () => {
445
- test
446
- .expect(RouterPattern.format([{
447
- _tag: "ParamSegment",
448
- name: "id",
449
- prefix: "pk_",
450
- }]))
451
- .toBe("/pk_[id]")
452
- test
453
- .expect(RouterPattern.format([{
454
- _tag: "ParamSegment",
455
- name: "id",
456
- suffix: ".json",
457
- }]))
458
- .toBe("/[id].json")
459
- test
460
- .expect(RouterPattern.format([
461
- { _tag: "ParamSegment", name: "id", prefix: "file_", suffix: ".txt" },
462
- ]))
463
- .toBe("/file_[id].txt")
464
- })
465
-
466
- test.it("rest segments", () => {
467
- test
468
- .expect(RouterPattern.format([{ _tag: "RestSegment", name: "path" }]))
469
- .toBe("/[...path]")
470
- test
471
- .expect(RouterPattern.format([{
472
- _tag: "RestSegment",
473
- name: "path",
474
- optional: true,
475
- }]))
476
- .toBe("/[[...path]]")
477
- })
478
-
479
- test.it("mixed segments", () => {
480
- test
481
- .expect(RouterPattern.format([
482
- { _tag: "LiteralSegment", value: "users" },
483
- { _tag: "ParamSegment", name: "id" },
484
- { _tag: "LiteralSegment", value: "posts" },
485
- ]))
486
- .toBe("/users/[id]/posts")
487
- })
488
- })
489
-
490
- test.describe("parseSegment", () => {
491
- test.it("parses literal segments", () => {
492
- test
493
- .expect(RouterPattern.parseSegment("users"))
494
- .toEqual({
495
- _tag: "LiteralSegment",
496
- value: "users",
497
- })
498
- })
499
-
500
- test.it("parses param segments", () => {
501
- test
502
- .expect(RouterPattern.parseSegment("[id]"))
503
- .toEqual({
504
- _tag: "ParamSegment",
505
- name: "id",
506
- })
507
- })
508
-
509
- test.it("parses optional param segments", () => {
510
- test
511
- .expect(RouterPattern.parseSegment("[[id]]"))
512
- .toEqual({
513
- _tag: "ParamSegment",
514
- name: "id",
515
- optional: true,
516
- })
517
- })
518
-
519
- test.it("parses rest segments", () => {
520
- test
521
- .expect(RouterPattern.parseSegment("[...path]"))
522
- .toEqual({
523
- _tag: "RestSegment",
524
- name: "path",
525
- })
526
- })
527
-
528
- test.it("parses optional rest segments", () => {
529
- test
530
- .expect(RouterPattern.parseSegment("[[...path]]"))
531
- .toEqual({
532
- _tag: "RestSegment",
533
- name: "path",
534
- optional: true,
535
- })
536
- })
537
-
538
- test.it("parses param with prefix", () => {
539
- test
540
- .expect(RouterPattern.parseSegment("pk_[id]"))
541
- .toEqual({
542
- _tag: "ParamSegment",
543
- name: "id",
544
- prefix: "pk_",
545
- })
546
- })
547
-
548
- test.it("parses param with suffix", () => {
549
- test
550
- .expect(RouterPattern.parseSegment("[id].json"))
551
- .toEqual({
552
- _tag: "ParamSegment",
553
- name: "id",
554
- suffix: ".json",
555
- })
556
- })
557
-
558
- test.it("accepts Unicode literals", () => {
559
- test
560
- .expect(RouterPattern.parseSegment("café"))
561
- .toEqual({
562
- _tag: "LiteralSegment",
563
- value: "café",
564
- })
565
- test
566
- .expect(RouterPattern.parseSegment("日本語"))
567
- .toEqual({
568
- _tag: "LiteralSegment",
569
- value: "日本語",
570
- })
571
- test
572
- .expect(RouterPattern.parseSegment("москва"))
573
- .toEqual({
574
- _tag: "LiteralSegment",
575
- value: "москва",
576
- })
577
- })
578
-
579
- test.it("accepts safe punctuation in literals", () => {
580
- test
581
- .expect(RouterPattern.parseSegment("file.txt"))
582
- .toEqual({
583
- _tag: "LiteralSegment",
584
- value: "file.txt",
585
- })
586
- test
587
- .expect(RouterPattern.parseSegment("my-file"))
588
- .toEqual({
589
- _tag: "LiteralSegment",
590
- value: "my-file",
591
- })
592
- test
593
- .expect(RouterPattern.parseSegment("my_file"))
594
- .toEqual({
595
- _tag: "LiteralSegment",
596
- value: "my_file",
597
- })
598
- test
599
- .expect(RouterPattern.parseSegment("file~1"))
600
- .toEqual({
601
- _tag: "LiteralSegment",
602
- value: "file~1",
603
- })
604
- })
605
-
606
- test.it("rejects invalid literal segments", () => {
607
- test
608
- .expect(RouterPattern.parseSegment("invalid$char"))
609
- .toBe(null)
610
- test
611
- .expect(RouterPattern.parseSegment("has%20spaces"))
612
- .toBe(null)
613
- test
614
- .expect(RouterPattern.parseSegment("special@char"))
615
- .toBe(null)
616
- test
617
- .expect(RouterPattern.parseSegment("bad#hash"))
618
- .toBe(null)
619
- test
620
- .expect(RouterPattern.parseSegment("with spaces"))
621
- .toBe(null)
622
- test
623
- .expect(RouterPattern.parseSegment(""))
624
- .toBe(null)
625
- })
626
- })
627
-
628
- test.describe("parse", () => {
629
- test.it("parses simple paths", () => {
630
- test
631
- .expect(RouterPattern.parse("/users"))
632
- .toEqual([
633
- { _tag: "LiteralSegment", value: "users" },
634
- ])
635
- test
636
- .expect(RouterPattern.parse("/users/profile"))
637
- .toEqual([
638
- { _tag: "LiteralSegment", value: "users" },
639
- { _tag: "LiteralSegment", value: "profile" },
640
- ])
641
- })
642
-
643
- test.it("parses paths with params", () => {
644
- test
645
- .expect(RouterPattern.parse("/users/[id]"))
646
- .toEqual([
647
- { _tag: "LiteralSegment", value: "users" },
648
- { _tag: "ParamSegment", name: "id" },
649
- ])
650
- })
651
-
652
- test.it("parses Unicode paths", () => {
653
- test
654
- .expect(RouterPattern.parse("/café/日本語/москва"))
655
- .toEqual([
656
- { _tag: "LiteralSegment", value: "café" },
657
- { _tag: "LiteralSegment", value: "日本語" },
658
- { _tag: "LiteralSegment", value: "москва" },
659
- ])
660
- })
661
-
662
- test.it("throws on invalid segments", () => {
663
- test
664
- .expect(() => RouterPattern.parse("/users/$invalid"))
665
- .toThrow(/Invalid path segment.*contains invalid characters/)
666
- test
667
- .expect(() => RouterPattern.parse("/path%20encoded"))
668
- .toThrow()
669
- test
670
- .expect(() => RouterPattern.parse("/special@char"))
671
- .toThrow()
672
- test
673
- .expect(() => RouterPattern.parse("/has spaces"))
674
- .toThrow()
675
- })
676
- })