obsidian-integration-testing 9.1.1 → 9.2.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/README.md +223 -18
- package/dist/lib/cjs/connect-to-cdp.cjs +23 -2
- package/dist/lib/cjs/eval-in-obsidian.cjs +1 -1
- package/dist/lib/cjs/eval-in-obsidian.d.cts +44 -1
- package/dist/lib/cjs/global-setup-core.cjs +28 -1
- package/dist/lib/cjs/index.cjs +12 -1
- package/dist/lib/cjs/index.d.cts +5 -0
- package/dist/lib/cjs/leftover-cleanup.cjs +134 -0
- package/dist/lib/cjs/leftover-cleanup.d.cts +216 -0
- package/dist/lib/cjs/library.cjs +1 -1
- package/dist/lib/cjs/namespace-bootstrap.cjs +20 -2
- package/dist/lib/cjs/obsidian-metadata.cjs +18 -1
- package/dist/lib/cjs/run-version-matrix.cjs +64 -0
- package/dist/lib/cjs/run-version-matrix.d.cts +49 -0
- package/dist/lib/cjs/setup-lock.cjs +145 -32
- package/dist/lib/cjs/setup-lock.d.cts +9 -3
- package/dist/lib/cjs/temp-vault.cjs +3 -2
- package/dist/lib/cjs/transport-appium.cjs +102 -30
- package/dist/lib/cjs/transport-appium.d.cts +50 -3
- package/dist/lib/cjs/transport-factory.cjs +66 -4
- package/dist/lib/cjs/transport-options.cjs +1 -1
- package/dist/lib/cjs/transport-options.d.cts +57 -0
- package/dist/lib/cjs/version-matrix.cjs +175 -0
- package/dist/lib/cjs/version-matrix.d.cts +224 -0
- package/dist/lib/esm/connect-to-cdp.mjs +27 -2
- package/dist/lib/esm/eval-in-obsidian.d.mts +44 -1
- package/dist/lib/esm/eval-in-obsidian.mjs +1 -1
- package/dist/lib/esm/global-setup-core.mjs +36 -2
- package/dist/lib/esm/index.d.mts +5 -0
- package/dist/lib/esm/index.mjs +11 -1
- package/dist/lib/esm/leftover-cleanup.d.mts +216 -0
- package/dist/lib/esm/leftover-cleanup.mjs +105 -0
- package/dist/lib/esm/library.mjs +1 -1
- package/dist/lib/esm/namespace-bootstrap.mjs +20 -2
- package/dist/lib/esm/obsidian-metadata.mjs +18 -1
- package/dist/lib/esm/run-version-matrix.d.mts +49 -0
- package/dist/lib/esm/run-version-matrix.mjs +48 -0
- package/dist/lib/esm/setup-lock.d.mts +9 -3
- package/dist/lib/esm/setup-lock.mjs +145 -32
- package/dist/lib/esm/temp-vault.mjs +3 -2
- package/dist/lib/esm/transport-appium.d.mts +50 -3
- package/dist/lib/esm/transport-appium.mjs +100 -29
- package/dist/lib/esm/transport-factory.mjs +75 -5
- package/dist/lib/esm/transport-options.d.mts +57 -0
- package/dist/lib/esm/version-matrix.d.mts +224 -0
- package/dist/lib/esm/version-matrix.mjs +147 -0
- package/dist/obsidian-integration-testing-9.2.1.tgz +0 -0
- package/package.json +18 -25
- package/dist/obsidian-integration-testing-9.1.1.tgz +0 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var leftover_cleanup_exports = {};
|
|
20
|
+
__export(leftover_cleanup_exports, {
|
|
21
|
+
DEFAULT_LEFTOVER_MAX_AGE_IN_MILLISECONDS: () => DEFAULT_LEFTOVER_MAX_AGE_IN_MILLISECONDS,
|
|
22
|
+
HARNESS_TEMP_DIR_NAME: () => HARNESS_TEMP_DIR_NAME,
|
|
23
|
+
OWNED_USER_DATA_DIR_PREFIX: () => OWNED_USER_DATA_DIR_PREFIX,
|
|
24
|
+
TEMP_VAULT_DIR_PREFIX: () => TEMP_VAULT_DIR_PREFIX,
|
|
25
|
+
checkIsLeftoverStale: () => checkIsLeftoverStale,
|
|
26
|
+
filterLeftoverNames: () => filterLeftoverNames,
|
|
27
|
+
resolveLeftoverMaxAgeInMilliseconds: () => resolveLeftoverMaxAgeInMilliseconds,
|
|
28
|
+
resolveShouldSweepLeftovers: () => resolveShouldSweepLeftovers,
|
|
29
|
+
sweepDeviceLeftovers: () => sweepDeviceLeftovers,
|
|
30
|
+
sweepHostLeftovers: () => sweepHostLeftovers
|
|
31
|
+
});
|
|
32
|
+
module.exports = __toCommonJS(leftover_cleanup_exports);
|
|
33
|
+
var import_promises = require("node:fs/promises");
|
|
34
|
+
var import_node_os = require("node:os");
|
|
35
|
+
var import_node_path = require("node:path");
|
|
36
|
+
const DEFAULT_LEFTOVER_MAX_AGE_IN_MILLISECONDS = 72e5;
|
|
37
|
+
const HARNESS_TEMP_DIR_NAME = "obsidian-integration-testing";
|
|
38
|
+
const OWNED_USER_DATA_DIR_PREFIX = "userdata-";
|
|
39
|
+
const TEMP_VAULT_DIR_PREFIX = "temp-vault-";
|
|
40
|
+
function checkIsLeftoverStale(params) {
|
|
41
|
+
if (params.maxAgeInMilliseconds === 0) {
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
return params.nowInMilliseconds - params.modifiedAtInMilliseconds >= params.maxAgeInMilliseconds;
|
|
45
|
+
}
|
|
46
|
+
function filterLeftoverNames(params) {
|
|
47
|
+
const excludedNames = params.excludedNames ?? [];
|
|
48
|
+
return params.names.map((name) => name.trim()).filter((name) => params.prefixes.some((prefix) => name.startsWith(prefix))).filter((name) => !excludedNames.includes(name));
|
|
49
|
+
}
|
|
50
|
+
function resolveLeftoverMaxAgeInMilliseconds(options) {
|
|
51
|
+
return options?.leftoverMaxAgeInMilliseconds ?? DEFAULT_LEFTOVER_MAX_AGE_IN_MILLISECONDS;
|
|
52
|
+
}
|
|
53
|
+
function resolveShouldSweepLeftovers(options) {
|
|
54
|
+
return options?.shouldSweepLeftovers ?? true;
|
|
55
|
+
}
|
|
56
|
+
async function sweepDeviceLeftovers(params) {
|
|
57
|
+
const { listNames, removeDir, vaultBasePath } = params;
|
|
58
|
+
const names = filterLeftoverNames({ names: await listNames(), prefixes: [TEMP_VAULT_DIR_PREFIX] });
|
|
59
|
+
if (names.length === 0) {
|
|
60
|
+
return { failedNames: [], removedCount: 0 };
|
|
61
|
+
}
|
|
62
|
+
for (const name of names) {
|
|
63
|
+
try {
|
|
64
|
+
await removeDir(`${vaultBasePath}${name}`);
|
|
65
|
+
} catch {
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
const survivingNames = filterLeftoverNames({ names: await listNames(), prefixes: [TEMP_VAULT_DIR_PREFIX] });
|
|
69
|
+
const failedNames = names.filter((name) => survivingNames.includes(name));
|
|
70
|
+
return { failedNames, removedCount: names.length - failedNames.length };
|
|
71
|
+
}
|
|
72
|
+
async function sweepHostLeftovers(options) {
|
|
73
|
+
const maxAgeInMilliseconds = options?.maxAgeInMilliseconds ?? DEFAULT_LEFTOVER_MAX_AGE_IN_MILLISECONDS;
|
|
74
|
+
const nowInMilliseconds = Date.now();
|
|
75
|
+
const roots = options?.roots ?? getDefaultLeftoverRoots();
|
|
76
|
+
let failedCount = 0;
|
|
77
|
+
let removedCount = 0;
|
|
78
|
+
for (const root of roots) {
|
|
79
|
+
const names = filterLeftoverNames({
|
|
80
|
+
excludedNames: options?.excludedNames,
|
|
81
|
+
names: await readDirNames(root.path),
|
|
82
|
+
prefixes: root.prefixes
|
|
83
|
+
});
|
|
84
|
+
for (const name of names) {
|
|
85
|
+
const path = (0, import_node_path.join)(root.path, name);
|
|
86
|
+
if (!await checkIsRemovableDir({ maxAgeInMilliseconds, nowInMilliseconds, path })) {
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
try {
|
|
90
|
+
await (0, import_promises.rm)(path, { force: true, recursive: true });
|
|
91
|
+
removedCount++;
|
|
92
|
+
} catch {
|
|
93
|
+
failedCount++;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return { failedCount, removedCount };
|
|
98
|
+
}
|
|
99
|
+
async function checkIsRemovableDir(params) {
|
|
100
|
+
const { maxAgeInMilliseconds, nowInMilliseconds } = params;
|
|
101
|
+
try {
|
|
102
|
+
const stats = await (0, import_promises.stat)(params.path);
|
|
103
|
+
return stats.isDirectory() && checkIsLeftoverStale({ maxAgeInMilliseconds, modifiedAtInMilliseconds: stats.mtimeMs, nowInMilliseconds });
|
|
104
|
+
} catch {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
function getDefaultLeftoverRoots() {
|
|
109
|
+
return [
|
|
110
|
+
{ path: (0, import_node_os.tmpdir)(), prefixes: [TEMP_VAULT_DIR_PREFIX] },
|
|
111
|
+
{ path: (0, import_node_path.join)((0, import_node_os.tmpdir)(), HARNESS_TEMP_DIR_NAME), prefixes: [OWNED_USER_DATA_DIR_PREFIX] }
|
|
112
|
+
];
|
|
113
|
+
}
|
|
114
|
+
async function readDirNames(path) {
|
|
115
|
+
try {
|
|
116
|
+
return await (0, import_promises.readdir)(path);
|
|
117
|
+
} catch {
|
|
118
|
+
return [];
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
122
|
+
0 && (module.exports = {
|
|
123
|
+
DEFAULT_LEFTOVER_MAX_AGE_IN_MILLISECONDS,
|
|
124
|
+
HARNESS_TEMP_DIR_NAME,
|
|
125
|
+
OWNED_USER_DATA_DIR_PREFIX,
|
|
126
|
+
TEMP_VAULT_DIR_PREFIX,
|
|
127
|
+
checkIsLeftoverStale,
|
|
128
|
+
filterLeftoverNames,
|
|
129
|
+
resolveLeftoverMaxAgeInMilliseconds,
|
|
130
|
+
resolveShouldSweepLeftovers,
|
|
131
|
+
sweepDeviceLeftovers,
|
|
132
|
+
sweepHostLeftovers
|
|
133
|
+
});
|
|
134
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL2xlZnRvdmVyLWNsZWFudXAudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi8qKlxuICogQGZpbGVcbiAqXG4gKiBTd2VlcHMgdGhlIHRlbXBvcmFyeSBkaXJlY3RvcmllcyBhIHByZXZpb3VzIGludGVncmF0aW9uIHJ1biBsZWFrZWQgXHUyMDE0IHRoZVxuICogYHRlbXAtdmF1bHQtKmAgc3RhZ2luZy92YXVsdCBkaXJlY3RvcmllcyBhbmQgdGhlIG93bmVkIGluc3RhbmNlJ3NcbiAqIGB1c2VyZGF0YS0qYCBDaHJvbWl1bSBwcm9maWxlcy5cbiAqXG4gKiBBIHJ1biB0aGF0IGRpZXMgbWlkLWZsaWdodCBjYW5ub3QgY2xlYW4gdXAgYWZ0ZXIgaXRzZWxmOiBvbiBBbmRyb2lkIHRoZVxuICogdGVhcmRvd24gdGFsa3MgdG8gdGhlIFdlYlZpZXcsIGFuZCBhIGRlYWQgV2ViVmlldyBpcyBleGFjdGx5IHdoYXQgbW9zdFxuICogZmFpbHVyZXMgYXJlIChgVmF1bHQgY2xlYW51cCBlcnJvciAobm9uLWZhdGFsKTogbm8gc3VjaCB3aW5kb3dgKS4gRXZlcnlcbiAqIGZhaWx1cmUgdGhlcmVmb3JlIGxlYWtzIGEgdmF1bHQsIGV2ZXJ5IGxlYWtlZCB2YXVsdCBzdGF5cyByZWdpc3RlcmVkIGZvclxuICogT2JzaWRpYW4gdG8gZW51bWVyYXRlIGF0IHN0YXJ0dXAsIGFuZCB0aGF0IGVudW1lcmF0aW9uIGhhcyB0byBmaW5pc2ggaW5zaWRlXG4gKiB0aGUgV2ViVmlldy1yZWFkaW5lc3MgYnVkZ2V0IFx1MjAxNCBzbyBlYWNoIGZhaWx1cmUgbWFrZXMgdGhlIG5leHQgb25lIGxpa2VsaWVyLlxuICogU3dlZXBpbmcgZm9yZWlnbiByZXNpZHVlIGF0IHRoZSBTVEFSVCBvZiBhIHJ1biBicmVha3MgdGhhdCBsb29wLCBiZWNhdXNlIGl0XG4gKiBydW5zIGJlZm9yZSBhbnl0aGluZyB0aGF0IGNhbiBkaWUuXG4gKlxuICogVGhlIHR3byBzaWRlcyB1c2UgZGVsaWJlcmF0ZWx5IGRpZmZlcmVudCBzYWZldHkgZ2F0ZXMgKHNlZSB0aGUgcmVwbydzIEwzMSk6XG4gKlxuICogLSAqKkRldmljZSAoQW5kcm9pZCkqKiBcdTIwMTQgdW5jb25kaXRpb25hbC4gQW5kcm9pZCBydW5zIGhvbGQgdGhlIGV4Y2x1c2l2ZVxuICogICBgYW5kcm9pZGAgc2V0dXAgbG9jaywgc28gbm8gY29uY3VycmVudCBydW4gY2FuIG93biBhIGRldmljZSB2YXVsdCwgYW5kIGFuXG4gKiAgIGFnZSBnYXRlIHdvdWxkIGxldCBhIHZhdWx0IGxlYWtlZCB0ZW4gbWludXRlcyBhZ28gc3Vydml2ZSBpbnRvIHRoZSBuZXh0IHJ1bi5cbiAqIC0gKipIb3N0KiogXHUyMDE0IGFnZS1nYXRlZC4gRGVza3RvcCBydW5zIGFyZSBkZWxpYmVyYXRlbHkgKm5vdCogc2VyaWFsaXplZCAoZWFjaFxuICogICBvd25zIGFuIGlzb2xhdGVkIGluc3RhbmNlKSBhbmQgZXZlcnkgcHJvamVjdCBvbiB0aGUgbWFjaGluZSBzaGFyZXMgb25lXG4gKiAgIGB0bXBkaXIoKWAsIHNvIGEgZGlyZWN0b3J5IHlvdW5nIGVub3VnaCB0byBiZWxvbmcgdG8gYSBsaXZlIHJ1biBpcyBsZWZ0XG4gKiAgIGFsb25lLlxuICovXG5cbmltcG9ydCB7XG4gIHJlYWRkaXIsXG4gIHJtLFxuICBzdGF0XG59IGZyb20gJ25vZGU6ZnMvcHJvbWlzZXMnO1xuaW1wb3J0IHsgdG1wZGlyIH0gZnJvbSAnbm9kZTpvcyc7XG5pbXBvcnQgeyBqb2luIH0gZnJvbSAnbm9kZTpwYXRoJztcblxuaW1wb3J0IHR5cGUgeyBPYnNpZGlhblRyYW5zcG9ydE9wdGlvbnMgfSBmcm9tICcuL3RyYW5zcG9ydC1vcHRpb25zLmNqcyc7XG5cbi8qKlxuICogRGVmYXVsdCBmb3IgdGhlIGBsZWZ0b3Zlck1heEFnZUluTWlsbGlzZWNvbmRzYCB0cmFuc3BvcnQgb3B0aW9uIFx1MjAxNCB0d28gaG91cnMuXG4gKi9cbmV4cG9ydCBjb25zdCBERUZBVUxUX0xFRlRPVkVSX01BWF9BR0VfSU5fTUlMTElTRUNPTkRTID0gNzIwMDAwMDtcblxuLyoqXG4gKiBOYW1lIG9mIHRoZSBoYXJuZXNzJ3Mgb3duIGRpcmVjdG9yeSBpbnNpZGUge0BsaW5rIHRtcGRpcn0sIHdoaWNoIGhvbGRzIHRoZVxuICogb3duZWQgaW5zdGFuY2VzJyB1c2VyLWRhdGEgZGlyZWN0b3JpZXMgYWxvbmdzaWRlIHRoZSB2ZXJzaW9uL2luc3RhbGxlciBjYWNoZXNcbiAqIGFuZCB0aGUgc2V0dXAgbG9ja3MuXG4gKi9cbmV4cG9ydCBjb25zdCBIQVJORVNTX1RFTVBfRElSX05BTUUgPSAnb2JzaWRpYW4taW50ZWdyYXRpb24tdGVzdGluZyc7XG5cbi8qKlxuICogUHJlZml4IG9mIGFuIG93bmVkIGRlc2t0b3AgaW5zdGFuY2UncyBpc29sYXRlZCB1c2VyLWRhdGEgZGlyZWN0b3J5LlxuICovXG5leHBvcnQgY29uc3QgT1dORURfVVNFUl9EQVRBX0RJUl9QUkVGSVggPSAndXNlcmRhdGEtJztcblxuLyoqXG4gKiBQcmVmaXggb2YgYSB0ZW1wb3JhcnkgdmF1bHQgZGlyZWN0b3J5LCBib3RoIG9uIHRoZSBob3N0ICh3aGVyZSBpdCBpcyBjcmVhdGVkKVxuICogYW5kIG9uIGFuIEFuZHJvaWQgZGV2aWNlICh3aGVyZSBpdCBrZWVwcyBpdHMgaG9zdCBiYXNlbmFtZSkuXG4gKi9cbmV4cG9ydCBjb25zdCBURU1QX1ZBVUxUX0RJUl9QUkVGSVggPSAndGVtcC12YXVsdC0nO1xuXG4vKipcbiAqIFBhcmFtZXRlcnMgZm9yIHtAbGluayBjaGVja0lzTGVmdG92ZXJTdGFsZX0uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQ2hlY2tJc0xlZnRvdmVyU3RhbGVQYXJhbXMge1xuICAvKipcbiAgICogSG93IG9sZCBhbiBlbnRyeSBtdXN0IGJlIHRvIGNvdW50IGFzIHN0YWxlLiBgMGAgZGlzYWJsZXMgdGhlIGdhdGUsIG1ha2luZ1xuICAgKiBldmVyeSBlbnRyeSBzdGFsZS5cbiAgICovXG4gIHJlYWRvbmx5IG1heEFnZUluTWlsbGlzZWNvbmRzOiBudW1iZXI7XG5cbiAgLyoqIFRoZSBlbnRyeSdzIG1vZGlmaWNhdGlvbiB0aW1lLCBpbiBlcG9jaCBtaWxsaXNlY29uZHMuICovXG4gIHJlYWRvbmx5IG1vZGlmaWVkQXRJbk1pbGxpc2Vjb25kczogbnVtYmVyO1xuXG4gIC8qKiBUaGUgY3VycmVudCB0aW1lLCBpbiBlcG9jaCBtaWxsaXNlY29uZHMuICovXG4gIHJlYWRvbmx5IG5vd0luTWlsbGlzZWNvbmRzOiBudW1iZXI7XG59XG5cbi8qKlxuICogUGFyYW1ldGVycyBmb3Ige0BsaW5rIGZpbHRlckxlZnRvdmVyTmFtZXN9LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEZpbHRlckxlZnRvdmVyTmFtZXNQYXJhbXMge1xuICAvKiogTmFtZXMgdG8ga2VlcCBldmVuIHdoZW4gdGhleSBtYXRjaCBhIHByZWZpeCAoZS5nLiB0aGUgY3VycmVudCBydW4ncyBvd24gdmF1bHQpLiAqL1xuICByZWFkb25seSBleGNsdWRlZE5hbWVzPzogcmVhZG9ubHkgc3RyaW5nW10gfCB1bmRlZmluZWQ7XG5cbiAgLyoqXG4gICAqIFJhdyBlbnRyeSBuYW1lcy4gQWNjZXB0cyBgYWRiIHNoZWxsIGxzYCBvdXRwdXQgc3BsaXQgaW50byBsaW5lcywgc28gZWFjaFxuICAgKiBuYW1lIGlzIHRyaW1tZWQgKGRyb3BwaW5nIHRoZSB0cmFpbGluZyBgXFxyYCBhbiBgYWRiYCBzaGVsbCBhZGRzIG9uIFdpbmRvd3MpXG4gICAqIGFuZCBibGFuayBsaW5lcyBhcmUgZHJvcHBlZC5cbiAgICovXG4gIHJlYWRvbmx5IG5hbWVzOiByZWFkb25seSBzdHJpbmdbXTtcblxuICAvKiogRGlyZWN0b3J5LW5hbWUgcHJlZml4ZXMgdGhhdCBtYXJrIGFuIGVudHJ5IGFzIHRoZSBoYXJuZXNzJ3Mgb3duIHJlc2lkdWUuICovXG4gIHJlYWRvbmx5IHByZWZpeGVzOiByZWFkb25seSBzdHJpbmdbXTtcbn1cblxuLyoqXG4gKiBBIGRpcmVjdG9yeSB0aGUgaG9zdCBzd2VlcCBzY2FucywgdG9nZXRoZXIgd2l0aCB0aGUgcHJlZml4ZXMgdGhhdCBtYXJrXG4gKiByZXNpZHVlIGluc2lkZSBpdC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBMZWZ0b3ZlclJvb3Qge1xuICAvKiogVGhlIGFic29sdXRlIHBhdGggdG8gc2Nhbi4gKi9cbiAgcmVhZG9ubHkgcGF0aDogc3RyaW5nO1xuXG4gIC8qKiBEaXJlY3RvcnktbmFtZSBwcmVmaXhlcyB0aGF0IG1hcmsgYW4gZW50cnkgYXMgcmVtb3ZhYmxlIHJlc2lkdWUuICovXG4gIHJlYWRvbmx5IHByZWZpeGVzOiByZWFkb25seSBzdHJpbmdbXTtcbn1cblxuLyoqXG4gKiBQYXJhbWV0ZXJzIGZvciB7QGxpbmsgc3dlZXBEZXZpY2VMZWZ0b3ZlcnN9LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFN3ZWVwRGV2aWNlTGVmdG92ZXJzUGFyYW1zIHtcbiAgLyoqXG4gICAqIExpc3RzIHRoZSBlbnRyeSBuYW1lcyBkaXJlY3RseSB1bmRlciB0aGUgdmF1bHQgYmFzZSBwYXRoLiBBIGxpc3RpbmcgZmFpbHVyZVxuICAgKiBtdXN0IHJlc29sdmUgdG8gYW4gZW1wdHkgbGlzdCByYXRoZXIgdGhhbiByZWplY3QgXHUyMDE0IGEgZGV2aWNlIHdpdGggbm8gdmF1bHRcbiAgICogZGlyZWN0b3J5IHlldCBpcyB0aGUgbm9ybWFsIGZpcnN0LXJ1biBzdGF0ZSwgbm90IGFuIGVycm9yLlxuICAgKi9cbiAgcmVhZG9ubHkgbGlzdE5hbWVzOiAoKSA9PiBQcm9taXNlPHJlYWRvbmx5IHN0cmluZ1tdPjtcblxuICAvKipcbiAgICogUmVtb3ZlcyBPTkUgZGlyZWN0b3J5LCBieSBhYnNvbHV0ZSBkZXZpY2UgcGF0aC4gTWF5IHJlamVjdDsgdGhlIGNhbGxlclxuICAgKiB0cmVhdHMgYSByZWplY3Rpb24gYXMgdGhpcyBkaXJlY3RvcnkgZmFpbGluZyBhbmQgbW92ZXMgb24gdG8gdGhlIG5leHQuXG4gICAqL1xuICByZWFkb25seSByZW1vdmVEaXI6IChwYXRoOiBzdHJpbmcpID0+IFByb21pc2U8dm9pZD47XG5cbiAgLyoqIFRoZSBhYnNvbHV0ZSBkZXZpY2UgcGF0aCB0aGUgdmF1bHRzIHNpdCB1bmRlciwgaW5jbHVkaW5nIGl0cyB0cmFpbGluZyBzZXBhcmF0b3IuICovXG4gIHJlYWRvbmx5IHZhdWx0QmFzZVBhdGg6IHN0cmluZztcbn1cblxuLyoqXG4gKiBSZXN1bHQgb2Yge0BsaW5rIHN3ZWVwRGV2aWNlTGVmdG92ZXJzfS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTd2VlcERldmljZUxlZnRvdmVyc1Jlc3VsdCB7XG4gIC8qKlxuICAgKiBUaGUgbmFtZXMgdGhhdCB3ZXJlIHN0aWxsIHByZXNlbnQgYWZ0ZXIgdGhlIHN3ZWVwLiBOYW1lZCByYXRoZXIgdGhhblxuICAgKiBjb3VudGVkLCBiZWNhdXNlIHRoZSBpbnRlcmVzdGluZyBjYXNlIGlzIGEgZGlyZWN0b3J5IHRoYXQgZmFpbHMgRVZFUlkgcnVuXG4gICAqIGFuZCBhIGNhbGxlciBjYW4gb25seSBzYXkgc28gaWYgaXQga25vd3Mgd2hpY2ggb25lLlxuICAgKi9cbiAgcmVhZG9ubHkgZmFpbGVkTmFtZXM6IHN0cmluZ1tdO1xuXG4gIC8qKiBIb3cgbWFueSBkaXJlY3RvcmllcyBhcmUgdmVyaWZpYWJseSBnb25lLiAqL1xuICByZWFkb25seSByZW1vdmVkQ291bnQ6IG51bWJlcjtcbn1cblxuLyoqXG4gKiBPcHRpb25zIGZvciB7QGxpbmsgc3dlZXBIb3N0TGVmdG92ZXJzfS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTd2VlcEhvc3RMZWZ0b3ZlcnNPcHRpb25zIHtcbiAgLyoqIE5hbWVzIHRvIGtlZXAgcmVnYXJkbGVzcyBvZiBhZ2UgKGUuZy4gdGhlIGN1cnJlbnQgcnVuJ3Mgb3duIGRpcmVjdG9yaWVzKS4gKi9cbiAgcmVhZG9ubHkgZXhjbHVkZWROYW1lcz86IHJlYWRvbmx5IHN0cmluZ1tdIHwgdW5kZWZpbmVkO1xuXG4gIC8qKlxuICAgKiBIb3cgb2xkIGEgZGlyZWN0b3J5IG11c3QgYmUgYmVmb3JlIGl0IGlzIHJlbW92ZWQuIGAwYCByZW1vdmVzIGV2ZXJ5IG1hdGNoLlxuICAgKlxuICAgKiBAZGVmYXVsdCB7QGxpbmsgREVGQVVMVF9MRUZUT1ZFUl9NQVhfQUdFX0lOX01JTExJU0VDT05EU31cbiAgICovXG4gIHJlYWRvbmx5IG1heEFnZUluTWlsbGlzZWNvbmRzPzogbnVtYmVyIHwgdW5kZWZpbmVkO1xuXG4gIC8qKlxuICAgKiBUaGUgcm9vdHMgdG8gc3dlZXAuIERlZmF1bHRzIHRvIHRoZSB0ZW1wLXZhdWx0IHJvb3QgKHtAbGluayB0bXBkaXJ9KSBhbmQgdGhlXG4gICAqIG93bmVkIHVzZXItZGF0YSByb290IChgPHRtcGRpcj4ve0BsaW5rIEhBUk5FU1NfVEVNUF9ESVJfTkFNRX1gKS5cbiAgICovXG4gIHJlYWRvbmx5IHJvb3RzPzogcmVhZG9ubHkgTGVmdG92ZXJSb290W10gfCB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogUmVzdWx0IG9mIHtAbGluayBzd2VlcEhvc3RMZWZ0b3ZlcnN9LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFN3ZWVwSG9zdExlZnRvdmVyc1Jlc3VsdCB7XG4gIC8qKiBIb3cgbWFueSBkaXJlY3RvcmllcyB3ZXJlIHNlbGVjdGVkIGZvciByZW1vdmFsIGJ1dCBjb3VsZCBub3QgYmUgcmVtb3ZlZC4gKi9cbiAgcmVhZG9ubHkgZmFpbGVkQ291bnQ6IG51bWJlcjtcblxuICAvKiogSG93IG1hbnkgZGlyZWN0b3JpZXMgd2VyZSByZW1vdmVkLiAqL1xuICByZWFkb25seSByZW1vdmVkQ291bnQ6IG51bWJlcjtcbn1cblxuLyoqXG4gKiBQYXJhbWV0ZXJzIGZvciB7QGxpbmsgY2hlY2tJc1JlbW92YWJsZURpcn0uXG4gKi9cbmludGVyZmFjZSBDaGVja0lzUmVtb3ZhYmxlRGlyUGFyYW1zIHtcbiAgLyoqIEhvdyBvbGQgdGhlIGVudHJ5IG11c3QgYmUgdG8gYmUgcmVtb3ZlZCAoYDBgIGRpc2FibGVzIHRoZSBnYXRlKS4gKi9cbiAgcmVhZG9ubHkgbWF4QWdlSW5NaWxsaXNlY29uZHM6IG51bWJlcjtcblxuICAvKiogVGhlIHN3ZWVwJ3MgcmVmZXJlbmNlIHRpbWUsIGluIGVwb2NoIG1pbGxpc2Vjb25kcy4gKi9cbiAgcmVhZG9ubHkgbm93SW5NaWxsaXNlY29uZHM6IG51bWJlcjtcblxuICAvKiogVGhlIGFic29sdXRlIHBhdGggdG8gdGhlIGVudHJ5LiAqL1xuICByZWFkb25seSBwYXRoOiBzdHJpbmc7XG59XG5cbi8qKlxuICogRGVjaWRlcyB3aGV0aGVyIGEgbGVmdG92ZXIgZW50cnkgaXMgb2xkIGVub3VnaCB0byBiZSByZW1vdmVkLlxuICpcbiAqIFRoZSBnYXRlIGV4aXN0cyBiZWNhdXNlIGV2ZXJ5IHByb2plY3Qgb24gdGhlIG1hY2hpbmUgc2hhcmVzIG9uZSBgdG1wZGlyKClgXG4gKiBhbmQgZGVza3RvcCBydW5zIGFyZSBub3Qgc2VyaWFsaXplZCwgc28gYSB5b3VuZyBkaXJlY3RvcnkgbWF5IHdlbGwgYmVsb25nIHRvXG4gKiBhIHJ1biB0aGF0IGlzIHN0aWxsIGluIGZsaWdodC4gQW4gZW50cnkgd2hvc2UgbW9kaWZpY2F0aW9uIHRpbWUgaXMgaW4gdGhlXG4gKiBmdXR1cmUgKGEgY2xvY2sgc2tldykgaXMgdHJlYXRlZCBhcyBsaXZlIGZvciB0aGUgc2FtZSByZWFzb24uXG4gKlxuICogQHBhcmFtIHBhcmFtcyAtIFRoZSBhZ2UgY29tcGFyaXNvbiBpbnB1dHMuXG4gKiBAcmV0dXJucyBgdHJ1ZWAgd2hlbiB0aGUgZW50cnkgbWF5IGJlIHJlbW92ZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjaGVja0lzTGVmdG92ZXJTdGFsZShwYXJhbXM6IENoZWNrSXNMZWZ0b3ZlclN0YWxlUGFyYW1zKTogYm9vbGVhbiB7XG4gIGlmIChwYXJhbXMubWF4QWdlSW5NaWxsaXNlY29uZHMgPT09IDApIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIHJldHVybiBwYXJhbXMubm93SW5NaWxsaXNlY29uZHMgLSBwYXJhbXMubW9kaWZpZWRBdEluTWlsbGlzZWNvbmRzID49IHBhcmFtcy5tYXhBZ2VJbk1pbGxpc2Vjb25kcztcbn1cblxuLyoqXG4gKiBTZWxlY3RzIHRoZSBlbnRyeSBuYW1lcyB0aGF0IGFyZSB0aGUgaGFybmVzcydzIG93biByZXNpZHVlLlxuICpcbiAqIE5hbWUtb25seSwgc28gdGhlIGNhbGxlciBjYW4gZmlsdGVyIGEgbGFyZ2UgZGlyZWN0b3J5IGxpc3RpbmcgYmVmb3JlIHBheWluZ1xuICogZm9yIGEgYHN0YXRgIHBlciBlbnRyeSwgYW5kIHNvIHRoZSBBbmRyb2lkIHN3ZWVwIGNhbiBmZWVkIGl0IHJhd1xuICogYGFkYiBzaGVsbCBsc2Agb3V0cHV0LlxuICpcbiAqIEBwYXJhbSBwYXJhbXMgLSBUaGUgbmFtZXMsIHByZWZpeGVzLCBhbmQgZXhjbHVzaW9ucy5cbiAqIEByZXR1cm5zIFRoZSBtYXRjaGluZyBuYW1lcywgdHJpbW1lZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZpbHRlckxlZnRvdmVyTmFtZXMocGFyYW1zOiBGaWx0ZXJMZWZ0b3Zlck5hbWVzUGFyYW1zKTogc3RyaW5nW10ge1xuICBjb25zdCBleGNsdWRlZE5hbWVzID0gcGFyYW1zLmV4Y2x1ZGVkTmFtZXMgPz8gW107XG4gIHJldHVybiBwYXJhbXMubmFtZXNcbiAgICAubWFwKChuYW1lKSA9PiBuYW1lLnRyaW0oKSlcbiAgICAuZmlsdGVyKChuYW1lKSA9PiBwYXJhbXMucHJlZml4ZXMuc29tZSgocHJlZml4KSA9PiBuYW1lLnN0YXJ0c1dpdGgocHJlZml4KSkpXG4gICAgLmZpbHRlcigobmFtZSkgPT4gIWV4Y2x1ZGVkTmFtZXMuaW5jbHVkZXMobmFtZSkpO1xufVxuXG4vKipcbiAqIFJlc29sdmVzIHRoZSBsZWZ0b3ZlciBhZ2UgZ2F0ZSwgYXBwbHlpbmcgdGhlIGRlZmF1bHQgd2hlbiB0aGUgb3B0aW9uIGlzXG4gKiBvbWl0dGVkLlxuICpcbiAqIEBwYXJhbSBvcHRpb25zIC0gVGhlIHRyYW5zcG9ydCBvcHRpb25zLlxuICogQHJldHVybnMgVGhlIG1heCBhZ2UgaW4gbWlsbGlzZWNvbmRzIChgMGAgZGlzYWJsZXMgdGhlIGdhdGUpLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVzb2x2ZUxlZnRvdmVyTWF4QWdlSW5NaWxsaXNlY29uZHMob3B0aW9uczogT2JzaWRpYW5UcmFuc3BvcnRPcHRpb25zIHwgdW5kZWZpbmVkKTogbnVtYmVyIHtcbiAgcmV0dXJuIG9wdGlvbnM/LmxlZnRvdmVyTWF4QWdlSW5NaWxsaXNlY29uZHMgPz8gREVGQVVMVF9MRUZUT1ZFUl9NQVhfQUdFX0lOX01JTExJU0VDT05EUztcbn1cblxuLyoqXG4gKiBSZXNvbHZlcyB3aGV0aGVyIGxlZnRvdmVyIGRpcmVjdG9yaWVzIGFyZSBzd2VwdCwgYXBwbHlpbmcgdGhlIGRlZmF1bHQgd2hlblxuICogdGhlIG9wdGlvbiBpcyBvbWl0dGVkLlxuICpcbiAqIEBwYXJhbSBvcHRpb25zIC0gVGhlIHRyYW5zcG9ydCBvcHRpb25zLlxuICogQHJldHVybnMgYHRydWVgIHdoZW4gdGhlIHN3ZWVwcyBzaG91bGQgcnVuLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVzb2x2ZVNob3VsZFN3ZWVwTGVmdG92ZXJzKG9wdGlvbnM6IE9ic2lkaWFuVHJhbnNwb3J0T3B0aW9ucyB8IHVuZGVmaW5lZCk6IGJvb2xlYW4ge1xuICByZXR1cm4gb3B0aW9ucz8uc2hvdWxkU3dlZXBMZWZ0b3ZlcnMgPz8gdHJ1ZTtcbn1cblxuLyoqXG4gKiBSZW1vdmVzIHRoZSBsZWZ0b3ZlciB2YXVsdCBkaXJlY3RvcmllcyBhIGRldmljZSBpcyBjYXJyeWluZywgb25lIGRpcmVjdG9yeSBhdFxuICogYSB0aW1lLCBhbmQgcmVwb3J0cyB3aGF0IGlzIHZlcmlmaWFibHkgZ29uZS5cbiAqXG4gKiAqKk9uZSBkaXJlY3RvcnkgcGVyIHJlbW92YWwsIGFuZCBhIGZhaWx1cmUgaXMgbm9uLWZhdGFsLioqIFJlbW92aW5nIHRoZSB3aG9sZVxuICogc2V0IGluIGEgc2luZ2xlIGBybSAtcmZgIGxldHMgb25lIHVuLXJlbW92YWJsZSBlbnRyeSBkZWNpZGUgdGhlIGZhdGUgb2YgZXZlcnlcbiAqIG90aGVyOiBhIG5hbWUgdGhhdCB0aGUgRlVTRSBsYXllciBjYW5ub3QgZXhwcmVzcyAoYW4gQW5kcm9pZCBlbXVsYXRvciBjYW5cbiAqIHByb2R1Y2Ugb25lIFx1MjAxNCBgcm0gLXJmYCwgYGZpbmQgLWRlbGV0ZWAgYW5kIGZvcmNlLXN0b3BwaW5nIE9ic2lkaWFuIGZpcnN0IGFsbFxuICogYW5zd2VyIGBPcGVyYXRpb24gbm90IHBlcm1pdHRlZGApIGlzIHBlcm1hbmVudCwgc28gYSBzd2VlcCB0aGF0IGdpdmVzIHVwIG9uIGl0XG4gKiBnaXZlcyB1cCBmb3JldmVyLCBhbmQgdGhlIHJlc2lkdWUgb25seSBncm93cy4gUGVyLWRpcmVjdG9yeSwgdGhhdCBlbnRyeSBjb3N0c1xuICogb25lIHdhcm5pbmcgcGVyIHJ1biBpbnN0ZWFkIG9mIHRoZSB3aG9sZSBzd2VlcC5cbiAqXG4gKiAqKlRoZSByZXN1bHQgaXMgbWVhc3VyZWQsIG5vdCBhc3N1bWVkLioqIFRoZSBkaXJlY3RvcmllcyBhcmUgcmUtbGlzdGVkXG4gKiBhZnRlcndhcmRzIGFuZCBvbmx5IHRoZSBvbmVzIHRoYXQgYWN0dWFsbHkgZGlzYXBwZWFyZWQgYXJlIGNvdW50ZWQsIGJlY2F1c2VcbiAqIHRoZSBmYWlsdXJlIHRoaXMgd2FzIHdyaXR0ZW4gZm9yIHdhcyBhIHN3ZWVwIHRoYXQgcmVwb3J0ZWQgc3VjY2VzcyB3aGlsZVxuICogY2xlYXJpbmcgbm90aGluZyBcdTIwMTQgYSByZW1vdmFsIGNvbW1hbmQgY2FuIGV4aXQgbm9uLXplcm8sIG9yIHBhcnRpYWxseSBzdWNjZWVkLFxuICogYW5kIG5laXRoZXIgaXMgdmlzaWJsZSBmcm9tIGl0cyBleGl0IGNvZGUgYWxvbmUuXG4gKlxuICogQHBhcmFtIHBhcmFtcyAtIEhvdyB0byBsaXN0IGFuZCByZW1vdmUsIGFuZCB0aGUgYmFzZSBwYXRoIHRvIHN3ZWVwLlxuICogQHJldHVybnMgVGhlIHZlcmlmaWVkIHJlbW92YWwgY291bnQgYW5kIHRoZSBuYW1lcyB0aGF0IHN1cnZpdmVkLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc3dlZXBEZXZpY2VMZWZ0b3ZlcnMoXG4gIHBhcmFtczogU3dlZXBEZXZpY2VMZWZ0b3ZlcnNQYXJhbXNcbik6IFByb21pc2U8U3dlZXBEZXZpY2VMZWZ0b3ZlcnNSZXN1bHQ+IHtcbiAgY29uc3QgeyBsaXN0TmFtZXMsIHJlbW92ZURpciwgdmF1bHRCYXNlUGF0aCB9ID0gcGFyYW1zO1xuXG4gIGNvbnN0IG5hbWVzID0gZmlsdGVyTGVmdG92ZXJOYW1lcyh7IG5hbWVzOiBhd2FpdCBsaXN0TmFtZXMoKSwgcHJlZml4ZXM6IFtURU1QX1ZBVUxUX0RJUl9QUkVGSVhdIH0pO1xuICBpZiAobmFtZXMubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIHsgZmFpbGVkTmFtZXM6IFtdLCByZW1vdmVkQ291bnQ6IDAgfTtcbiAgfVxuXG4gIGZvciAoY29uc3QgbmFtZSBvZiBuYW1lcykge1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCByZW1vdmVEaXIoYCR7dmF1bHRCYXNlUGF0aH0ke25hbWV9YCk7XG4gICAgfSBjYXRjaCB7XG4gICAgICAvLyBOb24tZmF0YWwgYnkgZGVzaWduOiB0aGUgbmV4dCBkaXJlY3Rvcnkgc3RpbGwgZ2V0cyBpdHMgY2hhbmNlLlxuICAgIH1cbiAgfVxuXG4gIGNvbnN0IHN1cnZpdmluZ05hbWVzID0gZmlsdGVyTGVmdG92ZXJOYW1lcyh7IG5hbWVzOiBhd2FpdCBsaXN0TmFtZXMoKSwgcHJlZml4ZXM6IFtURU1QX1ZBVUxUX0RJUl9QUkVGSVhdIH0pO1xuICBjb25zdCBmYWlsZWROYW1lcyA9IG5hbWVzLmZpbHRlcigobmFtZSkgPT4gc3Vydml2aW5nTmFtZXMuaW5jbHVkZXMobmFtZSkpO1xuXG4gIHJldHVybiB7IGZhaWxlZE5hbWVzLCByZW1vdmVkQ291bnQ6IG5hbWVzLmxlbmd0aCAtIGZhaWxlZE5hbWVzLmxlbmd0aCB9O1xufVxuXG4vKipcbiAqIFJlbW92ZXMgdGhlIGhvc3Qtc2lkZSBkaXJlY3RvcmllcyBsZWZ0IGJlaGluZCBieSBlYXJsaWVyIHJ1bnMuXG4gKlxuICogQmVzdC1lZmZvcnQgdGhyb3VnaG91dDogYW4gdW5yZWFkYWJsZSByb290LCBhbiBlbnRyeSB0aGF0IGNhbm5vdCBiZSBgc3RhdGBlZCxcbiAqIGFuZCBhIGRpcmVjdG9yeSB0aGF0IHJlZnVzZXMgdG8gYmUgcmVtb3ZlZCAoYSBsaXZlIHByb2Nlc3Mgc3RpbGwgaG9sZGluZyBhXG4gKiBoYW5kbGUgYW5zd2VycyBgRVBFUk1gIG9uIFdpbmRvd3MpIGFyZSBhbGwgc2tpcHBlZCByYXRoZXIgdGhhbiB0aHJvd24sIHNvIGFcbiAqIHN3ZWVwIGNhbiBuZXZlciBmYWlsIHRoZSBydW4gaXQgaXMgY2xlYW5pbmcgdXAgZm9yLlxuICpcbiAqIEBwYXJhbSBvcHRpb25zIC0gVGhlIHN3ZWVwIG9wdGlvbnMuXG4gKiBAcmV0dXJucyBIb3cgbWFueSBkaXJlY3RvcmllcyB3ZXJlIHJlbW92ZWQsIGFuZCBob3cgbWFueSByZXNpc3RlZCByZW1vdmFsLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc3dlZXBIb3N0TGVmdG92ZXJzKG9wdGlvbnM/OiBTd2VlcEhvc3RMZWZ0b3ZlcnNPcHRpb25zKTogUHJvbWlzZTxTd2VlcEhvc3RMZWZ0b3ZlcnNSZXN1bHQ+IHtcbiAgY29uc3QgbWF4QWdlSW5NaWxsaXNlY29uZHMgPSBvcHRpb25zPy5tYXhBZ2VJbk1pbGxpc2Vjb25kcyA/PyBERUZBVUxUX0xFRlRPVkVSX01BWF9BR0VfSU5fTUlMTElTRUNPTkRTO1xuICBjb25zdCBub3dJbk1pbGxpc2Vjb25kcyA9IERhdGUubm93KCk7XG4gIGNvbnN0IHJvb3RzID0gb3B0aW9ucz8ucm9vdHMgPz8gZ2V0RGVmYXVsdExlZnRvdmVyUm9vdHMoKTtcblxuICBsZXQgZmFpbGVkQ291bnQgPSAwO1xuICBsZXQgcmVtb3ZlZENvdW50ID0gMDtcblxuICBmb3IgKGNvbnN0IHJvb3Qgb2Ygcm9vdHMpIHtcbiAgICBjb25zdCBuYW1lcyA9IGZpbHRlckxlZnRvdmVyTmFtZXMoe1xuICAgICAgZXhjbHVkZWROYW1lczogb3B0aW9ucz8uZXhjbHVkZWROYW1lcyxcbiAgICAgIG5hbWVzOiBhd2FpdCByZWFkRGlyTmFtZXMocm9vdC5wYXRoKSxcbiAgICAgIHByZWZpeGVzOiByb290LnByZWZpeGVzXG4gICAgfSk7XG5cbiAgICBmb3IgKGNvbnN0IG5hbWUgb2YgbmFtZXMpIHtcbiAgICAgIGNvbnN0IHBhdGggPSBqb2luKHJvb3QucGF0aCwgbmFtZSk7XG4gICAgICBpZiAoIWF3YWl0IGNoZWNrSXNSZW1vdmFibGVEaXIoeyBtYXhBZ2VJbk1pbGxpc2Vjb25kcywgbm93SW5NaWxsaXNlY29uZHMsIHBhdGggfSkpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHJtKHBhdGgsIHsgZm9yY2U6IHRydWUsIHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgICAgICAgcmVtb3ZlZENvdW50Kys7XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgZmFpbGVkQ291bnQrKztcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4geyBmYWlsZWRDb3VudCwgcmVtb3ZlZENvdW50IH07XG59XG5cbi8qKlxuICogQ2hlY2tzIHdoZXRoZXIgYSBtYXRjaGVkIGVudHJ5IGlzIGEgZGlyZWN0b3J5IG9sZCBlbm91Z2ggdG8gcmVtb3ZlLlxuICpcbiAqIEBwYXJhbSBwYXJhbXMgLSBUaGUgZW50cnkgcGF0aCBhbmQgYWdlLWdhdGUgaW5wdXRzLlxuICogQHJldHVybnMgYHRydWVgIHdoZW4gdGhlIGVudHJ5IG1heSBiZSByZW1vdmVkLlxuICovXG5hc3luYyBmdW5jdGlvbiBjaGVja0lzUmVtb3ZhYmxlRGlyKHBhcmFtczogQ2hlY2tJc1JlbW92YWJsZURpclBhcmFtcyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICBjb25zdCB7IG1heEFnZUluTWlsbGlzZWNvbmRzLCBub3dJbk1pbGxpc2Vjb25kcyB9ID0gcGFyYW1zO1xuICB0cnkge1xuICAgIGNvbnN0IHN0YXRzID0gYXdhaXQgc3RhdChwYXJhbXMucGF0aCk7XG4gICAgcmV0dXJuIHN0YXRzLmlzRGlyZWN0b3J5KClcbiAgICAgICYmIGNoZWNrSXNMZWZ0b3ZlclN0YWxlKHsgbWF4QWdlSW5NaWxsaXNlY29uZHMsIG1vZGlmaWVkQXRJbk1pbGxpc2Vjb25kczogc3RhdHMubXRpbWVNcywgbm93SW5NaWxsaXNlY29uZHMgfSk7XG4gIH0gY2F0Y2gge1xuICAgIC8vIFZhbmlzaGVkLCBvciB1bnJlYWRhYmxlIFx1MjAxNCBlaXRoZXIgd2F5IGl0IGlzIG5vdCBvdXJzIHRvIHJlbW92ZS5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSByb290cyBzd2VwdCB3aGVuIHRoZSBjYWxsZXIgZG9lcyBub3QgbmFtZSBpdHMgb3duLlxuICpcbiAqIEByZXR1cm5zIFRoZSB0ZW1wLXZhdWx0IHJvb3QgYW5kIHRoZSBvd25lZCB1c2VyLWRhdGEgcm9vdC5cbiAqL1xuZnVuY3Rpb24gZ2V0RGVmYXVsdExlZnRvdmVyUm9vdHMoKTogTGVmdG92ZXJSb290W10ge1xuICByZXR1cm4gW1xuICAgIHsgcGF0aDogdG1wZGlyKCksIHByZWZpeGVzOiBbVEVNUF9WQVVMVF9ESVJfUFJFRklYXSB9LFxuICAgIHsgcGF0aDogam9pbih0bXBkaXIoKSwgSEFSTkVTU19URU1QX0RJUl9OQU1FKSwgcHJlZml4ZXM6IFtPV05FRF9VU0VSX0RBVEFfRElSX1BSRUZJWF0gfVxuICBdO1xufVxuXG4vKipcbiAqIExpc3RzIGEgZGlyZWN0b3J5J3MgZW50cnkgbmFtZXMsIHRyZWF0aW5nIGFuIHVucmVhZGFibGUgZGlyZWN0b3J5IGFzIGVtcHR5LlxuICpcbiAqIEBwYXJhbSBwYXRoIC0gVGhlIGFic29sdXRlIHBhdGggdG8gbGlzdC5cbiAqIEByZXR1cm5zIFRoZSBlbnRyeSBuYW1lcywgb3IgYW4gZW1wdHkgbGlzdC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gcmVhZERpck5hbWVzKHBhdGg6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nW10+IHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gYXdhaXQgcmVhZGRpcihwYXRoKTtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG59XG4iXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBMkJBLHNCQUlPO0FBQ1AscUJBQXVCO0FBQ3ZCLHVCQUFxQjtBQU9kLE1BQU0sMkNBQTJDO0FBT2pELE1BQU0sd0JBQXdCO0FBSzlCLE1BQU0sNkJBQTZCO0FBTW5DLE1BQU0sd0JBQXdCO0FBOEk5QixTQUFTLHFCQUFxQixRQUE2QztBQUNoRixNQUFJLE9BQU8seUJBQXlCLEdBQUc7QUFDckMsV0FBTztBQUFBLEVBQ1Q7QUFFQSxTQUFPLE9BQU8sb0JBQW9CLE9BQU8sNEJBQTRCLE9BQU87QUFDOUU7QUFZTyxTQUFTLG9CQUFvQixRQUE2QztBQUMvRSxRQUFNLGdCQUFnQixPQUFPLGlCQUFpQixDQUFDO0FBQy9DLFNBQU8sT0FBTyxNQUNYLElBQUksQ0FBQyxTQUFTLEtBQUssS0FBSyxDQUFDLEVBQ3pCLE9BQU8sQ0FBQyxTQUFTLE9BQU8sU0FBUyxLQUFLLENBQUMsV0FBVyxLQUFLLFdBQVcsTUFBTSxDQUFDLENBQUMsRUFDMUUsT0FBTyxDQUFDLFNBQVMsQ0FBQyxjQUFjLFNBQVMsSUFBSSxDQUFDO0FBQ25EO0FBU08sU0FBUyxvQ0FBb0MsU0FBdUQ7QUFDekcsU0FBTyxTQUFTLGdDQUFnQztBQUNsRDtBQVNPLFNBQVMsNEJBQTRCLFNBQXdEO0FBQ2xHLFNBQU8sU0FBUyx3QkFBd0I7QUFDMUM7QUF1QkEsZUFBc0IscUJBQ3BCLFFBQ3FDO0FBQ3JDLFFBQU0sRUFBRSxXQUFXLFdBQVcsY0FBYyxJ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
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file
|
|
3
|
+
*
|
|
4
|
+
* Sweeps the temporary directories a previous integration run leaked — the
|
|
5
|
+
* `temp-vault-*` staging/vault directories and the owned instance's
|
|
6
|
+
* `userdata-*` Chromium profiles.
|
|
7
|
+
*
|
|
8
|
+
* A run that dies mid-flight cannot clean up after itself: on Android the
|
|
9
|
+
* teardown talks to the WebView, and a dead WebView is exactly what most
|
|
10
|
+
* failures are (`Vault cleanup error (non-fatal): no such window`). Every
|
|
11
|
+
* failure therefore leaks a vault, every leaked vault stays registered for
|
|
12
|
+
* Obsidian to enumerate at startup, and that enumeration has to finish inside
|
|
13
|
+
* the WebView-readiness budget — so each failure makes the next one likelier.
|
|
14
|
+
* Sweeping foreign residue at the START of a run breaks that loop, because it
|
|
15
|
+
* runs before anything that can die.
|
|
16
|
+
*
|
|
17
|
+
* The two sides use deliberately different safety gates (see the repo's L31):
|
|
18
|
+
*
|
|
19
|
+
* - **Device (Android)** — unconditional. Android runs hold the exclusive
|
|
20
|
+
* `android` setup lock, so no concurrent run can own a device vault, and an
|
|
21
|
+
* age gate would let a vault leaked ten minutes ago survive into the next run.
|
|
22
|
+
* - **Host** — age-gated. Desktop runs are deliberately *not* serialized (each
|
|
23
|
+
* owns an isolated instance) and every project on the machine shares one
|
|
24
|
+
* `tmpdir()`, so a directory young enough to belong to a live run is left
|
|
25
|
+
* alone.
|
|
26
|
+
*/
|
|
27
|
+
import type { ObsidianTransportOptions } from './transport-options.cjs';
|
|
28
|
+
/**
|
|
29
|
+
* Default for the `leftoverMaxAgeInMilliseconds` transport option — two hours.
|
|
30
|
+
*/
|
|
31
|
+
export declare const DEFAULT_LEFTOVER_MAX_AGE_IN_MILLISECONDS = 7200000;
|
|
32
|
+
/**
|
|
33
|
+
* Name of the harness's own directory inside {@link tmpdir}, which holds the
|
|
34
|
+
* owned instances' user-data directories alongside the version/installer caches
|
|
35
|
+
* and the setup locks.
|
|
36
|
+
*/
|
|
37
|
+
export declare const HARNESS_TEMP_DIR_NAME = "obsidian-integration-testing";
|
|
38
|
+
/**
|
|
39
|
+
* Prefix of an owned desktop instance's isolated user-data directory.
|
|
40
|
+
*/
|
|
41
|
+
export declare const OWNED_USER_DATA_DIR_PREFIX = "userdata-";
|
|
42
|
+
/**
|
|
43
|
+
* Prefix of a temporary vault directory, both on the host (where it is created)
|
|
44
|
+
* and on an Android device (where it keeps its host basename).
|
|
45
|
+
*/
|
|
46
|
+
export declare const TEMP_VAULT_DIR_PREFIX = "temp-vault-";
|
|
47
|
+
/**
|
|
48
|
+
* Parameters for {@link checkIsLeftoverStale}.
|
|
49
|
+
*/
|
|
50
|
+
export interface CheckIsLeftoverStaleParams {
|
|
51
|
+
/**
|
|
52
|
+
* How old an entry must be to count as stale. `0` disables the gate, making
|
|
53
|
+
* every entry stale.
|
|
54
|
+
*/
|
|
55
|
+
readonly maxAgeInMilliseconds: number;
|
|
56
|
+
/** The entry's modification time, in epoch milliseconds. */
|
|
57
|
+
readonly modifiedAtInMilliseconds: number;
|
|
58
|
+
/** The current time, in epoch milliseconds. */
|
|
59
|
+
readonly nowInMilliseconds: number;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Parameters for {@link filterLeftoverNames}.
|
|
63
|
+
*/
|
|
64
|
+
export interface FilterLeftoverNamesParams {
|
|
65
|
+
/** Names to keep even when they match a prefix (e.g. the current run's own vault). */
|
|
66
|
+
readonly excludedNames?: readonly string[] | undefined;
|
|
67
|
+
/**
|
|
68
|
+
* Raw entry names. Accepts `adb shell ls` output split into lines, so each
|
|
69
|
+
* name is trimmed (dropping the trailing `\r` an `adb` shell adds on Windows)
|
|
70
|
+
* and blank lines are dropped.
|
|
71
|
+
*/
|
|
72
|
+
readonly names: readonly string[];
|
|
73
|
+
/** Directory-name prefixes that mark an entry as the harness's own residue. */
|
|
74
|
+
readonly prefixes: readonly string[];
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* A directory the host sweep scans, together with the prefixes that mark
|
|
78
|
+
* residue inside it.
|
|
79
|
+
*/
|
|
80
|
+
export interface LeftoverRoot {
|
|
81
|
+
/** The absolute path to scan. */
|
|
82
|
+
readonly path: string;
|
|
83
|
+
/** Directory-name prefixes that mark an entry as removable residue. */
|
|
84
|
+
readonly prefixes: readonly string[];
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Parameters for {@link sweepDeviceLeftovers}.
|
|
88
|
+
*/
|
|
89
|
+
export interface SweepDeviceLeftoversParams {
|
|
90
|
+
/**
|
|
91
|
+
* Lists the entry names directly under the vault base path. A listing failure
|
|
92
|
+
* must resolve to an empty list rather than reject — a device with no vault
|
|
93
|
+
* directory yet is the normal first-run state, not an error.
|
|
94
|
+
*/
|
|
95
|
+
readonly listNames: () => Promise<readonly string[]>;
|
|
96
|
+
/**
|
|
97
|
+
* Removes ONE directory, by absolute device path. May reject; the caller
|
|
98
|
+
* treats a rejection as this directory failing and moves on to the next.
|
|
99
|
+
*/
|
|
100
|
+
readonly removeDir: (path: string) => Promise<void>;
|
|
101
|
+
/** The absolute device path the vaults sit under, including its trailing separator. */
|
|
102
|
+
readonly vaultBasePath: string;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Result of {@link sweepDeviceLeftovers}.
|
|
106
|
+
*/
|
|
107
|
+
export interface SweepDeviceLeftoversResult {
|
|
108
|
+
/**
|
|
109
|
+
* The names that were still present after the sweep. Named rather than
|
|
110
|
+
* counted, because the interesting case is a directory that fails EVERY run
|
|
111
|
+
* and a caller can only say so if it knows which one.
|
|
112
|
+
*/
|
|
113
|
+
readonly failedNames: string[];
|
|
114
|
+
/** How many directories are verifiably gone. */
|
|
115
|
+
readonly removedCount: number;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Options for {@link sweepHostLeftovers}.
|
|
119
|
+
*/
|
|
120
|
+
export interface SweepHostLeftoversOptions {
|
|
121
|
+
/** Names to keep regardless of age (e.g. the current run's own directories). */
|
|
122
|
+
readonly excludedNames?: readonly string[] | undefined;
|
|
123
|
+
/**
|
|
124
|
+
* How old a directory must be before it is removed. `0` removes every match.
|
|
125
|
+
*
|
|
126
|
+
* @default {@link DEFAULT_LEFTOVER_MAX_AGE_IN_MILLISECONDS}
|
|
127
|
+
*/
|
|
128
|
+
readonly maxAgeInMilliseconds?: number | undefined;
|
|
129
|
+
/**
|
|
130
|
+
* The roots to sweep. Defaults to the temp-vault root ({@link tmpdir}) and the
|
|
131
|
+
* owned user-data root (`<tmpdir>/{@link HARNESS_TEMP_DIR_NAME}`).
|
|
132
|
+
*/
|
|
133
|
+
readonly roots?: readonly LeftoverRoot[] | undefined;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Result of {@link sweepHostLeftovers}.
|
|
137
|
+
*/
|
|
138
|
+
export interface SweepHostLeftoversResult {
|
|
139
|
+
/** How many directories were selected for removal but could not be removed. */
|
|
140
|
+
readonly failedCount: number;
|
|
141
|
+
/** How many directories were removed. */
|
|
142
|
+
readonly removedCount: number;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Decides whether a leftover entry is old enough to be removed.
|
|
146
|
+
*
|
|
147
|
+
* The gate exists because every project on the machine shares one `tmpdir()`
|
|
148
|
+
* and desktop runs are not serialized, so a young directory may well belong to
|
|
149
|
+
* a run that is still in flight. An entry whose modification time is in the
|
|
150
|
+
* future (a clock skew) is treated as live for the same reason.
|
|
151
|
+
*
|
|
152
|
+
* @param params - The age comparison inputs.
|
|
153
|
+
* @returns `true` when the entry may be removed.
|
|
154
|
+
*/
|
|
155
|
+
export declare function checkIsLeftoverStale(params: CheckIsLeftoverStaleParams): boolean;
|
|
156
|
+
/**
|
|
157
|
+
* Selects the entry names that are the harness's own residue.
|
|
158
|
+
*
|
|
159
|
+
* Name-only, so the caller can filter a large directory listing before paying
|
|
160
|
+
* for a `stat` per entry, and so the Android sweep can feed it raw
|
|
161
|
+
* `adb shell ls` output.
|
|
162
|
+
*
|
|
163
|
+
* @param params - The names, prefixes, and exclusions.
|
|
164
|
+
* @returns The matching names, trimmed.
|
|
165
|
+
*/
|
|
166
|
+
export declare function filterLeftoverNames(params: FilterLeftoverNamesParams): string[];
|
|
167
|
+
/**
|
|
168
|
+
* Resolves the leftover age gate, applying the default when the option is
|
|
169
|
+
* omitted.
|
|
170
|
+
*
|
|
171
|
+
* @param options - The transport options.
|
|
172
|
+
* @returns The max age in milliseconds (`0` disables the gate).
|
|
173
|
+
*/
|
|
174
|
+
export declare function resolveLeftoverMaxAgeInMilliseconds(options: ObsidianTransportOptions | undefined): number;
|
|
175
|
+
/**
|
|
176
|
+
* Resolves whether leftover directories are swept, applying the default when
|
|
177
|
+
* the option is omitted.
|
|
178
|
+
*
|
|
179
|
+
* @param options - The transport options.
|
|
180
|
+
* @returns `true` when the sweeps should run.
|
|
181
|
+
*/
|
|
182
|
+
export declare function resolveShouldSweepLeftovers(options: ObsidianTransportOptions | undefined): boolean;
|
|
183
|
+
/**
|
|
184
|
+
* Removes the leftover vault directories a device is carrying, one directory at
|
|
185
|
+
* a time, and reports what is verifiably gone.
|
|
186
|
+
*
|
|
187
|
+
* **One directory per removal, and a failure is non-fatal.** Removing the whole
|
|
188
|
+
* set in a single `rm -rf` lets one un-removable entry decide the fate of every
|
|
189
|
+
* other: a name that the FUSE layer cannot express (an Android emulator can
|
|
190
|
+
* produce one — `rm -rf`, `find -delete` and force-stopping Obsidian first all
|
|
191
|
+
* answer `Operation not permitted`) is permanent, so a sweep that gives up on it
|
|
192
|
+
* gives up forever, and the residue only grows. Per-directory, that entry costs
|
|
193
|
+
* one warning per run instead of the whole sweep.
|
|
194
|
+
*
|
|
195
|
+
* **The result is measured, not assumed.** The directories are re-listed
|
|
196
|
+
* afterwards and only the ones that actually disappeared are counted, because
|
|
197
|
+
* the failure this was written for was a sweep that reported success while
|
|
198
|
+
* clearing nothing — a removal command can exit non-zero, or partially succeed,
|
|
199
|
+
* and neither is visible from its exit code alone.
|
|
200
|
+
*
|
|
201
|
+
* @param params - How to list and remove, and the base path to sweep.
|
|
202
|
+
* @returns The verified removal count and the names that survived.
|
|
203
|
+
*/
|
|
204
|
+
export declare function sweepDeviceLeftovers(params: SweepDeviceLeftoversParams): Promise<SweepDeviceLeftoversResult>;
|
|
205
|
+
/**
|
|
206
|
+
* Removes the host-side directories left behind by earlier runs.
|
|
207
|
+
*
|
|
208
|
+
* Best-effort throughout: an unreadable root, an entry that cannot be `stat`ed,
|
|
209
|
+
* and a directory that refuses to be removed (a live process still holding a
|
|
210
|
+
* handle answers `EPERM` on Windows) are all skipped rather than thrown, so a
|
|
211
|
+
* sweep can never fail the run it is cleaning up for.
|
|
212
|
+
*
|
|
213
|
+
* @param options - The sweep options.
|
|
214
|
+
* @returns How many directories were removed, and how many resisted removal.
|
|
215
|
+
*/
|
|
216
|
+
export declare function sweepHostLeftovers(options?: SweepHostLeftoversOptions): Promise<SweepHostLeftoversResult>;
|
package/dist/lib/cjs/library.cjs
CHANGED
|
@@ -21,7 +21,7 @@ __export(library_exports, {
|
|
|
21
21
|
LIBRARY_VERSION: () => LIBRARY_VERSION
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(library_exports);
|
|
24
|
-
const LIBRARY_VERSION = false ? "dev" : "9.
|
|
24
|
+
const LIBRARY_VERSION = false ? "dev" : "9.2.0";
|
|
25
25
|
// Annotate the CommonJS export names for ESM import in node:
|
|
26
26
|
0 && (module.exports = {
|
|
27
27
|
LIBRARY_VERSION
|