@percy/core 1.0.0-beta.76 → 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/README.md +86 -18
- package/package.json +24 -14
- package/dist/api.js +0 -76
- package/dist/browser.js +0 -363
- package/dist/config.js +0 -358
- package/dist/discovery.js +0 -130
- package/dist/index.js +0 -15
- package/dist/install.js +0 -173
- package/dist/network.js +0 -365
- package/dist/page.js +0 -293
- package/dist/percy.js +0 -427
- package/dist/queue.js +0 -196
- package/dist/server.js +0 -471
- package/dist/session.js +0 -140
- package/dist/snapshot.js +0 -279
- package/dist/utils.js +0 -170
- package/post-install.js +0 -23
- package/test/helpers/server.js +0 -35
- package/types/index.d.ts +0 -101
package/dist/percy.js
DELETED
|
@@ -1,427 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.default = exports.Percy = void 0;
|
|
7
|
-
|
|
8
|
-
var _client = _interopRequireDefault(require("@percy/client"));
|
|
9
|
-
|
|
10
|
-
var _config = _interopRequireDefault(require("@percy/config"));
|
|
11
|
-
|
|
12
|
-
var _utils = require("@percy/config/dist/utils");
|
|
13
|
-
|
|
14
|
-
var _logger = _interopRequireDefault(require("@percy/logger"));
|
|
15
|
-
|
|
16
|
-
var _queue = _interopRequireDefault(require("./queue"));
|
|
17
|
-
|
|
18
|
-
var _browser = _interopRequireDefault(require("./browser"));
|
|
19
|
-
|
|
20
|
-
var _api = require("./api");
|
|
21
|
-
|
|
22
|
-
var _snapshot = require("./snapshot");
|
|
23
|
-
|
|
24
|
-
var _utils2 = require("./utils");
|
|
25
|
-
|
|
26
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
27
|
-
|
|
28
|
-
function _classPrivateFieldInitSpec(obj, privateMap, value) { _checkPrivateRedeclaration(obj, privateMap); privateMap.set(obj, value); }
|
|
29
|
-
|
|
30
|
-
function _checkPrivateRedeclaration(obj, privateCollection) { if (privateCollection.has(obj)) { throw new TypeError("Cannot initialize the same private elements twice on an object"); } }
|
|
31
|
-
|
|
32
|
-
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; }
|
|
33
|
-
|
|
34
|
-
function _classPrivateFieldGet(receiver, privateMap) { var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "get"); return _classApplyDescriptorGet(receiver, descriptor); }
|
|
35
|
-
|
|
36
|
-
function _classExtractFieldDescriptor(receiver, privateMap, action) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to " + action + " private field on non-instance"); } return privateMap.get(receiver); }
|
|
37
|
-
|
|
38
|
-
function _classApplyDescriptorGet(receiver, descriptor) { if (descriptor.get) { return descriptor.get.call(receiver); } return descriptor.value; }
|
|
39
|
-
|
|
40
|
-
var _uploads = /*#__PURE__*/new WeakMap();
|
|
41
|
-
|
|
42
|
-
var _snapshots = /*#__PURE__*/new WeakMap();
|
|
43
|
-
|
|
44
|
-
// A Percy instance will create a new build when started, handle snapshot
|
|
45
|
-
// creation, asset discovery, and resource uploads, and will finalize the build
|
|
46
|
-
// when stopped. Snapshots are processed concurrently and the build is not
|
|
47
|
-
// finalized until all snapshots have been handled.
|
|
48
|
-
class Percy {
|
|
49
|
-
// Static shortcut to create and start an instance in one call
|
|
50
|
-
static async start(options) {
|
|
51
|
-
let instance = new this(options);
|
|
52
|
-
await instance.start();
|
|
53
|
-
return instance;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
constructor({
|
|
57
|
-
// initial log level
|
|
58
|
-
loglevel,
|
|
59
|
-
// do not eagerly upload snapshots
|
|
60
|
-
deferUploads,
|
|
61
|
-
// run without uploading anything
|
|
62
|
-
skipUploads,
|
|
63
|
-
// implies `skipUploads` and also skips asset discovery
|
|
64
|
-
dryRun,
|
|
65
|
-
// configuration filepath
|
|
66
|
-
config,
|
|
67
|
-
// provided to @percy/client
|
|
68
|
-
token,
|
|
69
|
-
clientInfo = '',
|
|
70
|
-
environmentInfo = '',
|
|
71
|
-
// snapshot server options
|
|
72
|
-
server = true,
|
|
73
|
-
port = 5338,
|
|
74
|
-
// options such as `snapshot` and `discovery` that are valid Percy config
|
|
75
|
-
// options which will become accessible via the `.config` property
|
|
76
|
-
..._options
|
|
77
|
-
} = {}) {
|
|
78
|
-
_defineProperty(this, "log", (0, _logger.default)('core'));
|
|
79
|
-
|
|
80
|
-
_defineProperty(this, "readyState", null);
|
|
81
|
-
|
|
82
|
-
_classPrivateFieldInitSpec(this, _uploads, {
|
|
83
|
-
writable: true,
|
|
84
|
-
value: new _queue.default()
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
_classPrivateFieldInitSpec(this, _snapshots, {
|
|
88
|
-
writable: true,
|
|
89
|
-
value: new _queue.default()
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
_defineProperty(this, "idle", () => (0, _utils2.generatePromise)(async function* () {
|
|
93
|
-
yield* _classPrivateFieldGet(this, _snapshots).idle();
|
|
94
|
-
yield* _classPrivateFieldGet(this, _uploads).idle();
|
|
95
|
-
}.bind(this)));
|
|
96
|
-
|
|
97
|
-
_defineProperty(this, "start", options => (0, _utils2.generatePromise)(async function* () {
|
|
98
|
-
// already starting or started
|
|
99
|
-
if (this.readyState != null) return;
|
|
100
|
-
this.readyState = 0; // create a percy build as the first immediately queued task
|
|
101
|
-
|
|
102
|
-
let buildTask = _classPrivateFieldGet(this, _uploads).push('build/create', () => {
|
|
103
|
-
// pause other queued tasks until after the build is created
|
|
104
|
-
_classPrivateFieldGet(this, _uploads).stop();
|
|
105
|
-
|
|
106
|
-
return this.client.createBuild().then(({
|
|
107
|
-
data: {
|
|
108
|
-
id,
|
|
109
|
-
attributes
|
|
110
|
-
}
|
|
111
|
-
}) => {
|
|
112
|
-
this.build = {
|
|
113
|
-
id
|
|
114
|
-
};
|
|
115
|
-
this.build.number = attributes['build-number'];
|
|
116
|
-
this.build.url = attributes['web-url'];
|
|
117
|
-
|
|
118
|
-
_classPrivateFieldGet(this, _uploads).run();
|
|
119
|
-
});
|
|
120
|
-
}, 0); // handle deferred build errors
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
if (this.deferUploads) {
|
|
124
|
-
buildTask.catch(err => {
|
|
125
|
-
this.log.error('Failed to create build');
|
|
126
|
-
this.log.error(err);
|
|
127
|
-
this.close();
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
try {
|
|
132
|
-
var _this$server;
|
|
133
|
-
|
|
134
|
-
// when not deferred, wait until the build is created first
|
|
135
|
-
if (!this.deferUploads) await buildTask; // maybe launch the discovery browser
|
|
136
|
-
|
|
137
|
-
if (!this.dryRun && (options === null || options === void 0 ? void 0 : options.browser) !== false) {
|
|
138
|
-
yield this.browser.launch();
|
|
139
|
-
} // start the server after everything else is ready
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
yield (_this$server = this.server) === null || _this$server === void 0 ? void 0 : _this$server.listen(); // mark instance as started
|
|
143
|
-
|
|
144
|
-
this.log.info('Percy has started!');
|
|
145
|
-
this.readyState = 1;
|
|
146
|
-
} catch (error) {
|
|
147
|
-
var _this$server2;
|
|
148
|
-
|
|
149
|
-
// on error, close any running server and browser
|
|
150
|
-
await ((_this$server2 = this.server) === null || _this$server2 === void 0 ? void 0 : _this$server2.close());
|
|
151
|
-
await this.browser.close(); // mark instance as closed
|
|
152
|
-
|
|
153
|
-
this.readyState = 3; // when uploads are deferred, cancel build creation
|
|
154
|
-
|
|
155
|
-
if (error.canceled && this.deferUploads) {
|
|
156
|
-
_classPrivateFieldGet(this, _uploads).cancel('build/create');
|
|
157
|
-
|
|
158
|
-
this.readyState = null;
|
|
159
|
-
} // throw an easier-to-understand error when the port is taken
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
if (error.code === 'EADDRINUSE') {
|
|
163
|
-
throw new Error('Percy is already running or the port is in use');
|
|
164
|
-
} else {
|
|
165
|
-
throw error;
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
}.bind(this)));
|
|
169
|
-
|
|
170
|
-
_defineProperty(this, "flush", close => (0, _utils2.generatePromise)(async function* () {
|
|
171
|
-
// close the snapshot queue and wait for it to empty
|
|
172
|
-
if (_classPrivateFieldGet(this, _snapshots).size) {
|
|
173
|
-
if (close) _classPrivateFieldGet(this, _snapshots).close();
|
|
174
|
-
yield* _classPrivateFieldGet(this, _snapshots).flush(s => {
|
|
175
|
-
// do not log a count when not closing or while dry-running
|
|
176
|
-
if (!close || this.dryRun) return;
|
|
177
|
-
this.log.progress(`Processing ${s} snapshot${s !== 1 ? 's' : ''}...`, !!s);
|
|
178
|
-
});
|
|
179
|
-
} // run, close, and wait for the upload queue to empty
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
if (!this.skipUploads && _classPrivateFieldGet(this, _uploads).size) {
|
|
183
|
-
if (close) _classPrivateFieldGet(this, _uploads).close();
|
|
184
|
-
yield* _classPrivateFieldGet(this, _uploads).flush(s => {
|
|
185
|
-
// do not log a count when not closing or while creating a build
|
|
186
|
-
if (!close || _classPrivateFieldGet(this, _uploads).has('build/create')) return;
|
|
187
|
-
this.log.progress(`Uploading ${s} snapshot${s !== 1 ? 's' : ''}...`, !!s);
|
|
188
|
-
});
|
|
189
|
-
}
|
|
190
|
-
}.bind(this)).canceled(() => {
|
|
191
|
-
// reopen closed queues when canceled
|
|
192
|
-
_classPrivateFieldGet(this, _snapshots).open();
|
|
193
|
-
|
|
194
|
-
_classPrivateFieldGet(this, _uploads).open();
|
|
195
|
-
}));
|
|
196
|
-
|
|
197
|
-
_defineProperty(this, "stop", force => (0, _utils2.generatePromise)(async function* () {
|
|
198
|
-
var _this$server3, _this$build;
|
|
199
|
-
|
|
200
|
-
// not started, but the browser was launched
|
|
201
|
-
if (!this.readyState && this.browser.isConnected()) {
|
|
202
|
-
await this.browser.close();
|
|
203
|
-
} // not started or already stopped
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
if (!this.readyState || this.readyState > 2) return; // close queues asap
|
|
207
|
-
|
|
208
|
-
if (force) this.close(); // already stopping
|
|
209
|
-
|
|
210
|
-
if (this.readyState === 2) return;
|
|
211
|
-
this.readyState = 2; // log when force stopping
|
|
212
|
-
|
|
213
|
-
if (force) this.log.info('Stopping percy...'); // process uploads and close queues
|
|
214
|
-
|
|
215
|
-
yield* this.flush(true); // if dry-running, log the total number of snapshots
|
|
216
|
-
|
|
217
|
-
if (this.dryRun && _classPrivateFieldGet(this, _uploads).size) {
|
|
218
|
-
let total = _classPrivateFieldGet(this, _uploads).size - 1; // subtract the build task
|
|
219
|
-
|
|
220
|
-
this.log.info(`Found ${total} snapshot${total !== 1 ? 's' : ''}`);
|
|
221
|
-
} // close any running server and browser
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
await ((_this$server3 = this.server) === null || _this$server3 === void 0 ? void 0 : _this$server3.close());
|
|
225
|
-
await this.browser.close(); // finalize and log build info
|
|
226
|
-
|
|
227
|
-
let meta = {
|
|
228
|
-
build: this.build
|
|
229
|
-
};
|
|
230
|
-
|
|
231
|
-
if ((_this$build = this.build) !== null && _this$build !== void 0 && _this$build.failed) {
|
|
232
|
-
// do not finalize failed builds
|
|
233
|
-
this.log.warn(`Build #${this.build.number} failed: ${this.build.url}`, meta);
|
|
234
|
-
} else if (this.build) {
|
|
235
|
-
// finalize the build
|
|
236
|
-
await this.client.finalizeBuild(this.build.id);
|
|
237
|
-
this.log.info(`Finalized build #${this.build.number}: ${this.build.url}`, meta);
|
|
238
|
-
} else {
|
|
239
|
-
// no build was ever created (likely failed while deferred)
|
|
240
|
-
this.log.warn('Build not created', meta);
|
|
241
|
-
} // mark instance as stopped
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
this.readyState = 3;
|
|
245
|
-
}.bind(this)).canceled(() => {
|
|
246
|
-
// reset ready state when canceled
|
|
247
|
-
this.readyState = 1;
|
|
248
|
-
}));
|
|
249
|
-
|
|
250
|
-
if (loglevel) this.loglevel(loglevel);
|
|
251
|
-
this.dryRun = !!dryRun;
|
|
252
|
-
this.skipUploads = this.dryRun || !!skipUploads;
|
|
253
|
-
this.deferUploads = this.skipUploads || !!deferUploads;
|
|
254
|
-
if (this.deferUploads) _classPrivateFieldGet(this, _uploads).stop();
|
|
255
|
-
this.config = _config.default.load({
|
|
256
|
-
overrides: _options,
|
|
257
|
-
path: config
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
if (this.config.discovery.concurrency) {
|
|
261
|
-
let {
|
|
262
|
-
concurrency
|
|
263
|
-
} = this.config.discovery;
|
|
264
|
-
_classPrivateFieldGet(this, _uploads).concurrency = concurrency;
|
|
265
|
-
_classPrivateFieldGet(this, _snapshots).concurrency = concurrency;
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
this.client = new _client.default({
|
|
269
|
-
token,
|
|
270
|
-
clientInfo,
|
|
271
|
-
environmentInfo
|
|
272
|
-
});
|
|
273
|
-
this.browser = new _browser.default({ ...this.config.discovery.launchOptions,
|
|
274
|
-
cookies: this.config.discovery.cookies
|
|
275
|
-
});
|
|
276
|
-
|
|
277
|
-
if (server) {
|
|
278
|
-
this.server = (0, _api.createPercyServer)(this, port);
|
|
279
|
-
}
|
|
280
|
-
} // Shortcut for controlling the global logger's log level.
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
loglevel(level) {
|
|
284
|
-
return _logger.default.loglevel(level);
|
|
285
|
-
} // Snapshot server API address
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
address() {
|
|
289
|
-
var _this$server4;
|
|
290
|
-
|
|
291
|
-
return (_this$server4 = this.server) === null || _this$server4 === void 0 ? void 0 : _this$server4.address();
|
|
292
|
-
} // Set client & environment info, and override loaded config options
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
setConfig({
|
|
296
|
-
clientInfo,
|
|
297
|
-
environmentInfo,
|
|
298
|
-
...config
|
|
299
|
-
}) {
|
|
300
|
-
this.client.addClientInfo(clientInfo);
|
|
301
|
-
this.client.addEnvironmentInfo(environmentInfo); // normalize config and do nothing if empty
|
|
302
|
-
|
|
303
|
-
config = _config.default.normalize(config, {
|
|
304
|
-
schema: '/config'
|
|
305
|
-
});
|
|
306
|
-
if (!config) return this.config; // validate provided config options
|
|
307
|
-
|
|
308
|
-
let errors = _config.default.validate(config);
|
|
309
|
-
|
|
310
|
-
if (errors) {
|
|
311
|
-
this.log.warn('Invalid config:');
|
|
312
|
-
|
|
313
|
-
for (let e of errors) this.log.warn(`- ${e.path}: ${e.message}`);
|
|
314
|
-
} // merge and override existing config options
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
this.config = (0, _utils.merge)([this.config, config], (path, prev, next) => {
|
|
318
|
-
// replace arrays instead of merging
|
|
319
|
-
return Array.isArray(next) && [path, next];
|
|
320
|
-
}); // adjust concurrency if necessary
|
|
321
|
-
|
|
322
|
-
if (this.config.discovery.concurrency) {
|
|
323
|
-
let {
|
|
324
|
-
concurrency
|
|
325
|
-
} = this.config.discovery;
|
|
326
|
-
_classPrivateFieldGet(this, _uploads).concurrency = concurrency;
|
|
327
|
-
_classPrivateFieldGet(this, _snapshots).concurrency = concurrency;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
return this.config;
|
|
331
|
-
} // Resolves once snapshot and upload queues are idle
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
// Immediately stops all queues, preventing any more tasks from running
|
|
335
|
-
close() {
|
|
336
|
-
_classPrivateFieldGet(this, _snapshots).close(true);
|
|
337
|
-
|
|
338
|
-
_classPrivateFieldGet(this, _uploads).close(true);
|
|
339
|
-
} // Starts a local API server, a browser process, and queues creating a new Percy build which will run
|
|
340
|
-
// at a later time when uploads are deferred, or run immediately when not deferred.
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
// Deprecated capture method
|
|
344
|
-
capture(options) {
|
|
345
|
-
this.log.deprecated('The #capture() method will be ' + 'removed in 1.0.0. Use #snapshot() instead.');
|
|
346
|
-
return this.snapshot(options);
|
|
347
|
-
} // Takes one or more snapshots of a page while discovering resources to upload with the
|
|
348
|
-
// snapshot. If an existing dom snapshot is provided, it will be served as the root resource
|
|
349
|
-
// during asset discovery. Once asset discovery has completed, the queued snapshot will resolve
|
|
350
|
-
// and an upload task will be queued separately.
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
snapshot(options) {
|
|
354
|
-
if (this.readyState !== 1) {
|
|
355
|
-
throw new Error('Not running');
|
|
356
|
-
} // handle multiple snapshots
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
if (Array.isArray(options)) {
|
|
360
|
-
return Promise.all(options.map(o => this.snapshot(o)));
|
|
361
|
-
} // get derived snapshot config options
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
let snapshot = (0, _snapshot.getSnapshotConfig)(this, options); // clear any existing snapshot uploads of the same name (for retries)
|
|
365
|
-
|
|
366
|
-
for (let {
|
|
367
|
-
name
|
|
368
|
-
} of [snapshot, ...(snapshot.additionalSnapshots || [])]) {
|
|
369
|
-
_classPrivateFieldGet(this, _uploads).cancel(`upload/${name}`);
|
|
370
|
-
} // resolves after asset discovery has finished and uploads have been queued
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
return _classPrivateFieldGet(this, _snapshots).push(`snapshot/${snapshot.name}`, async function* () {
|
|
374
|
-
try {
|
|
375
|
-
yield* (0, _snapshot.discoverSnapshotResources)(this, snapshot, (snap, resources) => {
|
|
376
|
-
if (!this.dryRun) this.log.info(`Snapshot taken: ${snap.name}`, snap.meta);
|
|
377
|
-
|
|
378
|
-
this._scheduleUpload(snap.name, { ...snap,
|
|
379
|
-
resources
|
|
380
|
-
});
|
|
381
|
-
});
|
|
382
|
-
} catch (error) {
|
|
383
|
-
if (error.canceled) {
|
|
384
|
-
this.log.error('Received a duplicate snapshot name, ' + `the previous snapshot was canceled: ${snapshot.name}`);
|
|
385
|
-
} else {
|
|
386
|
-
this.log.error(`Encountered an error taking snapshot: ${snapshot.name}`, snapshot.meta);
|
|
387
|
-
this.log.error(error, snapshot.meta);
|
|
388
|
-
}
|
|
389
|
-
} // fixes an issue in Node 12 where implicit returns do not correctly resolve the async
|
|
390
|
-
// generator objects — https://crbug.com/v8/10238
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
return; // eslint-disable-line no-useless-return
|
|
394
|
-
}.bind(this));
|
|
395
|
-
} // Queues a snapshot upload with the provided options
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
_scheduleUpload(name, options) {
|
|
399
|
-
return _classPrivateFieldGet(this, _uploads).push(`upload/${name}`, async () => {
|
|
400
|
-
try {
|
|
401
|
-
/* istanbul ignore if: useful for other internal packages */
|
|
402
|
-
if (typeof options === 'function') options = await options();
|
|
403
|
-
await this.client.sendSnapshot(this.build.id, options);
|
|
404
|
-
} catch (error) {
|
|
405
|
-
var _error$response, _failed$detail;
|
|
406
|
-
|
|
407
|
-
let failed = ((_error$response = error.response) === null || _error$response === void 0 ? void 0 : _error$response.statusCode) === 422 && error.response.body.errors.find(e => {
|
|
408
|
-
var _e$source;
|
|
409
|
-
|
|
410
|
-
return ((_e$source = e.source) === null || _e$source === void 0 ? void 0 : _e$source.pointer) === '/data/attributes/build';
|
|
411
|
-
});
|
|
412
|
-
this.log.error(`Encountered an error uploading snapshot: ${name}`, options.meta);
|
|
413
|
-
this.log.error((_failed$detail = failed === null || failed === void 0 ? void 0 : failed.detail) !== null && _failed$detail !== void 0 ? _failed$detail : error, options.meta); // build failed at some point, stop accepting snapshots
|
|
414
|
-
|
|
415
|
-
if (failed) {
|
|
416
|
-
this.build.failed = true;
|
|
417
|
-
this.close();
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
});
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
exports.Percy = Percy;
|
|
426
|
-
var _default = Percy;
|
|
427
|
-
exports.default = _default;
|
package/dist/queue.js
DELETED
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.default = exports.Queue = void 0;
|
|
7
|
-
|
|
8
|
-
var _utils = require("./utils");
|
|
9
|
-
|
|
10
|
-
function _classPrivateFieldInitSpec(obj, privateMap, value) { _checkPrivateRedeclaration(obj, privateMap); privateMap.set(obj, value); }
|
|
11
|
-
|
|
12
|
-
function _checkPrivateRedeclaration(obj, privateCollection) { if (privateCollection.has(obj)) { throw new TypeError("Cannot initialize the same private elements twice on an object"); } }
|
|
13
|
-
|
|
14
|
-
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; }
|
|
15
|
-
|
|
16
|
-
function _classPrivateFieldGet(receiver, privateMap) { var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "get"); return _classApplyDescriptorGet(receiver, descriptor); }
|
|
17
|
-
|
|
18
|
-
function _classExtractFieldDescriptor(receiver, privateMap, action) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to " + action + " private field on non-instance"); } return privateMap.get(receiver); }
|
|
19
|
-
|
|
20
|
-
function _classApplyDescriptorGet(receiver, descriptor) { if (descriptor.get) { return descriptor.get.call(receiver); } return descriptor.value; }
|
|
21
|
-
|
|
22
|
-
var _queued = /*#__PURE__*/new WeakMap();
|
|
23
|
-
|
|
24
|
-
var _pending = /*#__PURE__*/new WeakMap();
|
|
25
|
-
|
|
26
|
-
class Queue {
|
|
27
|
-
constructor(concurrency = 10) {
|
|
28
|
-
_defineProperty(this, "running", true);
|
|
29
|
-
|
|
30
|
-
_defineProperty(this, "closed", false);
|
|
31
|
-
|
|
32
|
-
_classPrivateFieldInitSpec(this, _queued, {
|
|
33
|
-
writable: true,
|
|
34
|
-
value: new Map()
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
_classPrivateFieldInitSpec(this, _pending, {
|
|
38
|
-
writable: true,
|
|
39
|
-
value: new Map()
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
this.concurrency = concurrency;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
push(id, callback, priority) {
|
|
46
|
-
if (this.closed && !id.startsWith('@@/')) {
|
|
47
|
-
throw new Error('Closed');
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
this.cancel(id);
|
|
51
|
-
let task = {
|
|
52
|
-
id,
|
|
53
|
-
callback,
|
|
54
|
-
priority
|
|
55
|
-
};
|
|
56
|
-
task.promise = new Promise((resolve, reject) => {
|
|
57
|
-
Object.assign(task, {
|
|
58
|
-
resolve,
|
|
59
|
-
reject
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
_classPrivateFieldGet(this, _queued).set(id, task);
|
|
63
|
-
|
|
64
|
-
this._dequeue();
|
|
65
|
-
});
|
|
66
|
-
return task.promise;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
cancel(id) {
|
|
70
|
-
var _classPrivateFieldGet2, _classPrivateFieldGet3;
|
|
71
|
-
|
|
72
|
-
(_classPrivateFieldGet2 = _classPrivateFieldGet(this, _pending).get(id)) === null || _classPrivateFieldGet2 === void 0 ? void 0 : (_classPrivateFieldGet3 = _classPrivateFieldGet2.cancel) === null || _classPrivateFieldGet3 === void 0 ? void 0 : _classPrivateFieldGet3.call(_classPrivateFieldGet2);
|
|
73
|
-
|
|
74
|
-
_classPrivateFieldGet(this, _pending).delete(id);
|
|
75
|
-
|
|
76
|
-
_classPrivateFieldGet(this, _queued).delete(id);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
has(id) {
|
|
80
|
-
return _classPrivateFieldGet(this, _queued).has(id) || _classPrivateFieldGet(this, _pending).has(id);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
clear() {
|
|
84
|
-
_classPrivateFieldGet(this, _queued).clear();
|
|
85
|
-
|
|
86
|
-
return this.size;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
get size() {
|
|
90
|
-
return _classPrivateFieldGet(this, _queued).size + _classPrivateFieldGet(this, _pending).size;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
run() {
|
|
94
|
-
this.running = true;
|
|
95
|
-
|
|
96
|
-
while (this.running && _classPrivateFieldGet(this, _queued).size && _classPrivateFieldGet(this, _pending).size < this.concurrency) this._dequeue();
|
|
97
|
-
|
|
98
|
-
return this;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
stop() {
|
|
102
|
-
this.running = false;
|
|
103
|
-
return this;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
open() {
|
|
107
|
-
this.closed = false;
|
|
108
|
-
return this;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
close(abort) {
|
|
112
|
-
if (abort) this.stop().clear();
|
|
113
|
-
this.closed = true;
|
|
114
|
-
return this;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
idle(callback) {
|
|
118
|
-
return (0, _utils.waitFor)(() => {
|
|
119
|
-
callback === null || callback === void 0 ? void 0 : callback(_classPrivateFieldGet(this, _pending).size);
|
|
120
|
-
return !_classPrivateFieldGet(this, _pending).size;
|
|
121
|
-
}, {
|
|
122
|
-
idle: 10
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
empty(callback) {
|
|
127
|
-
return (0, _utils.waitFor)(() => {
|
|
128
|
-
callback === null || callback === void 0 ? void 0 : callback(this.size);
|
|
129
|
-
return !this.size;
|
|
130
|
-
}, {
|
|
131
|
-
idle: 10
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
flush(callback) {
|
|
136
|
-
let stopped = !this.running;
|
|
137
|
-
this.run().push('@@/flush', () => {
|
|
138
|
-
if (stopped) this.stop();
|
|
139
|
-
});
|
|
140
|
-
return this.idle(pend => {
|
|
141
|
-
let left = [..._classPrivateFieldGet(this, _queued).keys()].indexOf('@@/flush');
|
|
142
|
-
if (!~left && !_classPrivateFieldGet(this, _pending).has('@@/flush')) left = 0;
|
|
143
|
-
callback === null || callback === void 0 ? void 0 : callback(pend + left);
|
|
144
|
-
}).canceled(() => {
|
|
145
|
-
if (stopped) this.stop();
|
|
146
|
-
this.cancel('@@/flush');
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
next() {
|
|
151
|
-
let next;
|
|
152
|
-
|
|
153
|
-
for (let [id, task] of _classPrivateFieldGet(this, _queued)) {
|
|
154
|
-
if (!next || task.priority != null && next.priority == null || task.priority < next.priority) next = task;
|
|
155
|
-
if (id === '@@/flush') break;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
return next;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
_dequeue() {
|
|
162
|
-
if (!this.running) return;
|
|
163
|
-
if (_classPrivateFieldGet(this, _pending).size >= this.concurrency) return;
|
|
164
|
-
let task = this.next();
|
|
165
|
-
if (!task) return;
|
|
166
|
-
|
|
167
|
-
_classPrivateFieldGet(this, _queued).delete(task.id);
|
|
168
|
-
|
|
169
|
-
_classPrivateFieldGet(this, _pending).set(task.id, task);
|
|
170
|
-
|
|
171
|
-
let done = callback => arg => {
|
|
172
|
-
var _task$cancel;
|
|
173
|
-
|
|
174
|
-
if (!((_task$cancel = task.cancel) !== null && _task$cancel !== void 0 && _task$cancel.triggered)) {
|
|
175
|
-
_classPrivateFieldGet(this, _pending).delete(task.id);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
callback(arg);
|
|
179
|
-
|
|
180
|
-
this._dequeue();
|
|
181
|
-
};
|
|
182
|
-
|
|
183
|
-
try {
|
|
184
|
-
let gen = (0, _utils.generatePromise)(task.callback);
|
|
185
|
-
task.cancel = gen.cancel;
|
|
186
|
-
return gen.then(done(task.resolve), done(task.reject));
|
|
187
|
-
} catch (err) {
|
|
188
|
-
done(task.reject)(err);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
exports.Queue = Queue;
|
|
195
|
-
var _default = Queue;
|
|
196
|
-
exports.default = _default;
|