2025-10-31 19:07:36 +00:00
|
|
|
import { Server } from "@/server/server"
|
2026-05-02 23:33:38 +00:00
|
|
|
import { InstanceRuntime } from "@/project/instance-runtime"
|
2026-04-27 18:33:33 +00:00
|
|
|
import { Rpc } from "@/util/rpc"
|
2025-11-07 00:48:10 +00:00
|
|
|
import { upgrade } from "@/cli/upgrade"
|
2026-04-27 18:33:33 +00:00
|
|
|
import { Config } from "@/config/config"
|
2026-01-09 21:33:46 +00:00
|
|
|
import { GlobalBus } from "@/bus/global"
|
2026-05-03 13:58:31 +00:00
|
|
|
import { ServerAuth } from "@/server/auth"
|
2026-03-24 22:20:11 +00:00
|
|
|
import { writeHeapSnapshot } from "node:v8"
|
2026-04-03 02:34:33 +00:00
|
|
|
import { Heap } from "@/cli/heap"
|
2026-05-02 23:33:38 +00:00
|
|
|
import { AppRuntime } from "@/effect/app-runtime"
|
|
|
|
|
import { Effect } from "effect"
|
|
|
|
|
import { disposeAllInstancesAndEmitGlobalDisposed } from "@/server/global-lifecycle"
|
2026-04-17 19:22:08 +00:00
|
|
|
|
2026-04-03 02:34:33 +00:00
|
|
|
Heap.start()
|
|
|
|
|
|
2026-01-09 21:33:46 +00:00
|
|
|
// Subscribe to global events and forward them via RPC
|
|
|
|
|
GlobalBus.on("event", (event) => {
|
|
|
|
|
Rpc.emit("global.event", event)
|
|
|
|
|
})
|
|
|
|
|
|
2026-03-19 23:32:59 +00:00
|
|
|
let server: Awaited<ReturnType<typeof Server.listen>> | undefined
|
2026-01-09 21:33:46 +00:00
|
|
|
|
2025-10-31 19:07:36 +00:00
|
|
|
export const rpc = {
|
2026-01-09 21:33:46 +00:00
|
|
|
async fetch(input: { url: string; method: string; headers: Record<string, string>; body?: string }) {
|
2026-01-13 22:50:19 +00:00
|
|
|
const headers = { ...input.headers }
|
2026-05-03 13:58:31 +00:00
|
|
|
const auth = ServerAuth.header()
|
2026-01-13 22:50:19 +00:00
|
|
|
if (auth && !headers["authorization"] && !headers["Authorization"]) {
|
|
|
|
|
headers["Authorization"] = auth
|
|
|
|
|
}
|
2026-01-09 21:33:46 +00:00
|
|
|
const request = new Request(input.url, {
|
|
|
|
|
method: input.method,
|
2026-01-13 22:50:19 +00:00
|
|
|
headers,
|
2026-01-09 21:33:46 +00:00
|
|
|
body: input.body,
|
|
|
|
|
})
|
2026-04-09 05:18:46 +00:00
|
|
|
const response = await Server.Default().app.fetch(request)
|
2026-01-09 21:33:46 +00:00
|
|
|
const body = await response.text()
|
|
|
|
|
return {
|
|
|
|
|
status: response.status,
|
|
|
|
|
headers: Object.fromEntries(response.headers.entries()),
|
|
|
|
|
body,
|
2025-10-31 19:07:36 +00:00
|
|
|
}
|
|
|
|
|
},
|
2026-03-24 22:20:11 +00:00
|
|
|
snapshot() {
|
|
|
|
|
const result = writeHeapSnapshot("server.heapsnapshot")
|
|
|
|
|
return result
|
|
|
|
|
},
|
2026-01-09 21:33:46 +00:00
|
|
|
async server(input: { port: number; hostname: string; mdns?: boolean; cors?: string[] }) {
|
|
|
|
|
if (server) await server.stop(true)
|
2026-03-19 23:32:59 +00:00
|
|
|
server = await Server.listen(input)
|
2026-01-09 21:33:46 +00:00
|
|
|
return { url: server.url.toString() }
|
|
|
|
|
},
|
2025-11-22 22:26:46 +00:00
|
|
|
async checkUpgrade(input: { directory: string }) {
|
2026-05-15 20:00:07 +00:00
|
|
|
await InstanceRuntime.load({ directory: input.directory })
|
|
|
|
|
await upgrade().catch(() => {})
|
2025-11-22 22:26:46 +00:00
|
|
|
},
|
2026-01-02 03:11:38 +00:00
|
|
|
async reload() {
|
2026-05-02 23:33:38 +00:00
|
|
|
await AppRuntime.runPromise(
|
|
|
|
|
Effect.gen(function* () {
|
|
|
|
|
const cfg = yield* Config.Service
|
|
|
|
|
yield* cfg.invalidate()
|
|
|
|
|
yield* disposeAllInstancesAndEmitGlobalDisposed({ swallowErrors: true })
|
|
|
|
|
}),
|
|
|
|
|
)
|
2026-01-02 03:11:38 +00:00
|
|
|
},
|
2025-10-31 19:07:36 +00:00
|
|
|
async shutdown() {
|
2026-05-02 23:33:38 +00:00
|
|
|
await InstanceRuntime.disposeAllInstances()
|
2026-03-19 23:32:59 +00:00
|
|
|
if (server) await server.stop(true)
|
2025-10-31 19:07:36 +00:00
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Rpc.listen(rpc)
|