obsidian-dev-utils 83.2.0 → 84.0.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 (63) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/dist/dev/main.js +2463 -1744
  3. package/dist/lib/cjs/generated-during-build.cjs +2 -2
  4. package/dist/lib/cjs/obsidian/components/plugin-notice-component.cjs +139 -8
  5. package/dist/lib/cjs/obsidian/components/plugin-notice-component.d.cts +94 -0
  6. package/dist/lib/cjs/obsidian/components/rename-delete-handler-component.cjs +10 -10
  7. package/dist/lib/cjs/obsidian/components/rename-delete-handler-component.d.cts +3 -3
  8. package/dist/lib/cjs/obsidian/css-class.cjs +2 -1
  9. package/dist/lib/cjs/obsidian/css-class.d.cts +5 -0
  10. package/dist/lib/cjs/obsidian/editor.cjs +1 -1
  11. package/dist/lib/cjs/obsidian/editor.d.cts +2 -2
  12. package/dist/lib/cjs/obsidian/file-manager.cjs +9 -9
  13. package/dist/lib/cjs/obsidian/file-manager.d.cts +9 -9
  14. package/dist/lib/cjs/obsidian/i18n/locales/en.cjs +8 -8
  15. package/dist/lib/cjs/obsidian/i18n/locales/en.d.cts +7 -7
  16. package/dist/lib/cjs/obsidian/i18n/locales/translations-map.d.cts +7 -7
  17. package/dist/lib/cjs/obsidian/index.cjs +7 -4
  18. package/dist/lib/cjs/obsidian/index.d.cts +2 -1
  19. package/dist/lib/cjs/obsidian/markdown-code-block-processor.cjs +7 -7
  20. package/dist/lib/cjs/obsidian/markdown-code-block-processor.d.cts +9 -9
  21. package/dist/lib/cjs/obsidian/plugin/plugin.cjs +21 -21
  22. package/dist/lib/cjs/obsidian/plugin/plugin.d.cts +15 -15
  23. package/dist/lib/cjs/obsidian/resource-lock.cjs +899 -0
  24. package/dist/lib/cjs/obsidian/resource-lock.d.cts +227 -0
  25. package/dist/lib/cjs/obsidian/vault-transaction.cjs +371 -0
  26. package/dist/lib/cjs/obsidian/vault-transaction.d.cts +146 -0
  27. package/dist/lib/cjs/obsidian/vault.cjs +4 -4
  28. package/dist/lib/cjs/obsidian/vault.d.cts +3 -3
  29. package/dist/lib/esm/generated-during-build.mjs +2 -2
  30. package/dist/lib/esm/obsidian/components/plugin-notice-component.d.mts +94 -0
  31. package/dist/lib/esm/obsidian/components/plugin-notice-component.mjs +143 -9
  32. package/dist/lib/esm/obsidian/components/rename-delete-handler-component.d.mts +3 -3
  33. package/dist/lib/esm/obsidian/components/rename-delete-handler-component.mjs +10 -10
  34. package/dist/lib/esm/obsidian/css-class.d.mts +5 -0
  35. package/dist/lib/esm/obsidian/css-class.mjs +2 -1
  36. package/dist/lib/esm/obsidian/editor.d.mts +2 -2
  37. package/dist/lib/esm/obsidian/editor.mjs +1 -1
  38. package/dist/lib/esm/obsidian/file-manager.d.mts +9 -9
  39. package/dist/lib/esm/obsidian/file-manager.mjs +9 -9
  40. package/dist/lib/esm/obsidian/i18n/locales/en.d.mts +7 -7
  41. package/dist/lib/esm/obsidian/i18n/locales/en.mjs +8 -8
  42. package/dist/lib/esm/obsidian/i18n/locales/translations-map.d.mts +7 -7
  43. package/dist/lib/esm/obsidian/index.d.mts +2 -1
  44. package/dist/lib/esm/obsidian/index.mjs +5 -3
  45. package/dist/lib/esm/obsidian/markdown-code-block-processor.d.mts +9 -9
  46. package/dist/lib/esm/obsidian/markdown-code-block-processor.mjs +7 -7
  47. package/dist/lib/esm/obsidian/plugin/plugin.d.mts +15 -15
  48. package/dist/lib/esm/obsidian/plugin/plugin.mjs +21 -21
  49. package/dist/lib/esm/obsidian/resource-lock.d.mts +227 -0
  50. package/dist/lib/esm/obsidian/resource-lock.mjs +799 -0
  51. package/dist/lib/esm/obsidian/vault-transaction.d.mts +146 -0
  52. package/dist/lib/esm/obsidian/vault-transaction.mjs +271 -0
  53. package/dist/lib/esm/obsidian/vault.d.mts +3 -3
  54. package/dist/lib/esm/obsidian/vault.mjs +4 -4
  55. package/dist/styles.css +8 -1
  56. package/obsidian/resource-lock/package.json +6 -0
  57. package/obsidian/vault-transaction/package.json +6 -0
  58. package/package.json +2 -2
  59. package/dist/lib/cjs/obsidian/editor-lock.cjs +0 -545
  60. package/dist/lib/cjs/obsidian/editor-lock.d.cts +0 -142
  61. package/dist/lib/esm/obsidian/editor-lock.d.mts +0 -142
  62. package/dist/lib/esm/obsidian/editor-lock.mjs +0 -442
  63. package/obsidian/editor-lock/package.json +0 -6
@@ -0,0 +1,146 @@
1
+ /// <reference path="../library.d.mts" />
2
+ /**
3
+ * @file
4
+ *
5
+ * A reversible, transactional log of vault mutations. Each mutation records how to undo itself;
6
+ * {@link VaultTransaction.rollback} reverses the completed steps in reverse order and
7
+ * {@link VaultTransaction.commit} finalizes them. It is built on the `*Safe` vault wrappers so it
8
+ * inherits their case-insensitive / retry / missing-file handling.
9
+ *
10
+ * A deletion is performed as a **soft-delete**: the resource is moved aside into a dot-prefixed
11
+ * staging folder (a folder moves its whole subtree in a single rename, so subtree rollback is cheap
12
+ * and faithful). Because Obsidian's vault file-tree and file watcher ignore any `.`-prefixed path,
13
+ * staged resources are **untracked** — they do not churn the metadata cache, flash in the file
14
+ * explorer, or get propagated by sync while the transaction is in flight. The flip side is that
15
+ * `vault.*` methods cannot see the staging area, so ALL staging I/O goes through
16
+ * {@link App.vault.adapter} (`mkdir`/`rename`/`exists`/`trashSystem`/`rmdir`).
17
+ * {@link VaultTransaction.commit} then trashes the staged resources for real; {@link VaultTransaction.rollback}
18
+ * moves them back.
19
+ */
20
+ import type { App, TFile } from 'obsidian';
21
+ import type { PathOrAbstractFile } from './file-system.mjs';
22
+ /**
23
+ * Parameters for the {@link VaultTransaction} constructor.
24
+ */
25
+ export interface VaultTransactionConstructorParams {
26
+ /**
27
+ * The Obsidian application instance.
28
+ */
29
+ readonly app: App;
30
+ /**
31
+ * Opens an ambient mutation-bypass scope covering the paths this transaction touches, so the
32
+ * transaction's own writes pass a `shouldBlockMutations` lock that the owning operation holds. It is
33
+ * called once when the transaction is constructed, and the returned {@link Disposable} is disposed
34
+ * when the transaction settles (on `commit`, `rollback`, or `await using` disposal) — so the bypass
35
+ * stays active through rollback, including auto-rollback, which a caller managing the scope itself
36
+ * could easily get wrong. Typically
37
+ * `() => resourceLockComponent.bypassBlockedMutations(lockedPathsOrFiles)`. Omit it for the common
38
+ * standalone case where the transaction operates on unlocked paths.
39
+ *
40
+ * @returns A {@link Disposable} that ends the bypass scope.
41
+ */
42
+ openMutationBypass?(this: void): Disposable;
43
+ /**
44
+ * The dot-prefixed folder that soft-deleted resources are moved into until the transaction is
45
+ * committed or rolled back. It must stay `.`-prefixed so Obsidian leaves the staged resources
46
+ * untracked.
47
+ *
48
+ * @default `'.obsidian-dev-utils-temp'`
49
+ */
50
+ readonly stagingFolderPath?: string;
51
+ }
52
+ /**
53
+ * A reversible log of vault mutations. Perform mutations through its methods, then call
54
+ * {@link VaultTransaction.commit} on success or {@link VaultTransaction.rollback} on failure. It is
55
+ * `await using`-friendly: if neither is called, disposal rolls back.
56
+ */
57
+ export declare class VaultTransaction {
58
+ private readonly app;
59
+ private hasStagingFolder;
60
+ private mutationBypass;
61
+ private readonly stagedTrashPaths;
62
+ private readonly stagingFolderPath;
63
+ private state;
64
+ private readonly undoSteps;
65
+ /**
66
+ * Creates a new vault transaction.
67
+ *
68
+ * @param params - The parameters.
69
+ */
70
+ constructor(params: VaultTransactionConstructorParams);
71
+ /**
72
+ * Commits the transaction: finalizes soft-deletes by trashing the staged resources for real and
73
+ * removes the staging folder. After this the transaction can no longer be mutated or rolled back.
74
+ *
75
+ * @returns A {@link Promise} that resolves when the commit completes.
76
+ */
77
+ commit(): Promise<void>;
78
+ /**
79
+ * Creates a file with the given content, recording its removal as the inverse.
80
+ *
81
+ * @param path - The path of the file to create.
82
+ * @param data - The content of the file.
83
+ * @returns A {@link Promise} resolving to the created {@link TFile}.
84
+ */
85
+ create(path: string, data: string): Promise<TFile>;
86
+ /**
87
+ * Creates a folder (including missing ancestors), recording its removal as the inverse. A no-op if
88
+ * the folder already exists.
89
+ *
90
+ * @param path - The path of the folder to create.
91
+ * @returns A {@link Promise} that resolves when the folder exists.
92
+ */
93
+ createFolder(path: string): Promise<void>;
94
+ /**
95
+ * Replaces the content of a file, capturing the old content so it can be restored on rollback.
96
+ *
97
+ * @param pathOrFile - The path or file to modify.
98
+ * @param newContent - The new content.
99
+ * @returns A {@link Promise} that resolves when the file is modified.
100
+ */
101
+ modify(pathOrFile: PathOrAbstractFile, newContent: string): Promise<void>;
102
+ /**
103
+ * Transforms the content of a file, capturing the old content so it can be restored on rollback.
104
+ *
105
+ * @param pathOrFile - The path or file to process.
106
+ * @param newContentProvider - Maps the current content to the new content.
107
+ * @returns A {@link Promise} that resolves when the file is processed.
108
+ */
109
+ process(pathOrFile: PathOrAbstractFile, newContentProvider: (content: string) => string): Promise<void>;
110
+ /**
111
+ * Renames or moves a resource, recording the reverse rename as the inverse.
112
+ *
113
+ * @param oldPathOrFile - The resource to rename.
114
+ * @param newPath - The desired new path (an available path is chosen if it is taken).
115
+ * @returns A {@link Promise} resolving to the actual new path.
116
+ */
117
+ rename(oldPathOrFile: PathOrAbstractFile, newPath: string): Promise<string>;
118
+ /**
119
+ * Rolls back the transaction: undoes the completed steps in reverse order and removes the staging
120
+ * folder. Idempotent.
121
+ *
122
+ * @returns A {@link Promise} that resolves when the rollback completes.
123
+ */
124
+ rollback(): Promise<void>;
125
+ /**
126
+ * Rolls back the transaction on disposal unless it was already committed or rolled back.
127
+ */
128
+ [Symbol.asyncDispose](): Promise<void>;
129
+ /**
130
+ * Soft-deletes a resource by moving it into the staging folder, recording the move-back as the
131
+ * inverse. The real trash happens on {@link VaultTransaction.commit}. A no-op if the resource does
132
+ * not exist.
133
+ *
134
+ * @param pathOrFile - The path or resource to trash.
135
+ * @returns A {@link Promise} that resolves when the resource has been staged.
136
+ */
137
+ trash(pathOrFile: PathOrAbstractFile): Promise<void>;
138
+ private assertNotCommitted;
139
+ private assertOpen;
140
+ private disposeMutationBypass;
141
+ private ensureStagingFolder;
142
+ private getAvailableStagedPath;
143
+ private hardDelete;
144
+ private pushUndo;
145
+ private removeStagingFolder;
146
+ }
@@ -0,0 +1,271 @@
1
+ /*
2
+ THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
3
+ if you want to view the source, please visit the github repository of this plugin
4
+ */
5
+
6
+ (function initEsm() {
7
+ // eslint-disable-next-line obsidianmd/no-global-this -- Actively use globalThis.
8
+ if (globalThis.process) {
9
+ return;
10
+ }
11
+
12
+ const browserProcess = {
13
+ browser: true,
14
+ cwd() {
15
+ return '/';
16
+ },
17
+ env: {},
18
+ platform: 'android'
19
+ };
20
+ // eslint-disable-next-line obsidianmd/no-global-this -- Actively use globalThis.
21
+ globalThis.process = browserProcess;
22
+ })();
23
+
24
+ import { assertNonNullable } from "../type-guards.mjs";
25
+ import {
26
+ getAbstractFileOrNull,
27
+ getPath
28
+ } from "./file-system.mjs";
29
+ import {
30
+ createFolderSafe,
31
+ process,
32
+ readSafe,
33
+ renameSafe
34
+ } from "./vault.mjs";
35
+ const DEFAULT_STAGING_FOLDER_PATH = ".obsidian-dev-utils-temp";
36
+ class VaultTransaction {
37
+ app;
38
+ hasStagingFolder = false;
39
+ mutationBypass = null;
40
+ stagedTrashPaths = [];
41
+ stagingFolderPath;
42
+ state = "open";
43
+ undoSteps = [];
44
+ /**
45
+ * Creates a new vault transaction.
46
+ *
47
+ * @param params - The parameters.
48
+ */
49
+ constructor(params) {
50
+ this.app = params.app;
51
+ this.stagingFolderPath = params.stagingFolderPath ?? DEFAULT_STAGING_FOLDER_PATH;
52
+ this.mutationBypass = params.openMutationBypass?.() ?? null;
53
+ }
54
+ /**
55
+ * Commits the transaction: finalizes soft-deletes by trashing the staged resources for real and
56
+ * removes the staging folder. After this the transaction can no longer be mutated or rolled back.
57
+ *
58
+ * @returns A {@link Promise} that resolves when the commit completes.
59
+ */
60
+ async commit() {
61
+ this.assertOpen();
62
+ this.state = "committed";
63
+ const adapter = this.app.vault.adapter;
64
+ for (const stagedPath of this.stagedTrashPaths) {
65
+ const wasTrashedToSystem = await adapter.trashSystem(stagedPath);
66
+ if (!wasTrashedToSystem) {
67
+ await adapter.trashLocal(stagedPath);
68
+ }
69
+ }
70
+ await this.removeStagingFolder();
71
+ this.disposeMutationBypass();
72
+ }
73
+ /**
74
+ * Creates a file with the given content, recording its removal as the inverse.
75
+ *
76
+ * @param path - The path of the file to create.
77
+ * @param data - The content of the file.
78
+ * @returns A {@link Promise} resolving to the created {@link TFile}.
79
+ */
80
+ async create(path, data) {
81
+ this.assertOpen();
82
+ const file = await this.app.vault.create(path, data);
83
+ const createdPath = file.path;
84
+ this.pushUndo(async () => {
85
+ await this.hardDelete(createdPath);
86
+ });
87
+ return file;
88
+ }
89
+ /**
90
+ * Creates a folder (including missing ancestors), recording its removal as the inverse. A no-op if
91
+ * the folder already exists.
92
+ *
93
+ * @param path - The path of the folder to create.
94
+ * @returns A {@link Promise} that resolves when the folder exists.
95
+ */
96
+ async createFolder(path) {
97
+ this.assertOpen();
98
+ const wasCreated = await createFolderSafe(this.app, path);
99
+ if (wasCreated) {
100
+ this.pushUndo(async () => {
101
+ await this.hardDelete(path);
102
+ });
103
+ }
104
+ }
105
+ /**
106
+ * Replaces the content of a file, capturing the old content so it can be restored on rollback.
107
+ *
108
+ * @param pathOrFile - The path or file to modify.
109
+ * @param newContent - The new content.
110
+ * @returns A {@link Promise} that resolves when the file is modified.
111
+ */
112
+ async modify(pathOrFile, newContent) {
113
+ await this.process(pathOrFile, () => newContent);
114
+ }
115
+ /**
116
+ * Transforms the content of a file, capturing the old content so it can be restored on rollback.
117
+ *
118
+ * @param pathOrFile - The path or file to process.
119
+ * @param newContentProvider - Maps the current content to the new content.
120
+ * @returns A {@link Promise} that resolves when the file is processed.
121
+ */
122
+ async process(pathOrFile, newContentProvider) {
123
+ this.assertOpen();
124
+ const path = getPath(this.app, pathOrFile);
125
+ const oldContent = await readSafe(this.app, path);
126
+ await process({
127
+ app: this.app,
128
+ newContentProvider: ({ content }) => newContentProvider(content),
129
+ pathOrFile: path,
130
+ resourceLockComponent: null
131
+ });
132
+ assertNonNullable(oldContent);
133
+ this.pushUndo(async () => {
134
+ await process({
135
+ app: this.app,
136
+ newContentProvider: oldContent,
137
+ pathOrFile: path,
138
+ resourceLockComponent: null
139
+ });
140
+ });
141
+ }
142
+ /**
143
+ * Renames or moves a resource, recording the reverse rename as the inverse.
144
+ *
145
+ * @param oldPathOrFile - The resource to rename.
146
+ * @param newPath - The desired new path (an available path is chosen if it is taken).
147
+ * @returns A {@link Promise} resolving to the actual new path.
148
+ */
149
+ async rename(oldPathOrFile, newPath) {
150
+ this.assertOpen();
151
+ const oldPath = getPath(this.app, oldPathOrFile);
152
+ const actualNewPath = await renameSafe({ app: this.app, newPath, oldPathOrAbstractFile: oldPathOrFile });
153
+ this.pushUndo(async () => {
154
+ await renameSafe({ app: this.app, newPath: oldPath, oldPathOrAbstractFile: actualNewPath });
155
+ });
156
+ return actualNewPath;
157
+ }
158
+ /**
159
+ * Rolls back the transaction: undoes the completed steps in reverse order and removes the staging
160
+ * folder. Idempotent.
161
+ *
162
+ * @returns A {@link Promise} that resolves when the rollback completes.
163
+ */
164
+ async rollback() {
165
+ if (this.state === "rolledBack") {
166
+ return;
167
+ }
168
+ this.assertNotCommitted();
169
+ this.state = "rolledBack";
170
+ for (const step of [...this.undoSteps].reverse()) {
171
+ await step.undo();
172
+ }
173
+ await this.removeStagingFolder();
174
+ this.disposeMutationBypass();
175
+ }
176
+ /**
177
+ * Rolls back the transaction on disposal unless it was already committed or rolled back.
178
+ */
179
+ async [Symbol.asyncDispose]() {
180
+ if (this.state === "open") {
181
+ await this.rollback();
182
+ }
183
+ }
184
+ /**
185
+ * Soft-deletes a resource by moving it into the staging folder, recording the move-back as the
186
+ * inverse. The real trash happens on {@link VaultTransaction.commit}. A no-op if the resource does
187
+ * not exist.
188
+ *
189
+ * @param pathOrFile - The path or resource to trash.
190
+ * @returns A {@link Promise} that resolves when the resource has been staged.
191
+ */
192
+ async trash(pathOrFile) {
193
+ this.assertOpen();
194
+ const file = getAbstractFileOrNull({ app: this.app, pathOrFile });
195
+ if (!file) {
196
+ return;
197
+ }
198
+ const originalPath = file.path;
199
+ await this.ensureStagingFolder();
200
+ const stagedPath = await this.getAvailableStagedPath(file.name);
201
+ const adapter = this.app.vault.adapter;
202
+ await adapter.rename(originalPath, stagedPath);
203
+ this.stagedTrashPaths.push(stagedPath);
204
+ this.pushUndo(async () => {
205
+ if (await adapter.exists(stagedPath)) {
206
+ await adapter.rename(stagedPath, originalPath);
207
+ }
208
+ });
209
+ }
210
+ assertNotCommitted() {
211
+ if (this.state === "committed") {
212
+ throw new Error("Cannot roll back a committed transaction.");
213
+ }
214
+ }
215
+ assertOpen() {
216
+ if (this.state !== "open") {
217
+ throw new Error(`Cannot mutate a ${this.state} transaction.`);
218
+ }
219
+ }
220
+ disposeMutationBypass() {
221
+ this.mutationBypass?.[Symbol.dispose]();
222
+ this.mutationBypass = null;
223
+ }
224
+ async ensureStagingFolder() {
225
+ if (this.hasStagingFolder) {
226
+ return;
227
+ }
228
+ const adapter = this.app.vault.adapter;
229
+ if (!await adapter.exists(this.stagingFolderPath)) {
230
+ await adapter.mkdir(this.stagingFolderPath);
231
+ }
232
+ this.hasStagingFolder = true;
233
+ }
234
+ async getAvailableStagedPath(name) {
235
+ const adapter = this.app.vault.adapter;
236
+ const dotIndex = name.lastIndexOf(".");
237
+ const hasExtension = dotIndex > 0;
238
+ const baseName = hasExtension ? name.slice(0, dotIndex) : name;
239
+ const extension = hasExtension ? name.slice(dotIndex) : "";
240
+ let candidate = `${this.stagingFolderPath}/${name}`;
241
+ let counter = 1;
242
+ while (await adapter.exists(candidate)) {
243
+ candidate = `${this.stagingFolderPath}/${baseName} ${counter.toString()}${extension}`;
244
+ counter++;
245
+ }
246
+ return candidate;
247
+ }
248
+ async hardDelete(path) {
249
+ const file = getAbstractFileOrNull({ app: this.app, pathOrFile: path });
250
+ if (file) {
251
+ await this.app.vault.delete(file, true);
252
+ }
253
+ }
254
+ pushUndo(undo) {
255
+ this.undoSteps.push({ undo });
256
+ }
257
+ async removeStagingFolder() {
258
+ if (!this.hasStagingFolder) {
259
+ return;
260
+ }
261
+ this.hasStagingFolder = false;
262
+ const adapter = this.app.vault.adapter;
263
+ if (await adapter.exists(this.stagingFolderPath)) {
264
+ await adapter.rmdir(this.stagingFolderPath, true);
265
+ }
266
+ }
267
+ }
268
+ export {
269
+ VaultTransaction
270
+ };
271
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vLi4vc3JjL29ic2lkaWFuL3ZhdWx0LXRyYW5zYWN0aW9uLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvKipcbiAqIEBmaWxlXG4gKlxuICogQSByZXZlcnNpYmxlLCB0cmFuc2FjdGlvbmFsIGxvZyBvZiB2YXVsdCBtdXRhdGlvbnMuIEVhY2ggbXV0YXRpb24gcmVjb3JkcyBob3cgdG8gdW5kbyBpdHNlbGY7XG4gKiB7QGxpbmsgVmF1bHRUcmFuc2FjdGlvbi5yb2xsYmFja30gcmV2ZXJzZXMgdGhlIGNvbXBsZXRlZCBzdGVwcyBpbiByZXZlcnNlIG9yZGVyIGFuZFxuICoge0BsaW5rIFZhdWx0VHJhbnNhY3Rpb24uY29tbWl0fSBmaW5hbGl6ZXMgdGhlbS4gSXQgaXMgYnVpbHQgb24gdGhlIGAqU2FmZWAgdmF1bHQgd3JhcHBlcnMgc28gaXRcbiAqIGluaGVyaXRzIHRoZWlyIGNhc2UtaW5zZW5zaXRpdmUgLyByZXRyeSAvIG1pc3NpbmctZmlsZSBoYW5kbGluZy5cbiAqXG4gKiBBIGRlbGV0aW9uIGlzIHBlcmZvcm1lZCBhcyBhICoqc29mdC1kZWxldGUqKjogdGhlIHJlc291cmNlIGlzIG1vdmVkIGFzaWRlIGludG8gYSBkb3QtcHJlZml4ZWRcbiAqIHN0YWdpbmcgZm9sZGVyIChhIGZvbGRlciBtb3ZlcyBpdHMgd2hvbGUgc3VidHJlZSBpbiBhIHNpbmdsZSByZW5hbWUsIHNvIHN1YnRyZWUgcm9sbGJhY2sgaXMgY2hlYXBcbiAqIGFuZCBmYWl0aGZ1bCkuIEJlY2F1c2UgT2JzaWRpYW4ncyB2YXVsdCBmaWxlLXRyZWUgYW5kIGZpbGUgd2F0Y2hlciBpZ25vcmUgYW55IGAuYC1wcmVmaXhlZCBwYXRoLFxuICogc3RhZ2VkIHJlc291cmNlcyBhcmUgKip1bnRyYWNrZWQqKiBcdTIwMTQgdGhleSBkbyBub3QgY2h1cm4gdGhlIG1ldGFkYXRhIGNhY2hlLCBmbGFzaCBpbiB0aGUgZmlsZVxuICogZXhwbG9yZXIsIG9yIGdldCBwcm9wYWdhdGVkIGJ5IHN5bmMgd2hpbGUgdGhlIHRyYW5zYWN0aW9uIGlzIGluIGZsaWdodC4gVGhlIGZsaXAgc2lkZSBpcyB0aGF0XG4gKiBgdmF1bHQuKmAgbWV0aG9kcyBjYW5ub3Qgc2VlIHRoZSBzdGFnaW5nIGFyZWEsIHNvIEFMTCBzdGFnaW5nIEkvTyBnb2VzIHRocm91Z2hcbiAqIHtAbGluayBBcHAudmF1bHQuYWRhcHRlcn0gKGBta2RpcmAvYHJlbmFtZWAvYGV4aXN0c2AvYHRyYXNoU3lzdGVtYC9gcm1kaXJgKS5cbiAqIHtAbGluayBWYXVsdFRyYW5zYWN0aW9uLmNvbW1pdH0gdGhlbiB0cmFzaGVzIHRoZSBzdGFnZWQgcmVzb3VyY2VzIGZvciByZWFsOyB7QGxpbmsgVmF1bHRUcmFuc2FjdGlvbi5yb2xsYmFja31cbiAqIG1vdmVzIHRoZW0gYmFjay5cbiAqL1xuXG5pbXBvcnQgdHlwZSB7XG4gIEFwcCxcbiAgVEZpbGVcbn0gZnJvbSAnb2JzaWRpYW4nO1xuXG5pbXBvcnQgdHlwZSB7IFBhdGhPckFic3RyYWN0RmlsZSB9IGZyb20gJy4vZmlsZS1zeXN0ZW0udHMnO1xuXG5pbXBvcnQgeyBhc3NlcnROb25OdWxsYWJsZSB9IGZyb20gJy4uL3R5cGUtZ3VhcmRzLnRzJztcbmltcG9ydCB7XG4gIGdldEFic3RyYWN0RmlsZU9yTnVsbCxcbiAgZ2V0UGF0aFxufSBmcm9tICcuL2ZpbGUtc3lzdGVtLnRzJztcbmltcG9ydCB7XG4gIGNyZWF0ZUZvbGRlclNhZmUsXG4gIHByb2Nlc3MsXG4gIHJlYWRTYWZlLFxuICByZW5hbWVTYWZlXG59IGZyb20gJy4vdmF1bHQudHMnO1xuXG5jb25zdCBERUZBVUxUX1NUQUdJTkdfRk9MREVSX1BBVEggPSAnLm9ic2lkaWFuLWRldi11dGlscy10ZW1wJztcblxuLyoqXG4gKiBQYXJhbWV0ZXJzIGZvciB0aGUge0BsaW5rIFZhdWx0VHJhbnNhY3Rpb259IGNvbnN0cnVjdG9yLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFZhdWx0VHJhbnNhY3Rpb25Db25zdHJ1Y3RvclBhcmFtcyB7XG4gIC8qKlxuICAgKiBUaGUgT2JzaWRpYW4gYXBwbGljYXRpb24gaW5zdGFuY2UuXG4gICAqL1xuICByZWFkb25seSBhcHA6IEFwcDtcblxuICAvKipcbiAgICogT3BlbnMgYW4gYW1iaWVudCBtdXRhdGlvbi1ieXBhc3Mgc2NvcGUgY292ZXJpbmcgdGhlIHBhdGhzIHRoaXMgdHJhbnNhY3Rpb24gdG91Y2hlcywgc28gdGhlXG4gICAqIHRyYW5zYWN0aW9uJ3Mgb3duIHdyaXRlcyBwYXNzIGEgYHNob3VsZEJsb2NrTXV0YXRpb25zYCBsb2NrIHRoYXQgdGhlIG93bmluZyBvcGVyYXRpb24gaG9sZHMuIEl0IGlzXG4gICAqIGNhbGxlZCBvbmNlIHdoZW4gdGhlIHRyYW5zYWN0aW9uIGlzIGNvbnN0cnVjdGVkLCBhbmQgdGhlIHJldHVybmVkIHtAbGluayBEaXNwb3NhYmxlfSBpcyBkaXNwb3NlZFxuICAgKiB3aGVuIHRoZSB0cmFuc2FjdGlvbiBzZXR0bGVzIChvbiBgY29tbWl0YCwgYHJvbGxiYWNrYCwgb3IgYGF3YWl0IHVzaW5nYCBkaXNwb3NhbCkgXHUyMDE0IHNvIHRoZSBieXBhc3NcbiAgICogc3RheXMgYWN0aXZlIHRocm91Z2ggcm9sbGJhY2ssIGluY2x1ZGluZyBhdXRvLXJvbGxiYWNrLCB3aGljaCBhIGNhbGxlciBtYW5hZ2luZyB0aGUgc2NvcGUgaXRzZWxmXG4gICAqIGNvdWxkIGVhc2lseSBnZXQgd3JvbmcuIFR5cGljYWxseVxuICAgKiBgKCkgPT4gcmVzb3VyY2VMb2NrQ29tcG9uZW50LmJ5cGFzc0Jsb2NrZWRNdXRhdGlvbnMobG9ja2VkUGF0aHNPckZpbGVzKWAuIE9taXQgaXQgZm9yIHRoZSBjb21tb25cbiAgICogc3RhbmRhbG9uZSBjYXNlIHdoZXJlIHRoZSB0cmFuc2FjdGlvbiBvcGVyYXRlcyBvbiB1bmxvY2tlZCBwYXRocy5cbiAgICpcbiAgICogQHJldHVybnMgQSB7QGxpbmsgRGlzcG9zYWJsZX0gdGhhdCBlbmRzIHRoZSBieXBhc3Mgc2NvcGUuXG4gICAqL1xuICBvcGVuTXV0YXRpb25CeXBhc3M/KHRoaXM6IHZvaWQpOiBEaXNwb3NhYmxlO1xuXG4gIC8qKlxuICAgKiBUaGUgZG90LXByZWZpeGVkIGZvbGRlciB0aGF0IHNvZnQtZGVsZXRlZCByZXNvdXJjZXMgYXJlIG1vdmVkIGludG8gdW50aWwgdGhlIHRyYW5zYWN0aW9uIGlzXG4gICAqIGNvbW1pdHRlZCBvciByb2xsZWQgYmFjay4gSXQgbXVzdCBzdGF5IGAuYC1wcmVmaXhlZCBzbyBPYnNpZGlhbiBsZWF2ZXMgdGhlIHN0YWdlZCByZXNvdXJjZXNcbiAgICogdW50cmFja2VkLlxuICAgKlxuICAgKiBAZGVmYXVsdCBgJy5vYnNpZGlhbi1kZXYtdXRpbHMtdGVtcCdgXG4gICAqL1xuICByZWFkb25seSBzdGFnaW5nRm9sZGVyUGF0aD86IHN0cmluZztcbn1cblxudHlwZSBUcmFuc2FjdGlvblN0YXRlID0gJ2NvbW1pdHRlZCcgfCAnb3BlbicgfCAncm9sbGVkQmFjayc7XG5cbmludGVyZmFjZSBVbmRvU3RlcCB7XG4gIHVuZG8odGhpczogdm9pZCk6IFByb21pc2U8dm9pZD47XG59XG5cbi8qKlxuICogQSByZXZlcnNpYmxlIGxvZyBvZiB2YXVsdCBtdXRhdGlvbnMuIFBlcmZvcm0gbXV0YXRpb25zIHRocm91Z2ggaXRzIG1ldGhvZHMsIHRoZW4gY2FsbFxuICoge0BsaW5rIFZhdWx0VHJhbnNhY3Rpb24uY29tbWl0fSBvbiBzdWNjZXNzIG9yIHtAbGluayBWYXVsdFRyYW5zYWN0aW9uLnJvbGxiYWNrfSBvbiBmYWlsdXJlLiBJdCBpc1xuICogYGF3YWl0IHVzaW5nYC1mcmllbmRseTogaWYgbmVpdGhlciBpcyBjYWxsZWQsIGRpc3Bvc2FsIHJvbGxzIGJhY2suXG4gKi9cbmV4cG9ydCBjbGFzcyBWYXVsdFRyYW5zYWN0aW9uIHtcbiAgcHJpdmF0ZSByZWFkb25seSBhcHA6IEFwcDtcbiAgcHJpdmF0ZSBoYXNTdGFnaW5nRm9sZGVyID0gZmFsc2U7XG4gIHByaXZhdGUgbXV0YXRpb25CeXBhc3M6IERpc3Bvc2FibGUgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSByZWFkb25seSBzdGFnZWRUcmFzaFBhdGhzOiBzdHJpbmdbXSA9IFtdO1xuICBwcml2YXRlIHJlYWRvbmx5IHN0YWdpbmdGb2xkZXJQYXRoOiBzdHJpbmc7XG4gIHByaXZhdGUgc3RhdGU6IFRyYW5zYWN0aW9uU3RhdGUgPSAnb3Blbic7XG4gIHByaXZhdGUgcmVhZG9ubHkgdW5kb1N0ZXBzOiBVbmRvU3RlcFtdID0gW107XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBuZXcgdmF1bHQgdHJhbnNhY3Rpb24uXG4gICAqXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBUaGUgcGFyYW1ldGVycy5cbiAgICovXG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihwYXJhbXM6IFZhdWx0VHJhbnNhY3Rpb25Db25zdHJ1Y3RvclBhcmFtcykge1xuICAgIHRoaXMuYXBwID0gcGFyYW1zLmFwcDtcbiAgICB0aGlzLnN0YWdpbmdGb2xkZXJQYXRoID0gcGFyYW1zLnN0YWdpbmdGb2xkZXJQYXRoID8/IERFRkFVTFRfU1RBR0lOR19GT0xERVJfUEFUSDtcbiAgICB0aGlzLm11dGF0aW9uQnlwYXNzID0gcGFyYW1zLm9wZW5NdXRhdGlvbkJ5cGFzcz8uKCkgPz8gbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb21taXRzIHRoZSB0cmFuc2FjdGlvbjogZmluYWxpemVzIHNvZnQtZGVsZXRlcyBieSB0cmFzaGluZyB0aGUgc3RhZ2VkIHJlc291cmNlcyBmb3IgcmVhbCBhbmRcbiAgICogcmVtb3ZlcyB0aGUgc3RhZ2luZyBmb2xkZXIuIEFmdGVyIHRoaXMgdGhlIHRyYW5zYWN0aW9uIGNhbiBubyBsb25nZXIgYmUgbXV0YXRlZCBvciByb2xsZWQgYmFjay5cbiAgICpcbiAgICogQHJldHVybnMgQSB7QGxpbmsgUHJvbWlzZX0gdGhhdCByZXNvbHZlcyB3aGVuIHRoZSBjb21taXQgY29tcGxldGVzLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIGNvbW1pdCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0aGlzLmFzc2VydE9wZW4oKTtcbiAgICB0aGlzLnN0YXRlID0gJ2NvbW1pdHRlZCc7XG4gICAgY29uc3QgYWRhcHRlciA9IHRoaXMuYXBwLnZhdWx0LmFkYXB0ZXI7XG4gICAgZm9yIChjb25zdCBzdGFnZWRQYXRoIG9mIHRoaXMuc3RhZ2VkVHJhc2hQYXRocykge1xuICAgICAgY29uc3Qgd2FzVHJhc2hlZFRvU3lzdGVtID0gYXdhaXQgYWRhcHRlci50cmFzaFN5c3RlbShzdGFnZWRQYXRoKTtcbiAgICAgIGlmICghd2FzVHJhc2hlZFRvU3lzdGVtKSB7XG4gICAgICAgIGF3YWl0IGFkYXB0ZXIudHJhc2hMb2NhbChzdGFnZWRQYXRoKTtcbiAgICAgIH1cbiAgICB9XG4gICAgYXdhaXQgdGhpcy5yZW1vdmVTdGFnaW5nRm9sZGVyKCk7XG4gICAgdGhpcy5kaXNwb3NlTXV0YXRpb25CeXBhc3MoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgZmlsZSB3aXRoIHRoZSBnaXZlbiBjb250ZW50LCByZWNvcmRpbmcgaXRzIHJlbW92YWwgYXMgdGhlIGludmVyc2UuXG4gICAqXG4gICAqIEBwYXJhbSBwYXRoIC0gVGhlIHBhdGggb2YgdGhlIGZpbGUgdG8gY3JlYXRlLlxuICAgKiBAcGFyYW0gZGF0YSAtIFRoZSBjb250ZW50IG9mIHRoZSBmaWxlLlxuICAgKiBAcmV0dXJucyBBIHtAbGluayBQcm9taXNlfSByZXNvbHZpbmcgdG8gdGhlIGNyZWF0ZWQge0BsaW5rIFRGaWxlfS5cbiAgICovXG4gIHB1YmxpYyBhc3luYyBjcmVhdGUocGF0aDogc3RyaW5nLCBkYXRhOiBzdHJpbmcpOiBQcm9taXNlPFRGaWxlPiB7XG4gICAgdGhpcy5hc3NlcnRPcGVuKCk7XG4gICAgY29uc3QgZmlsZSA9IGF3YWl0IHRoaXMuYXBwLnZhdWx0LmNyZWF0ZShwYXRoLCBkYXRhKTtcbiAgICBjb25zdCBjcmVhdGVkUGF0aCA9IGZpbGUucGF0aDtcbiAgICB0aGlzLnB1c2hVbmRvKGFzeW5jICgpID0+IHtcbiAgICAgIGF3YWl0IHRoaXMuaGFyZERlbGV0ZShjcmVhdGVkUGF0aCk7XG4gICAgfSk7XG4gICAgcmV0dXJuIGZpbGU7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIGZvbGRlciAoaW5jbHVkaW5nIG1pc3NpbmcgYW5jZXN0b3JzKSwgcmVjb3JkaW5nIGl0cyByZW1vdmFsIGFzIHRoZSBpbnZlcnNlLiBBIG5vLW9wIGlmXG4gICAqIHRoZSBmb2xkZXIgYWxyZWFkeSBleGlzdHMuXG4gICAqXG4gICAqIEBwYXJhbSBwYXRoIC0gVGhlIHBhdGggb2YgdGhlIGZvbGRlciB0byBjcmVhdGUuXG4gICAqIEByZXR1cm5zIEEge0BsaW5rIFByb21pc2V9IHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgZm9sZGVyIGV4aXN0cy5cbiAgICovXG4gIHB1YmxpYyBhc3luYyBjcmVhdGVGb2xkZXIocGF0aDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdGhpcy5hc3NlcnRPcGVuKCk7XG4gICAgY29uc3Qgd2FzQ3JlYXRlZCA9IGF3YWl0IGNyZWF0ZUZvbGRlclNhZmUodGhpcy5hcHAsIHBhdGgpO1xuICAgIGlmICh3YXNDcmVhdGVkKSB7XG4gICAgICB0aGlzLnB1c2hVbmRvKGFzeW5jICgpID0+IHtcbiAgICAgICAgYXdhaXQgdGhpcy5oYXJkRGVsZXRlKHBhdGgpO1xuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcGxhY2VzIHRoZSBjb250ZW50IG9mIGEgZmlsZSwgY2FwdHVyaW5nIHRoZSBvbGQgY29udGVudCBzbyBpdCBjYW4gYmUgcmVzdG9yZWQgb24gcm9sbGJhY2suXG4gICAqXG4gICAqIEBwYXJhbSBwYXRoT3JGaWxlIC0gVGhlIHBhdGggb3IgZmlsZSB0byBtb2RpZnkuXG4gICAqIEBwYXJhbSBuZXdDb250ZW50IC0gVGhlIG5ldyBjb250ZW50LlxuICAgKiBAcmV0dXJucyBBIHtAbGluayBQcm9taXNlfSB0aGF0IHJlc29sdmVzIHdoZW4gdGhlIGZpbGUgaXMgbW9kaWZpZWQuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgbW9kaWZ5KHBhdGhPckZpbGU6IFBhdGhPckFic3RyYWN0RmlsZSwgbmV3Q29udGVudDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgdGhpcy5wcm9jZXNzKHBhdGhPckZpbGUsICgpID0+IG5ld0NvbnRlbnQpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRyYW5zZm9ybXMgdGhlIGNvbnRlbnQgb2YgYSBmaWxlLCBjYXB0dXJpbmcgdGhlIG9sZCBjb250ZW50IHNvIGl0IGNhbiBiZSByZXN0b3JlZCBvbiByb2xsYmFjay5cbiAgICpcbiAgICogQHBhcmFtIHBhdGhPckZpbGUgLSBUaGUgcGF0aCBvciBmaWxlIHRvIHByb2Nlc3MuXG4gICAqIEBwYXJhbSBuZXdDb250ZW50UHJvdmlkZXIgLSBNYXBzIHRoZSBjdXJyZW50IGNvbnRlbnQgdG8gdGhlIG5ldyBjb250ZW50LlxuICAgKiBAcmV0dXJucyBBIHtAbGluayBQcm9taXNlfSB0aGF0IHJlc29sdmVzIHdoZW4gdGhlIGZpbGUgaXMgcHJvY2Vzc2VkLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIHByb2Nlc3MocGF0aE9yRmlsZTogUGF0aE9yQWJzdHJhY3RGaWxlLCBuZXdDb250ZW50UHJvdmlkZXI6IChjb250ZW50OiBzdHJpbmcpID0+IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMuYXNzZXJ0T3BlbigpO1xuICAgIGNvbnN0IHBhdGggPSBnZXRQYXRoKHRoaXMuYXBwLCBwYXRoT3JGaWxlKTtcbiAgICBjb25zdCBvbGRDb250ZW50ID0gYXdhaXQgcmVhZFNhZmUodGhpcy5hcHAsIHBhdGgpO1xuICAgIGF3YWl0IHByb2Nlc3Moe1xuICAgICAgYXBwOiB0aGlzLmFwcCxcbiAgICAgIG5ld0NvbnRlbnRQcm92aWRlcjogKHsgY29udGVudCB9KSA9PiBuZXdDb250ZW50UHJvdmlkZXIoY29udGVudCksXG4gICAgICBwYXRoT3JGaWxlOiBwYXRoLFxuICAgICAgcmVzb3VyY2VMb2NrQ29tcG9uZW50OiBudWxsXG4gICAgfSk7XG4gICAgLy8gUmVhY2hpbmcgdGhpcyBsaW5lIG1lYW5zIGBwcm9jZXNzYCBzdWNjZWVkZWQuIEEgbWlzc2luZyBmaWxlIHdvdWxkIGhhdmUgdGhyb3duIGFib3ZlIChpdHNcbiAgICAvLyBgc2hvdWxkRmFpbE9uTWlzc2luZ0ZpbGVgIGRlZmF1bHQpLCBzbyB0aGUgcHJlLWltYWdlIHdhcyBjYXB0dXJlZCBhbmQgY2FuIGJlIHJlc3RvcmVkIG9uIHJvbGxiYWNrLlxuICAgIGFzc2VydE5vbk51bGxhYmxlKG9sZENvbnRlbnQpO1xuICAgIHRoaXMucHVzaFVuZG8oYXN5bmMgKCkgPT4ge1xuICAgICAgYXdhaXQgcHJvY2Vzcyh7XG4gICAgICAgIGFwcDogdGhpcy5hcHAsXG4gICAgICAgIG5ld0NvbnRlbnRQcm92aWRlcjogb2xkQ29udGVudCxcbiAgICAgICAgcGF0aE9yRmlsZTogcGF0aCxcbiAgICAgICAgcmVzb3VyY2VMb2NrQ29tcG9uZW50OiBudWxsXG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW5hbWVzIG9yIG1vdmVzIGEgcmVzb3VyY2UsIHJlY29yZGluZyB0aGUgcmV2ZXJzZSByZW5hbWUgYXMgdGhlIGludmVyc2UuXG4gICAqXG4gICAqIEBwYXJhbSBvbGRQYXRoT3JGaWxlIC0gVGhlIHJlc291cmNlIHRvIHJlbmFtZS5cbiAgICogQHBhcmFtIG5ld1BhdGggLSBUaGUgZGVzaXJlZCBuZXcgcGF0aCAoYW4gYXZhaWxhYmxlIHBhdGggaXMgY2hvc2VuIGlmIGl0IGlzIHRha2VuKS5cbiAgICogQHJldHVybnMgQSB7QGxpbmsgUHJvbWlzZX0gcmVzb2x2aW5nIHRvIHRoZSBhY3R1YWwgbmV3IHBhdGguXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgcmVuYW1lKG9sZFBhdGhPckZpbGU6IFBhdGhPckFic3RyYWN0RmlsZSwgbmV3UGF0aDogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICB0aGlzLmFzc2VydE9wZW4oKTtcbiAgICBjb25zdCBvbGRQYXRoID0gZ2V0UGF0aCh0aGlzLmFwcCwgb2xkUGF0aE9yRmlsZSk7XG4gICAgY29uc3QgYWN0dWFsTmV3UGF0aCA9IGF3YWl0IHJlbmFtZVNhZmUoeyBhcHA6IHRoaXMuYXBwLCBuZXdQYXRoLCBvbGRQYXRoT3JBYnN0cmFjdEZpbGU6IG9sZFBhdGhPckZpbGUgfSk7XG4gICAgdGhpcy5wdXNoVW5kbyhhc3luYyAoKSA9PiB7XG4gICAgICBhd2FpdCByZW5hbWVTYWZlKHsgYXBwOiB0aGlzLmFwcCwgbmV3UGF0aDogb2xkUGF0aCwgb2xkUGF0aE9yQWJzdHJhY3RGaWxlOiBhY3R1YWxOZXdQYXRoIH0pO1xuICAgIH0pO1xuICAgIHJldHVybiBhY3R1YWxOZXdQYXRoO1xuICB9XG5cbiAgLyoqXG4gICAqIFJvbGxzIGJhY2sgdGhlIHRyYW5zYWN0aW9uOiB1bmRvZXMgdGhlIGNvbXBsZXRlZCBzdGVwcyBpbiByZXZlcnNlIG9yZGVyIGFuZCByZW1vdmVzIHRoZSBzdGFnaW5nXG4gICAqIGZvbGRlci4gSWRlbXBvdGVudC5cbiAgICpcbiAgICogQHJldHVybnMgQSB7QGxpbmsgUHJvbWlzZX0gdGhhdCByZXNvbHZlcyB3aGVuIHRoZSByb2xsYmFjayBjb21wbGV0ZXMuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgcm9sbGJhY2soKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHRoaXMuc3RhdGUgPT09ICdyb2xsZWRCYWNrJykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLmFzc2VydE5vdENvbW1pdHRlZCgpO1xuICAgIHRoaXMuc3RhdGUgPSAncm9sbGVkQmFjayc7XG4gICAgZm9yIChjb25zdCBzdGVwIG9mIFsuLi50aGlzLnVuZG9TdGVwc10ucmV2ZXJzZSgpKSB7XG4gICAgICBhd2FpdCBzdGVwLnVuZG8oKTtcbiAgICB9XG4gICAgYXdhaXQgdGhpcy5yZW1vdmVTdGFnaW5nRm9sZGVyKCk7XG4gICAgdGhpcy5kaXNwb3NlTXV0YXRpb25CeXBhc3MoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSb2xscyBiYWNrIHRoZSB0cmFuc2FjdGlvbiBvbiBkaXNwb3NhbCB1bmxlc3MgaXQgd2FzIGFscmVhZHkgY29tbWl0dGVkIG9yIHJvbGxlZCBiYWNrLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIFtTeW1ib2wuYXN5bmNEaXNwb3NlXSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy5zdGF0ZSA9PT0gJ29wZW4nKSB7XG4gICAgICBhd2FpdCB0aGlzLnJvbGxiYWNrKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNvZnQtZGVsZXRlcyBhIHJlc291cmNlIGJ5IG1vdmluZyBpdCBpbnRvIHRoZSBzdGFnaW5nIGZvbGRlciwgcmVjb3JkaW5nIHRoZSBtb3ZlLWJhY2sgYXMgdGhlXG4gICAqIGludmVyc2UuIFRoZSByZWFsIHRyYXNoIGhhcHBlbnMgb24ge0BsaW5rIFZhdWx0VHJhbnNhY3Rpb24uY29tbWl0fS4gQSBuby1vcCBpZiB0aGUgcmVzb3VyY2UgZG9lc1xuICAgKiBub3QgZXhpc3QuXG4gICAqXG4gICAqIEBwYXJhbSBwYXRoT3JGaWxlIC0gVGhlIHBhdGggb3IgcmVzb3VyY2UgdG8gdHJhc2guXG4gICAqIEByZXR1cm5zIEEge0BsaW5rIFByb21pc2V9IHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgcmVzb3VyY2UgaGFzIGJlZW4gc3RhZ2VkLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIHRyYXNoKHBhdGhPckZpbGU6IFBhdGhPckFic3RyYWN0RmlsZSk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMuYXNzZXJ0T3BlbigpO1xuICAgIGNvbnN0IGZpbGUgPSBnZXRBYnN0cmFjdEZpbGVPck51bGwoeyBhcHA6IHRoaXMuYXBwLCBwYXRoT3JGaWxlIH0pO1xuICAgIGlmICghZmlsZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBvcmlnaW5hbFBhdGggPSBmaWxlLnBhdGg7XG4gICAgYXdhaXQgdGhpcy5lbnN1cmVTdGFnaW5nRm9sZGVyKCk7XG4gICAgY29uc3Qgc3RhZ2VkUGF0aCA9IGF3YWl0IHRoaXMuZ2V0QXZhaWxhYmxlU3RhZ2VkUGF0aChmaWxlLm5hbWUpO1xuICAgIGNvbnN0IGFkYXB0ZXIgPSB0aGlzLmFwcC52YXVsdC5hZGFwdGVyO1xuICAgIC8vIE1vdmUgdGhyb3VnaCB0aGUgYWRhcHRlciwgbm90IGB2YXVsdC5yZW5hbWVgOiB0aGUgc3RhZ2luZyBmb2xkZXIgaXMgZG90LXByZWZpeGVkIGFuZCB0aGVyZWZvcmVcbiAgICAvLyBVbnRyYWNrZWQsIHNvIGEgYHZhdWx0LipgIG1vdmUgY2Fubm90IHRhcmdldCBpdCAobm9yIHNob3VsZCBpdCByZXdyaXRlIGxpbmtzIHRvIGEgc29mdC1kZWxldGUpLlxuICAgIGF3YWl0IGFkYXB0ZXIucmVuYW1lKG9yaWdpbmFsUGF0aCwgc3RhZ2VkUGF0aCk7XG4gICAgdGhpcy5zdGFnZWRUcmFzaFBhdGhzLnB1c2goc3RhZ2VkUGF0aCk7XG4gICAgdGhpcy5wdXNoVW5kbyhhc3luYyAoKSA9PiB7XG4gICAgICBpZiAoYXdhaXQgYWRhcHRlci5leGlzdHMoc3RhZ2VkUGF0aCkpIHtcbiAgICAgICAgYXdhaXQgYWRhcHRlci5yZW5hbWUoc3RhZ2VkUGF0aCwgb3JpZ2luYWxQYXRoKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgYXNzZXJ0Tm90Q29tbWl0dGVkKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLnN0YXRlID09PSAnY29tbWl0dGVkJykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3Qgcm9sbCBiYWNrIGEgY29tbWl0dGVkIHRyYW5zYWN0aW9uLicpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXNzZXJ0T3BlbigpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5zdGF0ZSAhPT0gJ29wZW4nKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCBtdXRhdGUgYSAke3RoaXMuc3RhdGV9IHRyYW5zYWN0aW9uLmApO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZGlzcG9zZU11dGF0aW9uQnlwYXNzKCk6IHZvaWQge1xuICAgIHRoaXMubXV0YXRpb25CeXBhc3M/LltTeW1ib2wuZGlzcG9zZV0oKTtcbiAgICB0aGlzLm11dGF0aW9uQnlwYXNzID0gbnVsbDtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZW5zdXJlU3RhZ2luZ0ZvbGRlcigpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy5oYXNTdGFnaW5nRm9sZGVyKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGFkYXB0ZXIgPSB0aGlzLmFwcC52YXVsdC5hZGFwdGVyO1xuICAgIGlmICghYXdhaXQgYWRhcHRlci5leGlzdHModGhpcy5zdGFnaW5nRm9sZGVyUGF0aCkpIHtcbiAgICAgIGF3YWl0IGFkYXB0ZXIubWtkaXIodGhpcy5zdGFnaW5nRm9sZGVyUGF0aCk7XG4gICAgfVxuICAgIHRoaXMuaGFzU3RhZ2luZ0ZvbGRlciA9IHRydWU7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGdldEF2YWlsYWJsZVN0YWdlZFBhdGgobmFtZTogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCBhZGFwdGVyID0gdGhpcy5hcHAudmF1bHQuYWRhcHRlcjtcbiAgICBjb25zdCBkb3RJbmRleCA9IG5hbWUubGFzdEluZGV4T2YoJy4nKTtcbiAgICBjb25zdCBoYXNFeHRlbnNpb24gPSBkb3RJbmRleCA+IDA7XG4gICAgY29uc3QgYmFzZU5hbWUgPSBoYXNFeHRlbnNpb24gPyBuYW1lLnNsaWNlKDAsIGRvdEluZGV4KSA6IG5hbWU7XG4gICAgY29uc3QgZXh0ZW5zaW9uID0gaGFzRXh0ZW5zaW9uID8gbmFtZS5zbGljZShkb3RJbmRleCkgOiAnJztcbiAgICBsZXQgY2FuZGlkYXRlID0gYCR7dGhpcy5zdGFnaW5nRm9sZGVyUGF0aH0vJHtuYW1lfWA7XG4gICAgbGV0IGNvdW50ZXIgPSAxO1xuICAgIHdoaWxlIChhd2FpdCBhZGFwdGVyLmV4aXN0cyhjYW5kaWRhdGUpKSB7XG4gICAgICBjYW5kaWRhdGUgPSBgJHt0aGlzLnN0YWdpbmdGb2xkZXJQYXRofS8ke2Jhc2VOYW1lfSAke2NvdW50ZXIudG9TdHJpbmcoKX0ke2V4dGVuc2lvbn1gO1xuICAgICAgY291bnRlcisrO1xuICAgIH1cbiAgICByZXR1cm4gY2FuZGlkYXRlO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBoYXJkRGVsZXRlKHBhdGg6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGZpbGUgPSBnZXRBYnN0cmFjdEZpbGVPck51bGwoeyBhcHA6IHRoaXMuYXBwLCBwYXRoT3JGaWxlOiBwYXRoIH0pO1xuICAgIGlmIChmaWxlKSB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgb2JzaWRpYW5tZC9wcmVmZXItZmlsZS1tYW5hZ2VyLXRyYXNoLWZpbGUgLS0gVW5kb2luZyBhIHRyYW5zYWN0aW9uLWxvY2FsIGNyZWF0ZSBtdXN0IHZhbmlzaCBpdCBlbnRpcmVseSwgbm90IGxhbmQgaXQgaW4gdGhlIHVzZXIncyB0cmFzaC5cbiAgICAgIGF3YWl0IHRoaXMuYXBwLnZhdWx0LmRlbGV0ZShmaWxlLCB0cnVlKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHB1c2hVbmRvKHVuZG86ICgpID0+IFByb21pc2U8dm9pZD4pOiB2b2lkIHtcbiAgICB0aGlzLnVuZG9TdGVwcy5wdXNoKHsgdW5kbyB9KTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgcmVtb3ZlU3RhZ2luZ0ZvbGRlcigpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAoIXRoaXMuaGFzU3RhZ2luZ0ZvbGRlcikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLmhhc1N0YWdpbmdGb2xkZXIgPSBmYWxzZTtcbiAgICBjb25zdCBhZGFwdGVyID0gdGhpcy5hcHAudmF1bHQuYWRhcHRlcjtcbiAgICBpZiAoYXdhaXQgYWRhcHRlci5leGlzdHModGhpcy5zdGFnaW5nRm9sZGVyUGF0aCkpIHtcbiAgICAgIGF3YWl0IGFkYXB0ZXIucm1kaXIodGhpcy5zdGFnaW5nRm9sZGVyUGF0aCwgdHJ1ZSk7XG4gICAgfVxuICB9XG59XG4iXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQTBCQSxTQUFTLHlCQUF5QjtBQUNsQztBQUFBLEVBQ0U7QUFBQSxFQUNBO0FBQUEsT0FDSztBQUNQO0FBQUEsRUFDRTtBQUFBLEVBQ0E7QUFBQSxFQUNBO0FBQUEsRUFDQTtBQUFBLE9BQ0s7QUFFUCxNQUFNLDhCQUE4QjtBQThDN0IsTUFBTSxpQkFBaUI7QUFBQSxFQUNYO0FBQUEsRUFDVCxtQkFBbUI7QUFBQSxFQUNuQixpQkFBb0M7QUFBQSxFQUMzQixtQkFBNkIsQ0FBQztBQUFBLEVBQzlCO0FBQUEsRUFDVCxRQUEwQjtBQUFBLEVBQ2pCLFlBQXdCLENBQUM7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFPbkMsWUFBWSxRQUEyQztBQUM1RCxTQUFLLE1BQU0sT0FBTztBQUNsQixTQUFLLG9CQUFvQixPQUFPLHFCQUFxQjtBQUNyRCxTQUFLLGlCQUFpQixPQUFPLHFCQUFxQixLQUFLO0FBQUEsRUFDekQ7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQVFBLE1BQWEsU0FBd0I7QUFDbkMsU0FBSyxXQUFXO0FBQ2hCLFNBQUssUUFBUTtBQUNiLFVBQU0sVUFBVSxLQUFLLElBQUksTUFBTTtBQUMvQixlQUFXLGNBQWMsS0FBSyxrQkFBa0I7QUFDOUMsWUFBTSxxQkFBcUIsTUFBTSxRQUFRLFlBQVksVUFBVTtBQUMvRCxVQUFJLENBQUMsb0JBQW9CO0FBQ3ZCLGNBQU0sUUFBUSxXQUFXLFVBQVU7QUFBQSxNQUNyQztBQUFBLElBQ0Y7QUFDQSxVQUFNLEtBQUssb0JBQW9CO0FBQy9CLFNBQUssc0JBQXNCO0FBQUEsRUFDN0I7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBU0EsTUFBYSxPQUFPLE1BQWMsTUFBOEI7QUFDOUQsU0FBSyxXQUFXO0FBQ2hCLFVBQU0sT0FBTyxNQUFNLEtBQUssSUFBSSxNQUFNLE9BQU8sTUFBTSxJQUFJO0FBQ25ELFVBQU0sY0FBYyxLQUFLO0FBQ3pCLFNBQUssU0FBUyxZQUFZO0FBQ3hCLFlBQU0sS0FBSyxXQUFXLFdBQVc7QUFBQSxJQUNuQyxDQUFDO0FBQ0QsV0FBTztBQUFBLEVBQ1Q7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBU0EsTUFBYSxhQUFhLE1BQTZCO0FBQ3JELFNBQUssV0FBVztBQUNoQixVQUFNLGFBQWEsTUFBTSxpQkFBaUIsS0FBSyxLQUFLLElBQUk7QUFDeEQsUUFBSSxZQUFZO0FBQ2QsV0FBSyxTQUFTLFlBQVk7QUFDeEIsY0FBTSxLQUFLLFdBQVcsSUFBSTtBQUFBLE1BQzVCLENBQUM7QUFBQSxJQUNIO0FBQUEsRUFDRjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFTQSxNQUFhLE9BQU8sWUFBZ0MsWUFBbUM7QUFDckYsVUFBTSxLQUFLLFFBQVEsWUFBWSxNQUFNLFVBQVU7QUFBQSxFQUNqRDtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFTQSxNQUFhLFFBQVEsWUFBZ0Msb0JBQWdFO0FBQ25ILFNBQUssV0FBVztBQUNoQixVQUFNLE9BQU8sUUFBUSxLQUFLLEtBQUssVUFBVTtBQUN6QyxVQUFNLGFBQWEsTUFBTSxTQUFTLEtBQUssS0FBSyxJQUFJO0FBQ2hELFVBQU0sUUFBUTtBQUFBLE1BQ1osS0FBSyxLQUFLO0FBQUEsTUFDVixvQkFBb0IsQ0FBQyxFQUFFLFFBQVEsTUFBTSxtQkFBbUIsT0FBTztBQUFBLE1BQy9ELFlBQVk7QUFBQSxNQUNaLHVCQUF1QjtBQUFBLElBQ3pCLENBQUM7QUFHRCxzQkFBa0IsVUFBVTtBQUM1QixTQUFLLFNBQVMsWUFBWTtBQUN4QixZQUFNLFFBQVE7QUFBQSxRQUNaLEtBQUssS0FBSztBQUFBLFFBQ1Ysb0JBQW9CO0FBQUEsUUFDcEIsWUFBWTtBQUFBLFFBQ1osdUJBQXVCO0FBQUEsTUFDekIsQ0FBQztBQUFBLElBQ0gsQ0FBQztBQUFBLEVBQ0g7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBU0EsTUFBYSxPQUFPLGVBQW1DLFNBQWtDO0FBQ3ZGLFNBQUssV0FBVztBQUNoQixVQUFNLFVBQVUsUUFBUSxLQUFLLEtBQUssYUFBYTtBQUMvQyxVQUFNLGdCQUFnQixNQUFNLFdBQVcsRUFBRSxLQUFLLEtBQUssS0FBSyxTQUFTLHVCQUF1QixjQUFjLENBQUM7QUFDdkcsU0FBSyxTQUFTLFlBQVk7QUFDeEIsWUFBTSxXQUFXLEVBQUUsS0FBSyxLQUFLLEtBQUssU0FBUyxTQUFTLHVCQUF1QixjQUFjLENBQUM7QUFBQSxJQUM1RixDQUFDO0FBQ0QsV0FBTztBQUFBLEVBQ1Q7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQVFBLE1BQWEsV0FBMEI7QUFDckMsUUFBSSxLQUFLLFVBQVUsY0FBYztBQUMvQjtBQUFBLElBQ0Y7QUFDQSxTQUFLLG1CQUFtQjtBQUN4QixTQUFLLFFBQVE7QUFDYixlQUFXLFFBQVEsQ0FBQyxHQUFHLEtBQUssU0FBUyxFQUFFLFFBQVEsR0FBRztBQUNoRCxZQUFNLEtBQUssS0FBSztBQUFBLElBQ2xCO0FBQ0EsVUFBTSxLQUFLLG9CQUFvQjtBQUMvQixTQUFLLHNCQUFzQjtBQUFBLEVBQzdCO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFLQSxPQUFjLE9BQU8sWUFBWSxJQUFtQjtBQUNsRCxRQUFJLEtBQUssVUFBVSxRQUFRO0FBQ3pCLFlBQU0sS0FBSyxTQUFTO0FBQUEsSUFDdEI7QUFBQSxFQUNGO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBVUEsTUFBYSxNQUFNLFlBQStDO0FBQ2hFLFNBQUssV0FBVztBQUNoQixVQUFNLE9BQU8sc0JBQXNCLEVBQUUsS0FBSyxLQUFLLEtBQUssV0FBVyxDQUFDO0FBQ2hFLFFBQUksQ0FBQyxNQUFNO0FBQ1Q7QUFBQSxJQUNGO0FBQ0EsVUFBTSxlQUFlLEtBQUs7QUFDMUIsVUFBTSxLQUFLLG9CQUFvQjtBQUMvQixVQUFNLGFBQWEsTUFBTSxLQUFLLHVCQUF1QixLQUFLLElBQUk7QUFDOUQsVUFBTSxVQUFVLEtBQUssSUFBSSxNQUFNO0FBRy9CLFVBQU0sUUFBUSxPQUFPLGNBQWMsVUFBVTtBQUM3QyxTQUFLLGlCQUFpQixLQUFLLFVBQVU7QUFDckMsU0FBSyxTQUFTLFlBQVk7QUFDeEIsVUFBSSxNQUFNLFFBQVEsT0FBTyxVQUFVLEdBQUc7QUFDcEMsY0FBTSxRQUFRLE9BQU8sWUFBWSxZQUFZO0FBQUEsTUFDL0M7QUFBQSxJQUNGLENBQUM7QUFBQSxFQUNIO0FBQUEsRUFFUSxxQkFBMkI7QUFDakMsUUFBSSxLQUFLLFVBQVUsYUFBYTtBQUM5QixZQUFNLElBQUksTUFBTSwyQ0FBMkM7QUFBQSxJQUM3RDtBQUFBLEVBQ0Y7QUFBQSxFQUVRLGFBQW1CO0FBQ3pCLFFBQUksS0FBSyxVQUFVLFFBQVE7QUFDekIsWUFBTSxJQUFJLE1BQU0sbUJBQW1CLEtBQUssS0FBSyxlQUFlO0FBQUEsSUFDOUQ7QUFBQSxFQUNGO0FBQUEsRUFFUSx3QkFBOEI7QUFDcEMsU0FBSyxpQkFBaUIsT0FBTyxPQUFPLEVBQUU7QUFDdEMsU0FBSyxpQkFBaUI7QUFBQSxFQUN4QjtBQUFBLEVBRUEsTUFBYyxzQkFBcUM7QUFDakQsUUFBSSxLQUFLLGtCQUFrQjtBQUN6QjtBQUFBLElBQ0Y7QUFDQSxVQUFNLFVBQVUsS0FBSyxJQUFJLE1BQU07QUFDL0IsUUFBSSxDQUFDLE1BQU0sUUFBUSxPQUFPLEtBQUssaUJBQWlCLEdBQUc7QUFDakQsWUFBTSxRQUFRLE1BQU0sS0FBSyxpQkFBaUI7QUFBQSxJQUM1QztBQUNBLFNBQUssbUJBQW1CO0FBQUEsRUFDMUI7QUFBQSxFQUVBLE1BQWMsdUJBQXVCLE1BQStCO0FBQ2xFLFVBQU0sVUFBVSxLQUFLLElBQUksTUFBTTtBQUMvQixVQUFNLFdBQVcsS0FBSyxZQUFZLEdBQUc7QUFDckMsVUFBTSxlQUFlLFdBQVc7QUFDaEMsVUFBTSxXQUFXLGVBQWUsS0FBSyxNQUFNLEdBQUcsUUFBUSxJQUFJO0FBQzFELFVBQU0sWUFBWSxlQUFlLEtBQUssTUFBTSxRQUFRLElBQUk7QUFDeEQsUUFBSSxZQUFZLEdBQUcsS0FBSyxpQkFBaUIsSUFBSSxJQUFJO0FBQ2pELFFBQUksVUFBVTtBQUNkLFdBQU8sTUFBTSxRQUFRLE9BQU8sU0FBUyxHQUFHO0FBQ3RDLGtCQUFZLEdBQUcsS0FBSyxpQkFBaUIsSUFBSSxRQUFRLElBQUksUUFBUSxTQUFTLENBQUMsR0FBRyxTQUFTO0FBQ25GO0FBQUEsSUFDRjtBQUNBLFdBQU87QUFBQSxFQUNUO0FBQUEsRUFFQSxNQUFjLFdBQVcsTUFBNkI7QUFDcEQsVUFBTSxPQUFPLHNCQUFzQixFQUFFLEtBQUssS0FBSyxLQUFLLFlBQVksS0FBSyxDQUFDO0FBQ3RFLFFBQUksTUFBTTtBQUVSLFlBQU0sS0FBSyxJQUFJLE1BQU0sT0FBTyxNQUFNLElBQUk7QUFBQSxJQUN4QztBQUFBLEVBQ0Y7QUFBQSxFQUVRLFNBQVMsTUFBaUM7QUFDaEQsU0FBSyxVQUFVLEtBQUssRUFBRSxLQUFLLENBQUM7QUFBQSxFQUM5QjtBQUFBLEVBRUEsTUFBYyxzQkFBcUM7QUFDakQsUUFBSSxDQUFDLEtBQUssa0JBQWtCO0FBQzFCO0FBQUEsSUFDRjtBQUNBLFNBQUssbUJBQW1CO0FBQ3hCLFVBQU0sVUFBVSxLQUFLLElBQUksTUFBTTtBQUMvQixRQUFJLE1BQU0sUUFBUSxPQUFPLEtBQUssaUJBQWlCLEdBQUc7QUFDaEQsWUFBTSxRQUFRLE1BQU0sS0FBSyxtQkFBbUIsSUFBSTtBQUFBLElBQ2xEO0FBQUEsRUFDRjtBQUNGOyIsCiAgIm5hbWVzIjogW10KfQo=
@@ -8,8 +8,8 @@ import type { App, ListedFiles } from 'obsidian';
8
8
  import { TAbstractFile, TFile, TFolder } from 'obsidian';
9
9
  import type { RetryOptions } from '../async.mjs';
10
10
  import type { ValueProvider } from '../value-provider.mjs';
11
- import type { EditorLockComponent } from './editor-lock.mjs';
12
11
  import type { PathOrAbstractFile, PathOrFile, PathOrFolder } from './file-system.mjs';
12
+ import type { ResourceLockComponent } from './resource-lock.mjs';
13
13
  import { FileSystemType } from './file-system.mjs';
14
14
  /**
15
15
  * Arguments for {@link process}.
@@ -143,11 +143,11 @@ export interface IsChildParams {
143
143
  */
144
144
  export interface ProcessOptions extends RetryOptions {
145
145
  /**
146
- * An editor-lock component used to lock the file's editor read-only for the duration of
146
+ * An resource-lock component used to lock the file's editor read-only for the duration of
147
147
  * processing. The lock is reference-counted, so it composes with any outer operation-level lock
148
148
  * on the same note.
149
149
  */
150
- readonly editorLockComponent: EditorLockComponent | null;
150
+ readonly resourceLockComponent: null | ResourceLockComponent;
151
151
  /**
152
152
  * Whether to fail if the file is missing or deleted.
153
153
  *