effect-start 0.23.0 → 0.23.1
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 +1 -1
- package/src/Start.ts +18 -13
- package/src/StartApp.ts +11 -0
- package/src/bun/BunServer.ts +47 -6
- package/src/x/tailscale/TailscaleTunnel.ts +7 -5
package/package.json
CHANGED
package/src/Start.ts
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import type * as FileSystem from "./FileSystem.ts"
|
|
2
2
|
import * as Context from "effect/Context"
|
|
3
|
+
import * as Deferred from "effect/Deferred"
|
|
3
4
|
import * as Effect from "effect/Effect"
|
|
4
5
|
import * as Function from "effect/Function"
|
|
5
6
|
import * as Layer from "effect/Layer"
|
|
6
|
-
import * as Option from "effect/Option"
|
|
7
7
|
import type * as ChildProcess from "./ChildProcess.ts"
|
|
8
8
|
import * as BunRuntime from "./bun/BunRuntime.ts"
|
|
9
9
|
import * as BunServer from "./bun/BunServer.ts"
|
|
10
10
|
import * as NodeFileSystem from "./node/NodeFileSystem.ts"
|
|
11
11
|
import * as BunChildProcessSpawner from "./bun/BunChildProcessSpawner.ts"
|
|
12
|
+
import * as StartApp from "./StartApp.ts"
|
|
12
13
|
|
|
13
14
|
export function layer<
|
|
14
15
|
Layers extends [Layer.Layer<never, any, any>, ...Array<Layer.Layer<never, any, any>>],
|
|
@@ -66,12 +67,25 @@ export function pack<const Layers extends readonly [Layer.Layer.Any, ...Array<La
|
|
|
66
67
|
export function serve<
|
|
67
68
|
ROut,
|
|
68
69
|
E,
|
|
69
|
-
RIn extends
|
|
70
|
+
RIn extends
|
|
71
|
+
| BunServer.BunServer
|
|
72
|
+
| FileSystem.FileSystem
|
|
73
|
+
| ChildProcess.ChildProcessSpawner
|
|
74
|
+
| StartApp.StartApp,
|
|
70
75
|
>(
|
|
71
76
|
load: () => Promise<{
|
|
72
77
|
default: Layer.Layer<ROut, E, RIn>
|
|
73
78
|
}>,
|
|
74
79
|
) {
|
|
80
|
+
const startAppLayer = Layer.effect(
|
|
81
|
+
StartApp.StartApp,
|
|
82
|
+
Deferred.make<BunServer.BunServer>().pipe(
|
|
83
|
+
Effect.map((server) => ({
|
|
84
|
+
server,
|
|
85
|
+
})),
|
|
86
|
+
),
|
|
87
|
+
)
|
|
88
|
+
|
|
75
89
|
const appLayer = Function.pipe(
|
|
76
90
|
Effect.tryPromise(load),
|
|
77
91
|
Effect.map((v) => v.default),
|
|
@@ -79,24 +93,15 @@ export function serve<
|
|
|
79
93
|
Layer.unwrapEffect,
|
|
80
94
|
)
|
|
81
95
|
|
|
82
|
-
const serverLayer = Layer.scoped(
|
|
83
|
-
BunServer.BunServer,
|
|
84
|
-
Effect.gen(function* () {
|
|
85
|
-
const existing = yield* Effect.serviceOption(BunServer.BunServer)
|
|
86
|
-
if (Option.isSome(existing)) return existing.value
|
|
87
|
-
return yield* BunServer.make({})
|
|
88
|
-
}),
|
|
89
|
-
)
|
|
90
|
-
|
|
91
96
|
const appLayerResolved = Function.pipe(
|
|
92
97
|
appLayer,
|
|
93
|
-
Layer.provide(serverLayer),
|
|
94
98
|
Layer.provide(NodeFileSystem.layer),
|
|
95
99
|
Layer.provide(BunChildProcessSpawner.layer),
|
|
100
|
+
Layer.provideMerge(startAppLayer),
|
|
96
101
|
)
|
|
97
102
|
|
|
98
103
|
const composed = Function.pipe(
|
|
99
|
-
|
|
104
|
+
BunServer.layerStart(),
|
|
100
105
|
BunServer.withLogAddress,
|
|
101
106
|
Layer.provide(appLayerResolved),
|
|
102
107
|
) as Layer.Layer<BunServer.BunServer, never, never>
|
package/src/StartApp.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as Context from "effect/Context"
|
|
2
|
+
import * as Deferred from "effect/Deferred"
|
|
3
|
+
import type * as BunServer from "./bun/BunServer.ts"
|
|
4
|
+
|
|
5
|
+
export namespace StartApp {
|
|
6
|
+
export interface Service {
|
|
7
|
+
readonly server: Deferred.Deferred<BunServer.BunServer>
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export class StartApp extends Context.Tag("effect-start/StartApp")<StartApp, StartApp.Service>() {}
|
package/src/bun/BunServer.ts
CHANGED
|
@@ -15,6 +15,7 @@ import * as PathPattern from "../PathPattern.ts"
|
|
|
15
15
|
import * as PlataformRuntime from "../PlatformRuntime.ts"
|
|
16
16
|
import * as Route from "../Route.ts"
|
|
17
17
|
import * as RouteHttp from "../RouteHttp.ts"
|
|
18
|
+
import * as StartApp from "../StartApp.ts"
|
|
18
19
|
import type * as RouteMount from "../RouteMount.ts"
|
|
19
20
|
import * as RouteTree from "../RouteTree.ts"
|
|
20
21
|
import * as BunRoute from "./BunRoute.ts"
|
|
@@ -52,12 +53,11 @@ export type BunServer = {
|
|
|
52
53
|
|
|
53
54
|
export const BunServer = Context.GenericTag<BunServer>("effect-start/BunServer")
|
|
54
55
|
|
|
55
|
-
export const make = (
|
|
56
|
+
export const make = (
|
|
57
|
+
options: BunServeOptions,
|
|
58
|
+
tree?: RouteTree.RouteTree,
|
|
59
|
+
): Effect.Effect<BunServer, never, Scope.Scope> =>
|
|
56
60
|
Effect.gen(function* () {
|
|
57
|
-
const routes = yield* Effect.serviceOption(Route.Routes).pipe(
|
|
58
|
-
Effect.andThen(Option.getOrUndefined),
|
|
59
|
-
)
|
|
60
|
-
|
|
61
61
|
const port = yield* Config.number("PORT").pipe(
|
|
62
62
|
Effect.catchTag("ConfigError", () => {
|
|
63
63
|
return PlataformRuntime.isAgentHarness()
|
|
@@ -98,7 +98,7 @@ export const make = (options: BunServeOptions): Effect.Effect<BunServer, never,
|
|
|
98
98
|
Effect.andThen(Runtime.provideService(BunServer, service)),
|
|
99
99
|
)
|
|
100
100
|
|
|
101
|
-
let currentRoutes: BunRoute.BunRoutes =
|
|
101
|
+
let currentRoutes: BunRoute.BunRoutes = tree ? yield* walkBunRoutes(runtime, tree) : {}
|
|
102
102
|
|
|
103
103
|
const websocket: Bun.WebSocketHandler<WebSocketContext> = {
|
|
104
104
|
open(ws) {
|
|
@@ -170,6 +170,47 @@ export const make = (options: BunServeOptions): Effect.Effect<BunServer, never,
|
|
|
170
170
|
export const layer = (options?: BunServeOptions): Layer.Layer<BunServer> =>
|
|
171
171
|
Layer.scoped(BunServer, make(options ?? {}))
|
|
172
172
|
|
|
173
|
+
export const layerRoutes = (
|
|
174
|
+
options?: BunServeOptions,
|
|
175
|
+
): Layer.Layer<BunServer, never, Route.Routes> =>
|
|
176
|
+
Layer.scoped(
|
|
177
|
+
BunServer,
|
|
178
|
+
Effect.gen(function* () {
|
|
179
|
+
const routes = yield* Route.Routes
|
|
180
|
+
return yield* make(options ?? {}, routes)
|
|
181
|
+
}),
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Resolves the Bun server in one place for Start.serve so routes are available:
|
|
186
|
+
* 1) Reuse a user-provided BunServer when one already exists in context.
|
|
187
|
+
* 2) Otherwise create the server from Route.Routes when routes are available.
|
|
188
|
+
* 3) Otherwise create a fallback server with the default 404 handler.
|
|
189
|
+
*/
|
|
190
|
+
export const layerStart = (
|
|
191
|
+
options?: BunServeOptions,
|
|
192
|
+
): Layer.Layer<BunServer, never, StartApp.StartApp> =>
|
|
193
|
+
Layer.scoped(
|
|
194
|
+
BunServer,
|
|
195
|
+
Effect.gen(function* () {
|
|
196
|
+
const app = yield* StartApp.StartApp
|
|
197
|
+
const existing = yield* Effect.serviceOption(BunServer)
|
|
198
|
+
if (Option.isSome(existing)) {
|
|
199
|
+
yield* Deferred.succeed(app.server, existing.value)
|
|
200
|
+
return existing.value
|
|
201
|
+
}
|
|
202
|
+
const routes = yield* Effect.serviceOption(Route.Routes)
|
|
203
|
+
if (Option.isSome(routes)) {
|
|
204
|
+
const server = yield* make(options ?? {}, routes.value)
|
|
205
|
+
yield* Deferred.succeed(app.server, server)
|
|
206
|
+
return server
|
|
207
|
+
}
|
|
208
|
+
const server = yield* make(options ?? {})
|
|
209
|
+
yield* Deferred.succeed(app.server, server)
|
|
210
|
+
return server
|
|
211
|
+
}),
|
|
212
|
+
)
|
|
213
|
+
|
|
173
214
|
export const withLogAddress = <A, E, R>(layer: Layer.Layer<A, E, R>) =>
|
|
174
215
|
Layer.effectDiscard(
|
|
175
216
|
BunServer.pipe(
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import * as BunServer from "../../bun/BunServer.ts"
|
|
2
1
|
import * as PlatformError from "../../PlatformError.ts"
|
|
2
|
+
import * as StartApp from "../../StartApp.ts"
|
|
3
3
|
import * as System from "../../System.ts"
|
|
4
|
+
import * as Deferred from "effect/Deferred"
|
|
4
5
|
import * as Effect from "effect/Effect"
|
|
5
6
|
import * as Layer from "effect/Layer"
|
|
6
7
|
import * as LogLevel from "effect/LogLevel"
|
|
@@ -86,12 +87,13 @@ export const start = (opts: {
|
|
|
86
87
|
export const layer = (opts?: { public?: boolean }) =>
|
|
87
88
|
Layer.scopedDiscard(
|
|
88
89
|
Effect.gen(function* () {
|
|
89
|
-
const { server } = yield* BunServer.BunServer
|
|
90
|
-
const port = server.port!
|
|
91
|
-
const command = "tailscale"
|
|
92
|
-
|
|
93
90
|
yield* Effect.forkScoped(
|
|
94
91
|
Effect.gen(function* () {
|
|
92
|
+
const app = yield* StartApp.StartApp
|
|
93
|
+
const { server } = yield* Deferred.await(app.server)
|
|
94
|
+
const port = server.port!
|
|
95
|
+
const command = "tailscale"
|
|
96
|
+
|
|
95
97
|
yield* System.which(command)
|
|
96
98
|
const status = yield* getStatus(command)
|
|
97
99
|
const dnsName = status.Self?.DNSName?.replace(/\.$/, "")
|