honojs-middleware/packages/qwik-city/src/index.ts

95 lines
2.5 KiB
TypeScript

/* eslint-disable @typescript-eslint/no-explicit-any */
import { _deserializeData, _serializeData, _verifySerializable } from '@builder.io/qwik'
import { setServerPlatform } from '@builder.io/qwik/server'
import type {
ServerRenderOptions,
ServerRequestEvent,
} from '@builder.io/qwik-city/middleware/request-handler'
import {
mergeHeadersCookies,
requestHandler,
} from '@builder.io/qwik-city/middleware/request-handler'
import type { MiddlewareHandler } from 'hono'
export const qwikMiddleware = (opts: ServerRenderOptions): MiddlewareHandler => {
;(globalThis as any).TextEncoderStream = TextEncoderStream
const qwikSerializer = {
_deserializeData,
_serializeData,
_verifySerializable,
}
if (opts.manifest) {
setServerPlatform(opts.manifest)
}
return async (c, next) => {
const url = new URL(c.req.url)
const serverRequestEv: ServerRequestEvent<Response> = {
mode: 'server',
locale: undefined,
url,
request: c.req.raw,
getWritableStream: (status, headers, cookies, resolve) => {
const { readable, writable } = new TransformStream()
const response = new Response(readable, {
status,
headers: mergeHeadersCookies(headers, cookies),
})
resolve(response)
return writable
},
getClientConn: () => ({}),
platform: {},
env: c.env,
}
const handledResponse = await requestHandler(serverRequestEv, opts, qwikSerializer)
if (handledResponse) {
handledResponse.completion.then((v) => {
if (v) {
console.error(v)
}
})
const response = await handledResponse.response
if (response) {
return response
}
}
await next()
}
}
const resolved = Promise.resolve()
class TextEncoderStream {
// minimal polyfill implementation of TextEncoderStream
_writer: any
readable: any
writable: any
constructor() {
this._writer = null
this.readable = {
pipeTo: (writableStream: any) => {
this._writer = writableStream.getWriter()
},
}
this.writable = {
getWriter: () => {
if (!this._writer) {
throw new Error('No writable stream')
}
const encoder = new TextEncoder()
return {
write: async (chunk: any) => {
if (chunk != null) {
await this._writer.write(encoder.encode(chunk))
}
},
close: () => this._writer.close(),
ready: resolved,
}
},
}
}
}