zapier-platform-core 17.4.0 → 17.6.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/index.js CHANGED
@@ -1,4 +1,6 @@
1
1
  const zapier = require('./src');
2
2
  zapier.version = require('./package.json').version;
3
3
  zapier.tools = require('./src/tools/exported');
4
+ zapier.errors = require('./src/errors');
5
+ zapier.console = require('./src/tools/console-singleton').consoleProxy;
4
6
  module.exports = zapier;
package/index.mjs CHANGED
@@ -1,8 +1,12 @@
1
1
  import zapier from './src/index.js';
2
2
  import packageJson from './package.json' with { type: 'json' };
3
3
  import _tools from './src/tools/exported.js';
4
+ import _errors from './src/errors.js';
5
+ import { consoleProxy } from './src/tools/console-singleton.js';
4
6
  zapier.version = packageJson.version;
5
7
  zapier.tools = _tools;
8
+ zapier.errors = _errors;
9
+ zapier.console = consoleProxy;
6
10
  // Allows `import { ... } from 'zapier-platform-core'`
7
11
  export const {
8
12
  createAppHandler,
@@ -14,8 +18,10 @@ export const {
14
18
  defineSearch,
15
19
  defineTrigger,
16
20
  integrationTestHandler,
21
+ console,
17
22
  tools,
18
23
  version,
24
+ errors,
19
25
  } = zapier;
20
26
  // Allows `import zapier from 'zapier-platform-core'`
21
27
  export default zapier;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zapier-platform-core",
3
- "version": "17.4.0",
3
+ "version": "17.6.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/",
@@ -56,14 +56,14 @@
56
56
  "content-disposition": "0.5.4",
57
57
  "dotenv": "16.5.0",
58
58
  "fernet": "^0.3.3",
59
- "form-data": "4.0.1",
59
+ "form-data": "4.0.4",
60
60
  "lodash": "4.17.21",
61
61
  "mime-types": "2.1.35",
62
62
  "node-abort-controller": "3.1.1",
63
63
  "node-fetch": "2.7.0",
64
64
  "oauth-sign": "0.9.0",
65
65
  "semver": "7.7.1",
66
- "zapier-platform-schema": "17.4.0"
66
+ "zapier-platform-schema": "17.6.0"
67
67
  },
68
68
  "devDependencies": {
69
69
  "@types/node-fetch": "^2.6.11",
@@ -10,7 +10,7 @@ const createJSONtool = require('../../tools/create-json-tool');
10
10
  const createStoreKeyTool = require('../../tools/create-storekey-tool');
11
11
  const createCallbackHigherOrderFunction = require('../../tools/create-callback-wrapper');
12
12
  const createLegacyScriptingRunner = require('../../tools/create-legacy-scripting-runner');
13
- const createLoggerConsole = require('../../tools/create-logger-console');
13
+ const { initialize } = require('../../tools/console-singleton');
14
14
  const errors = require('../../errors');
15
15
  const hashing = require('../../tools/hashing');
16
16
 
@@ -19,9 +19,10 @@ const hashing = require('../../tools/hashing');
19
19
  */
20
20
  const injectZObject = (input) => {
21
21
  const bundle = _.get(input, '_zapier.event.bundle', {});
22
+
22
23
  const zRoot = {
23
24
  cache: createCache(input),
24
- console: createLoggerConsole(input),
25
+ console: initialize(input),
25
26
  cursor: createStoreKeyTool(input),
26
27
  dehydrate: createDehydrator(input, 'method'),
27
28
  dehydrateFile: createDehydrator(input, 'file'),
package/src/index.js CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  const createLambdaHandler = require('./tools/create-lambda-handler');
4
4
  const createAppTester = require('./tools/create-app-tester');
5
+ const { consoleProxy } = require('./tools/console-singleton');
5
6
 
6
7
  let _integrationTestHandler;
7
8
  const integrationTestHandler = (event, context, callback) => {
@@ -15,5 +16,6 @@ module.exports = {
15
16
  createAppHandler: createLambdaHandler,
16
17
  createAppTester,
17
18
  integrationTestHandler,
19
+ console: consoleProxy,
18
20
  ...require('./typeHelpers'),
19
21
  };
@@ -0,0 +1,49 @@
1
+ 'use strict';
2
+
3
+ const createLoggerConsole = require('./create-logger-console');
4
+
5
+ /**
6
+ * Shared console instance that can be used standalone or as z.console.
7
+ * Uses createLoggerConsole to create the single instance shared between both.
8
+ */
9
+
10
+ // Shared console instance - will be initialized by middleware
11
+ let loggerConsole = null;
12
+
13
+ /**
14
+ * Initialize the console with the input context from middleware.
15
+ * This is called by the z-object middleware and uses createLoggerConsole.
16
+ * Creates a new logger console for each Lambda invocation to ensure proper isolation.
17
+ * Returns the shared console instance for z.console to use.
18
+ */
19
+ const initialize = (input) => {
20
+ // Always create a new logger console for each invocation to ensure
21
+ // log context isolation between Lambda invocations
22
+ loggerConsole = createLoggerConsole(input);
23
+ return loggerConsole;
24
+ };
25
+
26
+ /**
27
+ * Reset the singleton for testing purposes
28
+ */
29
+ const reset = () => {
30
+ loggerConsole = null;
31
+ };
32
+
33
+ /**
34
+ * Proxy that behaves like a console object.
35
+ * Forwards calls to loggerConsole if initialized, otherwise to global console.
36
+ */
37
+ const consoleProxy = new Proxy(console, {
38
+ get(target, prop, receiver) {
39
+ // Use loggerConsole if initialized, otherwise fall back to global console
40
+ const actualConsole = loggerConsole || target;
41
+ return Reflect.get(actualConsole, prop, actualConsole);
42
+ },
43
+ });
44
+
45
+ module.exports = {
46
+ consoleProxy,
47
+ initialize,
48
+ reset,
49
+ };
@@ -32,16 +32,68 @@ const LOG_STREAM_BYTES_LIMIT = 15 * 1024 * 1024;
32
32
 
33
33
  const DEFAULT_LOGGER_TIMEOUT = 200;
34
34
 
35
+ // Will be initialized lazily
36
+ const SAFE_AUTH_DATA_KEYS = new Set();
37
+
35
38
  const sleep = promisify(setTimeout);
36
39
 
37
- const isUrl = (url) => {
38
- try {
39
- // eslint-disable-next-line no-new
40
- new URL(url);
41
- return true;
42
- } catch (e) {
40
+ const initSafeAuthDataKeys = () => {
41
+ // An authData key in (safePrefixes x safeSuffixes) is considered safe to log
42
+ // uncensored
43
+ const safePrefixes = [
44
+ 'account',
45
+ 'bot_user',
46
+ 'cloud',
47
+ 'cloud_site',
48
+ 'company',
49
+ 'domain',
50
+ 'email',
51
+ 'environment',
52
+ 'location',
53
+ 'org',
54
+ 'organization',
55
+ 'project',
56
+ 'region',
57
+ 'scope',
58
+ 'scopes',
59
+ 'site',
60
+ 'subdomain',
61
+ 'team',
62
+ 'token_type',
63
+ 'user',
64
+ 'workspace',
65
+ ];
66
+ const safeSuffixes = ['', '_id', '_name', 'id', 'name'];
67
+ for (const prefix of safePrefixes) {
68
+ for (const suffix of safeSuffixes) {
69
+ SAFE_AUTH_DATA_KEYS.add(prefix + suffix);
70
+ }
71
+ }
72
+ };
73
+
74
+ const isUrl = (value) => {
75
+ if (!value || typeof value !== 'string') {
43
76
  return false;
44
77
  }
78
+ const commonProtocols = [
79
+ 'https://',
80
+ 'http://',
81
+ 'ftp://',
82
+ 'ftps://',
83
+ 'file://',
84
+ ];
85
+ for (const protocol of commonProtocols) {
86
+ if (value.startsWith(protocol)) {
87
+ try {
88
+ // eslint-disable-next-line no-new
89
+ new URL(value);
90
+ return true;
91
+ } catch (e) {
92
+ return false;
93
+ }
94
+ }
95
+ }
96
+ return false;
45
97
  };
46
98
 
47
99
  const MAX_LENGTH = 3500;
@@ -136,6 +188,13 @@ const attemptFindSecretsInStr = (s, isGettingNewSecret) => {
136
188
  return findSensitiveValues(parsedRespContent);
137
189
  };
138
190
 
191
+ const isSafeAuthDataKey = (key) => {
192
+ if (SAFE_AUTH_DATA_KEYS.size === 0) {
193
+ initSafeAuthDataKeys();
194
+ }
195
+ return SAFE_AUTH_DATA_KEYS.has(key.toLowerCase());
196
+ };
197
+
139
198
  const buildSensitiveValues = (event, data) => {
140
199
  const bundle = event.bundle || {};
141
200
  const authData = bundle.authData || {};
@@ -147,7 +206,9 @@ const buildSensitiveValues = (event, data) => {
147
206
  if (isSensitiveKey(key)) {
148
207
  return true;
149
208
  }
150
-
209
+ if (isSafeAuthDataKey(key)) {
210
+ return false;
211
+ }
151
212
  if (isUrl(value) && !isUrlWithSecrets(value)) {
152
213
  return false;
153
214
  }
@@ -0,0 +1,24 @@
1
+ import { expectType } from 'tsd';
2
+ import { console } from '..';
3
+
4
+ // Test that console is exported and has the right type
5
+ expectType<Console>(console);
6
+
7
+ // Test that console has expected methods with proper signatures
8
+ expectType<{
9
+ (...data: any[]): void;
10
+ (message?: any, ...optionalParams: any[]): void;
11
+ }>(console.log);
12
+ expectType<{
13
+ (...data: any[]): void;
14
+ (message?: any, ...optionalParams: any[]): void;
15
+ }>(console.error);
16
+ expectType<{
17
+ (...data: any[]): void;
18
+ (message?: any, ...optionalParams: any[]): void;
19
+ }>(console.warn);
20
+
21
+ // Test that console can be used for logging
22
+ console.log('test message');
23
+ console.error('test error');
24
+ console.warn('test warning');
package/types/custom.d.ts CHANGED
@@ -11,6 +11,8 @@ import { Headers } from 'node-fetch';
11
11
  // The EXPORTED OBJECT
12
12
  export const version: string;
13
13
  export const tools: { env: { inject: (filename?: string) => void } };
14
+ export const console: Console;
15
+ export const errors: ErrorsModule;
14
16
 
15
17
  // see: https://github.com/zapier/zapier-platform-cli/issues/339#issue-336888249
16
18
  export const createAppTester: (
@@ -138,19 +140,30 @@ export interface Bundle<
138
140
  targetUrl?: string;
139
141
  }
140
142
 
141
- declare class AppError extends Error {
142
- constructor(message: string, code?: string, status?: number);
143
- }
144
- declare class HaltedError extends Error {}
145
- declare class ExpiredAuthError extends Error {}
146
- declare class RefreshAuthError extends Error {}
147
- declare class ThrottledError extends Error {
148
- constructor(message: string, delay?: number);
149
- }
150
- declare class ResponseError extends Error {
151
- constructor(response: HttpResponse);
143
+ // Error class types that match the runtime structure from src/errors.js
144
+ type ErrorConstructor = new (message?: string) => Error;
145
+ type AppErrorConstructor = new (message: string, code?: string, status?: number) => Error;
146
+ type ThrottledErrorConstructor = new (message: string, delay?: number) => Error;
147
+ type ResponseErrorConstructor = new (response: HttpResponse) => Error;
148
+
149
+ interface ErrorsModule {
150
+ Error: AppErrorConstructor;
151
+ HaltedError: ErrorConstructor;
152
+ ExpiredAuthError: ErrorConstructor;
153
+ RefreshAuthError: ErrorConstructor;
154
+ ThrottledError: ThrottledErrorConstructor;
155
+ ResponseError: ResponseErrorConstructor;
156
+ CheckError: ErrorConstructor;
157
+ DehydrateError: ErrorConstructor;
158
+ MethodDoesNotExist: ErrorConstructor;
159
+ NotImplementedError: ErrorConstructor;
160
+ RequireModuleError: ErrorConstructor;
161
+ StashedBundleError: ErrorConstructor;
162
+ StopRequestError: ErrorConstructor;
163
+ handleError: (...args: any[]) => never;
152
164
  }
153
165
 
166
+
154
167
  // copied http stuff from external typings
155
168
  export interface HttpRequestOptions {
156
169
  agent?: Agent;
@@ -286,14 +299,7 @@ export interface ZObject {
286
299
  input_encoding?: string,
287
300
  ) => string;
288
301
 
289
- errors: {
290
- Error: typeof AppError;
291
- HaltedError: typeof HaltedError;
292
- ExpiredAuthError: typeof ExpiredAuthError;
293
- RefreshAuthError: typeof RefreshAuthError;
294
- ThrottledError: typeof ThrottledError;
295
- ResponseError: typeof ResponseError;
296
- };
302
+ errors: ErrorsModule;
297
303
 
298
304
  cache: {
299
305
  get: (key: string) => Promise<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: 17.3.1
7
+ * zapier-platform-schema version: 17.5.0
8
8
  * schema-to-ts compiler version: 0.1.0
9
9
  */
10
10
  import type {
@@ -704,7 +704,15 @@ export interface AuthField {
704
704
  label?: string;
705
705
 
706
706
  /** The type of this value used to be. */
707
- type?: 'string' | 'number' | 'boolean' | 'datetime' | 'copy' | 'password';
707
+ type?:
708
+ | 'string'
709
+ | 'number'
710
+ | 'boolean'
711
+ | 'datetime'
712
+ | 'copy'
713
+ | 'password'
714
+ | 'integer'
715
+ | 'text';
708
716
 
709
717
  /** If this value is required or not. This defaults to `true`. */
710
718
  required?: boolean;