zapier-platform-core 15.9.1 → 15.11.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 +9 -7
- package/src/tools/create-http-patch.js +21 -3
- package/src/tools/create-lambda-handler.js +87 -33
- package/src/tools/http.js +24 -0
- package/src/tools/wrap-hydrate.js +5 -3
- package/types/index.d.ts +2 -0
- package/types/index.test-d.ts +152 -0
- package/{index.d.ts → types/zapier.custom.d.ts} +26 -7
- package/types/zapier.generated.d.ts +1739 -0
package/package.json
CHANGED
|
@@ -1,26 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zapier-platform-core",
|
|
3
|
-
"version": "15.
|
|
3
|
+
"version": "15.11.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/",
|
|
7
7
|
"author": "Zapier Engineering <contact@zapier.com>",
|
|
8
8
|
"license": "SEE LICENSE IN LICENSE",
|
|
9
9
|
"main": "index.js",
|
|
10
|
-
"
|
|
10
|
+
"types": "types/index.d.ts",
|
|
11
11
|
"files": [
|
|
12
12
|
"/include/",
|
|
13
|
-
"/index.d.ts",
|
|
14
13
|
"/index.js",
|
|
15
|
-
"/src/"
|
|
14
|
+
"/src/",
|
|
15
|
+
"/types/"
|
|
16
16
|
],
|
|
17
17
|
"scripts": {
|
|
18
18
|
"preversion": "git pull && yarn test",
|
|
19
19
|
"version": "node bin/bump-dependencies.js && yarn && git add package.json yarn.lock",
|
|
20
20
|
"postversion": "git push && git push --tags",
|
|
21
21
|
"main-tests": "mocha -t 20s --recursive test --exit",
|
|
22
|
+
"type-tests": "tsd",
|
|
22
23
|
"solo-test": "test $(OPT_OUT_PATCH_TEST_ONLY=yes mocha --recursive test -g 'should be able to opt out of patch' -R json | jq '.stats.passes') -eq 1 && echo 'Ran 1 test and it passed!'",
|
|
23
|
-
"test": "yarn main-tests && yarn solo-test",
|
|
24
|
+
"test": "yarn main-tests && yarn solo-test && yarn type-tests",
|
|
24
25
|
"test:debug": "mocha inspect -t 10s --recursive test",
|
|
25
26
|
"debug": "mocha -t 10s --inspect-brk --recursive test",
|
|
26
27
|
"test:w": "mocha -t 10s --recursive test --watch",
|
|
@@ -52,7 +53,7 @@
|
|
|
52
53
|
"node-fetch": "2.6.7",
|
|
53
54
|
"oauth-sign": "0.9.0",
|
|
54
55
|
"semver": "7.5.2",
|
|
55
|
-
"zapier-platform-schema": "15.
|
|
56
|
+
"zapier-platform-schema": "15.11.0"
|
|
56
57
|
},
|
|
57
58
|
"devDependencies": {
|
|
58
59
|
"@types/node-fetch": "^2.6.11",
|
|
@@ -61,7 +62,8 @@
|
|
|
61
62
|
"dicer": "^0.3.1",
|
|
62
63
|
"fs-extra": "^11.1.1",
|
|
63
64
|
"mock-fs": "^5.2.0",
|
|
64
|
-
"nock": "^13.5.4"
|
|
65
|
+
"nock": "^13.5.4",
|
|
66
|
+
"tsd": "^0.31.1"
|
|
65
67
|
},
|
|
66
68
|
"optionalDependencies": {
|
|
67
69
|
"@types/node": "^20.3.1"
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
const zlib = require('zlib');
|
|
2
2
|
const _ = require('lodash');
|
|
3
|
+
|
|
4
|
+
const { ALLOWED_HTTP_DATA_CONTENT_TYPES, getContentType } = require('./http');
|
|
5
|
+
|
|
3
6
|
const constants = require('../constants');
|
|
4
7
|
|
|
5
8
|
const createHttpPatch = (event) => {
|
|
@@ -54,19 +57,34 @@ const createHttpPatch = (event) => {
|
|
|
54
57
|
const newCallback = function (response) {
|
|
55
58
|
const chunks = [];
|
|
56
59
|
|
|
60
|
+
// Only include request or response data for specific content types
|
|
61
|
+
// which we are able to read in logs and which are not typically too large
|
|
62
|
+
const requestContentType = getContentType(options.headers || {});
|
|
63
|
+
const responseContentType = getContentType(response.headers || {});
|
|
64
|
+
|
|
65
|
+
const shouldIncludeRequestData =
|
|
66
|
+
ALLOWED_HTTP_DATA_CONTENT_TYPES.has(requestContentType);
|
|
67
|
+
const shouldIncludeResponseData =
|
|
68
|
+
ALLOWED_HTTP_DATA_CONTENT_TYPES.has(responseContentType);
|
|
69
|
+
|
|
57
70
|
const sendToLogger = (responseBody) => {
|
|
58
71
|
// Prepare data for GL
|
|
59
72
|
const logData = {
|
|
60
73
|
log_type: 'http',
|
|
61
|
-
request_type
|
|
74
|
+
// Using a custom request_type to differentiate from z.request() since `request_via_client` is not logged in GL
|
|
75
|
+
request_type: 'patched-devplatform-outbound',
|
|
62
76
|
request_url: requestUrl,
|
|
63
77
|
request_method: options.method || 'GET',
|
|
64
78
|
request_headers: options.headers,
|
|
65
|
-
request_data:
|
|
79
|
+
request_data: shouldIncludeRequestData
|
|
80
|
+
? options.body || ''
|
|
81
|
+
: '<unsupported format>',
|
|
66
82
|
request_via_client: false,
|
|
67
83
|
response_status_code: response.statusCode,
|
|
68
84
|
response_headers: response.headers,
|
|
69
|
-
response_content:
|
|
85
|
+
response_content: shouldIncludeResponseData
|
|
86
|
+
? responseBody
|
|
87
|
+
: '<unsupported format>',
|
|
70
88
|
};
|
|
71
89
|
|
|
72
90
|
object.zapierLogger(
|
|
@@ -19,42 +19,84 @@ const environmentTools = require('./environment');
|
|
|
19
19
|
const schemaTools = require('./schema');
|
|
20
20
|
const ZapierPromise = require('./promise');
|
|
21
21
|
|
|
22
|
-
const
|
|
23
|
-
const FunctionSchema = require('zapier-platform-schema/lib/schemas/FunctionSchema');
|
|
24
|
-
|
|
25
|
-
const isRequestOrFunction = (obj) => {
|
|
22
|
+
const isDefinedPrimitive = (value) => {
|
|
26
23
|
return (
|
|
27
|
-
|
|
24
|
+
value === null ||
|
|
25
|
+
typeof value === 'string' ||
|
|
26
|
+
typeof value === 'number' ||
|
|
27
|
+
typeof value === 'boolean'
|
|
28
28
|
);
|
|
29
29
|
};
|
|
30
30
|
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
31
|
+
const shouldFullyReplace = (path) => {
|
|
32
|
+
// covers inputFields, outputFields, sample, throttle, etc
|
|
33
|
+
const isOperation = path[path.length - 2] === 'operation';
|
|
34
|
+
return isOperation;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const extendAppRaw = (base, extension, path) => {
|
|
38
|
+
if (extension === undefined) {
|
|
39
|
+
return base;
|
|
40
|
+
} else if (isDefinedPrimitive(extension)) {
|
|
41
|
+
return extension;
|
|
42
|
+
} else if (Array.isArray(extension)) {
|
|
43
|
+
return [...extension];
|
|
44
|
+
} else if (_.isPlainObject(extension)) {
|
|
45
|
+
path = path || [];
|
|
46
|
+
if (shouldFullyReplace(path)) {
|
|
47
|
+
return extension;
|
|
48
|
+
} else {
|
|
49
|
+
const baseObject = _.isPlainObject(base) ? base : {};
|
|
50
|
+
const result = { ...baseObject };
|
|
51
|
+
for (const [key, value] of Object.entries(extension)) {
|
|
52
|
+
const newPath = [...path, key];
|
|
53
|
+
result[key] = extendAppRaw(baseObject[key], value, newPath);
|
|
54
|
+
}
|
|
55
|
+
return result;
|
|
42
56
|
}
|
|
57
|
+
}
|
|
58
|
+
throw new TypeError('Unexpected extension type');
|
|
59
|
+
};
|
|
43
60
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
61
|
+
const mayMoveCreatesToResourcesInExtension = (base, extension) => {
|
|
62
|
+
// The backend sends an extension for creates.KEY.operation.perform as a
|
|
63
|
+
// special case for legacy-scripting-runner.
|
|
64
|
+
// For details, see the MR description at
|
|
65
|
+
// https://gitlab.com/zapier/zapier/-/merge_requests/57964
|
|
66
|
+
//
|
|
67
|
+
// We need to make sure that 'creates.{key}Create' in extension won't collide
|
|
68
|
+
// with 'resources.{key}.create' in base. Otherwise, the checks in
|
|
69
|
+
// compileApp() will throw an error. So here we move 'creates.{key}Create' to
|
|
70
|
+
// 'resources.{key}.create' in extension if base has 'resources.{key}.create'.
|
|
71
|
+
//
|
|
72
|
+
// There's a regression test: Search for 'resource key collision' in
|
|
73
|
+
// integration-test.js.
|
|
74
|
+
if (
|
|
75
|
+
!_.isPlainObject(base.resources) ||
|
|
76
|
+
!_.isPlainObject(extension.creates) ||
|
|
77
|
+
_.isEmpty(base.resources) ||
|
|
78
|
+
_.isEmpty(extension.creates)
|
|
79
|
+
) {
|
|
80
|
+
return extension;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const creates = extension.creates;
|
|
84
|
+
extension.creates = {};
|
|
85
|
+
extension.resources = extension.resources || {};
|
|
86
|
+
|
|
87
|
+
for (const [key, resource] of Object.entries(base.resources)) {
|
|
88
|
+
const standaloneCreate = creates[key + 'Create'];
|
|
89
|
+
if (resource.create && standaloneCreate) {
|
|
90
|
+
delete standaloneCreate.key;
|
|
91
|
+
delete standaloneCreate.noun;
|
|
92
|
+
extension.resources[key] = {
|
|
93
|
+
...extension.resources[key],
|
|
94
|
+
create: standaloneCreate,
|
|
95
|
+
};
|
|
53
96
|
}
|
|
97
|
+
}
|
|
54
98
|
|
|
55
|
-
|
|
56
|
-
};
|
|
57
|
-
return _.mergeWith(base, extension, concatArrayAndOverrideKeys);
|
|
99
|
+
return extension;
|
|
58
100
|
};
|
|
59
101
|
|
|
60
102
|
const getAppRawOverride = (rpc, appRawOverride) => {
|
|
@@ -69,6 +111,10 @@ const getAppRawOverride = (rpc, appRawOverride) => {
|
|
|
69
111
|
appRawOverride = appRawOverride[0];
|
|
70
112
|
|
|
71
113
|
if (typeof appRawOverride !== 'string') {
|
|
114
|
+
appRawExtension = mayMoveCreatesToResourcesInExtension(
|
|
115
|
+
appRawOverride,
|
|
116
|
+
appRawExtension
|
|
117
|
+
);
|
|
72
118
|
appRawOverride = extendAppRaw(appRawOverride, appRawExtension);
|
|
73
119
|
resolve(appRawOverride);
|
|
74
120
|
return;
|
|
@@ -116,17 +162,25 @@ const getAppRawOverride = (rpc, appRawOverride) => {
|
|
|
116
162
|
// so allow for that, and an event.appRawOverride for "buildless" apps.
|
|
117
163
|
const loadApp = (event, rpc, appRawOrPath) => {
|
|
118
164
|
return new ZapierPromise((resolve, reject) => {
|
|
165
|
+
const appRaw = _.isString(appRawOrPath)
|
|
166
|
+
? require(appRawOrPath)
|
|
167
|
+
: appRawOrPath;
|
|
168
|
+
|
|
119
169
|
if (event && event.appRawOverride) {
|
|
170
|
+
if (
|
|
171
|
+
Array.isArray(event.appRawOverride) &&
|
|
172
|
+
event.appRawOverride.length > 1 &&
|
|
173
|
+
!event.appRawOverride[0]
|
|
174
|
+
) {
|
|
175
|
+
event.appRawOverride[0] = appRaw;
|
|
176
|
+
}
|
|
177
|
+
|
|
120
178
|
return getAppRawOverride(rpc, event.appRawOverride)
|
|
121
179
|
.then((appRawOverride) => resolve(appRawOverride))
|
|
122
180
|
.catch((err) => reject(err));
|
|
123
181
|
}
|
|
124
182
|
|
|
125
|
-
|
|
126
|
-
return resolve(require(appRawOrPath));
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
return resolve(appRawOrPath);
|
|
183
|
+
return resolve(appRaw);
|
|
130
184
|
});
|
|
131
185
|
};
|
|
132
186
|
|
package/src/tools/http.js
CHANGED
|
@@ -4,6 +4,23 @@ const fetch = require('node-fetch');
|
|
|
4
4
|
const FORM_TYPE = 'application/x-www-form-urlencoded';
|
|
5
5
|
const JSON_TYPE = 'application/json';
|
|
6
6
|
const JSON_TYPE_UTF8 = 'application/json; charset=utf-8';
|
|
7
|
+
const BINARY_TYPE = 'application/octet-stream';
|
|
8
|
+
const HTML_TYPE = 'text/html';
|
|
9
|
+
const TEXT_TYPE = 'text/plain';
|
|
10
|
+
const YAML_TYPE = 'application/yaml';
|
|
11
|
+
const XML_TYPE = 'application/xml';
|
|
12
|
+
const JSONAPI_TYPE = 'application/vnd.api+json';
|
|
13
|
+
|
|
14
|
+
const ALLOWED_HTTP_DATA_CONTENT_TYPES = new Set([
|
|
15
|
+
FORM_TYPE,
|
|
16
|
+
JSON_TYPE,
|
|
17
|
+
JSON_TYPE_UTF8,
|
|
18
|
+
HTML_TYPE,
|
|
19
|
+
TEXT_TYPE,
|
|
20
|
+
YAML_TYPE,
|
|
21
|
+
XML_TYPE,
|
|
22
|
+
JSONAPI_TYPE,
|
|
23
|
+
]);
|
|
7
24
|
|
|
8
25
|
const getContentType = (headers) => {
|
|
9
26
|
const headerKeys = Object.keys(headers);
|
|
@@ -101,6 +118,13 @@ module.exports = {
|
|
|
101
118
|
FORM_TYPE,
|
|
102
119
|
JSON_TYPE,
|
|
103
120
|
JSON_TYPE_UTF8,
|
|
121
|
+
BINARY_TYPE,
|
|
122
|
+
HTML_TYPE,
|
|
123
|
+
TEXT_TYPE,
|
|
124
|
+
YAML_TYPE,
|
|
125
|
+
XML_TYPE,
|
|
126
|
+
JSONAPI_TYPE,
|
|
127
|
+
ALLOWED_HTTP_DATA_CONTENT_TYPES,
|
|
104
128
|
getContentType,
|
|
105
129
|
parseDictHeader,
|
|
106
130
|
unheader,
|
|
@@ -4,9 +4,11 @@ const crypto = require('crypto');
|
|
|
4
4
|
|
|
5
5
|
const { DehydrateError } = require('../errors');
|
|
6
6
|
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
|
|
7
|
+
// https://nodejs.org/docs/latest-v16.x/api/http.html#httpmaxheadersize
|
|
8
|
+
// Base64 encoding adds approx 4/3 to the original size
|
|
9
|
+
// To account for encoding, we use the inverse to calc the max original size (3/4)
|
|
10
|
+
// 16kb limit * 1024 * (3 / 4) = 12.228 kb max, minus some room for additional overhead
|
|
11
|
+
const MAX_PAYLOAD_SIZE = 12000;
|
|
10
12
|
|
|
11
13
|
const wrapHydrate = (payload) => {
|
|
12
14
|
payload = JSON.stringify(payload);
|
package/types/index.d.ts
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AfterResponseMiddleware,
|
|
3
|
+
BeforeRequestMiddleware,
|
|
4
|
+
Bundle,
|
|
5
|
+
PerformFunction,
|
|
6
|
+
ZObject,
|
|
7
|
+
} from './zapier.custom';
|
|
8
|
+
import type {
|
|
9
|
+
App,
|
|
10
|
+
Authentication,
|
|
11
|
+
AuthenticationOAuth2Config,
|
|
12
|
+
BasicActionOperation,
|
|
13
|
+
BasicCreateActionOperation,
|
|
14
|
+
BasicDisplay,
|
|
15
|
+
BasicHookOperation,
|
|
16
|
+
BasicPollingOperation,
|
|
17
|
+
Create,
|
|
18
|
+
Search,
|
|
19
|
+
Trigger,
|
|
20
|
+
} from './zapier.generated';
|
|
21
|
+
|
|
22
|
+
import { expectType } from 'tsd';
|
|
23
|
+
|
|
24
|
+
const basicDisplay: BasicDisplay = {
|
|
25
|
+
label: 'some-label',
|
|
26
|
+
description: 'some-description',
|
|
27
|
+
directions: 'some-directions',
|
|
28
|
+
hidden: false,
|
|
29
|
+
};
|
|
30
|
+
expectType<BasicDisplay>(basicDisplay);
|
|
31
|
+
|
|
32
|
+
const oauth2Config: AuthenticationOAuth2Config = {
|
|
33
|
+
authorizeUrl: 'https://example.com/authorize',
|
|
34
|
+
getAccessToken: 'https://example.com/token',
|
|
35
|
+
refreshAccessToken: async (z: ZObject, b: Bundle) => 'some-refresh-token',
|
|
36
|
+
};
|
|
37
|
+
expectType<AuthenticationOAuth2Config>(oauth2Config);
|
|
38
|
+
|
|
39
|
+
const authentication: Authentication = {
|
|
40
|
+
type: 'oauth2',
|
|
41
|
+
test: async (z: ZObject, b: Bundle) => ({ data: true }),
|
|
42
|
+
oauth2Config,
|
|
43
|
+
};
|
|
44
|
+
expectType<Authentication>(authentication);
|
|
45
|
+
|
|
46
|
+
const createOperation: BasicCreateActionOperation = {
|
|
47
|
+
inputFields: [{ key: 'some-input-key-1', type: 'string', required: true }],
|
|
48
|
+
perform: async (z: ZObject, b: Bundle) => ({ data: true }),
|
|
49
|
+
sample: { id: 'some-id', name: 'some-name' },
|
|
50
|
+
};
|
|
51
|
+
expectType<BasicCreateActionOperation>(createOperation);
|
|
52
|
+
|
|
53
|
+
const create: Create = {
|
|
54
|
+
key: 'some_create_key_v1',
|
|
55
|
+
noun: 'Some Noun',
|
|
56
|
+
display: {
|
|
57
|
+
label: 'some create label',
|
|
58
|
+
description: 'some trigger description',
|
|
59
|
+
},
|
|
60
|
+
operation: createOperation,
|
|
61
|
+
};
|
|
62
|
+
expectType<Create>(create);
|
|
63
|
+
|
|
64
|
+
const pollingOperation: BasicPollingOperation = {
|
|
65
|
+
type: 'polling',
|
|
66
|
+
inputFields: [{ key: 'some-input-key-1', type: 'number', required: true }],
|
|
67
|
+
perform: async (z: ZObject, b: Bundle) => ({ data: true }),
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const pollingTrigger: Trigger = {
|
|
71
|
+
key: 'some_polling_trigger_key_v1',
|
|
72
|
+
noun: 'Some Noun',
|
|
73
|
+
display: {
|
|
74
|
+
label: 'some polling trigger label',
|
|
75
|
+
description: 'some polling trigger description',
|
|
76
|
+
},
|
|
77
|
+
operation: pollingOperation,
|
|
78
|
+
};
|
|
79
|
+
expectType<Trigger>(pollingTrigger);
|
|
80
|
+
|
|
81
|
+
const hookOperation: BasicHookOperation = {
|
|
82
|
+
type: 'hook',
|
|
83
|
+
inputFields: [{ key: 'some-input-key-1', type: 'boolean', required: false }],
|
|
84
|
+
perform: async (z: ZObject, b: Bundle) => ({ data: true }),
|
|
85
|
+
performList: async (z: ZObject, b: Bundle) => [{ data: true }],
|
|
86
|
+
performSubscribe: async (z: ZObject, b: Bundle) => ({ data: true }),
|
|
87
|
+
performUnsubscribe: async (z: ZObject, b: Bundle) => ({ data: true }),
|
|
88
|
+
};
|
|
89
|
+
expectType<BasicHookOperation>(hookOperation);
|
|
90
|
+
|
|
91
|
+
const hookTrigger: Trigger = {
|
|
92
|
+
key: 'some_hook_trigger_key_v1',
|
|
93
|
+
noun: 'Some Noun',
|
|
94
|
+
display: {
|
|
95
|
+
label: 'some hook label',
|
|
96
|
+
description: 'some hook description',
|
|
97
|
+
},
|
|
98
|
+
operation: hookOperation,
|
|
99
|
+
};
|
|
100
|
+
expectType<Trigger>(hookTrigger);
|
|
101
|
+
|
|
102
|
+
const searchOperation: BasicActionOperation = {
|
|
103
|
+
inputFields: [{ key: 'some-input-key-1', type: 'file', required: true }],
|
|
104
|
+
perform: async (z: ZObject, b: Bundle) => [{ data: true }],
|
|
105
|
+
};
|
|
106
|
+
expectType<BasicActionOperation>(searchOperation);
|
|
107
|
+
|
|
108
|
+
const search: Search = {
|
|
109
|
+
key: 'some_search_key_v1',
|
|
110
|
+
noun: 'Some Noun',
|
|
111
|
+
display: {
|
|
112
|
+
label: 'some search label',
|
|
113
|
+
description: 'some search description',
|
|
114
|
+
},
|
|
115
|
+
operation: searchOperation,
|
|
116
|
+
};
|
|
117
|
+
expectType<Search>(search);
|
|
118
|
+
|
|
119
|
+
const addBearerHeader: BeforeRequestMiddleware = (request, z, bundle) => {
|
|
120
|
+
if (bundle?.authData?.access_token && !request.headers!.Authorization) {
|
|
121
|
+
request.headers!.Authorization = `Bearer ${bundle.authData.access_token}`;
|
|
122
|
+
}
|
|
123
|
+
return request;
|
|
124
|
+
};
|
|
125
|
+
expectType<BeforeRequestMiddleware>(addBearerHeader);
|
|
126
|
+
|
|
127
|
+
const checkPermissionsError: AfterResponseMiddleware = (response, z) => {
|
|
128
|
+
if (response.status === 403) {
|
|
129
|
+
throw new z.errors.Error(
|
|
130
|
+
response.json?.['o:errorDetails']?.[0].detail,
|
|
131
|
+
response.status.toString()
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
return response;
|
|
135
|
+
};
|
|
136
|
+
expectType<AfterResponseMiddleware>(checkPermissionsError);
|
|
137
|
+
|
|
138
|
+
const app: App = {
|
|
139
|
+
platformVersion: '0.0.1',
|
|
140
|
+
version: '0.0.1',
|
|
141
|
+
|
|
142
|
+
beforeRequest: [addBearerHeader],
|
|
143
|
+
afterResponse: [checkPermissionsError],
|
|
144
|
+
|
|
145
|
+
creates: { [create.key]: create },
|
|
146
|
+
triggers: {
|
|
147
|
+
[pollingTrigger.key]: pollingTrigger,
|
|
148
|
+
[hookTrigger.key]: hookTrigger,
|
|
149
|
+
},
|
|
150
|
+
searches: { [search.key]: search },
|
|
151
|
+
};
|
|
152
|
+
expectType<App>(app);
|
|
@@ -22,10 +22,6 @@ export const createAppTester: (
|
|
|
22
22
|
clearZcacheBeforeUse?: boolean
|
|
23
23
|
) => Promise<T>; // appTester always returns a promise
|
|
24
24
|
|
|
25
|
-
// internal only
|
|
26
|
-
// export const integrationTestHandler: () => any;
|
|
27
|
-
// export const createAppHandler: (appRaw: object) => any
|
|
28
|
-
|
|
29
25
|
type HttpMethod =
|
|
30
26
|
| 'GET'
|
|
31
27
|
| 'POST'
|
|
@@ -118,9 +114,9 @@ export interface HttpResponse extends BaseHttpResponse {
|
|
|
118
114
|
|
|
119
115
|
export interface RawHttpResponse extends BaseHttpResponse {
|
|
120
116
|
body: NodeJS.ReadableStream;
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
117
|
+
buffer(): Promise<Buffer>;
|
|
118
|
+
json(): Promise<object>;
|
|
119
|
+
text(): Promise<string>;
|
|
124
120
|
}
|
|
125
121
|
|
|
126
122
|
type DehydrateFunc = <T>(
|
|
@@ -204,3 +200,26 @@ export interface ZObject {
|
|
|
204
200
|
delete: (key: string) => Promise<boolean>;
|
|
205
201
|
};
|
|
206
202
|
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* A function that performs the action.
|
|
206
|
+
*
|
|
207
|
+
* @template BI The shape of data in the `bundle.inputData` object.
|
|
208
|
+
* @template R The return type of the function.
|
|
209
|
+
*/
|
|
210
|
+
export type PerformFunction<BI = Record<string, any>, R = any> = (
|
|
211
|
+
z: ZObject,
|
|
212
|
+
bundle: Bundle<BI>
|
|
213
|
+
) => Promise<R>;
|
|
214
|
+
|
|
215
|
+
export type BeforeRequestMiddleware = (
|
|
216
|
+
request: HttpRequestOptions,
|
|
217
|
+
z?: ZObject,
|
|
218
|
+
bundle?: Bundle
|
|
219
|
+
) => HttpRequestOptions;
|
|
220
|
+
|
|
221
|
+
export type AfterResponseMiddleware = (
|
|
222
|
+
response: HttpResponse,
|
|
223
|
+
z: ZObject,
|
|
224
|
+
bundle?: Bundle
|
|
225
|
+
) => HttpResponse;
|