///| Cloudflare Workers adapter helpers for Sol.
///|
/// Mars app type used by Sol.
pub type App = @mars.Server
///|
/// Cloudflare Workers environment object.
pub type Env = @mars.JsEnv
///|
/// Cloudflare Workers execution context.
pub type ExecutionContext = @mars.JsExecCtx
///|
priv struct WorkerFetchHandler(
(@mars.JsRequest, @mars.JsEnv, @mars.JsExecCtx) -> @js.Promise[
@mars.JsResponse,
]
)
///|
extern "js" fn ffi_convert_worker_fetch_handler(
handler : @js.Any,
) -> WorkerFetchHandler =
#| (handler) => handler
///|
extern "js" fn ffi_set_cloudflare_runtime() -> Unit =
#| () => {
#| globalThis.__SOL_RUNTIME__ = "cloudflare";
#| globalThis.__SOL_ADAPTER_MODE__ = true;
#| }
///|
extern "js" fn ffi_ensure_mars_reschedule_symbol() -> Unit =
#| () => {
#| if (typeof globalThis.moonbitlang$async$internal$event_loop$$reschedule !== "function") {
#| globalThis.moonbitlang$async$internal$event_loop$$reschedule = () => {};
#| }
#| }
///|
extern "js" fn ffi_export_cloudflare_app(
fetch_handler : WorkerFetchHandler,
) -> Unit =
#| (fetchHandler) => {
#| globalThis.__SOL_APP__ = {
#| fetch(request, env, ctx) {
#| return fetchHandler(request, env, ctx);
#| }
#| };
#| }
///|
fn to_worker_fetch_handler(app : App) -> WorkerFetchHandler {
ffi_convert_worker_fetch_handler(
@js.any(fn(
request : @mars.JsRequest,
env : @mars.JsEnv,
ctx : @mars.JsExecCtx,
) {
let fetch_handler = app.to_fetch_handler_with_env(env, ctx)
fetch_handler(request)
}),
)
}
///|
/// Export a Sol app as a Cloudflare Worker `fetch(request, env, ctx)` app.
pub fn export_app(app : App) -> Unit {
ffi_set_cloudflare_runtime()
ffi_ensure_mars_reschedule_symbol()
ffi_export_cloudflare_app(to_worker_fetch_handler(app))
}
///|
/// Run a configured Sol app in Cloudflare adapter mode.
pub fn run(configure : (App) -> Unit) -> Unit {
let app = @mars.Server::new()
configure(app)
export_app(app)
}
///|
/// Run a Sol app factory in Cloudflare adapter mode.
pub fn run_app(create_and_configure : () -> App) -> Unit {
let app = create_and_configure()
export_app(app)
}