-
-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Guillaume Chau
committed
Aug 19, 2019
1 parent
69e2e4b
commit 1adc07a
Showing
14 changed files
with
1,006 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
/** @type {import('../ProjectCreateJob').CreateModule} */ | ||
module.exports = api => { | ||
api.injectFeature({ | ||
name: 'Apollo (needs Express)', | ||
value: 'apollo', | ||
// @ts-ignore | ||
description: 'GraphQL Server', | ||
link: 'https://www.apollographql.com/', | ||
}) | ||
|
||
api.onPromptComplete((answers, preset) => { | ||
// @ts-ignore | ||
preset.plugins['@nodepack/plugin-apollo'] = '' | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
{ | ||
"name": "@nodepack/plugin-apollo", | ||
"version": "0.4.2", | ||
"description": "Nodepack plugin for Apollo Server (GraphQL)", | ||
"author": "Guillaume Chau <[email protected]>", | ||
"license": "MIT", | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/Akryum/nodepack.git" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/Akryum/nodepack/issues" | ||
}, | ||
"homepage": "https://github.com/Akryum/nodepack#readme", | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"main": "src/index.js", | ||
"typings": "types/index.d.ts", | ||
"scripts": { | ||
"test": "yarn test:lint", | ||
"test:lint": "eslint src" | ||
}, | ||
"dependencies": { | ||
"@types/express": "^4.11.1", | ||
"apollo-server-express": "2.8.1", | ||
"graphql-playground-middleware-express": "^1.7.12", | ||
"graphql-deduplicator": "^2.0.5", | ||
"lodash": "^4.17.15", | ||
"mock-express-response": "^0.2.2", | ||
"subscriptions-transport-ws": "^0.9.16" | ||
}, | ||
"devDependencies": { | ||
}, | ||
"peerDependencies": { | ||
"@nodepack/app-context": "^0.4.0", | ||
"@nodepack/service": "^0.4.0", | ||
"@nodepack/utils": "^0.4.0", | ||
"graphql": "^14.4.2" | ||
}, | ||
"optionalDependencies": { | ||
"graphql-tag": "^2.10.1" | ||
} | ||
} |
36 changes: 36 additions & 0 deletions
36
packages/@nodepack/plugin-apollo/src/app-migrations/index.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
/** @type {import('@nodepack/service').MigrationPlugin} */ | ||
module.exports = api => { | ||
const schemaTemplate = `./templates/schema-${api.hasPlugin('typescript') ? 'ts' : 'js'}` | ||
|
||
api.register({ | ||
id: 'defaultPackage', | ||
title: 'Install dependencies', | ||
up: (api, options) => { | ||
api.extendPackage({ | ||
dependencies: { | ||
graphql: '^14.4.2', | ||
'graphql-tag': '^2.10.1', | ||
}, | ||
}) | ||
}, | ||
down: (api, options) => { | ||
api.extendPackage({ | ||
dependencies: { | ||
graphql: undefined, | ||
'graphql-tag': undefined, | ||
}, | ||
}) | ||
}, | ||
}) | ||
|
||
api.register({ | ||
id: 'defaultSchema', | ||
title: 'Template: default schema', | ||
up: (api, options) => { | ||
api.render(schemaTemplate, options) | ||
}, | ||
down: (api, options) => { | ||
api.unrender(schemaTemplate) | ||
}, | ||
}) | ||
} |
13 changes: 13 additions & 0 deletions
13
packages/@nodepack/plugin-apollo/src/app-migrations/templates/schema-js/src/schema/hello.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import gql from 'graphql-tag' | ||
|
||
export const typeDefs = gql` | ||
type Query { | ||
hello: String! | ||
} | ||
` | ||
|
||
export const resolvers = { | ||
Query: { | ||
hello: (root, args, ctx, info) => `Hello world`, | ||
}, | ||
} |
15 changes: 15 additions & 0 deletions
15
packages/@nodepack/plugin-apollo/src/app-migrations/templates/schema-ts/src/schema/hello.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import gql from 'graphql-tag' | ||
import { IResolvers } from 'graphql-tools' | ||
import { ApolloContext } from '@nodepack/plugin-apollo' | ||
|
||
export const typeDefs = gql` | ||
type Query { | ||
hello: String! | ||
} | ||
` | ||
|
||
export const resolvers: IResolvers = { | ||
Query: { | ||
hello: (root, args, ctx: ApolloContext, info) => `Hello world`, | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
/** @type {import('@nodepack/service').ServicePlugin} */ | ||
module.exports = (api, options) => { | ||
if (api.hasPlugin('express')) { | ||
api.addRuntimeModule('./runtime/apollo-express.js') | ||
} else { | ||
throw new Error(`You need @nodepack/plugin-express with Apollo. Other options not yet supported.`) | ||
} | ||
} |
69 changes: 69 additions & 0 deletions
69
packages/@nodepack/plugin-apollo/src/runtime/apollo-express.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import { hook, callHook } from '@nodepack/app-context' | ||
import { loadSchema } from './schema' | ||
import { makeExecutableSchema, ApolloServer } from 'apollo-server-express' | ||
import MockExpressResponse from 'mock-express-response' | ||
import expressPlayground from 'graphql-playground-middleware-express' | ||
import { getApolloConfig, printReady } from './server' | ||
|
||
hook('express-http', async (ctx) => { | ||
const { config, express: app, httpServer } = ctx | ||
const apolloConfig = config.apollo || {} | ||
|
||
// Load schema | ||
const fullSchema = ctx.schema = await loadSchema(ctx) | ||
|
||
await callHook('apollo-schema', ctx) | ||
|
||
const localSchema = makeExecutableSchema({ | ||
typeDefs: fullSchema.typeDefs, | ||
resolvers: fullSchema.resolvers, | ||
}) | ||
|
||
// Apollo Server | ||
const server = ctx.server = new ApolloServer(await getApolloConfig({ | ||
ctx, | ||
apolloConfig, | ||
localSchema, | ||
onSubConnect: (connection, websocket) => { | ||
return new Promise((resolve, reject) => { | ||
const req = websocket.upgradeReq | ||
// @ts-ignore | ||
app.handle(req, new MockExpressResponse(), (err, result) => { | ||
if (err) { | ||
reject(err) | ||
} else { | ||
resolve(result) | ||
} | ||
}) | ||
}) | ||
}, | ||
})) | ||
|
||
// GraphQL Playground | ||
if (apolloConfig.playground !== false) { | ||
const playgroundRoute = ctx.playgroundRoute = | ||
typeof apolloConfig.playground === 'string' ? apolloConfig.playground : '/playground' | ||
app.get(playgroundRoute, expressPlayground({ | ||
endpoint: server.graphqlPath, | ||
subscriptionEndpoint: server.subscriptionsPath, | ||
})) | ||
} | ||
|
||
// Express middleware | ||
server.applyMiddleware({ | ||
app, | ||
cors: config.cors, | ||
}) | ||
|
||
// Subscriptions | ||
server.installSubscriptionHandlers(httpServer) | ||
|
||
// Listen hook | ||
hook('express-listen', async (ctx) => { | ||
await callHook('apollo-listen', ctx) | ||
}) | ||
|
||
hook('print-ready', () => { | ||
printReady(ctx) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { PubSub } from 'apollo-server-express' | ||
import events from 'events' | ||
|
||
export function createDefaultPubsub () { | ||
const eventEmitter = new events.EventEmitter() | ||
eventEmitter.setMaxListeners(Infinity) | ||
return new PubSub({ | ||
eventEmitter, | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import merge from 'lodash/merge' | ||
|
||
/** @typedef {import('graphql').DocumentNode} DocumentNode */ | ||
/** @typedef {import('apollo-server-express').IResolvers} IResolvers */ | ||
|
||
/** | ||
* @param {any} ctx | ||
*/ | ||
export async function loadSchema (ctx) { | ||
/** @type {DocumentNode[]} */ | ||
const typeDefs = [] | ||
/** @type {DocumentNode[]} */ | ||
const internalTypeDefs = [] | ||
/** @type {IResolvers} */ | ||
const resolvers = {} | ||
/** @type {DocumentNode[]} */ | ||
const mergeTypeDefs = [] | ||
/** @type {IResolvers} */ | ||
const mergeResolvers = {} | ||
|
||
const files = require.context('@', true, /^.\/schema\/.*\.[jt]sx?$/) | ||
for (const key of files.keys()) { | ||
let module = files(key) | ||
if (module.default) { | ||
module = module.default | ||
} | ||
if (typeof module === 'function') { | ||
module = await module(ctx) | ||
} | ||
if (module.typeDefs) { | ||
typeDefs.push(module.typeDefs) | ||
} | ||
if (module.internalTypeDefs) { | ||
internalTypeDefs.push(module.internalTypeDefs) | ||
} | ||
if (module.mergeTypeDefs) { | ||
mergeTypeDefs.push(module.mergeTypeDefs) | ||
} | ||
if (module.resolvers) { | ||
merge(resolvers, module.resolvers) | ||
} | ||
if (module.mergeResolvers) { | ||
merge(mergeResolvers, module.mergeResolvers) | ||
} | ||
} | ||
|
||
return { | ||
typeDefs, | ||
internalTypeDefs, | ||
resolvers, | ||
mergeTypeDefs, | ||
mergeResolvers, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import { callHook, createContext } from '@nodepack/app-context' | ||
import { createDefaultPubsub } from './pubsub' | ||
|
||
export async function getApolloConfig ({ | ||
ctx, | ||
apolloConfig, | ||
localSchema, | ||
onSubConnect, | ||
}) { | ||
// PubSub for subscriptions | ||
const pubsub = ctx.config.pubsub || createDefaultPubsub() | ||
|
||
return { | ||
schema: localSchema, | ||
context: async (context) => { | ||
let user | ||
if (context.req) { | ||
// @ts-ignore | ||
user = context.req.user | ||
} else if (context.connection) { | ||
user = context.connection.context.user | ||
} | ||
const reqCtx = await createContext() | ||
reqCtx.user = user | ||
reqCtx.rawContext = context | ||
reqCtx.req = context.req | ||
reqCtx.res = context.res | ||
reqCtx.connection = context.connection | ||
reqCtx.pubsub = pubsub | ||
await callHook('apollo-request', reqCtx) | ||
return reqCtx | ||
}, | ||
tracing: true, | ||
introspection: true, | ||
subscriptions: { | ||
path: '/subscriptions', | ||
/** | ||
* @param {any} connection | ||
*/ | ||
onConnect: async (connection, websocket) => { | ||
// @ts-ignore | ||
const req = websocket.upgradeReq | ||
if (onSubConnect) { | ||
await onSubConnect(connection, websocket) | ||
} | ||
return { | ||
...connection.context, | ||
user: req.user, | ||
} | ||
}, | ||
}, | ||
...apolloConfig.apolloServerOptions || {}, | ||
playground: false, | ||
} | ||
} | ||
|
||
export function printReady (ctx) { | ||
console.log(`🚀 Server ready at http://localhost:${ctx.port}${ctx.server.graphqlPath}`) | ||
console.log(`⚡ Subs ready at ws://localhost:${ctx.port}${ctx.server.subscriptionsPath}`) | ||
if (ctx.playgroundRoute) { | ||
console.log(`🎮️ Playground ready at http://localhost:${ctx.port}${ctx.playgroundRoute}`) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { DocumentNode } from 'graphql' | ||
import { IResolvers, PubSubEngine, ApolloServer } from 'apollo-server-express' | ||
import { ExecutionParams } from 'subscriptions-transport-ws' | ||
import { Request, Response } from 'express' | ||
|
||
export interface Schema { | ||
typeDefs: DocumentNode | ||
resolvers: IResolvers | ||
internalTypeDefs: DocumentNode | ||
mergeTypeDefs: DocumentNode | ||
mergeResolvers: IResolvers | ||
} | ||
|
||
export interface ApolloContext { | ||
schema: Schema | ||
req: Request | ||
res: Response | ||
connection: ExecutionParams | ||
pubsub: PubSubEngine | ||
user: any | ||
server: ApolloServer | ||
} |
Oops, something went wrong.