astro/packages/integrations/node/src/server.ts
Matthew Phillips 5e52814d97
Adapters v0 (#2855)
* Adapter v0

* Finalizing adapters

* Update the lockfile

* Add the default adapter after config setup is called

* Create the default adapter in config:done

* Fix lint error

* Remove unused callConfigSetup

* remove unused export

* Use a test adapter to test SSR

* Adds a changeset

* Updated based on feedback

* Updated the lockfile

* Only throw if set to a different adapter

* Clean up outdated comments

* Move the adapter to an  config option

* Make adapter optional

* Update the docs/changeset to reflect config API change

* Clarify regular Node usage
2022-03-24 07:26:25 -04:00

48 lines
1.1 KiB
TypeScript

import type { SSRManifest } from 'astro';
import type { IncomingMessage, ServerResponse } from 'http';
import { NodeApp } from 'astro/app/node';
import { polyfill } from '@astrojs/webapi';
polyfill(globalThis, {
exclude: 'window document'
});
export function createExports(manifest: SSRManifest) {
const app = new NodeApp(manifest, new URL(import.meta.url));
return {
async handler(req: IncomingMessage, res: ServerResponse, next?: (err?: unknown) => void) {
const route = app.match(req);
if(route) {
try {
const response = await app.render(req);
await writeWebResponse(res, response);
} catch(err: unknown) {
if(next) {
next(err);
} else {
throw err;
}
}
} else if(next) {
return next();
}
}
}
}
async function writeWebResponse(res: ServerResponse, webResponse: Response) {
const { status, headers, body } = webResponse;
res.writeHead(status, Object.fromEntries(headers.entries()));
if (body) {
const reader = body.getReader();
while (true) {
const { done, value } = await reader.read();
if (done) break;
if (value) {
res.write(value);
}
}
}
res.end();
}