@xenon-device-management/xenon 1.17.5 → 1.18.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/services/InspectorService.js +35 -11
- package/lib/test/unit/inspector-hierarchy.spec.js +55 -0
- package/lib/test/unit/sync-dir.spec.js +104 -0
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/scripts/generate-prisma.js +28 -18
- package/scripts/lib/sync-dir.js +92 -0
package/lib/package.json
CHANGED
|
@@ -432,28 +432,46 @@ let InspectorService = class InspectorService {
|
|
|
432
432
|
score: 95,
|
|
433
433
|
});
|
|
434
434
|
}
|
|
435
|
+
// On iOS `node.text` is `label || value`, so every locator that selects on
|
|
436
|
+
// it — predicate and xpath alike — has to name whichever of the two
|
|
437
|
+
// actually supplied it. Hardcoding `label` sends a page indicator, whose
|
|
438
|
+
// text lives in `value`, to a predicate that matches nothing.
|
|
439
|
+
const iosTextAttr = asText(node.attributes.label) === node.text ? 'label' : 'value';
|
|
435
440
|
// 3. Platform Specific - Performance Tier
|
|
436
441
|
if (platform === 'ios') {
|
|
437
442
|
// iOS Predicate String - High Performance
|
|
438
|
-
const
|
|
443
|
+
const predicateValue = node.text || node.label || '';
|
|
439
444
|
if (node.text || node.label) {
|
|
440
445
|
suggestions.push({
|
|
441
446
|
strategy: '-ios predicate string',
|
|
442
|
-
value:
|
|
443
|
-
|
|
447
|
+
value: `type == "${node.type}" AND ${iosTextAttr} == "${predicateValue}"`,
|
|
448
|
+
// A compound predicate is at least as selective as its label term, so
|
|
449
|
+
// a unique label makes it unique. The converse does not hold — two
|
|
450
|
+
// elements sharing a label may differ by type — which makes this
|
|
451
|
+
// conservative rather than exact, and that is the right direction:
|
|
452
|
+
// it was previously hardcoded true, and a predicate badged unique
|
|
453
|
+
// was measured against a real device matching two elements.
|
|
454
|
+
unique: this.isUnique(uniqueness, 'text', predicateValue),
|
|
444
455
|
score: 90,
|
|
445
456
|
});
|
|
446
457
|
}
|
|
447
458
|
// iOS Class Chain - High Precision
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
459
|
+
//
|
|
460
|
+
// The predicate MUST be wrapped in backticks. Without them Appium
|
|
461
|
+
// resolves nothing at all: measured against a real iPhone,
|
|
462
|
+
// `**/XCUIElementTypePageIndicator[name == "Page control"]` found 0
|
|
463
|
+
// elements and the same chain with backticks found 1. Every class chain
|
|
464
|
+
// this service produced was unusable, and each was badged unique — 280
|
|
465
|
+
// of them in a single snapshot of a home screen.
|
|
466
|
+
const chainValue = node.attributes.name ? String(node.attributes.name) : node.text || '';
|
|
467
|
+
const chainTerm = node.attributes.name ? 'name' : 'label';
|
|
453
468
|
suggestions.push({
|
|
454
469
|
strategy: '-ios class chain',
|
|
455
|
-
value:
|
|
456
|
-
|
|
470
|
+
value: `**/${node.type}[\`${chainTerm} == "${chainValue}"\`]`,
|
|
471
|
+
// Same index the accessibility-id suggestion uses, and the same value:
|
|
472
|
+
// a node's identity there is `name || label`, which is exactly what
|
|
473
|
+
// the chain selects on.
|
|
474
|
+
unique: this.isUnique(uniqueness, 'accessibility id', chainValue),
|
|
457
475
|
score: 85,
|
|
458
476
|
});
|
|
459
477
|
}
|
|
@@ -495,9 +513,15 @@ let InspectorService = class InspectorService {
|
|
|
495
513
|
});
|
|
496
514
|
}
|
|
497
515
|
else if (node.text) {
|
|
516
|
+
// `@text` is an Android attribute. An XCUIElement has name, label and
|
|
517
|
+
// value and no text at all, so every iOS suggestion in this shape
|
|
518
|
+
// resolved to nothing: measured on a real iPhone,
|
|
519
|
+
// `//XCUIElementTypePageIndicator[@text="Page control"]` found 0 and the
|
|
520
|
+
// same path with `@label` found 1.
|
|
521
|
+
const textAttr = platform === 'ios' ? iosTextAttr : 'text';
|
|
498
522
|
suggestions.push({
|
|
499
523
|
strategy: 'xpath',
|
|
500
|
-
value: `//${tagName}[
|
|
524
|
+
value: `//${tagName}[@${textAttr}="${node.text}"]`,
|
|
501
525
|
unique: this.isUnique(uniqueness, 'text', node.text),
|
|
502
526
|
score: 60,
|
|
503
527
|
});
|
|
@@ -197,6 +197,61 @@ describe('InspectorService hierarchy parsing', () => {
|
|
|
197
197
|
(0, chai_1.expect)(root.name).to.equal('1');
|
|
198
198
|
});
|
|
199
199
|
});
|
|
200
|
+
describe('iOS locator syntax', () => {
|
|
201
|
+
// Two StaticTexts share the label "Done" and neither has a name, so both a
|
|
202
|
+
// predicate and a class chain built from that label are genuinely
|
|
203
|
+
// ambiguous. The button carries a name and is genuinely unique. The text
|
|
204
|
+
// field has a value and no label.
|
|
205
|
+
const XML = `<AppiumAUT>
|
|
206
|
+
<XCUIElementTypeApplication type="XCUIElementTypeApplication" name="MyApp" label="MyApp" x="0" y="0" width="390" height="844">
|
|
207
|
+
<XCUIElementTypeButton type="XCUIElementTypeButton" name="done-btn" label="Save" x="0" y="0" width="10" height="10" />
|
|
208
|
+
<XCUIElementTypeStaticText type="XCUIElementTypeStaticText" label="Done" x="0" y="20" width="10" height="10" />
|
|
209
|
+
<XCUIElementTypeStaticText type="XCUIElementTypeStaticText" label="Done" x="0" y="30" width="10" height="10" />
|
|
210
|
+
<XCUIElementTypeTextField type="XCUIElementTypeTextField" value="typed text" x="0" y="40" width="10" height="10" />
|
|
211
|
+
</XCUIElementTypeApplication>
|
|
212
|
+
</AppiumAUT>`;
|
|
213
|
+
const root = () => parse(XML, 'ios');
|
|
214
|
+
const byType = (t) => find(root(), (n) => n.type === t)[0];
|
|
215
|
+
it('wraps the class chain predicate in backticks', () => {
|
|
216
|
+
// Measured on a real iPhone: without backticks Appium resolves 0
|
|
217
|
+
// elements, with them it resolves 1. Every chain this produced was
|
|
218
|
+
// unusable — 280 of them in one home-screen snapshot.
|
|
219
|
+
(0, chai_1.expect)(locator(byType('XCUIElementTypeButton'), '-ios class chain').value).to.equal('**/XCUIElementTypeButton[`name == "done-btn"`]');
|
|
220
|
+
});
|
|
221
|
+
it('selects on label in the class chain when there is no name', () => {
|
|
222
|
+
(0, chai_1.expect)(locator(byType('XCUIElementTypeStaticText'), '-ios class chain').value).to.equal('**/XCUIElementTypeStaticText[`label == "Done"`]');
|
|
223
|
+
});
|
|
224
|
+
it('uses an attribute an XCUIElement actually has in xpath', () => {
|
|
225
|
+
// `@text` is Android's. iOS has name, label and value — and `@text`
|
|
226
|
+
// resolved to nothing on a real device.
|
|
227
|
+
const xpath = locator(byType('XCUIElementTypeStaticText'), 'xpath').value;
|
|
228
|
+
(0, chai_1.expect)(xpath).to.equal('//XCUIElementTypeStaticText[@label="Done"]');
|
|
229
|
+
(0, chai_1.expect)(xpath).to.not.contain('@text');
|
|
230
|
+
});
|
|
231
|
+
it('names value rather than label when value is what supplied the text', () => {
|
|
232
|
+
(0, chai_1.expect)(locator(byType('XCUIElementTypeTextField'), 'xpath').value).to.equal('//XCUIElementTypeTextField[@value="typed text"]');
|
|
233
|
+
});
|
|
234
|
+
it('names the same attribute in the predicate as in the xpath', () => {
|
|
235
|
+
// A page indicator carries its text in `value` and has no label at all.
|
|
236
|
+
// The predicate hardcoded `label ==`, so it matched nothing — measured
|
|
237
|
+
// against a real iPhone as the last surviving miss after the other
|
|
238
|
+
// fixes landed.
|
|
239
|
+
const field = byType('XCUIElementTypeTextField');
|
|
240
|
+
(0, chai_1.expect)(locator(field, '-ios predicate string').value).to.equal('type == "XCUIElementTypeTextField" AND value == "typed text"');
|
|
241
|
+
(0, chai_1.expect)(locator(byType('XCUIElementTypeStaticText'), '-ios predicate string').value).to.equal('type == "XCUIElementTypeStaticText" AND label == "Done"');
|
|
242
|
+
});
|
|
243
|
+
it('stops claiming every predicate and class chain is unique', () => {
|
|
244
|
+
// Both were hardcoded true. On a real device a predicate badged unique
|
|
245
|
+
// matched two elements.
|
|
246
|
+
const shared = byType('XCUIElementTypeStaticText'); // label "Done", shared
|
|
247
|
+
(0, chai_1.expect)(locator(shared, '-ios predicate string').unique).to.equal(false);
|
|
248
|
+
(0, chai_1.expect)(locator(shared, '-ios class chain').unique).to.equal(false);
|
|
249
|
+
});
|
|
250
|
+
it('still reports a genuinely unique one as unique', () => {
|
|
251
|
+
const named = byType('XCUIElementTypeButton'); // name "done-btn", unique
|
|
252
|
+
(0, chai_1.expect)(locator(named, '-ios class chain').unique).to.equal(true);
|
|
253
|
+
});
|
|
254
|
+
});
|
|
200
255
|
describe('iOS', () => {
|
|
201
256
|
it('parses the XCUIElementType tree unchanged', () => {
|
|
202
257
|
const root = parse(IOS_XML, 'ios');
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const chai_1 = require("chai");
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const os_1 = __importDefault(require("os"));
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
11
|
+
const { syncDirectory, verifyGeneratedClient } = require('../../scripts/lib/sync-dir');
|
|
12
|
+
/**
|
|
13
|
+
* `postinstall` regenerates the Prisma client inside the installed package and
|
|
14
|
+
* copies it over the one the tarball shipped. The two differ in size — the
|
|
15
|
+
* embedded engine paths differ between a repo checkout and a package under
|
|
16
|
+
* node_modules — so this copy always writes a different-length file over an
|
|
17
|
+
* existing one, and anything it does not overwrite survives.
|
|
18
|
+
*
|
|
19
|
+
* An installed client was found holding a fragment of its own previous
|
|
20
|
+
* version: `path.join(…)` on one line continued by a bare `.join(…)` on the
|
|
21
|
+
* next. That is valid JavaScript, so nothing caught it until require() failed
|
|
22
|
+
* with "path.join(...).join is not a function" and the plugin silently did not
|
|
23
|
+
* load.
|
|
24
|
+
*/
|
|
25
|
+
describe('generated client sync', () => {
|
|
26
|
+
let root;
|
|
27
|
+
let src;
|
|
28
|
+
let dest;
|
|
29
|
+
beforeEach(() => {
|
|
30
|
+
root = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), 'xenon-sync-'));
|
|
31
|
+
src = path_1.default.join(root, 'src');
|
|
32
|
+
dest = path_1.default.join(root, 'dest');
|
|
33
|
+
fs_1.default.mkdirSync(src, { recursive: true });
|
|
34
|
+
fs_1.default.mkdirSync(dest, { recursive: true });
|
|
35
|
+
});
|
|
36
|
+
afterEach(() => fs_1.default.rmSync(root, { recursive: true, force: true }));
|
|
37
|
+
it('leaves the destination holding exactly the source', () => {
|
|
38
|
+
fs_1.default.writeFileSync(path_1.default.join(src, 'index.js'), 'new');
|
|
39
|
+
fs_1.default.mkdirSync(path_1.default.join(src, 'runtime'));
|
|
40
|
+
fs_1.default.writeFileSync(path_1.default.join(src, 'runtime', 'library.js'), 'lib');
|
|
41
|
+
syncDirectory(src, dest);
|
|
42
|
+
(0, chai_1.expect)(fs_1.default.readFileSync(path_1.default.join(dest, 'index.js'), 'utf8')).to.equal('new');
|
|
43
|
+
(0, chai_1.expect)(fs_1.default.readFileSync(path_1.default.join(dest, 'runtime', 'library.js'), 'utf8')).to.equal('lib');
|
|
44
|
+
});
|
|
45
|
+
it('removes a file the new generation no longer emits', () => {
|
|
46
|
+
fs_1.default.writeFileSync(path_1.default.join(src, 'index.js'), 'new');
|
|
47
|
+
fs_1.default.writeFileSync(path_1.default.join(dest, 'index.js'), 'old');
|
|
48
|
+
fs_1.default.writeFileSync(path_1.default.join(dest, 'libquery_engine-old-target.node'), 'stale engine');
|
|
49
|
+
syncDirectory(src, dest);
|
|
50
|
+
(0, chai_1.expect)(fs_1.default.existsSync(path_1.default.join(dest, 'libquery_engine-old-target.node'))).to.equal(false);
|
|
51
|
+
});
|
|
52
|
+
it('cannot leave a longer previous version behind a shorter new one', () => {
|
|
53
|
+
// The shape of the real corruption: the destination was longer than its
|
|
54
|
+
// replacement, and what survived was the tail.
|
|
55
|
+
fs_1.default.writeFileSync(path_1.default.join(src, 'index.js'), 'path.join(a)\n');
|
|
56
|
+
fs_1.default.writeFileSync(path_1.default.join(dest, 'index.js'), 'path.join(a)\n.join(b) // leftover tail\n');
|
|
57
|
+
syncDirectory(src, dest);
|
|
58
|
+
const after = fs_1.default.readFileSync(path_1.default.join(dest, 'index.js'), 'utf8');
|
|
59
|
+
(0, chai_1.expect)(after).to.equal('path.join(a)\n');
|
|
60
|
+
(0, chai_1.expect)(after).to.not.contain('leftover tail');
|
|
61
|
+
});
|
|
62
|
+
it('copies into a destination that does not exist yet', () => {
|
|
63
|
+
fs_1.default.writeFileSync(path_1.default.join(src, 'index.js'), 'new');
|
|
64
|
+
const fresh = path_1.default.join(root, 'fresh');
|
|
65
|
+
(0, chai_1.expect)(syncDirectory(src, fresh)).to.equal(1);
|
|
66
|
+
(0, chai_1.expect)(fs_1.default.readFileSync(path_1.default.join(fresh, 'index.js'), 'utf8')).to.equal('new');
|
|
67
|
+
});
|
|
68
|
+
it('does nothing when there is no source to sync', () => {
|
|
69
|
+
(0, chai_1.expect)(syncDirectory(path_1.default.join(root, 'missing'), dest)).to.equal(0);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
describe('generated client verification', () => {
|
|
73
|
+
let dir;
|
|
74
|
+
beforeEach(() => {
|
|
75
|
+
dir = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), 'xenon-verify-'));
|
|
76
|
+
});
|
|
77
|
+
afterEach(() => fs_1.default.rmSync(dir, { recursive: true, force: true }));
|
|
78
|
+
it('accepts a client that loads', () => {
|
|
79
|
+
fs_1.default.writeFileSync(path_1.default.join(dir, 'index.js'), 'module.exports = { PrismaClient: class {} };');
|
|
80
|
+
(0, chai_1.expect)(verifyGeneratedClient(dir)).to.deep.equal({ ok: true });
|
|
81
|
+
});
|
|
82
|
+
it('rejects the corruption that actually shipped', () => {
|
|
83
|
+
// Syntactically valid — which is exactly why nothing caught it — and a
|
|
84
|
+
// TypeError the moment it is required.
|
|
85
|
+
fs_1.default.writeFileSync(path_1.default.join(dir, 'index.js'), 'const path = require("path");\npath.join("a", "b")\n.join("c", "d")\n');
|
|
86
|
+
const verdict = verifyGeneratedClient(dir);
|
|
87
|
+
(0, chai_1.expect)(verdict.ok).to.equal(false);
|
|
88
|
+
(0, chai_1.expect)(verdict.error).to.contain('join is not a function');
|
|
89
|
+
});
|
|
90
|
+
it('rejects a client that is not there at all', () => {
|
|
91
|
+
const verdict = verifyGeneratedClient(dir);
|
|
92
|
+
(0, chai_1.expect)(verdict.ok).to.equal(false);
|
|
93
|
+
(0, chai_1.expect)(verdict.error).to.contain('does not exist');
|
|
94
|
+
});
|
|
95
|
+
it('judges a relative path by the client, not by module resolution', () => {
|
|
96
|
+
// `require` reads a relative path as relative to sync-dir.js while
|
|
97
|
+
// `existsSync` reads it as relative to cwd. Unresolved, a relative caller
|
|
98
|
+
// gets "Cannot find module" for a file that is plainly there — a verdict
|
|
99
|
+
// that says nothing about the client.
|
|
100
|
+
const rel = path_1.default.relative(process.cwd(), dir);
|
|
101
|
+
fs_1.default.writeFileSync(path_1.default.join(dir, 'index.js'), 'module.exports = { PrismaClient: class {} };');
|
|
102
|
+
(0, chai_1.expect)(verifyGeneratedClient(rel)).to.deep.equal({ ok: true });
|
|
103
|
+
});
|
|
104
|
+
});
|
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/streamStartConflict.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/app/ws/logcatWs.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/LogcatMultiplexer.ts","../src/device-managers/android/LogcatStreamService.ts","../src/device-managers/android/ScrcpyServerSession.ts","../src/device-managers/android/androidStreamReuse.ts","../src/device-managers/android/displayState.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/deviceAccessGuard.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/DisplayStateService.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/device-access/SessionOwnerResolver.ts","../src/services/device-access/actor.ts","../src/services/device-access/deviceAccessPolicy.ts","../src/services/device-access/ticketActorAccess.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/inspector/verifyLocator.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/logcat/PackageResolver.ts","../src/services/logcat/logcatParse.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/probeDuration.ts","../src/services/recording/proof-bundle.ts","../src/services/recording/recording-store.ts","../src/services/recording/recordingCleanup.ts","../src/services/session/sessionIdentity.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/android-stream-stall-eof.spec.ts","../test/unit/annotation-render.spec.ts","../test/unit/auth-disabled-resolution.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-access-guard.spec.ts","../test/unit/device-access-policy.spec.ts","../test/unit/device-service.spec.ts","../test/unit/device-utils.spec.ts","../test/unit/display-state.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/inspector-hierarchy.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/logcat-multiplexer.spec.ts","../test/unit/logcat-parse.spec.ts","../test/unit/logcat-stream-service.spec.ts","../test/unit/logcat-ws.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/package-resolver.spec.ts","../test/unit/plugin.spec.ts","../test/unit/port-exhaustion.spec.ts","../test/unit/prisma.spec.ts","../test/unit/probe-duration.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-cleanup.spec.ts","../test/unit/recording-instrumentation.spec.ts","../test/unit/recording-orchestrator.spec.ts","../test/unit/recording-source-ended.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/schema-required-args.spec.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/session-attribution-wiring.spec.ts","../test/unit/session-identity.spec.ts","../test/unit/session-owner-resolver.spec.ts","../test/unit/shutdown-sync-nets.spec.ts","../test/unit/single-flight.spec.ts","../test/unit/socketServer.bearer.spec.ts","../test/unit/stream-start-conflict.spec.ts","../test/unit/stream-status-type.spec.ts","../test/unit/stream-stop-ownership.spec.ts","../test/unit/stream-ticket-identity.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/verify-locator.spec.ts","../test/unit/video-pipeline-args.spec.ts","../test/unit/video-pipeline-exit.spec.ts","../test/unit/video-pipeline-outputpath.spec.ts","../test/unit/wda-cap-injection.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/streamStartConflict.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/app/ws/logcatWs.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/LogcatMultiplexer.ts","../src/device-managers/android/LogcatStreamService.ts","../src/device-managers/android/ScrcpyServerSession.ts","../src/device-managers/android/androidStreamReuse.ts","../src/device-managers/android/displayState.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/deviceAccessGuard.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/DisplayStateService.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/device-access/SessionOwnerResolver.ts","../src/services/device-access/actor.ts","../src/services/device-access/deviceAccessPolicy.ts","../src/services/device-access/ticketActorAccess.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/inspector/verifyLocator.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/logcat/PackageResolver.ts","../src/services/logcat/logcatParse.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/probeDuration.ts","../src/services/recording/proof-bundle.ts","../src/services/recording/recording-store.ts","../src/services/recording/recordingCleanup.ts","../src/services/session/sessionIdentity.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/android-stream-stall-eof.spec.ts","../test/unit/annotation-render.spec.ts","../test/unit/auth-disabled-resolution.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-access-guard.spec.ts","../test/unit/device-access-policy.spec.ts","../test/unit/device-service.spec.ts","../test/unit/device-utils.spec.ts","../test/unit/display-state.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/inspector-hierarchy.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/logcat-multiplexer.spec.ts","../test/unit/logcat-parse.spec.ts","../test/unit/logcat-stream-service.spec.ts","../test/unit/logcat-ws.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/package-resolver.spec.ts","../test/unit/plugin.spec.ts","../test/unit/port-exhaustion.spec.ts","../test/unit/prisma.spec.ts","../test/unit/probe-duration.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-cleanup.spec.ts","../test/unit/recording-instrumentation.spec.ts","../test/unit/recording-orchestrator.spec.ts","../test/unit/recording-source-ended.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/schema-required-args.spec.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/session-attribution-wiring.spec.ts","../test/unit/session-identity.spec.ts","../test/unit/session-owner-resolver.spec.ts","../test/unit/shutdown-sync-nets.spec.ts","../test/unit/single-flight.spec.ts","../test/unit/socketServer.bearer.spec.ts","../test/unit/stream-start-conflict.spec.ts","../test/unit/stream-status-type.spec.ts","../test/unit/stream-stop-ownership.spec.ts","../test/unit/stream-ticket-identity.spec.ts","../test/unit/sync-dir.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/verify-locator.spec.ts","../test/unit/video-pipeline-args.spec.ts","../test/unit/video-pipeline-exit.spec.ts","../test/unit/video-pipeline-outputpath.spec.ts","../test/unit/wda-cap-injection.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
|
@@ -2,6 +2,7 @@ const { execSync } = require('child_process');
|
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const { normalizeDirToLf } = require('./lib/normalize-eol');
|
|
5
|
+
const { syncDirectory, verifyGeneratedClient } = require('./lib/sync-dir');
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Robust Prisma Client Generator (v1.1.9)
|
|
@@ -61,11 +62,36 @@ function generate() {
|
|
|
61
62
|
fs.mkdirSync(path.dirname(libOutputDir), { recursive: true });
|
|
62
63
|
}
|
|
63
64
|
|
|
64
|
-
//
|
|
65
|
-
|
|
65
|
+
// Replaces the destination rather than overwriting file by file.
|
|
66
|
+
// The regenerated client is a different size from the one the
|
|
67
|
+
// tarball shipped, so a per-file copy can leave remnants of the
|
|
68
|
+
// version it replaced — see scripts/lib/sync-dir.js.
|
|
69
|
+
syncDirectory(srcOutputDir, libOutputDir);
|
|
66
70
|
console.log('✅ [Xenon] Prisma client synced to lib/src/generated/client.');
|
|
67
71
|
}
|
|
68
72
|
|
|
73
|
+
// The plugin cannot start without this, and a damaged client is valid
|
|
74
|
+
// JavaScript that only fails when required — so it is loaded here,
|
|
75
|
+
// while the install is still on screen, rather than discovered later
|
|
76
|
+
// as "Could not load plugin 'xenon'" with an unrelated-looking
|
|
77
|
+
// TypeError.
|
|
78
|
+
const verifyTarget = fs.existsSync(path.resolve(rootDir, 'lib'))
|
|
79
|
+
? libOutputDir
|
|
80
|
+
: srcOutputDir;
|
|
81
|
+
const verdict = verifyGeneratedClient(verifyTarget);
|
|
82
|
+
if (!verdict.ok) {
|
|
83
|
+
console.error('');
|
|
84
|
+
console.error('❌ [Xenon] The generated Prisma client is present but cannot be loaded.');
|
|
85
|
+
console.error(`❌ [Xenon] ${verifyTarget}`);
|
|
86
|
+
console.error(`❌ [Xenon] ${verdict.error}`);
|
|
87
|
+
console.error('❌ [Xenon] Xenon will fail to start. Reinstall the plugin into a clean');
|
|
88
|
+
console.error('❌ [Xenon] directory to rebuild it:');
|
|
89
|
+
console.error('❌ [Xenon] appium plugin uninstall xenon');
|
|
90
|
+
console.error('❌ [Xenon] rm -rf "$APPIUM_HOME/node_modules/@xenon-device-management"');
|
|
91
|
+
console.error('❌ [Xenon] appium plugin install --source=npm @xenon-device-management/xenon');
|
|
92
|
+
console.error('');
|
|
93
|
+
}
|
|
94
|
+
|
|
69
95
|
} catch (error) {
|
|
70
96
|
console.error('⚠️ [Xenon] Prisma generation encountered an issue.');
|
|
71
97
|
console.error('⚠️ [Xenon] This is expected in some restricted environments.');
|
|
@@ -76,20 +102,4 @@ function generate() {
|
|
|
76
102
|
}
|
|
77
103
|
}
|
|
78
104
|
|
|
79
|
-
function copyRecursiveSync(src, dest) {
|
|
80
|
-
const exists = fs.existsSync(src);
|
|
81
|
-
const stats = exists && fs.statSync(src);
|
|
82
|
-
const isDirectory = exists && stats.isDirectory();
|
|
83
|
-
if (isDirectory) {
|
|
84
|
-
if (!fs.existsSync(dest)) {
|
|
85
|
-
fs.mkdirSync(dest, { recursive: true });
|
|
86
|
-
}
|
|
87
|
-
fs.readdirSync(src).forEach((childItemName) => {
|
|
88
|
-
copyRecursiveSync(path.join(src, childItemName), path.join(dest, childItemName));
|
|
89
|
-
});
|
|
90
|
-
} else {
|
|
91
|
-
fs.copyFileSync(src, dest);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
105
|
generate();
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Authoritative directory sync for the generated Prisma client.
|
|
5
|
+
*
|
|
6
|
+
* `postinstall` regenerates the client inside the installed package and copies
|
|
7
|
+
* it over the one the tarball shipped. The two are not the same size — the
|
|
8
|
+
* embedded engine paths differ between a repo checkout and a package under
|
|
9
|
+
* node_modules — so the copy always writes a different-length file over an
|
|
10
|
+
* existing one.
|
|
11
|
+
*
|
|
12
|
+
* A plain per-file copy leaves whatever the new generation did not overwrite:
|
|
13
|
+
* files the previous generation emitted and this one does not, and, if a write
|
|
14
|
+
* is ever cut short, the tail of the longer file it replaced. That second case
|
|
15
|
+
* is how an installed client came to hold a fragment of its own previous
|
|
16
|
+
* version — `path.join(…)` on one line continued by a bare `.join(…)` on the
|
|
17
|
+
* next, which is valid JavaScript, so it survived to fail at require() time
|
|
18
|
+
* with "path.join(...).join is not a function" and the plugin simply did not
|
|
19
|
+
* load.
|
|
20
|
+
*
|
|
21
|
+
* Replacing the destination outright removes the whole class: after a sync the
|
|
22
|
+
* destination is exactly the source, with nothing inherited.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
const path = require('path');
|
|
26
|
+
const fs = require('fs');
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Copy `src` to `dest` so that `dest` afterwards contains exactly `src`.
|
|
30
|
+
*
|
|
31
|
+
* @param {string} src
|
|
32
|
+
* @param {string} dest
|
|
33
|
+
* @returns {number} count of files written
|
|
34
|
+
*/
|
|
35
|
+
function syncDirectory(src, dest) {
|
|
36
|
+
if (!fs.existsSync(src)) return 0;
|
|
37
|
+
|
|
38
|
+
// Remove first: `fs.cp`/`copyFile` overwrite per file and would leave
|
|
39
|
+
// anything the new generation no longer emits.
|
|
40
|
+
if (fs.existsSync(dest)) {
|
|
41
|
+
fs.rmSync(dest, { recursive: true, force: true });
|
|
42
|
+
}
|
|
43
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
44
|
+
|
|
45
|
+
return copyInto(src, dest);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function copyInto(src, dest) {
|
|
49
|
+
let written = 0;
|
|
50
|
+
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
51
|
+
const from = path.join(src, entry.name);
|
|
52
|
+
const to = path.join(dest, entry.name);
|
|
53
|
+
if (entry.isDirectory()) {
|
|
54
|
+
fs.mkdirSync(to, { recursive: true });
|
|
55
|
+
written += copyInto(from, to);
|
|
56
|
+
} else {
|
|
57
|
+
fs.copyFileSync(from, to);
|
|
58
|
+
written += 1;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return written;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Confirm the generated client can actually be loaded.
|
|
66
|
+
*
|
|
67
|
+
* A corrupted client is syntactically valid JavaScript — the failure is a
|
|
68
|
+
* TypeError at require() time — so parsing it proves nothing. The only honest
|
|
69
|
+
* check is to load it, which is what the plugin does on startup anyway.
|
|
70
|
+
*
|
|
71
|
+
* @param {string} clientDir
|
|
72
|
+
* @returns {{ ok: true } | { ok: false, error: string }}
|
|
73
|
+
*/
|
|
74
|
+
function verifyGeneratedClient(clientDir) {
|
|
75
|
+
// Resolved, because `require` takes a relative path as relative to THIS
|
|
76
|
+
// module while `fs.existsSync` takes it as relative to cwd. Left unresolved,
|
|
77
|
+
// a relative caller gets "Cannot find module" for a file that is plainly
|
|
78
|
+
// there, and the verdict says nothing about whether the client is sound.
|
|
79
|
+
const entry = path.resolve(clientDir, 'index.js');
|
|
80
|
+
if (!fs.existsSync(entry)) {
|
|
81
|
+
return { ok: false, error: `${entry} does not exist` };
|
|
82
|
+
}
|
|
83
|
+
try {
|
|
84
|
+
delete require.cache[require.resolve(entry)];
|
|
85
|
+
require(entry);
|
|
86
|
+
return { ok: true };
|
|
87
|
+
} catch (err) {
|
|
88
|
+
return { ok: false, error: err && err.message ? err.message : String(err) };
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
module.exports = { syncDirectory, verifyGeneratedClient };
|