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.
Files changed (87) hide show
  1. package/package.json +8 -9
  2. package/src/Commander.test.ts +507 -245
  3. package/src/ContentNegotiation.test.ts +603 -0
  4. package/src/ContentNegotiation.ts +542 -0
  5. package/src/Entity.test.ts +592 -0
  6. package/src/Entity.ts +362 -0
  7. package/src/FileRouter.ts +16 -12
  8. package/src/{FileRouterCodegen.test.ts → FileRouterCodegen.todo.ts} +384 -219
  9. package/src/FileRouterCodegen.ts +6 -6
  10. package/src/FileRouterPattern.test.ts +93 -62
  11. package/src/FileRouter_files.test.ts +5 -5
  12. package/src/FileRouter_path.test.ts +121 -69
  13. package/src/FileRouter_tree.test.ts +62 -56
  14. package/src/FileSystemExtra.test.ts +46 -30
  15. package/src/Http.test.ts +319 -0
  16. package/src/Http.ts +167 -0
  17. package/src/HttpAppExtra.test.ts +39 -20
  18. package/src/HttpAppExtra.ts +0 -1
  19. package/src/HttpUtils.test.ts +35 -18
  20. package/src/HttpUtils.ts +2 -0
  21. package/src/PathPattern.test.ts +648 -0
  22. package/src/PathPattern.ts +485 -0
  23. package/src/Route.ts +266 -1069
  24. package/src/RouteBody.test.ts +234 -0
  25. package/src/RouteBody.ts +193 -0
  26. package/src/RouteHook.test.ts +40 -0
  27. package/src/RouteHook.ts +106 -0
  28. package/src/RouteHttp.test.ts +2906 -0
  29. package/src/RouteHttp.ts +427 -0
  30. package/src/RouteHttpTracer.ts +92 -0
  31. package/src/RouteMount.test.ts +481 -0
  32. package/src/RouteMount.ts +470 -0
  33. package/src/RouteSchema.test.ts +427 -0
  34. package/src/RouteSchema.ts +423 -0
  35. package/src/RouteTree.test.ts +494 -0
  36. package/src/RouteTree.ts +219 -0
  37. package/src/RouteTrie.test.ts +322 -0
  38. package/src/RouteTrie.ts +224 -0
  39. package/src/RouterPattern.test.ts +569 -548
  40. package/src/RouterPattern.ts +7 -7
  41. package/src/Start.ts +3 -3
  42. package/src/StreamExtra.ts +21 -1
  43. package/src/TuplePathPattern.ts +64 -0
  44. package/src/Values.test.ts +263 -0
  45. package/src/Values.ts +76 -0
  46. package/src/bun/BunBundle.test.ts +36 -42
  47. package/src/bun/BunBundle.ts +2 -2
  48. package/src/bun/BunBundle_imports.test.ts +4 -6
  49. package/src/bun/BunHttpServer.test.ts +183 -6
  50. package/src/bun/BunHttpServer.ts +72 -32
  51. package/src/bun/BunHttpServer_web.ts +18 -6
  52. package/src/bun/BunImportTrackerPlugin.test.ts +3 -3
  53. package/src/bun/BunRoute.test.ts +124 -442
  54. package/src/bun/BunRoute.ts +146 -286
  55. package/src/{BundleHttp.test.ts → bundler/BundleHttp.test.ts} +34 -60
  56. package/src/{BundleHttp.ts → bundler/BundleHttp.ts} +1 -2
  57. package/src/client/index.ts +1 -1
  58. package/src/{Effect_HttpRouter.test.ts → effect/HttpRouter.test.ts} +69 -90
  59. package/src/experimental/EncryptedCookies.test.ts +125 -64
  60. package/src/experimental/SseHttpResponse.ts +0 -1
  61. package/src/hyper/Hyper.ts +89 -0
  62. package/src/{HyperHtml.test.ts → hyper/HyperHtml.test.ts} +13 -13
  63. package/src/{HyperHtml.ts → hyper/HyperHtml.ts} +2 -2
  64. package/src/{jsx.d.ts → hyper/jsx.d.ts} +1 -1
  65. package/src/index.ts +3 -4
  66. package/src/middlewares/BasicAuthMiddleware.test.ts +29 -19
  67. package/src/{NodeFileSystem.ts → node/FileSystem.ts} +6 -2
  68. package/src/testing/TestHttpClient.test.ts +26 -26
  69. package/src/testing/TestLogger.test.ts +27 -14
  70. package/src/testing/TestLogger.ts +15 -9
  71. package/src/x/datastar/Datastar.test.ts +47 -48
  72. package/src/x/datastar/Datastar.ts +1 -1
  73. package/src/x/tailwind/TailwindPlugin.test.ts +56 -58
  74. package/src/x/tailwind/plugin.ts +1 -1
  75. package/src/FileHttpRouter.test.ts +0 -239
  76. package/src/FileHttpRouter.ts +0 -194
  77. package/src/Hyper.ts +0 -194
  78. package/src/Route.test.ts +0 -1370
  79. package/src/RouteRender.ts +0 -40
  80. package/src/Router.test.ts +0 -375
  81. package/src/Router.ts +0 -255
  82. package/src/bun/BunRoute_bundles.test.ts +0 -219
  83. /package/src/{Bundle.ts → bundler/Bundle.ts} +0 -0
  84. /package/src/{BundleFiles.ts → bundler/BundleFiles.ts} +0 -0
  85. /package/src/{HyperNode.ts → hyper/HyperNode.ts} +0 -0
  86. /package/src/{jsx-runtime.ts → hyper/jsx-runtime.ts} +0 -0
  87. /package/src/{NodeUtils.ts → node/Utils.ts} +0 -0
@@ -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
- }