zapier-platform-core 15.16.0 → 15.17.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": "15.
|
|
3
|
+
"version": "15.17.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.
|
|
56
|
+
"zapier-platform-schema": "15.17.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.
|
|
64
|
+
"mock-fs": "^5.3.0",
|
|
65
65
|
"nock": "^13.5.4",
|
|
66
66
|
"tsd": "^0.31.1"
|
|
67
67
|
},
|
package/src/constants.js
CHANGED
|
@@ -14,6 +14,8 @@ const RESPONSE_SIZE_LIMIT = 6291456;
|
|
|
14
14
|
const UPLOAD_MAX_SIZE = 1000 * 1000 * 1000 * 1; // 1GB, in zapier backend too
|
|
15
15
|
const NON_STREAM_UPLOAD_MAX_SIZE = 1000 * 1000 * 150;
|
|
16
16
|
|
|
17
|
+
const ENCODED_FILENAME_MAX_LENGTH = 1000; // 1KB - S3 Metadata max is 2048
|
|
18
|
+
|
|
17
19
|
const HYDRATE_DIRECTIVE_HOIST = '$HOIST$';
|
|
18
20
|
|
|
19
21
|
const RENDER_ONLY_METHODS = [
|
|
@@ -58,6 +60,7 @@ const PACKAGE_VERSION = packageJson.version;
|
|
|
58
60
|
module.exports = {
|
|
59
61
|
DEFAULT_LOGGING_HTTP_API_KEY,
|
|
60
62
|
DEFAULT_LOGGING_HTTP_ENDPOINT,
|
|
63
|
+
ENCODED_FILENAME_MAX_LENGTH,
|
|
61
64
|
HYDRATE_DIRECTIVE_HOIST,
|
|
62
65
|
IS_TESTING,
|
|
63
66
|
KILL_MAX_LIMIT,
|
|
@@ -12,7 +12,11 @@ const contentDisposition = require('content-disposition');
|
|
|
12
12
|
|
|
13
13
|
const mime = require('mime-types');
|
|
14
14
|
|
|
15
|
-
const {
|
|
15
|
+
const {
|
|
16
|
+
ENCODED_FILENAME_MAX_LENGTH,
|
|
17
|
+
UPLOAD_MAX_SIZE,
|
|
18
|
+
NON_STREAM_UPLOAD_MAX_SIZE,
|
|
19
|
+
} = require('../constants');
|
|
16
20
|
const uploader = require('./uploader');
|
|
17
21
|
|
|
18
22
|
const DEFAULT_FILE_NAME = 'unnamedfile';
|
|
@@ -186,6 +190,24 @@ const ensureUploadMaxSizeNotExceeded = (streamOrData, length) => {
|
|
|
186
190
|
}
|
|
187
191
|
};
|
|
188
192
|
|
|
193
|
+
// S3's max metadata size is 2KB
|
|
194
|
+
// If the filename needs to be encoded, both the filename
|
|
195
|
+
// and encoded filename are included in the Content-Disposition header
|
|
196
|
+
const ensureMetadataMaxSizeNotExceeded = (filename) => {
|
|
197
|
+
const filenameMaxSize = ENCODED_FILENAME_MAX_LENGTH;
|
|
198
|
+
if (filename) {
|
|
199
|
+
const encodedFilename = encodeURIComponent(filename);
|
|
200
|
+
if (
|
|
201
|
+
encodedFilename !== filename &&
|
|
202
|
+
encodedFilename.length > filenameMaxSize
|
|
203
|
+
) {
|
|
204
|
+
throw new Error(
|
|
205
|
+
`URI-Encoded Filename is too long at ${encodedFilename.length}, ${ENCODED_FILENAME_MAX_LENGTH} is the max.`
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
|
|
189
211
|
// Designed to be some user provided function/api.
|
|
190
212
|
const createFileStasher = (input) => {
|
|
191
213
|
const rpc = _.get(input, '_zapier.rpc');
|
|
@@ -247,6 +269,8 @@ const createFileStasher = (input) => {
|
|
|
247
269
|
const finalLength = knownLength || length;
|
|
248
270
|
ensureUploadMaxSizeNotExceeded(streamOrData, finalLength);
|
|
249
271
|
|
|
272
|
+
ensureMetadataMaxSizeNotExceeded(filename || _filename);
|
|
273
|
+
|
|
250
274
|
return uploader(
|
|
251
275
|
signedPostData,
|
|
252
276
|
streamOrData,
|
|
@@ -330,6 +330,11 @@ const sendLog = async (logStreamFactory, options, event, message, data) => {
|
|
|
330
330
|
toStdout(event, message, safeData);
|
|
331
331
|
}
|
|
332
332
|
|
|
333
|
+
if (event.customLogger && typeof event.customLogger === 'function') {
|
|
334
|
+
// For `zapier invoke` command
|
|
335
|
+
event.customLogger(safeMessage, safeData);
|
|
336
|
+
}
|
|
337
|
+
|
|
333
338
|
if (options.logBuffer && data.log_type === 'console') {
|
|
334
339
|
// Cap size of messages in log buffer, in case devs log humongous things.
|
|
335
340
|
options.logBuffer.push({ type: safeData.log_type, message: safeMessage });
|
|
@@ -31,17 +31,42 @@ const rpcCacheMock = (zcacheTestObj, method, key, value = null, ttl = null) => {
|
|
|
31
31
|
throw new Error(`Unexpected method '${method}'`);
|
|
32
32
|
};
|
|
33
33
|
|
|
34
|
+
const rpcCursorMock = (cursorTestObj, method, key, value = null) => {
|
|
35
|
+
if (method === 'get_cursor') {
|
|
36
|
+
return cursorTestObj[key] || null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (method === 'set_cursor') {
|
|
40
|
+
cursorTestObj[key] = value;
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
throw new Error(`Unexpected method '${method}'`);
|
|
45
|
+
};
|
|
46
|
+
|
|
34
47
|
const createRpcClient = (event) => {
|
|
35
|
-
return function (method) {
|
|
48
|
+
return async function (method) {
|
|
36
49
|
const params = _.toArray(arguments);
|
|
37
50
|
params.shift();
|
|
38
51
|
|
|
39
52
|
const zcacheMethods = ['zcache_get', 'zcache_set', 'zcache_delete'];
|
|
40
|
-
if (
|
|
53
|
+
if (
|
|
54
|
+
zcacheMethods.includes(method) &&
|
|
55
|
+
_.isPlainObject(event.zcacheTestObj)
|
|
56
|
+
) {
|
|
41
57
|
const [key, value = null] = params;
|
|
42
58
|
return rpcCacheMock(event.zcacheTestObj, method, key, value);
|
|
43
59
|
}
|
|
44
60
|
|
|
61
|
+
const cursorMethods = ['get_cursor', 'set_cursor'];
|
|
62
|
+
if (
|
|
63
|
+
cursorMethods.includes(method) &&
|
|
64
|
+
_.isPlainObject(event.cursorTestObj)
|
|
65
|
+
) {
|
|
66
|
+
const [key, value = null] = params;
|
|
67
|
+
return rpcCursorMock(event.cursorTestObj, method, key, value);
|
|
68
|
+
}
|
|
69
|
+
|
|
45
70
|
const id = genId();
|
|
46
71
|
const body = JSON.stringify({
|
|
47
72
|
id,
|
|
@@ -72,25 +97,46 @@ const createRpcClient = (event) => {
|
|
|
72
97
|
}
|
|
73
98
|
}
|
|
74
99
|
|
|
75
|
-
|
|
76
|
-
|
|
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
|
+
}
|
|
77
114
|
if (res.content) {
|
|
115
|
+
// check if the ids match
|
|
78
116
|
if (res.content.id !== id) {
|
|
79
117
|
throw new Error(
|
|
80
118
|
`Got id ${res.content.id} but expected ${id} when calling RPC`
|
|
81
119
|
);
|
|
82
120
|
}
|
|
83
|
-
|
|
121
|
+
if (res.content.error) {
|
|
122
|
+
throw new Error(res.content.error);
|
|
123
|
+
}
|
|
124
|
+
return res.content.result;
|
|
84
125
|
} else {
|
|
85
126
|
throw new Error(`Got a ${res.status} when calling RPC`);
|
|
86
127
|
}
|
|
87
|
-
})
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
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
|
+
);
|
|
91
135
|
}
|
|
92
|
-
|
|
93
|
-
|
|
136
|
+
// sleep for 100ms before retrying
|
|
137
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
138
|
+
}
|
|
139
|
+
}
|
|
94
140
|
};
|
|
95
141
|
};
|
|
96
142
|
|
package/types/zapier.custom.d.ts
CHANGED
|
@@ -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 {
|
|
@@ -135,12 +138,13 @@ type DehydrateFunc = <T>(
|
|
|
135
138
|
export interface ZObject {
|
|
136
139
|
request: {
|
|
137
140
|
// most specific overloads go first
|
|
138
|
-
(
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
141
|
+
(
|
|
142
|
+
url: string,
|
|
143
|
+
options: HttpRequestOptions & { raw: true }
|
|
144
|
+
): Promise<RawHttpResponse>;
|
|
145
|
+
(
|
|
146
|
+
options: HttpRequestOptions & { raw: true; url: string }
|
|
147
|
+
): Promise<RawHttpResponse>;
|
|
144
148
|
|
|
145
149
|
(url: string, options?: HttpRequestOptions): Promise<HttpResponse>;
|
|
146
150
|
(options: HttpRequestOptions & { url: string }): Promise<HttpResponse>;
|
|
@@ -199,6 +203,7 @@ export interface ZObject {
|
|
|
199
203
|
ExpiredAuthError: typeof ExpiredAuthError;
|
|
200
204
|
RefreshAuthError: typeof RefreshAuthError;
|
|
201
205
|
ThrottledError: typeof ThrottledError;
|
|
206
|
+
ResponseError: typeof ResponseError;
|
|
202
207
|
};
|
|
203
208
|
|
|
204
209
|
cache: {
|