@percy/sdk-utils 1.10.2 → 1.10.4

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/README.md CHANGED
@@ -43,8 +43,7 @@ percy.domScript === fs.readFile(require.resolve('@percy/dom'))
43
43
  Returns `true` or `false` if the Percy CLI API server is running. Calls the server's `/healthcheck`
44
44
  endpoint and populates information for the [`percy`](#percy) property. The result of this function
45
45
  is cached and subsequent calls will return the first cached result. If the healthcheck fails, will
46
- log a message unless the CLI loglevel is `quiet` or `silent`. Upon a successful health check, a
47
- remote logging connection is also established.
46
+ log a message unless the CLI loglevel is `quiet` or `silent`.
48
47
 
49
48
  ``` js
50
49
  import { isPercyEnabled } from '@percy/sdk-utils'
package/dist/bundle.js CHANGED
@@ -6,6 +6,53 @@
6
6
  process.env = process.env || {};
7
7
  process.env.__PERCY_BROWSERIFIED__ = true;
8
8
 
9
+ // Used when determining if a message should be logged
10
+ const LOG_LEVELS = {
11
+ debug: 0,
12
+ info: 1,
13
+ warn: 2,
14
+ error: 3
15
+ }; // Create a small logger util using the specified namespace
16
+
17
+ function logger(namespace) {
18
+ return Object.keys(LOG_LEVELS).reduce((ns, lvl) => Object.assign(ns, {
19
+ [lvl]: function () {
20
+ for (var _len = arguments.length, a = new Array(_len), _key = 0; _key < _len; _key++) {
21
+ a[_key] = arguments[_key];
22
+ }
23
+
24
+ return logger.log(namespace, lvl, ...a);
25
+ }
26
+ }), {});
27
+ }
28
+ Object.assign(logger, {
29
+ // Set and/or return the local loglevel
30
+ loglevel: function () {
31
+ let lvl = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : logger.loglevel.lvl;
32
+ return logger.loglevel.lvl = lvl || process.env.PERCY_LOGLEVEL || 'info';
33
+ },
34
+ // Track and send/write logs for the specified namespace and log level
35
+ log: (ns, lvl, msg, meta) => {
36
+ let err = typeof msg !== 'string' && (lvl === 'error' || lvl === 'debug'); // check if the specific level is within the local loglevel range
37
+
38
+ if (LOG_LEVELS[lvl] != null && LOG_LEVELS[lvl] >= LOG_LEVELS[logger.loglevel()]) {
39
+ let debug = logger.loglevel() === 'debug';
40
+ let label = debug ? `percy:${ns}` : 'percy'; // colorize the label when possible for consistency with the CLI logger
41
+
42
+ if (!process.env.__PERCY_BROWSERIFIED__) label = `\u001b[95m${label}\u001b[39m`;
43
+ msg = `[${label}] ${err && debug && msg.stack || msg}`;
44
+
45
+ if (process.env.__PERCY_BROWSERIFIED__) {
46
+ // use console[warn|error|log] in browsers
47
+ console[['warn', 'error'].includes(lvl) ? lvl : 'log'](msg);
48
+ } else {
49
+ // use process[stdout|stderr].write in node
50
+ process[lvl === 'info' ? 'stdout' : 'stderr'].write(msg + '\n');
51
+ }
52
+ }
53
+ }
54
+ });
55
+
9
56
  // helper to create a version object from a string
10
57
  function toVersion(str) {
11
58
  str || (str = '0.0.0');
@@ -65,145 +112,6 @@
65
112
 
66
113
  };
67
114
 
68
- const LOG_LEVELS = {
69
- debug: 0,
70
- info: 1,
71
- warn: 2,
72
- error: 3
73
- }; // Create a small logger util using the specified namespace
74
-
75
- function logger(namespace) {
76
- return Object.keys(LOG_LEVELS).reduce((ns, lvl) => Object.assign(ns, {
77
- [lvl]: function () {
78
- for (var _len = arguments.length, a = new Array(_len), _key = 0; _key < _len; _key++) {
79
- a[_key] = arguments[_key];
80
- }
81
-
82
- return logger.log(namespace, lvl, ...a);
83
- }
84
- }), {});
85
- } // Set and/or return the local loglevel
86
-
87
- const loglevel = logger.loglevel = lvl => {
88
- return loglevel.lvl = lvl || loglevel.lvl || process.env.PERCY_LOGLEVEL || 'info';
89
- }; // Track and send/write logs for the specified namespace and log level
90
-
91
-
92
- const log = logger.log = (ns, lvl, msg, meta) => {
93
- let err = typeof msg !== 'string' && (lvl === 'error' || lvl === 'debug');
94
- meta = {
95
- remote: true,
96
- ...meta
97
- };
98
-
99
- if (remote.socket) {
100
- // prefer remote logging when available and serialize any errors
101
- if (err) msg = {
102
- name: msg.name,
103
- message: msg.message,
104
- stack: msg.stack
105
- };
106
- return remote.socket.send(JSON.stringify({
107
- log: [ns, lvl, msg, meta]
108
- }));
109
- } else {
110
- // keep log history of full message when not remote
111
- let message = err ? msg.stack : msg.toString();
112
- let [debug, level, timestamp, error] = [ns, lvl, Date.now(), !!err];
113
- (log.history || (log.history = [])).push({
114
- debug,
115
- level,
116
- message,
117
- meta,
118
- timestamp,
119
- error
120
- });
121
- } // check if the specific level is within the local loglevel range
122
-
123
-
124
- if (LOG_LEVELS[lvl] != null && LOG_LEVELS[lvl] >= LOG_LEVELS[loglevel()]) {
125
- let debug = loglevel() === 'debug';
126
- let label = debug ? `percy:${ns}` : 'percy'; // colorize the label when possible for consistency with the CLI logger
127
-
128
- if (!process.env.__PERCY_BROWSERIFIED__) label = `\u001b[95m${label}\u001b[39m`;
129
- msg = `[${label}] ${err && debug && msg.stack || msg}`;
130
-
131
- if (process.env.__PERCY_BROWSERIFIED__) {
132
- // use console[warn|error|log] in browsers
133
- console[['warn', 'error'].includes(lvl) ? lvl : 'log'](msg);
134
- } else {
135
- // use process[stdout|stderr].write in node
136
- process[lvl === 'info' ? 'stdout' : 'stderr'].write(msg + '\n');
137
- }
138
- }
139
- }; // Create a new WebSocket and resolve with it once connected
140
-
141
-
142
- function createWebSocket(address) {
143
- let timeout = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1000;
144
- return new Promise((resolve, reject) => {
145
- let ws;
146
-
147
- let done = e => {
148
- var _ws, _ws$_socket;
149
-
150
- (_ws = ws) === null || _ws === void 0 ? void 0 : (_ws$_socket = _ws._socket) === null || _ws$_socket === void 0 ? void 0 : _ws$_socket.unref();
151
- clearTimeout(timeoutid);
152
- /* istanbul ignore else: edge case */
153
-
154
- if (ws) ws.onopen = ws.onerror = null;
155
- if (!e.error && e.type !== 'error') return resolve(ws);else reject(e.error || 'Error: Socket connection failed');
156
- };
157
-
158
- let timeoutid = setTimeout(done, timeout, {
159
- error: 'Error: Socket connection timed out'
160
- });
161
- Promise.resolve(process.env.__PERCY_BROWSERIFIED__
162
- /* eslint-disable-next-line import/no-extraneous-dependencies */
163
- ? {
164
- default: window.WebSocket
165
- } : ({})).then(_ref => {
166
- let {
167
- default: WS
168
- } = _ref;
169
- ws = new WS(address.replace(/^http/, 'ws'));
170
- ws.onopen = ws.onerror = done;
171
- }, reject);
172
- });
173
- } // Connect to a remote logger at the specified address within the timeout
174
-
175
-
176
- const remote = logger.remote = async timeout => {
177
- try {
178
- var _remote$socket;
179
-
180
- // already connected
181
- if (((_remote$socket = remote.socket) === null || _remote$socket === void 0 ? void 0 : _remote$socket.readyState) === 1) return; // connect to namespaced logging address
182
-
183
- let address = new URL('/logger', info.address).href; // create and cache a websocket connection
184
-
185
- let ws = remote.socket = await createWebSocket(address, timeout);
186
- await new Promise((resolve, reject) => {
187
- // accept loglevel updates and resolve after first message
188
- ws.onmessage = e => resolve(loglevel(JSON.parse(e.data).loglevel));
189
-
190
- ws.onclose = () => {
191
- // cleanup listeners and reject if not resolved
192
- remote.socket = ws.onmessage = ws.onclose = null;
193
- reject(new Error('Connection closed'));
194
- };
195
- }); // send any messages already logged in this environment
196
-
197
- if (log.history) ws.send(JSON.stringify({
198
- messages: log.history
199
- }));
200
- } catch (err) {
201
- // there was an error connecting, will fallback to minimal logging
202
- logger.log('utils', 'debug', 'Unable to connect to remote logger');
203
- logger.log('utils', 'debug', err);
204
- }
205
- };
206
-
207
115
  async function request(path) {
208
116
  let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
209
117
  let response = await request.fetch(`${info.address}${path}`, options); // maybe parse response body as json
@@ -292,10 +200,6 @@
292
200
  log.info('Percy is not running, disabling snapshots');
293
201
  log.debug(error);
294
202
  }
295
-
296
- if (info.enabled) {
297
- await logger.remote();
298
- }
299
203
  }
300
204
 
301
205
  return info.enabled;
package/dist/logger.js CHANGED
@@ -5,15 +5,6 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.default = void 0;
7
7
  exports.logger = logger;
8
-
9
- var _percyInfo = _interopRequireDefault(require("./percy-info.js"));
10
-
11
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
12
-
13
- function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
14
-
15
- function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
16
-
17
8
  // Used when determining if a message should be logged
18
9
  const LOG_LEVELS = {
19
10
  debug: 0,
@@ -26,126 +17,33 @@ function logger(namespace) {
26
17
  return Object.keys(LOG_LEVELS).reduce((ns, lvl) => Object.assign(ns, {
27
18
  [lvl]: (...a) => logger.log(namespace, lvl, ...a)
28
19
  }), {});
29
- } // Set and/or return the local loglevel
30
-
31
-
32
- const loglevel = logger.loglevel = lvl => {
33
- return loglevel.lvl = lvl || loglevel.lvl || process.env.PERCY_LOGLEVEL || 'info';
34
- }; // Track and send/write logs for the specified namespace and log level
35
-
36
-
37
- const log = logger.log = (ns, lvl, msg, meta) => {
38
- let err = typeof msg !== 'string' && (lvl === 'error' || lvl === 'debug');
39
- meta = {
40
- remote: true,
41
- ...meta
42
- };
43
-
44
- if (remote.socket) {
45
- // prefer remote logging when available and serialize any errors
46
- if (err) msg = {
47
- name: msg.name,
48
- message: msg.message,
49
- stack: msg.stack
50
- };
51
- return remote.socket.send(JSON.stringify({
52
- log: [ns, lvl, msg, meta]
53
- }));
54
- } else {
55
- // keep log history of full message when not remote
56
- let message = err ? msg.stack : msg.toString();
57
- let [debug, level, timestamp, error] = [ns, lvl, Date.now(), !!err];
58
- (log.history || (log.history = [])).push({
59
- debug,
60
- level,
61
- message,
62
- meta,
63
- timestamp,
64
- error
65
- });
66
- } // check if the specific level is within the local loglevel range
67
-
68
-
69
- if (LOG_LEVELS[lvl] != null && LOG_LEVELS[lvl] >= LOG_LEVELS[loglevel()]) {
70
- let debug = loglevel() === 'debug';
71
- let label = debug ? `percy:${ns}` : 'percy'; // colorize the label when possible for consistency with the CLI logger
72
-
73
- if (!process.env.__PERCY_BROWSERIFIED__) label = `\u001b[95m${label}\u001b[39m`;
74
- msg = `[${label}] ${err && debug && msg.stack || msg}`;
75
-
76
- if (process.env.__PERCY_BROWSERIFIED__) {
77
- // use console[warn|error|log] in browsers
78
- console[['warn', 'error'].includes(lvl) ? lvl : 'log'](msg);
79
- } else {
80
- // use process[stdout|stderr].write in node
81
- process[lvl === 'info' ? 'stdout' : 'stderr'].write(msg + '\n');
20
+ }
21
+
22
+ Object.assign(logger, {
23
+ // Set and/or return the local loglevel
24
+ loglevel: (lvl = logger.loglevel.lvl) => {
25
+ return logger.loglevel.lvl = lvl || process.env.PERCY_LOGLEVEL || 'info';
26
+ },
27
+ // Track and send/write logs for the specified namespace and log level
28
+ log: (ns, lvl, msg, meta) => {
29
+ let err = typeof msg !== 'string' && (lvl === 'error' || lvl === 'debug'); // check if the specific level is within the local loglevel range
30
+
31
+ if (LOG_LEVELS[lvl] != null && LOG_LEVELS[lvl] >= LOG_LEVELS[logger.loglevel()]) {
32
+ let debug = logger.loglevel() === 'debug';
33
+ let label = debug ? `percy:${ns}` : 'percy'; // colorize the label when possible for consistency with the CLI logger
34
+
35
+ if (!process.env.__PERCY_BROWSERIFIED__) label = `\u001b[95m${label}\u001b[39m`;
36
+ msg = `[${label}] ${err && debug && msg.stack || msg}`;
37
+
38
+ if (process.env.__PERCY_BROWSERIFIED__) {
39
+ // use console[warn|error|log] in browsers
40
+ console[['warn', 'error'].includes(lvl) ? lvl : 'log'](msg);
41
+ } else {
42
+ // use process[stdout|stderr].write in node
43
+ process[lvl === 'info' ? 'stdout' : 'stderr'].write(msg + '\n');
44
+ }
82
45
  }
83
46
  }
84
- }; // Create a new WebSocket and resolve with it once connected
85
-
86
-
87
- function createWebSocket(address, timeout = 1000) {
88
- return new Promise((resolve, reject) => {
89
- let ws;
90
-
91
- let done = e => {
92
- var _ws, _ws$_socket;
93
-
94
- (_ws = ws) === null || _ws === void 0 ? void 0 : (_ws$_socket = _ws._socket) === null || _ws$_socket === void 0 ? void 0 : _ws$_socket.unref();
95
- clearTimeout(timeoutid);
96
- /* istanbul ignore else: edge case */
97
-
98
- if (ws) ws.onopen = ws.onerror = null;
99
- if (!e.error && e.type !== 'error') return resolve(ws);else reject(e.error || 'Error: Socket connection failed');
100
- };
101
-
102
- let timeoutid = setTimeout(done, timeout, {
103
- error: 'Error: Socket connection timed out'
104
- });
105
- Promise.resolve(process.env.__PERCY_BROWSERIFIED__
106
- /* eslint-disable-next-line import/no-extraneous-dependencies */
107
- ? {
108
- default: window.WebSocket
109
- } : Promise.resolve().then(() => _interopRequireWildcard(require('ws')))).then(({
110
- default: WS
111
- }) => {
112
- ws = new WS(address.replace(/^http/, 'ws'));
113
- ws.onopen = ws.onerror = done;
114
- }, reject);
115
- });
116
- } // Connect to a remote logger at the specified address within the timeout
117
-
118
-
119
- const remote = logger.remote = async timeout => {
120
- try {
121
- var _remote$socket;
122
-
123
- // already connected
124
- if (((_remote$socket = remote.socket) === null || _remote$socket === void 0 ? void 0 : _remote$socket.readyState) === 1) return; // connect to namespaced logging address
125
-
126
- let address = new URL('/logger', _percyInfo.default.address).href; // create and cache a websocket connection
127
-
128
- let ws = remote.socket = await createWebSocket(address, timeout);
129
- await new Promise((resolve, reject) => {
130
- // accept loglevel updates and resolve after first message
131
- ws.onmessage = e => resolve(loglevel(JSON.parse(e.data).loglevel));
132
-
133
- ws.onclose = () => {
134
- // cleanup listeners and reject if not resolved
135
- remote.socket = ws.onmessage = ws.onclose = null;
136
- reject(new Error('Connection closed'));
137
- };
138
- }); // send any messages already logged in this environment
139
-
140
- if (log.history) ws.send(JSON.stringify({
141
- messages: log.history
142
- }));
143
- } catch (err) {
144
- // there was an error connecting, will fallback to minimal logging
145
- logger.log('utils', 'debug', 'Unable to connect to remote logger');
146
- logger.log('utils', 'debug', err);
147
- }
148
- };
149
-
47
+ });
150
48
  var _default = logger;
151
49
  exports.default = _default;
@@ -38,10 +38,6 @@ async function isPercyEnabled() {
38
38
  log.info('Percy is not running, disabling snapshots');
39
39
  log.debug(error);
40
40
  }
41
-
42
- if (_percyInfo.default.enabled) {
43
- await _logger.default.remote();
44
- }
45
41
  }
46
42
 
47
43
  return _percyInfo.default.enabled;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@percy/sdk-utils",
3
- "version": "1.10.2",
3
+ "version": "1.10.4",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -50,5 +50,5 @@
50
50
  ]
51
51
  }
52
52
  },
53
- "gitHead": "66527175cdac3848157be7dd8368f5845d98e77e"
53
+ "gitHead": "16a9a410bfcb8eab51b86a08cff12d8d35e4747e"
54
54
  }
package/test/client.js CHANGED
@@ -16,6 +16,9 @@
16
16
  const utils = require$$0__default["default"];
17
17
  const helpers = {
18
18
  async setupTest() {
19
+ let {
20
+ logger = true
21
+ } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
19
22
  utils.percy.version = '';
20
23
  delete utils.percy.config;
21
24
  delete utils.percy.enabled;
@@ -24,8 +27,9 @@
24
27
  delete utils.logger.loglevel.lvl;
25
28
  delete process.env.PERCY_LOGLEVEL;
26
29
  delete process.env.PERCY_SERVER_ADDRESS;
30
+ utils.logger.log = helpers.logger.__log__;
31
+ if (logger) helpers.logger.mock();
27
32
  await helpers.test('reset');
28
- await utils.logger.remote();
29
33
  },
30
34
 
31
35
  async test(cmd, arg) {
@@ -41,8 +45,32 @@
41
45
 
42
46
  get testSnapshotURL() {
43
47
  return `${utils.percy.address}/test/snapshot`;
44
- }
48
+ },
49
+
50
+ logger: {
51
+ __log__: utils.logger.log,
52
+ loglevel: utils.logger.loglevel,
53
+ stdout: [],
54
+ stderr: [],
55
+
56
+ mock() {
57
+ helpers.logger.reset();
45
58
 
59
+ utils.logger.log = (ns, lvl, msg) => {
60
+ if (lvl === 'debug' && helpers.logger.loglevel.lvl !== 'debug') return;
61
+ msg = `[percy${lvl === 'debug' ? `:${ns}` : ''}] ${msg}`;
62
+ let io = lvl === 'info' ? 'stdout' : 'stderr';
63
+ helpers.logger[io].push(msg);
64
+ };
65
+ },
66
+
67
+ reset() {
68
+ helpers.logger.stdout = [];
69
+ helpers.logger.stderr = [];
70
+ helpers.logger.loglevel('info');
71
+ }
72
+
73
+ }
46
74
  };
47
75
  var helpers_1 = helpers;
48
76
 
package/test/helpers.js CHANGED
@@ -1,7 +1,7 @@
1
1
  const utils = require('@percy/sdk-utils');
2
2
 
3
3
  const helpers = {
4
- async setupTest() {
4
+ async setupTest({ logger = true } = {}) {
5
5
  utils.percy.version = '';
6
6
  delete utils.percy.config;
7
7
  delete utils.percy.enabled;
@@ -10,8 +10,9 @@ const helpers = {
10
10
  delete utils.logger.loglevel.lvl;
11
11
  delete process.env.PERCY_LOGLEVEL;
12
12
  delete process.env.PERCY_SERVER_ADDRESS;
13
+ utils.logger.log = helpers.logger.__log__;
14
+ if (logger) helpers.logger.mock();
13
15
  await helpers.test('reset');
14
- await utils.logger.remote();
15
16
  },
16
17
 
17
18
  async test(cmd, arg) {
@@ -27,6 +28,30 @@ const helpers = {
27
28
 
28
29
  get testSnapshotURL() {
29
30
  return `${utils.percy.address}/test/snapshot`;
31
+ },
32
+
33
+ logger: {
34
+ __log__: utils.logger.log,
35
+ loglevel: utils.logger.loglevel,
36
+ stdout: [],
37
+ stderr: [],
38
+
39
+ mock() {
40
+ helpers.logger.reset();
41
+
42
+ utils.logger.log = (ns, lvl, msg) => {
43
+ if (lvl === 'debug' && helpers.logger.loglevel.lvl !== 'debug') return;
44
+ msg = `[percy${lvl === 'debug' ? `:${ns}` : ''}] ${msg}`;
45
+ let io = (lvl === 'info') ? 'stdout' : 'stderr';
46
+ helpers.logger[io].push(msg);
47
+ };
48
+ },
49
+
50
+ reset() {
51
+ helpers.logger.stdout = [];
52
+ helpers.logger.stderr = [];
53
+ helpers.logger.loglevel('info');
54
+ }
30
55
  }
31
56
  };
32
57