zapier-platform-core 12.0.3 → 12.1.0

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": "12.0.3",
3
+ "version": "12.1.0",
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/",
@@ -47,10 +47,11 @@
47
47
  "form-data": "4.0.0",
48
48
  "lodash": "4.17.21",
49
49
  "mime-types": "2.1.34",
50
+ "node-abort-controller": "3.0.1",
50
51
  "node-fetch": "2.6.7",
51
52
  "oauth-sign": "0.9.0",
52
53
  "semver": "7.3.5",
53
- "zapier-platform-schema": "12.0.3"
54
+ "zapier-platform-schema": "12.1.0"
54
55
  },
55
56
  "devDependencies": {
56
57
  "adm-zip": "0.5.5",
@@ -1,9 +1,11 @@
1
1
  'use strict';
2
2
 
3
+ const { promisify } = require('util');
3
4
  const { Transform } = require('stream');
4
5
  const { parse: querystringParse } = require('querystring');
5
6
 
6
7
  const _ = require('lodash');
8
+ const { AbortController } = require('node-abort-controller');
7
9
 
8
10
  const request = require('./request-client-internal');
9
11
  const { simpleTruncate, recurseReplace, truncateData } = require('./data');
@@ -28,6 +30,10 @@ const {
28
30
  // than the limit (16 MB) on the server side.
29
31
  const LOG_STREAM_BYTES_LIMIT = 15 * 1024 * 1024;
30
32
 
33
+ const DEFAULT_LOGGER_TIMEOUT = 200;
34
+
35
+ const sleep = promisify(setTimeout);
36
+
31
37
  const isUrl = (url) => {
32
38
  try {
33
39
  // eslint-disable-next-line no-new
@@ -167,6 +173,7 @@ class LogStream extends Transform {
167
173
  constructor(options) {
168
174
  super(options);
169
175
  this.bytesWritten = 0;
176
+ this.controller = new AbortController();
170
177
  this.request = this._newRequest(options.url, options.token);
171
178
  }
172
179
 
@@ -179,15 +186,20 @@ class LogStream extends Transform {
179
186
  'X-Token': token,
180
187
  },
181
188
  body: this,
189
+ signal: this.controller.signal,
182
190
  };
183
191
  return request(httpOptions).catch((err) => {
192
+ if (err.name === 'AbortError') {
193
+ return {
194
+ status: 200,
195
+ content: 'aborted',
196
+ };
197
+ }
198
+
184
199
  // Swallow logging errors. This will show up in AWS logs at least.
185
- console.error(
186
- 'Error making log request:',
187
- err,
188
- 'http options:',
189
- httpOptions
190
- );
200
+ // Don't need to log for AbortError because that happens when we abort
201
+ // on purpose.
202
+ console.error('Error making log request:', err);
191
203
  });
192
204
  }
193
205
 
@@ -196,6 +208,10 @@ class LogStream extends Transform {
196
208
  this.bytesWritten += Buffer.byteLength(chunk, encoding);
197
209
  callback();
198
210
  }
211
+
212
+ abort() {
213
+ this.controller.abort();
214
+ }
199
215
  }
200
216
 
201
217
  // Implements singleton for LogStream. The goal is for every sendLog() call we
@@ -222,17 +238,35 @@ class LogStreamFactory {
222
238
  return this._logStream;
223
239
  }
224
240
 
225
- async end() {
241
+ // Ends the logger and gets a response from the log server. Optionally takes
242
+ // timeoutToAbort to specify how many milliseconds we want to wait before
243
+ // force aborting the connection to the log server.
244
+ async end(timeoutToAbort = DEFAULT_LOGGER_TIMEOUT) {
226
245
  // Mark the factory as ended. This suggests that any logStream.write() that
227
246
  // follows should end() right away.
228
247
  this.ended = true;
248
+ let response;
229
249
 
230
250
  if (this._logStream) {
231
251
  this._logStream.end();
232
- const response = await this._logStream.request;
252
+
253
+ const clock =
254
+ timeoutToAbort > 0 ? sleep(timeoutToAbort) : Promise.resolve(undefined);
255
+ const responsePromise = this._logStream.request;
256
+
257
+ const result = await Promise.race([clock, responsePromise]);
258
+ const isTimeout = !result;
259
+ if (isTimeout) {
260
+ this._logStream.abort();
261
+ // Expect to get a `{content: 'aborted'}` response
262
+ response = await responsePromise;
263
+ } else {
264
+ response = result;
265
+ }
266
+
233
267
  this._logStream = null;
234
- return response;
235
268
  }
269
+ return response;
236
270
  }
237
271
  }
238
272
 
@@ -294,7 +328,7 @@ const sendLog = async (logStreamFactory, options, event, message, data) => {
294
328
  // (bad) callback that is still running after the Lambda handler returns?
295
329
  // We need to make sure the bad callback ends the logger as well.
296
330
  // Otherwise, it will hang!
297
- logStreamFactory.end();
331
+ logStreamFactory.end(DEFAULT_LOGGER_TIMEOUT);
298
332
  }
299
333
  }
300
334
  };
@@ -331,8 +365,8 @@ const createLogger = (event, options) => {
331
365
  const logStreamFactory = new LogStreamFactory();
332
366
  const logger = sendLog.bind(undefined, logStreamFactory, options, event);
333
367
 
334
- logger.end = async () => {
335
- return logStreamFactory.end();
368
+ logger.end = async (timeoutToAbort = DEFAULT_LOGGER_TIMEOUT) => {
369
+ return logStreamFactory.end(timeoutToAbort);
336
370
  };
337
371
  return logger;
338
372
  };