effect-start 0.25.0 → 0.26.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 (117) hide show
  1. package/package.json +18 -86
  2. package/dist/ChildProcess.js +0 -42
  3. package/dist/Commander.js +0 -410
  4. package/dist/ContentNegotiation.js +0 -465
  5. package/dist/Cookies.js +0 -371
  6. package/dist/Development.js +0 -94
  7. package/dist/Effectify.js +0 -27
  8. package/dist/Entity.js +0 -289
  9. package/dist/Fetch.js +0 -192
  10. package/dist/FilePathPattern.js +0 -97
  11. package/dist/FileRouter.js +0 -204
  12. package/dist/FileRouterCodegen.js +0 -298
  13. package/dist/FileSystem.js +0 -132
  14. package/dist/Http.js +0 -107
  15. package/dist/PathPattern.js +0 -451
  16. package/dist/PlatformError.js +0 -40
  17. package/dist/PlatformRuntime.js +0 -71
  18. package/dist/Route.js +0 -143
  19. package/dist/RouteBody.js +0 -92
  20. package/dist/RouteError.js +0 -76
  21. package/dist/RouteHook.js +0 -64
  22. package/dist/RouteHttp.js +0 -367
  23. package/dist/RouteHttpTracer.js +0 -90
  24. package/dist/RouteMount.js +0 -86
  25. package/dist/RouteSchema.js +0 -271
  26. package/dist/RouteSse.js +0 -94
  27. package/dist/RouteTree.js +0 -119
  28. package/dist/RouteTrie.js +0 -179
  29. package/dist/SchemaExtra.js +0 -99
  30. package/dist/Socket.js +0 -40
  31. package/dist/SqlIntrospect.js +0 -515
  32. package/dist/Start.js +0 -79
  33. package/dist/StartApp.js +0 -3
  34. package/dist/StreamExtra.js +0 -135
  35. package/dist/System.js +0 -38
  36. package/dist/TuplePathPattern.js +0 -74
  37. package/dist/Unique.js +0 -226
  38. package/dist/Values.js +0 -52
  39. package/dist/bun/BunBundle.js +0 -186
  40. package/dist/bun/BunChildProcessSpawner.js +0 -142
  41. package/dist/bun/BunImportTrackerPlugin.js +0 -91
  42. package/dist/bun/BunRoute.js +0 -157
  43. package/dist/bun/BunRuntime.js +0 -41
  44. package/dist/bun/BunServer.js +0 -285
  45. package/dist/bun/BunVirtualFilesPlugin.js +0 -54
  46. package/dist/bun/_BunEnhancedResolve.js +0 -127
  47. package/dist/bun/index.js +0 -5
  48. package/dist/bundler/Bundle.js +0 -92
  49. package/dist/bundler/BundleFiles.js +0 -154
  50. package/dist/bundler/BundleRoute.js +0 -62
  51. package/dist/client/Overlay.js +0 -33
  52. package/dist/client/ScrollState.js +0 -106
  53. package/dist/client/index.js +0 -97
  54. package/dist/console/Console.js +0 -42
  55. package/dist/console/ConsoleErrors.js +0 -211
  56. package/dist/console/ConsoleLogger.js +0 -56
  57. package/dist/console/ConsoleMetrics.js +0 -72
  58. package/dist/console/ConsoleProcess.js +0 -59
  59. package/dist/console/ConsoleStore.js +0 -72
  60. package/dist/console/ConsoleTracer.js +0 -107
  61. package/dist/console/Simulation.js +0 -784
  62. package/dist/console/index.js +0 -3
  63. package/dist/console/routes/tree.js +0 -30
  64. package/dist/datastar/actions/fetch.js +0 -536
  65. package/dist/datastar/actions/peek.js +0 -13
  66. package/dist/datastar/actions/setAll.js +0 -19
  67. package/dist/datastar/actions/toggleAll.js +0 -19
  68. package/dist/datastar/attributes/attr.js +0 -49
  69. package/dist/datastar/attributes/bind.js +0 -194
  70. package/dist/datastar/attributes/class.js +0 -54
  71. package/dist/datastar/attributes/computed.js +0 -25
  72. package/dist/datastar/attributes/effect.js +0 -10
  73. package/dist/datastar/attributes/indicator.js +0 -33
  74. package/dist/datastar/attributes/init.js +0 -27
  75. package/dist/datastar/attributes/jsonSignals.js +0 -33
  76. package/dist/datastar/attributes/on.js +0 -81
  77. package/dist/datastar/attributes/onIntersect.js +0 -53
  78. package/dist/datastar/attributes/onInterval.js +0 -31
  79. package/dist/datastar/attributes/onSignalPatch.js +0 -51
  80. package/dist/datastar/attributes/ref.js +0 -11
  81. package/dist/datastar/attributes/show.js +0 -32
  82. package/dist/datastar/attributes/signals.js +0 -18
  83. package/dist/datastar/attributes/style.js +0 -57
  84. package/dist/datastar/attributes/text.js +0 -29
  85. package/dist/datastar/engine.js +0 -1145
  86. package/dist/datastar/index.js +0 -25
  87. package/dist/datastar/utils.js +0 -250
  88. package/dist/datastar/watchers/patchElements.js +0 -486
  89. package/dist/datastar/watchers/patchSignals.js +0 -14
  90. package/dist/experimental/EncryptedCookies.js +0 -328
  91. package/dist/experimental/index.js +0 -1
  92. package/dist/hyper/Hyper.js +0 -28
  93. package/dist/hyper/HyperHtml.js +0 -165
  94. package/dist/hyper/HyperNode.js +0 -13
  95. package/dist/hyper/HyperRoute.js +0 -45
  96. package/dist/hyper/html.js +0 -30
  97. package/dist/hyper/index.js +0 -5
  98. package/dist/hyper/jsx-runtime.js +0 -14
  99. package/dist/index.js +0 -8
  100. package/dist/node/NodeFileSystem.js +0 -675
  101. package/dist/node/NodeUtils.js +0 -23
  102. package/dist/sql/Sql.js +0 -8
  103. package/dist/sql/bun/index.js +0 -142
  104. package/dist/sql/index.js +0 -1
  105. package/dist/sql/libsql/index.js +0 -156
  106. package/dist/sql/mssql/docker.js +0 -110
  107. package/dist/sql/mssql/index.js +0 -194
  108. package/dist/testing/TestLogger.js +0 -42
  109. package/dist/testing/index.js +0 -2
  110. package/dist/testing/utils.js +0 -61
  111. package/dist/x/cloudflare/CloudflareTunnel.js +0 -63
  112. package/dist/x/cloudflare/index.js +0 -1
  113. package/dist/x/tailscale/TailscaleTunnel.js +0 -94
  114. package/dist/x/tailscale/index.js +0 -1
  115. package/dist/x/tailwind/TailwindPlugin.js +0 -294
  116. package/dist/x/tailwind/compile.js +0 -210
  117. package/dist/x/tailwind/plugin.js +0 -17
@@ -1,271 +0,0 @@
1
- import * as Effect from "effect/Effect"
2
- import * as Schema from "effect/Schema"
3
- import * as Entity from "./Entity.js"
4
- import * as Http from "./Http.js"
5
- import * as PathPattern from "./PathPattern.js"
6
- import * as Route from "./Route.js"
7
- import * as RouteHook from "./RouteHook.js"
8
-
9
- export const RequestBodyError = (
10
- reason,
11
- cause,
12
- ) => ({ _tag: "RequestBodyError", reason, cause })
13
-
14
- export const File = Schema.TaggedStruct("File", {
15
- key: Schema.String,
16
- name: Schema.String,
17
- contentType: Schema.String,
18
- content: Schema.Uint8ArrayFromSelf,
19
- })
20
-
21
- export function schemaHeaders(
22
- fields,
23
- ) {
24
- const decode = Schema.decodeUnknown(fields)
25
- return RouteHook.filter((ctx) =>
26
- Effect.map(decode(Http.mapHeaders(ctx.request.headers)), (parsed) => ({
27
- context: {
28
- headers: {
29
- ...ctx.headers,
30
- ...parsed,
31
- },
32
- },
33
- })),
34
- )
35
- }
36
-
37
- export function schemaCookies(
38
- fields,
39
- ) {
40
- const decode = Schema.decodeUnknown(fields)
41
- return RouteHook.filter((ctx) =>
42
- Effect.map(decode(Http.parseCookies(ctx.request.headers.get("cookie"))), (parsed) => ({
43
- context: {
44
- cookies: {
45
- ...ctx.cookies,
46
- ...parsed,
47
- },
48
- },
49
- })),
50
- )
51
- }
52
-
53
- export function schemaSearchParams(
54
- fields,
55
- ) {
56
- const decode = Schema.decodeUnknown(fields)
57
- return RouteHook.filter((ctx) => {
58
- const url = new URL(ctx.request.url)
59
- return Effect.map(decode(Http.mapUrlSearchParams(url.searchParams)), (parsed) => ({
60
- context: {
61
- searchParams: {
62
- ...ctx.searchParams,
63
- ...parsed,
64
- },
65
- },
66
- }))
67
- })
68
- }
69
-
70
- export function schemaPathParams(
71
- fields,
72
- ) {
73
- const decode = Schema.decodeUnknown(fields)
74
- return RouteHook.filter((ctx) => {
75
- const url = new URL(ctx.request.url)
76
- const pattern = ctx.path ?? "/"
77
- const params = PathPattern.match(pattern, url.pathname) ?? {}
78
- return Effect.map(decode(params), (parsed) => ({
79
- context: {
80
- pathParams: {
81
- ...ctx.pathParams,
82
- ...parsed,
83
- },
84
- },
85
- }))
86
- })
87
- }
88
-
89
- export function schemaBodyJson(
90
- fields,
91
- ) {
92
- const decode = Schema.decodeUnknown(fields)
93
- return RouteHook.filter((ctx) =>
94
- Effect.gen(function* () {
95
- const json = yield* Effect.tryPromise({
96
- try: () => ctx.request.json(),
97
- catch: (error) => RequestBodyError("JsonError", error),
98
- })
99
- const parsed = yield* decode(json)
100
- return {
101
- context: {
102
- body: {
103
- ...ctx.body,
104
- ...parsed,
105
- },
106
- },
107
- }
108
- }),
109
- )
110
- }
111
-
112
- export function schemaBodyUrlParams(
113
- fields,
114
- ) {
115
- const decode = Schema.decodeUnknown(fields)
116
- return RouteHook.filter((ctx) =>
117
- Effect.gen(function* () {
118
- const text = yield* Effect.tryPromise({
119
- try: () => ctx.request.text(),
120
- catch: (error) => RequestBodyError("UrlParamsError", error),
121
- })
122
- const params = new URLSearchParams(text)
123
- const parsed = yield* decode(Http.mapUrlSearchParams(params))
124
- return {
125
- context: {
126
- body: {
127
- ...ctx.body,
128
- ...parsed,
129
- },
130
- },
131
- }
132
- }),
133
- )
134
- }
135
-
136
- export function schemaBodyMultipart(
137
- fields,
138
- ) {
139
- const decode = Schema.decodeUnknown(fields)
140
- return RouteHook.filter((ctx) =>
141
- Effect.gen(function* () {
142
- const record = yield* Effect.tryPromise({
143
- try: () => Http.parseFormData(ctx.request),
144
- catch: (error) => RequestBodyError("MultipartError", error),
145
- })
146
- const parsed = yield* decode(record)
147
- return {
148
- context: {
149
- body: {
150
- ...ctx.body,
151
- ...parsed,
152
- },
153
- },
154
- }
155
- }),
156
- )
157
- }
158
-
159
- export function schemaBodyForm(
160
- fields,
161
- ) {
162
- const decode = Schema.decodeUnknown(fields)
163
- return RouteHook.filter((ctx) =>
164
- Effect.gen(function* () {
165
- const contentType = ctx.request.headers.get("content-type") ?? ""
166
-
167
- if (contentType.includes("application/x-www-form-urlencoded")) {
168
- const text = yield* Effect.tryPromise({
169
- try: () => ctx.request.text(),
170
- catch: (error) => RequestBodyError("UrlParamsError", error),
171
- })
172
- const params = new URLSearchParams(text)
173
- const record = Http.mapUrlSearchParams(params)
174
- const parsed = yield* decode(record)
175
- return {
176
- context: {
177
- body: {
178
- ...ctx.body,
179
- ...parsed,
180
- },
181
- },
182
- }
183
- }
184
-
185
- const record = yield* Effect.tryPromise({
186
- try: () => Http.parseFormData(ctx.request),
187
- catch: (error) => RequestBodyError("FormDataError", error),
188
- })
189
- const parsed = yield* decode(record)
190
- return {
191
- context: {
192
- body: {
193
- ...ctx.body,
194
- ...parsed,
195
- },
196
- },
197
- }
198
- }),
199
- )
200
- }
201
-
202
- /**
203
- * Intercepts typed errors from downstream handlers, encodes them through the
204
- * schema, and returns a JSON response with the given status code.
205
- *
206
- * Without `schemaError`, handler errors fall through to global catch during
207
- * execution of request. `schemaError` short circuts error handling by
208
- * return an error response immedietly.
209
- *
210
- * TODO: store the errors in runtime to enable generating OpenAPI and other
211
- * goodies.
212
- */
213
- export function schemaError(
214
- schema,
215
- options,
216
- ) {
217
- const status = options?.status ?? (schema).status
218
- if (typeof status !== "number") {
219
- throw new Error(
220
- "schemaError: status is required either via options or as a static property on the schema",
221
- )
222
- }
223
- const encode = Schema.encode(schema)
224
- const is = Schema.is(schema)
225
- return function (
226
- self,
227
- ) {
228
- const route = Route.make((_context, next) =>
229
- Entity.resolve(next()).pipe(
230
- Effect.catchIf(is, (error) =>
231
- Effect.map(Effect.orDie(encode(error)), (encoded) => Entity.make(encoded, { status })),
232
- ),
233
- ),
234
- )
235
-
236
- const items = [
237
- ...Route.items(self),
238
- route,
239
- ]
240
-
241
- return Route.set(items, Route.descriptor(self))
242
- }
243
- }
244
-
245
- export function schemaSuccess(
246
- schema,
247
- ) {
248
- const encode = Schema.encodeUnknown(schema)
249
- return function (
250
- self,
251
- ) {
252
- const route = Route.make((_context, next) =>
253
- Effect.flatMap(Entity.resolve(next()), (entity) =>
254
- Effect.map(encode(entity.body), (encoded) =>
255
- Entity.make(encoded, {
256
- status: entity.status,
257
- headers: entity.headers,
258
- url: entity.url,
259
- }),
260
- ),
261
- ),
262
- )
263
-
264
- const items = [
265
- ...Route.items(self),
266
- route,
267
- ]
268
-
269
- return Route.set(items, Route.descriptor(self))
270
- }
271
- }
package/dist/RouteSse.js DELETED
@@ -1,94 +0,0 @@
1
- import * as Duration from "effect/Duration"
2
- import * as Effect from "effect/Effect"
3
- import * as Schedule from "effect/Schedule"
4
- import * as Stream from "effect/Stream"
5
- import * as Entity from "./Entity.js"
6
- import * as Route from "./Route.js"
7
- import * as StreamExtra from "./StreamExtra.js"
8
-
9
- const HEARTBEAT_INTERVAL = Duration.seconds(5)
10
- const HEARTBEAT = ": <3\n\n"
11
-
12
- function isTaggedEvent(event) {
13
- return Object.hasOwn(event, "_tag") && typeof event["_tag"] === "string"
14
- }
15
-
16
- function formatSseEvent(event) {
17
- if (isTaggedEvent(event)) {
18
- const json = JSON.stringify(event)
19
- return `event: ${event._tag}\ndata: ${json}\n\n`
20
- }
21
-
22
- const e = event
23
- let result = ""
24
- if (e.event) {
25
- result += `event: ${e.event}\n`
26
- }
27
- if (typeof e.data === "string") {
28
- for (const line of e.data.split("\n")) {
29
- result += `data: ${line}\n`
30
- }
31
- }
32
- if (e.retry !== undefined) {
33
- result += `retry: ${e.retry}\n`
34
- }
35
- if (result === "") {
36
- return ""
37
- }
38
- return result + "\n"
39
- }
40
-
41
- export function sse(handler) {
42
- return function (self) {
43
- const sseHandler = (ctx, _next) => {
44
- const getStream = () => {
45
- if (typeof handler === "function") {
46
- const result = (handler)(ctx, _next)
47
- if (StreamExtra.isStream(result)) {
48
- return Effect.succeed(result)
49
- }
50
- if (Effect.isEffect(result)) {
51
- return result
52
- }
53
- return Effect.gen(function* () {
54
- return yield* result
55
- })
56
- }
57
- if (StreamExtra.isStream(handler)) {
58
- return Effect.succeed(handler)
59
- }
60
- if (Effect.isEffect(handler)) {
61
- return handler
62
- }
63
- return Effect.succeed(Stream.empty)
64
- }
65
-
66
- return Effect.map(getStream(), (eventStream) => {
67
- const formattedStream = Stream.map(eventStream, formatSseEvent)
68
- const heartbeat = Stream.repeat(
69
- Stream.succeed(HEARTBEAT),
70
- Schedule.spaced(HEARTBEAT_INTERVAL),
71
- ).pipe(Stream.drop(1))
72
- const merged = Stream.merge(formattedStream, heartbeat, {
73
- haltStrategy: "left",
74
- })
75
- return Entity.make(merged, {
76
- headers: {
77
- "content-type": "text/event-stream",
78
- "cache-control": "no-cache",
79
- connection: "keep-alive",
80
- },
81
- })
82
- })
83
- }
84
-
85
- const route = Route.make(
86
- sseHandler,
87
- { format: "text" },
88
- )
89
-
90
- const items = [...Route.items(self), route]
91
-
92
- return Route.set(items, Route.descriptor(self))
93
- }
94
- }
package/dist/RouteTree.js DELETED
@@ -1,119 +0,0 @@
1
- import * as Predicate from "effect/Predicate"
2
- import * as PathPattern from "./PathPattern.js"
3
- import * as Route from "./Route.js"
4
-
5
- const TypeId = Symbol.for("effect-start/RouteTree")
6
- const RouteTreeRoutes = Symbol()
7
-
8
- const LayerKey = "*"
9
-
10
- function routes(tree) {
11
- return tree[RouteTreeRoutes]
12
- }
13
-
14
- // segment priority: static (0) < :param (1) < :param? (2) < :param+ (3) < :param* (4)
15
- function sortScore(path) {
16
- const segments = path.split("/")
17
- const greedyIdx = segments.findIndex((s) => s.endsWith("*") || s.endsWith("+"))
18
- const maxPriority = Math.max(
19
- ...segments.map((s) =>
20
- !s.startsWith(":") ? 0 : s.endsWith("*") ? 4 : s.endsWith("+") ? 3 : s.endsWith("?") ? 2 : 1,
21
- ),
22
- 0,
23
- )
24
-
25
- return greedyIdx === -1
26
- ? // non-greedy: sort by depth, then by max segment priority
27
- (segments.length << 16) + (maxPriority << 8)
28
- : // greedy: sort after non-greedy, by greedy position (later = first), then priority
29
- (1 << 24) + ((16 - greedyIdx) << 16) + (maxPriority << 8)
30
- }
31
-
32
- function sortRoutes(input) {
33
- const keys = Object.keys(input).sort((a, b) => sortScore(a) - sortScore(b) || a.localeCompare(b))
34
- const sorted = {}
35
- for (const key of keys) {
36
- sorted[key] = input[key]
37
- }
38
- return sorted
39
- }
40
-
41
- export function make(
42
- input,
43
- ) {
44
- const layerRoutes = [...(input[LayerKey] ?? [])]
45
- const merged = {}
46
-
47
- function flatten(map, prefix, layers) {
48
- for (const key of Object.keys(map)) {
49
- if (key === LayerKey) continue
50
- const path = key
51
- const entry = map[path]
52
- const fullPath = `${prefix}${path}`
53
-
54
- if (isRouteTree(entry)) {
55
- flatten(routes(entry), fullPath, layers)
56
- } else {
57
- merged[fullPath] = [...layers, ...(entry)]
58
- }
59
- }
60
- }
61
-
62
- flatten(input, "", layerRoutes)
63
-
64
- return {
65
- [TypeId]: TypeId,
66
- [RouteTreeRoutes]: sortRoutes(merged),
67
- }
68
- }
69
-
70
- function* flattenRoutes(
71
- path,
72
- routes,
73
- ) {
74
- for (const route of routes) {
75
- const descriptor = {
76
- ...route[Route.RouteDescriptor],
77
- path,
78
- }
79
- yield Route.make(route.handler, descriptor)
80
- }
81
- }
82
-
83
- export function* walk(tree) {
84
- const _routes = routes(tree)
85
-
86
- for (const path of Object.keys(_routes)) {
87
- yield* flattenRoutes(path, _routes[path])
88
- }
89
- }
90
-
91
- export function merge(a, b) {
92
- const combined = { ...routes(a) }
93
- for (const [path, items] of Object.entries(routes(b))) {
94
- const key = path
95
- combined[key] = combined[key] ? [...combined[key], ...items] : items
96
- }
97
- return {
98
- [TypeId]: TypeId,
99
- [RouteTreeRoutes]: sortRoutes(combined),
100
- }
101
- }
102
-
103
- export function isRouteTree(input) {
104
- return Predicate.hasProperty(input, TypeId)
105
- }
106
-
107
- export function lookup(tree, method, path) {
108
- for (const route of walk(tree)) {
109
- const descriptor = Route.descriptor(route)
110
-
111
- if (descriptor.method !== "*" && descriptor.method !== method) continue
112
-
113
- const params = PathPattern.match(descriptor.path, path)
114
- if (params !== null) {
115
- return { route, params }
116
- }
117
- }
118
- return null
119
- }
package/dist/RouteTrie.js DELETED
@@ -1,179 +0,0 @@
1
- import * as PathPattern from "./PathPattern.js"
2
- import * as Route from "./Route.js"
3
-
4
- function createNode() {
5
- return {
6
- children: {},
7
- paramChild: null,
8
- paramName: null,
9
- requiredWildcardChild: null,
10
- requiredWildcardName: null,
11
- optionalWildcardChild: null,
12
- optionalWildcardName: null,
13
- routes: [],
14
- }
15
- }
16
-
17
- function insertRoute(node, segments, route) {
18
- if (segments.length === 0) {
19
- node.routes.push(route)
20
- return
21
- }
22
-
23
- const segment = segments[0]
24
- const rest = segments.slice(1)
25
-
26
- if (segment.startsWith(":")) {
27
- const name = segment.slice(1)
28
-
29
- if (name.endsWith("+")) {
30
- if (!node.requiredWildcardChild) {
31
- node.requiredWildcardChild = createNode()
32
- }
33
- node.requiredWildcardChild.requiredWildcardName = name.slice(0, -1)
34
- node.requiredWildcardChild.routes.push(route)
35
- } else if (name.endsWith("*")) {
36
- if (!node.optionalWildcardChild) {
37
- node.optionalWildcardChild = createNode()
38
- }
39
- node.optionalWildcardChild.optionalWildcardName = name.slice(0, -1)
40
- node.optionalWildcardChild.routes.push(route)
41
- } else if (name.endsWith("?")) {
42
- if (!node.paramChild) {
43
- node.paramChild = createNode()
44
- }
45
- node.paramChild.paramName = name.slice(0, -1)
46
- insertRoute(node.paramChild, rest, route)
47
- insertRoute(node, rest, route)
48
- } else {
49
- if (!node.paramChild) {
50
- node.paramChild = createNode()
51
- }
52
- node.paramChild.paramName = name
53
- insertRoute(node.paramChild, rest, route)
54
- }
55
- } else {
56
- if (!node.children[segment]) {
57
- node.children[segment] = createNode()
58
- }
59
- insertRoute(node.children[segment], rest, route)
60
- }
61
- }
62
-
63
- function collectRoutes(
64
- items,
65
- parentPath,
66
- parentMethod,
67
- ) {
68
- const results = []
69
-
70
- for (const item of items) {
71
- const desc = Route.descriptor(item)
72
- const currentPath = typeof desc?.path === "string" ? parentPath + desc.path : parentPath
73
- const currentMethod = desc?.method ?? parentMethod
74
-
75
- if (Route.isRoute(item)) {
76
- if (currentPath !== "") {
77
- results.push({
78
- route: item,
79
- method: currentMethod,
80
- path: currentPath,
81
- })
82
- }
83
- } else {
84
- const nestedItems = Route.items(item)
85
- results.push(...collectRoutes(nestedItems, currentPath, currentMethod))
86
- }
87
- }
88
-
89
- return results
90
- }
91
-
92
- export function make(set) {
93
- const methods = {}
94
- const collected = collectRoutes(Route.items(set), "", "*")
95
-
96
- for (const { route, method, path } of collected) {
97
- if (!methods[method]) {
98
- methods[method] = createNode()
99
- }
100
- const result = PathPattern.validate(path)
101
- if (!result.ok) {
102
- throw new Error(result.error)
103
- }
104
- insertRoute(methods[method], result.segments, route)
105
- }
106
-
107
- return { methods }
108
- }
109
-
110
- function lookupNode(
111
- node,
112
- segments,
113
- params,
114
- ) {
115
- const results = []
116
-
117
- if (segments.length === 0) {
118
- for (const route of node.routes) {
119
- results.push({ route, params })
120
- }
121
- if (node.optionalWildcardChild && node.optionalWildcardChild.optionalWildcardName) {
122
- for (const route of node.optionalWildcardChild.routes) {
123
- results.push({ route, params })
124
- }
125
- }
126
- return results
127
- }
128
-
129
- const segment = segments[0]
130
- const rest = segments.slice(1)
131
-
132
- if (node.children[segment]) {
133
- results.push(...lookupNode(node.children[segment], rest, params))
134
- }
135
-
136
- if (node.paramChild && node.paramChild.paramName) {
137
- const newParams = { ...params, [node.paramChild.paramName]: segment }
138
- results.push(...lookupNode(node.paramChild, rest, newParams))
139
- }
140
-
141
- if (node.requiredWildcardChild && node.requiredWildcardChild.requiredWildcardName) {
142
- const wildcardValue = segments.join("/")
143
- const newParams = {
144
- ...params,
145
- [node.requiredWildcardChild.requiredWildcardName]: wildcardValue,
146
- }
147
- for (const route of node.requiredWildcardChild.routes) {
148
- results.push({ route, params: newParams })
149
- }
150
- }
151
-
152
- if (node.optionalWildcardChild && node.optionalWildcardChild.optionalWildcardName) {
153
- const wildcardValue = segments.join("/")
154
- const newParams = {
155
- ...params,
156
- [node.optionalWildcardChild.optionalWildcardName]: wildcardValue,
157
- }
158
- for (const route of node.optionalWildcardChild.routes) {
159
- results.push({ route, params: newParams })
160
- }
161
- }
162
-
163
- return results
164
- }
165
-
166
- export function lookup(trie, method, path) {
167
- const segments = path.split("/").filter(Boolean)
168
- const results = []
169
-
170
- if (trie.methods[method]) {
171
- results.push(...lookupNode(trie.methods[method], segments, {}))
172
- }
173
-
174
- if (method !== "*" && trie.methods["*"]) {
175
- results.push(...lookupNode(trie.methods["*"], segments, {}))
176
- }
177
-
178
- return results
179
- }