inspector-ng 0.0.6 → 0.0.7
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 +40 -0
- package/esm2022/lib/checkpoints.mjs +267 -0
- package/esm2022/lib/constants.mjs +2 -2
- package/esm2022/lib/inspector.component.mjs +69 -22
- package/esm2022/lib/types.mjs +1 -1
- package/esm2022/public-api.mjs +2 -1
- package/fesm2022/inspector-ng.mjs +333 -23
- package/fesm2022/inspector-ng.mjs.map +1 -1
- package/lib/checkpoints.d.ts +58 -0
- package/lib/constants.d.ts +1 -1
- package/lib/inspector.component.d.ts +14 -2
- package/lib/types.d.ts +4 -1
- package/package.json +4 -2
- package/public-api.d.ts +1 -0
package/README.md
CHANGED
|
@@ -56,6 +56,46 @@ That's it. Press **`M`** in your browser to open the inspector toolbar. No furth
|
|
|
56
56
|
|
|
57
57
|
## Configuration
|
|
58
58
|
|
|
59
|
+
### Developer checkpoints
|
|
60
|
+
|
|
61
|
+
Checkpoints save the current Angular Router URL plus state you explicitly register. They do **not** record or replay HTTP requests.
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
import { ApplicationConfig } from '@angular/core';
|
|
65
|
+
import { BehaviorSubject } from 'rxjs';
|
|
66
|
+
import {
|
|
67
|
+
createBehaviorSubjectCheckpointAdapter,
|
|
68
|
+
InspectorCheckpointRegistry,
|
|
69
|
+
provideInspectorCheckpoints,
|
|
70
|
+
} from 'inspector-ng';
|
|
71
|
+
|
|
72
|
+
export const appConfig: ApplicationConfig = {
|
|
73
|
+
providers: [provideInspectorCheckpoints()],
|
|
74
|
+
};
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Register serializable state from an application service or component:
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
const application = new BehaviorSubject({ customerName: '', amount: 0 });
|
|
81
|
+
const unregister = checkpointRegistry.register(
|
|
82
|
+
createBehaviorSubjectCheckpointAdapter('workflow:application', application),
|
|
83
|
+
);
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Open the inspector and use the checkpoint button to save, restore, rename, or delete snapshots. Checkpoints use `localStorage`; when the browser quota is reached, the oldest checkpoint is removed to make room. Do not register sensitive values.
|
|
87
|
+
|
|
88
|
+
For Native Federation, the shell owns `provideInspectorCheckpoints()`. Remotes receive the shell's `InspectorCheckpointRegistry` and register namespaced adapters such as `workflow:application`. The shell should register a remote loader for each scope so remotes are loaded before state is restored:
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
checkpointRegistry.registerRemoteScope('workflow', async () => {
|
|
92
|
+
const remote = await loadRemoteModule('workflow', './CheckpointAdapters');
|
|
93
|
+
remote.registerInspectorCheckpointAdapters(checkpointRegistry);
|
|
94
|
+
});
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Repeated remote adapter registration is safe, so a bridge may run before every restore. Share `inspector-ng` as a Native Federation singleton in both shell and remotes.
|
|
98
|
+
|
|
59
99
|
### Inputs
|
|
60
100
|
|
|
61
101
|
| Input | Type | Default | Description |
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import { Injectable, Inject, PLATFORM_ID, computed, signal } from '@angular/core';
|
|
2
|
+
import { isPlatformBrowser } from '@angular/common';
|
|
3
|
+
import { Router } from '@angular/router';
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
import * as i1 from "@angular/router";
|
|
6
|
+
const STORAGE_KEY = 'inspector-checkpoints-v1';
|
|
7
|
+
export class InspectorCheckpointRegistry {
|
|
8
|
+
constructor(platformId, router) {
|
|
9
|
+
this.router = router;
|
|
10
|
+
this.checkpoints = signal([]);
|
|
11
|
+
this.isBusy = signal(false);
|
|
12
|
+
this.error = signal(null);
|
|
13
|
+
this.warning = signal(null);
|
|
14
|
+
this.totalBytes = computed(() => this.checkpoints().reduce((total, checkpoint) => total + checkpoint.sizeBytes, 0));
|
|
15
|
+
this.adapters = new Map();
|
|
16
|
+
this.remoteLoaders = new Map();
|
|
17
|
+
this.isCheckpoint = (value) => {
|
|
18
|
+
if (!value || typeof value !== 'object')
|
|
19
|
+
return false;
|
|
20
|
+
const checkpoint = value;
|
|
21
|
+
return checkpoint.version === 1 && typeof checkpoint.id === 'string' &&
|
|
22
|
+
typeof checkpoint.name === 'string' && typeof checkpoint.url === 'string' &&
|
|
23
|
+
typeof checkpoint.createdAt === 'string' && Array.isArray(checkpoint.scopes) &&
|
|
24
|
+
!!checkpoint.state && typeof checkpoint.state === 'object' && typeof checkpoint.sizeBytes === 'number';
|
|
25
|
+
};
|
|
26
|
+
this.isBrowser = isPlatformBrowser(platformId);
|
|
27
|
+
this.hydrate();
|
|
28
|
+
}
|
|
29
|
+
register(adapter) {
|
|
30
|
+
if (!adapter.id.includes(':')) {
|
|
31
|
+
throw new Error('Checkpoint adapter IDs must be namespaced (for example, workflow:application).');
|
|
32
|
+
}
|
|
33
|
+
if (this.adapters.has(adapter.id)) {
|
|
34
|
+
// Remote bridge loaders can run more than once across checkpoint restores.
|
|
35
|
+
// Treat repeated registration as idempotent so a loaded remote stays usable.
|
|
36
|
+
return () => undefined;
|
|
37
|
+
}
|
|
38
|
+
this.adapters.set(adapter.id, adapter);
|
|
39
|
+
return () => this.adapters.delete(adapter.id);
|
|
40
|
+
}
|
|
41
|
+
registerRemoteScope(scope, loader) {
|
|
42
|
+
this.remoteLoaders.set(scope, loader);
|
|
43
|
+
return () => this.remoteLoaders.delete(scope);
|
|
44
|
+
}
|
|
45
|
+
async save(name) {
|
|
46
|
+
this.error.set(null);
|
|
47
|
+
if (!this.isBrowser) {
|
|
48
|
+
this.error.set('Checkpoints are only available in a browser.');
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
this.isBusy.set(true);
|
|
52
|
+
try {
|
|
53
|
+
const state = {};
|
|
54
|
+
for (const adapter of this.adapters.values()) {
|
|
55
|
+
state[adapter.id] = this.cloneValue(await adapter.capture(), adapter.id);
|
|
56
|
+
}
|
|
57
|
+
const createdAt = new Date().toISOString();
|
|
58
|
+
const checkpoint = {
|
|
59
|
+
version: 1,
|
|
60
|
+
id: this.createId(),
|
|
61
|
+
name: name?.trim() || this.nextAutomaticName(this.routePath(this.router.url)),
|
|
62
|
+
url: this.router.url,
|
|
63
|
+
createdAt,
|
|
64
|
+
scopes: this.getScopes(Object.keys(state)),
|
|
65
|
+
state,
|
|
66
|
+
sizeBytes: 0,
|
|
67
|
+
};
|
|
68
|
+
checkpoint.sizeBytes = this.sizeOf(checkpoint);
|
|
69
|
+
this.persistWithEviction([checkpoint, ...this.checkpoints()]);
|
|
70
|
+
return this.checkpoints().find((item) => item.id === checkpoint.id) ?? null;
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
this.error.set(this.messageFor(error, 'Unable to save checkpoint.'));
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
finally {
|
|
77
|
+
this.isBusy.set(false);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
async restore(id) {
|
|
81
|
+
const checkpoint = this.checkpoints().find((item) => item.id === id);
|
|
82
|
+
this.error.set(null);
|
|
83
|
+
this.warning.set(null);
|
|
84
|
+
if (!checkpoint) {
|
|
85
|
+
this.error.set('Checkpoint not found.');
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
this.isBusy.set(true);
|
|
89
|
+
try {
|
|
90
|
+
for (const scope of checkpoint.scopes) {
|
|
91
|
+
const loader = this.remoteLoaders.get(scope);
|
|
92
|
+
if (loader) {
|
|
93
|
+
await loader();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
const missing = [];
|
|
97
|
+
for (const [adapterId, value] of Object.entries(checkpoint.state)) {
|
|
98
|
+
const adapter = this.adapters.get(adapterId);
|
|
99
|
+
if (!adapter) {
|
|
100
|
+
missing.push(adapterId);
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
await adapter.restore(this.cloneValue(value, adapterId));
|
|
104
|
+
}
|
|
105
|
+
if (missing.length) {
|
|
106
|
+
this.warning.set(`Skipped ${missing.length} unavailable adapter${missing.length === 1 ? '' : 's'}: ${missing.join(', ')}.`);
|
|
107
|
+
}
|
|
108
|
+
await this.router.navigateByUrl(checkpoint.url);
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
this.error.set(this.messageFor(error, 'Unable to restore checkpoint.'));
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
finally {
|
|
116
|
+
this.isBusy.set(false);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
rename(id, name) {
|
|
120
|
+
const nextName = name.trim();
|
|
121
|
+
if (!nextName) {
|
|
122
|
+
this.error.set('A checkpoint name is required.');
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
this.error.set(null);
|
|
126
|
+
const next = this.checkpoints().map((checkpoint) => checkpoint.id === id ? { ...checkpoint, name: nextName } : checkpoint);
|
|
127
|
+
this.persistWithEviction(next);
|
|
128
|
+
}
|
|
129
|
+
delete(id) {
|
|
130
|
+
this.error.set(null);
|
|
131
|
+
this.persistWithEviction(this.checkpoints().filter((checkpoint) => checkpoint.id !== id));
|
|
132
|
+
}
|
|
133
|
+
hydrate() {
|
|
134
|
+
if (!this.isBrowser) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
try {
|
|
138
|
+
const raw = window.localStorage.getItem(STORAGE_KEY);
|
|
139
|
+
if (!raw)
|
|
140
|
+
return;
|
|
141
|
+
const parsed = JSON.parse(raw);
|
|
142
|
+
if (!Array.isArray(parsed))
|
|
143
|
+
return;
|
|
144
|
+
const checkpoints = parsed.filter(this.isCheckpoint);
|
|
145
|
+
const normalized = this.normalizeLegacyNames(checkpoints);
|
|
146
|
+
const sorted = normalized.checkpoints.sort((a, b) => b.createdAt.localeCompare(a.createdAt) || b.id.localeCompare(a.id));
|
|
147
|
+
this.checkpoints.set(sorted);
|
|
148
|
+
if (normalized.changed) {
|
|
149
|
+
window.localStorage.setItem(STORAGE_KEY, JSON.stringify(sorted));
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
this.warning.set('Saved checkpoints could not be read and were ignored.');
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
persistWithEviction(checkpoints) {
|
|
157
|
+
if (!this.isBrowser)
|
|
158
|
+
return;
|
|
159
|
+
let candidate = checkpoints;
|
|
160
|
+
while (true) {
|
|
161
|
+
try {
|
|
162
|
+
window.localStorage.setItem(STORAGE_KEY, JSON.stringify(candidate));
|
|
163
|
+
this.checkpoints.set(candidate);
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
if (!this.isQuotaError(error) || candidate.length === 0) {
|
|
168
|
+
throw error;
|
|
169
|
+
}
|
|
170
|
+
candidate = candidate.slice(0, -1);
|
|
171
|
+
this.warning.set('Storage was full; the oldest checkpoint was removed.');
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
cloneValue(value, adapterId) {
|
|
176
|
+
try {
|
|
177
|
+
const serialized = JSON.stringify(value);
|
|
178
|
+
if (serialized === undefined)
|
|
179
|
+
throw new Error('undefined values are not supported');
|
|
180
|
+
return JSON.parse(serialized);
|
|
181
|
+
}
|
|
182
|
+
catch {
|
|
183
|
+
throw new Error(`Adapter "${adapterId}" returned a value that cannot be JSON serialized.`);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
getScopes(adapterIds) {
|
|
187
|
+
return [...new Set(adapterIds.map((id) => id.split(':', 1)[0]))];
|
|
188
|
+
}
|
|
189
|
+
routePath(url) {
|
|
190
|
+
return url.split(/[?#]/, 1)[0] || '/';
|
|
191
|
+
}
|
|
192
|
+
nextAutomaticName(route, usedNames = new Set(this.checkpoints().map(({ name }) => name))) {
|
|
193
|
+
if (!usedNames.has(route))
|
|
194
|
+
return route;
|
|
195
|
+
for (let suffix = 2;; suffix += 1) {
|
|
196
|
+
const candidate = `${route} ${suffix}`;
|
|
197
|
+
if (!usedNames.has(candidate))
|
|
198
|
+
return candidate;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
normalizeLegacyNames(checkpoints) {
|
|
202
|
+
const legacyIds = new Set(checkpoints.filter((checkpoint) => this.isLegacyAutomaticName(checkpoint)).map(({ id }) => id));
|
|
203
|
+
if (!legacyIds.size)
|
|
204
|
+
return { checkpoints, changed: false };
|
|
205
|
+
const usedNames = new Set(checkpoints.filter(({ id }) => !legacyIds.has(id)).map(({ name }) => name));
|
|
206
|
+
const names = new Map();
|
|
207
|
+
const oldestFirst = checkpoints
|
|
208
|
+
.filter(({ id }) => legacyIds.has(id))
|
|
209
|
+
.sort((a, b) => a.createdAt.localeCompare(b.createdAt) || a.id.localeCompare(b.id));
|
|
210
|
+
for (const checkpoint of oldestFirst) {
|
|
211
|
+
const name = this.nextAutomaticName(this.routePath(checkpoint.url), usedNames);
|
|
212
|
+
names.set(checkpoint.id, name);
|
|
213
|
+
usedNames.add(name);
|
|
214
|
+
}
|
|
215
|
+
return {
|
|
216
|
+
checkpoints: checkpoints.map((checkpoint) => names.has(checkpoint.id) ? { ...checkpoint, name: names.get(checkpoint.id) } : checkpoint),
|
|
217
|
+
changed: true,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
isLegacyAutomaticName(checkpoint) {
|
|
221
|
+
const route = this.routePath(checkpoint.url);
|
|
222
|
+
const prefix = `${route} · `;
|
|
223
|
+
if (!checkpoint.name.startsWith(prefix))
|
|
224
|
+
return false;
|
|
225
|
+
const timestamp = checkpoint.name.slice(prefix.length);
|
|
226
|
+
if (timestamp === new Date(checkpoint.createdAt).toLocaleString())
|
|
227
|
+
return true;
|
|
228
|
+
const parsedTimestamp = Date.parse(timestamp);
|
|
229
|
+
const createdTimestamp = Date.parse(checkpoint.createdAt);
|
|
230
|
+
return Number.isFinite(parsedTimestamp) && Number.isFinite(createdTimestamp) &&
|
|
231
|
+
Math.abs(parsedTimestamp - createdTimestamp) < 1000;
|
|
232
|
+
}
|
|
233
|
+
createId() {
|
|
234
|
+
return `checkpoint-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
|
|
235
|
+
}
|
|
236
|
+
sizeOf(checkpoint) {
|
|
237
|
+
return new Blob([JSON.stringify(checkpoint)]).size;
|
|
238
|
+
}
|
|
239
|
+
isQuotaError(error) {
|
|
240
|
+
return error instanceof DOMException && (error.name === 'QuotaExceededError' || error.name === 'NS_ERROR_DOM_QUOTA_REACHED');
|
|
241
|
+
}
|
|
242
|
+
messageFor(error, fallback) {
|
|
243
|
+
return error instanceof Error ? error.message : fallback;
|
|
244
|
+
}
|
|
245
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: InspectorCheckpointRegistry, deps: [{ token: PLATFORM_ID }, { token: Router }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
246
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: InspectorCheckpointRegistry }); }
|
|
247
|
+
}
|
|
248
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: InspectorCheckpointRegistry, decorators: [{
|
|
249
|
+
type: Injectable
|
|
250
|
+
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
251
|
+
type: Inject,
|
|
252
|
+
args: [PLATFORM_ID]
|
|
253
|
+
}] }, { type: i1.Router, decorators: [{
|
|
254
|
+
type: Inject,
|
|
255
|
+
args: [Router]
|
|
256
|
+
}] }] });
|
|
257
|
+
export function provideInspectorCheckpoints() {
|
|
258
|
+
return [InspectorCheckpointRegistry];
|
|
259
|
+
}
|
|
260
|
+
export function createBehaviorSubjectCheckpointAdapter(id, subject) {
|
|
261
|
+
return {
|
|
262
|
+
id,
|
|
263
|
+
capture: () => subject.value,
|
|
264
|
+
restore: (value) => subject.next(value),
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hlY2twb2ludHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9pbnNwZWN0b3Itbmcvc3JjL2xpYi9jaGVja3BvaW50cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxXQUFXLEVBQVksUUFBUSxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUM1RixPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNwRCxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0saUJBQWlCLENBQUM7OztBQThCekMsTUFBTSxXQUFXLEdBQUcsMEJBQTBCLENBQUM7QUFHL0MsTUFBTSxPQUFPLDJCQUEyQjtJQWF0QyxZQUN1QixVQUFrQixFQUNOLE1BQWM7UUFBZCxXQUFNLEdBQU4sTUFBTSxDQUFRO1FBZHhDLGdCQUFXLEdBQUcsTUFBTSxDQUF3QixFQUFFLENBQUMsQ0FBQztRQUNoRCxXQUFNLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3ZCLFVBQUssR0FBRyxNQUFNLENBQWdCLElBQUksQ0FBQyxDQUFDO1FBQ3BDLFlBQU8sR0FBRyxNQUFNLENBQWdCLElBQUksQ0FBQyxDQUFDO1FBQ3RDLGVBQVUsR0FBRyxRQUFRLENBQUMsR0FBRyxFQUFFLENBQ2xDLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxLQUFLLEVBQUUsVUFBVSxFQUFFLEVBQUUsQ0FBQyxLQUFLLEdBQUcsVUFBVSxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUMsQ0FDbEYsQ0FBQztRQUVlLGFBQVEsR0FBRyxJQUFJLEdBQUcsRUFBc0MsQ0FBQztRQUN6RCxrQkFBYSxHQUFHLElBQUksR0FBRyxFQUEyQyxDQUFDO1FBMlA1RSxpQkFBWSxHQUFHLENBQUMsS0FBYyxFQUFnQyxFQUFFO1lBQ3RFLElBQUksQ0FBQyxLQUFLLElBQUksT0FB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OzswQkFlTixNQUFNOzJCQUFDLFdBQVc7OzBCQUNsQixNQUFNOzJCQUFDLE1BQU07O0FBZ1FsQixNQUFNLFVBQVUsMkJBQTJCO0lBQ3pDLE9BQU8sQ0FBQywyQkFBMkIsQ0FBQyxDQUFDO0FBQ3ZDLENBQUM7QUFFRCxNQUFNLFVBQVUsc0NBQXNDLENBQ3BELEVBQVUsRUFDVixPQUEyQjtJQUUzQixPQUFPO1FBQ0wsRUFBRTtRQUNGLE9BQU8sRUFBRSxHQUFHLEVBQUUsQ0FBQyxPQUFPLENBQUMsS0FBNEM7UUFDbkUsT0FBTyxFQUFFLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQVUsQ0FBQztLQUM3QyxDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUsIEluamVjdCwgUExBVEZPUk1fSUQsIFByb3ZpZGVyLCBjb21wdXRlZCwgc2lnbmFsIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBpc1BsYXRmb3JtQnJvd3NlciB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBSb3V0ZXIgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuaW1wb3J0IHsgQmVoYXZpb3JTdWJqZWN0IH0gZnJvbSAncnhqcyc7XG5cbmV4cG9ydCB0eXBlIEluc3BlY3RvckNoZWNrcG9pbnRWYWx1ZSA9XG4gIHwgc3RyaW5nXG4gIHwgbnVtYmVyXG4gIHwgYm9vbGVhblxuICB8IG51bGxcbiAgfCBJbnNwZWN0b3JDaGVja3BvaW50VmFsdWVbXVxuICB8IHsgW2tleTogc3RyaW5nXTogSW5zcGVjdG9yQ2hlY2twb2ludFZhbHVlIH07XG5cbmV4cG9ydCBpbnRlcmZhY2UgSW5zcGVjdG9yQ2hlY2twb2ludEFkYXB0ZXIge1xuICBpZDogc3RyaW5nO1xuICBjYXB0dXJlKCk6IEluc3BlY3RvckNoZWNrcG9pbnRWYWx1ZSB8IFByb21pc2U8SW5zcGVjdG9yQ2hlY2twb2ludFZhbHVlPjtcbiAgcmVzdG9yZSh2YWx1ZTogSW5zcGVjdG9yQ2hlY2twb2ludFZhbHVlKTogdm9pZCB8IFByb21pc2U8dm9pZD47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSW5zcGVjdG9yQ2hlY2twb2ludCB7XG4gIHZlcnNpb246IDE7XG4gIGlkOiBzdHJpbmc7XG4gIG5hbWU6IHN0cmluZztcbiAgdXJsOiBzdHJpbmc7XG4gIGNyZWF0ZWRBdDogc3RyaW5nO1xuICBzY29wZXM6IHN0cmluZ1tdO1xuICBzdGF0ZTogUmVjb3JkPHN0cmluZywgSW5zcGVjdG9yQ2hlY2twb2ludFZhbHVlPjtcbiAgc2l6ZUJ5dGVzOiBudW1iZXI7XG59XG5cbmV4cG9ydCB0eXBlIEluc3BlY3RvckNoZWNrcG9pbnRSZW1vdGVMb2FkZXIgPSAoKSA9PiB2b2lkIHwgUHJvbWlzZTx2b2lkPjtcblxuY29uc3QgU1RPUkFHRV9LRVkgPSAnaW5zcGVjdG9yLWNoZWNrcG9pbnRzLXYxJztcblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIEluc3BlY3RvckNoZWNrcG9pbnRSZWdpc3RyeSB7XG4gIHJlYWRvbmx5IGNoZWNrcG9pbnRzID0gc2lnbmFsPEluc3BlY3RvckNoZWNrcG9pbnRbXT4oW10pO1xuICByZWFkb25seSBpc0J1c3kgPSBzaWduYWwoZmFsc2UpO1xuICByZWFkb25seSBlcnJvciA9IHNpZ25hbDxzdHJpbmcgfCBudWxsPihudWxsKTtcbiAgcmVhZG9ubHkgd2FybmluZyA9IHNpZ25hbDxzdHJpbmcgfCBudWxsPihudWxsKTtcbiAgcmVhZG9ubHkgdG90YWxCeXRlcyA9IGNvbXB1dGVkKCgpID0+XG4gICAgdGhpcy5jaGVja3BvaW50cygpLnJlZHVjZSgodG90YWwsIGNoZWNrcG9pbnQpID0+IHRvdGFsICsgY2hlY2twb2ludC5zaXplQnl0ZXMsIDApLFxuICApO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgYWRhcHRlcnMgPSBuZXcgTWFwPHN0cmluZywgSW5zcGVjdG9yQ2hlY2twb2ludEFkYXB0ZXI+KCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgcmVtb3RlTG9hZGVycyA9IG5ldyBNYXA8c3RyaW5nLCBJbnNwZWN0b3JDaGVja3BvaW50UmVtb3RlTG9hZGVyPigpO1xuICBwcml2YXRlIHJlYWRvbmx5IGlzQnJvd3NlcjogYm9vbGVhbjtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBASW5qZWN0KFBMQVRGT1JNX0lEKSBwbGF0Zm9ybUlkOiBvYmplY3QsXG4gICAgQEluamVjdChSb3V0ZXIpIHByaXZhdGUgcmVhZG9ubHkgcm91dGVyOiBSb3V0ZXIsXG4gICkge1xuICAgIHRoaXMuaXNCcm93c2VyID0gaXNQbGF0Zm9ybUJyb3dzZXIocGxhdGZvcm1JZCk7XG4gICAgdGhpcy5oeWRyYXRlKCk7XG4gIH1cblxuICByZWdpc3RlcihhZGFwdGVyOiBJbnNwZWN0b3JDaGVja3BvaW50QWRhcHRlcik6ICgpID0+IHZvaWQge1xuICAgIGlmICghYWRhcHRlci5pZC5pbmNsdWRlcygnOicpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NoZWNrcG9pbnQgYWRhcHRlciBJRHMgbXVzdCBiZSBuYW1lc3BhY2VkIChmb3IgZXhhbXBsZSwgd29ya2Zsb3c6YXBwbGljYXRpb24pLicpO1xuICAgIH1cbiAgICBpZiAodGhpcy5hZGFwdGVycy5oYXMoYWRhcHRlci5pZCkpIHtcbiAgICAgIC8vIFJlbW90ZSBicmlkZ2UgbG9hZGVycyBjYW4gcnVuIG1vcmUgdGhhbiBvbmNlIGFjcm9zcyBjaGVja3BvaW50IHJlc3RvcmVzLlxuICAgICAgLy8gVHJlYXQgcmVwZWF0ZWQgcmVnaXN0cmF0aW9uIGFzIGlkZW1wb3RlbnQgc28gYSBsb2FkZWQgcmVtb3RlIHN0YXlzIHVzYWJsZS5cbiAgICAgIHJldHVybiAoKSA9PiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIHRoaXMuYWRhcHRlcnMuc2V0KGFkYXB0ZXIuaWQsIGFkYXB0ZXIpO1xuICAgIHJldHVybiAoKSA9PiB0aGlzLmFkYXB0ZXJzLmRlbGV0ZShhZGFwdGVyLmlkKTtcbiAgfVxuXG4gIHJlZ2lzdGVyUmVtb3RlU2NvcGUoc2NvcGU6IHN0cmluZywgbG9hZGVyOiBJbnNwZWN0b3JDaGVja3BvaW50UmVtb3RlTG9hZGVyKTogKCkgPT4gdm9pZCB7XG4gICAgdGhpcy5yZW1vdGVMb2FkZXJzLnNldChzY29wZSwgbG9hZGVyKTtcbiAgICByZXR1cm4gKCkgPT4gdGhpcy5yZW1vdGVMb2FkZXJzLmRlbGV0ZShzY29wZSk7XG4gIH1cblxuICBhc3luYyBzYXZlKG5hbWU/OiBzdHJpbmcpOiBQcm9taXNlPEluc3BlY3RvckNoZWNrcG9pbnQgfCBudWxsPiB7XG4gICAgdGhpcy5lcnJvci5zZXQobnVsbCk7XG4gICAgaWYgKCF0aGlzLmlzQnJvd3Nlcikge1xuICAgICAgdGhpcy5lcnJvci5zZXQoJ0NoZWNrcG9pbnRzIGFyZSBvbmx5IGF2YWlsYWJsZSBpbiBhIGJyb3dzZXIuJyk7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB0aGlzLmlzQnVzeS5zZXQodHJ1ZSk7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHN0YXRlOiBSZWNvcmQ8c3RyaW5nLCBJbnNwZWN0b3JDaGVja3BvaW50VmFsdWU+ID0ge307XG4gICAgICBmb3IgKGNvbnN0IGFkYXB0ZXIgb2YgdGhpcy5hZGFwdGVycy52YWx1ZXMoKSkge1xuICAgICAgICBzdGF0ZVthZGFwdGVyLmlkXSA9IHRoaXMuY2xvbmVWYWx1ZShhd2FpdCBhZGFwdGVyLmNhcHR1cmUoKSwgYWRhcHRlci5pZCk7XG4gICAgICB9XG4gICAgICBjb25zdCBjcmVhdGVkQXQgPSBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCk7XG4gICAgICBjb25zdCBjaGVja3BvaW50OiBJbnNwZWN0b3JDaGVja3BvaW50ID0ge1xuICAgICAgICB2ZXJzaW9uOiAxLFxuICAgICAgICBpZDogdGhpcy5jcmVhdGVJZCgpLFxuICAgICAgICBuYW1lOiBuYW1lPy50cmltKCkgfHwgdGhpcy5uZXh0QXV0b21hdGljTmFtZSh0aGlzLnJvdXRlUGF0aCh0aGlzLnJvdXRlci51cmwpKSxcbiAgICAgICAgdXJsOiB0aGlzLnJvdXRlci51cmwsXG4gICAgICAgIGNyZWF0ZWRBdCxcbiAgICAgICAgc2NvcGVzOiB0aGlzLmdldFNjb3BlcyhPYmplY3Qua2V5cyhzdGF0ZSkpLFxuICAgICAgICBzdGF0ZSxcbiAgICAgICAgc2l6ZUJ5dGVzOiAwLFxuICAgICAgfTtcbiAgICAgIGNoZWNrcG9pbnQuc2l6ZUJ5dGVzID0gdGhpcy5zaXplT2YoY2hlY2twb2ludCk7XG4gICAgICB0aGlzLnBlcnNpc3RXaXRoRXZpY3Rpb24oW2NoZWNrcG9pbnQsIC4uLnRoaXMuY2hlY2twb2ludHMoKV0pO1xuICAgICAgcmV0dXJuIHRoaXMuY2hlY2twb2ludHMoKS5maW5kKChpdGVtKSA9PiBpdGVtLmlkID09PSBjaGVja3BvaW50LmlkKSA/PyBudWxsO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aGlzLmVycm9yLnNldCh0aGlzLm1lc3NhZ2VGb3IoZXJyb3IsICdVbmFibGUgdG8gc2F2ZSBjaGVja3BvaW50LicpKTtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH0gZmluYWxseSB7XG4gICAgICB0aGlzLmlzQnVzeS5zZXQoZmFsc2UpO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIHJlc3RvcmUoaWQ6IHN0cmluZyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGNvbnN0IGNoZWNrcG9pbnQgPSB0aGlzLmNoZWNrcG9pbnRzKCkuZmluZCgoaXRlbSkgPT4gaXRlbS5pZCA9PT0gaWQpO1xuICAgIHRoaXMuZXJyb3Iuc2V0KG51bGwpO1xuICAgIHRoaXMud2FybmluZy5zZXQobnVsbCk7XG4gICAgaWYgKCFjaGVja3BvaW50KSB7XG4gICAgICB0aGlzLmVycm9yLnNldCgnQ2hlY2twb2ludCBub3QgZm91bmQuJyk7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgdGhpcy5pc0J1c3kuc2V0KHRydWUpO1xuICAgIHRyeSB7XG4gICAgICBmb3IgKGNvbnN0IHNjb3BlIG9mIGNoZWNrcG9pbnQuc2NvcGVzKSB7XG4gICAgICAgIGNvbnN0IGxvYWRlciA9IHRoaXMucmVtb3RlTG9hZGVycy5nZXQoc2NvcGUpO1xuICAgICAgICBpZiAobG9hZGVyKSB7XG4gICAgICAgICAgYXdhaXQgbG9hZGVyKCk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY29uc3QgbWlzc2luZzogc3RyaW5nW10gPSBbXTtcbiAgICAgIGZvciAoY29uc3QgW2FkYXB0ZXJJZCwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKGNoZWNrcG9pbnQuc3RhdGUpKSB7XG4gICAgICAgIGNvbnN0IGFkYXB0ZXIgPSB0aGlzLmFkYXB0ZXJzLmdldChhZGFwdGVySWQpO1xuICAgICAgICBpZiAoIWFkYXB0ZXIpIHtcbiAgICAgICAgICBtaXNzaW5nLnB1c2goYWRhcHRlcklkKTtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBhd2FpdCBhZGFwdGVyLnJlc3RvcmUodGhpcy5jbG9uZVZhbHVlKHZhbHVlLCBhZGFwdGVySWQpKTtcbiAgICAgIH1cbiAgICAgIGlmIChtaXNzaW5nLmxlbmd0aCkge1xuICAgICAgICB0aGlzLndhcm5pbmcuc2V0KGBTa2lwcGVkICR7bWlzc2luZy5sZW5ndGh9IHVuYXZhaWxhYmxlIGFkYXB0ZXIke21pc3NpbmcubGVuZ3RoID09PSAxID8gJycgOiAncyd9OiAke21pc3Npbmcuam9pbignLCAnKX0uYCk7XG4gICAgICB9XG4gICAgICBhd2FpdCB0aGlzLnJvdXRlci5uYXZpZ2F0ZUJ5VXJsKGNoZWNrcG9pbnQudXJsKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aGlzLmVycm9yLnNldCh0aGlzLm1lc3NhZ2VGb3IoZXJyb3IsICdVbmFibGUgdG8gcmVzdG9yZSBjaGVja3BvaW50LicpKTtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgdGhpcy5pc0J1c3kuc2V0KGZhbHNlKTtcbiAgICB9XG4gIH1cblxuICByZW5hbWUoaWQ6IHN0cmluZywgbmFtZTogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgbmV4dE5hbWUgPSBuYW1lLnRyaW0oKTtcbiAgICBpZiAoIW5leHROYW1lKSB7XG4gICAgICB0aGlzLmVycm9yLnNldCgnQSBjaGVja3BvaW50IG5hbWUgaXMgcmVxdWlyZWQuJyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuZXJyb3Iuc2V0KG51bGwpO1xuICAgIGNvbnN0IG5leHQgPSB0aGlzLmNoZWNrcG9pbnRzKCkubWFwKChjaGVja3BvaW50KSA9PlxuICAgICAgY2hlY2twb2ludC5pZCA9PT0gaWQgPyB7IC4uLmNoZWNrcG9pbnQsIG5hbWU6IG5leHROYW1lIH0gOiBjaGVja3BvaW50LFxuICAgICk7XG4gICAgdGhpcy5wZXJzaXN0V2l0aEV2aWN0aW9uKG5leHQpO1xuICB9XG5cbiAgZGVsZXRlKGlkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLmVycm9yLnNldChudWxsKTtcbiAgICB0aGlzLnBlcnNpc3RXaXRoRXZpY3Rpb24odGhpcy5jaGVja3BvaW50cygpLmZpbHRlcigoY2hlY2twb2ludCkgPT4gY2hlY2twb2ludC5pZCAhPT0gaWQpKTtcbiAgfVxuXG4gIHByaXZhdGUgaHlkcmF0ZSgpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuaXNCcm93c2VyKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICBjb25zdCByYXcgPSB3aW5kb3cubG9jYWxTdG9yYWdlLmdldEl0ZW0oU1RPUkFHRV9LRVkpO1xuICAgICAgaWYgKCFyYXcpIHJldHVybjtcbiAgICAgIGNvbnN0IHBhcnNlZCA9IEpTT04ucGFyc2UocmF3KSBhcyB1bmtub3duO1xuICAgICAgaWYgKCFBcnJheS5pc0FycmF5KHBhcnNlZCkpIHJldHVybjtcbiAgICAgIGNvbnN0IGNoZWNrcG9pbnRzID0gcGFyc2VkLmZpbHRlcih0aGlzLmlzQ2hlY2twb2ludCk7XG4gICAgICBjb25zdCBub3JtYWxpemVkID0gdGhpcy5ub3JtYWxpemVMZWdhY3lOYW1lcyhjaGVja3BvaW50cyk7XG4gICAgICBjb25zdCBzb3J0ZWQgPSBub3JtYWxpemVkLmNoZWNrcG9pbnRzLnNvcnQoKGEsIGIpID0+XG4gICAgICAgIGIuY3JlYXRlZEF0LmxvY2FsZUNvbXBhcmUoYS5jcmVhdGVkQXQpIHx8IGIuaWQubG9jYWxlQ29tcGFyZShhLmlkKVxuICAgICAgKTtcbiAgICAgIHRoaXMuY2hlY2twb2ludHMuc2V0KHNvcnRlZCk7XG4gICAgICBpZiAobm9ybWFsaXplZC5jaGFuZ2VkKSB7XG4gICAgICAgIHdpbmRvdy5sb2NhbFN0b3JhZ2Uuc2V0SXRlbShTVE9SQUdFX0tFWSwgSlNPTi5zdHJpbmdpZnkoc29ydGVkKSk7XG4gICAgICB9XG4gICAgfSBjYXRjaCB7XG4gICAgICB0aGlzLndhcm5pbmcuc2V0KCdTYXZlZCBjaGVja3BvaW50cyBjb3VsZCBub3QgYmUgcmVhZCBhbmQgd2VyZSBpZ25vcmVkLicpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgcGVyc2lzdFdpdGhFdmljdGlvbihjaGVja3BvaW50czogSW5zcGVjdG9yQ2hlY2twb2ludFtdKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmlzQnJvd3NlcikgcmV0dXJuO1xuICAgIGxldCBjYW5kaWRhdGUgPSBjaGVja3BvaW50cztcbiAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgd2luZG93LmxvY2FsU3RvcmFnZS5zZXRJdGVtKFNUT1JBR0VfS0VZLCBKU09OLnN0cmluZ2lmeShjYW5kaWRhdGUpKTtcbiAgICAgICAgdGhpcy5jaGVja3BvaW50cy5zZXQoY2FuZGlkYXRlKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgaWYgKCF0aGlzLmlzUXVvdGFFcnJvcihlcnJvcikgfHwgY2FuZGlkYXRlLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9XG4gICAgICAgIGNhbmRpZGF0ZSA9IGNhbmRpZGF0ZS5zbGljZSgwLCAtMSk7XG4gICAgICAgIHRoaXMud2FybmluZy5zZXQoJ1N0b3JhZ2Ugd2FzIGZ1bGw7IHRoZSBvbGRlc3QgY2hlY2twb2ludCB3YXMgcmVtb3ZlZC4nKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGNsb25lVmFsdWUodmFsdWU6IHVua25vd24sIGFkYXB0ZXJJZDogc3RyaW5nKTogSW5zcGVjdG9yQ2hlY2twb2ludFZhbHVlIHtcbiAgICB0cnkge1xuICAgICAgY29uc3Qgc2VyaWFsaXplZCA9IEpTT04uc3RyaW5naWZ5KHZhbHVlKTtcbiAgICAgIGlmIChzZXJpYWxpemVkID09PSB1bmRlZmluZWQpIHRocm93IG5ldyBFcnJvcigndW5kZWZpbmVkIHZhbHVlcyBhcmUgbm90IHN1cHBvcnRlZCcpO1xuICAgICAgcmV0dXJuIEpTT04ucGFyc2Uoc2VyaWFsaXplZCkgYXMgSW5zcGVjdG9yQ2hlY2twb2ludFZhbHVlO1xuICAgIH0gY2F0Y2gge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBBZGFwdGVyIFwiJHthZGFwdGVySWR9XCIgcmV0dXJuZWQgYSB2YWx1ZSB0aGF0IGNhbm5vdCBiZSBKU09OIHNlcmlhbGl6ZWQuYCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZXRTY29wZXMoYWRhcHRlcklkczogc3RyaW5nW10pOiBzdHJpbmdbXSB7XG4gICAgcmV0dXJuIFsuLi5uZXcgU2V0KGFkYXB0ZXJJZHMubWFwKChpZCkgPT4gaWQuc3BsaXQoJzonLCAxKVswXSkpXTtcbiAgfVxuXG4gIHByaXZhdGUgcm91dGVQYXRoKHVybDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdXJsLnNwbGl0KC9bPyNdLywgMSlbMF0gfHwgJy8nO1xuICB9XG5cbiAgcHJpdmF0ZSBuZXh0QXV0b21hdGljTmFtZShyb3V0ZTogc3RyaW5nLCB1c2VkTmFtZXMgPSBuZXcgU2V0KHRoaXMuY2hlY2twb2ludHMoKS5tYXAoKHsgbmFtZSB9KSA9PiBuYW1lKSkpOiBzdHJpbmcge1xuICAgIGlmICghdXNlZE5hbWVzLmhhcyhyb3V0ZSkpIHJldHVybiByb3V0ZTtcbiAgICBmb3IgKGxldCBzdWZmaXggPSAyOyA7IHN1ZmZpeCArPSAxKSB7XG4gICAgICBjb25zdCBjYW5kaWRhdGUgPSBgJHtyb3V0ZX0gJHtzdWZmaXh9YDtcbiAgICAgIGlmICghdXNlZE5hbWVzLmhhcyhjYW5kaWRhdGUpKSByZXR1cm4gY2FuZGlkYXRlO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgbm9ybWFsaXplTGVnYWN5TmFtZXMoY2hlY2twb2ludHM6IEluc3BlY3RvckNoZWNrcG9pbnRbXSk6IHtcbiAgICBjaGVja3BvaW50czogSW5zcGVjdG9yQ2hlY2twb2ludFtdO1xuICAgIGNoYW5nZWQ6IGJvb2xlYW47XG4gIH0ge1xuICAgIGNvbnN0IGxlZ2FjeUlkcyA9IG5ldyBTZXQoXG4gICAgICBjaGVja3BvaW50cy5maWx0ZXIoKGNoZWNrcG9pbnQpID0+IHRoaXMuaXNMZWdhY3lBdXRvbWF0aWNOYW1lKGNoZWNrcG9pbnQpKS5tYXAoKHsgaWQgfSkgPT4gaWQpLFxuICAgICk7XG4gICAgaWYgKCFsZWdhY3lJZHMuc2l6ZSkgcmV0dXJuIHsgY2hlY2twb2ludHMsIGNoYW5nZWQ6IGZhbHNlIH07XG5cbiAgICBjb25zdCB1c2VkTmFtZXMgPSBuZXcgU2V0KFxuICAgICAgY2hlY2twb2ludHMuZmlsdGVyKCh7IGlkIH0pID0+ICFsZWdhY3lJZHMuaGFzKGlkKSkubWFwKCh7IG5hbWUgfSkgPT4gbmFtZSksXG4gICAgKTtcbiAgICBjb25zdCBuYW1lcyA9IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmc+KCk7XG4gICAgY29uc3Qgb2xkZXN0Rmlyc3QgPSBjaGVja3BvaW50c1xuICAgICAgLmZpbHRlcigoeyBpZCB9KSA9PiBsZWdhY3lJZHMuaGFzKGlkKSlcbiAgICAgIC5zb3J0KChhLCBiKSA9PiBhLmNyZWF0ZWRBdC5sb2NhbGVDb21wYXJlKGIuY3JlYXRlZEF0KSB8fCBhLmlkLmxvY2FsZUNvbXBhcmUoYi5pZCkpO1xuXG4gICAgZm9yIChjb25zdCBjaGVja3BvaW50IG9mIG9sZGVzdEZpcnN0KSB7XG4gICAgICBjb25zdCBuYW1lID0gdGhpcy5uZXh0QXV0b21hdGljTmFtZSh0aGlzLnJvdXRlUGF0aChjaGVja3BvaW50LnVybCksIHVzZWROYW1lcyk7XG4gICAgICBuYW1lcy5zZXQoY2hlY2twb2ludC5pZCwgbmFtZSk7XG4gICAgICB1c2VkTmFtZXMuYWRkKG5hbWUpO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBjaGVja3BvaW50czogY2hlY2twb2ludHMubWFwKChjaGVja3BvaW50KSA9PlxuICAgICAgICBuYW1lcy5oYXMoY2hlY2twb2ludC5pZCkgPyB7IC4uLmNoZWNrcG9pbnQsIG5hbWU6IG5hbWVzLmdldChjaGVja3BvaW50LmlkKSEgfSA6IGNoZWNrcG9pbnRcbiAgICAgICksXG4gICAgICBjaGFuZ2VkOiB0cnVlLFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIGlzTGVnYWN5QXV0b21hdGljTmFtZShjaGVja3BvaW50OiBJbnNwZWN0b3JDaGVja3BvaW50KTogYm9vbGVhbiB7XG4gICAgY29uc3Qgcm91dGUgPSB0aGlzLnJvdXRlUGF0aChjaGVja3BvaW50LnVybCk7XG4gICAgY29uc3QgcHJlZml4ID0gYCR7cm91dGV9IMK3IGA7XG4gICAgaWYgKCFjaGVja3BvaW50Lm5hbWUuc3RhcnRzV2l0aChwcmVmaXgpKSByZXR1cm4gZmFsc2U7XG4gICAgY29uc3QgdGltZXN0YW1wID0gY2hlY2twb2ludC5uYW1lLnNsaWNlKHByZWZpeC5sZW5ndGgpO1xuICAgIGlmICh0aW1lc3RhbXAgPT09IG5ldyBEYXRlKGNoZWNrcG9pbnQuY3JlYXRlZEF0KS50b0xvY2FsZVN0cmluZygpKSByZXR1cm4gdHJ1ZTtcblxuICAgIGNvbnN0IHBhcnNlZFRpbWVzdGFtcCA9IERhdGUucGFyc2UodGltZXN0YW1wKTtcbiAgICBjb25zdCBjcmVhdGVkVGltZXN0YW1wID0gRGF0ZS5wYXJzZShjaGVja3BvaW50LmNyZWF0ZWRBdCk7XG4gICAgcmV0dXJuIE51bWJlci5pc0Zpbml0ZShwYXJzZWRUaW1lc3RhbXApICYmIE51bWJlci5pc0Zpbml0ZShjcmVhdGVkVGltZXN0YW1wKSAmJlxuICAgICAgTWF0aC5hYnMocGFyc2VkVGltZXN0YW1wIC0gY3JlYXRlZFRpbWVzdGFtcCkgPCAxMDAwO1xuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVJZCgpOiBzdHJpbmcge1xuICAgIHJldHVybiBgY2hlY2twb2ludC0ke0RhdGUubm93KCl9LSR7TWF0aC5yYW5kb20oKS50b1N0cmluZygzNikuc2xpY2UoMiwgOSl9YDtcbiAgfVxuXG4gIHByaXZhdGUgc2l6ZU9mKGNoZWNrcG9pbnQ6IEluc3BlY3RvckNoZWNrcG9pbnQpOiBudW1iZXIge1xuICAgIHJldHVybiBuZXcgQmxvYihbSlNPTi5zdHJpbmdpZnkoY2hlY2twb2ludCldKS5zaXplO1xuICB9XG5cbiAgcHJpdmF0ZSBpc1F1b3RhRXJyb3IoZXJyb3I6IHVua25vd24pOiBib29sZWFuIHtcbiAgICByZXR1cm4gZXJyb3IgaW5zdGFuY2VvZiBET01FeGNlcHRpb24gJiYgKFxuICAgICAgZXJyb3IubmFtZSA9PT0gJ1F1b3RhRXhjZWVkZWRFcnJvcicgfHwgZXJyb3IubmFtZSA9PT0gJ05TX0VSUk9SX0RPTV9RVU9UQV9SRUFDSEVEJ1xuICAgICk7XG4gIH1cblxuICBwcml2YXRlIG1lc3NhZ2VGb3IoZXJyb3I6IHVua25vd24sIGZhbGxiYWNrOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IGZhbGxiYWNrO1xuICB9XG5cbiAgcHJpdmF0ZSBpc0NoZWNrcG9pbnQgPSAodmFsdWU6IHVua25vd24pOiB2YWx1ZSBpcyBJbnNwZWN0b3JDaGVja3BvaW50ID0+IHtcbiAgICBpZiAoIXZhbHVlIHx8IHR5cGVvZiB2YWx1ZSAhPT0gJ29iamVjdCcpIHJldHVybiBmYWxzZTtcbiAgICBjb25zdCBjaGVja3BvaW50ID0gdmFsdWUgYXMgUGFydGlhbDxJbnNwZWN0b3JDaGVja3BvaW50PjtcbiAgICByZXR1cm4gY2hlY2twb2ludC52ZXJzaW9uID09PSAxICYmIHR5cGVvZiBjaGVja3BvaW50LmlkID09PSAnc3RyaW5nJyAmJlxuICAgICAgdHlwZW9mIGNoZWNrcG9pbnQubmFtZSA9PT0gJ3N0cmluZycgJiYgdHlwZW9mIGNoZWNrcG9pbnQudXJsID09PSAnc3RyaW5nJyAmJlxuICAgICAgdHlwZW9mIGNoZWNrcG9pbnQuY3JlYXRlZEF0ID09PSAnc3RyaW5nJyAmJiBBcnJheS5pc0FycmF5KGNoZWNrcG9pbnQuc2NvcGVzKSAmJlxuICAgICAgISFjaGVja3BvaW50LnN0YXRlICYmIHR5cGVvZiBjaGVja3BvaW50LnN0YXRlID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgY2hlY2twb2ludC5zaXplQnl0ZXMgPT09ICdudW1iZXInO1xuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcHJvdmlkZUluc3BlY3RvckNoZWNrcG9pbnRzKCk6IFByb3ZpZGVyW10ge1xuICByZXR1cm4gW0luc3BlY3RvckNoZWNrcG9pbnRSZWdpc3RyeV07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVCZWhhdmlvclN1YmplY3RDaGVja3BvaW50QWRhcHRlcjxUPihcbiAgaWQ6IHN0cmluZyxcbiAgc3ViamVjdDogQmVoYXZpb3JTdWJqZWN0PFQ+LFxuKTogSW5zcGVjdG9yQ2hlY2twb2ludEFkYXB0ZXIge1xuICByZXR1cm4ge1xuICAgIGlkLFxuICAgIGNhcHR1cmU6ICgpID0+IHN1YmplY3QudmFsdWUgYXMgdW5rbm93biBhcyBJbnNwZWN0b3JDaGVja3BvaW50VmFsdWUsXG4gICAgcmVzdG9yZTogKHZhbHVlKSA9PiBzdWJqZWN0Lm5leHQodmFsdWUgYXMgVCksXG4gIH07XG59XG4iXX0=
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export const inspector_STORAGE_KEY = "inspector-state";
|
|
2
|
-
export const inspector_STATE_VERSION =
|
|
2
|
+
export const inspector_STATE_VERSION = 2;
|
|
3
3
|
export const GUIDE_SNAP_DISTANCE = 10;
|
|
4
4
|
export const GUIDE_HITBOX_SIZE = 14;
|
|
5
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
5
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uc3RhbnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvaW5zcGVjdG9yLW5nL3NyYy9saWIvY29uc3RhbnRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE1BQU0sQ0FBQyxNQUFNLHFCQUFxQixHQUFHLGlCQUFpQixDQUFDO0FBQ3ZELE1BQU0sQ0FBQyxNQUFNLHVCQUF1QixHQUFHLENBQUMsQ0FBQztBQUN6QyxNQUFNLENBQUMsTUFBTSxtQkFBbUIsR0FBRyxFQUFFLENBQUM7QUFDdEMsTUFBTSxDQUFDLE1BQU0saUJBQWlCLEdBQUcsRUFBRSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGNvbnN0IGluc3BlY3Rvcl9TVE9SQUdFX0tFWSA9IFwiaW5zcGVjdG9yLXN0YXRlXCI7XG5leHBvcnQgY29uc3QgaW5zcGVjdG9yX1NUQVRFX1ZFUlNJT04gPSAyO1xuZXhwb3J0IGNvbnN0IEdVSURFX1NOQVBfRElTVEFOQ0UgPSAxMDtcbmV4cG9ydCBjb25zdCBHVUlERV9ISVRCT1hfU0laRSA9IDE0O1xuIl19
|