Skip to content

Commit

Permalink
Request-listener (#16)
Browse files Browse the repository at this point in the history
* clean up middleware

* request listener

* typo
  • Loading branch information
rossrobino authored Sep 7, 2024
1 parent cf59b87 commit 07901b2
Show file tree
Hide file tree
Showing 13 changed files with 378 additions and 97 deletions.
9 changes: 9 additions & 0 deletions .changeset/small-trees-sparkle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"domco": minor
"create-domco": patch
---

Adds request listener in place of `@hono/node-server`.

- This change removes the last remaining dependency for the project other than `vite` and `hono`.
- Removes `serveStatic` option for `createApp`, use `middleware` instead, see [example](https://domco.robino.dev/deploy#example).
10 changes: 5 additions & 5 deletions apps/docs/src/content/deploy.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,28 +15,28 @@ Run `vite build` to build your application into `dist/`.

By default **domco** will generate a `app.js` module and static assets for your application. If you are not using an [adapter](#adapters), you can import `createApp` from the `app.js` module and configure your app to use in one of [Hono's supported environments](https://hono.dev/docs/getting-started/basic).

The `client/` directory holds client assets. JS and CSS assets with hashed file names will automatically be served with immutable cache headers from `dist/client/_immutable/`. Other assets are processed and included in `dist/client/` directly.
The `client/` directory holds client assets. JS and CSS assets with hashed file names will be output to `dist/client/_immutable/`, you can serve this path with immutable cache headers. Other assets are processed and included in `dist/client/` directly.

## Example

Here's an example of how to serve your app using the result of your build with `@hono/node-server`.
Here's an example of how to serve your app using the result of your build with [`@hono/node-server`](https://github.com/honojs/node-server).

```ts
// main.js
// server.js
// import from build output
import { createApp } from "./dist/server/app.js";
import { serve } from "@hono/node-server";
import { serveStatic } from "@hono/node-server/serve-static";

const app = createApp({ serveStatic });
const app = createApp({ middleware: [serveStatic({ root: "./dist/client" })] });

serve(app);
```

Run this module to start your server.

```bash
node main.js
node server.js
```

## Adapters
Expand Down
20 changes: 3 additions & 17 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/create-domco/src/template/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const versions = {
domco: "0.9.1",
domco: "0.10.0",
hono: "4.5.11",
autoprefixer: "10.4.20",
prettier: "3.3.3",
Expand Down
7 changes: 4 additions & 3 deletions packages/domco/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@
"types": "./dist/injector/index.d.ts",
"default": "./dist/injector/index.js"
},
"./node/request-listener": {
"types": "./dist/node/request-listener/index.d.ts",
"default": "./dist/node/request-listener/index.js"
},
"./version": {
"types": "./dist/version/index.d.ts",
"default": "./dist/version/index.js"
Expand Down Expand Up @@ -76,8 +80,5 @@
"peerDependencies": {
"hono": "^4.5.0",
"vite": "^5.4.0"
},
"dependencies": {
"@hono/node-server": "^1.12.2"
}
}
21 changes: 11 additions & 10 deletions packages/domco/src/adapter/vercel/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type {
OutputConfig,
RequiredOptions,
VercelAdapterOptions,
} from "./types/index.js";
} from "./types.js";
import { createMiddleware } from "hono/factory";
import type { HonoOptions } from "hono/hono-base";
import fs from "node:fs/promises";
Expand Down Expand Up @@ -37,12 +37,12 @@ const nodeEntry: AdapterEntry = ({ appId }) => {
id: entryId,
code: `
import { createApp } from "${appId}";
import { handle } from "@hono/node-server/vercel";
import { createRequestListener } from "domco/node/request-listener";
import { getPath } from "domco/adapter/vercel";
const app = createApp({ honoOptions: { getPath } });
export default handle(app);
export default createRequestListener(app.fetch);
`,
};
};
Expand Down Expand Up @@ -118,24 +118,25 @@ export const adapter: AdapterBuilder<VercelAdapterOptions | undefined> = (
resolvedOptions.isr = options?.isr;
resolvedOptions.images = options?.images;

/**
* This is applied in `dev` and `preview` so users can see the src images.
*/
const imageMiddleware = createMiddleware(async (c, next) => {
if (resolvedOptions.images) {
if (c.req.path.startsWith("/_vercel/image")) {
const { url, w, q } = c.req.query();

if (!url) throw Error(`Add a \`url\` query param to ${c.req.url}`);
if (!w) throw Error(`Add a \`w\` query param to ${c.req.url}`);
if (!q) throw Error(`Add a \`q\` query param to ${c.req.url}`);
if (!url) throw new Error(`Add a \`url\` query param to ${c.req.url}`);
if (!w) throw new Error(`Add a \`w\` query param to ${c.req.url}`);
if (!q) throw new Error(`Add a \`q\` query param to ${c.req.url}`);

if (!resolvedOptions.images.sizes.includes(parseInt(w))) {
throw Error(
throw new Error(
`\`${w}\` is not an included image size. Add \`${w}\` to \`sizes\` in your adapter config to support this width.`,
);
}

if (url) {
return c.redirect(url);
}
return c.redirect(url);
}
}
await next();
Expand Down
File renamed without changes.
14 changes: 8 additions & 6 deletions packages/domco/src/app/dev/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ import type { ViteDevServer } from "vite";
* @param options
* @returns Hono app instance.
*/
export const createAppDev = <Env extends {} = any>(options?: {
devServer?: ViteDevServer;
honoOptions?: HonoOptions<Env>;
middleware?: MiddlewareHandler[];
}) => {
const { devServer, honoOptions, middleware } = options ?? {};
export const createAppDev = <Env extends {} = any>(
options: {
devServer?: ViteDevServer;
honoOptions?: HonoOptions<Env>;
middleware?: MiddlewareHandler[];
} = {},
) => {
const { devServer, honoOptions, middleware } = options;

const rootApp = new Hono<Env>(honoOptions);

Expand Down
46 changes: 13 additions & 33 deletions packages/domco/src/app/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { dirNames, headers } from "../constants/index.js";
import { addRoutes, applySetup, setServer } from "./util/index.js";
import { manifest } from "domco:manifest";
import { routes } from "domco:routes";
import { Hono, type MiddlewareHandler } from "hono";
import type { HonoOptions } from "hono/hono-base";
import type { ServeStaticOptions } from "hono/serve-static";

/**
* Creates your production Hono app instance. You can import `createApp` from
Expand All @@ -22,50 +20,32 @@ import type { ServeStaticOptions } from "hono/serve-static";
* @example
*
* ```js
* // example of the NodeJS build that is output to `./dist/server/node.js`
* // example using Node.js and `@hono/node-server`
* import { serve } from "@hono/node-server";
* import { serveStatic } from "@hono/node-server/serve-static";
* import { createApp } from "./dist/server/app.js";
*
* const app = createApp({ serveStatic });
* const app = createApp({ middleware: [serveStatic({ root: "./dist/client" })] });
*
* serve(app);
* ```
*/
export const createApp = <Env extends {} = any>(options?: {
honoOptions?: HonoOptions<Env>;
middleware?: MiddlewareHandler[];
serveStatic?: (options?: ServeStaticOptions) => MiddlewareHandler;
}) => {
const { honoOptions, serveStatic, middleware } = options ?? {};

const app = new Hono<Env>(honoOptions);
export const createApp = <Env extends {} = any>(
options: {
honoOptions?: HonoOptions<Env>;
middleware?: MiddlewareHandler[];
} = {},
) => {
const app = new Hono<Env>(options.honoOptions);

app.use(setServer);

if (middleware) {
for (const mw of middleware) {
app.use(mw);
}
}

applySetup(app, routes);

// handlers need to be added after static so handleStatic will run first
if (serveStatic) {
app.use(`/${dirNames.out.client.immutable}/*`, async (c, next) => {
await next();
c.header("cache-control", headers.cacheControl.immutable);
});

app.use(async (c, next) => {
if (c.req.method === "GET") {
return serveStatic({
root: `./${dirNames.out.base}/${dirNames.out.client.base}`,
})(c, next);
}
await next();
});
if (options.middleware) {
for (const mw of options.middleware) {
app.use(mw);
}
}

addRoutes({ app, routes, manifest });
Expand Down
Loading

0 comments on commit 07901b2

Please sign in to comment.