@percy/core 1.0.0-beta.9 → 1.0.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/dist/percy.js DELETED
@@ -1,428 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.default = void 0;
7
-
8
- var _client = _interopRequireDefault(require("@percy/client"));
9
-
10
- var _config = _interopRequireDefault(require("@percy/config"));
11
-
12
- var _logger = _interopRequireDefault(require("@percy/logger"));
13
-
14
- var _config2 = require("./config");
15
-
16
- var _discoverer = _interopRequireDefault(require("./discoverer"));
17
-
18
- var _percyCss = _interopRequireDefault(require("./percy-css"));
19
-
20
- var _server = require("./server");
21
-
22
- var _queue = _interopRequireDefault(require("./queue"));
23
-
24
- var _assert = _interopRequireDefault(require("./utils/assert"));
25
-
26
- var _resources = require("./utils/resources");
27
-
28
- var _url = require("./utils/url");
29
-
30
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
31
-
32
- function _classPrivateFieldGet(receiver, privateMap) { var descriptor = privateMap.get(receiver); if (!descriptor) { throw new TypeError("attempted to get private field on non-instance"); } if (descriptor.get) { return descriptor.get.call(receiver); } return descriptor.value; }
33
-
34
- function _classPrivateFieldSet(receiver, privateMap, value) { var descriptor = privateMap.get(receiver); if (!descriptor) { throw new TypeError("attempted to set private field on non-instance"); } if (descriptor.set) { descriptor.set.call(receiver, value); } else { if (!descriptor.writable) { throw new TypeError("attempted to set read only private field"); } descriptor.value = value; } return value; }
35
-
36
- // Register core config options
37
- _config.default.addSchema(_config2.schema); // A Percy instance will create a new build when started, handle snapshot
38
- // creation, asset discovery, and resource uploads, and will finalize the build
39
- // when stopped. Snapshots are processed concurrently and the build is not
40
- // finalized until all snapshots have been handled.
41
-
42
-
43
- var _captures = new WeakMap();
44
-
45
- var _snapshots = new WeakMap();
46
-
47
- var _stopping = new WeakMap();
48
-
49
- var _running = new WeakMap();
50
-
51
- class Percy {
52
- // Static shortcut to create and start an instance in one call
53
- static async start(options) {
54
- let instance = new this(options);
55
- await instance.start();
56
- return instance;
57
- }
58
-
59
- constructor({
60
- // provided to @percy/client
61
- token,
62
- clientInfo = '',
63
- environmentInfo = '',
64
- // snapshot server options
65
- server = true,
66
- port = 5338,
67
- // capture concurrency
68
- concurrency = 5,
69
- // initial log level
70
- loglevel,
71
- // configuration filepath
72
- config,
73
- // options such as `snapshot` and `discovery` that are valid Percy config
74
- // options which will become accessible via the `#config` property
75
- ...options
76
- } = {}) {
77
- _captures.set(this, {
78
- writable: true,
79
- value: null
80
- });
81
-
82
- _snapshots.set(this, {
83
- writable: true,
84
- value: null
85
- });
86
-
87
- _stopping.set(this, {
88
- writable: true,
89
- value: false
90
- });
91
-
92
- _running.set(this, {
93
- writable: true,
94
- value: false
95
- });
96
-
97
- if (loglevel) {
98
- this.loglevel(loglevel);
99
- }
100
-
101
- if (server) {
102
- this.port = port;
103
- this.app = (0, _server.createServerApp)(this);
104
- }
105
-
106
- _classPrivateFieldSet(this, _snapshots, new _queue.default());
107
-
108
- _classPrivateFieldSet(this, _captures, new _queue.default(concurrency));
109
-
110
- this.config = config === false ? _config.default.getDefaults(options) : _config.default.load({
111
- path: config,
112
- overrides: options
113
- });
114
- this.discoverer = new _discoverer.default(this.config.discovery);
115
- this.client = new _client.default({
116
- token,
117
- clientInfo,
118
- environmentInfo
119
- });
120
- } // Shortcut for controlling the global logger's log level.
121
-
122
-
123
- loglevel(level) {
124
- return _logger.default.loglevel(level);
125
- } // Snapshot server API address
126
-
127
-
128
- apiAddress() {
129
- var _this$server, _address;
130
-
131
- let {
132
- address
133
- } = ((_this$server = this.server) === null || _this$server === void 0 ? void 0 : _this$server.address()) || {};
134
- address = ((_address = address) === null || _address === void 0 ? void 0 : _address.includes(':')) ? `[${address}]` : address;
135
- return address && `http://${address}:${this.port}/percy`;
136
- } // Returns a boolean indicating if this instance is running.
137
-
138
-
139
- isRunning() {
140
- return _classPrivateFieldGet(this, _running);
141
- } // Starts the local API server, the asset discovery process, and creates a new
142
- // Percy build. When an error is encountered, the discoverer and server are closed.
143
-
144
-
145
- async start() {
146
- // throws when the token is missing
147
- this.client.getToken();
148
-
149
- try {
150
- // if there is an exress app, a server should be started
151
- if (this.app) {
152
- this.server = await (0, _server.startServer)(this.app, this.port);
153
- } // launch the discoverer browser and create a percy build
154
-
155
-
156
- await this.discoverer.launch();
157
- await this.client.createBuild(); // log build details
158
-
159
- let build = this.client.build;
160
- let meta = {
161
- build: {
162
- id: build.id
163
- }
164
- };
165
-
166
- _logger.default.info('Percy has started!', meta);
167
-
168
- _logger.default.info(`Created build #${build.number}: ${build.url}`, meta); // mark this process as running
169
-
170
-
171
- _classPrivateFieldSet(this, _running, true);
172
- } catch (error) {
173
- var _this$server2;
174
-
175
- // on error, close any running browser or server
176
- await this.discoverer.close();
177
- (_this$server2 = this.server) === null || _this$server2 === void 0 ? void 0 : _this$server2.close(); // throw an easier-to understand error when the port is taken
178
-
179
- if (error.code === 'EADDRINUSE') {
180
- throw new Error('Percy is already running or the port is in use');
181
- } else {
182
- throw error;
183
- }
184
- }
185
- } // Stops the local API server and discoverer once snapshots have completed and
186
- // finalizes the Percy build. Does nothing if not running.
187
-
188
-
189
- async stop() {
190
- // do nothing if not running or already stopping
191
- if (this.isRunning() && !_classPrivateFieldGet(this, _stopping)) {
192
- var _this$server3;
193
-
194
- _classPrivateFieldSet(this, _stopping, true);
195
-
196
- let build = this.client.build;
197
- let meta = {
198
- build: {
199
- id: build.id
200
- }
201
- };
202
-
203
- _logger.default.info('Stopping percy...', meta); // log about queued captures or uploads
204
-
205
-
206
- if (_classPrivateFieldGet(this, _captures).length) {
207
- _logger.default.info(`Waiting for ${_classPrivateFieldGet(this, _captures).length} page(s) to finish snapshotting`, meta);
208
- } else if (_classPrivateFieldGet(this, _snapshots).length) {
209
- _logger.default.info(`Waiting for ${_classPrivateFieldGet(this, _snapshots).length} snapshot(s) to finish uploading`, meta);
210
- } // wait for any queued captures or snapshots
211
-
212
-
213
- await this.idle(); // close the server and browser
214
-
215
- (_this$server3 = this.server) === null || _this$server3 === void 0 ? void 0 : _this$server3.close();
216
- await this.discoverer.close();
217
-
218
- _classPrivateFieldSet(this, _running, false); // log build info
219
-
220
-
221
- await this.client.finalizeBuild();
222
-
223
- _logger.default.info(`Finalized build #${build.number}: ${build.url}`, meta);
224
-
225
- _logger.default.info('Done!');
226
- }
227
- } // Resolves when captures and snapshots are idle.
228
-
229
-
230
- async idle() {
231
- await Promise.all([_classPrivateFieldGet(this, _captures).idle(), _classPrivateFieldGet(this, _snapshots).idle()]);
232
- } // Handles asset discovery for the URL and DOM snapshot at each requested
233
- // width with the provided options. Resolves when the snapshot has been taken
234
- // and asset discovery is finished, but does not gaurantee that the snapshot
235
- // will be succesfully uploaded.
236
-
237
-
238
- snapshot({
239
- url,
240
- name,
241
- domSnapshot,
242
- widths,
243
- minHeight,
244
- percyCSS,
245
- requestHeaders,
246
- enableJavaScript,
247
- clientInfo,
248
- environmentInfo
249
- }) {
250
- var _widths, _widths2, _minHeight, _ref, _enableJavaScript;
251
-
252
- // required assertions
253
- (0, _assert.default)(this.isRunning(), 'Not running');
254
- (0, _assert.default)(url, 'Missing required argument: url');
255
- (0, _assert.default)(name, 'Missing required argument: name');
256
- (0, _assert.default)(domSnapshot, 'Missing required argument: domSnapshot'); // fallback to instance snapshot widths
257
-
258
- widths = ((_widths = widths) === null || _widths === void 0 ? void 0 : _widths.length) ? widths : this.config.snapshot.widths;
259
- (0, _assert.default)((_widths2 = widths) === null || _widths2 === void 0 ? void 0 : _widths2.length, 'Missing required argument: widths');
260
- (0, _assert.default)(widths.length <= 10, 'too many widths'); // normalize the URL
261
-
262
- url = (0, _url.normalizeURL)(url); // fallback to instance minimum height
263
-
264
- minHeight = (_minHeight = minHeight) !== null && _minHeight !== void 0 ? _minHeight : this.config.snapshot.minHeight; // combine snapshot Percy CSS with instance Percy CSS
265
-
266
- percyCSS = [this.config.snapshot.percyCSS, percyCSS].filter(Boolean).join('\n'); // combine snapshot request headers with instance request headers
267
-
268
- requestHeaders = { ...this.config.snapshot.requestHeaders,
269
- ...requestHeaders
270
- }; // fallback to instance enable JS flag
271
-
272
- enableJavaScript = (_ref = (_enableJavaScript = enableJavaScript) !== null && _enableJavaScript !== void 0 ? _enableJavaScript : this.config.snapshot.enableJavaScript) !== null && _ref !== void 0 ? _ref : false; // useful meta info for the logfile
273
-
274
- let meta = {
275
- snapshot: {
276
- name
277
- },
278
- build: {
279
- id: this.client.build.id
280
- }
281
- };
282
-
283
- _logger.default.debug('---------');
284
-
285
- _logger.default.debug('Handling snapshot:', meta);
286
-
287
- _logger.default.debug(`-> name: ${name}`, meta);
288
-
289
- _logger.default.debug(`-> url: ${url}`, meta);
290
-
291
- _logger.default.debug(`-> widths: ${widths.join('px, ')}px`, meta);
292
-
293
- _logger.default.debug(`-> clientInfo: ${clientInfo}`, meta);
294
-
295
- _logger.default.debug(`-> environmentInfo: ${environmentInfo}`, meta);
296
-
297
- _logger.default.debug(`-> requestHeaders: ${JSON.stringify(requestHeaders)}`, meta);
298
-
299
- _logger.default.debug(`-> domSnapshot:\n${domSnapshot.length <= 1024 ? domSnapshot : domSnapshot.substr(0, 1024) + '... [truncated]'}`, meta); // use a promise as a try-catch so we can do the remaining work
300
- // asynchronously, but perform the above synchronously
301
-
302
-
303
- return Promise.resolve().then(async () => {
304
- // inject Percy CSS
305
- let [percyDOM, percyCSSResource] = (0, _percyCss.default)(url, domSnapshot, percyCSS, meta); // use a map so resources remain unique by url
306
-
307
- let resources = new Map([[url, (0, _resources.createRootResource)(url, percyDOM)]]); // include the Percy CSS resource if there was one
308
-
309
- if (percyCSSResource) resources.set('percy-css', percyCSSResource); // gather resources at each width concurrently
310
-
311
- await Promise.all(widths.map(width => this.discoverer.gatherResources(resources, {
312
- rootUrl: url,
313
- rootDom: domSnapshot,
314
- enableJavaScript,
315
- requestHeaders,
316
- width,
317
- meta
318
- }))); // include a log resource for debugging
319
-
320
- let logs = await _logger.default.query({
321
- filter: ({
322
- snapshot: s
323
- }) => (s === null || s === void 0 ? void 0 : s.name) === name
324
- });
325
- resources.set('percy-logs', (0, _resources.createLogResource)(logs)); // log that the snapshot has been taken before uploading it
326
-
327
- _logger.default.info(`Snapshot taken: ${name}`, meta); // upload within the async snapshot queue
328
-
329
-
330
- _classPrivateFieldGet(this, _snapshots).push(() => this.client.sendSnapshot({
331
- name,
332
- widths,
333
- minHeight,
334
- enableJavaScript,
335
- clientInfo,
336
- environmentInfo,
337
- resources: Array.from(resources.values())
338
- }).catch(error => {
339
- _logger.default.error(`Encountered an error uploading snapshot: ${name}`, meta);
340
-
341
- _logger.default.error(error);
342
- }));
343
- }).catch(error => {
344
- _logger.default.error(`Encountered an error taking snapshot: ${name}`, meta);
345
-
346
- _logger.default.error(error);
347
- });
348
- }
349
-
350
- capture({
351
- url,
352
- name,
353
- waitFor,
354
- execute,
355
- snapshots = [],
356
- ...options
357
- }) {
358
- (0, _assert.default)(this.isRunning(), 'Not running');
359
- (0, _assert.default)(url, `Missing URL for${name ? ` ${name}` : ' snapshots'}`);
360
- snapshots = name ? [{
361
- name,
362
- execute
363
- }].concat(snapshots) : snapshots;
364
- (0, _assert.default)(snapshots.length && snapshots.every(s => s.name), `Missing name for ${url}`); // the entire capture process happens within the async capture queue
365
-
366
- return _classPrivateFieldGet(this, _captures).push(async () => {
367
- let results = [];
368
- let page;
369
-
370
- try {
371
- // borrow a page from the discoverer
372
- page = await this.discoverer.page(); // allow @percy/dom injection
373
-
374
- await page.setBypassCSP(true); // set any request headers
375
-
376
- await page.setExtraHTTPHeaders(options.requestHeaders || {}); // @todo - resize viewport
377
- // go to and wait for network idle
378
-
379
- await page.goto(url, {
380
- waitUntil: 'networkidle2'
381
- }); // inject @percy/dom for serialization
382
-
383
- await page.addScriptTag({
384
- path: require.resolve('@percy/dom')
385
- }); // wait for any other elements or timeout before snapshotting
386
-
387
- if (waitFor) await page.waitFor(waitFor); // multiple snapshots can be captured on a single page
388
-
389
- for (let {
390
- name,
391
- execute
392
- } of snapshots) {
393
- // optionally execute a script to interact with the page
394
- if (execute) await execute(page); // serialize and capture a DOM snapshot
395
-
396
- /* istanbul ignore next: no instrumenting injected code */
397
-
398
- let domSnapshot = await page.evaluate(({
399
- enableJavaScript
400
- }) =>
401
- /* eslint-disable-next-line no-undef */
402
- PercyDOM.serialize({
403
- enableJavaScript
404
- }), options); // snapshots are awaited on concurrently after sequentially capturing their DOM
405
-
406
- results.push(this.snapshot({ ...options,
407
- url,
408
- name,
409
- domSnapshot
410
- }));
411
- }
412
- } catch (error) {
413
- _logger.default.error(`Encountered an error for page: ${url}`);
414
-
415
- _logger.default.error(error);
416
- } finally {
417
- var _page;
418
-
419
- // await on any resulting snapshots
420
- await Promise.all(results);
421
- await ((_page = page) === null || _page === void 0 ? void 0 : _page.close());
422
- }
423
- });
424
- }
425
-
426
- }
427
-
428
- exports.default = Percy;
package/dist/queue.js DELETED
@@ -1,103 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.default = void 0;
7
-
8
- var _idle = _interopRequireDefault(require("./utils/idle"));
9
-
10
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
-
12
- function _classPrivateFieldSet(receiver, privateMap, value) { var descriptor = privateMap.get(receiver); if (!descriptor) { throw new TypeError("attempted to set private field on non-instance"); } if (descriptor.set) { descriptor.set.call(receiver, value); } else { if (!descriptor.writable) { throw new TypeError("attempted to set read only private field"); } descriptor.value = value; } return value; }
13
-
14
- function _classPrivateFieldGet(receiver, privateMap) { var descriptor = privateMap.get(receiver); if (!descriptor) { throw new TypeError("attempted to get private field on non-instance"); } if (descriptor.get) { return descriptor.get.call(receiver); } return descriptor.value; }
15
-
16
- var _queue = new WeakMap();
17
-
18
- var _pending = new WeakMap();
19
-
20
- // Concurrent task-based queue for handling snapshots and asset discovery.
21
- class Queue {
22
- // Defaults to inifinite concurrency
23
- constructor(concurrency = Infinity) {
24
- _queue.set(this, {
25
- writable: true,
26
- value: []
27
- });
28
-
29
- _pending.set(this, {
30
- writable: true,
31
- value: 0
32
- });
33
-
34
- this.concurrency = concurrency;
35
- } // Pushing a new task to the queue will attempt to run it unless the
36
- // concurrency limit has been reached. The returned promise will resolve or
37
- // reject when the task has succeeded or thrown an error.
38
-
39
-
40
- push(task) {
41
- return new Promise((resolve, reject) => {
42
- _classPrivateFieldGet(this, _queue).push({
43
- task,
44
- resolve,
45
- reject
46
- });
47
-
48
- this._dequeue();
49
- });
50
- } // Returns the amount of queued and pending tasks.
51
-
52
-
53
- get length() {
54
- return _classPrivateFieldGet(this, _queue).length + _classPrivateFieldGet(this, _pending);
55
- } // Resolves when there are no more queued or pending tasks.
56
-
57
-
58
- idle() {
59
- return (0, _idle.default)(() => this.length);
60
- } // Clears the active queue. Tasks that were queued will not be executed and
61
- // tasks that are pending (have already executed) will be allowed to finish.
62
-
63
-
64
- clear() {
65
- _classPrivateFieldSet(this, _queue, []);
66
-
67
- return this.length;
68
- } // Begins processing the queue by running the oldest task first. Pending tasks
69
- // are tracked and no tasks will run unless there are less pending than the
70
- // concurrency limit. More tasks are dequeued when the current task
71
- // finishes. Resolves when the current task finishes although this method
72
- // should never be awaited on so multiple tasks can run concurrently.
73
-
74
-
75
- async _dequeue() {
76
- var _this$pending;
77
-
78
- if (_classPrivateFieldGet(this, _pending) >= this.concurrency) return;
79
-
80
- let item = _classPrivateFieldGet(this, _queue).shift();
81
-
82
- if (!item) return;
83
- _classPrivateFieldSet(this, _pending, (_this$pending = +_classPrivateFieldGet(this, _pending)) + 1), _this$pending;
84
-
85
- try {
86
- var _this$pending2;
87
-
88
- let value = await item.task();
89
- _classPrivateFieldSet(this, _pending, (_this$pending2 = +_classPrivateFieldGet(this, _pending)) - 1), _this$pending2;
90
- item.resolve(value);
91
- } catch (error) {
92
- var _this$pending3;
93
-
94
- _classPrivateFieldSet(this, _pending, (_this$pending3 = +_classPrivateFieldGet(this, _pending)) - 1), _this$pending3;
95
- item.reject(error);
96
- } finally {
97
- this._dequeue();
98
- }
99
- }
100
-
101
- }
102
-
103
- exports.default = Queue;
package/dist/server.js DELETED
@@ -1,82 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.createServerApp = createServerApp;
7
- exports.startServer = startServer;
8
-
9
- // Handles async routes with a middleware pattern to catch and forward errors
10
- function asyncRoute(handler) {
11
- return (req, res, next) => handler(req, res, next).catch(next);
12
- } // Lazily creates and returns an express app for communicating with the Percy
13
- // instance using a local API
14
-
15
-
16
- function createServerApp(percy) {
17
- // lazily required to speed up imports when the server is not needed
18
- let express = require('express');
19
-
20
- let cors = require('cors');
21
-
22
- let bodyParser = require('body-parser');
23
-
24
- return express().use(cors()).use(bodyParser.urlencoded({
25
- extended: true
26
- })).use(bodyParser.json({
27
- limit: '50mb'
28
- })) // healthcheck returns meta info as well
29
- .get('/percy/healthcheck', (_, res) => {
30
- res.json({
31
- success: true,
32
- config: percy.config,
33
- loglevel: percy.loglevel(),
34
- build: percy.client.build
35
- });
36
- }) // responds when idle
37
- .get('/percy/idle', asyncRoute(async (_, res) => {
38
- await percy.idle();
39
- res.json({
40
- success: true
41
- });
42
- })) // serves @percy/dom as a convenience
43
- .get('/percy/dom.js', (_, res) => {
44
- res.sendFile(require.resolve('@percy/dom'));
45
- }) // forward snapshot requests
46
- .post('/percy/snapshot', asyncRoute(async (req, res) => {
47
- await percy.snapshot(req.body);
48
- res.json({
49
- success: true
50
- });
51
- })) // stops the instance
52
- .post('/percy/stop', asyncRoute(async (_, res) => {
53
- await percy.stop();
54
- res.json({
55
- success: true
56
- });
57
- })) // other routes 404
58
- .use('*', (_, res) => {
59
- res.status(404).json({
60
- success: false,
61
- error: 'Not found'
62
- });
63
- }) // generic error handler
64
- .use(({
65
- message
66
- }, req, res, next) => {
67
- res.status(500).json({
68
- success: false,
69
- error: message
70
- });
71
- });
72
- } // Promised based helper for starting an app at the specified port. Resolves
73
- // when the server is listening, rejects if there are any errors when starting.
74
-
75
-
76
- function startServer(app, port) {
77
- return new Promise((resolve, reject) => {
78
- let server = app.listen(port);
79
- server.once('listening', () => resolve(server));
80
- server.once('error', reject);
81
- });
82
- }
@@ -1,50 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.default = percyAssert;
7
-
8
- var _assert = require("assert");
9
-
10
- function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
11
-
12
- // Percy assertions errors contain extra meta data and have specific lookup keys
13
- // for different computed assertion error messages.
14
- class PercyAssertionError extends Error {
15
- constructor(lookup, meta = {}) {
16
- var _PercyAssertionError$, _PercyAssertionError$2, _PercyAssertionError$3;
17
-
18
- super((_PercyAssertionError$ = (_PercyAssertionError$2 = (_PercyAssertionError$3 = PercyAssertionError.dict)[lookup]) === null || _PercyAssertionError$2 === void 0 ? void 0 : _PercyAssertionError$2.call(_PercyAssertionError$3, meta)) !== null && _PercyAssertionError$ !== void 0 ? _PercyAssertionError$ : lookup);
19
- this.name = this.constructor.name;
20
- this.meta = meta;
21
- }
22
-
23
- toString() {
24
- return this.message;
25
- }
26
-
27
- } // Wraps native assert to throw a Percy assertion error with optional meta.
28
-
29
-
30
- _defineProperty(PercyAssertionError, "dict", {
31
- 'disallowed status': ({
32
- status
33
- }) => `Disallowed response status [${status}]`,
34
- 'is empty': () => 'Empty response',
35
- 'is remote': () => 'Remote resource',
36
- 'no response': () => 'No response',
37
- 'too many bytes': ({
38
- size
39
- }) => `Max file size exceeded [${size}]`,
40
- 'too many redirects': ({
41
- length
42
- }) => `Too many redirects [${length}]`,
43
- 'too many widths': ({
44
- widths
45
- }) => `Too many widths requested: maximum is 10, requested ${widths}`
46
- });
47
-
48
- function percyAssert(condition, lookup, meta) {
49
- (0, _assert.strict)(condition, new PercyAssertionError(lookup, meta));
50
- }
@@ -1,24 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.default = readableBytes;
7
-
8
- // Converts a raw byte integer into a human readable string.
9
- function readableBytes(bytes) {
10
- let units = ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
11
- let thresh = 1024;
12
- let u = -1;
13
-
14
- if (Math.abs(bytes) < thresh) {
15
- return `${bytes}B`;
16
- }
17
-
18
- while (Math.abs(bytes) >= thresh && u < units.length - 1) {
19
- bytes /= thresh;
20
- ++u;
21
- }
22
-
23
- return `${bytes.toFixed(1)}${units[u]}`;
24
- }