Skip to content

Commit

Permalink
h3 and nuxt documentation (#499)
Browse files Browse the repository at this point in the history
  • Loading branch information
benjie authored Sep 16, 2023
2 parents 5c4be3c + b1aafbf commit 542bdff
Show file tree
Hide file tree
Showing 2 changed files with 196 additions and 0 deletions.
56 changes: 56 additions & 0 deletions grafast/website/grafserv/servers/h3.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# h3 V1

```ts
import { createServer } from "node:http";
import { createApp, eventHandler, toNodeListener } from "h3";
import { grafserv } from "grafserv/h3/v1";
import preset from "./graphile.config";
import schema from "./schema.mjs";

// create a h3 app
const app = createApp();
// (Add any h3 eventHandlers you want here.)

// Create a Node HTTP server, mounting h3 into it
const server = createServer(toNodeListener(app));
server.on("error", (e) => {
console.error(e);
});

// Create a Grafserv instance
const serv = grafserv({ schema, preset });

// Add the Grafserv instance's route handlers to the h3 app
serv.addTo(app).catch((e) => {
console.error(e);
process.exit(1);
});

// Start the server
server.listen(preset.grafserv?.port ?? 5678);
```

# Experimental

## Websocket support

h3 does not yet support WebSocket.

An unofficial and experimental workaround consists to replace

```ts
serv.addTo(app).catch((e) => {
console.error(e);
process.exit(1);
});
```

with

```ts
// this method register directly `server.on('upgrade', ...)` for handling websockets by postgraphile
serv.addTo_experimental(app, server).catch((e) => {
console.error(e);
process.exit(1);
});
```
140 changes: 140 additions & 0 deletions grafast/website/grafserv/servers/nuxt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
# Nuxt API route

Grafserv handles a number of API routes, so you should define one for each of
the things you care about. It's critical that you ensure that the paths line up
with those used in the Graphile config, otherwise the assets will not correctly
be served/referenced, this may cause issues when communicating between Ruru
and GraphQL.

Creating `grafserv`:

```ts title="server/grafserv/serv.ts"
import { grafserv } from "grafserv/h3/v1";
import preset from "./graphile.config";
import schema from "./schema.mjs";

// Create a shared Grafserv instance
export const serv = grafserv({ schema, preset });
```

and the API routes :

```ts title="server/api/graphql.ts"
import { serv } from "@/server/grafserv/serv";

// Create and export the `/api/graphql` route handler
export default eventHandler((event) => serv.handleGraphQLEvent(event));
```

```ts title="pages/routes/ruru.ts"
import { serv } from "@/server/grafserv/serv";

// Create and export the `/ruru` route handler
export default eventHandler((event) => serv.handleGraphiqlEvent(event));
```

```ts title="pages/api/graphql/stream.ts"
import { serv } from "@/server/grafserv/serv";

// Create and export the `/api/graphql/stream` route handler
export default eventHandler((event) => serv.handleEventStreamEvent(event));
```

# Experimental

## Websocket support

Nitro and h3 does not yet support WebSocket.

An unofficial and experimental workaround consists to create a nuxt module:

```ts title="modules/grafserv/index.ts"
// nuxt auto-register modules located in `modules/*.ts` or `modules/*/index.ts`

import { defineNuxtModule, addServerPlugin } from "@nuxt/kit";

import httpProxy from "http-proxy";

export default defineNuxtModule({
async setup(options, nuxt) {
/**
* Register websockets in DEVELOPMENT mode.
*/
if (nuxt.options.dev) {
// hook called in development only
nuxt.hook("listen", (devServer) => {
// create a proxy for routing ws to runtime server created in dev plugin
const proxy = httpProxy.createProxy({
target: {
host: "localhost",
port: 3100,
},
});
// registering ws on devServer
devServer.on("upgrade", (req, socket, head) => {
// routing ws by path
switch (req.url) {
case "/api/graphql":
// proxy websocket to runtime server created in dev plugin
proxy.ws(req, socket, head);
break;
default:
socket.destroy();
}
});
});
// Registering runtime plugin for dev
addServerPlugin("@/modules/grafserv/ws-dev");
}

/**
* Register websockets in PRODUCTION mode.
*/
if (!nuxt.options.dev)
// Registering runtime plugin for production
addServerPlugin("@/modules/grafserv/ws");
},
});
```

and two Nitro plugins (one for dev, and one for prod)

```ts title="modules/grafserv/ws-dev.ts"
import { Server } from "http";
import { serv } from "@/server/grafserv/serv";

// plugin running in DEVELOPMENT (runtime)
export default defineNitroPlugin(async (nitroApp) => {
// Create a server for handling websockets
const server = new Server().listen({ port: 3100 }, () =>
console.log("Runtime server listening on port 3100"),
);
// Cleanly close server (on leave or HMR before plugin reload)
nitroApp.hooks.hookOnce("close", () => {
server.closeAllConnections();
server.close((err) =>
err
? console.warn("Runtime server wrongly closed", err)
: console.log("Runtime server stopped"),
);
});
// Attaching ws to server
serv.attachWebsocketsToServer_experimental(server);
});
```

```ts title="modules/grafserv/ws.ts"
import { serv } from "@/server/grafserv/serv";

// plugin running in PRODUCTION (runtime)
export default defineNitroPlugin(async (nitroApp) => {
// this hook will be called only once at first http request
nitroApp.hooks.hookOnce("request", (event: H3Event) => {
const server = event.node.req.socket.server;
if (server) {
// Attaching ws to server
serv.attachWebsocketsToServer_experimental(server);
}
});
});
```

0 comments on commit 542bdff

Please sign in to comment.