Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow listening on unix sockets #10

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions package/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import { OptionsSchema } from '~/validators';

import type { AstroAdapter, AstroIntegration } from 'astro';

import type { Options } from '~/types.ts';
import type { Options, InternalOptions } from '~/types.ts';

export function getAdapter(args: Options = {}): AstroAdapter {
export function getAdapter(args: InternalOptions): AstroAdapter {
return {
args,
exports: [
Expand Down Expand Up @@ -49,10 +49,10 @@ export default function integration(options?: Options): AstroIntegration {
getAdapter({
...parsedOptions.data,
assets: params.config.build.assets,
client: params.config.build.client?.toString(),
client: params.config.build.client.toString(),
host: params.config.server.host,
port: params.config.server.port,
server: params.config.build.server?.toString(),
server: params.config.build.server.toString(),
}),
);
},
Expand Down
16 changes: 9 additions & 7 deletions package/src/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,12 @@ import { extractHostname, serveStaticFile } from '~/server/utils';
import type { SSRManifest } from 'astro';
import type { Server } from 'bun';

import type { CreateExports, Options } from '~/types';
import type { CreateExports, InternalOptions } from '~/types';

export function createExports(manifest: SSRManifest, options: Options): CreateExports {
export function createExports(
manifest: SSRManifest,
options: InternalOptions,
): CreateExports {
return {
handle: handler(manifest, options),
running: (): boolean => _server !== null,
Expand All @@ -26,11 +29,12 @@ export function createExports(manifest: SSRManifest, options: Options): CreateEx
}

let _server: Server | null = null;
export function start(manifest: SSRManifest, options: Options): void {
export function start(manifest: SSRManifest, options: InternalOptions): void {
const { env } = process;

const hostname = env.HOST ?? extractHostname(options.host);
const port = env.PORT ? Number.parseInt(env.PORT) : options.port;
const unix = env.UNIX ?? options.unix;

if (cluster.isPrimary && options.cluster) {
const numCPUs = os.cpus().length;
Expand All @@ -47,14 +51,12 @@ export function start(manifest: SSRManifest, options: Options): void {
const logger = app.getAdapterLogger();

_server = Bun.serve({
development: import.meta.env.DEV,
error: (error): Response =>
new Response(`<pre>${error}\n${error.stack}</pre>`, {
headers: { 'Content-Type': 'text/html' },
}),
fetch: handler(manifest, options),
hostname,
port,
...(unix ? { unix } : { hostname, port }),
});

function exit(): void {
Expand All @@ -72,7 +74,7 @@ export function start(manifest: SSRManifest, options: Options): void {

function handler(
manifest: SSRManifest,
options: Options,
options: InternalOptions,
): (req: Request, server: Server) => Promise<Response> {
const clientRoot = options.client ?? new URL('../client/', import.meta.url).href;

Expand Down
85 changes: 70 additions & 15 deletions package/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,46 @@
import type { Server } from 'bun';
import type { z } from 'zod';
import type { AstroConfig } from 'astro';

import type { OptionsSchema } from '~/validators';

// the options available to the user when they are adding
// the adapter to their configuration
export interface Options {
/**
* Create a cluster of bun servers listening on the same port,
* and automatically load-balance incoming requests across them.
*
* Example:
* ```ts
* export default defineConfig({
* adapter: bun({ cluster: true })
* })
* ```
*
* Defaults to `false`
*/
cluster?: z.infer<typeof OptionsSchema>["cluster"];
/**
* The path to the unix socket on which to host the server.
*
* This can provide better performance when Bun is running alongside
* a local reverse proxy that supports unix sockets.
*
* When a unix socket is provided, Bun does not bind to a TCP port,
* and the options and environment variables for the hostname and port
* are ignored.
*
* Example:
* ```ts
* export default defineConfig({
* adapter: bun({ unix: "/tmp/my-socket.sock" })
* })
* ```
*/
unix?: z.infer<typeof OptionsSchema>["unix"];
}

export const CreateExports = {
HANDLE: 'handle',
RUNNING: 'running',
Expand All @@ -19,27 +57,44 @@ export type CreateExports = {

// export type Options = z.infer<typeof OptionsSchema>;

export interface Options {
/** TODO(@nurodev): Undocumented */
assets?: z.infer<typeof OptionsSchema>['assets'];
/** TODO(@nurodev): Undocumented */
client?: z.infer<typeof OptionsSchema>['client'];
// options provided by the user combined with other
// relevant configuration picked from the integration API
export interface InternalOptions extends Options {
/**
* Name of the publicly exposed directory where all
* static assets are put.
*
* Astro defaults to `"_astro"`.
*/
assets: AstroConfig['build']['assets'];
/**
* Enable clustering for the server. (Only linux!)
* The full file URL to where astro is configured to put
* the client bundle and assets such as images, fonts,
* stylesheets, and static html.
*
* @default false
* Astro defaults to `"<project root>/dist/client/"`.
*/
cluster?: z.infer<typeof OptionsSchema>['cluster'];
client: AstroConfig['build']['server']['href'];
/**
* The hostname to serve the application on.
* The full file URL to where astro is configured to put
* the server bundle.
*
* Astro defaults to `"<project root>/dist/server/""`.
*/
server: AstroConfig['build']['server']['href'];
/**
* Network address where the astro dev server is
* configured to listen for requests in addition to
* `localhost`.
*
* Astro defaults to `false`.
*/
host?: z.infer<typeof OptionsSchema>['host'];
host: AstroConfig['server']['host'];
/**
* The port to serve the application on.
* Network port where the astro dev server is
* configured to listen for requests.
*
* @default 4321
* Astro default to `4321`.
*/
port?: z.infer<typeof OptionsSchema>['port'];
/** TODO(@nurodev): Undocumented */
server?: z.infer<typeof OptionsSchema>['server'];
port: AstroConfig['server']['port'];
}
6 changes: 1 addition & 5 deletions package/src/validators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@ import { z } from 'zod';

export const OptionsSchema = z
.object({
assets: z.string(),
client: z.string(),
cluster: z.boolean().optional().default(false),
host: z.union([z.string(), z.boolean()]),
port: z.coerce.number().default(4321),
server: z.string(),
unix: z.string().optional(),
})
.partial();