Created
July 6, 2017 21:28
-
-
Save ibolmo/e227fa99cbdb3aef3b61ad68fc647734 to your computer and use it in GitHub Desktop.
A Zapier Platform CLI resource with hooks inside.
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
const _sharedBaseUrl = 'http://57b20fb546b57d1100a3c405.mockapi.io/api'; | |
const subscribeHook = (z, bundle) => { | |
// `z.console.log()` is similar to `console.log()`. | |
z.console.log('console says hello world!'); | |
z.console.log(bundle); | |
// bundle.targetUrl has the Hook URL this app should call when a recipe is created. | |
const data = { | |
url: bundle.targetUrl, | |
style: bundle.inputData.style | |
}; | |
// You can build requests and our client will helpfully inject all the variables | |
// you need to complete. You can also register middleware to control this. | |
const options = { | |
url: 'http://57b20fb546b57d1100a3c405.mockapi.io/api/hooks', | |
method: 'POST', | |
body: JSON.stringify(data) | |
}; | |
// You may return a promise or a normal data structure from any perform method. | |
return z.request(options) | |
.then((response) => JSON.parse(response.content)); | |
}; | |
const unsubscribeHook = (z, bundle) => { | |
// bundle.subscribeData contains the parsed response JSON from the subscribe | |
// request made initially. | |
const hookId = bundle.subscribeData.id; | |
// You can build requests and our client will helpfully inject all the variables | |
// you need to complete. You can also register middleware to control this. | |
const options = { | |
url: `http://57b20fb546b57d1100a3c405.mockapi.io/api/hooks/${hookId}`, | |
method: 'DELETE', | |
}; | |
// You may return a promise or a normal data structure from any perform method. | |
return z.request(options) | |
.then((response) => JSON.parse(response.content)); | |
}; | |
const getFallbackRealRecipe = (z, bundle) => { | |
// For the test poll, you should get some real data, to aid the setup process. | |
const options = { | |
url: 'http://57b20fb546b57d1100a3c405.mockapi.io/api/recipes/', | |
params: { | |
style: bundle.inputData.style | |
} | |
}; | |
return z.request(options) | |
.then((response) => JSON.parse(response.content)); | |
}; | |
const getRecipe = (z, bundle) => { | |
return z.request({ | |
url: `${_sharedBaseUrl}/recipes/${bundle.inputData.id}`, | |
}) | |
.then((response) => JSON.parse(response.content)); | |
}; | |
const listRecipes = (z, bundle) => { | |
return z.request({ | |
url: _sharedBaseUrl + '/recipes', | |
params: { | |
style: bundle.inputData.style | |
} | |
}) | |
.then((response) => JSON.parse(response.content)); | |
}; | |
const createRecipe = (z, bundle) => { | |
const requestOptions = { | |
url: _sharedBaseUrl + '/recipes', | |
method: 'POST', | |
body: JSON.stringify({ | |
name: bundle.inputData.name, | |
directions: bundle.inputData.directions, | |
authorId: bundle.inputData.authorId, | |
}), | |
headers: { | |
'content-type': 'application/json' | |
} | |
}; | |
return z.request(requestOptions) | |
.then((response) => JSON.parse(response.content)); | |
}; | |
const searchRecipe = (z, bundle) => { | |
return z.request({ | |
url: _sharedBaseUrl + '/recipes', | |
params: { | |
nameSearch: bundle.inputData.name | |
} | |
}) | |
.then((response) => { | |
const matchingRecipes = JSON.parse(response.content); | |
// Only return the first matching recipe | |
if (matchingRecipes && matchingRecipes.length) { | |
return [matchingRecipes[0]]; | |
} | |
return []; | |
}); | |
}; | |
// This file exports a Recipe resource. The definition below contains all of the keys available, | |
// and implements the list and create methods. | |
module.exports = { | |
key: 'recipe', | |
noun: 'Recipe', | |
// The get method is used by Zapier to fetch a complete representation of a record. This is helpful when the HTTP | |
// response from a create call only return an ID, or a search that only returns a minimuml representation of the | |
// record. Zapier will follow these up with the get() to retrieve the entire object. | |
get: { | |
display: { | |
label: 'Get Recipe', | |
description: 'Gets a recipe.', | |
}, | |
operation: { | |
inputFields: [ | |
{key: 'id', required: true}, | |
], | |
perform: getRecipe, | |
}, | |
}, | |
// The list method on this resource becomes a Trigger on the app. Zapier will use polling to watch for new records | |
list: { | |
display: { | |
label: 'New Recipe', | |
description: 'Trigger when a new recipe is added.', | |
}, | |
operation: { | |
inputFields: [ | |
{key: 'style', type: 'string', helpText: 'Explain what style of cuisine this is.'}, | |
], | |
perform: listRecipes, | |
}, | |
}, | |
// If your app supports webhooks, you can define a hook method instead of a list method. | |
// Zapier will turn this into a webhook Trigger on the app. | |
hook: { | |
display: { | |
label: 'New Recipe (Hook)', | |
description: 'Trigger when a new recipe is added.' | |
}, | |
// `operation` is where the business logic goes. | |
operation: { | |
// `inputFields` can define the fields a user could provide, | |
// we'll pass them in as `bundle.inputData` later. | |
inputFields: [ | |
{key: 'style', type: 'string', helpText: 'Which styles of cuisine this should trigger on.'} | |
], | |
type: 'hook', | |
performSubscribe: subscribeHook, | |
performUnsubscribe: unsubscribeHook, | |
perform: getRecipe, | |
performList: getFallbackRealRecipe, | |
// In cases where Zapier needs to show an example record to the user, but we are unable to get a live example | |
// from the API, Zapier will fallback to this hard-coded sample. It should reflect the data structure of | |
// returned records, and have obviously dummy values that we can show to any user. | |
sample: { | |
id: 1, | |
createdAt: 1472069465, | |
name: 'Best Spagetti Ever', | |
authorId: 1, | |
directions: '1. Boil Noodles\n2.Serve with sauce', | |
style: 'italian', | |
}, | |
// If the resource can have fields that are custom on a per-user basis, define a function to fetch the custom | |
// field definitions. The result will be used to augment the sample. | |
// outputFields: () => { return []; } | |
// Alternatively, a static field definition should be provided, to specify labels for the fields | |
outputFields: [ | |
{key: 'id', label: 'ID'}, | |
{key: 'createdAt', label: 'Created At'}, | |
{key: 'name', label: 'Name'}, | |
{key: 'directions', label: 'Directions'}, | |
{key: 'authorId', label: 'Author ID'}, | |
{key: 'style', label: 'Style'}, | |
] | |
} | |
}, | |
// The create method on this resource becomes a Write on this app | |
create: { | |
display: { | |
label: 'Create Recipe', | |
description: 'Creates a new recipe.', | |
}, | |
operation: { | |
inputFields: [ | |
{key: 'name', required: true, type: 'string'}, | |
{key: 'directions', required: true, type: 'text', helpText: 'Explain how should one make the recipe, step by step.'}, | |
{key: 'authorId', required: true, type: 'integer', label: 'Author ID'}, | |
{key: 'style', required: false, type: 'string', helpText: 'Explain what style of cuisine this is.'}, | |
], | |
perform: createRecipe, | |
}, | |
}, | |
// The search method on this resource becomes a Search on this app | |
search: { | |
display: { | |
label: 'Find Recipe', | |
description: 'Finds an existing recipe by name.', | |
}, | |
operation: { | |
inputFields: [ | |
{key: 'name', required: true, type: 'string'}, | |
], | |
perform: searchRecipe, | |
}, | |
}, | |
// In cases where Zapier needs to show an example record to the user, but we are unable to get a live example | |
// from the API, Zapier will fallback to this hard-coded sample. It should reflect the data structure of | |
// returned records, and have obviously dummy values that we can show to any user. | |
sample: { | |
id: 1, | |
createdAt: 1472069465, | |
name: 'Best Spagetti Ever', | |
authorId: 1, | |
directions: '1. Boil Noodles\n2.Serve with sauce', | |
style: 'italian', | |
}, | |
// If the resource can have fields that are custom on a per-user basis, define a function to fetch the custom | |
// field definitions. The result will be used to augment the sample. | |
// outputFields: () => { return []; } | |
// Alternatively, a static field definition should be provided, to specify labels for the fields | |
outputFields: [ | |
{key: 'id', label: 'ID'}, | |
{key: 'createdAt', label: 'Created At'}, | |
{key: 'name', label: 'Name'}, | |
{key: 'directions', label: 'Directions'}, | |
{key: 'authorId', label: 'Author ID'}, | |
{key: 'style', label: 'Style'}, | |
] | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment