@xenon-device-management/xenon 1.11.0 → 1.11.1
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/lib/package.json +1 -1
- package/lib/src/app/routers/control.js +11 -13
- package/lib/src/device-managers/android/AndroidStreamService.js +53 -6
- package/lib/src/device-managers/android/androidStreamReuse.js +38 -0
- package/lib/test/unit/android-stream-reuse-service.spec.js +93 -0
- package/lib/test/unit/android-stream-reuse.spec.js +71 -0
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
package/lib/package.json
CHANGED
|
@@ -832,20 +832,18 @@ router.get('/:udid/stream', (req, res) => __awaiter(void 0, void 0, void 0, func
|
|
|
832
832
|
}
|
|
833
833
|
}
|
|
834
834
|
else {
|
|
835
|
-
// Android auto-start
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
835
|
+
// Android auto-start. Always go through startStream: it health-checks an
|
|
836
|
+
// existing session before reusing it (decideAndroidStreamReuse) and dedupes
|
|
837
|
+
// concurrent starts. The short-circuit that used to live here — hand back
|
|
838
|
+
// any session marked 'running' — bypassed both, re-introducing the very
|
|
839
|
+
// stale-port bug the service now guards against. Reuse stays just as cheap;
|
|
840
|
+
// the health check is an in-process property read, not a request.
|
|
841
|
+
try {
|
|
842
|
+
const result = yield typedi_1.Container.get(AndroidStreamService_1.default).startStream(udid);
|
|
843
|
+
mjpegPort = result.mjpegPort;
|
|
840
844
|
}
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
const result = yield androidStreamService.startStream(udid);
|
|
844
|
-
mjpegPort = result.mjpegPort;
|
|
845
|
-
}
|
|
846
|
-
catch (err) {
|
|
847
|
-
return res.status(503).send({ error: 'Android stream failed', message: err.message });
|
|
848
|
-
}
|
|
845
|
+
catch (err) {
|
|
846
|
+
return res.status(503).send({ error: 'Android stream failed', message: err.message });
|
|
849
847
|
}
|
|
850
848
|
}
|
|
851
849
|
if (!mjpegPort) {
|
|
@@ -66,6 +66,7 @@ const ResourceIsolationService_1 = require("../../services/ResourceIsolationServ
|
|
|
66
66
|
const PortAllocator_1 = require("../../services/PortAllocator");
|
|
67
67
|
const ffmpegPath_1 = require("../../helpers/ffmpegPath");
|
|
68
68
|
const singleFlight_1 = require("../../helpers/singleFlight");
|
|
69
|
+
const androidStreamReuse_1 = require("./androidStreamReuse");
|
|
69
70
|
// JPEG quality for the in-process sharp encoder (0-100). ~78 approximates the
|
|
70
71
|
// old ffmpeg `-q:v 8` (mjpeg quantizer scale) — the low-lag/quality knob.
|
|
71
72
|
const JPEG_QUALITY = 78;
|
|
@@ -216,11 +217,26 @@ let AndroidStreamService = class AndroidStreamService {
|
|
|
216
217
|
startStream(udid) {
|
|
217
218
|
return __awaiter(this, void 0, void 0, function* () {
|
|
218
219
|
const performStartup = () => __awaiter(this, void 0, void 0, function* () {
|
|
219
|
-
var _a, _b;
|
|
220
|
+
var _a, _b, _c;
|
|
220
221
|
try {
|
|
222
|
+
// A session is handed back only when it is actually serving. A closed
|
|
223
|
+
// server, or one that went live without ever capturing a frame, was
|
|
224
|
+
// otherwise reused indefinitely and every consumer — recording included
|
|
225
|
+
// — got a port that yields nothing. See androidStreamReuse / issue #196.
|
|
221
226
|
const existing = this.sessions.get(udid);
|
|
222
|
-
|
|
223
|
-
|
|
227
|
+
const decision = (0, androidStreamReuse_1.decideAndroidStreamReuse)(existing && {
|
|
228
|
+
status: existing.status,
|
|
229
|
+
serverListening: ((_a = existing.server) === null || _a === void 0 ? void 0 : _a.listening) === true,
|
|
230
|
+
hasFrame: existing.latestFrame !== undefined,
|
|
231
|
+
});
|
|
232
|
+
if (decision.reuse) {
|
|
233
|
+
if (existing)
|
|
234
|
+
return { mjpegPort: existing.mjpegPort };
|
|
235
|
+
}
|
|
236
|
+
else if (existing) {
|
|
237
|
+
logger_1.default.warn(`[${udid}] Stream session on port ${existing.mjpegPort} is not usable ` +
|
|
238
|
+
`(${decision.reason}); discarding it and starting fresh.`);
|
|
239
|
+
yield this.disposeSession(udid, existing);
|
|
224
240
|
}
|
|
225
241
|
const device = yield device_store_1.DeviceStoreFactory.getStore().findDevice({ udid });
|
|
226
242
|
if (!device)
|
|
@@ -256,12 +272,12 @@ let AndroidStreamService = class AndroidStreamService {
|
|
|
256
272
|
break;
|
|
257
273
|
}
|
|
258
274
|
catch (bindErr) {
|
|
259
|
-
logger_1.default.warn(`[${udid}] MJPEG bind failed on ${mjpegPort} (attempt ${attempt + 1}): ${(
|
|
275
|
+
logger_1.default.warn(`[${udid}] MJPEG bind failed on ${mjpegPort} (attempt ${attempt + 1}): ${(_b = bindErr === null || bindErr === void 0 ? void 0 : bindErr.message) !== null && _b !== void 0 ? _b : bindErr}`);
|
|
260
276
|
this.sessions.delete(udid);
|
|
261
277
|
try {
|
|
262
|
-
(
|
|
278
|
+
(_c = candidate.server) === null || _c === void 0 ? void 0 : _c.close();
|
|
263
279
|
}
|
|
264
|
-
catch (
|
|
280
|
+
catch (_d) {
|
|
265
281
|
/* ignore */
|
|
266
282
|
}
|
|
267
283
|
yield portAllocator.release(mjpegPort).catch(() => undefined);
|
|
@@ -318,6 +334,37 @@ let AndroidStreamService = class AndroidStreamService {
|
|
|
318
334
|
return this.startFlight.run(udid, performStartup);
|
|
319
335
|
});
|
|
320
336
|
}
|
|
337
|
+
/**
|
|
338
|
+
* Release a dead session's resources so a fresh one can replace it.
|
|
339
|
+
*
|
|
340
|
+
* Deliberately *not* stopStream(): that also unblocks the device when the
|
|
341
|
+
* lock is a manual one, which would drop the caller's own hold on the device
|
|
342
|
+
* halfway through a restart. Only stream-owned resources are touched here.
|
|
343
|
+
*/
|
|
344
|
+
disposeSession(udid, session) {
|
|
345
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
346
|
+
var _a;
|
|
347
|
+
// The capture loop and every writeFrame loop poll this, so flipping it
|
|
348
|
+
// first stops them before the server goes away.
|
|
349
|
+
session.status = 'stopped';
|
|
350
|
+
try {
|
|
351
|
+
(_a = session.server) === null || _a === void 0 ? void 0 : _a.close();
|
|
352
|
+
}
|
|
353
|
+
catch (_b) {
|
|
354
|
+
/* ignore */
|
|
355
|
+
}
|
|
356
|
+
session.server = null;
|
|
357
|
+
// Only drop our own entry — never evict a newer session for this udid.
|
|
358
|
+
if (this.sessions.get(udid) === session)
|
|
359
|
+
this.sessions.delete(udid);
|
|
360
|
+
try {
|
|
361
|
+
yield typedi_1.Container.get(PortAllocator_1.PortAllocator).release(session.mjpegPort);
|
|
362
|
+
}
|
|
363
|
+
catch (e) {
|
|
364
|
+
logger_1.default.warn(`[${udid}] Failed to release mjpeg port lease while restarting stream: ${e}`);
|
|
365
|
+
}
|
|
366
|
+
});
|
|
367
|
+
}
|
|
321
368
|
stopStream(udid) {
|
|
322
369
|
return __awaiter(this, void 0, void 0, function* () {
|
|
323
370
|
var _a;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Decide whether an existing Android MJPEG stream session can be handed back as
|
|
4
|
+
* is, or has to be torn down and restarted.
|
|
5
|
+
*
|
|
6
|
+
* Why this exists: `startStream` used to return `existing.mjpegPort` for any
|
|
7
|
+
* session marked 'running' *or* 'starting', with nothing verifying that a
|
|
8
|
+
* server was still bound to it. A session whose HTTP server had closed, or one
|
|
9
|
+
* that went live without ever capturing a frame (startStream warns and
|
|
10
|
+
* continues after a 5s first-frame wait), was therefore reused indefinitely —
|
|
11
|
+
* every caller, `ensureMjpegForRecording` included, got a port that serves
|
|
12
|
+
* nothing, and ffmpeg left a 0-byte mp4 behind. Same silent symptom as #194,
|
|
13
|
+
* reached by a different route. See issue #196.
|
|
14
|
+
*
|
|
15
|
+
* This is the Android analogue of `resolveIosMjpegPort` (#191), minus the async
|
|
16
|
+
* probe: the MJPEG server is ours and in-process, so its liveness is a property
|
|
17
|
+
* read rather than a loopback request.
|
|
18
|
+
*
|
|
19
|
+
* Kept free of TypeDI and `http` so the decision is unit-testable; the service
|
|
20
|
+
* maps its live session onto the view below.
|
|
21
|
+
*/
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
+
exports.decideAndroidStreamReuse = decideAndroidStreamReuse;
|
|
24
|
+
function decideAndroidStreamReuse(session) {
|
|
25
|
+
if (!session)
|
|
26
|
+
return { reuse: false, reason: 'no-session' };
|
|
27
|
+
// 'starting' is deliberately excluded: the bind loop registers the candidate
|
|
28
|
+
// before awaiting the listen, so that status means "a port exists" and not
|
|
29
|
+
// "a port serves". Concurrent callers join the in-flight start via
|
|
30
|
+
// SingleFlight (#195) instead of being handed a half-bound port here.
|
|
31
|
+
if (session.status !== 'running')
|
|
32
|
+
return { reuse: false, reason: 'not-running' };
|
|
33
|
+
if (!session.serverListening)
|
|
34
|
+
return { reuse: false, reason: 'server-closed' };
|
|
35
|
+
if (!session.hasFrame)
|
|
36
|
+
return { reuse: false, reason: 'no-frame' };
|
|
37
|
+
return { reuse: true };
|
|
38
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
require("reflect-metadata");
|
|
16
|
+
const chai_1 = require("chai");
|
|
17
|
+
const sinon_1 = __importDefault(require("sinon"));
|
|
18
|
+
const typedi_1 = require("typedi");
|
|
19
|
+
const AndroidStreamService_1 = __importDefault(require("../../src/device-managers/android/AndroidStreamService"));
|
|
20
|
+
const singleFlight_1 = require("../../src/helpers/singleFlight");
|
|
21
|
+
const PortAllocator_1 = require("../../src/services/PortAllocator");
|
|
22
|
+
const device_store_1 = require("../../src/data-service/device-store");
|
|
23
|
+
// Companion to android-stream-reuse.spec.ts: that one covers the decision, this
|
|
24
|
+
// one covers the wiring — that startStream still short-circuits on a healthy
|
|
25
|
+
// session, and that an unusable one is actually torn down (capture loop stopped,
|
|
26
|
+
// server closed, port lease released) instead of being left listening while a
|
|
27
|
+
// replacement binds a second port. See issue #196.
|
|
28
|
+
// Bypass the constructor: it starts a 1h watchdog interval we don't want.
|
|
29
|
+
function makeService(session) {
|
|
30
|
+
const svc = Object.create(AndroidStreamService_1.default.prototype);
|
|
31
|
+
svc.sessions = new Map();
|
|
32
|
+
svc.startFlight = new singleFlight_1.SingleFlight();
|
|
33
|
+
if (session)
|
|
34
|
+
svc.sessions.set(session.udid, session);
|
|
35
|
+
return svc;
|
|
36
|
+
}
|
|
37
|
+
function session(udid, mjpegPort, overrides = {}) {
|
|
38
|
+
return Object.assign({ udid,
|
|
39
|
+
mjpegPort, server: { listening: true, close: sinon_1.default.spy() }, status: 'running', latestFrame: Buffer.from([0xff, 0xd8]), lastViewerAt: Date.now(), viewerCount: 0 }, overrides);
|
|
40
|
+
}
|
|
41
|
+
describe('AndroidStreamService.startStream session reuse', () => {
|
|
42
|
+
let releaseSpy;
|
|
43
|
+
let getStoreStub;
|
|
44
|
+
beforeEach(() => {
|
|
45
|
+
releaseSpy = sinon_1.default.spy((_port) => __awaiter(void 0, void 0, void 0, function* () { return undefined; }));
|
|
46
|
+
const containerStub = sinon_1.default.stub(typedi_1.Container, 'get').callsFake((token) => {
|
|
47
|
+
if (token === PortAllocator_1.PortAllocator)
|
|
48
|
+
return { release: releaseSpy };
|
|
49
|
+
return containerStub.wrappedMethod.call(typedi_1.Container, token);
|
|
50
|
+
});
|
|
51
|
+
// Any attempt at a real startup dies here, which is what we want: it marks
|
|
52
|
+
// the point where the reuse short-circuit was NOT taken.
|
|
53
|
+
getStoreStub = sinon_1.default.stub(device_store_1.DeviceStoreFactory, 'getStore').returns({
|
|
54
|
+
findDevice: () => __awaiter(void 0, void 0, void 0, function* () { return undefined; }),
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
afterEach(() => sinon_1.default.restore());
|
|
58
|
+
it('hands back a healthy session without touching the device store', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
59
|
+
const svc = makeService(session('android-1', 9100));
|
|
60
|
+
(0, chai_1.expect)(yield svc.startStream('android-1')).to.deep.equal({ mjpegPort: 9100 });
|
|
61
|
+
(0, chai_1.expect)(getStoreStub.called, 'reuse must not fall through to a real startup').to.be.false;
|
|
62
|
+
(0, chai_1.expect)(releaseSpy.called, 'a reused session keeps its port lease').to.be.false;
|
|
63
|
+
}));
|
|
64
|
+
for (const [label, overrides] of [
|
|
65
|
+
['the server is no longer listening', { server: { listening: false, close: sinon_1.default.spy() } }],
|
|
66
|
+
['it never captured a frame', { latestFrame: undefined }],
|
|
67
|
+
['it is still starting', { status: 'starting' }],
|
|
68
|
+
]) {
|
|
69
|
+
it(`discards a session and restarts when ${label}`, () => __awaiter(void 0, void 0, void 0, function* () {
|
|
70
|
+
const dead = session('android-1', 9100, overrides);
|
|
71
|
+
const svc = makeService(dead);
|
|
72
|
+
// No device in the store, so the fresh startup throws — proving we fell
|
|
73
|
+
// through rather than returning the stale port.
|
|
74
|
+
let err;
|
|
75
|
+
try {
|
|
76
|
+
yield svc.startStream('android-1');
|
|
77
|
+
}
|
|
78
|
+
catch (e) {
|
|
79
|
+
err = e;
|
|
80
|
+
}
|
|
81
|
+
(0, chai_1.expect)(err === null || err === void 0 ? void 0 : err.message, 'must attempt a real startup').to.match(/not found in DB/);
|
|
82
|
+
(0, chai_1.expect)(dead.status, 'capture loop must be told to stop').to.equal('stopped');
|
|
83
|
+
(0, chai_1.expect)(dead.server, 'server handle cleared').to.equal(null);
|
|
84
|
+
(0, chai_1.expect)(svc.sessions.has('android-1'), 'stale session evicted').to.be.false;
|
|
85
|
+
(0, chai_1.expect)(releaseSpy.calledWith(9100), 'stale port lease released').to.be.true;
|
|
86
|
+
}));
|
|
87
|
+
}
|
|
88
|
+
it('does not release a lease when there was no session at all', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
89
|
+
const svc = makeService(null);
|
|
90
|
+
yield svc.startStream('android-1').catch(() => undefined);
|
|
91
|
+
(0, chai_1.expect)(releaseSpy.called).to.be.false;
|
|
92
|
+
}));
|
|
93
|
+
});
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const chai_1 = require("chai");
|
|
4
|
+
const androidStreamReuse_1 = require("../../src/device-managers/android/androidStreamReuse");
|
|
5
|
+
// Guards issue #196. AndroidStreamService.startStream reused any session marked
|
|
6
|
+
// 'running' *or* 'starting' without checking that anything was still serving:
|
|
7
|
+
//
|
|
8
|
+
// const existing = this.sessions.get(udid);
|
|
9
|
+
// if (existing && (existing.status === 'running' || existing.status === 'starting')) {
|
|
10
|
+
// return { mjpegPort: existing.mjpegPort };
|
|
11
|
+
// }
|
|
12
|
+
//
|
|
13
|
+
// so a session whose HTTP server had closed, or which never captured a frame,
|
|
14
|
+
// handed every caller — including ensureMjpegForRecording — a port that serves
|
|
15
|
+
// nothing. ffmpeg then exits 1 against it and leaves a 0-byte mp4, the same
|
|
16
|
+
// silent symptom that took a while to diagnose in #194.
|
|
17
|
+
const healthy = {
|
|
18
|
+
status: 'running',
|
|
19
|
+
serverListening: true,
|
|
20
|
+
hasFrame: true,
|
|
21
|
+
};
|
|
22
|
+
describe('decideAndroidStreamReuse', () => {
|
|
23
|
+
it('reuses a running session that is listening and has a frame', () => {
|
|
24
|
+
(0, chai_1.expect)((0, androidStreamReuse_1.decideAndroidStreamReuse)(healthy)).to.deep.equal({ reuse: true });
|
|
25
|
+
});
|
|
26
|
+
it('starts fresh when there is no session', () => {
|
|
27
|
+
(0, chai_1.expect)((0, androidStreamReuse_1.decideAndroidStreamReuse)(undefined)).to.deep.equal({
|
|
28
|
+
reuse: false,
|
|
29
|
+
reason: 'no-session',
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
it("does not treat 'starting' as ready", () => {
|
|
33
|
+
// The bind loop registers the candidate as 'starting' *before* awaiting the
|
|
34
|
+
// listen, so a caller arriving in that window used to get a port that was
|
|
35
|
+
// not yet bound. SingleFlight (#195) closes the concurrent case; this keeps
|
|
36
|
+
// a session left stranded in 'starting' from being handed out later.
|
|
37
|
+
(0, chai_1.expect)((0, androidStreamReuse_1.decideAndroidStreamReuse)(Object.assign(Object.assign({}, healthy), { status: 'starting' }))).to.deep.equal({
|
|
38
|
+
reuse: false,
|
|
39
|
+
reason: 'not-running',
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
it('restarts a stopped or errored session', () => {
|
|
43
|
+
for (const status of ['stopped', 'error']) {
|
|
44
|
+
(0, chai_1.expect)((0, androidStreamReuse_1.decideAndroidStreamReuse)(Object.assign(Object.assign({}, healthy), { status })), status).to.deep.equal({
|
|
45
|
+
reuse: false,
|
|
46
|
+
reason: 'not-running',
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
it('restarts a running session whose server is no longer listening', () => {
|
|
51
|
+
(0, chai_1.expect)((0, androidStreamReuse_1.decideAndroidStreamReuse)(Object.assign(Object.assign({}, healthy), { serverListening: false }))).to.deep.equal({
|
|
52
|
+
reuse: false,
|
|
53
|
+
reason: 'server-closed',
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
it('restarts a running session that never captured a frame', () => {
|
|
57
|
+
// startStream logs "no frames captured after 5000ms" and goes 'running'
|
|
58
|
+
// anyway, so this state is reachable today: every later caller gets a live
|
|
59
|
+
// socket that emits headers and no JPEGs.
|
|
60
|
+
(0, chai_1.expect)((0, androidStreamReuse_1.decideAndroidStreamReuse)(Object.assign(Object.assign({}, healthy), { hasFrame: false }))).to.deep.equal({
|
|
61
|
+
reuse: false,
|
|
62
|
+
reason: 'no-frame',
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
it('reports the most fundamental failure first', () => {
|
|
66
|
+
// A session that is neither running nor listening is reported as
|
|
67
|
+
// 'not-running' — the reason drives a log line, so it should name the cause
|
|
68
|
+
// rather than a downstream consequence of it.
|
|
69
|
+
(0, chai_1.expect)((0, androidStreamReuse_1.decideAndroidStreamReuse)({ status: 'stopped', serverListening: false, hasFrame: false })).to.deep.equal({ reuse: false, reason: 'not-running' });
|
|
70
|
+
});
|
|
71
|
+
});
|
package/lib/tsconfig.tsbuildinfo
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["../src/InternalHttpClient.ts","../src/PluginContext.ts","../src/XenonCapabilityManager.ts","../src/chromeUtils.ts","../src/config.ts","../src/device-utils.ts","../src/index.ts","../src/logger.ts","../src/plugin.ts","../src/prisma.ts","../src/app/index.ts","../src/app/swagger-docs.ts","../src/app/swagger.ts","../src/app/routers/androidH264Config.ts","../src/app/routers/apikeys.ts","../src/app/routers/apps.ts","../src/app/routers/audit.ts","../src/app/routers/auth.ts","../src/app/routers/bug-report.ts","../src/app/routers/build-export.ts","../src/app/routers/capabilities.ts","../src/app/routers/config.ts","../src/app/routers/control.ts","../src/app/routers/dashboard.ts","../src/app/routers/grid.ts","../src/app/routers/interceptor.ts","../src/app/routers/iosStreamPort.ts","../src/app/routers/ports.ts","../src/app/routers/processes.ts","../src/app/routers/profile.ts","../src/app/routers/profileIdentity.ts","../src/app/routers/projects.ts","../src/app/routers/recordings.ts","../src/app/routers/reservation.ts","../src/app/routers/sdk-leases.ts","../src/app/routers/sdk-version.ts","../src/app/routers/streamType.ts","../src/app/routers/teams.ts","../src/app/routers/users.ts","../src/app/routers/webhook.ts","../src/app/ws/h264StreamWs.ts","../src/commands/handle.ts","../src/commands/index.ts","../src/dashboard/asset-manager.ts","../src/dashboard/commands.ts","../src/dashboard/event-manager.ts","../src/dashboard/services/app-service.ts","../src/dashboard/services/failure-analysis-service.ts","../src/dashboard/services/session-service.ts","../src/data-service/CircuitBreaker.ts","../src/data-service/config-service.ts","../src/data-service/db.ts","../src/data-service/device-service.ts","../src/data-service/device-store.interface.ts","../src/data-service/device-store.ts","../src/data-service/pending-sessions-service.ts","../src/data-service/pluginArgs.ts","../src/data-service/prisma-service.ts","../src/data-service/prisma-store.ts","../src/data-service/queue-service.ts","../src/data-service/web-config-service.ts","../src/device-managers/AndroidDeviceManager.ts","../src/device-managers/ChromeDriverManager.ts","../src/device-managers/HealthMonitorService.ts","../src/device-managers/IOSDeviceManager.ts","../src/device-managers/NodeDevices.ts","../src/device-managers/iOSTracker.ts","../src/device-managers/index.ts","../src/device-managers/android/AndroidH264StreamService.ts","../src/device-managers/android/AndroidStreamService.ts","../src/device-managers/android/DeviceLockManager.ts","../src/device-managers/android/H264Multiplexer.ts","../src/device-managers/android/ScrcpyServerSession.ts","../src/device-managers/android/h264NalParser.ts","../src/device-managers/android/scrcpyVersion.ts","../src/device-managers/cloud/CapabilityManager.ts","../src/device-managers/cloud/Devices.ts","../src/device-managers/ios/IOSDiscoveryService.ts","../src/device-managers/ios/IOSStreamService.ts","../src/device-managers/ios/WDAClient.ts","../src/device-managers/ios/iosBattery.ts","../src/device-managers/ios/iosStreamDiagnostics.ts","../src/device-managers/ios/tunnelProcess.ts","../src/enums/Capabilities.ts","../src/enums/Cloud.ts","../src/enums/Platform.ts","../src/enums/SessionType.ts","../src/enums/SocketEvents.ts","../src/generated/client/default.d.ts","../src/generated/client/default.js","../src/generated/client/edge.d.ts","../src/generated/client/edge.js","../src/generated/client/index-browser.js","../src/generated/client/index.d.ts","../src/generated/client/index.js","../src/generated/client/wasm.d.ts","../src/generated/client/wasm.js","../src/generated/client/runtime/edge-esm.js","../src/generated/client/runtime/edge.js","../src/generated/client/runtime/index-browser.d.ts","../src/generated/client/runtime/index-browser.js","../src/generated/client/runtime/library.d.ts","../src/generated/client/runtime/library.js","../src/generated/client/runtime/react-native.js","../src/generated/client/runtime/wasm.js","../src/helpers/UniversalMjpegProxy.ts","../src/helpers/ffmpegPath.ts","../src/helpers/index.ts","../src/helpers/networkAddresses.ts","../src/helpers/singleFlight.ts","../src/interceptors/CommandInterceptor.ts","../src/interfaces/ICloudManager.ts","../src/interfaces/IDevice.ts","../src/interfaces/IDeviceFilterOptions.ts","../src/interfaces/IDeviceManager.ts","../src/interfaces/IOptions.ts","../src/interfaces/IPluginArgs.ts","../src/interfaces/ISessionCapability.ts","../src/logging/sessionContext.ts","../src/middleware/authMiddleware.ts","../src/middleware/csrfMiddleware.ts","../src/middleware/leaseTokenMiddleware.ts","../src/middleware/loginRateLimiter.ts","../src/middleware/rateLimitMiddleware.ts","../src/middleware/roleGuard.ts","../src/middleware/scopeGuard.ts","../src/profiling/AndroidAppProfiler.ts","../src/proxy/wd-command-proxy.ts","../src/scripts/generate-database-migration.ts","../src/scripts/goIosVersion.ts","../src/scripts/initialize-database.ts","../src/scripts/install-go-ios.ts","../src/scripts/prepare-prisma.ts","../src/scripts/run-migrations.ts","../src/services/AICommandService.ts","../src/services/AIService.ts","../src/services/ApiKeyService.ts","../src/services/CircuitBreaker.ts","../src/services/CleanupService.ts","../src/services/DeviceReconciler.ts","../src/services/EmailService.ts","../src/services/EventBus.ts","../src/services/EventLogService.ts","../src/services/InspectorService.ts","../src/services/InterceptorService.ts","../src/services/MetricsService.ts","../src/services/NetworkConditioningService.ts","../src/services/NotificationService.ts","../src/services/OrphanSweeper.ts","../src/services/PasswordResetService.ts","../src/services/PortAllocator.ts","../src/services/ProcessMetricsService.ts","../src/services/ProcessRegistry.ts","../src/services/RequestLogService.ts","../src/services/ResourceIsolationService.ts","../src/services/SecurityService.ts","../src/services/SelectorStateService.ts","../src/services/SelectorVerificationJob.ts","../src/services/ServerManager.ts","../src/services/SessionHeartbeatService.ts","../src/services/SessionLifecycleService.ts","../src/services/ShutdownCoordinator.ts","../src/services/SocketClient.ts","../src/services/SocketServer.ts","../src/services/TeamService.ts","../src/services/TracingService.ts","../src/services/UserService.ts","../src/services/UserSessionService.ts","../src/services/VideoPipelineService.ts","../src/services/sessionTokenGate.ts","../src/services/artifacts/ArtifactStore.ts","../src/services/autowait/AutowaitService.ts","../src/services/autowait/waitFor.ts","../src/services/bug-report/BugReportService.ts","../src/services/bug-report/archive.ts","../src/services/bug-report/har-collector.ts","../src/services/bug-report/manifest.ts","../src/services/bug-report/readme.ts","../src/services/bug-report/types.ts","../src/services/bug-report/video-slice.ts","../src/services/bug-report/window.ts","../src/services/healing/FuzzyXmlHealingProvider.ts","../src/services/healing/HealEtalonService.ts","../src/services/healing/HealedLocatorGenerator.ts","../src/services/healing/HealingMetrics.ts","../src/services/healing/HealingOrchestrator.ts","../src/services/healing/LlmHealingProvider.ts","../src/services/healing/OcrHealingProvider.ts","../src/services/healing/ResilioTreeHealingProvider.ts","../src/services/healing/VisualAiHealingProvider.ts","../src/services/healing/types.ts","../src/services/identity/bootstrap.ts","../src/services/identity/sessionCleanupCron.ts","../src/services/identity/userAuthorization.ts","../src/services/interceptor/AndroidProxyAdapter.ts","../src/services/interceptor/CertManager.ts","../src/services/interceptor/HarBuilder.ts","../src/services/interceptor/HostFilter.ts","../src/services/interceptor/MitmProxyHost.ts","../src/services/interceptor/MockEngine.ts","../src/services/interceptor/RequestBuffer.ts","../src/services/interceptor/SessionArchive.ts","../src/services/interceptor/types.ts","../src/services/lease/LeaseOrphanSweeper.ts","../src/services/lease/LeaseService.ts","../src/services/lease/buildCapabilityBag.ts","../src/services/lease/leaseToken.ts","../src/services/omni-vision/OmniVisionService.ts","../src/services/omni-vision/VisionAssertionService.ts","../src/services/ports/PortAllocatorClient.ts","../src/services/ports/PortAllocatorService.ts","../src/services/recording/RecordingOrchestrator.ts","../src/services/recording/annotation-render.ts","../src/services/recording/busy-precheck.ts","../src/services/recording/concurrency-gate.ts","../src/services/recording/ensureMjpegForRecording.ts","../src/services/recording/manualLock.ts","../src/services/recording/proof-bundle.ts","../src/services/recording/recording-store.ts","../src/services/telemetry/attributes.ts","../src/services/token/JwtKeyService.ts","../src/services/token/StreamTicketService.ts","../src/services/token/mcpScopes.ts","../src/sessions/CloudSession.ts","../src/sessions/LocalSession.ts","../src/sessions/RemoteSession.ts","../src/sessions/SessionManager.ts","../src/sessions/XenonSession.ts","../src/types/CLIArgs.ts","../src/types/CloudArgs.ts","../src/types/CloudSchema.ts","../src/types/DeviceType.ts","../src/types/DeviceUpdate.ts","../src/types/IOSDevice.ts","../src/types/Platform.ts","../src/types/SessionStatus.ts","../src/types/express.d.ts","../src/types/healing.d.ts","../src/types/identity.ts","../src/validators/CapabilityValidator.ts","../test/e2e/e2ehelper.ts","../test/e2e/plugin-harness.ts","../test/e2e/plugin.spec.ts","../test/e2e/startup-verification.spec.ts","../test/e2e/telemetry_verification.spec.ts","../test/e2e/video-recording-test.spec.js","../test/e2e/android/conf.spec.js","../test/e2e/android/conf2.spec.js","../test/e2e/android/conf3.spec.js","../test/e2e/hubnode/forward-request.spec.ts","../test/e2e/hubnode/hubnode.spec.ts","../test/e2e/ios/conf1.spec.js","../test/e2e/ios/conf2.spec.js","../test/helpers/seedUser.ts","../test/helpers/test-container.ts","../test/integration/androidDevices.spec.ts","../test/integration/audit-ingest.spec.ts","../test/integration/auth-flow.spec.ts","../test/integration/auth-rate-limit.spec.ts","../test/integration/bug-report-route.spec.ts","../test/integration/cliArgs.js","../test/integration/cross-workflow.spec.ts","../test/integration/forgot-password-rate-limit.spec.ts","../test/integration/forgot-password.spec.ts","../test/integration/healing-events-sessionfilter.spec.ts","../test/integration/legacy-deprecation-headers.spec.ts","../test/integration/migration.spec.ts","../test/integration/node-pair-auth-rest.spec.ts","../test/integration/ports-router.spec.ts","../test/integration/profile-tokens.spec.ts","../test/integration/recordings-router.spec.ts","../test/integration/reset-revokes-sessions.spec.ts","../test/integration/role-matrix.spec.ts","../test/integration/sdk-leases-router.spec.ts","../test/integration/sdk-version.spec.ts","../test/integration/selector-health-endpoint.spec.ts","../test/integration/selector-state-flow.spec.ts","../test/integration/team-membership-migration.spec.ts","../test/integration/team-visibility-dashboard.spec.ts","../test/integration/team-visibility-grid.spec.ts","../test/integration/team-visibility-recordings.spec.ts","../test/integration/users-flow.spec.ts","../test/integration/users-lockout.spec.ts","../test/integration/ios/01iOSSimulator.spec.ts","../test/integration/ios/02iOSDevices.spec.ts","../test/unit/AndroidDeviceManager.spec.ts","../test/unit/ApiKeyService.test.ts","../test/unit/ArtifactStore.spec.ts","../test/unit/AutowaitService.spec.ts","../test/unit/CapabilitiesRouter.spec.ts","../test/unit/ChromeDriverManager.spec.js","../test/unit/CleanupService.spec.ts","../test/unit/CommandInterceptor.autowait.spec.ts","../test/unit/DeviceModel.spec.ts","../test/unit/EmailService.test.ts","../test/unit/EventLogService.spec.ts","../test/unit/FuzzyXmlHealingProvider.test.ts","../test/unit/GetAdbOriginal.js","../test/unit/HealingCascade.test.ts","../test/unit/IOSDeviceManager.spec.js","../test/unit/JwtKeyService.spec.ts","../test/unit/McpScopes.spec.ts","../test/unit/OrphanSweeper.test.ts","../test/unit/PasswordResetService.test.ts","../test/unit/PortAllocator.test.ts","../test/unit/ProcessRegistry.test.ts","../test/unit/ProjectsRouter.spec.ts","../test/unit/RemoteIOs.spec.js","../test/unit/ResilioTreeHealingProvider.test.ts","../test/unit/SessionHeartbeatWrite.test.ts","../test/unit/SessionLifecycleCaps.spec.ts","../test/unit/SessionTokenGate.spec.ts","../test/unit/StreamTicketService.spec.ts","../test/unit/TeamService.test.ts","../test/unit/TokenEndpoint.spec.ts","../test/unit/UserService.test.ts","../test/unit/UserSessionService.test.ts","../test/unit/XenonCapabilityManager.spec.ts","../test/unit/aggregate-hotspots-tuple-key.spec.ts","../test/unit/android-h264-config.spec.ts","../test/unit/android-h264-service.spec.ts","../test/unit/android-stream-adb-path.spec.ts","../test/unit/android-stream-encoder.spec.ts","../test/unit/android-stream-fast-start.spec.ts","../test/unit/android-stream-release.spec.ts","../test/unit/annotation-render.spec.ts","../test/unit/auth-me-auth-disabled.test.ts","../test/unit/authMiddleware.bearer.spec.ts","../test/unit/authMiddleware.mcpAudience.spec.ts","../test/unit/authMiddleware.streamTicket.spec.ts","../test/unit/authMiddleware.test.ts","../test/unit/bootstrap-identity.test.ts","../test/unit/build-export.spec.ts","../test/unit/busy-precheck.spec.ts","../test/unit/commands.spec.js","../test/unit/concurrency-gate.spec.ts","../test/unit/config.spec.js","../test/unit/device-service.spec.ts","../test/unit/device-utils.spec.ts","../test/unit/enrich-devices-team-names.test.ts","../test/unit/event-manager-regression-hook.spec.ts","../test/unit/extract-access-key-token-pair.test.ts","../test/unit/ffmpeg-path.spec.ts","../test/unit/findAndLockDevice-leasemerge.spec.ts","../test/unit/go-ios-version.spec.ts","../test/unit/h264-multiplexer.spec.ts","../test/unit/h264-nal-parser.spec.ts","../test/unit/h264-ws-frame.spec.ts","../test/unit/healing-instrumentation.spec.ts","../test/unit/healing-state-endpoints.spec.ts","../test/unit/healing-tier-gate.spec.ts","../test/unit/helpers.spec.ts","../test/unit/ios-stream-port.spec.ts","../test/unit/ios-tunnel-process.spec.ts","../test/unit/iosBattery.spec.ts","../test/unit/iosStreamDiagnostics.spec.ts","../test/unit/loginRateLimiter.test.ts","../test/unit/manualLock.test.ts","../test/unit/mjpeg-proxy-cache.spec.ts","../test/unit/network-addresses.test.ts","../test/unit/normalize-eol.spec.js","../test/unit/omni-vision.spec.ts","../test/unit/plugin.spec.ts","../test/unit/prisma.spec.ts","../test/unit/profile-router.test.ts","../test/unit/profileIdentity.spec.ts","../test/unit/proof-bundle.spec.ts","../test/unit/rateLimitMiddleware.test.ts","../test/unit/recording-instrumentation.spec.ts","../test/unit/recording-orchestrator.spec.ts","../test/unit/recording-store.spec.ts","../test/unit/remux-to-standard-mp4.spec.ts","../test/unit/roleGuard.test.ts","../test/unit/run-migrations-fail-fast.test.ts","../test/unit/run-migrations.test.ts","../test/unit/scrcpy-server-session.spec.ts","../test/unit/scrcpy-version.spec.ts","../test/unit/selector-state-service.spec.ts","../test/unit/selector-verification-job.spec.ts","../test/unit/single-flight.spec.ts","../test/unit/socketServer.bearer.spec.ts","../test/unit/stream-status-type.spec.ts","../test/unit/team-filter.test.ts","../test/unit/tracing-service-init.spec.ts","../test/unit/userAuthorization.test.ts","../test/unit/users-router.test.ts","../test/unit/video-pipeline-args.spec.ts","../test/unit/video-pipeline-outputpath.spec.ts","../test/unit/bug-report/archive.spec.ts","../test/unit/bug-report/har-collector.spec.ts","../test/unit/bug-report/manifest.spec.ts","../test/unit/bug-report/readme.spec.ts","../test/unit/bug-report/route.spec.ts","../test/unit/bug-report/service.spec.ts","../test/unit/bug-report/video-slice.spec.ts","../test/unit/bug-report/window.spec.ts","../test/unit/fixtures/device.config.js","../test/unit/fixtures/devices.js","../test/unit/interceptor/AndroidProxyAdapter.spec.ts","../test/unit/interceptor/CertManager.spec.ts","../test/unit/interceptor/HarBuilder.spec.ts","../test/unit/interceptor/HostFilter.spec.ts","../test/unit/interceptor/MitmProxyHost.spec.ts","../test/unit/interceptor/MockEngine.spec.ts","../test/unit/interceptor/RequestBuffer.spec.ts","../test/unit/interceptor/SessionArchive.spec.ts","../test/unit/lease/LeaseOrphanSweeper.spec.ts","../test/unit/lease/LeaseService.spec.ts","../test/unit/lease/buildCapabilityBag.spec.ts","../test/unit/lease/leaseToken.spec.ts","../test/unit/lease/nodePairAuth.spec.ts","../test/unit/ports/PortAllocatorService.spec.ts"],"version":"5.9.3"}
|
|
1
|
+
{"root":["../src/InternalHttpClient.ts","../src/PluginContext.ts","../src/XenonCapabilityManager.ts","../src/chromeUtils.ts","../src/config.ts","../src/device-utils.ts","../src/index.ts","../src/logger.ts","../src/plugin.ts","../src/prisma.ts","../src/app/index.ts","../src/app/swagger-docs.ts","../src/app/swagger.ts","../src/app/routers/androidH264Config.ts","../src/app/routers/apikeys.ts","../src/app/routers/apps.ts","../src/app/routers/audit.ts","../src/app/routers/auth.ts","../src/app/routers/bug-report.ts","../src/app/routers/build-export.ts","../src/app/routers/capabilities.ts","../src/app/routers/config.ts","../src/app/routers/control.ts","../src/app/routers/dashboard.ts","../src/app/routers/grid.ts","../src/app/routers/interceptor.ts","../src/app/routers/iosStreamPort.ts","../src/app/routers/ports.ts","../src/app/routers/processes.ts","../src/app/routers/profile.ts","../src/app/routers/profileIdentity.ts","../src/app/routers/projects.ts","../src/app/routers/recordings.ts","../src/app/routers/reservation.ts","../src/app/routers/sdk-leases.ts","../src/app/routers/sdk-version.ts","../src/app/routers/streamType.ts","../src/app/routers/teams.ts","../src/app/routers/users.ts","../src/app/routers/webhook.ts","../src/app/ws/h264StreamWs.ts","../src/commands/handle.ts","../src/commands/index.ts","../src/dashboard/asset-manager.ts","../src/dashboard/commands.ts","../src/dashboard/event-manager.ts","../src/dashboard/services/app-service.ts","../src/dashboard/services/failure-analysis-service.ts","../src/dashboard/services/session-service.ts","../src/data-service/CircuitBreaker.ts","../src/data-service/config-service.ts","../src/data-service/db.ts","../src/data-service/device-service.ts","../src/data-service/device-store.interface.ts","../src/data-service/device-store.ts","../src/data-service/pending-sessions-service.ts","../src/data-service/pluginArgs.ts","../src/data-service/prisma-service.ts","../src/data-service/prisma-store.ts","../src/data-service/queue-service.ts","../src/data-service/web-config-service.ts","../src/device-managers/AndroidDeviceManager.ts","../src/device-managers/ChromeDriverManager.ts","../src/device-managers/HealthMonitorService.ts","../src/device-managers/IOSDeviceManager.ts","../src/device-managers/NodeDevices.ts","../src/device-managers/iOSTracker.ts","../src/device-managers/index.ts","../src/device-managers/android/AndroidH264StreamService.ts","../src/device-managers/android/AndroidStreamService.ts","../src/device-managers/android/DeviceLockManager.ts","../src/device-managers/android/H264Multiplexer.ts","../src/device-managers/android/ScrcpyServerSession.ts","../src/device-managers/android/androidStreamReuse.ts","../src/device-managers/android/h264NalParser.ts","../src/device-managers/android/scrcpyVersion.ts","../src/device-managers/cloud/CapabilityManager.ts","../src/device-managers/cloud/Devices.ts","../src/device-managers/ios/IOSDiscoveryService.ts","../src/device-managers/ios/IOSStreamService.ts","../src/device-managers/ios/WDAClient.ts","../src/device-managers/ios/iosBattery.ts","../src/device-managers/ios/iosStreamDiagnostics.ts","../src/device-managers/ios/tunnelProcess.ts","../src/enums/Capabilities.ts","../src/enums/Cloud.ts","../src/enums/Platform.ts","../src/enums/SessionType.ts","../src/enums/SocketEvents.ts","../src/generated/client/default.d.ts","../src/generated/client/default.js","../src/generated/client/edge.d.ts","../src/generated/client/edge.js","../src/generated/client/index-browser.js","../src/generated/client/index.d.ts","../src/generated/client/index.js","../src/generated/client/wasm.d.ts","../src/generated/client/wasm.js","../src/generated/client/runtime/edge-esm.js","../src/generated/client/runtime/edge.js","../src/generated/client/runtime/index-browser.d.ts","../src/generated/client/runtime/index-browser.js","../src/generated/client/runtime/library.d.ts","../src/generated/client/runtime/library.js","../src/generated/client/runtime/react-native.js","../src/generated/client/runtime/wasm.js","../src/helpers/UniversalMjpegProxy.ts","../src/helpers/ffmpegPath.ts","../src/helpers/index.ts","../src/helpers/networkAddresses.ts","../src/helpers/singleFlight.ts","../src/interceptors/CommandInterceptor.ts","../src/interfaces/ICloudManager.ts","../src/interfaces/IDevice.ts","../src/interfaces/IDeviceFilterOptions.ts","../src/interfaces/IDeviceManager.ts","../src/interfaces/IOptions.ts","../src/interfaces/IPluginArgs.ts","../src/interfaces/ISessionCapability.ts","../src/logging/sessionContext.ts","../src/middleware/authMiddleware.ts","../src/middleware/csrfMiddleware.ts","../src/middleware/leaseTokenMiddleware.ts","../src/middleware/loginRateLimiter.ts","../src/middleware/rateLimitMiddleware.ts","../src/middleware/roleGuard.ts","../src/middleware/scopeGuard.ts","../src/profiling/AndroidAppProfiler.ts","../src/proxy/wd-command-proxy.ts","../src/scripts/generate-database-migration.ts","../src/scripts/goIosVersion.ts","../src/scripts/initialize-database.ts","../src/scripts/install-go-ios.ts","../src/scripts/prepare-prisma.ts","../src/scripts/run-migrations.ts","../src/services/AICommandService.ts","../src/services/AIService.ts","../src/services/ApiKeyService.ts","../src/services/CircuitBreaker.ts","../src/services/CleanupService.ts","../src/services/DeviceReconciler.ts","../src/services/EmailService.ts","../src/services/EventBus.ts","../src/services/EventLogService.ts","../src/services/InspectorService.ts","../src/services/InterceptorService.ts","../src/services/MetricsService.ts","../src/services/NetworkConditioningService.ts","../src/services/NotificationService.ts","../src/services/OrphanSweeper.ts","../src/services/PasswordResetService.ts","../src/services/PortAllocator.ts","../src/services/ProcessMetricsService.ts","../src/services/ProcessRegistry.ts","../src/services/RequestLogService.ts","../src/services/ResourceIsolationService.ts","../src/services/SecurityService.ts","../src/services/SelectorStateService.ts","../src/services/SelectorVerificationJob.ts","../src/services/ServerManager.ts","../src/services/SessionHeartbeatService.ts","../src/services/SessionLifecycleService.ts","../src/services/ShutdownCoordinator.ts","../src/services/SocketClient.ts","../src/services/SocketServer.ts","../src/services/TeamService.ts","../src/services/TracingService.ts","../src/services/UserService.ts","../src/services/UserSessionService.ts","../src/services/VideoPipelineService.ts","../src/services/sessionTokenGate.ts","../src/services/artifacts/ArtifactStore.ts","../src/services/autowait/AutowaitService.ts","../src/services/autowait/waitFor.ts","../src/services/bug-report/BugReportService.ts","../src/services/bug-report/archive.ts","../src/services/bug-report/har-collector.ts","../src/services/bug-report/manifest.ts","../src/services/bug-report/readme.ts","../src/services/bug-report/types.ts","../src/services/bug-report/video-slice.ts","../src/services/bug-report/window.ts","../src/services/healing/FuzzyXmlHealingProvider.ts","../src/services/healing/HealEtalonService.ts","../src/services/healing/HealedLocatorGenerator.ts","../src/services/healing/HealingMetrics.ts","../src/services/healing/HealingOrchestrator.ts","../src/services/healing/LlmHealingProvider.ts","../src/services/healing/OcrHealingProvider.ts","../src/services/healing/ResilioTreeHealingProvider.ts","../src/services/healing/VisualAiHealingProvider.ts","../src/services/healing/types.ts","../src/services/identity/bootstrap.ts","../src/services/identity/sessionCleanupCron.ts","../src/services/identity/userAuthorization.ts","../src/services/interceptor/AndroidProxyAdapter.ts","../src/services/interceptor/CertManager.ts","../src/services/interceptor/HarBuilder.ts","../src/services/interceptor/HostFilter.ts","../src/services/interceptor/MitmProxyHost.ts","../src/services/interceptor/MockEngine.ts","../src/services/interceptor/RequestBuffer.ts","../src/services/interceptor/SessionArchive.ts","../src/services/interceptor/types.ts","../src/services/lease/LeaseOrphanSweeper.ts","../src/services/lease/LeaseService.ts","../src/services/lease/buildCapabilityBag.ts","../src/services/lease/leaseToken.ts","../src/services/omni-vision/OmniVisionService.ts","../src/services/omni-vision/VisionAssertionService.ts","../src/services/ports/PortAllocatorClient.ts","../src/services/ports/PortAllocatorService.ts","../src/services/recording/RecordingOrchestrator.ts","../src/services/recording/annotation-render.ts","../src/services/recording/busy-precheck.ts","../src/services/recording/concurrency-gate.ts","../src/services/recording/ensureMjpegForRecording.ts","../src/services/recording/manualLock.ts","../src/services/recording/proof-bundle.ts","../src/services/recording/recording-store.ts","../src/services/telemetry/attributes.ts","../src/services/token/JwtKeyService.ts","../src/services/token/StreamTicketService.ts","../src/services/token/mcpScopes.ts","../src/sessions/CloudSession.ts","../src/sessions/LocalSession.ts","../src/sessions/RemoteSession.ts","../src/sessions/SessionManager.ts","../src/sessions/XenonSession.ts","../src/types/CLIArgs.ts","../src/types/CloudArgs.ts","../src/types/CloudSchema.ts","../src/types/DeviceType.ts","../src/types/DeviceUpdate.ts","../src/types/IOSDevice.ts","../src/types/Platform.ts","../src/types/SessionStatus.ts","../src/types/express.d.ts","../src/types/healing.d.ts","../src/types/identity.ts","../src/validators/CapabilityValidator.ts","../test/e2e/e2ehelper.ts","../test/e2e/plugin-harness.ts","../test/e2e/plugin.spec.ts","../test/e2e/startup-verification.spec.ts","../test/e2e/telemetry_verification.spec.ts","../test/e2e/video-recording-test.spec.js","../test/e2e/android/conf.spec.js","../test/e2e/android/conf2.spec.js","../test/e2e/android/conf3.spec.js","../test/e2e/hubnode/forward-request.spec.ts","../test/e2e/hubnode/hubnode.spec.ts","../test/e2e/ios/conf1.spec.js","../test/e2e/ios/conf2.spec.js","../test/helpers/seedUser.ts","../test/helpers/test-container.ts","../test/integration/androidDevices.spec.ts","../test/integration/audit-ingest.spec.ts","../test/integration/auth-flow.spec.ts","../test/integration/auth-rate-limit.spec.ts","../test/integration/bug-report-route.spec.ts","../test/integration/cliArgs.js","../test/integration/cross-workflow.spec.ts","../test/integration/forgot-password-rate-limit.spec.ts","../test/integration/forgot-password.spec.ts","../test/integration/healing-events-sessionfilter.spec.ts","../test/integration/legacy-deprecation-headers.spec.ts","../test/integration/migration.spec.ts","../test/integration/node-pair-auth-rest.spec.ts","../test/integration/ports-router.spec.ts","../test/integration/profile-tokens.spec.ts","../test/integration/recordings-router.spec.ts","../test/integration/reset-revokes-sessions.spec.ts","../test/integration/role-matrix.spec.ts","../test/integration/sdk-leases-router.spec.ts","../test/integration/sdk-version.spec.ts","../test/integration/selector-health-endpoint.spec.ts","../test/integration/selector-state-flow.spec.ts","../test/integration/team-membership-migration.spec.ts","../test/integration/team-visibility-dashboard.spec.ts","../test/integration/team-visibility-grid.spec.ts","../test/integration/team-visibility-recordings.spec.ts","../test/integration/users-flow.spec.ts","../test/integration/users-lockout.spec.ts","../test/integration/ios/01iOSSimulator.spec.ts","../test/integration/ios/02iOSDevices.spec.ts","../test/unit/AndroidDeviceManager.spec.ts","../test/unit/ApiKeyService.test.ts","../test/unit/ArtifactStore.spec.ts","../test/unit/AutowaitService.spec.ts","../test/unit/CapabilitiesRouter.spec.ts","../test/unit/ChromeDriverManager.spec.js","../test/unit/CleanupService.spec.ts","../test/unit/CommandInterceptor.autowait.spec.ts","../test/unit/DeviceModel.spec.ts","../test/unit/EmailService.test.ts","../test/unit/EventLogService.spec.ts","../test/unit/FuzzyXmlHealingProvider.test.ts","../test/unit/GetAdbOriginal.js","../test/unit/HealingCascade.test.ts","../test/unit/IOSDeviceManager.spec.js","../test/unit/JwtKeyService.spec.ts","../test/unit/McpScopes.spec.ts","../test/unit/OrphanSweeper.test.ts","../test/unit/PasswordResetService.test.ts","../test/unit/PortAllocator.test.ts","../test/unit/ProcessRegistry.test.ts","../test/unit/ProjectsRouter.spec.ts","../test/unit/RemoteIOs.spec.js","../test/unit/ResilioTreeHealingProvider.test.ts","../test/unit/SessionHeartbeatWrite.test.ts","../test/unit/SessionLifecycleCaps.spec.ts","../test/unit/SessionTokenGate.spec.ts","../test/unit/StreamTicketService.spec.ts","../test/unit/TeamService.test.ts","../test/unit/TokenEndpoint.spec.ts","../test/unit/UserService.test.ts","../test/unit/UserSessionService.test.ts","../test/unit/XenonCapabilityManager.spec.ts","../test/unit/aggregate-hotspots-tuple-key.spec.ts","../test/unit/android-h264-config.spec.ts","../test/unit/android-h264-service.spec.ts","../test/unit/android-stream-adb-path.spec.ts","../test/unit/android-stream-encoder.spec.ts","../test/unit/android-stream-fast-start.spec.ts","../test/unit/android-stream-release.spec.ts","../test/unit/android-stream-reuse-service.spec.ts","../test/unit/android-stream-reuse.spec.ts","../test/unit/annotation-render.spec.ts","../test/unit/auth-me-auth-disabled.test.ts","../test/unit/authMiddleware.bearer.spec.ts","../test/unit/authMiddleware.mcpAudience.spec.ts","../test/unit/authMiddleware.streamTicket.spec.ts","../test/unit/authMiddleware.test.ts","../test/unit/bootstrap-identity.test.ts","../test/unit/build-export.spec.ts","../test/unit/busy-precheck.spec.ts","../test/unit/commands.spec.js","../test/unit/concurrency-gate.spec.ts","../test/unit/config.spec.js","../test/unit/device-service.spec.ts","../test/unit/device-utils.spec.ts","../test/unit/enrich-devices-team-names.test.ts","../test/unit/event-manager-regression-hook.spec.ts","../test/unit/extract-access-key-token-pair.test.ts","../test/unit/ffmpeg-path.spec.ts","../test/unit/findAndLockDevice-leasemerge.spec.ts","../test/unit/go-ios-version.spec.ts","../test/unit/h264-multiplexer.spec.ts","../test/unit/h264-nal-parser.spec.ts","../test/unit/h264-ws-frame.spec.ts","../test/unit/healing-instrumentation.spec.ts","../test/unit/healing-state-endpoints.spec.ts","../test/unit/healing-tier-gate.spec.ts","../test/unit/helpers.spec.ts","../test/unit/ios-stream-port.spec.ts","../test/unit/ios-tunnel-process.spec.ts","../test/unit/iosBattery.spec.ts","../test/unit/iosStreamDiagnostics.spec.ts","../test/unit/loginRateLimiter.test.ts","../test/unit/manualLock.test.ts","../test/unit/mjpeg-proxy-cache.spec.ts","../test/unit/network-addresses.test.ts","../test/unit/normalize-eol.spec.js","../test/unit/omni-vision.spec.ts","../test/unit/plugin.spec.ts","../test/unit/prisma.spec.ts","../test/unit/profile-router.test.ts","../test/unit/profileIdentity.spec.ts","../test/unit/proof-bundle.spec.ts","../test/unit/rateLimitMiddleware.test.ts","../test/unit/recording-instrumentation.spec.ts","../test/unit/recording-orchestrator.spec.ts","../test/unit/recording-store.spec.ts","../test/unit/remux-to-standard-mp4.spec.ts","../test/unit/roleGuard.test.ts","../test/unit/run-migrations-fail-fast.test.ts","../test/unit/run-migrations.test.ts","../test/unit/scrcpy-server-session.spec.ts","../test/unit/scrcpy-version.spec.ts","../test/unit/selector-state-service.spec.ts","../test/unit/selector-verification-job.spec.ts","../test/unit/single-flight.spec.ts","../test/unit/socketServer.bearer.spec.ts","../test/unit/stream-status-type.spec.ts","../test/unit/team-filter.test.ts","../test/unit/tracing-service-init.spec.ts","../test/unit/userAuthorization.test.ts","../test/unit/users-router.test.ts","../test/unit/video-pipeline-args.spec.ts","../test/unit/video-pipeline-outputpath.spec.ts","../test/unit/bug-report/archive.spec.ts","../test/unit/bug-report/har-collector.spec.ts","../test/unit/bug-report/manifest.spec.ts","../test/unit/bug-report/readme.spec.ts","../test/unit/bug-report/route.spec.ts","../test/unit/bug-report/service.spec.ts","../test/unit/bug-report/video-slice.spec.ts","../test/unit/bug-report/window.spec.ts","../test/unit/fixtures/device.config.js","../test/unit/fixtures/devices.js","../test/unit/interceptor/AndroidProxyAdapter.spec.ts","../test/unit/interceptor/CertManager.spec.ts","../test/unit/interceptor/HarBuilder.spec.ts","../test/unit/interceptor/HostFilter.spec.ts","../test/unit/interceptor/MitmProxyHost.spec.ts","../test/unit/interceptor/MockEngine.spec.ts","../test/unit/interceptor/RequestBuffer.spec.ts","../test/unit/interceptor/SessionArchive.spec.ts","../test/unit/lease/LeaseOrphanSweeper.spec.ts","../test/unit/lease/LeaseService.spec.ts","../test/unit/lease/buildCapabilityBag.spec.ts","../test/unit/lease/leaseToken.spec.ts","../test/unit/lease/nodePairAuth.spec.ts","../test/unit/ports/PortAllocatorService.spec.ts"],"version":"5.9.3"}
|
package/package.json
CHANGED