graphql-yoga
Advanced tools
/// <reference types="node" /> | ||
import { IncomingMessage, Server, ServerResponse } from 'http'; | ||
import { IncomingMessage, Server as NodeServer, ServerResponse } from 'http'; | ||
import { getNodeRequest } from '@ardatan/graphql-helix'; | ||
import { BaseGraphQLServer } from '@graphql-yoga/core'; | ||
import type { GraphQLServerInject, GraphQLServerOptions } from './types'; | ||
import { Server as BaseServer } from '@graphql-yoga/core'; | ||
import type { GraphQLServerInject, ServerOptions } from './types'; | ||
import LightMyRequest from 'light-my-request'; | ||
import { ExecutionResult } from 'graphql'; | ||
/** | ||
* Create a simple yet powerful GraphQL server ready for production workloads. | ||
* Spec compliant server that supports bleeding edge GraphQL features without any vendor lock-ins. | ||
* | ||
* Comes baked in with: | ||
* | ||
* - Envelop - Plugin system for GraphQL | ||
* - GraphQL Helix - Extensible and Framework agnostic GraphQL server | ||
* - GraphiQL - GraphQL IDE for your browser | ||
* - Pino - Super fast, low overhead Node.js logger | ||
* | ||
* Example: | ||
* ```ts | ||
* import { schema } from './schema' | ||
* // Provide a GraphQL schema | ||
* const server = new GraphQLServer({ schema }) | ||
* // Start the server. Defaults to http://localhost:4000/graphql | ||
* server.start() | ||
* ``` | ||
*/ | ||
export declare class GraphQLServer<TContext> extends BaseGraphQLServer<TContext> { | ||
declare class Server<TContext> extends BaseServer<TContext> { | ||
/** | ||
@@ -42,6 +22,6 @@ * Port for server | ||
private _server; | ||
constructor(options: GraphQLServerOptions<TContext>); | ||
constructor(options: ServerOptions<TContext>); | ||
handleIncomingMessage(...args: Parameters<typeof getNodeRequest>): Promise<Response>; | ||
requestListener(req: IncomingMessage, res: ServerResponse): Promise<void>; | ||
get server(): Server; | ||
requestListener: (req: IncomingMessage, res: ServerResponse) => Promise<void>; | ||
get server(): NodeServer; | ||
start(callback?: VoidFunction): Promise<void>; | ||
@@ -67,4 +47,26 @@ stop(callback?: (err?: Error) => void): Promise<void>; | ||
} | ||
export type { GraphQLServerOptions } from './types'; | ||
export { Plugin, enableIf, envelop, useEnvelop, usePayloadFormatter, useExtendContext, useTiming, EnvelopError as GraphQLServerError, } from '@envelop/core'; | ||
export { GraphQLBlob } from '@graphql-yoga/core'; | ||
/** | ||
* Create a simple yet powerful GraphQL server ready for production workloads. | ||
* Spec compliant server that supports bleeding edge GraphQL features without any vendor lock-ins. | ||
* | ||
* Comes baked in with: | ||
* | ||
* - Envelop - Plugin system for GraphQL | ||
* - GraphQL Helix - Extensible and Framework agnostic GraphQL server | ||
* - GraphiQL - GraphQL IDE for your browser | ||
* - Pino - Super fast, low overhead Node.js logger | ||
* | ||
* Example: | ||
* ```ts | ||
* import { schema } from './schema' | ||
* // Provide a GraphQL schema | ||
* const server = createServer({ schema }) | ||
* // Start the server. Defaults to http://localhost:4000/graphql | ||
* server.start() | ||
* ``` | ||
*/ | ||
export declare function createServer<TContext>(options: ServerOptions<TContext>): Server<TContext>; | ||
export type { ServerOptions } from './types'; | ||
export { createPubSub } from './pubsub'; | ||
export * from '@envelop/core'; | ||
export { EnvelopError as GraphQLServerError } from '@envelop/core'; |
180
index.js
@@ -15,24 +15,58 @@ 'use strict'; | ||
const graphql = require('graphql'); | ||
const pushPullAsyncIterableIterator = require('@n1ru4l/push-pull-async-iterable-iterator'); | ||
const resolveGlobalConfig = (api = globalThis) => { | ||
if (!api.Event || !api.EventTarget) { | ||
throw new Error(` | ||
[graphql-yoga] 'createPubSub' uses the Event and EventTarget APIs. | ||
In modern JavaScript environments those are part of the global scope. However, if you are using an older version of Node.js (<= 16.x.x), those APIs must be polyfilled. | ||
You can provide polyfills to the 'createPubSub' function: | ||
\`\`\` | ||
// yarn install @ungap/event @ungap/event-target | ||
import Event from '@ungap/event' | ||
import EventTarget from '@ungap/event-target' | ||
const pubSub = createPubSub({ | ||
event: { | ||
Event, | ||
EventTarget, | ||
} | ||
}) | ||
\`\`\` | ||
`); | ||
} | ||
return globalThis; | ||
}; | ||
/** | ||
* Create a simple yet powerful GraphQL server ready for production workloads. | ||
* Spec compliant server that supports bleeding edge GraphQL features without any vendor lock-ins. | ||
* | ||
* Comes baked in with: | ||
* | ||
* - Envelop - Plugin system for GraphQL | ||
* - GraphQL Helix - Extensible and Framework agnostic GraphQL server | ||
* - GraphiQL - GraphQL IDE for your browser | ||
* - Pino - Super fast, low overhead Node.js logger | ||
* | ||
* Example: | ||
* ```ts | ||
* import { schema } from './schema' | ||
* // Provide a GraphQL schema | ||
* const server = new GraphQLServer({ schema }) | ||
* // Start the server. Defaults to http://localhost:4000/graphql | ||
* server.start() | ||
* ``` | ||
* Utility for publishing and subscribing to events. | ||
*/ | ||
class GraphQLServer extends core.BaseGraphQLServer { | ||
const createPubSub = (config) => { | ||
const { Event, EventTarget } = resolveGlobalConfig(config === null || config === void 0 ? void 0 : config.event); | ||
const target = new EventTarget(); | ||
return { | ||
publish(routingKey, ...args) { | ||
const event = new Event(routingKey); | ||
event.data = args[0]; | ||
target.dispatchEvent(event); | ||
}, | ||
subscribe(...[routingKey, id]) { | ||
const topic = id === undefined ? routingKey : `${routingKey}:${id}`; | ||
const { pushValue, asyncIterableIterator } = pushPullAsyncIterableIterator.makePushPullAsyncIterableIterator(); | ||
const handler = (event) => { | ||
pushValue(event.data); | ||
}; | ||
target.addEventListener(topic, handler); | ||
const originalReturn = asyncIterableIterator.return.bind(asyncIterableIterator); | ||
asyncIterableIterator.return = (...args) => { | ||
target.removeEventListener(topic, handler); | ||
return originalReturn(...args); | ||
}; | ||
return asyncIterableIterator; | ||
}, | ||
}; | ||
}; | ||
class Server extends core.Server { | ||
constructor(options) { | ||
@@ -45,2 +79,6 @@ var _a, _b; | ||
}); | ||
this.requestListener = async (req, res) => { | ||
const response = await this.handleIncomingMessage(req); | ||
await graphqlHelix.sendNodeResponse(response, res); | ||
}; | ||
this.port = options.port || parseInt(process.env.PORT || '4000'); | ||
@@ -61,3 +99,3 @@ this.endpoint = options.endpoint || '/graphql'; | ||
: {}; | ||
this.logger = pino({ | ||
const pinoLogger = pino({ | ||
...prettyPrintOptions, | ||
@@ -67,2 +105,9 @@ level: this.isDev ? 'debug' : 'info', | ||
}); | ||
this.logger = { | ||
log: (...args) => pinoLogger.info(...args), | ||
debug: (...args) => pinoLogger.debug(...args), | ||
error: (...args) => pinoLogger.error(...args), | ||
warn: (...args) => pinoLogger.warn(...args), | ||
info: (...args) => pinoLogger.info(...args), | ||
}; | ||
this.logger.debug('Setting up server.'); | ||
@@ -72,19 +117,20 @@ if (options.https) { | ||
typeof options.https === 'object' | ||
? https.createServer(options.https, this.requestListener.bind(this)) | ||
: https.createServer(this.requestListener.bind(this)); | ||
? https.createServer(options.https, this.requestListener) | ||
: https.createServer(this.requestListener); | ||
} | ||
else { | ||
this._server = http.createServer(this.requestListener.bind(this)); | ||
this._server = http.createServer(this.requestListener); | ||
} | ||
if (this.graphiql) { | ||
this.graphiql.endpoint = this.endpoint; | ||
} | ||
} | ||
async handleIncomingMessage(...args) { | ||
this.logger.debug('Node Request received', ...args); | ||
this.logger.debug('Node Request received'); | ||
const request = await graphqlHelix.getNodeRequest(...args); | ||
this.logger.debug('Node Request processed'); | ||
const response = await this.handleRequest(request); | ||
this.logger.debug('Response returned'); | ||
return response; | ||
} | ||
async requestListener(req, res) { | ||
const response = await this.handleIncomingMessage(req); | ||
await graphqlHelix.sendNodeResponse(response, res); | ||
} | ||
get server() { | ||
@@ -137,3 +183,3 @@ return this._server; | ||
async inject({ document, variables, operationName, headers, }) { | ||
const response = await LightMyRequest.inject(this.requestListener.bind(this), { | ||
const response = await LightMyRequest.inject(this.requestListener, { | ||
method: 'POST', | ||
@@ -156,51 +202,41 @@ url: this.endpoint, | ||
} | ||
/** | ||
* Create a simple yet powerful GraphQL server ready for production workloads. | ||
* Spec compliant server that supports bleeding edge GraphQL features without any vendor lock-ins. | ||
* | ||
* Comes baked in with: | ||
* | ||
* - Envelop - Plugin system for GraphQL | ||
* - GraphQL Helix - Extensible and Framework agnostic GraphQL server | ||
* - GraphiQL - GraphQL IDE for your browser | ||
* - Pino - Super fast, low overhead Node.js logger | ||
* | ||
* Example: | ||
* ```ts | ||
* import { schema } from './schema' | ||
* // Provide a GraphQL schema | ||
* const server = createServer({ schema }) | ||
* // Start the server. Defaults to http://localhost:4000/graphql | ||
* server.start() | ||
* ``` | ||
*/ | ||
function createServer(options) { | ||
return new Server(options); | ||
} | ||
Object.defineProperty(exports, 'GraphQLBlob', { | ||
Object.keys(core$1).forEach(function (k) { | ||
if (k !== 'default') Object.defineProperty(exports, k, { | ||
enumerable: true, | ||
get: function () { | ||
return core.GraphQLBlob; | ||
return core$1[k]; | ||
} | ||
}); | ||
}); | ||
Object.defineProperty(exports, 'GraphQLServerError', { | ||
enumerable: true, | ||
get: function () { | ||
return core$1.EnvelopError; | ||
} | ||
enumerable: true, | ||
get: function () { | ||
return core$1.EnvelopError; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'enableIf', { | ||
enumerable: true, | ||
get: function () { | ||
return core$1.enableIf; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'envelop', { | ||
enumerable: true, | ||
get: function () { | ||
return core$1.envelop; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'useEnvelop', { | ||
enumerable: true, | ||
get: function () { | ||
return core$1.useEnvelop; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'useExtendContext', { | ||
enumerable: true, | ||
get: function () { | ||
return core$1.useExtendContext; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'usePayloadFormatter', { | ||
enumerable: true, | ||
get: function () { | ||
return core$1.usePayloadFormatter; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'useTiming', { | ||
enumerable: true, | ||
get: function () { | ||
return core$1.useTiming; | ||
} | ||
}); | ||
exports.GraphQLServer = GraphQLServer; | ||
exports.createPubSub = createPubSub; | ||
exports.createServer = createServer; |
{ | ||
"name": "graphql-yoga", | ||
"version": "2.0.1-canary-6a9fcf2.0", | ||
"version": "2.0.1-canary-a04e8b0.0", | ||
"description": "", | ||
@@ -9,7 +9,8 @@ "peerDependencies": { | ||
"dependencies": { | ||
"@ardatan/graphql-helix": "0.0.6", | ||
"@ardatan/graphql-helix": "^0.0.10", | ||
"@envelop/core": "^1.6.2", | ||
"@graphql-typed-document-node/core": "^3.1.1", | ||
"@graphql-yoga/core": "0.2.0-canary-6a9fcf2.0", | ||
"@graphql-yoga/handler": "0.2.0-canary-6a9fcf2.0", | ||
"@graphql-yoga/core": "0.3.0-canary-a04e8b0.0", | ||
"@graphql-yoga/handler": "0.2.0-alpha.1", | ||
"@n1ru4l/push-pull-async-iterable-iterator": "^3.1.0", | ||
"light-my-request": "^4.7.0", | ||
@@ -16,0 +17,0 @@ "pino": "^7.2.0", |
@@ -5,3 +5,3 @@ # `@graphql-yoga` | ||
const { GraphQLSchema, GraphQLObjectType, GraphQLString } = require('graphql') | ||
const { GraphQLServer } = require('../core/dist') | ||
const { createServer } = require('graphql-yoga') | ||
@@ -41,4 +41,4 @@ const schema = new GraphQLSchema({ | ||
const server = new GraphQLServer({ schema }) | ||
const server = createServer({ schema }) | ||
server.start() | ||
``` |
/// <reference types="node" /> | ||
import type { BaseGraphQLServerOptions } from '@graphql-yoga/core'; | ||
import type { ServerOptions as BaseServerOptions } from '@graphql-yoga/core'; | ||
import type { DocumentNode } from 'graphql'; | ||
@@ -7,7 +7,7 @@ import type { TypedDocumentNode } from '@graphql-typed-document-node/core'; | ||
import { OutgoingHttpHeaders } from 'http2'; | ||
import { ServerOptions } from 'https'; | ||
import { ServerOptions as HttpsServerOptions } from 'https'; | ||
/** | ||
* Configuration options for the server | ||
*/ | ||
export declare type GraphQLServerOptions<TContext> = BaseGraphQLServerOptions<TContext> & { | ||
export declare type ServerOptions<TContext> = BaseServerOptions<TContext> & { | ||
/** | ||
@@ -35,3 +35,3 @@ * GraphQL endpoint | ||
*/ | ||
https?: ServerOptions | boolean; | ||
https?: HttpsServerOptions | boolean; | ||
}; | ||
@@ -38,0 +38,0 @@ export declare type GraphQLServerInject<TData = any, TVariables = Record<string, any>> = { |
Sorry, the diff of this file is not supported yet
22789
30.14%7
16.67%574
26.99%10
11.11%