disable server unless explicitly opted in (#7529)

This commit is contained in:
Dax
2026-01-09 16:33:46 -05:00
committed by GitHub
parent 75df5040ea
commit 982b71e861
6 changed files with 194 additions and 49 deletions
@@ -3,21 +3,66 @@ import { createSimpleContext } from "./helper"
import { createGlobalEmitter } from "@solid-primitives/event-bus"
import { batch, onCleanup, onMount } from "solid-js"
export type EventSource = {
on: (handler: (event: Event) => void) => () => void
}
export const { use: useSDK, provider: SDKProvider } = createSimpleContext({
name: "SDK",
init: (props: { url: string; directory?: string }) => {
init: (props: { url: string; directory?: string; fetch?: typeof fetch; events?: EventSource }) => {
const abort = new AbortController()
const sdk = createOpencodeClient({
baseUrl: props.url,
signal: abort.signal,
directory: props.directory,
fetch: props.fetch,
})
const emitter = createGlobalEmitter<{
[key in Event["type"]]: Extract<Event, { type: key }>
}>()
let queue: Event[] = []
let timer: Timer | undefined
let last = 0
const flush = () => {
if (queue.length === 0) return
const events = queue
queue = []
timer = undefined
last = Date.now()
// Batch all event emissions so all store updates result in a single render
batch(() => {
for (const event of events) {
emitter.emit(event.type, event)
}
})
}
const handleEvent = (event: Event) => {
queue.push(event)
const elapsed = Date.now() - last
if (timer) return
// If we just flushed recently (within 16ms), batch this with future events
// Otherwise, process immediately to avoid latency
if (elapsed < 16) {
timer = setTimeout(flush, 16)
return
}
flush()
}
onMount(async () => {
// If an event source is provided, use it instead of SSE
if (props.events) {
const unsub = props.events.on(handleEvent)
onCleanup(unsub)
return
}
// Fall back to SSE
while (true) {
if (abort.signal.aborted) break
const events = await sdk.event.subscribe(
@@ -26,36 +71,9 @@ export const { use: useSDK, provider: SDKProvider } = createSimpleContext({
signal: abort.signal,
},
)
let queue: Event[] = []
let timer: Timer | undefined
let last = 0
const flush = () => {
if (queue.length === 0) return
const events = queue
queue = []
timer = undefined
last = Date.now()
// Batch all event emissions so all store updates result in a single render
batch(() => {
for (const event of events) {
emitter.emit(event.type, event)
}
})
}
for await (const event of events.stream) {
queue.push(event)
const elapsed = Date.now() - last
if (timer) continue
// If we just flushed recently (within 16ms), batch this with future events
// Otherwise, process immediately to avoid latency
if (elapsed < 16) {
timer = setTimeout(flush, 16)
continue
}
flush()
handleEvent(event)
}
// Flush any remaining events
@@ -68,6 +86,7 @@ export const { use: useSDK, provider: SDKProvider } = createSimpleContext({
onCleanup(() => {
abort.abort()
if (timer) clearTimeout(timer)
})
return { client: sdk, event: emitter, url: props.url }