diff --git a/docs/index.html b/docs/index.html index 29ad2ffd7..f5ceb27ae 100644 --- a/docs/index.html +++ b/docs/index.html @@ -3320,9 +3320,7 @@

Manual HTTP Requests

return z .request('https://example.com/api/v2/recipes.json', customHttpOptions) .then(response => { - if (response.status >= 300) { - throw new Error(`Unexpected status code ${response.status}`); - } + response.throwForStatus(); const recipes = z.JSON.parse(response.content); // do any custom processing of recipes here... @@ -3384,8 +3382,14 @@

POST and PUT Requests

return z .request('https://example.com/api/v2/recipes.json', options) .then(response => { + // throw and try to extract message from standard error responses + response.throwForStatus(); if (response.status !== 201) { - throw new Error(`Unexpected status code ${response.status}`); + throw new z.errors.Error( + `Unexpected status code ${response.status}`, + 'CreateRecipeError', + response.status + ); } }); } @@ -3432,8 +3436,14 @@

Using HTTP middleware

const mustBe200 = (response, z, bundle) => { if (response.status !== 200) { - throw new Error(`Unexpected status code ${response.status}`); + throw new z.errors.Error( + `Unexpected status code ${response.status}`, + 'UnexpectedStatus', + response.status + ); } + // throw for standard error statuses + response.throwForStatus(); return response; }; diff --git a/example-apps/babel/src/authentication.js b/example-apps/babel/src/authentication.js index 0c897aa38..e54dd647d 100644 --- a/example-apps/babel/src/authentication.js +++ b/example-apps/babel/src/authentication.js @@ -9,7 +9,11 @@ const test = async (z /*, bundle */) => { // This method can return any truthy value to indicate the credentials are valid. // Raise an error to show if (response.status === 401) { - throw new Error('The username and/or password you supplied is incorrect'); + throw new z.errors.Error( + 'The username and/or password you supplied is incorrect', + 'AuthenticationError', + response.status + ); } return response; }; diff --git a/example-apps/basic-auth/authentication.js b/example-apps/basic-auth/authentication.js index fc09e87e8..aa2728e8e 100644 --- a/example-apps/basic-auth/authentication.js +++ b/example-apps/basic-auth/authentication.js @@ -11,8 +11,10 @@ const test = (z /*, bundle */) => { }) .then(response => { if (response.status === 401) { - throw new Error( - 'The username and/or password you supplied is incorrect' + throw new z.errors.Error( + 'The username and/or password you supplied is incorrect', + 'AuthenticationError', + response.status ); } return response; diff --git a/example-apps/custom-auth/authentication.js b/example-apps/custom-auth/authentication.js index 609e657e7..9a5c9bf7a 100644 --- a/example-apps/custom-auth/authentication.js +++ b/example-apps/custom-auth/authentication.js @@ -11,7 +11,11 @@ const testAuth = (z /*, bundle */) => { }) .then(response => { if (response.status === 401) { - throw new Error('The API Key you supplied is invalid'); + throw new z.errors.Error( + 'The API Key you supplied is invalid', + 'AuthenticationError', + response.status + ); } return response.json; }); diff --git a/example-apps/digest-auth/authentication.js b/example-apps/digest-auth/authentication.js index 31359881f..2a442e979 100644 --- a/example-apps/digest-auth/authentication.js +++ b/example-apps/digest-auth/authentication.js @@ -1,4 +1,4 @@ -const test = (z /*, bundle*/) => { +const test = (z /*, bundle */) => { // Normally you want to make a request to an endpoint that is either specifically designed to test auth, or one that // every user will have access to, such as an account or profile endpoint like /me. // In this example, we'll hit httpbin, which validates the Authorization Header against the arguments passed in the URL path @@ -11,8 +11,10 @@ const test = (z /*, bundle*/) => { }) .then(response => { if (response.status === 401) { - throw new Error( - 'The username and/or password you supplied is incorrect' + throw new z.errors.Error( + 'The username and/or password you supplied is incorrect', + 'AuthenticationError', + response.status ); } return response; diff --git a/example-apps/github/index.js b/example-apps/github/index.js index 8698f1799..1cd577baa 100644 --- a/example-apps/github/index.js +++ b/example-apps/github/index.js @@ -5,7 +5,11 @@ const authentication = require('./authentication'); const handleHTTPError = (response, z) => { if (response.status >= 400) { - throw new Error(`Unexpected status code ${response.status}`); + throw new z.errors.Error( + `Unexpected status code ${response.status}`, + 'StatusError', + response.status + ); } return response; }; diff --git a/example-apps/oauth2/authentication.js b/example-apps/oauth2/authentication.js index a9be43881..82a32fee5 100644 --- a/example-apps/oauth2/authentication.js +++ b/example-apps/oauth2/authentication.js @@ -17,7 +17,11 @@ const getAccessToken = (z, bundle) => { // Needs to return at minimum, `access_token`, and if your app also does refresh, then `refresh_token` too return promise.then(response => { if (response.status !== 200) { - throw new Error('Unable to fetch access token: ' + response.content); + throw new z.errors.Error( + 'Unable to fetch access token: ' + response.content, + 'GetAccessTokenError', + response.status + ); } const result = JSON.parse(response.content); @@ -46,7 +50,11 @@ const refreshAccessToken = (z, bundle) => { // return it here to update the user's auth on Zapier. return promise.then(response => { if (response.status !== 200) { - throw new Error('Unable to fetch access token: ' + response.content); + throw new z.errors.Error( + 'Unable to fetch access token: ' + response.content, + 'RefreshAccessTokenError', + response.status + ); } const result = JSON.parse(response.content); @@ -68,7 +76,11 @@ const testAuth = (z /*, bundle */) => { // Raise an error to show return promise.then(response => { if (response.status === 401) { - throw new Error('The access token you supplied is not valid'); + throw new z.errors.Error( + 'The access token you supplied is not valid', + 'AuthenticationError', + response.status + ); } return z.JSON.parse(response.content); }); diff --git a/example-apps/onedrive/authentication.js b/example-apps/onedrive/authentication.js index 78bbf1635..fd246620e 100644 --- a/example-apps/onedrive/authentication.js +++ b/example-apps/onedrive/authentication.js @@ -51,7 +51,11 @@ const getAccessToken = (z, bundle) => { return promise.then((response) => { if (response.status !== 200) { - throw new Error('Unable to fetch access token: ' + response.content) + throw new z.errors.Error( + 'Unable to fetch access token: ' + response.content, + 'GetAccessTokenError', + response.status + ) } const result = z.JSON.parse(response.content) @@ -89,7 +93,11 @@ const refreshAccessToken = (z, bundle) => { return promise.then((response) => { if (response.status !== 200) { - throw new Error('Unable to fetch access token: ' + response.content) + throw new z.errors.Error( + 'Unable to fetch access token: ' + response.content, + 'RefreshAccessTokenError', + response.status + ) } const result = z.JSON.parse(response.content) @@ -112,7 +120,11 @@ const testAuth = (z) => { return promise.then((response) => { if (response.status === 401) { - throw new Error('The access token you supplied is not valid') + throw new z.errors.Error( + 'The access token you supplied is not valid', + 'AuthenticationError', + response.status + ) } return z.JSON.parse(response.content) }) diff --git a/example-apps/onedrive/resources/base-item.js b/example-apps/onedrive/resources/base-item.js index b6c396b1f..e807f1577 100644 --- a/example-apps/onedrive/resources/base-item.js +++ b/example-apps/onedrive/resources/base-item.js @@ -20,7 +20,7 @@ const getItem = (itemType, z, bundle) => { } return z .request(options) - .then(_.partial(parseResponse, itemType)) + .then(_.partial(parseResponse, z, itemType)) .then((item) => cleanupPaths([item])[0]) .then((item) => { if (item.file) { @@ -47,7 +47,7 @@ const listItems = (itemType, z, bundle) => { return z .request(options) - .then(_.partial(parseResponse, itemType)) + .then(_.partial(parseResponse, z, itemType)) .then(cleanupPaths) .then((items) => { items.forEach((item) => { @@ -78,7 +78,7 @@ const searchItem = (itemType, z, bundle) => { return z .request(options) - .then(_.partial(parseResponse, itemType)) + .then(_.partial(parseResponse, z, itemType)) .then(cleanupPaths) .catch(handleError) } @@ -114,7 +114,11 @@ const handleCreateWithSession = ( }) .then((response) => { if (response.status >= 300) { - throw new Error('Unable to start an upload session.') + throw new z.errors.Error( + 'Unable to start an upload session.', + 'UploadSessionError', + response.status + ) } const uploadUrl = z.JSON.parse(response.content).uploadUrl diff --git a/example-apps/onedrive/resources/folder.js b/example-apps/onedrive/resources/folder.js index b929715b2..f8ae053d5 100644 --- a/example-apps/onedrive/resources/folder.js +++ b/example-apps/onedrive/resources/folder.js @@ -45,7 +45,7 @@ const createFolder = (z, bundle) => { 'content-type': 'application/json' } }) - .then(_.partial(parseResponse, 'folder')) + .then(_.partial(parseResponse, z, 'folder')) .then(cleanupPaths) .catch(handleError) } diff --git a/example-apps/onedrive/utils.js b/example-apps/onedrive/utils.js index c5a776093..f118bb522 100644 --- a/example-apps/onedrive/utils.js +++ b/example-apps/onedrive/utils.js @@ -8,7 +8,7 @@ const contentDisposition = require('content-disposition') // on the OneDrive API. We intentionally don't set it up as an `afterResposne` // handler because not *all* calls need it (i.e. the auth test and file create), // so we break it out and share the code this way instead. -const parseResponse = (type, response) => { +const parseResponse = (z, type, response) => { let results = [] if (response.status >= 200 && response.status < 300) { @@ -19,7 +19,7 @@ const parseResponse = (type, response) => { results = results.value } } else { - throw new Error(response.content) + throw new z.errors.Error(response.content, null, response.status) } // Only return files or folders, according to type diff --git a/example-apps/session-auth/authentication.js b/example-apps/session-auth/authentication.js index 58c6bd350..27bb8b8fa 100644 --- a/example-apps/session-auth/authentication.js +++ b/example-apps/session-auth/authentication.js @@ -10,7 +10,11 @@ const testAuth = (z /*, bundle */) => { // Raise an error to show return promise.then(response => { if (response.status === 401) { - throw new Error('The Session Key you supplied is invalid'); + throw new z.errors.Error( + 'The Session Key you supplied is invalid', + 'AuthenticationError', + response.status + ); } return response; }); @@ -28,7 +32,11 @@ const getSessionKey = (z, bundle) => { return promise.then(response => { if (response.status === 401) { - throw new Error('The username/password you supplied is invalid'); + throw new z.errors.Error( + 'The username/password you supplied is invalid', + 'GetSessionKeyError', + response.status + ); } const json = JSON.parse(response.content); return { diff --git a/example-apps/typescript/src/authentication.ts b/example-apps/typescript/src/authentication.ts index f2c40264e..5e24ca75c 100644 --- a/example-apps/typescript/src/authentication.ts +++ b/example-apps/typescript/src/authentication.ts @@ -11,7 +11,7 @@ const test = async (z: ZObject /*, bundle*/) => { // This method can return any truthy value to indicate the credentials are valid. // Raise an error to show if (response.status === 401) { - throw new Error("The username and/or password you supplied is incorrect"); + throw new z.errors.Error("The username and/or password you supplied is incorrect", "AuthenticationError", response.status); } return response; }; diff --git a/examples/auth/basic.js b/examples/auth/basic.js index 3d6d333f2..f229b1515 100644 --- a/examples/auth/basic.js +++ b/examples/auth/basic.js @@ -7,7 +7,11 @@ const test = async (z /*, bundle */) => { if (response.status === 401) { // This message is surfaced to the user - throw new Error('The username and/or password you supplied is incorrect'); + throw new z.errors.Error( + 'The username and/or password you supplied is incorrect', + 'AuthenticationError', + response.status + ); } // anything truthy indicates the credentials are valid. Data returned from this test is available to the connection label diff --git a/examples/auth/custom.js b/examples/auth/custom.js index c7628c512..93fd05dea 100644 --- a/examples/auth/custom.js +++ b/examples/auth/custom.js @@ -7,7 +7,11 @@ const test = async (z /*, bundle */) => { if (response.status === 401) { // This message is surfaced to the user - throw new Error('The API Key you supplied is invalid'); + throw new z.errors.Error( + 'The API Key you supplied is invalid', + 'AuthenticationError', + response.status + ); } return response; }; diff --git a/examples/auth/digest.js b/examples/auth/digest.js index 0ac962296..3820298e7 100644 --- a/examples/auth/digest.js +++ b/examples/auth/digest.js @@ -9,7 +9,11 @@ const test = async (z /*, bundle */) => { if (response.status === 401) { // This message is surfaced to the user - throw new Error('The username and/or password you supplied is incorrect'); + throw new z.errors.Error( + 'The username and/or password you supplied is incorrect', + 'AuthenticationError', + response.status + ); } // anything truthy indicates the credentials are valid. Data returned from this test is available to the connection label diff --git a/examples/auth/oauth2.js b/examples/auth/oauth2.js index 61f9190ee..01e0a8100 100644 --- a/examples/auth/oauth2.js +++ b/examples/auth/oauth2.js @@ -20,7 +20,11 @@ const getAccessToken = async (z, bundle) => { // Needs to return `access_token`. // If your app does an app refresh, then `refresh_token` should be returned as well if (response.status !== 200) { - throw new Error('Unable to fetch access token: ' + response.content); + throw new z.error.Error( + 'Unable to fetch access token: ' + response.content, + 'GetAccessTokenError', + response.status + ); } return { @@ -50,7 +54,11 @@ const refreshAccessToken = async (z, bundle) => { // If the refresh token stays constant, no need to return it // If the refresh token changes, return it here to update the stored value in Zapier if (response.status !== 200) { - throw new Error('Unable to fetch access token: ' + response.content); + throw new z.errors.Error( + 'Unable to fetch access token: ' + response.content, + 'RefreshAccessTokenError', + response.status + ); } return { @@ -77,7 +85,11 @@ const testAuth = async (z /*, bundle */) => { if (response.status === 401) { // This message is surfaced to the user - throw new Error('The access token you supplied is not valid'); + throw new z.errors.Error( + 'The access token you supplied is not valid', + 'AuthenticationError', + response.status + ); } // This method can return any truthy value to indicate the credentials are valid. diff --git a/examples/auth/session.js b/examples/auth/session.js index 8e56f7268..3d217744e 100644 --- a/examples/auth/session.js +++ b/examples/auth/session.js @@ -7,7 +7,11 @@ const test = async (z /*, bundle */) => { if (response.status === 401) { // This message is surfaced to the user - throw new Error('The Session Key you supplied is invalid'); + throw new z.errors.Error( + 'The Session Key you supplied is invalid', + 'AuthenticationError', + response.status + ); } // This method can return any truthy value to indicate the credentials are valid. @@ -26,7 +30,11 @@ const getSessionKey = async (z, bundle) => { }); if (response.status === 401) { - throw new Error('The username/password you supplied is invalid'); + throw new z.errors.Error( + 'The username/password you supplied is invalid', + 'GetSessionKeyError', + response.status + ); } return { diff --git a/packages/cli/README.md b/packages/cli/README.md index b6532c478..134c115ba 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -1932,9 +1932,7 @@ const listExample = (z, bundle) => { return z .request('https://example.com/api/v2/recipes.json', customHttpOptions) .then(response => { - if (response.status >= 300) { - throw new Error(`Unexpected status code ${response.status}`); - } + response.throwForStatus(); const recipes = z.JSON.parse(response.content); // do any custom processing of recipes here... @@ -1985,8 +1983,14 @@ const App = { return z .request('https://example.com/api/v2/recipes.json', options) .then(response => { + // throw and try to extract message from standard error responses + response.throwForStatus(); if (response.status !== 201) { - throw new Error(`Unexpected status code ${response.status}`); + throw new z.errors.Error( + `Unexpected status code ${response.status}`, + 'CreateRecipeError', + response.status + ); } }); } @@ -2015,8 +2019,14 @@ const addHeader = (request, z, bundle) => { const mustBe200 = (response, z, bundle) => { if (response.status !== 200) { - throw new Error(`Unexpected status code ${response.status}`); + throw new z.errors.Error( + `Unexpected status code ${response.status}`, + 'UnexpectedStatus', + response.status + ); } + // throw for standard error statuses + response.throwForStatus(); return response; }; diff --git a/packages/cli/docs/index.html b/packages/cli/docs/index.html index 29ad2ffd7..f5ceb27ae 100644 --- a/packages/cli/docs/index.html +++ b/packages/cli/docs/index.html @@ -3320,9 +3320,7 @@

Manual HTTP Requests

return z .request('https://example.com/api/v2/recipes.json', customHttpOptions) .then(response => { - if (response.status >= 300) { - throw new Error(`Unexpected status code ${response.status}`); - } + response.throwForStatus(); const recipes = z.JSON.parse(response.content); // do any custom processing of recipes here... @@ -3384,8 +3382,14 @@

POST and PUT Requests

return z .request('https://example.com/api/v2/recipes.json', options) .then(response => { + // throw and try to extract message from standard error responses + response.throwForStatus(); if (response.status !== 201) { - throw new Error(`Unexpected status code ${response.status}`); + throw new z.errors.Error( + `Unexpected status code ${response.status}`, + 'CreateRecipeError', + response.status + ); } }); } @@ -3432,8 +3436,14 @@

Using HTTP middleware

const mustBe200 = (response, z, bundle) => { if (response.status !== 200) { - throw new Error(`Unexpected status code ${response.status}`); + throw new z.errors.Error( + `Unexpected status code ${response.status}`, + 'UnexpectedStatus', + response.status + ); } + // throw for standard error statuses + response.throwForStatus(); return response; }; diff --git a/packages/cli/snippets/manual-request.js b/packages/cli/snippets/manual-request.js index aee46f17b..2b68bbe9b 100644 --- a/packages/cli/snippets/manual-request.js +++ b/packages/cli/snippets/manual-request.js @@ -8,9 +8,7 @@ const listExample = (z, bundle) => { return z .request('https://example.com/api/v2/recipes.json', customHttpOptions) .then(response => { - if (response.status >= 300) { - throw new Error(`Unexpected status code ${response.status}`); - } + response.throwForStatus(); const recipes = z.JSON.parse(response.content); // do any custom processing of recipes here... diff --git a/packages/cli/snippets/middleware.js b/packages/cli/snippets/middleware.js index be5661546..051b7d895 100644 --- a/packages/cli/snippets/middleware.js +++ b/packages/cli/snippets/middleware.js @@ -5,8 +5,14 @@ const addHeader = (request, z, bundle) => { const mustBe200 = (response, z, bundle) => { if (response.status !== 200) { - throw new Error(`Unexpected status code ${response.status}`); + throw new z.errors.Error( + `Unexpected status code ${response.status}`, + 'UnexpectedStatus', + response.status + ); } + // throw for standard error statuses + response.throwForStatus(); return response; }; diff --git a/packages/cli/snippets/put.js b/packages/cli/snippets/put.js index 66b390e44..09576d7d5 100644 --- a/packages/cli/snippets/put.js +++ b/packages/cli/snippets/put.js @@ -20,8 +20,14 @@ const App = { return z .request('https://example.com/api/v2/recipes.json', options) .then(response => { + // throw and try to extract message from standard error responses + response.throwForStatus(); if (response.status !== 201) { - throw new Error(`Unexpected status code ${response.status}`); + throw new z.errors.Error( + `Unexpected status code ${response.status}`, + 'CreateRecipeError', + response.status + ); } }); }