effect-start 0.23.0 → 0.25.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 (356) hide show
  1. package/dist/ChildProcess.js +32 -20
  2. package/dist/Commander.js +377 -293
  3. package/dist/ContentNegotiation.js +424 -318
  4. package/dist/Cookies.js +340 -271
  5. package/dist/Development.js +85 -49
  6. package/dist/Effectify.js +22 -14
  7. package/dist/Entity.js +260 -195
  8. package/dist/Fetch.js +192 -0
  9. package/dist/FilePathPattern.js +88 -77
  10. package/dist/FileRouter.js +192 -136
  11. package/dist/FileRouterCodegen.js +262 -191
  12. package/dist/FileSystem.js +126 -64
  13. package/dist/Http.js +96 -77
  14. package/dist/PathPattern.js +311 -273
  15. package/dist/PlatformError.js +36 -21
  16. package/dist/PlatformRuntime.js +65 -40
  17. package/dist/Route.js +122 -79
  18. package/dist/RouteBody.js +83 -58
  19. package/dist/RouteError.js +46 -25
  20. package/dist/RouteHook.js +58 -34
  21. package/dist/RouteHttp.js +346 -237
  22. package/dist/RouteHttpTracer.js +86 -58
  23. package/dist/RouteMount.js +81 -58
  24. package/dist/RouteSchema.js +253 -170
  25. package/dist/RouteSse.js +87 -72
  26. package/dist/RouteTree.js +99 -73
  27. package/dist/RouteTrie.js +160 -133
  28. package/dist/SchemaExtra.js +87 -62
  29. package/dist/Socket.js +32 -21
  30. package/dist/SqlIntrospect.js +317 -268
  31. package/dist/Start.js +55 -25
  32. package/dist/StartApp.js +3 -21
  33. package/dist/StreamExtra.js +109 -74
  34. package/dist/System.js +37 -21
  35. package/dist/TuplePathPattern.js +64 -58
  36. package/dist/Unique.js +159 -120
  37. package/dist/Values.js +48 -32
  38. package/dist/bun/BunBundle.js +158 -109
  39. package/dist/bun/BunChildProcessSpawner.js +121 -82
  40. package/dist/bun/BunImportTrackerPlugin.js +85 -63
  41. package/dist/bun/BunRoute.js +135 -99
  42. package/dist/bun/BunRuntime.js +39 -29
  43. package/dist/bun/BunServer.js +268 -140
  44. package/dist/bun/BunVirtualFilesPlugin.js +47 -33
  45. package/dist/bun/_BunEnhancedResolve.js +107 -82
  46. package/dist/bun/index.js +5 -5
  47. package/dist/bundler/Bundle.js +82 -38
  48. package/dist/bundler/BundleFiles.js +140 -82
  49. package/dist/bundler/BundleRoute.js +49 -38
  50. package/dist/client/Overlay.js +29 -28
  51. package/dist/client/ScrollState.js +94 -82
  52. package/dist/client/index.js +79 -61
  53. package/dist/console/Console.js +40 -24
  54. package/dist/console/ConsoleErrors.js +189 -178
  55. package/dist/console/ConsoleLogger.js +52 -43
  56. package/dist/console/ConsoleMetrics.js +69 -58
  57. package/dist/console/ConsoleProcess.js +57 -47
  58. package/dist/console/ConsoleStore.js +56 -45
  59. package/dist/console/ConsoleTracer.js +101 -88
  60. package/dist/console/Simulation.js +714 -563
  61. package/dist/console/index.js +3 -3
  62. package/dist/console/routes/tree.js +29 -28
  63. package/dist/datastar/actions/fetch.js +514 -381
  64. package/dist/datastar/actions/peek.js +12 -12
  65. package/dist/datastar/actions/setAll.js +18 -11
  66. package/dist/datastar/actions/toggleAll.js +18 -11
  67. package/dist/datastar/attributes/attr.js +48 -47
  68. package/dist/datastar/attributes/bind.js +186 -167
  69. package/dist/datastar/attributes/class.js +51 -44
  70. package/dist/datastar/attributes/computed.js +23 -24
  71. package/dist/datastar/attributes/effect.js +9 -8
  72. package/dist/datastar/attributes/indicator.js +32 -29
  73. package/dist/datastar/attributes/init.js +26 -25
  74. package/dist/datastar/attributes/jsonSignals.js +32 -29
  75. package/dist/datastar/attributes/on.js +76 -73
  76. package/dist/datastar/attributes/onIntersect.js +51 -51
  77. package/dist/datastar/attributes/onInterval.js +30 -29
  78. package/dist/datastar/attributes/onSignalPatch.js +49 -40
  79. package/dist/datastar/attributes/ref.js +10 -9
  80. package/dist/datastar/attributes/show.js +31 -30
  81. package/dist/datastar/attributes/signals.js +17 -16
  82. package/dist/datastar/attributes/style.js +56 -49
  83. package/dist/datastar/attributes/text.js +28 -25
  84. package/dist/datastar/engine.js +1079 -933
  85. package/dist/datastar/index.js +25 -24
  86. package/dist/datastar/utils.js +203 -155
  87. package/dist/datastar/watchers/patchElements.js +459 -372
  88. package/dist/datastar/watchers/patchSignals.js +13 -13
  89. package/dist/experimental/EncryptedCookies.js +305 -189
  90. package/dist/experimental/index.js +1 -1
  91. package/dist/hyper/Hyper.js +22 -17
  92. package/dist/hyper/HyperHtml.js +138 -123
  93. package/dist/hyper/HyperNode.js +11 -9
  94. package/dist/hyper/HyperRoute.js +41 -28
  95. package/dist/hyper/html.js +27 -27
  96. package/dist/hyper/index.js +5 -5
  97. package/dist/hyper/jsx-runtime.js +11 -5
  98. package/dist/index.js +8 -8
  99. package/dist/node/NodeFileSystem.js +606 -341
  100. package/dist/node/NodeUtils.js +21 -18
  101. package/dist/sql/Sql.js +8 -0
  102. package/dist/sql/bun/index.js +134 -67
  103. package/dist/sql/index.js +1 -0
  104. package/dist/sql/libsql/index.js +156 -0
  105. package/dist/sql/mssql/docker.js +103 -60
  106. package/dist/sql/mssql/index.js +182 -101
  107. package/dist/testing/TestLogger.js +39 -29
  108. package/dist/testing/index.js +2 -2
  109. package/dist/testing/utils.js +45 -23
  110. package/dist/x/cloudflare/CloudflareTunnel.js +61 -28
  111. package/dist/x/cloudflare/index.js +1 -1
  112. package/dist/x/tailscale/TailscaleTunnel.js +86 -60
  113. package/dist/x/tailscale/index.js +1 -1
  114. package/dist/x/tailwind/TailwindPlugin.js +280 -205
  115. package/dist/x/tailwind/compile.js +185 -129
  116. package/dist/x/tailwind/plugin.js +13 -11
  117. package/package.json +1 -1
  118. package/src/Development.ts +3 -1
  119. package/src/Entity.ts +17 -0
  120. package/src/Fetch.ts +271 -0
  121. package/src/SqlIntrospect.ts +64 -70
  122. package/src/Start.ts +24 -22
  123. package/src/StartApp.ts +11 -0
  124. package/src/bun/BunServer.ts +89 -16
  125. package/src/hyper/HyperHtml.ts +0 -1
  126. package/src/sql/bun/index.ts +1 -1
  127. package/src/sql/index.ts +1 -0
  128. package/src/sql/libsql/index.ts +173 -0
  129. package/src/sql/libsql/libsql.d.ts +39 -0
  130. package/src/sql/mssql/index.ts +1 -1
  131. package/src/x/tailscale/TailscaleTunnel.ts +7 -5
  132. package/dist/BlobStore.d.ts +0 -80
  133. package/dist/BlobStore.js +0 -19
  134. package/dist/ChildProcess.d.ts +0 -60
  135. package/dist/Commander.d.ts +0 -100
  136. package/dist/ContentNegotiation.d.ts +0 -12
  137. package/dist/Cookies.d.ts +0 -47
  138. package/dist/Development.d.ts +0 -39
  139. package/dist/Effectify.d.ts +0 -209
  140. package/dist/Entity.d.ts +0 -47
  141. package/dist/FilePathPattern.d.ts +0 -29
  142. package/dist/FileRouter.d.ts +0 -56
  143. package/dist/FileRouterCodegen.d.ts +0 -18
  144. package/dist/FileRouterPattern.d.ts +0 -9
  145. package/dist/FileRouterPattern.js +0 -35
  146. package/dist/FileSystem.d.ts +0 -158
  147. package/dist/Http.d.ts +0 -37
  148. package/dist/HttpAppExtra.d.ts +0 -7
  149. package/dist/HttpAppExtra.js +0 -320
  150. package/dist/HttpUtils.d.ts +0 -3
  151. package/dist/HttpUtils.js +0 -11
  152. package/dist/PathPattern.d.ts +0 -134
  153. package/dist/PlatformError.d.ts +0 -38
  154. package/dist/PlatformRuntime.d.ts +0 -27
  155. package/dist/Route.d.ts +0 -97
  156. package/dist/RouteBody.d.ts +0 -47
  157. package/dist/RouteError.d.ts +0 -98
  158. package/dist/RouteHook.d.ts +0 -12
  159. package/dist/RouteHttp.d.ts +0 -21
  160. package/dist/RouteHttpTracer.d.ts +0 -10
  161. package/dist/RouteMount.d.ts +0 -86
  162. package/dist/RouteSchema.d.ts +0 -86
  163. package/dist/RouteSse.d.ts +0 -21
  164. package/dist/RouteTree.d.ts +0 -57
  165. package/dist/RouteTrie.d.ts +0 -20
  166. package/dist/RouterPattern.d.ts +0 -118
  167. package/dist/RouterPattern.js +0 -269
  168. package/dist/SchemaExtra.d.ts +0 -7
  169. package/dist/Socket.d.ts +0 -27
  170. package/dist/Sql.d.ts +0 -34
  171. package/dist/Sql.js +0 -5
  172. package/dist/SqlIntrospect.d.ts +0 -91
  173. package/dist/Start.d.ts +0 -44
  174. package/dist/StartApp.d.ts +0 -19
  175. package/dist/StreamExtra.d.ts +0 -28
  176. package/dist/System.d.ts +0 -7
  177. package/dist/TuplePathPattern.d.ts +0 -9
  178. package/dist/Unique.d.ts +0 -50
  179. package/dist/Values.d.ts +0 -27
  180. package/dist/bun/BunBlobStoreDisk.d.ts +0 -6
  181. package/dist/bun/BunBlobStoreDisk.js +0 -116
  182. package/dist/bun/BunBlobStoreS3.d.ts +0 -11
  183. package/dist/bun/BunBlobStoreS3.js +0 -89
  184. package/dist/bun/BunBlobWatcherDisk.d.ts +0 -6
  185. package/dist/bun/BunBlobWatcherDisk.js +0 -60
  186. package/dist/bun/BunBlobWatcherQueue.d.ts +0 -6
  187. package/dist/bun/BunBlobWatcherQueue.js +0 -17
  188. package/dist/bun/BunBundle.d.ts +0 -11
  189. package/dist/bun/BunChildProcessSpawner.d.ts +0 -3
  190. package/dist/bun/BunHttpServer.d.ts +0 -44
  191. package/dist/bun/BunHttpServer.js +0 -186
  192. package/dist/bun/BunHttpServer_web.d.ts +0 -60
  193. package/dist/bun/BunHttpServer_web.js +0 -252
  194. package/dist/bun/BunImportTrackerPlugin.d.ts +0 -13
  195. package/dist/bun/BunPlatformHttpServer.d.ts +0 -10
  196. package/dist/bun/BunPlatformHttpServer.js +0 -53
  197. package/dist/bun/BunRoute.d.ts +0 -48
  198. package/dist/bun/BunRuntime.d.ts +0 -2
  199. package/dist/bun/BunServer.d.ts +0 -40
  200. package/dist/bun/BunServerRequest.d.ts +0 -60
  201. package/dist/bun/BunServerRequest.js +0 -252
  202. package/dist/bun/BunSql.d.ts +0 -4
  203. package/dist/bun/BunSql.js +0 -81
  204. package/dist/bun/BunVirtualFilesPlugin.d.ts +0 -4
  205. package/dist/bun/_BunEnhancedResolve.d.ts +0 -45
  206. package/dist/bun/index.d.ts +0 -5
  207. package/dist/bundler/Bundle.d.ts +0 -61
  208. package/dist/bundler/BundleFiles.d.ts +0 -13
  209. package/dist/bundler/BundleHttp.d.ts +0 -45
  210. package/dist/bundler/BundleHttp.js +0 -176
  211. package/dist/bundler/BundleRoute.d.ts +0 -27
  212. package/dist/client/Overlay.d.ts +0 -2
  213. package/dist/client/ScrollState.d.ts +0 -6
  214. package/dist/client/index.d.ts +0 -6
  215. package/dist/console/Console.d.ts +0 -6
  216. package/dist/console/ConsoleErrors.d.ts +0 -3
  217. package/dist/console/ConsoleLogger.d.ts +0 -3
  218. package/dist/console/ConsoleMetrics.d.ts +0 -3
  219. package/dist/console/ConsoleProcess.d.ts +0 -3
  220. package/dist/console/ConsoleStore.d.ts +0 -144
  221. package/dist/console/ConsoleTracer.d.ts +0 -3
  222. package/dist/console/Simulation.d.ts +0 -2
  223. package/dist/console/index.d.ts +0 -3
  224. package/dist/console/routes/errors/route.d.ts +0 -10
  225. package/dist/console/routes/errors/route.js +0 -47
  226. package/dist/console/routes/fiberDetail.d.ts +0 -16
  227. package/dist/console/routes/fiberDetail.js +0 -38
  228. package/dist/console/routes/fibers/route.d.ts +0 -10
  229. package/dist/console/routes/fibers/route.js +0 -19
  230. package/dist/console/routes/git/route.d.ts +0 -11
  231. package/dist/console/routes/git/route.js +0 -33
  232. package/dist/console/routes/layout.d.ts +0 -9
  233. package/dist/console/routes/layout.js +0 -3
  234. package/dist/console/routes/logs/route.d.ts +0 -10
  235. package/dist/console/routes/logs/route.js +0 -32
  236. package/dist/console/routes/metrics/route.d.ts +0 -10
  237. package/dist/console/routes/metrics/route.js +0 -17
  238. package/dist/console/routes/route.d.ts +0 -6
  239. package/dist/console/routes/route.js +0 -5
  240. package/dist/console/routes/routes/route.d.ts +0 -6
  241. package/dist/console/routes/routes/route.js +0 -20
  242. package/dist/console/routes/services/route.d.ts +0 -6
  243. package/dist/console/routes/services/route.js +0 -12
  244. package/dist/console/routes/system/route.d.ts +0 -10
  245. package/dist/console/routes/system/route.js +0 -18
  246. package/dist/console/routes/traceDetail.d.ts +0 -16
  247. package/dist/console/routes/traceDetail.js +0 -14
  248. package/dist/console/routes/traces/route.d.ts +0 -10
  249. package/dist/console/routes/traces/route.js +0 -39
  250. package/dist/console/routes/tree.d.ts +0 -153
  251. package/dist/console/ui/Errors.d.ts +0 -4
  252. package/dist/console/ui/Errors.js +0 -15
  253. package/dist/console/ui/Fibers.d.ts +0 -24
  254. package/dist/console/ui/Fibers.js +0 -121
  255. package/dist/console/ui/Git.d.ts +0 -20
  256. package/dist/console/ui/Git.js +0 -95
  257. package/dist/console/ui/Logs.d.ts +0 -4
  258. package/dist/console/ui/Logs.js +0 -25
  259. package/dist/console/ui/Metrics.d.ts +0 -4
  260. package/dist/console/ui/Metrics.js +0 -26
  261. package/dist/console/ui/Routes.d.ts +0 -8
  262. package/dist/console/ui/Routes.js +0 -70
  263. package/dist/console/ui/Services.d.ts +0 -10
  264. package/dist/console/ui/Services.js +0 -246
  265. package/dist/console/ui/Shell.d.ts +0 -10
  266. package/dist/console/ui/Shell.js +0 -7
  267. package/dist/console/ui/System.d.ts +0 -4
  268. package/dist/console/ui/System.js +0 -35
  269. package/dist/console/ui/Traces.d.ts +0 -12
  270. package/dist/console/ui/Traces.js +0 -179
  271. package/dist/datastar/actions/fetch.d.ts +0 -30
  272. package/dist/datastar/actions/peek.d.ts +0 -1
  273. package/dist/datastar/actions/setAll.d.ts +0 -1
  274. package/dist/datastar/actions/toggleAll.d.ts +0 -1
  275. package/dist/datastar/attributes/attr.d.ts +0 -1
  276. package/dist/datastar/attributes/bind.d.ts +0 -1
  277. package/dist/datastar/attributes/class.d.ts +0 -1
  278. package/dist/datastar/attributes/computed.d.ts +0 -1
  279. package/dist/datastar/attributes/effect.d.ts +0 -1
  280. package/dist/datastar/attributes/indicator.d.ts +0 -1
  281. package/dist/datastar/attributes/init.d.ts +0 -1
  282. package/dist/datastar/attributes/jsonSignals.d.ts +0 -1
  283. package/dist/datastar/attributes/on.d.ts +0 -1
  284. package/dist/datastar/attributes/onIntersect.d.ts +0 -1
  285. package/dist/datastar/attributes/onInterval.d.ts +0 -1
  286. package/dist/datastar/attributes/onSignalPatch.d.ts +0 -1
  287. package/dist/datastar/attributes/ref.d.ts +0 -1
  288. package/dist/datastar/attributes/show.d.ts +0 -1
  289. package/dist/datastar/attributes/signals.d.ts +0 -1
  290. package/dist/datastar/attributes/style.d.ts +0 -1
  291. package/dist/datastar/attributes/text.d.ts +0 -1
  292. package/dist/datastar/engine.d.ts +0 -162
  293. package/dist/datastar/happydom.d.ts +0 -1
  294. package/dist/datastar/happydom.js +0 -8
  295. package/dist/datastar/index.d.ts +0 -24
  296. package/dist/datastar/load.d.ts +0 -24
  297. package/dist/datastar/load.js +0 -24
  298. package/dist/datastar/utils.d.ts +0 -51
  299. package/dist/datastar/watchers/patchElements.d.ts +0 -1
  300. package/dist/datastar/watchers/patchSignals.d.ts +0 -1
  301. package/dist/experimental/EncryptedCookies.d.ts +0 -48
  302. package/dist/experimental/SseHttpResponse.d.ts +0 -7
  303. package/dist/experimental/SseHttpResponse.js +0 -28
  304. package/dist/experimental/index.d.ts +0 -1
  305. package/dist/hyper/Hyper.d.ts +0 -25
  306. package/dist/hyper/HyperHtml.d.ts +0 -23
  307. package/dist/hyper/HyperHtml.test.d.ts +0 -1
  308. package/dist/hyper/HyperHtml.test.js +0 -197
  309. package/dist/hyper/HyperNode.d.ts +0 -14
  310. package/dist/hyper/HyperRoute.d.ts +0 -8
  311. package/dist/hyper/HyperRoute.test.d.ts +0 -1
  312. package/dist/hyper/HyperRoute.test.js +0 -83
  313. package/dist/hyper/html.d.ts +0 -11
  314. package/dist/hyper/index.d.ts +0 -6
  315. package/dist/hyper/jsx-runtime.d.ts +0 -7
  316. package/dist/index.d.ts +0 -8
  317. package/dist/inference_check.d.ts +0 -1
  318. package/dist/inference_check.js +0 -15
  319. package/dist/lint/plugin.d.ts +0 -86
  320. package/dist/lint/plugin.js +0 -341
  321. package/dist/middlewares/BasicAuthMiddleware.d.ts +0 -8
  322. package/dist/middlewares/BasicAuthMiddleware.js +0 -22
  323. package/dist/middlewares/index.d.ts +0 -1
  324. package/dist/middlewares/index.js +0 -1
  325. package/dist/node/Effectify.d.ts +0 -209
  326. package/dist/node/Effectify.js +0 -19
  327. package/dist/node/FileSystem.d.ts +0 -7
  328. package/dist/node/FileSystem.js +0 -420
  329. package/dist/node/NodeFileSystem.d.ts +0 -7
  330. package/dist/node/NodeUtils.d.ts +0 -2
  331. package/dist/node/PlatformError.d.ts +0 -46
  332. package/dist/node/PlatformError.js +0 -43
  333. package/dist/node/Utils.d.ts +0 -1
  334. package/dist/node/Utils.js +0 -19
  335. package/dist/repro_fail.d.ts +0 -1
  336. package/dist/repro_fail.js +0 -14
  337. package/dist/sql/bun/index.d.ts +0 -3
  338. package/dist/sql/mssql/docker.d.ts +0 -2
  339. package/dist/sql/mssql/index.d.ts +0 -21
  340. package/dist/testing/TestHttpClient.d.ts +0 -13
  341. package/dist/testing/TestHttpClient.js +0 -68
  342. package/dist/testing/TestLogger.d.ts +0 -13
  343. package/dist/testing/index.d.ts +0 -2
  344. package/dist/testing/utils.d.ts +0 -9
  345. package/dist/x/cloudflare/CloudflareTunnel.d.ts +0 -10
  346. package/dist/x/cloudflare/index.d.ts +0 -1
  347. package/dist/x/datastar/Datastar.d.ts +0 -6
  348. package/dist/x/datastar/Datastar.js +0 -47
  349. package/dist/x/datastar/index.d.ts +0 -1
  350. package/dist/x/datastar/index.js +0 -1
  351. package/dist/x/tailscale/TailscaleTunnel.d.ts +0 -15
  352. package/dist/x/tailscale/index.d.ts +0 -1
  353. package/dist/x/tailwind/TailwindPlugin.d.ts +0 -23
  354. package/dist/x/tailwind/compile.d.ts +0 -19
  355. package/dist/x/tailwind/plugin.d.ts +0 -2
  356. /package/src/{Sql.ts → sql/Sql.ts} +0 -0
@@ -1,104 +1,124 @@
1
+
2
+
1
3
  function isValidSegment(segment) {
2
- if (segment.startsWith(":")) {
3
- const rest = segment.slice(1);
4
- if (rest.endsWith("*") || rest.endsWith("+") || rest.endsWith("?")) {
5
- const name = rest.slice(0, -1);
6
- return name !== "" && /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name);
7
- }
8
- return rest !== "" && /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(rest);
4
+ if (segment.startsWith(":")) {
5
+ const rest = segment.slice(1)
6
+ if (rest.endsWith("*") || rest.endsWith("+") || rest.endsWith("?")) {
7
+ const name = rest.slice(0, -1)
8
+ return name !== "" && /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name)
9
9
  }
10
- return /^[\p{L}\p{N}._~-]+$/u.test(segment);
10
+ return rest !== "" && /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(rest)
11
+ }
12
+ return /^[\p{L}\p{N}._~-]+$/u.test(segment)
11
13
  }
14
+
12
15
  export function validate(path) {
13
- const segments = path.split("/").filter(Boolean);
14
- for (const segment of segments) {
15
- if (!isValidSegment(segment)) {
16
- return {
17
- ok: false,
18
- error: `Invalid segment "${segment}" in "${path}"`,
19
- };
20
- }
16
+ const segments = path.split("/").filter(Boolean)
17
+ for (const segment of segments) {
18
+ if (!isValidSegment(segment)) {
19
+ return {
20
+ ok: false,
21
+ error: `Invalid segment "${segment}" in "${path}"`,
22
+ }
21
23
  }
22
- return { ok: true, segments };
24
+ }
25
+ return { ok: true, segments }
23
26
  }
27
+
24
28
  export function match(pattern, path) {
25
- const patternSegments = pattern.split("/").filter(Boolean);
26
- const pathSegments = path.split("/").filter(Boolean);
27
- const params = {};
28
- let patternIndex = 0;
29
- let pathIndex = 0;
30
- while (patternIndex < patternSegments.length) {
31
- const seg = patternSegments[patternIndex];
32
- if (seg.startsWith(":")) {
33
- const rest = seg.slice(1);
34
- if (rest.endsWith("+")) {
35
- const name = rest.slice(0, -1);
36
- const remaining = pathSegments.slice(pathIndex);
37
- if (remaining.length === 0) {
38
- return null;
39
- }
40
- params[name] = remaining.join("/");
41
- return params;
42
- }
43
- if (rest.endsWith("*")) {
44
- const name = rest.slice(0, -1);
45
- const remaining = pathSegments.slice(pathIndex);
46
- if (remaining.length > 0) {
47
- params[name] = remaining.join("/");
48
- }
49
- return params;
50
- }
51
- if (rest.endsWith("?")) {
52
- const name = rest.slice(0, -1);
53
- if (pathIndex < pathSegments.length) {
54
- params[name] = pathSegments[pathIndex];
55
- pathIndex++;
56
- }
57
- patternIndex++;
58
- continue;
59
- }
60
- if (pathIndex >= pathSegments.length) {
61
- return null;
62
- }
63
- params[rest] = pathSegments[pathIndex];
64
- pathIndex++;
65
- patternIndex++;
66
- continue;
29
+ const patternSegments = pattern.split("/").filter(Boolean)
30
+ const pathSegments = path.split("/").filter(Boolean)
31
+ const params = {}
32
+ let patternIndex = 0
33
+ let pathIndex = 0
34
+
35
+ while (patternIndex < patternSegments.length) {
36
+ const seg = patternSegments[patternIndex]
37
+
38
+ if (seg.startsWith(":")) {
39
+ const rest = seg.slice(1)
40
+
41
+ if (rest.endsWith("+")) {
42
+ const name = rest.slice(0, -1)
43
+ const remaining = pathSegments.slice(pathIndex)
44
+ if (remaining.length === 0) {
45
+ return null
67
46
  }
68
- if (pathIndex >= pathSegments.length) {
69
- return null;
47
+ params[name] = remaining.join("/")
48
+ return params
49
+ }
50
+
51
+ if (rest.endsWith("*")) {
52
+ const name = rest.slice(0, -1)
53
+ const remaining = pathSegments.slice(pathIndex)
54
+ if (remaining.length > 0) {
55
+ params[name] = remaining.join("/")
70
56
  }
71
- if (seg !== pathSegments[pathIndex]) {
72
- return null;
57
+ return params
58
+ }
59
+
60
+ if (rest.endsWith("?")) {
61
+ const name = rest.slice(0, -1)
62
+ if (pathIndex < pathSegments.length) {
63
+ params[name] = pathSegments[pathIndex]
64
+ pathIndex++
73
65
  }
74
- pathIndex++;
75
- patternIndex++;
66
+ patternIndex++
67
+ continue
68
+ }
69
+
70
+ if (pathIndex >= pathSegments.length) {
71
+ return null
72
+ }
73
+
74
+ params[rest] = pathSegments[pathIndex]
75
+ pathIndex++
76
+ patternIndex++
77
+ continue
78
+ }
79
+
80
+ if (pathIndex >= pathSegments.length) {
81
+ return null
76
82
  }
77
- if (pathIndex !== pathSegments.length) {
78
- return null;
83
+
84
+ if (seg !== pathSegments[pathIndex]) {
85
+ return null
79
86
  }
80
- return params;
87
+
88
+ pathIndex++
89
+ patternIndex++
90
+ }
91
+
92
+ if (pathIndex !== pathSegments.length) {
93
+ return null
94
+ }
95
+
96
+ return params
81
97
  }
98
+
82
99
  export function toRegex(path) {
83
- const result = path
84
- .replace(/\/+(\/|$)/g, "$1")
85
- .replace(/\./g, "\\.")
86
- .replace(/(\/?):(\w+)\+/g, "($1(?<$2>*))")
87
- .replace(/(\/?):(\w+)\*/g, "(?:\\/(?<$2>.*))?")
88
- .replace(/(\/?):(\w+)/g, "($1(?<$2>[^$1/]+?))")
89
- .replace(/(\/?)\*/g, "($1.*)?");
90
- return new RegExp(`^${result}/*$`);
100
+ const result = path
101
+ .replace(/\/+(\/|$)/g, "$1")
102
+ .replace(/\./g, "\\.")
103
+ .replace(/(\/?):(\w+)\+/g, "($1(?<$2>*))")
104
+ .replace(/(\/?):(\w+)\*/g, "(?:\\/(?<$2>.*))?")
105
+ .replace(/(\/?):(\w+)/g, "($1(?<$2>[^$1/]+?))")
106
+ .replace(/(\/?)\*/g, "($1.*)?")
107
+
108
+ return new RegExp(`^${result}/*$`)
91
109
  }
110
+
92
111
  function getModifier(seg) {
93
- const last = seg[seg.length - 1];
94
- if (last === "?" || last === "*" || last === "+")
95
- return last;
96
- return "";
112
+ const last = seg[seg.length - 1]
113
+ if (last === "?" || last === "*" || last === "+") return last
114
+ return ""
97
115
  }
116
+
98
117
  function getParamName(seg) {
99
- const modifier = getModifier(seg);
100
- return modifier ? seg.slice(1, -1) : seg.slice(1);
118
+ const modifier = getModifier(seg)
119
+ return modifier ? seg.slice(1, -1) : seg.slice(1)
101
120
  }
121
+
102
122
  /**
103
123
  * Converts to Express path pattern.
104
124
  *
@@ -110,45 +130,47 @@ function getParamName(seg) {
110
130
  * - `:param*` → `/`, `/*param`
111
131
  */
112
132
  export function toExpress(path) {
113
- const segments = path.split("/").filter(Boolean);
114
- const optionalWildcardIndex = segments.findIndex((s) => s.startsWith(":") && s.endsWith("*"));
115
- if (optionalWildcardIndex !== -1) {
116
- const before = segments.slice(0, optionalWildcardIndex);
117
- const rest = segments[optionalWildcardIndex];
118
- const name = getParamName(rest);
119
- const beforeJoined = before
120
- .map((s) => (s.startsWith(":") ? `:${getParamName(s)}` : s))
121
- .join("/");
122
- const basePath = beforeJoined ? "/" + beforeJoined : "/";
123
- const withWildcard = basePath === "/" ? `/*${name}` : basePath + `/*${name}`;
124
- return [basePath, withWildcard];
125
- }
126
- let result = "";
127
- for (const seg of segments) {
128
- if (!seg.startsWith(":")) {
129
- result += "/" + seg;
130
- }
131
- else {
132
- const name = getParamName(seg);
133
- const modifier = getModifier(seg);
134
- switch (modifier) {
135
- case "":
136
- result += `/:${name}`;
137
- break;
138
- case "?":
139
- result += `{/:${name}}`;
140
- break;
141
- case "+":
142
- result += `/*${name}`;
143
- break;
144
- case "*":
145
- result += `/*${name}`;
146
- break;
147
- }
148
- }
133
+ const segments = path.split("/").filter(Boolean)
134
+ const optionalWildcardIndex = segments.findIndex((s) => s.startsWith(":") && s.endsWith("*"))
135
+
136
+ if (optionalWildcardIndex !== -1) {
137
+ const before = segments.slice(0, optionalWildcardIndex)
138
+ const rest = segments[optionalWildcardIndex]
139
+ const name = getParamName(rest)
140
+ const beforeJoined = before
141
+ .map((s) => (s.startsWith(":") ? `:${getParamName(s)}` : s))
142
+ .join("/")
143
+ const basePath = beforeJoined ? "/" + beforeJoined : "/"
144
+ const withWildcard = basePath === "/" ? `/*${name}` : basePath + `/*${name}`
145
+ return [basePath, withWildcard]
146
+ }
147
+
148
+ let result = ""
149
+ for (const seg of segments) {
150
+ if (!seg.startsWith(":")) {
151
+ result += "/" + seg
152
+ } else {
153
+ const name = getParamName(seg)
154
+ const modifier = getModifier(seg)
155
+ switch (modifier) {
156
+ case "":
157
+ result += `/:${name}`
158
+ break
159
+ case "?":
160
+ result += `{/:${name}}`
161
+ break
162
+ case "+":
163
+ result += `/*${name}`
164
+ break
165
+ case "*":
166
+ result += `/*${name}`
167
+ break
168
+ }
149
169
  }
150
- return [result || "/"];
170
+ }
171
+ return [result || "/"]
151
172
  }
173
+
152
174
  /**
153
175
  * Converts to URLPattern path pattern.
154
176
  *
@@ -160,18 +182,18 @@ export function toExpress(path) {
160
182
  * - `:param*` → `:param*`
161
183
  */
162
184
  export function toURLPattern(path) {
163
- const segments = path.split("/").filter(Boolean);
164
- const joined = segments
165
- .map((seg) => {
166
- if (!seg.startsWith(":"))
167
- return seg;
168
- const name = getParamName(seg);
169
- const modifier = getModifier(seg);
170
- return `:${name}${modifier}`;
185
+ const segments = path.split("/").filter(Boolean)
186
+ const joined = segments
187
+ .map((seg) => {
188
+ if (!seg.startsWith(":")) return seg
189
+ const name = getParamName(seg)
190
+ const modifier = getModifier(seg)
191
+ return `:${name}${modifier}`
171
192
  })
172
- .join("/");
173
- return [joined ? "/" + joined : "/"];
193
+ .join("/")
194
+ return [joined ? "/" + joined : "/"]
174
195
  }
196
+
175
197
  /**
176
198
  * Converts to React Router path pattern.
177
199
  *
@@ -183,48 +205,50 @@ export function toURLPattern(path) {
183
205
  * - `:param*` → `/`, `/*` (splat, optional - two routes)
184
206
  */
185
207
  export function toReactRouter(path) {
186
- const segments = path.split("/").filter(Boolean);
187
- const optionalWildcardIndex = segments.findIndex((s) => s.startsWith(":") && s.endsWith("*"));
188
- if (optionalWildcardIndex !== -1) {
189
- const before = segments.slice(0, optionalWildcardIndex);
190
- const beforeJoined = before
191
- .map((s) => {
192
- if (!s.startsWith(":"))
193
- return s;
194
- const name = getParamName(s);
195
- const modifier = getModifier(s);
196
- return modifier === "?" ? `:${name}?` : `:${name}`;
197
- })
198
- .join("/");
199
- const basePath = beforeJoined ? "/" + beforeJoined : "/";
200
- const withWildcard = basePath === "/" ? "/*" : basePath + "/*";
201
- return [basePath, withWildcard];
202
- }
203
- const joined = segments
204
- .map((s) => {
205
- if (!s.startsWith(":"))
206
- return s;
207
- const name = getParamName(s);
208
- const modifier = getModifier(s);
209
- switch (modifier) {
210
- case "":
211
- return `:${name}`;
212
- case "?":
213
- return `:${name}?`;
214
- case "+":
215
- case "*":
216
- return "*";
217
- }
208
+ const segments = path.split("/").filter(Boolean)
209
+ const optionalWildcardIndex = segments.findIndex((s) => s.startsWith(":") && s.endsWith("*"))
210
+
211
+ if (optionalWildcardIndex !== -1) {
212
+ const before = segments.slice(0, optionalWildcardIndex)
213
+ const beforeJoined = before
214
+ .map((s) => {
215
+ if (!s.startsWith(":")) return s
216
+ const name = getParamName(s)
217
+ const modifier = getModifier(s)
218
+ return modifier === "?" ? `:${name}?` : `:${name}`
219
+ })
220
+ .join("/")
221
+ const basePath = beforeJoined ? "/" + beforeJoined : "/"
222
+ const withWildcard = basePath === "/" ? "/*" : basePath + "/*"
223
+ return [basePath, withWildcard]
224
+ }
225
+
226
+ const joined = segments
227
+ .map((s) => {
228
+ if (!s.startsWith(":")) return s
229
+ const name = getParamName(s)
230
+ const modifier = getModifier(s)
231
+ switch (modifier) {
232
+ case "":
233
+ return `:${name}`
234
+ case "?":
235
+ return `:${name}?`
236
+ case "+":
237
+ case "*":
238
+ return "*"
239
+ }
218
240
  })
219
- .join("/");
220
- return [joined ? "/" + joined : "/"];
241
+ .join("/")
242
+ return [joined ? "/" + joined : "/"]
221
243
  }
244
+
222
245
  /**
223
246
  * Alias for toReactRouter.
224
247
  *
225
248
  * @see https://reactrouter.com/start/framework/routing
226
249
  */
227
- export const toRemix = toReactRouter;
250
+ export const toRemix = toReactRouter
251
+
228
252
  /**
229
253
  * Converts to Remix file-based route naming convention.
230
254
  *
@@ -239,25 +263,27 @@ export const toRemix = toReactRouter;
239
263
  * - `:param*` → `($)` (optional splat) - Note: not officially supported
240
264
  */
241
265
  export function toRemixFile(path) {
242
- const segments = path.split("/").filter(Boolean);
243
- const mapped = segments.map((seg) => {
244
- if (!seg.startsWith(":"))
245
- return seg;
246
- const name = getParamName(seg);
247
- const modifier = getModifier(seg);
248
- switch (modifier) {
249
- case "":
250
- return `$${name}`;
251
- case "?":
252
- return `($${name})`;
253
- case "+":
254
- return "$";
255
- case "*":
256
- return "($)";
257
- }
258
- });
259
- return mapped.join(".");
266
+ const segments = path.split("/").filter(Boolean)
267
+
268
+ const mapped = segments.map((seg) => {
269
+ if (!seg.startsWith(":")) return seg
270
+ const name = getParamName(seg)
271
+ const modifier = getModifier(seg)
272
+ switch (modifier) {
273
+ case "":
274
+ return `$${name}`
275
+ case "?":
276
+ return `($${name})`
277
+ case "+":
278
+ return "$"
279
+ case "*":
280
+ return "($)"
281
+ }
282
+ })
283
+
284
+ return mapped.join(".")
260
285
  }
286
+
261
287
  /**
262
288
  * Converts to TanStack Router path/file pattern.
263
289
  *
@@ -273,25 +299,27 @@ export function toRemixFile(path) {
273
299
  * - `:param*` → `$` (splat, optional not supported - treated as required)
274
300
  */
275
301
  export function toTanStack(path) {
276
- const segments = path.split("/").filter(Boolean);
277
- const mapped = segments.map((seg) => {
278
- if (!seg.startsWith(":"))
279
- return seg;
280
- const name = getParamName(seg);
281
- const modifier = getModifier(seg);
282
- switch (modifier) {
283
- case "":
284
- return `$${name}`;
285
- case "?":
286
- return `{-$${name}}`;
287
- case "+":
288
- return "$";
289
- case "*":
290
- return "$";
291
- }
292
- });
293
- return mapped.join(".");
302
+ const segments = path.split("/").filter(Boolean)
303
+
304
+ const mapped = segments.map((seg) => {
305
+ if (!seg.startsWith(":")) return seg
306
+ const name = getParamName(seg)
307
+ const modifier = getModifier(seg)
308
+ switch (modifier) {
309
+ case "":
310
+ return `$${name}`
311
+ case "?":
312
+ return `{-$${name}}`
313
+ case "+":
314
+ return "$"
315
+ case "*":
316
+ return "$"
317
+ }
318
+ })
319
+
320
+ return mapped.join(".")
294
321
  }
322
+
295
323
  /**
296
324
  * Converts to Hono path pattern.
297
325
  *
@@ -306,42 +334,43 @@ export function toTanStack(path) {
306
334
  * - `:param*` → `/`, `/*` (unnamed, optional - two routes)
307
335
  */
308
336
  export function toHono(path) {
309
- const segments = path.split("/").filter(Boolean);
310
- const optionalWildcardIndex = segments.findIndex((s) => s.startsWith(":") && s.endsWith("*"));
311
- if (optionalWildcardIndex !== -1) {
312
- const before = segments.slice(0, optionalWildcardIndex);
313
- const beforeJoined = before
314
- .map((s) => {
315
- if (!s.startsWith(":"))
316
- return s;
317
- const name = getParamName(s);
318
- const modifier = getModifier(s);
319
- return modifier === "?" ? `:${name}?` : `:${name}`;
320
- })
321
- .join("/");
322
- const basePath = beforeJoined ? "/" + beforeJoined : "/";
323
- const withWildcard = basePath === "/" ? "/*" : basePath + "/*";
324
- return [basePath, withWildcard];
325
- }
326
- const joined = segments
327
- .map((s) => {
328
- if (!s.startsWith(":"))
329
- return s;
330
- const name = getParamName(s);
331
- const modifier = getModifier(s);
332
- switch (modifier) {
333
- case "":
334
- return `:${name}`;
335
- case "?":
336
- return `:${name}?`;
337
- case "+":
338
- case "*":
339
- return "*";
340
- }
337
+ const segments = path.split("/").filter(Boolean)
338
+ const optionalWildcardIndex = segments.findIndex((s) => s.startsWith(":") && s.endsWith("*"))
339
+
340
+ if (optionalWildcardIndex !== -1) {
341
+ const before = segments.slice(0, optionalWildcardIndex)
342
+ const beforeJoined = before
343
+ .map((s) => {
344
+ if (!s.startsWith(":")) return s
345
+ const name = getParamName(s)
346
+ const modifier = getModifier(s)
347
+ return modifier === "?" ? `:${name}?` : `:${name}`
348
+ })
349
+ .join("/")
350
+ const basePath = beforeJoined ? "/" + beforeJoined : "/"
351
+ const withWildcard = basePath === "/" ? "/*" : basePath + "/*"
352
+ return [basePath, withWildcard]
353
+ }
354
+
355
+ const joined = segments
356
+ .map((s) => {
357
+ if (!s.startsWith(":")) return s
358
+ const name = getParamName(s)
359
+ const modifier = getModifier(s)
360
+ switch (modifier) {
361
+ case "":
362
+ return `:${name}`
363
+ case "?":
364
+ return `:${name}?`
365
+ case "+":
366
+ case "*":
367
+ return "*"
368
+ }
341
369
  })
342
- .join("/");
343
- return [joined ? "/" + joined : "/"];
370
+ .join("/")
371
+ return [joined ? "/" + joined : "/"]
344
372
  }
373
+
345
374
  /**
346
375
  * Converts to Effect HttpRouter / find-my-way path pattern.
347
376
  *
@@ -355,8 +384,9 @@ export function toHono(path) {
355
384
  * - `:param*` → `/`, `/*` (two routes)
356
385
  */
357
386
  export function toEffect(path) {
358
- return toHono(path);
387
+ return toHono(path)
359
388
  }
389
+
360
390
  /**
361
391
  * Converts to Bun.serve path pattern.
362
392
  *
@@ -371,43 +401,51 @@ export function toEffect(path) {
371
401
  * - `:param*` → `/`, `/*` (two routes)
372
402
  */
373
403
  export function toBun(path) {
374
- const segments = path.split("/").filter(Boolean);
375
- const optionalIndex = segments.findIndex((s) => s.startsWith(":") && (s.endsWith("?") || s.endsWith("*")));
376
- if (optionalIndex === -1) {
377
- const joined = segments
378
- .map((s) => {
379
- if (!s.startsWith(":"))
380
- return s;
381
- const modifier = getModifier(s);
382
- const name = getParamName(s);
383
- return modifier === "+" || modifier === "*" ? "*" : `:${name}`;
384
- })
385
- .join("/");
386
- return [joined ? `/${joined}` : "/"];
404
+ const segments = path.split("/").filter(Boolean)
405
+
406
+ const optionalIndex = segments.findIndex(
407
+ (s) => s.startsWith(":") && (s.endsWith("?") || s.endsWith("*")),
408
+ )
409
+
410
+ if (optionalIndex === -1) {
411
+ const joined = segments
412
+ .map((s) => {
413
+ if (!s.startsWith(":")) return s
414
+ const modifier = getModifier(s)
415
+ const name = getParamName(s)
416
+ return modifier === "+" || modifier === "*" ? "*" : `:${name}`
417
+ })
418
+ .join("/")
419
+ return [joined ? `/${joined}` : "/"]
420
+ }
421
+
422
+ const before = segments.slice(0, optionalIndex)
423
+ const optional = segments[optionalIndex]
424
+ const after = segments.slice(optionalIndex + 1)
425
+
426
+ const formatSegment = (s) => {
427
+ if (!s.startsWith(":")) return s
428
+ const modifier = getModifier(s)
429
+ const name = getParamName(s)
430
+ switch (modifier) {
431
+ case "":
432
+ case "?":
433
+ return `:${name}`
434
+ case "+":
435
+ case "*":
436
+ return "*"
387
437
  }
388
- const before = segments.slice(0, optionalIndex);
389
- const optional = segments[optionalIndex];
390
- const after = segments.slice(optionalIndex + 1);
391
- const formatSegment = (s) => {
392
- if (!s.startsWith(":"))
393
- return s;
394
- const modifier = getModifier(s);
395
- const name = getParamName(s);
396
- switch (modifier) {
397
- case "":
398
- case "?":
399
- return `:${name}`;
400
- case "+":
401
- case "*":
402
- return "*";
403
- }
404
- };
405
- const beforePath = before.map(formatSegment).join("/");
406
- const basePath = beforePath ? `/${beforePath}` : "/";
407
- const optionalModifier = getModifier(optional);
408
- const optionalName = getParamName(optional);
409
- const requiredOptional = optionalModifier === "*" ? `:${optionalName}+` : `:${optionalName}`;
410
- const withOptionalSegments = [...before, requiredOptional, ...after];
411
- const withOptionalPath = `/${withOptionalSegments.map(formatSegment).join("/")}`;
412
- return [...toBun(basePath), ...toBun(withOptionalPath)];
438
+ }
439
+
440
+ const beforePath = before.map(formatSegment).join("/")
441
+ const basePath = beforePath ? `/${beforePath}` : "/"
442
+
443
+ const optionalModifier = getModifier(optional)
444
+ const optionalName = getParamName(optional)
445
+ const requiredOptional = optionalModifier === "*" ? `:${optionalName}+` : `:${optionalName}`
446
+
447
+ const withOptionalSegments = [...before, requiredOptional, ...after]
448
+ const withOptionalPath = `/${withOptionalSegments.map(formatSegment).join("/")}`
449
+
450
+ return [...toBun(basePath), ...toBun(withOptionalPath)]
413
451
  }