@composedb/server
Version:
Server-side ComposeDB query execution.
75 lines (74 loc) • 2.19 kB
JavaScript
/**
* ComposeDB server for hybrid execution on the {@linkcode client ComposeDB client}.
*
* ## Installation
*
* ```sh
* npm install @composedb/server
* ```
*
* @module server
*/ import { createServer } from 'node:http';
import { CeramicClient } from '@ceramicnetwork/http-client';
import { VIEWER_ID_HEADER } from '@composedb/constants';
import { createContext, getSchema } from '@composedb/runtime';
import getPort from 'get-port';
import { createYoga } from 'graphql-yoga';
/**
* Returns the viewer ID sent by the client, if set.
*/ export function getViewerID(request) {
return request.headers.get(VIEWER_ID_HEADER);
}
/**
* Create a {@link https://the-guild.dev/graphql/yoga-server/docs Yoga server} handling GraphQL requests.
*/ export function createHandler(params) {
const { cache, ceramic, definition, options, schema } = params;
const client = typeof ceramic === 'string' ? new CeramicClient(ceramic) : ceramic;
return createYoga({
context: (ctx)=>{
const fallbackViewerID = getViewerID(ctx.request);
return createContext({
cache,
ceramic: client,
fallbackViewerID
});
},
graphiql: false,
...options,
schema: getSchema({
definition,
readonly: true,
schema
})
});
}
/**
* Start a local GraphQL server.
*/ export async function startGraphQLServer(params) {
const handler = createHandler(params);
// eslint-disable-next-line @typescript-eslint/no-misused-promises
const server = createServer(handler);
function stop() {
return new Promise((resolve, reject)=>{
server.close((err)=>{
if (err) {
reject(err);
} else {
resolve();
}
});
});
}
const port = await getPort({
port: params.port
});
return await new Promise((resolve, reject)=>{
server.once('error', reject);
server.listen(port, ()=>{
resolve({
port,
stop
});
});
});
}