zapier-platform-cli 12.0.2 → 12.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README-source.md +2017 -0
- package/README.md +100 -90
- package/oclif.manifest.json +1 -1
- package/package.json +1 -1
- package/src/oclif/commands/team/add.js +26 -13
- package/src/oclif/commands/team/get.js +17 -21
- package/src/oclif/commands/team/remove.js +23 -26
- package/src/utils/team.js +33 -0
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@ You may find docs duplicate or outdated across the Zapier site. The most up-to-d
|
|
|
22
22
|
|
|
23
23
|
Our code is updated frequently. To see a full list of changes, look no further than [the CHANGELOG](https://github.com/zapier/zapier-platform/blob/master/CHANGELOG.md).
|
|
24
24
|
|
|
25
|
-
This doc describes the latest CLI version (**12.0.
|
|
25
|
+
This doc describes the latest CLI version (**12.0.3**), as of this writing. If you're using an older version of the CLI, you may want to check out these historical releases:
|
|
26
26
|
|
|
27
27
|
- CLI Docs: [10.2.0](https://github.com/zapier/zapier-platform/blob/zapier-platform-cli@10.2.0/packages/cli/README.md), [9.6.0](https://github.com/zapier/zapier-platform/blob/zapier-platform-cli@9.6.0/packages/cli/README.md), [8.4.2](https://github.com/zapier/zapier-platform/blob/zapier-platform-cli@8.4.2/packages/cli/README.md)
|
|
28
28
|
- CLI Reference: [10.2.0](https://github.com/zapier/zapier-platform/blob/zapier-platform-cli@10.2.0/packages/cli/docs/cli.md), [9.6.0](https://github.com/zapier/zapier-platform/blob/zapier-platform-cli@9.6.0/packages/cli/docs/cli.md), [8.4.2](https://github.com/zapier/zapier-platform/blob/zapier-platform-cli@8.4.2/packages/cli/docs/cli.md)
|
|
@@ -191,7 +191,7 @@ You can develop using any version of Node you'd like, but your eventual code mus
|
|
|
191
191
|
|
|
192
192
|
To ensure stability for our users, we strongly encourage you run tests on `v14` sometime before your code reaches users. This can be done multiple ways.
|
|
193
193
|
|
|
194
|
-
Firstly, by using a CI tool (like [Travis CI](https://travis-ci.org/) or [Circle CI](https://circleci.com/), which are free for open source projects). We provide a sample [.travis.yml](https://github.com/zapier/zapier-platform/blob/master/example-apps/
|
|
194
|
+
Firstly, by using a CI tool (like [Travis CI](https://travis-ci.org/) or [Circle CI](https://circleci.com/), which are free for open source projects). We provide a sample [.travis.yml](https://github.com/zapier/zapier-platform/blob/master/example-apps/trigger/.travis.yml) file in our template apps to get you started.
|
|
195
195
|
|
|
196
196
|
Alternatively, you can change your local node version with tools such as [nvm](https://github.com/nvm-sh/nvm#installation-and-update). Then you can either swap to that version with `nvm use v14`, or do `nvm exec v14 zapier test` so you can run tests without having to switch versions while developing.
|
|
197
197
|
|
|
@@ -207,6 +207,7 @@ npm install -g zapier-platform-cli
|
|
|
207
207
|
# setup auth to Zapier's platform with a deploy key
|
|
208
208
|
zapier login
|
|
209
209
|
```
|
|
210
|
+
> Note: If you log into Zapier via the single sign-on (Google, Facebook, or Microsoft), you may not have a Zapier password. If that's the case, you'll need to generate a deploy key, go to [your Zapier developer accont here](https://zapier.com/developer/partner-settings/deploy-keys/) and create/copy a key, then run ```zapier login``` command with the --sso flag.
|
|
210
211
|
|
|
211
212
|
Your Zapier CLI should be installed and ready to go at this point. Next up, we'll create our first app!
|
|
212
213
|
|
|
@@ -221,7 +222,7 @@ cd example-app
|
|
|
221
222
|
npm install
|
|
222
223
|
```
|
|
223
224
|
|
|
224
|
-
> Note:
|
|
225
|
+
> Note: When you run `zapier init`, you'll be presented with a list of templates to start with. Pick the one that matches a feature you'll need (such as "dynamic-dropdown" for an integration with [dynamic dropdown fields](#dynamic-dropdowns)), or select "minimal" for an integration with only the essentials. [View more example apps here](https://github.com/zapier/zapier-platform/tree/master/example-apps).
|
|
225
226
|
|
|
226
227
|
You should now have a working local app. You can run several local commands to try it out.
|
|
227
228
|
|
|
@@ -442,15 +443,15 @@ zapier convert 1234 --version 1.0.1 my-app
|
|
|
442
443
|
|
|
443
444
|
## Authentication
|
|
444
445
|
|
|
445
|
-
Most applications require some sort of authentication
|
|
446
|
+
Most applications require some sort of authentication. The Zapier platform provides core behaviors for several common authentication methods that might be used with your application, as well as the ability to customize authentication further.
|
|
446
447
|
|
|
447
|
-
|
|
448
|
+
When a user authenticates to your application through Zapier, a "connection" is created representing their authentication details. Data tied to a specific authentication connection is included in the [bundle object](#bundle-object) under `bundle.authData`.
|
|
448
449
|
|
|
449
450
|
### Basic
|
|
450
451
|
|
|
451
452
|
Useful if your app requires two pieces of information to authenticate: `username` and `password`, which only the end user can provide. By default, Zapier will do the standard Basic authentication base64 header encoding for you (via an automatically registered middleware).
|
|
452
453
|
|
|
453
|
-
>
|
|
454
|
+
> To create a new integration with basic authentication, run `zapier init [your app name] --template basic-auth`. You can also review an example of that code [here](https://github.com/zapier/zapier-platform/tree/master/example-apps/basic-auth).
|
|
454
455
|
|
|
455
456
|
If your app uses Basic auth with an encoded API key rather than a username and password, like `Authorization: Basic APIKEYHERE:x`, consider the [Custom](#custom) authentication method instead.
|
|
456
457
|
|
|
@@ -477,11 +478,11 @@ const App = {
|
|
|
477
478
|
|
|
478
479
|
*New in v7.4.0.*
|
|
479
480
|
|
|
480
|
-
The setup and user experience of Digest Auth is identical to Basic Auth. Users
|
|
481
|
+
The setup and user experience of Digest Auth is identical to Basic Auth. Users provide Zapier their username and password, and Zapier handles all the nonce and quality of protection details automatically.
|
|
481
482
|
|
|
482
|
-
>
|
|
483
|
+
> To create a new integration with digest authentication, run `zapier init [your app name] --template digest-auth`. You can also review an example of that code [here](https://github.com/zapier/zapier-platform/tree/master/example-apps/digest-auth).
|
|
483
484
|
|
|
484
|
-
> Limitation: Currently, MD5-sess and SHA are not implemented. Only the MD5 algorithm is supported. In addition, server nonces are not reused. That means for every `z.request` call, Zapier will
|
|
485
|
+
> Limitation: Currently, MD5-sess and SHA are not implemented. Only the MD5 algorithm is supported. In addition, server nonces are not reused. That means for every `z.request` call, Zapier will send an additional request beforehand to get the server nonce.
|
|
485
486
|
|
|
486
487
|
```js
|
|
487
488
|
const getConnectionLabel = (z, bundle) => {
|
|
@@ -510,9 +511,9 @@ const App = {
|
|
|
510
511
|
|
|
511
512
|
### Custom
|
|
512
513
|
|
|
513
|
-
|
|
514
|
+
Custom auth is most commonly used for apps that authenticate with API keys, although it also provides flexibility for any unusual authentication setup. You'll likely provide some custom `beforeRequest` middleware or a `requestTemplate` (see [Making HTTP Requests](#making-http-requests)) to pass in data returned from the authentication process, most commonly by adding/computing needed headers.
|
|
514
515
|
|
|
515
|
-
>
|
|
516
|
+
> To create a new integration with custom authentication, run `zapier init [your app name] --custom-auth`. You can also review an example of that code [here](https://github.com/zapier/zapier-platform/tree/master/example-apps/custom-auth).
|
|
516
517
|
|
|
517
518
|
```js
|
|
518
519
|
const authentication = {
|
|
@@ -558,9 +559,9 @@ const App = {
|
|
|
558
559
|
|
|
559
560
|
### Session
|
|
560
561
|
|
|
561
|
-
|
|
562
|
+
Session auth gives you the ability to exchange some user-provided data for some authentication data; for example, username and password for a session key. It can be used to implement almost any authentication method that uses that pattern - for example, alternative OAuth flows.
|
|
562
563
|
|
|
563
|
-
>
|
|
564
|
+
> To create a new integration with session authentication, run `zapier init [your app name] --template session-auth`. You can also review an example of that code [here](https://github.com/zapier/zapier-platform/tree/master/example-apps/session-auth).
|
|
564
565
|
|
|
565
566
|
```js
|
|
566
567
|
const getSessionKey = async (z, bundle) => {
|
|
@@ -628,15 +629,15 @@ const App = {
|
|
|
628
629
|
|
|
629
630
|
```
|
|
630
631
|
|
|
631
|
-
|
|
632
|
+
For Session auth, the function that fetches the additional authentication data needed to make API calls (`authentication.sessionConfig.perform`) has the user-provided fields in `bundle.inputData`. Afterwards, `bundle.authData` contains the data returned by that function (usually the session key or token).
|
|
632
633
|
|
|
633
634
|
### OAuth1
|
|
634
635
|
|
|
635
636
|
*New in `v7.5.0`.*
|
|
636
637
|
|
|
637
|
-
Zapier's OAuth1 implementation matches [Twitter
|
|
638
|
+
Zapier's OAuth1 implementation matches [Twitter](https://developer.twitter.com/en/docs/tutorials/authenticating-with-twitter-api-for-enterprise/authentication-method-overview#oauth1.0a) and [Trello](https://developer.atlassian.com/cloud/trello/guides/rest-api/authorization/#using-basic-oauth) implementations of the 3-legged OAuth flow.
|
|
638
639
|
|
|
639
|
-
>
|
|
640
|
+
> To create a new integration with OAuth1, run `zapier init [your app name] --template oauth1-trello`. You can also check out [oauth1-trello](https://github.com/zapier/zapier-platform/tree/master/example-apps/oauth1-trello), [oauth1-tumblr](https://github.com/zapier/zapier-platform/tree/master/example-apps/oauth1-tumblr), and [oauth1-twitter](https://github.com/zapier/zapier-platform/tree/master/example-apps/oauth1-twitter) for working example apps with OAuth1.
|
|
640
641
|
|
|
641
642
|
The flow works like this:
|
|
642
643
|
|
|
@@ -748,13 +749,15 @@ module.exports = App;
|
|
|
748
749
|
|
|
749
750
|
```
|
|
750
751
|
|
|
751
|
-
|
|
752
|
+
For OAuth1, `authentication.oauth1Config.getRequestToken`, `authentication.oauth1Config.authorizeUrl`, and `authentication.oauth1Config.getAccessToken` have fields like `redirect_uri` and the temporary credentials in `bundle.inputData`. After `getAccessToken` runs, the resulting token value(s) will be stored in `bundle.authData` for the connection.
|
|
753
|
+
|
|
754
|
+
Also, `authentication.oauth1Config.getAccessToken` has access to the additional return values in `rawRequest` and `cleanedRequest` should you need to extract other values (for example, from the query string).
|
|
752
755
|
|
|
753
756
|
### OAuth2
|
|
754
757
|
|
|
755
758
|
Zapier's OAuth2 implementation is based on the `authorization_code` flow, similar to [GitHub](https://developer.github.com/v3/oauth/) and [Facebook](https://developers.facebook.com/docs/authentication/server-side/).
|
|
756
759
|
|
|
757
|
-
>
|
|
760
|
+
> To create a new integration with OAuth2, run `zapier init [your app name] --template oauth2`. You can also check out [our working example app](https://github.com/zapier/zapier-platform/tree/master/example-apps/oauth2).
|
|
758
761
|
|
|
759
762
|
If your app's OAuth2 flow uses a different grant type, such as `client_credentials`, try using [Session auth](#session) instead.
|
|
760
763
|
|
|
@@ -771,7 +774,7 @@ You are required to define:
|
|
|
771
774
|
* `authorizeUrl`: The authorization URL
|
|
772
775
|
* `getAccessToken`: The API call to fetch the access token
|
|
773
776
|
|
|
774
|
-
If the access token has a limited life and you want to refresh the token when it expires, you'll also need to define the API call to perform that refresh. You can choose to set `autoRefresh: true`, as in the example app, if you want Zapier to automatically make a call to refresh the token after receiving a 401. See [Stale Authentication Credentials](#stale-authentication-credentials) for more details on handling auth refresh.
|
|
777
|
+
If the access token has a limited life and you want to refresh the token when it expires, you'll also need to define the API call to perform that refresh (`refreshAccessToken`). You can choose to set `autoRefresh: true`, as in the example app, if you want Zapier to automatically make a call to refresh the token after receiving a 401. See [Stale Authentication Credentials](#stale-authentication-credentials) for more details on handling auth refresh.
|
|
775
778
|
|
|
776
779
|
You'll also likely want to set your `CLIENT_ID` and `CLIENT_SECRET` as environment variables:
|
|
777
780
|
|
|
@@ -855,7 +858,9 @@ module.exports = App;
|
|
|
855
858
|
|
|
856
859
|
```
|
|
857
860
|
|
|
858
|
-
|
|
861
|
+
For OAuth2, `authentication.oauth2Config.authorizeUrl`, `authentication.oauth2Config.getAccessToken`, and `authentication.oauth2Config.refreshAccessToken` have fields like `redirect_uri` and `state` in `bundle.inputData`. After the code is exchanged for an access token and/or refresh token, those tokens are stored in `bundle.authData` for the connection.
|
|
862
|
+
|
|
863
|
+
Also, `authentication.oauth2Config.getAccessToken` has access to the additional return values in `rawRequest` and `cleanedRequest` should you need to extract other values (for example, from the query string).
|
|
859
864
|
|
|
860
865
|
|
|
861
866
|
## Resources
|
|
@@ -895,7 +900,7 @@ This will generate the resource file and add the necessary statements to the `in
|
|
|
895
900
|
A resource has a few basic properties. The first is the `key`, which allows Zapier to identify the resource on our backend.
|
|
896
901
|
The second is the `noun`, the user-friendly name of the resource that is presented to users throughout the Zapier UI.
|
|
897
902
|
|
|
898
|
-
>
|
|
903
|
+
> Check out [this working example app](https://github.com/zapier/zapier-platform/tree/master/example-apps/resource) to see resources in action.
|
|
899
904
|
|
|
900
905
|
After those, there is a set of optional properties that tell Zapier what methods can be performed on the resource.
|
|
901
906
|
The complete list of available methods can be found in the [Resource Schema Docs](https://github.com/zapier/zapier-platform/blob/master/packages/schema/docs/build/schema.md#resourceschema).
|
|
@@ -1000,14 +1005,9 @@ const App = {
|
|
|
1000
1005
|
You can find more details on the definition for each by looking at the [Trigger Schema](https://github.com/zapier/zapier-platform/blob/master/packages/schema/docs/build/schema.md#triggerschema),
|
|
1001
1006
|
[Search Schema](https://github.com/zapier/zapier-platform/blob/master/packages/schema/docs/build/schema.md#searchschema), and [Create Schema](https://github.com/zapier/zapier-platform/blob/master/packages/schema/docs/build/schema.md#createschema).
|
|
1002
1007
|
|
|
1003
|
-
>
|
|
1004
|
-
|
|
1005
|
-
> Example App: Check out https://github.com/zapier/zapier-platform/tree/master/example-apps/rest-hooks for a working example app using REST hook triggers.
|
|
1006
|
-
|
|
1007
|
-
> Example App: Check out https://github.com/zapier/zapier-platform/tree/master/example-apps/search for a working example app using searches.
|
|
1008
|
-
|
|
1009
|
-
> Example App: Check out https://github.com/zapier/zapier-platform/tree/master/example-apps/create for a working example app using creates.
|
|
1008
|
+
> To create a new integration with a premade trigger, search, or create, run `zapier init [your app name]` and select from the list that appears. You can also check out our working example apps [here](https://github.com/zapier/zapier-platform/tree/master/example-apps).
|
|
1010
1009
|
|
|
1010
|
+
> To add a trigger, search, or create to an existing integration, run `zapier scaffold [trigger|search|create] [noun]` to create the necessary files to your project. For example, `zapier scaffold trigger post` will create a new trigger called "New Post".
|
|
1011
1011
|
### Return Types
|
|
1012
1012
|
|
|
1013
1013
|
Each of the 3 types of function expects a certain type of object. As of core v1.0.11, there are automated checks to let you know when you're trying to pass the wrong type back. For reference, each expects:
|
|
@@ -1034,7 +1034,7 @@ In cases where Zapier needs to show an example record to the user, but we are un
|
|
|
1034
1034
|
|
|
1035
1035
|
On each trigger, search, or create in the `operation` directive - you can provide an array of objects as fields under the `inputFields`. Input Fields are what your users would see in the main Zapier user interface. For example, you might have a "Create Contact" action with fields like "First name", "Last name", "Email", etc. These fields will be able to accept input from previous steps in a Zap, for example:
|
|
1036
1036
|
|
|
1037
|
-

|
|
1038
1038
|
|
|
1039
1039
|
You can find more details about setting action fields from a user perspective in [our help documentation](https://zapier.com/help/creating-zap/#set-up-action-template).
|
|
1040
1040
|
|
|
@@ -1073,7 +1073,7 @@ You can find more details on the different field schema options at [our Field Sc
|
|
|
1073
1073
|
|
|
1074
1074
|
### Custom/Dynamic Fields
|
|
1075
1075
|
|
|
1076
|
-
In some cases,
|
|
1076
|
+
In some cases, you may need to provide dynamically-generated fields - especially for custom ones. This is common functionality for CRMs, form software, databases, and other highly-customizable platforms. Instead of an explicit field definition, you can provide a function we'll evaluate to return a list of fields - merging the dynamic with the static fields.
|
|
1077
1077
|
|
|
1078
1078
|
> You should see `bundle.inputData` partially filled in as users provide data - even in field retrieval. This allows you to build hierarchical relationships into fields (e.g. only show issues from the previously selected project).
|
|
1079
1079
|
|
|
@@ -1083,7 +1083,7 @@ In some cases, it might be necessary to provide fields that are dynamically gene
|
|
|
1083
1083
|
const recipeFields = async (z, bundle) => {
|
|
1084
1084
|
const response = await z.request('https://example.com/api/v2/fields.json');
|
|
1085
1085
|
|
|
1086
|
-
// Call
|
|
1086
|
+
// Call response.throwForStatus() if you're using zapier-platform-core v9 or older
|
|
1087
1087
|
|
|
1088
1088
|
// Should return an array like [{"key":"field_1"},{"key":"field_2"}]
|
|
1089
1089
|
return response.data; // response.json if you're using core v9 or older
|
|
@@ -1118,7 +1118,7 @@ const App = {
|
|
|
1118
1118
|
|
|
1119
1119
|
```
|
|
1120
1120
|
|
|
1121
|
-
Additionally, if there is a field that affects the generation of dynamic fields, you can set the `altersDynamicFields: true
|
|
1121
|
+
Additionally, if there is a field that affects the generation of dynamic fields, you can set the property `altersDynamicFields: true`. This informs the Zapier UI whenever the value of that field changes, the input fields need to be recomputed. For example, imagine the selection on a static dropdown called "Dessert Type" determining whether the function generating dynamic fields includes the field "With Sprinkles?" or not. If the value in one input field affects others, this is an important property to set.
|
|
1122
1122
|
|
|
1123
1123
|
```js
|
|
1124
1124
|
module.exports = {
|
|
@@ -1156,8 +1156,8 @@ module.exports = {
|
|
|
1156
1156
|
When using dynamic fields, the fields will be retrieved in three different contexts:
|
|
1157
1157
|
|
|
1158
1158
|
* Whenever the value of a field with `altersDynamicFields` is changed, as described above.
|
|
1159
|
-
* Whenever Zap Editor opens the "Set up" section for the trigger or action.
|
|
1160
|
-
* Whenever the Refresh
|
|
1159
|
+
* Whenever the Zap Editor opens the "Set up" section for the trigger or action.
|
|
1160
|
+
* Whenever the "Refresh fields" button at the bottom of the Editor's "Set up" section is clicked.
|
|
1161
1161
|
|
|
1162
1162
|
Be sure to set up your code accordingly - for example, don't rely on any input fields already having a value, since they won't have one the first time the "Set up" section loads.
|
|
1163
1163
|
|
|
@@ -1216,7 +1216,7 @@ In the above code example the dynamic property makes reference to a trigger with
|
|
|
1216
1216
|
```
|
|
1217
1217
|
|
|
1218
1218
|
The dynamic dropdown would look something like this.
|
|
1219
|
-

|
|
1220
1220
|
|
|
1221
1221
|
In the first code example the dynamic dropdown is powered by a trigger. You can also use a resource to power a dynamic dropdown. To do this combine the resource key and the resource method using camel case.
|
|
1222
1222
|
|
|
@@ -1723,7 +1723,7 @@ This object holds the user's auth details and the data for the API requests.
|
|
|
1723
1723
|
|
|
1724
1724
|
### `bundle.inputData`
|
|
1725
1725
|
|
|
1726
|
-
`bundle.inputData` is user-provided data for this particular run of the trigger/search/create, as defined by the `inputFields
|
|
1726
|
+
`bundle.inputData` is user-provided data for this particular run of the trigger/search/create, as defined by the [`inputFields`](#input-fields). For example:
|
|
1727
1727
|
|
|
1728
1728
|
```js
|
|
1729
1729
|
{
|
|
@@ -1977,22 +1977,22 @@ const App = {
|
|
|
1977
1977
|
|
|
1978
1978
|
## Making HTTP Requests
|
|
1979
1979
|
|
|
1980
|
-
There are two
|
|
1980
|
+
There are two ways to make HTTP requests:
|
|
1981
1981
|
|
|
1982
|
-
1. **Shorthand HTTP Requests** -
|
|
1983
|
-
2. **Manual HTTP Requests** - you
|
|
1982
|
+
1. [**Shorthand HTTP Requests**](#shorthand-http-requests) - Easy to use, but limits what you can control. Best for simple requests.
|
|
1983
|
+
2. [**Manual HTTP Requests**](#manual-http-requests) - Gives you full control over the request and response.
|
|
1984
1984
|
|
|
1985
|
-
|
|
1985
|
+
Use these helper constructs to reduce boilerplate:
|
|
1986
1986
|
|
|
1987
|
-
1. `requestTemplate`
|
|
1988
|
-
2. `beforeRequest` middleware
|
|
1989
|
-
3. `afterResponse` middleware
|
|
1987
|
+
1. `requestTemplate` - an object literal of [HTTP request options](#http-request-options) that will be merged with every request.
|
|
1988
|
+
2. `beforeRequest` - [middleware](#using-http-middleware) that mutates every request before it is sent.
|
|
1989
|
+
3. `afterResponse` - [middleware](#using-http-middleware) that mutates every response before it is completed.
|
|
1990
1990
|
|
|
1991
1991
|
> Note: you can install any HTTP client you like - but this is greatly discouraged as you lose [automatic HTTP logging](#http-logging) and middleware.
|
|
1992
1992
|
|
|
1993
1993
|
### Shorthand HTTP Requests
|
|
1994
1994
|
|
|
1995
|
-
For simple HTTP requests that do not require special pre or post
|
|
1995
|
+
For simple HTTP requests that do not require special pre- or post-processing, you can specify the [HTTP request options](#http-request-options) as an object literal in your app definition.
|
|
1996
1996
|
|
|
1997
1997
|
This features:
|
|
1998
1998
|
|
|
@@ -2002,8 +2002,8 @@ This features:
|
|
|
2002
2002
|
|
|
2003
2003
|
```js
|
|
2004
2004
|
const triggerShorthandRequest = {
|
|
2005
|
-
method: 'GET',
|
|
2006
2005
|
url: 'https://{{bundle.authData.subdomain}}.example.com/v2/api/recipes.json',
|
|
2006
|
+
method: 'GET',
|
|
2007
2007
|
params: {
|
|
2008
2008
|
sort_by: 'id',
|
|
2009
2009
|
sort_order: 'DESC',
|
|
@@ -2025,28 +2025,36 @@ const App = {
|
|
|
2025
2025
|
|
|
2026
2026
|
```
|
|
2027
2027
|
|
|
2028
|
-
In the URL above, `{{bundle.authData.subdomain}}` is automatically replaced with the live value from the bundle. If the call returns a non 2xx return code, an error is automatically raised. The response body is automatically parsed as JSON and returned.
|
|
2028
|
+
In the URL above, `{{bundle.authData.subdomain}}` is automatically replaced with the live value from the bundle. If the call returns a non 2xx return code, an error is automatically raised. The response body is automatically parsed as JSON or form-encoded and returned.
|
|
2029
2029
|
|
|
2030
2030
|
An error will be raised if the response cannot be parsed as JSON or form-encoded. To use shorthand requests with other response types, add [middleware](#using-http-middleware) that sets `response.data` to the parsed response.
|
|
2031
2031
|
|
|
2032
2032
|
### Manual HTTP Requests
|
|
2033
2033
|
|
|
2034
|
-
|
|
2034
|
+
Use this when you need full control over the request/response. For example:
|
|
2035
|
+
|
|
2036
|
+
1. To do processing (usually involving [`bundle.inputData`](#bundleinputdata)) before a request is made
|
|
2037
|
+
2. To do processing of an API's response before you return data to Zapier
|
|
2038
|
+
3. To process an unusual response type, such as XML
|
|
2035
2039
|
|
|
2036
|
-
To make a manual
|
|
2040
|
+
To make a manual request, pass your [request options](#http-request-options) to `z.request()` then use the resulting [response object](#http-response-object) to return the data you want:
|
|
2037
2041
|
|
|
2038
2042
|
```js
|
|
2039
|
-
const
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2043
|
+
const listRecipes = async (z, bundle) => {
|
|
2044
|
+
// Custom processing of bundle.inputData would go here...
|
|
2045
|
+
|
|
2046
|
+
const httpRequestOptions = {
|
|
2047
|
+
url: 'https://{{bundle.authData.subdomain}}.example.com/v2/api/recipes.json',
|
|
2048
|
+
method: 'GET',
|
|
2049
|
+
params: {
|
|
2050
|
+
cuisine: bundle.inputData.cuisine,
|
|
2044
2051
|
},
|
|
2045
2052
|
};
|
|
2046
|
-
const response = await z.request(
|
|
2053
|
+
const response = await z.request(httpRequestOptions);
|
|
2054
|
+
const recipes = response.data;
|
|
2055
|
+
|
|
2056
|
+
// Custom processing of recipes would go here...
|
|
2047
2057
|
|
|
2048
|
-
const recipes = response.data; // or response.json if you're using core v9 or older
|
|
2049
|
-
// You can do any custom processing of recipes here...
|
|
2050
2058
|
return recipes;
|
|
2051
2059
|
};
|
|
2052
2060
|
|
|
@@ -2057,7 +2065,7 @@ const App = {
|
|
|
2057
2065
|
// ...
|
|
2058
2066
|
operation: {
|
|
2059
2067
|
// ...
|
|
2060
|
-
perform:
|
|
2068
|
+
perform: listRecipes,
|
|
2061
2069
|
},
|
|
2062
2070
|
},
|
|
2063
2071
|
},
|
|
@@ -2065,6 +2073,8 @@ const App = {
|
|
|
2065
2073
|
|
|
2066
2074
|
```
|
|
2067
2075
|
|
|
2076
|
+
Manual requests perform lazy `{{curly}}` replacement. In the URL above, `{{bundle.authData.subdomain}}` is automatically replaced with the live value from the bundle.
|
|
2077
|
+
|
|
2068
2078
|
#### POST and PUT Requests
|
|
2069
2079
|
|
|
2070
2080
|
To POST or PUT data to your API you can do this:
|
|
@@ -2113,11 +2123,9 @@ const App = {
|
|
|
2113
2123
|
|
|
2114
2124
|
### Using HTTP middleware
|
|
2115
2125
|
|
|
2116
|
-
|
|
2126
|
+
To process all HTTP requests in a certain way, use the `beforeRequest` and `afterResponse` middleware functions.
|
|
2117
2127
|
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
Try putting them in your app definition:
|
|
2128
|
+
Middleware functions go in your app definition:
|
|
2121
2129
|
|
|
2122
2130
|
```js
|
|
2123
2131
|
const addHeader = (request, z, bundle) => {
|
|
@@ -2174,6 +2182,8 @@ Here is the full request lifecycle when you call `z.request({...})`:
|
|
|
2174
2182
|
|
|
2175
2183
|
The resulting response object is returned from `z.request()`.
|
|
2176
2184
|
|
|
2185
|
+
> Example App: check out https://github.com/zapier/zapier-platform/tree/master/example-apps/middleware for a working example app using HTTP middleware.
|
|
2186
|
+
|
|
2177
2187
|
#### Error Response Handling
|
|
2178
2188
|
|
|
2179
2189
|
Since `v10.0.0`, `z.request()` calls `response.throwForStatus()` before it returns a response. You can disable automatic error throwing by setting `skipThrowForStatus` on the request object:
|
|
@@ -2219,13 +2229,13 @@ This behavior has changed periodically across major versions, which changes how/
|
|
|
2219
2229
|
|
|
2220
2230
|

|
|
2221
2231
|
|
|
2222
|
-
Ensure you're handling errors correctly for your platform version. The latest released version is **12.0.
|
|
2232
|
+
Ensure you're handling errors correctly for your platform version. The latest released version is **12.0.3**.
|
|
2223
2233
|
|
|
2224
2234
|
### HTTP Request Options
|
|
2225
2235
|
|
|
2226
|
-
Shorthand requests and manual
|
|
2236
|
+
[Shorthand requests](#shorthand-http-requests) and [manual requests](#manual-http-requests) support the following HTTP `options`:
|
|
2227
2237
|
|
|
2228
|
-
* `url`: HTTP url, you can provide it
|
|
2238
|
+
* `url`: HTTP url, you can provide it as a separate argument (`z.request(url, options)`) or as part of the `options` object (`z.request({url: url, ...})`).
|
|
2229
2239
|
* `method`: HTTP method, default is `GET`.
|
|
2230
2240
|
* `headers`: request headers object, format `{'header-key': 'header-value'}`.
|
|
2231
2241
|
* `params`: URL query params object, format `{'query-key': 'query-value'}`.
|
|
@@ -2286,7 +2296,7 @@ const response = await z.request({
|
|
|
2286
2296
|
// options
|
|
2287
2297
|
});
|
|
2288
2298
|
|
|
2289
|
-
// A bunch of examples
|
|
2299
|
+
// A bunch of examples for demonstration
|
|
2290
2300
|
response.status;
|
|
2291
2301
|
response.headers['Content-Type'];
|
|
2292
2302
|
response.getHeader('content-type');
|
|
@@ -2502,7 +2512,7 @@ module.exports = App;
|
|
|
2502
2512
|
|
|
2503
2513
|
```
|
|
2504
2514
|
|
|
2505
|
-
>
|
|
2515
|
+
> To create a new integration for handling files, run `zapier init [your app name] --template files`. You can also check out our working example app [here](https://github.com/zapier/zapier-platform/tree/master/example-apps/files).
|
|
2506
2516
|
|
|
2507
2517
|
|
|
2508
2518
|
## Logging
|
|
@@ -2669,14 +2679,14 @@ const yourAfterResponse = (resp) => {
|
|
|
2669
2679
|
|
|
2670
2680
|
## Testing
|
|
2671
2681
|
|
|
2672
|
-
You can write unit tests for your Zapier
|
|
2682
|
+
You can write unit tests for your Zapier integration that run locally, outside of the Zapier editor.
|
|
2673
2683
|
You can run these tests in a CI tool like [Travis](https://travis-ci.com/).
|
|
2674
2684
|
|
|
2675
2685
|
### Writing Unit Tests
|
|
2676
2686
|
|
|
2677
|
-
|
|
2687
|
+
From v10 of `zapier-platform-cli`, we recommend using the [Jest](https://jestjs.io/) testing framework. After running `zapier init` you should find an example test to start from in the `test` directory.
|
|
2678
2688
|
|
|
2679
|
-
> Note: On v9, the recommendation was [Mocha](https://mochajs.org/). You can still use
|
|
2689
|
+
> Note: On v9, the recommendation was [Mocha](https://mochajs.org/). You can still use Mocha if you prefer.
|
|
2680
2690
|
|
|
2681
2691
|
```js
|
|
2682
2692
|
/* globals describe, expect, test */
|
|
@@ -2693,7 +2703,7 @@ const appTester = zapier.createAppTester(App);
|
|
|
2693
2703
|
zapier.tools.env.inject();
|
|
2694
2704
|
|
|
2695
2705
|
describe('triggers', () => {
|
|
2696
|
-
test('
|
|
2706
|
+
test('new recipe', async () => {
|
|
2697
2707
|
const bundle = {
|
|
2698
2708
|
inputData: {
|
|
2699
2709
|
style: 'mediterranean',
|
|
@@ -2701,7 +2711,7 @@ describe('triggers', () => {
|
|
|
2701
2711
|
};
|
|
2702
2712
|
|
|
2703
2713
|
const results = await appTester(
|
|
2704
|
-
App.triggers.
|
|
2714
|
+
App.triggers.recipe.operation.perform,
|
|
2705
2715
|
bundle
|
|
2706
2716
|
);
|
|
2707
2717
|
expect(results.length).toBeGreaterThan(1);
|
|
@@ -2727,8 +2737,8 @@ const App = require('../index');
|
|
|
2727
2737
|
const appTester = zapier.createAppTester(App);
|
|
2728
2738
|
|
|
2729
2739
|
describe('triggers', () => {
|
|
2730
|
-
test('
|
|
2731
|
-
const
|
|
2740
|
+
test('new recipe', async () => {
|
|
2741
|
+
const adHocResult = await appTester(
|
|
2732
2742
|
// your in-line function takes the same [z, bundle] arguments as normal
|
|
2733
2743
|
async (z, bundle) => {
|
|
2734
2744
|
// requests are made using your integration's actual middleware
|
|
@@ -2759,8 +2769,8 @@ describe('triggers', () => {
|
|
|
2759
2769
|
}
|
|
2760
2770
|
);
|
|
2761
2771
|
|
|
2762
|
-
expect(
|
|
2763
|
-
expect(
|
|
2772
|
+
expect(adHocResult.someHash).toEqual('a5beb6624e092adf7be31176c3079e64');
|
|
2773
|
+
expect(adHocResult.data).toEqual({ whatever: true });
|
|
2764
2774
|
|
|
2765
2775
|
// ... rest of test
|
|
2766
2776
|
});
|
|
@@ -2770,7 +2780,7 @@ describe('triggers', () => {
|
|
|
2770
2780
|
|
|
2771
2781
|
### Mocking Requests
|
|
2772
2782
|
|
|
2773
|
-
|
|
2783
|
+
It's useful to test your code without actually hitting any external services. [Nock](https://github.com/node-nock/nock) is a Node.js utility that intercepts requests before they ever leave your computer. You can specify a response code, body, headers, and more. It works out of the box with `z.request` by setting up your `nock` before calling `appTester`.
|
|
2774
2784
|
|
|
2775
2785
|
```js
|
|
2776
2786
|
/* globals describe, expect, test */
|
|
@@ -2783,7 +2793,7 @@ const appTester = zapier.createAppTester(App);
|
|
|
2783
2793
|
const nock = require('nock');
|
|
2784
2794
|
|
|
2785
2795
|
describe('triggers', () => {
|
|
2786
|
-
test('
|
|
2796
|
+
test('new recipe', async () => {
|
|
2787
2797
|
const bundle = {
|
|
2788
2798
|
inputData: {
|
|
2789
2799
|
style: 'mediterranean',
|
|
@@ -2814,7 +2824,7 @@ describe('triggers', () => {
|
|
|
2814
2824
|
|
|
2815
2825
|
```
|
|
2816
2826
|
|
|
2817
|
-
|
|
2827
|
+
Here's more info about nock and its usage in the [README](https://github.com/node-nock/nock/blob/master/README.md).
|
|
2818
2828
|
|
|
2819
2829
|
### Running Unit Tests
|
|
2820
2830
|
|
|
@@ -2857,11 +2867,11 @@ zapier test
|
|
|
2857
2867
|
|
|
2858
2868
|
### Testing in Your CI
|
|
2859
2869
|
|
|
2860
|
-
Whether you use Travis, Circle, Jenkins, or
|
|
2870
|
+
Whether you use Travis, Circle, Jenkins, or another service, we aim to make it painless to test in an automated environment.
|
|
2861
2871
|
|
|
2862
|
-
Behind the scenes `zapier test`
|
|
2872
|
+
Behind the scenes `zapier test` does a standard `npm test`, which could be [Jest](https://jestjs.io/) or [Mocha](https://mochajs.org/), based on your project setup.
|
|
2863
2873
|
|
|
2864
|
-
This makes it
|
|
2874
|
+
This makes it straightforward to integrate into your testing interface. For example, if you want to test with [Travis CI](https://travis-ci.com/), the `.travis.yml` would look something like this:
|
|
2865
2875
|
|
|
2866
2876
|
```yaml
|
|
2867
2877
|
language: node_js
|
|
@@ -2871,13 +2881,13 @@ before_script: npm install -g zapier-platform-cli
|
|
|
2871
2881
|
script: CLIENT_ID=1234 CLIENT_SECRET=abcd zapier test
|
|
2872
2882
|
```
|
|
2873
2883
|
|
|
2874
|
-
You can substitute `zapier test` with `npm test`, or a direct call to `node_modules/.bin/jest`.
|
|
2884
|
+
You can substitute `zapier test` with `npm test`, or a direct call to `node_modules/.bin/jest`. We recommend putting environment variables directly into the configuration screens Jenkins, Travis, or other services provide.
|
|
2875
2885
|
|
|
2876
|
-
|
|
2886
|
+
Alternatively to reading the deploy key from root (the default location), you may set the `ZAPIER_DEPLOY_KEY` environment variable to run privileged commands without the human input needed for `zapier login`. We suggest encrypting your deploy key in the manner your CI provides (such as [these instructions](https://docs.travis-ci.com/user/environment-variables/#Defining-encrypted-variables-in-.travis.yml), for Travis).
|
|
2877
2887
|
|
|
2878
2888
|
### Debugging Tests
|
|
2879
2889
|
|
|
2880
|
-
Sometimes tests aren't enough and you may want to step through your code and set breakpoints. The testing suite is a regular Node.js process, so debugging it doesn't take anything special. Because we recommend `jest` for testing, these instructions will outline steps for debugging w/ jest, but other test runners will work similarly. You can also refer to [Jest's own docs on the subject](https://jestjs.io/docs/en/troubleshooting#tests-are-failing-and-you-dont-know-why).
|
|
2890
|
+
Sometimes tests aren't enough, and you may want to step through your code and set breakpoints. The testing suite is a regular Node.js process, so debugging it doesn't take anything special. Because we recommend `jest` for testing, these instructions will outline steps for debugging w/ jest, but other test runners will work similarly. You can also refer to [Jest's own docs on the subject](https://jestjs.io/docs/en/troubleshooting#tests-are-failing-and-you-dont-know-why).
|
|
2881
2891
|
|
|
2882
2892
|
To start, add the following line to the `scripts` section of your `package.json`:
|
|
2883
2893
|
|
|
@@ -2928,7 +2938,7 @@ After a few seconds, you'll see your code, the `debugger` statement, and info ab
|
|
|
2928
2938
|
|
|
2929
2939
|

|
|
2930
2940
|
|
|
2931
|
-
|
|
2941
|
+
Debugging combined with thorough unit tests will hopefully equip you in keeping your Zapier integration in smooth working order.
|
|
2932
2942
|
|
|
2933
2943
|
## Using `npm` Modules
|
|
2934
2944
|
|
|
@@ -3049,7 +3059,7 @@ zapier push
|
|
|
3049
3059
|
|
|
3050
3060
|
There are a lot of details left out - check out the full example app for a working setup.
|
|
3051
3061
|
|
|
3052
|
-
>
|
|
3062
|
+
> To create a new integration with Babel, run `zapier init [your app name] --template babel`. You can also check out our working example app [here](https://github.com/zapier/zapier-platform/tree/master/example-apps/babel).
|
|
3053
3063
|
|
|
3054
3064
|
## FAQs
|
|
3055
3065
|
|
|
@@ -3083,7 +3093,7 @@ Not natively, but it can! Users have reported that the following `npm` modules a
|
|
|
3083
3093
|
* [xml2js](https://github.com/Leonidas-from-XIV/node-xml2js)
|
|
3084
3094
|
* [fast-xml-parser](https://github.com/NaturalIntelligence/fast-xml-parser)
|
|
3085
3095
|
|
|
3086
|
-
Since core v10, it's possible for [shorthand requests](shorthand-http-requests) to parse XML. Use an `afterResponse` [middleware](using-http-middleware) that sets `response.data` to the parsed XML:
|
|
3096
|
+
Since core v10, it's possible for [shorthand requests](#shorthand-http-requests) to parse XML. Use an `afterResponse` [middleware](#using-http-middleware) that sets `response.data` to the parsed XML:
|
|
3087
3097
|
|
|
3088
3098
|
```js
|
|
3089
3099
|
const xml = require('pixl-xml');
|
|
@@ -3205,7 +3215,7 @@ To understand search-powered fields, we have to have a good understanding of dyn
|
|
|
3205
3215
|
|
|
3206
3216
|
When users are selecting specific resources (for instance, a Google Sheet), it's important they're able to select the exact sheet they want. Instead of referencing the sheet by name (which may change), we match via `id` instead. Rather than directing the user copy and paste an id for every item they might encounter, there is the notion of a **dynamic dropdown**. A dropdown is a trigger that returns a list of resources. It can pull double duty and use its results to power another trigger, search, or action in the same app. It provides a list of ids with labels that show the item's name:
|
|
3207
3217
|
|
|
3208
|
-

|
|
3209
3219
|
|
|
3210
3220
|
The field's value reaches your app as an id. You define this connection with the `dynamic` property, which is a string: `trigger_key.id_key.label_key`. This approach works great if the user setting up the Zap always wants the Zap to use the same spreadsheet. They specify the id during setup and the Zap runs happily.
|
|
3211
3221
|
|
|
@@ -3218,7 +3228,7 @@ The field's value reaches your app as an id. You define this connection with the
|
|
|
3218
3228
|
|
|
3219
3229
|
If the connection between steps 3 and 4 is a common one, you can indicate that in your field by specifying `search` as a `search_key.id_key`. When paired **with a dynamic dropdown**, this will add a button to the editor that will add the search step to the user's Zap and map the id field correctly.
|
|
3220
3230
|
|
|
3221
|
-

|
|
3222
3232
|
|
|
3223
3233
|
This is paired most often with "update" actions, where a required parameter will be a resource id.
|
|
3224
3234
|
|
|
@@ -3404,7 +3414,7 @@ Broadly speaking, all releases will continue to work indefinitely. While you nev
|
|
|
3404
3414
|
For more info about which Node versions are supported, see [the faq](#how-do-i-manually-set-the-nodejs-version-to-run-my-app-with).
|
|
3405
3415
|
|
|
3406
3416
|
<!-- TODO: if we decouple releases, change this -->
|
|
3407
|
-
The most recently released version of `cli` and `core` is **12.0.
|
|
3417
|
+
The most recently released version of `cli` and `core` is **12.0.3**. You can see the versions you're working with by running `zapier -v`.
|
|
3408
3418
|
|
|
3409
3419
|
To update `cli`, run `npm install -g zapier-platform-cli`.
|
|
3410
3420
|
|