@jax-data-science/sci-image-visualizer 0.9.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. package/esm2022/index.mjs +10 -1
  2. package/esm2022/lib/contracts/image.contract.mjs +1 -1
  3. package/esm2022/lib/contracts/ports/region-io.port.mjs +1 -1
  4. package/esm2022/lib/contracts/region-editor-api.contract.mjs +1 -1
  5. package/esm2022/lib/contracts/region-store.contract.mjs +1 -1
  6. package/esm2022/lib/contracts/section-view.contract.mjs +2 -0
  7. package/esm2022/lib/contracts/visualizer.contract.mjs +1 -1
  8. package/esm2022/lib/contracts/viz-config.mjs +1 -1
  9. package/esm2022/lib/geometry/loft.mjs +128 -0
  10. package/esm2022/lib/geometry/polylabel.mjs +156 -0
  11. package/esm2022/lib/geometry/reconstruct.mjs +315 -0
  12. package/esm2022/lib/geometry/reslice-image.mjs +57 -0
  13. package/esm2022/lib/geometry/section.mjs +215 -0
  14. package/esm2022/lib/implementations/napari-js/napari-loading-badge.mjs +11 -7
  15. package/esm2022/lib/implementations/napari-js/napari-loading-state.mjs +20 -3
  16. package/esm2022/lib/implementations/napari-js/napari-region-mesh-pointer.mjs +100 -0
  17. package/esm2022/lib/implementations/napari-js/napari-region-overlay.mjs +28 -5
  18. package/esm2022/lib/implementations/napari-js/napari-scene.mjs +1 -1
  19. package/esm2022/lib/implementations/napari-js/napari-spatial-hover.mjs +9 -2
  20. package/esm2022/lib/implementations/napari-js/napari-tool-bridge.mjs +5 -2
  21. package/esm2022/lib/implementations/napari-js/napari-visualizer.service.mjs +81 -1
  22. package/esm2022/lib/implementations/napari-js/napari-volume-region-meshes.mjs +129 -0
  23. package/esm2022/lib/implementations/napari-js/napari-volume-scene.mjs +115 -4
  24. package/esm2022/lib/implementations/napari-js/napari-volume-slice-planes.mjs +103 -0
  25. package/esm2022/lib/implementations/napari-js/region-overlay/region-svg-renderer.mjs +15 -3
  26. package/esm2022/lib/implementations/osd/openseadragon-viewer-options.mjs +18 -2
  27. package/esm2022/lib/implementations/osd/openseadragon-visualizer.service.mjs +9 -1
  28. package/esm2022/lib/implementations/osd/osd-region-overlay-draw.mjs +18 -7
  29. package/esm2022/lib/implementations/osd/osd-region-overlay.mjs +38 -8
  30. package/esm2022/lib/implementations/osd/osd-tile-loading.mjs +71 -0
  31. package/esm2022/lib/implementations/osd/osd-viewer-like.mjs +1 -1
  32. package/esm2022/lib/implementations/osd/slice-cache.mjs +35 -6
  33. package/esm2022/lib/implementations/tile-server/tile-protocol.mjs +1 -1
  34. package/esm2022/lib/models/class-preset.mjs +1 -1
  35. package/esm2022/lib/models/polygon-factory.mjs +17 -1
  36. package/esm2022/lib/models/region-geojson.mjs +44 -6
  37. package/esm2022/lib/models/region.mjs +1 -1
  38. package/esm2022/lib/region-editor/class-tree/class-tree.component.mjs +156 -0
  39. package/esm2022/lib/region-editor/class-tree/class-tree.mjs +108 -0
  40. package/esm2022/lib/region-editor/classes-panel/classes-panel.component.mjs +77 -13
  41. package/esm2022/lib/region-editor/region-editor.component.mjs +670 -42
  42. package/esm2022/lib/region-editor/region-metrics.mjs +20 -2
  43. package/esm2022/lib/region-editor/region-persistence.service.mjs +44 -10
  44. package/esm2022/lib/region-editor/region-table/region-table.component.mjs +24 -8
  45. package/esm2022/lib/region-import/label-classes.mjs +149 -0
  46. package/esm2022/lib/region-import/label-volume.mjs +194 -0
  47. package/esm2022/lib/region-import/region-import.mjs +71 -0
  48. package/esm2022/lib/region-overlay/region-geometry.mjs +3 -3
  49. package/esm2022/lib/region-overlay/region-source-layer.mjs +378 -0
  50. package/esm2022/lib/region-overlay/region-style.mjs +97 -0
  51. package/esm2022/lib/region-source/http-region-source.mjs +104 -0
  52. package/esm2022/lib/region-source/region-source-ops.mjs +53 -0
  53. package/esm2022/lib/region-source/region-source-worker.mjs +10 -0
  54. package/esm2022/lib/region-source/region-source.mjs +67 -0
  55. package/esm2022/lib/region-source/region-tiles.mjs +708 -0
  56. package/esm2022/lib/region-source/worker-region-source.mjs +229 -0
  57. package/esm2022/lib/routing-visualizer.service.mjs +510 -22
  58. package/esm2022/lib/section-pane/section-pane.component.mjs +299 -0
  59. package/esm2022/lib/store/class-color.util.mjs +10 -5
  60. package/esm2022/lib/store/class-signatures.mjs +63 -0
  61. package/esm2022/lib/store/region-scope-cache.mjs +5 -1
  62. package/esm2022/lib/store/region-source-scope.mjs +186 -0
  63. package/esm2022/lib/store/region-store.service.mjs +774 -12
  64. package/esm2022/lib/store/visualizer-store.service.mjs +33 -6
  65. package/esm2022/lib/toolbar/region-tools/region-tools.component.mjs +8 -2
  66. package/esm2022/lib/toolbar/stack-controls/stack-controls.component.mjs +55 -15
  67. package/esm2022/lib/toolbar/toolbar.component.mjs +19 -5
  68. package/esm2022/lib/visualizer/region-load.mjs +67 -4
  69. package/esm2022/lib/visualizer/volume-sections.mjs +175 -0
  70. package/esm2022/lib/visualizer.component.mjs +155 -7
  71. package/fesm2022/{jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-Csxlnq7I.mjs → jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-BELcx0jv.mjs} +9851 -2904
  72. package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-BELcx0jv.mjs.map +1 -0
  73. package/fesm2022/{jax-data-science-sci-image-visualizer-onnx-sam-session-Bkujqg7m.mjs → jax-data-science-sci-image-visualizer-onnx-sam-session-DEDSm_NL.mjs} +4 -4
  74. package/fesm2022/{jax-data-science-sci-image-visualizer-onnx-sam-session-Bkujqg7m.mjs.map → jax-data-science-sci-image-visualizer-onnx-sam-session-DEDSm_NL.mjs.map} +1 -1
  75. package/fesm2022/jax-data-science-sci-image-visualizer-region-source-worker-CAqBjM5L.mjs +12 -0
  76. package/fesm2022/jax-data-science-sci-image-visualizer-region-source-worker-CAqBjM5L.mjs.map +1 -0
  77. package/fesm2022/jax-data-science-sci-image-visualizer.mjs +3 -3
  78. package/fesm2022/region-source.worker.js +1067 -0
  79. package/index.d.ts +12 -0
  80. package/lib/contracts/image.contract.d.ts +4 -0
  81. package/lib/contracts/ports/region-io.port.d.ts +24 -0
  82. package/lib/contracts/region-editor-api.contract.d.ts +102 -0
  83. package/lib/contracts/region-store.contract.d.ts +22 -0
  84. package/lib/contracts/section-view.contract.d.ts +44 -0
  85. package/lib/contracts/visualizer.contract.d.ts +10 -0
  86. package/lib/contracts/viz-config.d.ts +8 -0
  87. package/lib/geometry/loft.d.ts +22 -0
  88. package/lib/geometry/polylabel.d.ts +23 -0
  89. package/lib/geometry/reconstruct.d.ts +54 -0
  90. package/lib/geometry/reslice-image.d.ts +33 -0
  91. package/lib/geometry/section.d.ts +52 -0
  92. package/lib/implementations/napari-js/napari-loading-badge.d.ts +4 -2
  93. package/lib/implementations/napari-js/napari-loading-state.d.ts +8 -1
  94. package/lib/implementations/napari-js/napari-region-mesh-pointer.d.ts +32 -0
  95. package/lib/implementations/napari-js/napari-region-overlay.d.ts +6 -1
  96. package/lib/implementations/napari-js/napari-scene.d.ts +33 -0
  97. package/lib/implementations/napari-js/napari-spatial-hover.d.ts +3 -1
  98. package/lib/implementations/napari-js/napari-visualizer.service.d.ts +48 -0
  99. package/lib/implementations/napari-js/napari-volume-region-meshes.d.ts +66 -0
  100. package/lib/implementations/napari-js/napari-volume-scene.d.ts +45 -1
  101. package/lib/implementations/napari-js/napari-volume-slice-planes.d.ts +43 -0
  102. package/lib/implementations/osd/openseadragon-viewer-options.d.ts +2 -0
  103. package/lib/implementations/osd/openseadragon-visualizer.service.d.ts +2 -0
  104. package/lib/implementations/osd/osd-region-overlay-draw.d.ts +4 -3
  105. package/lib/implementations/osd/osd-region-overlay.d.ts +10 -3
  106. package/lib/implementations/osd/osd-tile-loading.d.ts +43 -0
  107. package/lib/implementations/osd/osd-viewer-like.d.ts +14 -0
  108. package/lib/implementations/osd/slice-cache.d.ts +13 -3
  109. package/lib/implementations/tile-server/tile-protocol.d.ts +3 -0
  110. package/lib/models/class-preset.d.ts +7 -0
  111. package/lib/models/polygon-factory.d.ts +5 -0
  112. package/lib/models/region-geojson.d.ts +40 -0
  113. package/lib/models/region.d.ts +19 -0
  114. package/lib/region-editor/class-tree/class-tree.component.d.ts +78 -0
  115. package/lib/region-editor/class-tree/class-tree.d.ts +31 -0
  116. package/lib/region-editor/classes-panel/classes-panel.component.d.ts +36 -6
  117. package/lib/region-editor/region-editor.component.d.ts +159 -17
  118. package/lib/region-editor/region-metrics.d.ts +8 -0
  119. package/lib/region-editor/region-persistence.service.d.ts +17 -5
  120. package/lib/region-editor/region-table/region-table.component.d.ts +10 -4
  121. package/lib/region-import/label-classes.d.ts +39 -0
  122. package/lib/region-import/label-volume.d.ts +31 -0
  123. package/lib/region-import/region-import.d.ts +46 -0
  124. package/lib/region-overlay/region-geometry.d.ts +4 -3
  125. package/lib/region-overlay/region-source-layer.d.ts +96 -0
  126. package/lib/region-overlay/region-style.d.ts +52 -0
  127. package/lib/region-source/http-region-source.d.ts +45 -0
  128. package/lib/region-source/region-source-ops.d.ts +89 -0
  129. package/lib/region-source/region-source-worker.d.ts +7 -0
  130. package/lib/region-source/region-source.d.ts +82 -0
  131. package/lib/region-source/region-tiles.d.ts +289 -0
  132. package/lib/region-source/worker-region-source.d.ts +65 -0
  133. package/lib/routing-visualizer.service.d.ts +168 -1
  134. package/lib/section-pane/section-pane.component.d.ts +47 -0
  135. package/lib/store/class-color.util.d.ts +6 -3
  136. package/lib/store/class-signatures.d.ts +11 -0
  137. package/lib/store/region-scope-cache.d.ts +2 -0
  138. package/lib/store/region-source-scope.d.ts +74 -0
  139. package/lib/store/region-store.service.d.ts +216 -2
  140. package/lib/store/visualizer-store.service.d.ts +10 -0
  141. package/lib/toolbar/region-tools/region-tools.component.d.ts +3 -1
  142. package/lib/toolbar/stack-controls/stack-controls.component.d.ts +20 -9
  143. package/lib/toolbar/toolbar.component.d.ts +9 -2
  144. package/lib/visualizer/region-load.d.ts +23 -4
  145. package/lib/visualizer/volume-sections.d.ts +64 -0
  146. package/lib/visualizer.component.d.ts +40 -0
  147. package/package.json +2 -2
  148. package/src/lib/assets/slice.svg +23 -0
  149. package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-Csxlnq7I.mjs.map +0 -1
@@ -0,0 +1,229 @@
1
+ /**
2
+ * A {@link RegionSource} over a GeoJSON string, parsed and tiled in the region-source Web Worker.
3
+ *
4
+ * One worker serves every open source. Where no worker can start (jsdom, SSR, a blocked worker
5
+ * URL) the same tables run on the main thread; if the worker dies, each source re-opens itself
6
+ * there from its text (which the host holds anyway: it handed it over) and carries on — whether
7
+ * it had a call in flight then or not (see {@link RegionSourceWorkerClient.generation}).
8
+ */
9
+ import { RegionTileCache, abortable } from './region-source';
10
+ import { RegionSourceTables, } from './region-source-ops';
11
+ /** The worker died under a call; the caller re-opens on the main thread. */
12
+ class WorkerLostError extends Error {
13
+ constructor() {
14
+ super('The region-source worker stopped.');
15
+ this.name = 'WorkerLostError';
16
+ }
17
+ }
18
+ /** Owns the region-source worker and the calls in flight on it. */
19
+ export class RegionSourceWorkerClient {
20
+ /**
21
+ * `factory` is optional: without one the real worker module is imported on demand —
22
+ * dynamically, because it holds an `import.meta.url` that ts-jest's CommonJS compile
23
+ * rejects.
24
+ */
25
+ constructor(factory) {
26
+ this.factory = factory;
27
+ this.worker = null;
28
+ this.starting = null;
29
+ this.unavailable = false;
30
+ this.nextId = 1;
31
+ this.pending = new Map();
32
+ /** The main-thread tables, once anything runs here. */
33
+ this.local = null;
34
+ this.tables = 0;
35
+ }
36
+ /** Whether calls now run on the main thread. */
37
+ get inThread() {
38
+ return this.unavailable;
39
+ }
40
+ /**
41
+ * Which table set calls run on: bumped when the worker is lost. A handle opened under another
42
+ * names a table that is gone (or, here, another source's), so its source must open again.
43
+ */
44
+ get generation() {
45
+ return this.tables;
46
+ }
47
+ /** Run `request` in the worker, or here when there is none. */
48
+ async call(request) {
49
+ return (await this.run(request)).result;
50
+ }
51
+ /** {@link call}, with the {@link generation} the request ran on. */
52
+ async run(request) {
53
+ const started = await this.ensureWorker();
54
+ // The worker may have been lost while this waited for it.
55
+ const worker = started === this.worker ? started : null;
56
+ const generation = this.tables;
57
+ if (!worker)
58
+ return { result: (this.local ??= new RegionSourceTables()).run(request), generation };
59
+ const id = this.nextId++;
60
+ const result = await new Promise((resolve, reject) => {
61
+ this.pending.set(id, { resolve: resolve, reject });
62
+ worker.postMessage({ ...request, id });
63
+ });
64
+ return { result, generation };
65
+ }
66
+ /** Terminate the worker; calls in flight reject. */
67
+ dispose() {
68
+ this.lose();
69
+ }
70
+ ensureWorker() {
71
+ if (this.worker)
72
+ return Promise.resolve(this.worker);
73
+ if (this.unavailable || (!this.factory && typeof Worker === 'undefined')) {
74
+ this.unavailable = true;
75
+ return Promise.resolve(null);
76
+ }
77
+ if (!this.starting) {
78
+ const starting = this.startWorker();
79
+ this.starting = starting;
80
+ void starting.then(() => {
81
+ if (this.starting === starting)
82
+ this.starting = null;
83
+ });
84
+ }
85
+ return this.starting;
86
+ }
87
+ async startWorker() {
88
+ try {
89
+ const made = this.factory
90
+ ? this.factory()
91
+ : import('./region-source-worker').then((m) => m.createRegionSourceWorker());
92
+ const worker = made instanceof Promise ? await made : made;
93
+ worker.onmessage = (event) => this.onReply(event.data);
94
+ worker.onerror = (event) => {
95
+ event.preventDefault?.();
96
+ if (worker === this.worker) {
97
+ console.warn('[region-source] worker failed; tiling on the main thread');
98
+ this.lose();
99
+ }
100
+ };
101
+ this.worker = worker;
102
+ return worker;
103
+ }
104
+ catch (err) {
105
+ console.warn('[region-source] worker unavailable; tiling on the main thread', err);
106
+ this.unavailable = true;
107
+ return null;
108
+ }
109
+ }
110
+ onReply(reply) {
111
+ const call = this.pending.get(reply.id);
112
+ if (!call)
113
+ return;
114
+ this.pending.delete(reply.id);
115
+ if (reply.ok)
116
+ call.resolve(reply.result);
117
+ else
118
+ call.reject(new Error(reply.error));
119
+ }
120
+ /** Stop the worker for good: every later call runs here, every call in flight is lost. */
121
+ lose() {
122
+ if (this.worker)
123
+ this.tables++;
124
+ this.unavailable = true;
125
+ this.worker?.terminate();
126
+ this.worker = null;
127
+ const calls = [...this.pending.values()];
128
+ this.pending.clear();
129
+ for (const call of calls)
130
+ call.reject(new WorkerLostError());
131
+ }
132
+ }
133
+ let shared = null;
134
+ /** The worker client every GeoJSON source shares. */
135
+ export function sharedRegionSourceClient() {
136
+ return (shared ??= new RegionSourceWorkerClient());
137
+ }
138
+ /**
139
+ * Open a GeoJSON FeatureCollection string as a tiled region source. Rejects on invalid JSON or
140
+ * a collection without `features`.
141
+ */
142
+ export async function openGeoJsonRegionSource(text, client = sharedRegionSourceClient()) {
143
+ // The worker lost under the open: open on the main thread instead.
144
+ const opened = await client
145
+ .run({ op: 'open', text })
146
+ .catch((err) => (err instanceof WorkerLostError ? client.run({ op: 'open', text }) : Promise.reject(err)));
147
+ const { handle, info } = opened.result;
148
+ return new WorkerRegionSource(client, text, handle, opened.generation, info);
149
+ }
150
+ /**
151
+ * The 3D reconstruction of a region from its outlines on a stack (see `geometry/reconstruct`),
152
+ * meshed in the region-source worker (on the main thread where there is none).
153
+ */
154
+ export function reconstructInWorker(slices, options, client = sharedRegionSourceClient()) {
155
+ return client.call({ op: 'mesh', slices, options });
156
+ }
157
+ class WorkerRegionSource {
158
+ constructor(client, text, handle,
159
+ /** The client's {@link RegionSourceWorkerClient.generation} {@link handle} was opened under. */
160
+ generation, info) {
161
+ this.client = client;
162
+ this.text = text;
163
+ this.handle = handle;
164
+ this.generation = generation;
165
+ this.info = info;
166
+ this.cache = new RegionTileCache();
167
+ this.disposed = false;
168
+ /** The main-thread re-open after the worker died, shared by every call that finds it so. */
169
+ this.reopening = null;
170
+ }
171
+ getTile(z, key, signal) {
172
+ const tile = this.cache.get(z, key, () => this.call((handle) => ({ op: 'tile', handle, z, level: key.level, gx: key.gx, gy: key.gy })));
173
+ return abortable(tile, signal);
174
+ }
175
+ getFeatures(ids) {
176
+ return this.call((handle) => ({ op: 'features', handle, ids }));
177
+ }
178
+ getIndex(z, query) {
179
+ return this.call((handle) => ({ op: 'index', handle, z, query }));
180
+ }
181
+ getClassOutlines(classes, level, exclude) {
182
+ return this.call((handle) => ({ op: 'outlines', handle, classes, level, exclude }));
183
+ }
184
+ getClassCounts(z, exclude) {
185
+ return this.call((handle) => ({ op: 'classes', handle, z, exclude }));
186
+ }
187
+ exportGeoJson(exclude, extra) {
188
+ return this.call((handle) => ({ op: 'export', handle, exclude, extra }));
189
+ }
190
+ dispose() {
191
+ if (this.disposed)
192
+ return;
193
+ this.disposed = true;
194
+ this.cache.clear();
195
+ // A handle from a lost worker's tables names nothing here, or another source's table.
196
+ if (this.generation !== this.client.generation)
197
+ return;
198
+ void this.client.call({ op: 'close', handle: this.handle }).catch(() => undefined);
199
+ }
200
+ /**
201
+ * Run a request on this source's table; when the worker died (under this call or before it),
202
+ * re-open here and run it there.
203
+ */
204
+ async call(make) {
205
+ for (let attempt = 0;; attempt++) {
206
+ if (this.generation !== this.client.generation)
207
+ await this.reopen();
208
+ try {
209
+ return await this.client.call(make(this.handle));
210
+ }
211
+ catch (err) {
212
+ if (!(err instanceof WorkerLostError) || attempt > 0)
213
+ throw err;
214
+ }
215
+ }
216
+ }
217
+ /** Open this source's text again on the client's current tables, once for every call waiting. */
218
+ reopen() {
219
+ this.reopening ??= this.client
220
+ .run({ op: 'open', text: this.text })
221
+ .then(({ result, generation }) => {
222
+ this.handle = result.handle;
223
+ this.generation = generation;
224
+ })
225
+ .finally(() => (this.reopening = null));
226
+ return this.reopening;
227
+ }
228
+ }
229
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid29ya2VyLXJlZ2lvbi1zb3VyY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL3JlZ2lvbi1zb3VyY2Uvd29ya2VyLXJlZ2lvbi1zb3VyY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7R0FPRztBQUNILE9BQU8sRUFBZ0IsZUFBZSxFQUFpQixTQUFTLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMxRixPQUFPLEVBS0wsa0JBQWtCLEdBQ25CLE1BQU0scUJBQXFCLENBQUM7QUFlN0IsNEVBQTRFO0FBQzVFLE1BQU0sZUFBZ0IsU0FBUSxLQUFLO0lBQ2pDO1FBQ0UsS0FBSyxDQUFDLG1DQUFtQyxDQUFDLENBQUM7UUFDM0MsSUFBSSxDQUFDLElBQUksR0FBRyxpQkFBaUIsQ0FBQztJQUNoQyxDQUFDO0NBQ0Y7QUFPRCxtRUFBbUU7QUFDbkUsTUFBTSxPQUFPLHdCQUF3QjtJQVVuQzs7OztPQUlHO0lBQ0gsWUFBNkIsT0FBbUM7UUFBbkMsWUFBTyxHQUFQLE9BQU8sQ0FBNEI7UUFkeEQsV0FBTSxHQUFrQixJQUFJLENBQUM7UUFDN0IsYUFBUSxHQUFrQyxJQUFJLENBQUM7UUFDL0MsZ0JBQVcsR0FBRyxLQUFLLENBQUM7UUFDcEIsV0FBTSxHQUFHLENBQUMsQ0FBQztRQUNGLFlBQU8sR0FBRyxJQUFJLEdBQUcsRUFBdUIsQ0FBQztRQUMxRCx1REFBdUQ7UUFDL0MsVUFBSyxHQUE4QixJQUFJLENBQUM7UUFDeEMsV0FBTSxHQUFHLENBQUMsQ0FBQztJQU9nRCxDQUFDO0lBRXBFLGdEQUFnRDtJQUNoRCxJQUFJLFFBQVE7UUFDVixPQUFPLElBQUksQ0FBQyxXQUFXLENBQUM7SUFDMUIsQ0FBQztJQUVEOzs7T0FHRztJQUNILElBQUksVUFBVTtRQUNaLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQztJQUNyQixDQUFDO0lBRUQsK0RBQStEO0lBQy9ELEtBQUssQ0FBQyxJQUFJLENBQWdDLE9BQVU7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SUFDSCxDQUFDO0lBRUQsaUdBQWlHO0lBQ3pGLE1BQU07UUFDWixJQUFJLENBQUMsU0FBUyxLQUFLLElBQUksQ0FBQyxNQUFNO2FBQzNCLEdBQUcsQ0FBQyxFQUFFLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQzthQUNwQyxJQUFJLENBQUMsQ0FBQyxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsRUFBRSxFQUFFO1lBQy9CLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQztZQUM1QixJQUFJLENBQUMsVUFBVSxHQUFHLFVBQVUsQ0FBQztRQUMvQixDQUFDLENBQUM7YUFDRCxPQUFPLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDMUMsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDO0lBQ3hCLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQSB7QGxpbmsgUmVnaW9uU291cmNlfSBvdmVyIGEgR2VvSlNPTiBzdHJpbmcsIHBhcnNlZCBhbmQgdGlsZWQgaW4gdGhlIHJlZ2lvbi1zb3VyY2UgV2ViIFdvcmtlci5cbiAqXG4gKiBPbmUgd29ya2VyIHNlcnZlcyBldmVyeSBvcGVuIHNvdXJjZS4gV2hlcmUgbm8gd29ya2VyIGNhbiBzdGFydCAoanNkb20sIFNTUiwgYSBibG9ja2VkIHdvcmtlclxuICogVVJMKSB0aGUgc2FtZSB0YWJsZXMgcnVuIG9uIHRoZSBtYWluIHRocmVhZDsgaWYgdGhlIHdvcmtlciBkaWVzLCBlYWNoIHNvdXJjZSByZS1vcGVucyBpdHNlbGZcbiAqIHRoZXJlIGZyb20gaXRzIHRleHQgKHdoaWNoIHRoZSBob3N0IGhvbGRzIGFueXdheTogaXQgaGFuZGVkIGl0IG92ZXIpIGFuZCBjYXJyaWVzIG9uIOKAlCB3aGV0aGVyXG4gKiBpdCBoYWQgYSBjYWxsIGluIGZsaWdodCB0aGVuIG9yIG5vdCAoc2VlIHtAbGluayBSZWdpb25Tb3VyY2VXb3JrZXJDbGllbnQuZ2VuZXJhdGlvbn0pLlxuICovXG5pbXBvcnQgeyBSZWdpb25Tb3VyY2UsIFJlZ2lvblRpbGVDYWNoZSwgU291cmNlRmVhdHVyZSwgYWJvcnRhYmxlIH0gZnJvbSAnLi9yZWdpb24tc291cmNlJztcbmltcG9ydCB7XG4gIFJlZ2lvblNvdXJjZU1lc3NhZ2UsXG4gIFJlZ2lvblNvdXJjZVJlcGx5LFxuICBSZWdpb25Tb3VyY2VSZXF1ZXN0LFxuICBSZWdpb25Tb3VyY2VSZXN1bHRzLFxuICBSZWdpb25Tb3VyY2VUYWJsZXMsXG59IGZyb20gJy4vcmVnaW9uLXNvdXJjZS1vcHMnO1xuaW1wb3J0IHR5cGUge1xuICBDbGFzc091dGxpbmVzLFxuICBSZWdpb25JbmRleFBhZ2UsXG4gIFJlZ2lvbkluZGV4UXVlcnksXG4gIFJlZ2lvblNvdXJjZUluZm8sXG4gIFJlZ2lvblRpbGUsXG4gIFJlZ2lvblRpbGVLZXksXG59IGZyb20gJy4vcmVnaW9uLXRpbGVzJztcbmltcG9ydCB0eXBlIHsgUmVjb25zdHJ1Y3RPcHRpb25zLCBTbGljZU91dGxpbmVzIH0gZnJvbSAnLi4vZ2VvbWV0cnkvcmVjb25zdHJ1Y3QnO1xuaW1wb3J0IHR5cGUgeyBNZXNoIH0gZnJvbSAnbmFwYXJpLWpzL2dlb21ldHJ5JztcblxuLyoqIE1ha2VzIHRoZSB3b3JrZXI7IG1heSBiZSBhc3luYywgYXMgdGhlIGRlZmF1bHQgb25lIGlzIChpdCBpbXBvcnRzIHRoZSBmYWN0b3J5IG9uIGRlbWFuZCkuICovXG5leHBvcnQgdHlwZSBSZWdpb25Tb3VyY2VXb3JrZXJGYWN0b3J5ID0gKCkgPT4gV29ya2VyIHwgUHJvbWlzZTxXb3JrZXI+O1xuXG4vKiogVGhlIHdvcmtlciBkaWVkIHVuZGVyIGEgY2FsbDsgdGhlIGNhbGxlciByZS1vcGVucyBvbiB0aGUgbWFpbiB0aHJlYWQuICovXG5jbGFzcyBXb3JrZXJMb3N0RXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCdUaGUgcmVnaW9uLXNvdXJjZSB3b3JrZXIgc3RvcHBlZC4nKTtcbiAgICB0aGlzLm5hbWUgPSAnV29ya2VyTG9zdEVycm9yJztcbiAgfVxufVxuXG5pbnRlcmZhY2UgUGVuZGluZ0NhbGwge1xuICByZXNvbHZlOiAodmFsdWU6IHVua25vd24pID0+IHZvaWQ7XG4gIHJlamVjdDogKHJlYXNvbjogdW5rbm93bikgPT4gdm9pZDtcbn1cblxuLyoqIE93bnMgdGhlIHJlZ2lvbi1zb3VyY2Ugd29ya2VyIGFuZCB0aGUgY2FsbHMgaW4gZmxpZ2h0IG9uIGl0LiAqL1xuZXhwb3J0IGNsYXNzIFJlZ2lvblNvdXJjZVdvcmtlckNsaWVudCB7XG4gIHByaXZhdGUgd29ya2VyOiBXb3JrZXIgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBzdGFydGluZzogUHJvbWlzZTxXb3JrZXIgfCBudWxsPiB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIHVuYXZhaWxhYmxlID0gZmFsc2U7XG4gIHByaXZhdGUgbmV4dElkID0gMTtcbiAgcHJpdmF0ZSByZWFkb25seSBwZW5kaW5nID0gbmV3IE1hcDxudW1iZXIsIFBlbmRpbmdDYWxsPigpO1xuICAvKiogVGhlIG1haW4tdGhyZWFkIHRhYmxlcywgb25jZSBhbnl0aGluZyBydW5zIGhlcmUuICovXG4gIHByaXZhdGUgbG9jYWw6IFJlZ2lvblNvdXJjZVRhYmxlcyB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIHRhYmxlcyA9IDA7XG5cbiAgLyoqXG4gICAqIGBmYWN0b3J5YCBpcyBvcHRpb25hbDogd2l0aG91dCBvbmUgdGhlIHJlYWwgd29ya2VyIG1vZHVsZSBpcyBpbXBvcnRlZCBvbiBkZW1hbmQg4oCUXG4gICAqIGR5bmFtaWNhbGx5LCBiZWNhdXNlIGl0IGhvbGRzIGFuIGBpbXBvcnQubWV0YS51cmxgIHRoYXQgdHMtamVzdCdzIENvbW1vbkpTIGNvbXBpbGVcbiAgICogcmVqZWN0cy5cbiAgICovXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgZmFjdG9yeT86IFJlZ2lvblNvdXJjZVdvcmtlckZhY3RvcnkpIHt9XG5cbiAgLyoqIFdoZXRoZXIgY2FsbHMgbm93IHJ1biBvbiB0aGUgbWFpbiB0aHJlYWQuICovXG4gIGdldCBpblRocmVhZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy51bmF2YWlsYWJsZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBXaGljaCB0YWJsZSBzZXQgY2FsbHMgcnVuIG9uOiBidW1wZWQgd2hlbiB0aGUgd29ya2VyIGlzIGxvc3QuIEEgaGFuZGxlIG9wZW5lZCB1bmRlciBhbm90aGVyXG4gICAqIG5hbWVzIGEgdGFibGUgdGhhdCBpcyBnb25lIChvciwgaGVyZSwgYW5vdGhlciBzb3VyY2UncyksIHNvIGl0cyBzb3VyY2UgbXVzdCBvcGVuIGFnYWluLlxuICAgKi9cbiAgZ2V0IGdlbmVyYXRpb24oKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy50YWJsZXM7XG4gIH1cblxuICAvKiogUnVuIGByZXF1ZXN0YCBpbiB0aGUgd29ya2VyLCBvciBoZXJlIHdoZW4gdGhlcmUgaXMgbm9uZS4gKi9cbiAgYXN5bmMgY2FsbDxSIGV4dGVuZHMgUmVnaW9uU291cmNlUmVxdWVzdD4ocmVxdWVzdDogUik6IFByb21pc2U8UmVnaW9uU291cmNlUmVzdWx0c1tSWydvcCddXT4ge1xuICAgIHJldHVybiAoYXdhaXQgdGhpcy5ydW4ocmVxdWVzdCkpLnJlc3VsdDtcbiAgfVxuXG4gIC8qKiB7QGxpbmsgY2FsbH0sIHdpdGggdGhlIHtAbGluayBnZW5lcmF0aW9ufSB0aGUgcmVxdWVzdCByYW4gb24uICovXG4gIGFzeW5jIHJ1bjxSIGV4dGVuZHMgUmVnaW9uU291cmNlUmVxdWVzdD4oXG4gICAgcmVxdWVzdDogUixcbiAgKTogUHJvbWlzZTx7IHJlc3VsdDogUmVnaW9uU291cmNlUmVzdWx0c1tSWydvcCddXTsgZ2VuZXJhdGlvbjogbnVtYmVyIH0+IHtcbiAgICBjb25zdCBzdGFydGVkID0gYXdhaXQgdGhpcy5lbnN1cmVXb3JrZXIoKTtcbiAgICAvLyBUaGUgd29ya2VyIG1heSBoYXZlIGJlZW4gbG9zdCB3aGlsZSB0aGlzIHdhaXRlZCBmb3IgaXQuXG4gICAgY29uc3Qgd29ya2VyID0gc3RhcnRlZCA9PT0gdGhpcy53b3JrZXIgPyBzdGFydGVkIDogbnVsbDtcbiAgICBjb25zdCBnZW5lcmF0aW9uID0gdGhpcy50YWJsZXM7XG4gICAgaWYgKCF3b3JrZXIpIHJldHVybiB7IHJlc3VsdDogKHRoaXMubG9jYWwgPz89IG5ldyBSZWdpb25Tb3VyY2VUYWJsZXMoKSkucnVuKHJlcXVlc3QpLCBnZW5lcmF0aW9uIH07XG4gICAgY29uc3QgaWQgPSB0aGlzLm5leHRJZCsrO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IG5ldyBQcm9taXNlPFJlZ2lvblNvdXJjZVJlc3VsdHNbUlsnb3AnXV0+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRoaXMucGVuZGluZy5zZXQoaWQsIHsgcmVzb2x2ZTogcmVzb2x2ZSBhcyAodjogdW5rbm93bikgPT4gdm9pZCwgcmVqZWN0IH0pO1xuICAgICAgd29ya2VyLnBvc3RNZXNzYWdlKHsgLi4ucmVxdWVzdCwgaWQgfSBhcyBSZWdpb25Tb3VyY2VNZXNzYWdlKTtcbiAgICB9KTtcbiAgICByZXR1cm4geyByZXN1bHQsIGdlbmVyYXRpb24gfTtcbiAgfVxuXG4gIC8qKiBUZXJtaW5hdGUgdGhlIHdvcmtlcjsgY2FsbHMgaW4gZmxpZ2h0IHJlamVjdC4gKi9cbiAgZGlzcG9zZSgpOiB2b2lkIHtcbiAgICB0aGlzLmxvc2UoKTtcbiAgfVxuXG4gIHByaXZhdGUgZW5zdXJlV29ya2VyKCk6IFByb21pc2U8V29ya2VyIHwgbnVsbD4ge1xuICAgIGlmICh0aGlzLndvcmtlcikgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh0aGlzLndvcmtlcik7XG4gICAgaWYgKHRoaXMudW5hdmFpbGFibGUgfHwgKCF0aGlzLmZhY3RvcnkgJiYgdHlwZW9mIFdvcmtlciA9PT0gJ3VuZGVmaW5lZCcpKSB7XG4gICAgICB0aGlzLnVuYXZhaWxhYmxlID0gdHJ1ZTtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUobnVsbCk7XG4gICAgfVxuICAgIGlmICghdGhpcy5zdGFydGluZykge1xuICAgICAgY29uc3Qgc3RhcnRpbmcgPSB0aGlzLnN0YXJ0V29ya2VyKCk7XG4gICAgICB0aGlzLnN0YXJ0aW5nID0gc3RhcnRpbmc7XG4gICAgICB2b2lkIHN0YXJ0aW5nLnRoZW4oKCkgPT4ge1xuICAgICAgICBpZiAodGhpcy5zdGFydGluZyA9PT0gc3RhcnRpbmcpIHRoaXMuc3RhcnRpbmcgPSBudWxsO1xuICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLnN0YXJ0aW5nO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBzdGFydFdvcmtlcigpOiBQcm9taXNlPFdvcmtlciB8IG51bGw+IHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgbWFkZSA9IHRoaXMuZmFjdG9yeVxuICAgICAgICA/IHRoaXMuZmFjdG9yeSgpXG4gICAgICAgIDogaW1wb3J0KCcuL3JlZ2lvbi1zb3VyY2Utd29ya2VyJykudGhlbigobSkgPT4gbS5jcmVhdGVSZWdpb25Tb3VyY2VXb3JrZXIoKSk7XG4gICAgICBjb25zdCB3b3JrZXIgPSBtYWRlIGluc3RhbmNlb2YgUHJvbWlzZSA/IGF3YWl0IG1hZGUgOiBtYWRlO1xuICAgICAgd29ya2VyLm9ubWVzc2FnZSA9IChldmVudDogTWVzc2FnZUV2ZW50PFJlZ2lvblNvdXJjZVJlcGx5PikgPT4gdGhpcy5vblJlcGx5KGV2ZW50LmRhdGEpO1xuICAgICAgd29ya2VyLm9uZXJyb3IgPSAoZXZlbnQ6IEV2ZW50KSA9PiB7XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0Py4oKTtcbiAgICAgICAgaWYgKHdvcmtlciA9PT0gdGhpcy53b3JrZXIpIHtcbiAgICAgICAgICBjb25zb2xlLndhcm4oJ1tyZWdpb24tc291cmNlXSB3b3JrZXIgZmFpbGVkOyB0aWxpbmcgb24gdGhlIG1haW4gdGhyZWFkJyk7XG4gICAgICAgICAgdGhpcy5sb3NlKCk7XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgICB0aGlzLndvcmtlciA9IHdvcmtlcjtcbiAgICAgIHJldHVybiB3b3JrZXI7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBjb25zb2xlLndhcm4oJ1tyZWdpb24tc291cmNlXSB3b3JrZXIgdW5hdmFpbGFibGU7IHRpbGluZyBvbiB0aGUgbWFpbiB0aHJlYWQnLCBlcnIpO1xuICAgICAgdGhpcy51bmF2YWlsYWJsZSA9IHRydWU7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIG9uUmVwbHkocmVwbHk6IFJlZ2lvblNvdXJjZVJlcGx5KTogdm9pZCB7XG4gICAgY29uc3QgY2FsbCA9IHRoaXMucGVuZGluZy5nZXQocmVwbHkuaWQpO1xuICAgIGlmICghY2FsbCkgcmV0dXJuO1xuICAgIHRoaXMucGVuZGluZy5kZWxldGUocmVwbHkuaWQpO1xuICAgIGlmIChyZXBseS5vaykgY2FsbC5yZXNvbHZlKHJlcGx5LnJlc3VsdCk7XG4gICAgZWxzZSBjYWxsLnJlamVjdChuZXcgRXJyb3IocmVwbHkuZXJyb3IpKTtcbiAgfVxuXG4gIC8qKiBTdG9wIHRoZSB3b3JrZXIgZm9yIGdvb2Q6IGV2ZXJ5IGxhdGVyIGNhbGwgcnVucyBoZXJlLCBldmVyeSBjYWxsIGluIGZsaWdodCBpcyBsb3N0LiAqL1xuICBwcml2YXRlIGxvc2UoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMud29ya2VyKSB0aGlzLnRhYmxlcysrO1xuICAgIHRoaXMudW5hdmFpbGFibGUgPSB0cnVlO1xuICAgIHRoaXMud29ya2VyPy50ZXJtaW5hdGUoKTtcbiAgICB0aGlzLndvcmtlciA9IG51bGw7XG4gICAgY29uc3QgY2FsbHMgPSBbLi4udGhpcy5wZW5kaW5nLnZhbHVlcygpXTtcbiAgICB0aGlzLnBlbmRpbmcuY2xlYXIoKTtcbiAgICBmb3IgKGNvbnN0IGNhbGwgb2YgY2FsbHMpIGNhbGwucmVqZWN0KG5ldyBXb3JrZXJMb3N0RXJyb3IoKSk7XG4gIH1cbn1cblxubGV0IHNoYXJlZDogUmVnaW9uU291cmNlV29ya2VyQ2xpZW50IHwgbnVsbCA9IG51bGw7XG5cbi8qKiBUaGUgd29ya2VyIGNsaWVudCBldmVyeSBHZW9KU09OIHNvdXJjZSBzaGFyZXMuICovXG5leHBvcnQgZnVuY3Rpb24gc2hhcmVkUmVnaW9uU291cmNlQ2xpZW50KCk6IFJlZ2lvblNvdXJjZVdvcmtlckNsaWVudCB7XG4gIHJldHVybiAoc2hhcmVkID8/PSBuZXcgUmVnaW9uU291cmNlV29ya2VyQ2xpZW50KCkpO1xufVxuXG4vKipcbiAqIE9wZW4gYSBHZW9KU09OIEZlYXR1cmVDb2xsZWN0aW9uIHN0cmluZyBhcyBhIHRpbGVkIHJlZ2lvbiBzb3VyY2UuIFJlamVjdHMgb24gaW52YWxpZCBKU09OIG9yXG4gKiBhIGNvbGxlY3Rpb24gd2l0aG91dCBgZmVhdHVyZXNgLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gb3Blbkdlb0pzb25SZWdpb25Tb3VyY2UoXG4gIHRleHQ6IHN0cmluZyxcbiAgY2xpZW50OiBSZWdpb25Tb3VyY2VXb3JrZXJDbGllbnQgPSBzaGFyZWRSZWdpb25Tb3VyY2VDbGllbnQoKSxcbik6IFByb21pc2U8UmVnaW9uU291cmNlPiB7XG4gIC8vIFRoZSB3b3JrZXIgbG9zdCB1bmRlciB0aGUgb3Blbjogb3BlbiBvbiB0aGUgbWFpbiB0aHJlYWQgaW5zdGVhZC5cbiAgY29uc3Qgb3BlbmVkID0gYXdhaXQgY2xpZW50XG4gICAgLnJ1bih7IG9wOiAnb3BlbicsIHRleHQgfSlcbiAgICAuY2F0Y2goKGVycikgPT4gKGVyciBpbnN0YW5jZW9mIFdvcmtlckxvc3RFcnJvciA/IGNsaWVudC5ydW4oeyBvcDogJ29wZW4nLCB0ZXh0IH0pIDogUHJvbWlzZS5yZWplY3QoZXJyKSkpO1xuICBjb25zdCB7IGhhbmRsZSwgaW5mbyB9ID0gb3BlbmVkLnJlc3VsdDtcbiAgcmV0dXJuIG5ldyBXb3JrZXJSZWdpb25Tb3VyY2UoY2xpZW50LCB0ZXh0LCBoYW5kbGUsIG9wZW5lZC5nZW5lcmF0aW9uLCBpbmZvKTtcbn1cblxuLyoqXG4gKiBUaGUgM0QgcmVjb25zdHJ1Y3Rpb24gb2YgYSByZWdpb24gZnJvbSBpdHMgb3V0bGluZXMgb24gYSBzdGFjayAoc2VlIGBnZW9tZXRyeS9yZWNvbnN0cnVjdGApLFxuICogbWVzaGVkIGluIHRoZSByZWdpb24tc291cmNlIHdvcmtlciAob24gdGhlIG1haW4gdGhyZWFkIHdoZXJlIHRoZXJlIGlzIG5vbmUpLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVjb25zdHJ1Y3RJbldvcmtlcihcbiAgc2xpY2VzOiByZWFkb25seSBTbGljZU91dGxpbmVzW10sXG4gIG9wdGlvbnM/OiBSZWNvbnN0cnVjdE9wdGlvbnMsXG4gIGNsaWVudDogUmVnaW9uU291cmNlV29ya2VyQ2xpZW50ID0gc2hhcmVkUmVnaW9uU291cmNlQ2xpZW50KCksXG4pOiBQcm9taXNlPE1lc2g+IHtcbiAgcmV0dXJuIGNsaWVudC5jYWxsKHsgb3A6ICdtZXNoJywgc2xpY2VzLCBvcHRpb25zIH0pO1xufVxuXG5jbGFzcyBXb3JrZXJSZWdpb25Tb3VyY2UgaW1wbGVtZW50cyBSZWdpb25Tb3VyY2Uge1xuICBwcml2YXRlIHJlYWRvbmx5IGNhY2hlID0gbmV3IFJlZ2lvblRpbGVDYWNoZSgpO1xuICBwcml2YXRlIGRpc3Bvc2VkID0gZmFsc2U7XG4gIC8qKiBUaGUgbWFpbi10aHJlYWQgcmUtb3BlbiBhZnRlciB0aGUgd29ya2VyIGRpZWQsIHNoYXJlZCBieSBldmVyeSBjYWxsIHRoYXQgZmluZHMgaXQgc28uICovXG4gIHByaXZhdGUgcmVvcGVuaW5nOiBQcm9taXNlPHZvaWQ+IHwgbnVsbCA9IG51bGw7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBjbGllbnQ6IFJlZ2lvblNvdXJjZVdvcmtlckNsaWVudCxcbiAgICBwcml2YXRlIHJlYWRvbmx5IHRleHQ6IHN0cmluZyxcbiAgICBwcml2YXRlIGhhbmRsZTogbnVtYmVyLFxuICAgIC8qKiBUaGUgY2xpZW50J3Mge0BsaW5rIFJlZ2lvblNvdXJjZVdvcmtlckNsaWVudC5nZW5lcmF0aW9ufSB7QGxpbmsgaGFuZGxlfSB3YXMgb3BlbmVkIHVuZGVyLiAqL1xuICAgIHByaXZhdGUgZ2VuZXJhdGlvbjogbnVtYmVyLFxuICAgIHJlYWRvbmx5IGluZm86IFJlZ2lvblNvdXJjZUluZm8sXG4gICkge31cblxuICBnZXRUaWxlKHo6IG51bWJlciwga2V5OiBSZWdpb25UaWxlS2V5LCBzaWduYWw/OiBBYm9ydFNpZ25hbCk6IFByb21pc2U8UmVnaW9uVGlsZT4ge1xuICAgIGNvbnN0IHRpbGUgPSB0aGlzLmNhY2hlLmdldCh6LCBrZXksICgpID0+XG4gICAgICB0aGlzLmNhbGwoKGhhbmRsZSkgPT4gKHsgb3A6ICd0aWxlJywgaGFuZGxlLCB6LCBsZXZlbDoga2V5LmxldmVsLCBneDoga2V5Lmd4LCBneToga2V5Lmd5IH0pKSxcbiAgICApO1xuICAgIHJldHVybiBhYm9ydGFibGUodGlsZSwgc2lnbmFsKTtcbiAgfVxuXG4gIGdldEZlYXR1cmVzKGlkczogcmVhZG9ubHkgc3RyaW5nW10pOiBQcm9taXNlPFNvdXJjZUZlYXR1cmVbXT4ge1xuICAgIHJldHVybiB0aGlzLmNhbGwoKGhhbmRsZSkgPT4gKHsgb3A6ICdmZWF0dXJlcycsIGhhbmRsZSwgaWRzIH0pKTtcbiAgfVxuXG4gIGdldEluZGV4KHo6IG51bWJlciwgcXVlcnk6IFJlZ2lvbkluZGV4UXVlcnkpOiBQcm9taXNlPFJlZ2lvbkluZGV4UGFnZT4ge1xuICAgIHJldHVybiB0aGlzLmNhbGwoKGhhbmRsZSkgPT4gKHsgb3A6ICdpbmRleCcsIGhhbmRsZSwgeiwgcXVlcnkgfSkpO1xuICB9XG5cbiAgZ2V0Q2xhc3NPdXRsaW5lcyhcbiAgICBjbGFzc2VzOiByZWFkb25seSBzdHJpbmdbXSB8IG51bGwsXG4gICAgbGV2ZWw6IG51bWJlcixcbiAgICBleGNsdWRlPzogcmVhZG9ubHkgc3RyaW5nW10sXG4gICk6IFByb21pc2U8Q2xhc3NPdXRsaW5lc1tdPiB7XG4gICAgcmV0dXJuIHRoaXMuY2FsbCgoaGFuZGxlKSA9PiAoeyBvcDogJ291dGxpbmVzJywgaGFuZGxlLCBjbGFzc2VzLCBsZXZlbCwgZXhjbHVkZSB9KSk7XG4gIH1cblxuICBnZXRDbGFzc0NvdW50cyh6OiBudW1iZXIgfCBudWxsLCBleGNsdWRlPzogcmVhZG9ubHkgc3RyaW5nW10pOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIG51bWJlcj4+IHtcbiAgICByZXR1cm4gdGhpcy5jYWxsKChoYW5kbGUpID0+ICh7IG9wOiAnY2xhc3NlcycsIGhhbmRsZSwgeiwgZXhjbHVkZSB9KSk7XG4gIH1cblxuICBleHBvcnRHZW9Kc29uKGV4Y2x1ZGU6IHJlYWRvbmx5IHN0cmluZ1tdLCBleHRyYTogcmVhZG9ubHkgb2JqZWN0W10pOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIHJldHVybiB0aGlzLmNhbGwoKGhhbmRsZSkgPT4gKHsgb3A6ICdleHBvcnQnLCBoYW5kbGUsIGV4Y2x1ZGUsIGV4dHJhIH0pKTtcbiAgfVxuXG4gIGRpc3Bvc2UoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuZGlzcG9zZWQpIHJldHVybjtcbiAgICB0aGlzLmRpc3Bvc2VkID0gdHJ1ZTtcbiAgICB0aGlzLmNhY2hlLmNsZWFyKCk7XG4gICAgLy8gQSBoYW5kbGUgZnJvbSBhIGxvc3Qgd29ya2VyJ3MgdGFibGVzIG5hbWVzIG5vdGhpbmcgaGVyZSwgb3IgYW5vdGhlciBzb3VyY2UncyB0YWJsZS5cbiAgICBpZiAodGhpcy5nZW5lcmF0aW9uICE9PSB0aGlzLmNsaWVudC5nZW5lcmF0aW9uKSByZXR1cm47XG4gICAgdm9pZCB0aGlzLmNsaWVudC5jYWxsKHsgb3A6ICdjbG9zZScsIGhhbmRsZTogdGhpcy5oYW5kbGUgfSkuY2F0Y2goKCkgPT4gdW5kZWZpbmVkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW4gYSByZXF1ZXN0IG9uIHRoaXMgc291cmNlJ3MgdGFibGU7IHdoZW4gdGhlIHdvcmtlciBkaWVkICh1bmRlciB0aGlzIGNhbGwgb3IgYmVmb3JlIGl0KSxcbiAgICogcmUtb3BlbiBoZXJlIGFuZCBydW4gaXQgdGhlcmUuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGNhbGw8UiBleHRlbmRzIFJlZ2lvblNvdXJjZVJlcXVlc3Q+KFxuICAgIG1ha2U6IChoYW5kbGU6IG51bWJlcikgPT4gUixcbiAgKTogUHJvbWlzZTxSZWdpb25Tb3VyY2VSZXN1bHRzW1JbJ29wJ11dPiB7XG4gICAgZm9yIChsZXQgYXR0ZW1wdCA9IDA7IDsgYXR0ZW1wdCsrKSB7XG4gICAgICBpZiAodGhpcy5nZW5lcmF0aW9uICE9PSB0aGlzLmNsaWVudC5nZW5lcmF0aW9uKSBhd2FpdCB0aGlzLnJlb3BlbigpO1xuICAgICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuY2xpZW50LmNhbGwobWFrZSh0aGlzLmhhbmRsZSkpO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIGlmICghKGVyciBpbnN0YW5jZW9mIFdvcmtlckxvc3RFcnJvcikgfHwgYXR0ZW1wdCA+IDApIHRocm93IGVycjtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKiogT3BlbiB0aGlzIHNvdXJjZSdzIHRleHQgYWdhaW4gb24gdGhlIGNsaWVudCdzIGN1cnJlbnQgdGFibGVzLCBvbmNlIGZvciBldmVyeSBjYWxsIHdhaXRpbmcuICovXG4gIHByaXZhdGUgcmVvcGVuKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMucmVvcGVuaW5nID8/PSB0aGlzLmNsaWVudFxuICAgICAgLnJ1bih7IG9wOiAnb3BlbicsIHRleHQ6IHRoaXMudGV4dCB9KVxuICAgICAgLnRoZW4oKHsgcmVzdWx0LCBnZW5lcmF0aW9uIH0pID0+IHtcbiAgICAgICAgdGhpcy5oYW5kbGUgPSByZXN1bHQuaGFuZGxlO1xuICAgICAgICB0aGlzLmdlbmVyYXRpb24gPSBnZW5lcmF0aW9uO1xuICAgICAgfSlcbiAgICAgIC5maW5hbGx5KCgpID0+ICh0aGlzLnJlb3BlbmluZyA9IG51bGwpKTtcbiAgICByZXR1cm4gdGhpcy5yZW9wZW5pbmc7XG4gIH1cbn1cbiJdfQ==