effect-start 0.14.0 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +8 -9
- package/src/Commander.test.ts +507 -245
- package/src/ContentNegotiation.test.ts +603 -0
- package/src/ContentNegotiation.ts +542 -0
- package/src/Entity.test.ts +592 -0
- package/src/Entity.ts +362 -0
- package/src/FileRouter.ts +16 -12
- package/src/{FileRouterCodegen.test.ts → FileRouterCodegen.todo.ts} +384 -219
- package/src/FileRouterCodegen.ts +6 -6
- package/src/FileRouterPattern.test.ts +93 -62
- package/src/FileRouter_files.test.ts +5 -5
- package/src/FileRouter_path.test.ts +121 -69
- package/src/FileRouter_tree.test.ts +62 -56
- package/src/FileSystemExtra.test.ts +46 -30
- package/src/Http.test.ts +319 -0
- package/src/Http.ts +167 -0
- package/src/HttpAppExtra.test.ts +39 -20
- package/src/HttpAppExtra.ts +0 -1
- package/src/HttpUtils.test.ts +35 -18
- package/src/HttpUtils.ts +2 -0
- package/src/PathPattern.test.ts +648 -0
- package/src/PathPattern.ts +485 -0
- package/src/Route.ts +266 -1069
- package/src/RouteBody.test.ts +234 -0
- package/src/RouteBody.ts +193 -0
- package/src/RouteHook.test.ts +40 -0
- package/src/RouteHook.ts +106 -0
- package/src/RouteHttp.test.ts +2906 -0
- package/src/RouteHttp.ts +427 -0
- package/src/RouteHttpTracer.ts +92 -0
- package/src/RouteMount.test.ts +481 -0
- package/src/RouteMount.ts +470 -0
- package/src/RouteSchema.test.ts +427 -0
- package/src/RouteSchema.ts +423 -0
- package/src/RouteTree.test.ts +494 -0
- package/src/RouteTree.ts +219 -0
- package/src/RouteTrie.test.ts +322 -0
- package/src/RouteTrie.ts +224 -0
- package/src/RouterPattern.test.ts +569 -548
- package/src/RouterPattern.ts +7 -7
- package/src/Start.ts +3 -3
- package/src/StreamExtra.ts +21 -1
- package/src/TuplePathPattern.ts +64 -0
- package/src/Values.test.ts +263 -0
- package/src/Values.ts +76 -0
- package/src/bun/BunBundle.test.ts +36 -42
- package/src/bun/BunBundle.ts +2 -2
- package/src/bun/BunBundle_imports.test.ts +4 -6
- package/src/bun/BunHttpServer.test.ts +183 -6
- package/src/bun/BunHttpServer.ts +72 -32
- package/src/bun/BunHttpServer_web.ts +18 -6
- package/src/bun/BunImportTrackerPlugin.test.ts +3 -3
- package/src/bun/BunRoute.test.ts +124 -442
- package/src/bun/BunRoute.ts +146 -286
- package/src/{BundleHttp.test.ts → bundler/BundleHttp.test.ts} +34 -60
- package/src/{BundleHttp.ts → bundler/BundleHttp.ts} +1 -2
- package/src/client/index.ts +1 -1
- package/src/{Effect_HttpRouter.test.ts → effect/HttpRouter.test.ts} +69 -90
- package/src/experimental/EncryptedCookies.test.ts +125 -64
- package/src/experimental/SseHttpResponse.ts +0 -1
- package/src/hyper/Hyper.ts +89 -0
- package/src/{HyperHtml.test.ts → hyper/HyperHtml.test.ts} +13 -13
- package/src/{HyperHtml.ts → hyper/HyperHtml.ts} +2 -2
- package/src/{jsx.d.ts → hyper/jsx.d.ts} +1 -1
- package/src/index.ts +3 -4
- package/src/middlewares/BasicAuthMiddleware.test.ts +29 -19
- package/src/{NodeFileSystem.ts → node/FileSystem.ts} +6 -2
- package/src/testing/TestHttpClient.test.ts +26 -26
- package/src/testing/TestLogger.test.ts +27 -14
- package/src/testing/TestLogger.ts +15 -9
- package/src/x/datastar/Datastar.test.ts +47 -48
- package/src/x/datastar/Datastar.ts +1 -1
- package/src/x/tailwind/TailwindPlugin.test.ts +56 -58
- package/src/x/tailwind/plugin.ts +1 -1
- package/src/FileHttpRouter.test.ts +0 -239
- package/src/FileHttpRouter.ts +0 -194
- package/src/Hyper.ts +0 -194
- package/src/Route.test.ts +0 -1370
- package/src/RouteRender.ts +0 -40
- package/src/Router.test.ts +0 -375
- package/src/Router.ts +0 -255
- package/src/bun/BunRoute_bundles.test.ts +0 -219
- /package/src/{Bundle.ts → bundler/Bundle.ts} +0 -0
- /package/src/{BundleFiles.ts → bundler/BundleFiles.ts} +0 -0
- /package/src/{HyperNode.ts → hyper/HyperNode.ts} +0 -0
- /package/src/{jsx-runtime.ts → hyper/jsx-runtime.ts} +0 -0
- /package/src/{NodeUtils.ts → node/Utils.ts} +0 -0
package/src/FileHttpRouter.ts
DELETED
|
@@ -1,194 +0,0 @@
|
|
|
1
|
-
// @ts-nocheck
|
|
2
|
-
import * as HttpApp from "@effect/platform/HttpApp"
|
|
3
|
-
import * as HttpMiddleware from "@effect/platform/HttpMiddleware"
|
|
4
|
-
import * as HttpRouter from "@effect/platform/HttpRouter"
|
|
5
|
-
import * as HttpServerRequest from "@effect/platform/HttpServerRequest"
|
|
6
|
-
import * as HttpServerResponse from "@effect/platform/HttpServerResponse"
|
|
7
|
-
import * as Effect from "effect/Effect"
|
|
8
|
-
import * as Function from "effect/Function"
|
|
9
|
-
import * as HttpUtils from "./HttpUtils.ts"
|
|
10
|
-
import * as Route from "./Route.ts"
|
|
11
|
-
import * as Router from "./Router.ts"
|
|
12
|
-
import * as RouteRender from "./RouteRender.ts"
|
|
13
|
-
import * as RouterPattern from "./RouterPattern.ts"
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Combines Effect error channel from a record of effects.
|
|
17
|
-
*/
|
|
18
|
-
type RecordEffectError<A> = A extends Record<string, any> ? Exclude<
|
|
19
|
-
{
|
|
20
|
-
[K in keyof A]: A[K] extends Effect.Effect<any, infer E, any> ? E
|
|
21
|
-
: never
|
|
22
|
-
}[keyof A],
|
|
23
|
-
undefined
|
|
24
|
-
>
|
|
25
|
-
: never
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Combines Effect requirement channel from a record of effects.
|
|
29
|
-
*/
|
|
30
|
-
type RecordEffectRequirements<A> = A extends Record<string, any> ? Exclude<
|
|
31
|
-
{
|
|
32
|
-
[K in keyof A]: A[K] extends Effect.Effect<any, any, infer R> ? R
|
|
33
|
-
: never
|
|
34
|
-
}[keyof A],
|
|
35
|
-
undefined
|
|
36
|
-
>
|
|
37
|
-
: never
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Infers the HttpRouter type from an array of ServerRoutes
|
|
41
|
-
*/
|
|
42
|
-
export type HttpRouterFromServerRoutes<
|
|
43
|
-
Routes extends ReadonlyArray<Router.ServerRoute>,
|
|
44
|
-
> = HttpRouter.HttpRouter<
|
|
45
|
-
(Routes extends ReadonlyArray<infer Route>
|
|
46
|
-
? Route extends Router.ServerRoute
|
|
47
|
-
? RecordEffectError<Awaited<ReturnType<Route["load"]>>>
|
|
48
|
-
: never
|
|
49
|
-
: never),
|
|
50
|
-
Exclude<
|
|
51
|
-
Routes extends ReadonlyArray<infer Route>
|
|
52
|
-
? Route extends Router.ServerRoute
|
|
53
|
-
? RecordEffectRequirements<Awaited<ReturnType<Route["load"]>>>
|
|
54
|
-
: never
|
|
55
|
-
: never,
|
|
56
|
-
// exclude HttpServerRequest since HttpRouter already has it
|
|
57
|
-
HttpServerRequest.HttpServerRequest
|
|
58
|
-
>
|
|
59
|
-
>
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Find layer routes that match a given route's method and media type.
|
|
63
|
-
*/
|
|
64
|
-
function findMatchingLayerRoutes(
|
|
65
|
-
route: Route.Route.Default,
|
|
66
|
-
layers: Route.RouteLayer[],
|
|
67
|
-
): Route.Route.Default[] {
|
|
68
|
-
const matchingRoutes: Route.Route.Default[] = []
|
|
69
|
-
|
|
70
|
-
for (const layer of layers) {
|
|
71
|
-
for (const layerRoute of layer.set) {
|
|
72
|
-
if (Route.matches(layerRoute, route)) {
|
|
73
|
-
matchingRoutes.push(layerRoute)
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
return matchingRoutes
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Wrap an inner route with a layer route.
|
|
83
|
-
* Returns a new route that, when executed, provides next() to call the inner route.
|
|
84
|
-
*/
|
|
85
|
-
function wrapWithLayerRoute(
|
|
86
|
-
innerRoute: Route.Route.Default,
|
|
87
|
-
layerRoute: Route.Route.Default,
|
|
88
|
-
): Route.Route.Default {
|
|
89
|
-
const handler: Route.RouteHandler = (context) => {
|
|
90
|
-
const innerNext = () => innerRoute.handler(context)
|
|
91
|
-
|
|
92
|
-
const contextWithNext: Route.RouteContext = {
|
|
93
|
-
...context,
|
|
94
|
-
next: innerNext,
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
return layerRoute.handler(contextWithNext)
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
return Route.make({
|
|
101
|
-
method: layerRoute.method,
|
|
102
|
-
media: layerRoute.media,
|
|
103
|
-
handler,
|
|
104
|
-
schemas: {},
|
|
105
|
-
})
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Makes a HttpRouter from file-based routes.
|
|
110
|
-
*/
|
|
111
|
-
|
|
112
|
-
export function make<
|
|
113
|
-
Routes extends ReadonlyArray<Router.ServerRoute>,
|
|
114
|
-
>(
|
|
115
|
-
routes: Routes,
|
|
116
|
-
): Effect.Effect<HttpRouterFromServerRoutes<Routes>> {
|
|
117
|
-
return Effect.gen(function*() {
|
|
118
|
-
const routesWithModules = yield* Effect.forEach(
|
|
119
|
-
routes,
|
|
120
|
-
(route) =>
|
|
121
|
-
Effect.gen(function*() {
|
|
122
|
-
const module = yield* Effect.tryPromise(() => route.load()).pipe(
|
|
123
|
-
Effect.orDie,
|
|
124
|
-
)
|
|
125
|
-
|
|
126
|
-
const layerModules = route.layers
|
|
127
|
-
? yield* Effect.forEach(
|
|
128
|
-
route.layers,
|
|
129
|
-
(layerLoad) =>
|
|
130
|
-
Effect.tryPromise(() => layerLoad()).pipe(Effect.orDie),
|
|
131
|
-
)
|
|
132
|
-
: []
|
|
133
|
-
|
|
134
|
-
const layers = layerModules
|
|
135
|
-
.map((mod: any) => mod.default)
|
|
136
|
-
.filter(Route.isRouteLayer)
|
|
137
|
-
|
|
138
|
-
return {
|
|
139
|
-
path: route.path,
|
|
140
|
-
routeSet: module.default,
|
|
141
|
-
layers,
|
|
142
|
-
}
|
|
143
|
-
}),
|
|
144
|
-
)
|
|
145
|
-
|
|
146
|
-
let router: HttpRouter.HttpRouter<any, any> = HttpRouter.empty
|
|
147
|
-
|
|
148
|
-
for (const { path, routeSet, layers } of routesWithModules) {
|
|
149
|
-
for (const route of routeSet.set) {
|
|
150
|
-
const matchingLayerRoutes = findMatchingLayerRoutes(route, layers)
|
|
151
|
-
|
|
152
|
-
let wrappedRoute = route
|
|
153
|
-
// Reverse so first layer in array becomes outermost wrapper.
|
|
154
|
-
// Example: [outerLayer, innerLayer] wraps as outer(inner(route))
|
|
155
|
-
for (const layerRoute of matchingLayerRoutes.reverse()) {
|
|
156
|
-
wrappedRoute = wrapWithLayerRoute(wrappedRoute, layerRoute)
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
const wrappedHandler: HttpApp.Default = Effect.gen(function*() {
|
|
160
|
-
const request = yield* HttpServerRequest.HttpServerRequest
|
|
161
|
-
|
|
162
|
-
const context: Route.RouteContext = {
|
|
163
|
-
request,
|
|
164
|
-
get url() {
|
|
165
|
-
return HttpUtils.makeUrlFromRequest(request)
|
|
166
|
-
},
|
|
167
|
-
slots: {},
|
|
168
|
-
next: () => Effect.void,
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
return yield* RouteRender.render(wrappedRoute, context)
|
|
172
|
-
})
|
|
173
|
-
|
|
174
|
-
const allMiddleware = layers
|
|
175
|
-
.map((layer) => layer.httpMiddleware)
|
|
176
|
-
.filter((m): m is Route.HttpMiddlewareFunction => m !== undefined)
|
|
177
|
-
|
|
178
|
-
let finalHandler = wrappedHandler
|
|
179
|
-
for (const middleware of allMiddleware) {
|
|
180
|
-
finalHandler = middleware(finalHandler)
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
for (const pattern of RouterPattern.toEffect(path)) {
|
|
184
|
-
router = HttpRouter.route(route.method)(
|
|
185
|
-
pattern,
|
|
186
|
-
finalHandler as any,
|
|
187
|
-
)(router)
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
return router as HttpRouterFromServerRoutes<Routes>
|
|
193
|
-
})
|
|
194
|
-
}
|
package/src/Hyper.ts
DELETED
|
@@ -1,194 +0,0 @@
|
|
|
1
|
-
import * as HttpApp from "@effect/platform/HttpApp"
|
|
2
|
-
import * as HttpServerResponse from "@effect/platform/HttpServerResponse"
|
|
3
|
-
import * as Context from "effect/Context"
|
|
4
|
-
import * as Effect from "effect/Effect"
|
|
5
|
-
import * as Effectable from "effect/Effectable"
|
|
6
|
-
import * as Fiber from "effect/Fiber"
|
|
7
|
-
import * as Function from "effect/Function"
|
|
8
|
-
import * as Layer from "effect/Layer"
|
|
9
|
-
import * as Option from "effect/Option"
|
|
10
|
-
import * as Pipeable from "effect/Pipeable"
|
|
11
|
-
import { YieldWrap } from "effect/Utils"
|
|
12
|
-
import * as HyperHtml from "./HyperHtml.ts"
|
|
13
|
-
import type { JSX } from "./jsx.d.ts"
|
|
14
|
-
import { HyperHooks } from "./x/datastar/index.ts"
|
|
15
|
-
|
|
16
|
-
const TypeId = Symbol.for("~hyper/TypeId")
|
|
17
|
-
const LayoutTypeId = Symbol.for("~hyper/LayoutTypeId")
|
|
18
|
-
|
|
19
|
-
type Elements = JSX.IntrinsicElements
|
|
20
|
-
|
|
21
|
-
type Children = JSX.Children
|
|
22
|
-
|
|
23
|
-
export type {
|
|
24
|
-
Children,
|
|
25
|
-
Elements,
|
|
26
|
-
JSX,
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export class Hyper extends Context.Tag("Hyper")<Hyper, {
|
|
30
|
-
hooks: typeof HyperHooks | undefined
|
|
31
|
-
}>() {}
|
|
32
|
-
|
|
33
|
-
export function layer(opts: {
|
|
34
|
-
hooks: typeof HyperHooks
|
|
35
|
-
}) {
|
|
36
|
-
return Layer.sync(Hyper, () => {
|
|
37
|
-
return {
|
|
38
|
-
hooks: opts.hooks,
|
|
39
|
-
}
|
|
40
|
-
})
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Accepts Effect that returns a HyperNode
|
|
45
|
-
* to a HttpApp.
|
|
46
|
-
* TODO: Implement Hyper.page that returns Hyper.Element
|
|
47
|
-
*/
|
|
48
|
-
export function handle<E, R>(
|
|
49
|
-
handler: Effect.Effect<
|
|
50
|
-
JSX.Children | HttpServerResponse.HttpServerResponse,
|
|
51
|
-
E,
|
|
52
|
-
R
|
|
53
|
-
>,
|
|
54
|
-
): HttpApp.Default<E, R>
|
|
55
|
-
export function handle(
|
|
56
|
-
handler: () => Generator<
|
|
57
|
-
never,
|
|
58
|
-
JSX.Children | HttpServerResponse.HttpServerResponse,
|
|
59
|
-
any
|
|
60
|
-
>,
|
|
61
|
-
): HttpApp.Default<never, never>
|
|
62
|
-
export function handle<Eff extends YieldWrap<Effect.Effect<any, any, any>>>(
|
|
63
|
-
handler: () => Generator<
|
|
64
|
-
Eff,
|
|
65
|
-
JSX.Children | HttpServerResponse.HttpServerResponse,
|
|
66
|
-
any
|
|
67
|
-
>,
|
|
68
|
-
): HttpApp.Default<
|
|
69
|
-
[Eff] extends [YieldWrap<Effect.Effect<infer _A, infer E, infer _R>>] ? E
|
|
70
|
-
: never,
|
|
71
|
-
[Eff] extends [YieldWrap<Effect.Effect<infer _A, infer _E, infer R>>] ? R
|
|
72
|
-
: never
|
|
73
|
-
>
|
|
74
|
-
export function handle(
|
|
75
|
-
handler:
|
|
76
|
-
| Effect.Effect<
|
|
77
|
-
JSX.Children | HttpServerResponse.HttpServerResponse,
|
|
78
|
-
any,
|
|
79
|
-
any
|
|
80
|
-
>
|
|
81
|
-
| (() => Generator<
|
|
82
|
-
YieldWrap<Effect.Effect<any, any, any>>,
|
|
83
|
-
JSX.Children | HttpServerResponse.HttpServerResponse,
|
|
84
|
-
any
|
|
85
|
-
>),
|
|
86
|
-
): HttpApp.Default<any, any> {
|
|
87
|
-
return Effect.gen(function*() {
|
|
88
|
-
const hyper = yield* Effect.serviceOption(Hyper).pipe(
|
|
89
|
-
Effect.andThen(Option.getOrNull),
|
|
90
|
-
)
|
|
91
|
-
const effect = isGenerator(handler) ? Effect.gen(handler) : handler
|
|
92
|
-
const value = yield* effect
|
|
93
|
-
|
|
94
|
-
if (HttpServerResponse.isServerResponse(value)) {
|
|
95
|
-
return value
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const html = HyperHtml.renderToString(value, hyper?.hooks)
|
|
99
|
-
|
|
100
|
-
return yield* HttpServerResponse.html`${html}`
|
|
101
|
-
})
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
function isGenerator<A, E, R>(
|
|
105
|
-
handler: any,
|
|
106
|
-
): handler is () => Generator<YieldWrap<Effect.Effect<A, E, R>>, any, any> {
|
|
107
|
-
return typeof handler === "function"
|
|
108
|
-
&& handler.constructor?.name === "GeneratorFunction"
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
const NoChildren: ReadonlyArray<never> = Object.freeze([])
|
|
112
|
-
|
|
113
|
-
type Primitive = string | number | boolean | null | undefined
|
|
114
|
-
|
|
115
|
-
export type HyperType = string | HyperComponent
|
|
116
|
-
|
|
117
|
-
export type HyperProps = {
|
|
118
|
-
[key: string]:
|
|
119
|
-
| Primitive
|
|
120
|
-
| ReadonlyArray<Primitive>
|
|
121
|
-
| HyperNode
|
|
122
|
-
| HyperNode[]
|
|
123
|
-
| null
|
|
124
|
-
| undefined
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
export type HyperComponent = (
|
|
128
|
-
props: HyperProps,
|
|
129
|
-
) => HyperNode | Primitive
|
|
130
|
-
|
|
131
|
-
export interface HyperNode {
|
|
132
|
-
type: HyperType
|
|
133
|
-
props: HyperProps
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
export function h(
|
|
137
|
-
type: HyperType,
|
|
138
|
-
props: HyperProps,
|
|
139
|
-
): HyperNode {
|
|
140
|
-
return {
|
|
141
|
-
type,
|
|
142
|
-
props: {
|
|
143
|
-
...props,
|
|
144
|
-
children: props.children ?? NoChildren,
|
|
145
|
-
},
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
export function unsafeUse<Value>(tag: Context.Tag<any, Value>) {
|
|
150
|
-
const currentFiber = Option.getOrThrow(
|
|
151
|
-
Fiber.getCurrentFiber(),
|
|
152
|
-
)
|
|
153
|
-
const context = currentFiber.currentContext
|
|
154
|
-
|
|
155
|
-
return Context.unsafeGet(context, tag)
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
export interface Layout<in out Provides, in out Requires>
|
|
159
|
-
extends Layer.Layer<Provides, never, Requires>
|
|
160
|
-
{
|
|
161
|
-
readonly [TypeId]: typeof LayoutTypeId
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
export function layout<Provides, Requires>(
|
|
165
|
-
handler:
|
|
166
|
-
| Effect.Effect<
|
|
167
|
-
JSX.Children | HttpServerResponse.HttpServerResponse,
|
|
168
|
-
any,
|
|
169
|
-
any
|
|
170
|
-
>
|
|
171
|
-
| (() => Generator<
|
|
172
|
-
YieldWrap<Effect.Effect<any, any, any>>,
|
|
173
|
-
JSX.Children | HttpServerResponse.HttpServerResponse,
|
|
174
|
-
any
|
|
175
|
-
>),
|
|
176
|
-
):
|
|
177
|
-
& Layout<Provides, Requires>
|
|
178
|
-
& {
|
|
179
|
-
handler: any
|
|
180
|
-
}
|
|
181
|
-
{
|
|
182
|
-
return {
|
|
183
|
-
[TypeId]: LayoutTypeId,
|
|
184
|
-
[Layer.LayerTypeId]: {
|
|
185
|
-
_ROut: Function.identity,
|
|
186
|
-
_E: Function.identity,
|
|
187
|
-
_RIn: Function.identity,
|
|
188
|
-
},
|
|
189
|
-
handler,
|
|
190
|
-
pipe() {
|
|
191
|
-
return Pipeable.pipeArguments(this, arguments)
|
|
192
|
-
},
|
|
193
|
-
}
|
|
194
|
-
}
|