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.
- package/package.json +18 -86
- package/dist/ChildProcess.js +0 -42
- package/dist/Commander.js +0 -410
- package/dist/ContentNegotiation.js +0 -465
- package/dist/Cookies.js +0 -371
- package/dist/Development.js +0 -94
- package/dist/Effectify.js +0 -27
- package/dist/Entity.js +0 -289
- package/dist/Fetch.js +0 -192
- package/dist/FilePathPattern.js +0 -97
- package/dist/FileRouter.js +0 -204
- package/dist/FileRouterCodegen.js +0 -298
- package/dist/FileSystem.js +0 -132
- package/dist/Http.js +0 -107
- package/dist/PathPattern.js +0 -451
- package/dist/PlatformError.js +0 -40
- package/dist/PlatformRuntime.js +0 -71
- package/dist/Route.js +0 -143
- package/dist/RouteBody.js +0 -92
- package/dist/RouteError.js +0 -76
- package/dist/RouteHook.js +0 -64
- package/dist/RouteHttp.js +0 -367
- package/dist/RouteHttpTracer.js +0 -90
- package/dist/RouteMount.js +0 -86
- package/dist/RouteSchema.js +0 -271
- package/dist/RouteSse.js +0 -94
- package/dist/RouteTree.js +0 -119
- package/dist/RouteTrie.js +0 -179
- package/dist/SchemaExtra.js +0 -99
- package/dist/Socket.js +0 -40
- package/dist/SqlIntrospect.js +0 -515
- package/dist/Start.js +0 -79
- package/dist/StartApp.js +0 -3
- package/dist/StreamExtra.js +0 -135
- package/dist/System.js +0 -38
- package/dist/TuplePathPattern.js +0 -74
- package/dist/Unique.js +0 -226
- package/dist/Values.js +0 -52
- package/dist/bun/BunBundle.js +0 -186
- package/dist/bun/BunChildProcessSpawner.js +0 -142
- package/dist/bun/BunImportTrackerPlugin.js +0 -91
- package/dist/bun/BunRoute.js +0 -157
- package/dist/bun/BunRuntime.js +0 -41
- package/dist/bun/BunServer.js +0 -285
- package/dist/bun/BunVirtualFilesPlugin.js +0 -54
- package/dist/bun/_BunEnhancedResolve.js +0 -127
- package/dist/bun/index.js +0 -5
- package/dist/bundler/Bundle.js +0 -92
- package/dist/bundler/BundleFiles.js +0 -154
- package/dist/bundler/BundleRoute.js +0 -62
- package/dist/client/Overlay.js +0 -33
- package/dist/client/ScrollState.js +0 -106
- package/dist/client/index.js +0 -97
- package/dist/console/Console.js +0 -42
- package/dist/console/ConsoleErrors.js +0 -211
- package/dist/console/ConsoleLogger.js +0 -56
- package/dist/console/ConsoleMetrics.js +0 -72
- package/dist/console/ConsoleProcess.js +0 -59
- package/dist/console/ConsoleStore.js +0 -72
- package/dist/console/ConsoleTracer.js +0 -107
- package/dist/console/Simulation.js +0 -784
- package/dist/console/index.js +0 -3
- package/dist/console/routes/tree.js +0 -30
- package/dist/datastar/actions/fetch.js +0 -536
- package/dist/datastar/actions/peek.js +0 -13
- package/dist/datastar/actions/setAll.js +0 -19
- package/dist/datastar/actions/toggleAll.js +0 -19
- package/dist/datastar/attributes/attr.js +0 -49
- package/dist/datastar/attributes/bind.js +0 -194
- package/dist/datastar/attributes/class.js +0 -54
- package/dist/datastar/attributes/computed.js +0 -25
- package/dist/datastar/attributes/effect.js +0 -10
- package/dist/datastar/attributes/indicator.js +0 -33
- package/dist/datastar/attributes/init.js +0 -27
- package/dist/datastar/attributes/jsonSignals.js +0 -33
- package/dist/datastar/attributes/on.js +0 -81
- package/dist/datastar/attributes/onIntersect.js +0 -53
- package/dist/datastar/attributes/onInterval.js +0 -31
- package/dist/datastar/attributes/onSignalPatch.js +0 -51
- package/dist/datastar/attributes/ref.js +0 -11
- package/dist/datastar/attributes/show.js +0 -32
- package/dist/datastar/attributes/signals.js +0 -18
- package/dist/datastar/attributes/style.js +0 -57
- package/dist/datastar/attributes/text.js +0 -29
- package/dist/datastar/engine.js +0 -1145
- package/dist/datastar/index.js +0 -25
- package/dist/datastar/utils.js +0 -250
- package/dist/datastar/watchers/patchElements.js +0 -486
- package/dist/datastar/watchers/patchSignals.js +0 -14
- package/dist/experimental/EncryptedCookies.js +0 -328
- package/dist/experimental/index.js +0 -1
- package/dist/hyper/Hyper.js +0 -28
- package/dist/hyper/HyperHtml.js +0 -165
- package/dist/hyper/HyperNode.js +0 -13
- package/dist/hyper/HyperRoute.js +0 -45
- package/dist/hyper/html.js +0 -30
- package/dist/hyper/index.js +0 -5
- package/dist/hyper/jsx-runtime.js +0 -14
- package/dist/index.js +0 -8
- package/dist/node/NodeFileSystem.js +0 -675
- package/dist/node/NodeUtils.js +0 -23
- package/dist/sql/Sql.js +0 -8
- package/dist/sql/bun/index.js +0 -142
- package/dist/sql/index.js +0 -1
- package/dist/sql/libsql/index.js +0 -156
- package/dist/sql/mssql/docker.js +0 -110
- package/dist/sql/mssql/index.js +0 -194
- package/dist/testing/TestLogger.js +0 -42
- package/dist/testing/index.js +0 -2
- package/dist/testing/utils.js +0 -61
- package/dist/x/cloudflare/CloudflareTunnel.js +0 -63
- package/dist/x/cloudflare/index.js +0 -1
- package/dist/x/tailscale/TailscaleTunnel.js +0 -94
- package/dist/x/tailscale/index.js +0 -1
- package/dist/x/tailwind/TailwindPlugin.js +0 -294
- package/dist/x/tailwind/compile.js +0 -210
- package/dist/x/tailwind/plugin.js +0 -17
package/dist/RouteSchema.js
DELETED
|
@@ -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
|
-
}
|