Skip to content

Instantly share code, notes, and snippets.

@merunga
Created April 11, 2018 12:19
Show Gist options
  • Save merunga/2b6d2292c5e04417c1649106071bbdcd to your computer and use it in GitHub Desktop.
Save merunga/2b6d2292c5e04417c1649106071bbdcd to your computer and use it in GitHub Desktop.
serverless-appsync-plugin codegen
// creates a `mapping-templates` folder with the velocity templates
// for each query and mutation defined in your schema.graphql
// and a `sls-appsync-mt.yml` to use inside of `serverless.yml`:
// custom.appsync.mappingTemplates: ${file(./sls-appsync-mt.yml)}
import fs, { readFileSync } from 'fs'
import { join } from 'path'
import { introspectSchema } from 'apollo-codegen'
import ejs from 'ejs'
import yaml from 'node-yaml'
const generateVelocityTemplate = ({ type = 'request', field }) => {
try {
const template = fs.readFileSync(join(__dirname, `../scripts/${type}-mapping-template.tmpl.ejs`), 'utf-8')
const mtContents = ejs.render( template, field ? { field } : {} )
const outPath = `./mapping-templates/${field ? `${field}-` : ''}${type}-mapping-template.txt`
fs.writeFileSync(outPath, mtContents, 'utf-8')
} catch (err) {
console.log(err)
}
}
introspectSchema(
join(__dirname, '../schema.graphql'),
join(__dirname, './schema.json')
)
.then(() => {
const schema = require('./schema.json').data.__schema
const toResolve = schema.types.reduce((toResolve, y) => {
if(
y.name === schema.queryType.name ||
y.name === schema.mutationType.name
) {
toResolve = [
...toResolve,
...y.fields.map(f => ({
field: f.name,
type: y.name === schema.queryType.name ? 'Query' : 'Mutation',
}))
]
}
return toResolve
}, [])
const slsConf = []
let dataSource = process.argv.length > 2 ? process.argv[2] : null
dataSource = dataSource || 'Lambda'
const dir = './mapping-templates'
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir)
}
toResolve.map((data) => {
const { field } = data
slsConf.push({
dataSource,
...data,
request: `${field}-request-mapping-template.txt`,
response: 'response-mapping-template.txt',
})
generateVelocityTemplate({ field })
})
generateVelocityTemplate({ type: 'response' })
yaml.writeSync(join(__dirname, '../sls-appsync-mt.yml'), slsConf)
fs.unlinkSync(join(__dirname, './schema.json'))
})
.catch(err => console.error(err))
type Comment {
_id: String!
# The comment's content.
content: String!
# The comment timestamp. This field is indexed to enable sorted pagination.
createdAt: String!
}
type Mutation {
# Comment on an event.
commentOnEvent(eventId: ID!, content: String!, createdAt: String!): Comment
}
type Subscription {
subscribeToEventComments(eventId: String!): Comment
@aws_subscribe(mutations: ["commentOnEvent"])
}
type Event {
_id: ID!
name: String!
where: String!
when: String!
description: String
# Paginate through all comments belonging to an individual post.
comments: [Comment]
}
type Query {
# Get a single event by id.
getEvent(_id: ID!): Event
# Paginate through events.
listEvents(limit: Int = 10): [Event]
}
type Mutation {
# Create a single event.
createEvent(
name: String!,
when: String!,
where: String!,
description: String
): Event
# Delete a single event by id.
deleteEvent(_id: ID!): Event
}
type Subscription {
subscribeToNewEvent: Event
@aws_subscribe(mutations: ["createEvent"])
}
{
"version": "2017-02-28",
"operation": "Invoke",
"payload": {
"field": "<%= field %>",
"arguments": $utils.toJson($context.arguments)
}
}
$util.toJson($context.result)
schema {
query: Query
mutation: Mutation
subscription: Subscription
}
// merges all the sub-schemas into `schema.graphql`
import path from 'path'
import fs from 'fs'
import { fileLoader, mergeTypes } from 'merge-graphql-schemas'
const typesArray = fileLoader(path.join(__dirname, '../schema'))
const schema = mergeTypes(typesArray, { all: true })
fs.writeFile(path.join(__dirname, '../schema.graphql'), `# AUTOGENERATED\n${schema.toString()}`, function(err) {
if(err) {
return console.log(err)
}
})
# AUTOGENERATED
schema {
query: Query
mutation: Mutation
subscription: Subscription
}
type Query {
# Get a single event by id.
getEvent(_id: ID!): Event
# Paginate through events.
listEvents(limit: Int = 10): [Event]
}
type Mutation {
# Comment on an event.
commentOnEvent(eventId: ID!, content: String!, createdAt: String!): Comment
# Create a single event.
createEvent(name: String!, when: String!, where: String!, description: String): Event
# Delete a single event by id.
deleteEvent(_id: ID!): Event
}
type Subscription {
subscribeToEventComments(eventId: String!): Comment @aws_subscribe(mutations: ["commentOnEvent"])
subscribeToNewEvent: Event @aws_subscribe(mutations: ["createEvent"])
}
type Comment {
_id: String!
# The comment's content.
content: String!
# The comment timestamp. This field is indexed to enable sorted pagination.
createdAt: String!
}
type Event {
_id: ID!
name: String!
where: String!
when: String!
description: String
# Paginate through all comments belonging to an individual post.
comments: [Comment]
}
# AUTOGENERATED
- dataSource: Lambda
field: getEvent
type: Query
request: getEvent-request-mapping-template.txt
response: response-mapping-template.txt
- dataSource: Lambda
field: listEvents
type: Query
request: listEvents-request-mapping-template.txt
response: response-mapping-template.txt
- dataSource: Lambda
field: commentOnEvent
type: Mutation
request: commentOnEvent-request-mapping-template.txt
response: response-mapping-template.txt
- dataSource: Lambda
field: createEvent
type: Mutation
request: createEvent-request-mapping-template.txt
response: response-mapping-template.txt
- dataSource: Lambda
field: deleteEvent
type: Mutation
request: deleteEvent-request-mapping-template.txt
response: response-mapping-template.txt
@merunga
Copy link
Author

merunga commented Apr 11, 2018

folder structure

  • scripts/
    • appsync-mt-gen-js
    • request-mapping-template.tmpl.ejs
    • response-mapping-template.tmpl.ejs
    • schema-merge.js
  • schema/
    • Comment.js
    • Event.js
    • root.js
  • schema.graphql
  • sls-appsync-mt.yml

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment