zapier-platform-core 11.3.3 → 12.0.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zapier-platform-core",
3
- "version": "11.3.3",
3
+ "version": "12.0.2",
4
4
  "description": "The core SDK for CLI apps in the Zapier Developer Platform.",
5
5
  "repository": "zapier/zapier-platform",
6
6
  "homepage": "https://platform.zapier.com/",
@@ -50,7 +50,7 @@
50
50
  "node-fetch": "2.6.7",
51
51
  "oauth-sign": "0.9.0",
52
52
  "semver": "7.3.5",
53
- "zapier-platform-schema": "11.3.3"
53
+ "zapier-platform-schema": "12.0.2"
54
54
  },
55
55
  "devDependencies": {
56
56
  "adm-zip": "0.5.5",
package/src/execute.js CHANGED
@@ -11,7 +11,18 @@ const ZapierPromise = require('./tools/promise');
11
11
  const constants = require('./constants');
12
12
 
13
13
  const executeHttpRequest = (input, options) => {
14
- options = _.extend({}, options, constants.REQUEST_OBJECT_SHORTHAND_OPTIONS);
14
+ options = _.extend(
15
+ {},
16
+ // shorthand requests should always throw _unless_ the object specifically opts out
17
+ // this covers godzilla devs who use shorthand requests (most of them) that rely on the throwing behavior
18
+ // when we set the app-wide skip for everyone, we don't want their behavior to change
19
+ // so, this line takes precedence over the global setting, but not the local one (`options`)
20
+ {
21
+ skipThrowForStatus: false,
22
+ },
23
+ options,
24
+ constants.REQUEST_OBJECT_SHORTHAND_OPTIONS
25
+ );
15
26
  return input.z.request(options).then((response) => {
16
27
  if (response.data === undefined) {
17
28
  throw new Error(
@@ -2,9 +2,17 @@
2
2
 
3
3
  const _ = require('lodash');
4
4
  const querystring = require('querystring');
5
- const throwForStatus = require('./throw-for-status');
6
5
  const { replaceHeaders } = require('./middleware-utils');
7
6
  const { FORM_TYPE } = require('../../tools/http');
7
+ const errors = require('../../errors');
8
+
9
+ const _throwForStatus = (response) => {
10
+ // calling this always throws, regardless of the skipThrowForStatus value
11
+ // eslint-disable-next-line yoda
12
+ if (400 <= response.status && response.status < 600) {
13
+ throw new errors.ResponseError(response);
14
+ }
15
+ };
8
16
 
9
17
  const prepareRawResponse = (resp, request) => {
10
18
  // TODO: if !2xx should we go ahead and get response.content for them?
@@ -14,7 +22,11 @@ const prepareRawResponse = (resp, request) => {
14
22
  skipThrowForStatus: request.skipThrowForStatus,
15
23
  };
16
24
  const outResp = _.extend(resp, extendedResp, replaceHeaders(resp));
17
- outResp.throwForStatus = () => throwForStatus(outResp) && undefined;
25
+
26
+ outResp.throwForStatus = () => {
27
+ _throwForStatus(outResp);
28
+ };
29
+
18
30
  Object.defineProperty(outResp, 'content', {
19
31
  get: function () {
20
32
  throw new Error(
@@ -27,30 +39,36 @@ const prepareRawResponse = (resp, request) => {
27
39
  return outResp;
28
40
  };
29
41
 
30
- const prepareContentResponse = (resp, request) => {
42
+ const prepareContentResponse = async (resp, request) => {
31
43
  // TODO: does it make sense to not trim the signature? more equivalence to raw...
32
- return resp.text().then((content) => {
33
- // trim down the response signature a ton for simplicity
34
- const preppedResp = {
35
- status: resp.status,
36
- json: undefined,
37
- data: undefined,
38
- content: content,
39
- request: request,
40
- skipThrowForStatus: request.skipThrowForStatus,
41
- };
42
- const outResp = _.extend(preppedResp, replaceHeaders(resp));
43
- try {
44
- if (outResp.headers.get('content-type') === FORM_TYPE) {
45
- outResp.data = querystring.parse(content);
46
- } else {
47
- outResp.data = JSON.parse(content);
48
- outResp.json = JSON.parse(content); // DEPRECATED (not using reference to isolate)
49
- }
50
- } catch (_e) {}
51
- outResp.throwForStatus = () => throwForStatus(outResp) && undefined;
52
- return outResp;
53
- });
44
+ const content = await resp.text();
45
+
46
+ // trim down the response signature a ton for simplicity
47
+ const preppedResp = {
48
+ status: resp.status,
49
+ json: undefined,
50
+ data: undefined,
51
+ content: content,
52
+ request: request,
53
+ // only controls if _we_ call throwForStatus automatically
54
+ skipThrowForStatus: request.skipThrowForStatus,
55
+ };
56
+ const outResp = _.extend(preppedResp, replaceHeaders(resp));
57
+
58
+ try {
59
+ if (outResp.headers.get('content-type') === FORM_TYPE) {
60
+ outResp.data = querystring.parse(content);
61
+ } else {
62
+ outResp.data = JSON.parse(content);
63
+ outResp.json = JSON.parse(content); // DEPRECATED (not using reference to isolate)
64
+ }
65
+ } catch (_e) {}
66
+
67
+ outResp.throwForStatus = () => {
68
+ _throwForStatus(outResp);
69
+ };
70
+
71
+ return outResp;
54
72
  };
55
73
 
56
74
  // Provide a standardized plain JS responseObj for common consumption, or raw response for streaming.
@@ -58,11 +76,11 @@ const prepareResponse = (resp) => {
58
76
  const request = resp.input;
59
77
  delete resp.input;
60
78
 
61
- if (request.raw) {
62
- return prepareRawResponse(resp, request);
63
- } else {
64
- return prepareContentResponse(resp, request);
65
- }
79
+ const responseFunc = request.raw
80
+ ? prepareRawResponse
81
+ : prepareContentResponse;
82
+
83
+ return responseFunc(resp, request);
66
84
  };
67
85
 
68
86
  module.exports = prepareResponse;
@@ -0,0 +1,16 @@
1
+ 'use strict';
2
+
3
+ const { RefreshAuthError } = require('../../errors');
4
+
5
+ /**
6
+ * Raise a RefreshAuthError _before_ any other error handling happens. Behaves more closely to the 9.x behavior rather than 10.x
7
+ */
8
+ const throwForStaleAuth = (resp) => {
9
+ if (resp.status === 401) {
10
+ throw new RefreshAuthError();
11
+ }
12
+
13
+ return resp;
14
+ };
15
+
16
+ module.exports = throwForStaleAuth;
@@ -1,17 +1,10 @@
1
1
  'use strict';
2
2
 
3
- const errors = require('../../errors');
4
-
5
- const throwForStatus = (response) => {
6
- if (
7
- !response.skipThrowForStatus &&
8
- response.status >= 400 &&
9
- response.status < 600
10
- ) {
11
- throw new errors.ResponseError(response);
3
+ const throwForStatusMiddleware = (response) => {
4
+ if (!response.skipThrowForStatus) {
5
+ response.throwForStatus();
12
6
  }
13
-
14
7
  return response;
15
8
  };
16
9
 
17
- module.exports = throwForStatus;
10
+ module.exports = throwForStatusMiddleware;
@@ -113,7 +113,12 @@ const prepareRequest = function (req) {
113
113
  body: false,
114
114
  },
115
115
  replace: true, // always replace curlies
116
- skipThrowForStatus: false,
116
+ // read default from app flags, but always defer to the request object if the value was set
117
+ skipThrowForStatus: _.get(
118
+ input,
119
+ ['_zapier', 'app', 'flags', 'skipThrowForStatus'],
120
+ false
121
+ ),
117
122
  _addContext: () => {},
118
123
  });
119
124
 
@@ -64,6 +64,11 @@ const recurseReplaceBank = (obj, bank = {}) => {
64
64
 
65
65
  Object.keys(bank).forEach((key) => {
66
66
  const matchesKey = matchesKeyRegexMap[key];
67
+ // RegExp.test modifies internal state of the regex object
68
+ // since we're re-using regexes, we have to reset that state between calls
69
+ // or the second time in a row that the key should match, it misses instead
70
+ // see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/lastIndex
71
+ matchesKey.lastIndex = 0;
67
72
  if (!matchesKey.test(maybeChangedString)) {
68
73
  return;
69
74
  }
@@ -18,7 +18,8 @@ const prepareRequest = require('../http-middlewares/before/prepare-request');
18
18
  // after middles
19
19
  const logResponse = require('../http-middlewares/after/log-response');
20
20
  const prepareResponse = require('../http-middlewares/after/prepare-response');
21
- const throwForStatus = require('../http-middlewares/after/throw-for-status');
21
+ const throwForStaleAuth = require('../http-middlewares/after/throw-for-stale-auth');
22
+ const throwForStatusMiddleware = require('../http-middlewares/after/throw-for-status');
22
23
 
23
24
  const createAppRequestClient = (input, options) => {
24
25
  input = ensurePath(input, '_zapier.app');
@@ -51,11 +52,22 @@ const createAppRequestClient = (input, options) => {
51
52
  httpBefores.push(disableSSLCertCheck);
52
53
  }
53
54
 
55
+ let includeAutoRefresh = false;
56
+ if (
57
+ app.authentication &&
58
+ (app.authentication.type === 'session' ||
59
+ (app.authentication.type === 'oauth2' &&
60
+ _.get(app, 'authentication.oauth2Config.autoRefresh')))
61
+ ) {
62
+ includeAutoRefresh = true;
63
+ }
64
+
54
65
  const httpAfters = [
55
66
  prepareResponse,
56
67
  logResponse,
68
+ ...(includeAutoRefresh ? [throwForStaleAuth] : []),
57
69
  ...ensureArray(app.afterResponse),
58
- throwForStatus,
70
+ throwForStatusMiddleware,
59
71
  ];
60
72
 
61
73
  return createRequestClient(httpBefores, httpAfters, options);