zapier-platform-core 15.16.1 → 15.18.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/CHANGELOG.md CHANGED
@@ -1,3 +1 @@
1
- Read docs: https://zapier.github.io/zapier-platform/.
2
-
3
- Changelog: https://github.com/zapier/zapier-platform/blob/main/CHANGELOG.md
1
+ See [CHANGELOG.md](https://github.com/zapier/zapier-platform/blob/main/CHANGELOG.md).
package/README.md CHANGED
@@ -1,9 +1,13 @@
1
- # Core for Zapier CLI Platform [![Travis](https://img.shields.io/travis/zapier/zapier-platform-core.svg)](https://travis-ci.org/zapier/zapier-platform-core)
1
+ # Zapier Platform Core
2
2
 
3
- This is the code that powers our [Zapier Platform CLI](https://zapier.github.io/zapier-platform-cli). You'll want to head to that repo to see how it's used.
3
+ This is the SDK used in Zapier integrations.
4
4
 
5
5
  ## Development
6
6
 
7
+ See [CONTRIBUTING.md](https://github.com/zapier/zapier-platform/blob/main/CONTRIBUTING.md) and [ARCHITECTURE.md](https://github.com/zapier/zapier-platform/blob/main/packages/core/ARCHITECTURE.md) of this package in particular.
8
+
9
+ Useful commands:
10
+
7
11
  * `npm install` for getting started
8
12
  * `npm test` for running unit tests
9
13
  * `npm run local-integration-test` for running integration tests locally
@@ -16,6 +20,8 @@ Make sure your AWS access key have permission to update and run Lambda functions
16
20
  * `npm run deploy-integration-test` builds and deploys a zip to a function named `integration-test-cli` on Lambda
17
21
  * `npm run lambda-integration-test` runs the integration test using the live Lambda function `integration-test-cli`
18
22
 
19
- ## Publishing (after merging)
23
+ ## Publishing
24
+
25
+ Only do this after merging your PR to `main`.
20
26
 
21
27
  * `npm version [patch|minor|major]` will pull, test, update schema version in dependencies for this package, update docs, increment version in package.json, and push tags, which then will tell Travis to publish to npm
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zapier-platform-core",
3
- "version": "15.16.1",
3
+ "version": "15.18.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/",
@@ -53,7 +53,7 @@
53
53
  "node-fetch": "2.6.7",
54
54
  "oauth-sign": "0.9.0",
55
55
  "semver": "7.5.2",
56
- "zapier-platform-schema": "15.16.1"
56
+ "zapier-platform-schema": "15.18.0"
57
57
  },
58
58
  "devDependencies": {
59
59
  "@types/node-fetch": "^2.6.11",
@@ -61,7 +61,7 @@
61
61
  "aws-sdk": "^2.1397.0",
62
62
  "dicer": "^0.3.1",
63
63
  "fs-extra": "^11.1.1",
64
- "mock-fs": "^5.2.0",
64
+ "mock-fs": "^5.3.0",
65
65
  "nock": "^13.5.4",
66
66
  "tsd": "^0.31.1"
67
67
  },
@@ -12,7 +12,8 @@ const createCache = (input) => {
12
12
  key,
13
13
  value = null,
14
14
  ttl = null,
15
- scope = null
15
+ scope = null,
16
+ nx = null
16
17
  ) => {
17
18
  if (!rpc) {
18
19
  throw new Error('rpc is not available');
@@ -36,6 +37,10 @@ const createCache = (input) => {
36
37
  );
37
38
  }
38
39
 
40
+ if (nx !== null && !_.isBoolean(nx)) {
41
+ throw new TypeError('nx must be a boolean');
42
+ }
43
+
39
44
  ensureJSONEncodable(value);
40
45
  };
41
46
 
@@ -46,10 +51,10 @@ const createCache = (input) => {
46
51
  const result = await rpc('zcache_get', key, scope);
47
52
  return result ? JSON.parse(result) : null;
48
53
  },
49
- set: async (key, value, ttl = null, scope = null) => {
50
- runValidationChecks(rpc, key, value, ttl, scope);
54
+ set: async (key, value, ttl = null, scope = null, nx = null) => {
55
+ runValidationChecks(rpc, key, value, ttl, scope, nx);
51
56
 
52
- return await rpc('zcache_set', key, JSON.stringify(value), ttl, scope);
57
+ return await rpc('zcache_set', key, JSON.stringify(value), ttl, scope, nx);
53
58
  },
54
59
  delete: async (key, scope = null) => {
55
60
  runValidationChecks(rpc, key, scope);
@@ -196,7 +196,8 @@ const createLambdaHandler = (appRawOrPath) => {
196
196
  ZapierPromise.patchGlobal();
197
197
  }
198
198
 
199
- // If we're running out of memory, exit the process. Backend will try again.
199
+ // If we're running out of memory or file descriptors, force exit the process.
200
+ // The backend will try again via @retry(ProcessExitedException).
200
201
  checkMemory(event);
201
202
 
202
203
  environmentTools.cleanEnvironment();
@@ -45,7 +45,7 @@ const rpcCursorMock = (cursorTestObj, method, key, value = null) => {
45
45
  };
46
46
 
47
47
  const createRpcClient = (event) => {
48
- return function (method) {
48
+ return async function (method) {
49
49
  const params = _.toArray(arguments);
50
50
  params.shift();
51
51
 
@@ -97,25 +97,46 @@ const createRpcClient = (event) => {
97
97
  }
98
98
  }
99
99
 
100
- return request(req)
101
- .then((res) => {
100
+ // RPC can fail, so let's retry.
101
+ // Be careful what we throw here as this will be forwarded to the user.
102
+ const maxRetries = 3;
103
+ let attempt = 0;
104
+ let res;
105
+
106
+ while (attempt < maxRetries) {
107
+ // We will throw here, which will be caught by catch logic to either retry or bubble up.
108
+ try {
109
+ res = await request(req);
110
+
111
+ if (res.status > 500) {
112
+ throw new Error('Unable to reach the RPC server');
113
+ }
102
114
  if (res.content) {
115
+ // check if the ids match
103
116
  if (res.content.id !== id) {
104
117
  throw new Error(
105
118
  `Got id ${res.content.id} but expected ${id} when calling RPC`
106
119
  );
107
120
  }
108
- return res.content;
121
+ if (res.content.error) {
122
+ throw new Error(res.content.error);
123
+ }
124
+ return res.content.result;
109
125
  } else {
110
126
  throw new Error(`Got a ${res.status} when calling RPC`);
111
127
  }
112
- })
113
- .then((content) => {
114
- if (content.error) {
115
- throw new Error(content.error);
128
+ } catch (err) {
129
+ attempt++;
130
+
131
+ if (attempt === maxRetries || (res && res.status < 500)) {
132
+ throw new Error(
133
+ `RPC request failed after ${attempt} attempts: ${err.message}`
134
+ );
116
135
  }
117
- return content.result;
118
- });
136
+ // sleep for 100ms before retrying
137
+ await new Promise((resolve) => setTimeout(resolve, 100));
138
+ }
139
+ }
119
140
  };
120
141
  };
121
142
 
@@ -8,22 +8,31 @@ let zrun = 0;
8
8
  const checkMemory = (event) => {
9
9
  event = event || {};
10
10
 
11
+ let memUsage;
12
+
13
+ try {
14
+ memUsage = process.memoryUsage();
15
+ } catch (err) {
16
+ if (err.code === 'EMFILE') {
17
+ console.error(
18
+ 'Force killing process by Zapier for too many open file descriptors'
19
+ );
20
+
21
+ /* eslint no-process-exit: 0 */
22
+ process.exit(1);
23
+ } else {
24
+ throw err;
25
+ }
26
+ }
27
+
11
28
  zrun += 1;
12
29
  if (!constants.IS_TESTING && !event.calledFromCli) {
13
- console.log(
14
- 'ZID:',
15
- zid,
16
- 'pid',
17
- 'ZRUN:',
18
- zrun,
19
- 'RSSMEM:',
20
- process.memoryUsage()
21
- );
30
+ console.log('ZID:', zid, 'pid', 'ZRUN:', zrun, 'RSSMEM:', memUsage);
22
31
  }
23
32
 
24
33
  if (
25
34
  zrun > constants.KILL_MIN_LIMIT &&
26
- process.memoryUsage().rss > constants.KILL_MAX_LIMIT
35
+ memUsage.rss > constants.KILL_MAX_LIMIT
27
36
  ) {
28
37
  // should throw "Process exited before completing request"
29
38
  // and a @retry in our stack will attempt again - and this
@@ -18,7 +18,7 @@ import type {
18
18
  Trigger,
19
19
  } from './zapier.generated';
20
20
 
21
- import { expectType } from 'tsd';
21
+ import { expectType, expectDeprecated } from 'tsd';
22
22
 
23
23
  const basicDisplay: BasicDisplay = {
24
24
  label: 'some-label',
@@ -166,3 +166,37 @@ const app: App = {
166
166
  searches: { [search.key]: search },
167
167
  };
168
168
  expectType<App>(app);
169
+
170
+ // Return types from z.request
171
+ async (z: ZObject) => {
172
+ const resp = await z.request<{ id: number; name: string }>(
173
+ 'https://example.com'
174
+ );
175
+ expectType<{ id: number; name: string }>(resp.data);
176
+ expectDeprecated(resp.json);
177
+ };
178
+
179
+ async (z: ZObject) => {
180
+ const resp = await z.request<{ id: number; name: string }>({
181
+ url: 'https://example.com',
182
+ });
183
+ expectType<{ id: number; name: string }>(resp.data);
184
+ };
185
+
186
+ // Return types from z.request (raw)
187
+ async (z: ZObject) => {
188
+ const resp = await z.request<{ id: number; name: string }>(
189
+ 'https://example.com',
190
+ { raw: true }
191
+ );
192
+ const result = await resp.json();
193
+ expectType<{ id: number; name: string }>(result);
194
+ };
195
+ async (z: ZObject) => {
196
+ const resp = await z.request<{ id: number; name: string }>({
197
+ raw: true,
198
+ url: 'https://example.com',
199
+ });
200
+ const result = await resp.json();
201
+ expectType<{ id: number; name: string }>(result);
202
+ };
@@ -73,6 +73,9 @@ declare class RefreshAuthError extends Error {}
73
73
  declare class ThrottledError extends Error {
74
74
  constructor(message: string, delay?: number);
75
75
  }
76
+ declare class ResponseError extends Error {
77
+ constructor(response: HttpResponse);
78
+ }
76
79
 
77
80
  // copied http stuff from external typings
78
81
  export interface HttpRequestOptions {
@@ -114,16 +117,17 @@ interface BaseHttpResponse {
114
117
  request: HttpRequestOptions;
115
118
  }
116
119
 
117
- export interface HttpResponse extends BaseHttpResponse {
120
+ export interface HttpResponse<T = any> extends BaseHttpResponse {
118
121
  content: string;
119
- data?: any;
120
- json?: any;
122
+ data: T;
123
+ /** @deprecated Since v10.0.0. Use `data` instead. */
124
+ json?: T;
121
125
  }
122
126
 
123
- export interface RawHttpResponse extends BaseHttpResponse {
127
+ export interface RawHttpResponse<T = any> extends BaseHttpResponse {
124
128
  body: NodeJS.ReadableStream;
125
129
  buffer(): Promise<Buffer>;
126
- json(): Promise<object>;
130
+ json(): Promise<T>;
127
131
  text(): Promise<string>;
128
132
  }
129
133
 
@@ -135,15 +139,20 @@ type DehydrateFunc = <T>(
135
139
  export interface ZObject {
136
140
  request: {
137
141
  // most specific overloads go first
138
- (url: string, options: HttpRequestOptions & { raw: true }): Promise<
139
- RawHttpResponse
142
+ <T = any>(
143
+ url: string,
144
+ options: HttpRequestOptions & { raw: true }
145
+ ): Promise<RawHttpResponse<T>>;
146
+ <T = any>(
147
+ options: HttpRequestOptions & { raw: true; url: string }
148
+ ): Promise<RawHttpResponse<T>>;
149
+
150
+ <T = any>(url: string, options?: HttpRequestOptions): Promise<
151
+ HttpResponse<T>
140
152
  >;
141
- (options: HttpRequestOptions & { raw: true; url: string }): Promise<
142
- RawHttpResponse
153
+ <T = any>(options: HttpRequestOptions & { url: string }): Promise<
154
+ HttpResponse<T>
143
155
  >;
144
-
145
- (url: string, options?: HttpRequestOptions): Promise<HttpResponse>;
146
- (options: HttpRequestOptions & { url: string }): Promise<HttpResponse>;
147
156
  };
148
157
 
149
158
  console: Console;
@@ -199,6 +208,7 @@ export interface ZObject {
199
208
  ExpiredAuthError: typeof ExpiredAuthError;
200
209
  RefreshAuthError: typeof RefreshAuthError;
201
210
  ThrottledError: typeof ThrottledError;
211
+ ResponseError: typeof ResponseError;
202
212
  };
203
213
 
204
214
  cache: {
@@ -221,14 +231,14 @@ export type PerformFunction<BI = Record<string, any>, R = any> = (
221
231
 
222
232
  export type BeforeRequestMiddleware = (
223
233
  request: HttpRequestOptions,
224
- z?: ZObject,
225
- bundle?: Bundle
234
+ z: ZObject,
235
+ bundle: Bundle
226
236
  ) => HttpRequestOptions | Promise<HttpRequestOptions>;
227
237
 
228
238
  export type AfterResponseMiddleware = (
229
239
  response: HttpResponse,
230
240
  z: ZObject,
231
- bundle?: Bundle
241
+ bundle: Bundle
232
242
  ) => HttpResponse | Promise<HttpResponse>;
233
243
 
234
244
  export interface BufferedItem<InputData = { [x: string]: any }> {
@@ -4,7 +4,7 @@
4
4
  * files, and/or the schema-to-ts tool and run its CLI to regenerate
5
5
  * these typings.
6
6
  *
7
- * zapier-platform-schema version: 15.16.0
7
+ * zapier-platform-schema version: 15.17.0
8
8
  * schema-to-ts compiler version: 0.1.0
9
9
  */
10
10