UNPKG

39.1 kBJavaScriptView Raw
1"use strict";
2/**
3 * @license
4 * Copyright Google LLC All Rights Reserved.
5 *
6 * Use of this source code is governed by an MIT-style license that can be
7 * found in the LICENSE file at https://angular.io/license
8 */
9Object.defineProperty(exports, "__esModule", { value: true });
10exports.SimpleMemoryHost = void 0;
11const rxjs_1 = require("rxjs");
12const exception_1 = require("../../exception");
13const path_1 = require("../path");
14class SimpleMemoryHost {
15 _newDirStats() {
16 return {
17 inspect() {
18 return '<Directory>';
19 },
20 isFile() {
21 return false;
22 },
23 isDirectory() {
24 return true;
25 },
26 size: 0,
27 atime: new Date(),
28 ctime: new Date(),
29 mtime: new Date(),
30 birthtime: new Date(),
31 content: null,
32 };
33 }
34 _newFileStats(content, oldStats) {
35 return {
36 inspect() {
37 return `<File size(${content.byteLength})>`;
38 },
39 isFile() {
40 return true;
41 },
42 isDirectory() {
43 return false;
44 },
45 size: content.byteLength,
46 atime: oldStats ? oldStats.atime : new Date(),
47 ctime: new Date(),
48 mtime: new Date(),
49 birthtime: oldStats ? oldStats.birthtime : new Date(),
50 content,
51 };
52 }
53 constructor() {
54 this._cache = new Map();
55 this._watchers = new Map();
56 this._cache.set((0, path_1.normalize)('/'), this._newDirStats());
57 }
58 _toAbsolute(path) {
59 return (0, path_1.isAbsolute)(path) ? path : (0, path_1.normalize)('/' + path);
60 }
61 _updateWatchers(path, type) {
62 const time = new Date();
63 let currentPath = path;
64 let parent = null;
65 if (this._watchers.size == 0) {
66 // Nothing to do if there's no watchers.
67 return;
68 }
69 const maybeWatcher = this._watchers.get(currentPath);
70 if (maybeWatcher) {
71 maybeWatcher.forEach((watcher) => {
72 const [options, subject] = watcher;
73 subject.next({ path, time, type });
74 if (!options.persistent && type == 2 /* HostWatchEventType.Deleted */) {
75 subject.complete();
76 this._watchers.delete(currentPath);
77 }
78 });
79 }
80 do {
81 currentPath = parent !== null ? parent : currentPath;
82 parent = (0, path_1.dirname)(currentPath);
83 const maybeWatcher = this._watchers.get(currentPath);
84 if (maybeWatcher) {
85 maybeWatcher.forEach((watcher) => {
86 const [options, subject] = watcher;
87 if (!options.recursive) {
88 return;
89 }
90 subject.next({ path, time, type });
91 if (!options.persistent && type == 2 /* HostWatchEventType.Deleted */) {
92 subject.complete();
93 this._watchers.delete(currentPath);
94 }
95 });
96 }
97 } while (parent != currentPath);
98 }
99 get capabilities() {
100 return { synchronous: true };
101 }
102 /**
103 * List of protected methods that give direct access outside the observables to the cache
104 * and internal states.
105 */
106 _write(path, content) {
107 path = this._toAbsolute(path);
108 const old = this._cache.get(path);
109 if (old && old.isDirectory()) {
110 throw new exception_1.PathIsDirectoryException(path);
111 }
112 // Update all directories. If we find a file we know it's an invalid write.
113 const fragments = (0, path_1.split)(path);
114 let curr = (0, path_1.normalize)('/');
115 for (const fr of fragments) {
116 curr = (0, path_1.join)(curr, fr);
117 const maybeStats = this._cache.get(fr);
118 if (maybeStats) {
119 if (maybeStats.isFile()) {
120 throw new exception_1.PathIsFileException(curr);
121 }
122 }
123 else {
124 this._cache.set(curr, this._newDirStats());
125 }
126 }
127 // Create the stats.
128 const stats = this._newFileStats(content, old);
129 this._cache.set(path, stats);
130 this._updateWatchers(path, old ? 0 /* HostWatchEventType.Changed */ : 1 /* HostWatchEventType.Created */);
131 }
132 _read(path) {
133 path = this._toAbsolute(path);
134 const maybeStats = this._cache.get(path);
135 if (!maybeStats) {
136 throw new exception_1.FileDoesNotExistException(path);
137 }
138 else if (maybeStats.isDirectory()) {
139 throw new exception_1.PathIsDirectoryException(path);
140 }
141 else if (!maybeStats.content) {
142 throw new exception_1.PathIsDirectoryException(path);
143 }
144 else {
145 return maybeStats.content;
146 }
147 }
148 _delete(path) {
149 path = this._toAbsolute(path);
150 if (this._isDirectory(path)) {
151 for (const [cachePath] of this._cache.entries()) {
152 if (cachePath.startsWith(path + path_1.NormalizedSep) || cachePath === path) {
153 this._cache.delete(cachePath);
154 }
155 }
156 }
157 else {
158 this._cache.delete(path);
159 }
160 this._updateWatchers(path, 2 /* HostWatchEventType.Deleted */);
161 }
162 _rename(from, to) {
163 from = this._toAbsolute(from);
164 to = this._toAbsolute(to);
165 if (!this._cache.has(from)) {
166 throw new exception_1.FileDoesNotExistException(from);
167 }
168 else if (this._cache.has(to)) {
169 throw new exception_1.FileAlreadyExistException(to);
170 }
171 if (this._isDirectory(from)) {
172 for (const path of this._cache.keys()) {
173 if (path.startsWith(from + path_1.NormalizedSep)) {
174 const content = this._cache.get(path);
175 if (content) {
176 // We don't need to clone or extract the content, since we're moving files.
177 this._cache.set((0, path_1.join)(to, path_1.NormalizedSep, path.slice(from.length)), content);
178 }
179 }
180 }
181 }
182 else {
183 const content = this._cache.get(from);
184 if (content) {
185 const fragments = (0, path_1.split)(to);
186 const newDirectories = [];
187 let curr = (0, path_1.normalize)('/');
188 for (const fr of fragments) {
189 curr = (0, path_1.join)(curr, fr);
190 const maybeStats = this._cache.get(fr);
191 if (maybeStats) {
192 if (maybeStats.isFile()) {
193 throw new exception_1.PathIsFileException(curr);
194 }
195 }
196 else {
197 newDirectories.push(curr);
198 }
199 }
200 for (const newDirectory of newDirectories) {
201 this._cache.set(newDirectory, this._newDirStats());
202 }
203 this._cache.delete(from);
204 this._cache.set(to, content);
205 }
206 }
207 this._updateWatchers(from, 3 /* HostWatchEventType.Renamed */);
208 }
209 _list(path) {
210 path = this._toAbsolute(path);
211 if (this._isFile(path)) {
212 throw new exception_1.PathIsFileException(path);
213 }
214 const fragments = (0, path_1.split)(path);
215 const result = new Set();
216 if (path !== path_1.NormalizedRoot) {
217 for (const p of this._cache.keys()) {
218 if (p.startsWith(path + path_1.NormalizedSep)) {
219 result.add((0, path_1.split)(p)[fragments.length]);
220 }
221 }
222 }
223 else {
224 for (const p of this._cache.keys()) {
225 if (p.startsWith(path_1.NormalizedSep) && p !== path_1.NormalizedRoot) {
226 result.add((0, path_1.split)(p)[1]);
227 }
228 }
229 }
230 return [...result];
231 }
232 _exists(path) {
233 return !!this._cache.get(this._toAbsolute(path));
234 }
235 _isDirectory(path) {
236 const maybeStats = this._cache.get(this._toAbsolute(path));
237 return maybeStats ? maybeStats.isDirectory() : false;
238 }
239 _isFile(path) {
240 const maybeStats = this._cache.get(this._toAbsolute(path));
241 return maybeStats ? maybeStats.isFile() : false;
242 }
243 _stat(path) {
244 const maybeStats = this._cache.get(this._toAbsolute(path));
245 if (!maybeStats) {
246 return null;
247 }
248 else {
249 return maybeStats;
250 }
251 }
252 _watch(path, options) {
253 path = this._toAbsolute(path);
254 const subject = new rxjs_1.Subject();
255 let maybeWatcherArray = this._watchers.get(path);
256 if (!maybeWatcherArray) {
257 maybeWatcherArray = [];
258 this._watchers.set(path, maybeWatcherArray);
259 }
260 maybeWatcherArray.push([options || {}, subject]);
261 return subject.asObservable();
262 }
263 write(path, content) {
264 return new rxjs_1.Observable((obs) => {
265 this._write(path, content);
266 obs.next();
267 obs.complete();
268 });
269 }
270 read(path) {
271 return new rxjs_1.Observable((obs) => {
272 const content = this._read(path);
273 obs.next(content);
274 obs.complete();
275 });
276 }
277 delete(path) {
278 return new rxjs_1.Observable((obs) => {
279 this._delete(path);
280 obs.next();
281 obs.complete();
282 });
283 }
284 rename(from, to) {
285 return new rxjs_1.Observable((obs) => {
286 this._rename(from, to);
287 obs.next();
288 obs.complete();
289 });
290 }
291 list(path) {
292 return new rxjs_1.Observable((obs) => {
293 obs.next(this._list(path));
294 obs.complete();
295 });
296 }
297 exists(path) {
298 return new rxjs_1.Observable((obs) => {
299 obs.next(this._exists(path));
300 obs.complete();
301 });
302 }
303 isDirectory(path) {
304 return new rxjs_1.Observable((obs) => {
305 obs.next(this._isDirectory(path));
306 obs.complete();
307 });
308 }
309 isFile(path) {
310 return new rxjs_1.Observable((obs) => {
311 obs.next(this._isFile(path));
312 obs.complete();
313 });
314 }
315 // Some hosts may not support stat.
316 stat(path) {
317 return new rxjs_1.Observable((obs) => {
318 obs.next(this._stat(path));
319 obs.complete();
320 });
321 }
322 watch(path, options) {
323 return this._watch(path, options);
324 }
325 reset() {
326 this._cache.clear();
327 this._watchers.clear();
328 }
329}
330exports.SimpleMemoryHost = SimpleMemoryHost;
331//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVtb3J5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvYW5ndWxhcl9kZXZraXQvY29yZS9zcmMvdmlydHVhbC1mcy9ob3N0L21lbW9yeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7OztHQU1HOzs7QUFFSCwrQkFBMkM7QUFDM0MsK0NBS3lCO0FBQ3pCLGtDQVVpQjtBQWVqQixNQUFhLGdCQUFnQjtJQUlqQixZQUFZO1FBQ3BCLE9BQU87WUFDTCxPQUFPO2dCQUNMLE9BQU8sYUFBYSxDQUFDO1lBQ3ZCLENBQUM7WUFFRCxNQUFNO2dCQUNKLE9BQU8sS0FBSyxDQUFDO1lBQ2YsQ0FBQztZQUNELFdBQVc7Z0JBQ1QsT0FBTyxJQUFJLENBQUM7WUFDZCxDQUFDO1lBQ0QsSUFBSSxFQUFFLENBQUM7WUFFUCxLQUFLLEVBQUUsSUFBSSxJQUFJLEVBQUU7WUFDakIsS0FBSyxFQUFFLElBQUksSUFBSSxFQUFFO1lBQ2pCLEtBQUssRUFBRSxJQUFJLElBQUksRUFBRTtZQUNqQixTQUFTLEVBQUUsSUFBSSxJQUFJLEVBQUU7WUFFckIsT0FBTyxFQUFFLElBQUk7U0FDZCxDQUFDO0lBQ0osQ0FBQztJQUNTLGFBQWEsQ0FBQyxPQUFtQixFQUFFLFFBQXVDO1FBQ2xGLE9BQU87WUFDTCxPQUFPO2dCQUNMLE9BQU8sY0FBYyxPQUFPLENBQUMsVUFBVSxJQUFJLENBQUM7WUFDOUMsQ0FBQztZQUVELE1BQU07Z0JBQ0osT0FBTyxJQUFJLENBQUM7WUFDZCxDQUFDO1lBQ0QsV0FBVztnQkFDVCxPQUFPLEtBQUssQ0FBQztZQUNmLENBQUM7WUFDRCxJQUFJLEVBQUUsT0FBTyxDQUFDLFVBQVU7WUFFeEIsS0FBSyxFQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxJQUFJLEVBQUU7WUFDN0MsS0FBSyxFQUFFLElBQUksSUFBSSxF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LElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7WUFDM0IsR0FBRyxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ2pCLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELEtBQUssQ0FBQyxJQUFVLEVBQUUsT0FBMEI7UUFDMUMsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxPQUFPLENBQUMsQ0FBQztJQUNwQyxDQUFDO0lBRUQsS0FBSztRQUNILElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDcEIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUN6QixDQUFDO0NBQ0Y7QUE5VkQsNENBOFZDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IEdvb2dsZSBMTEMgQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxuICovXG5cbmltcG9ydCB7IE9ic2VydmFibGUsIFN1YmplY3QgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7XG4gIEZpbGVBbHJlYWR5RXhpc3RFeGNlcHRpb24sXG4gIEZpbGVEb2VzTm90RXhpc3RFeGNlcHRpb24sXG4gIFBhdGhJc0RpcmVjdG9yeUV4Y2VwdGlvbixcbiAgUGF0aElzRmlsZUV4Y2VwdGlvbixcbn0gZnJvbSAnLi4vLi4vZXhjZXB0aW9uJztcbmltcG9ydCB7XG4gIE5vcm1hbGl6ZWRSb290LFxuICBOb3JtYWxpemVkU2VwLFxuICBQYXRoLFxuICBQYXRoRnJhZ21lbnQsXG4gIGRpcm5hbWUsXG4gIGlzQWJzb2x1dGUsXG4gIGpvaW4sXG4gIG5vcm1hbGl6ZSxcbiAgc3BsaXQsXG59IGZyb20gJy4uL3BhdGgnO1xuaW1wb3J0IHtcbiAgRmlsZUJ1ZmZlcixcbiAgSG9zdCxcbiAgSG9zdENhcGFiaWxpdGllcyxcbiAgSG9zdFdhdGNoRXZlbnQsXG4gIEhvc3RXYXRjaEV2ZW50VHlwZSxcbiAgSG9zdFdhdGNoT3B0aW9ucyxcbiAgU3RhdHMsXG59IGZyb20gJy4vaW50ZXJmYWNlJztcblxuZXhwb3J0IGludGVyZmFjZSBTaW1wbGVNZW1vcnlIb3N0U3RhdHMge1xuICByZWFkb25seSBjb250ZW50OiBGaWxlQnVmZmVyIHwgbnVsbDtcbn1cblxuZXhwb3J0IGNsYXNzIFNpbXBsZU1lbW9yeUhvc3QgaW1wbGVtZW50cyBIb3N0PHt9PiB7XG4gIHByb3RlY3RlZCBfY2FjaGUgPSBuZXcgTWFwPFBhdGgsIFN0YXRzPFNpbXBsZU1lbW9yeUhvc3RTdGF0cz4+KCk7XG4gIHByaXZhdGUgX3dhdGNoZXJzID0gbmV3IE1hcDxQYXRoLCBbSG9zdFdhdGNoT3B0aW9ucywgU3ViamVjdDxIb3N0V2F0Y2hFdmVudD5dW10+KCk7XG5cbiAgcHJvdGVjdGVkIF9uZXdEaXJTdGF0cygpIHtcbiAgICByZXR1cm4ge1xuICAgICAgaW5zcGVjdCgpIHtcbiAgICAgICAgcmV0dXJuICc8RGlyZWN0b3J5Pic7XG4gICAgICB9LFxuXG4gICAgICBpc0ZpbGUoKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH0sXG4gICAgICBpc0RpcmVjdG9yeSgpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9LFxuICAgICAgc2l6ZTogMCxcblxuICAgICAgYXRpbWU6IG5ldyBEYXRlKCksXG4gICAgICBjdGltZTogbmV3IERhdGUoKSxcbiAgICAgIG10aW1lOiBuZXcgRGF0ZSgpLFxuICAgICAgYmlydGh0aW1lOiBuZXcgRGF0ZSgpLFxuXG4gICAgICBjb250ZW50OiBudWxsLFxuICAgIH07XG4gIH1cbiAgcHJvdGVjdGVkIF9uZXdGaWxlU3RhdHMoY29udGVudDogRmlsZUJ1ZmZlciwgb2xkU3RhdHM/OiBTdGF0czxTaW1wbGVNZW1vcnlIb3N0U3RhdHM+KSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGluc3BlY3QoKSB7XG4gICAgICAgIHJldHVybiBgPEZpbGUgc2l6ZSgke2NvbnRlbnQuYnl0ZUxlbmd0aH0pPmA7XG4gICAgICB9LFxuXG4gICAgICBpc0ZpbGUoKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfSxcbiAgICAgIGlzRGlyZWN0b3J5KCkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9LFxuICAgICAgc2l6ZTogY29udGVudC5ieXRlTGVuZ3RoLFxuXG4gICAgICBhdGltZTogb2xkU3RhdHMgPyBvbGRTdGF0cy5hdGltZSA6IG5ldyBEYXRlKCksXG4gICAgICBjdGltZTogbmV3IERhdGUoKSxcbiAgICAgIG10aW1lOiBuZXcgRGF0ZSgpLFxuICAgICAgYmlydGh0aW1lOiBvbGRTdGF0cyA/IG9sZFN0YXRzLmJpcnRodGltZSA6IG5ldyBEYXRlKCksXG5cbiAgICAgIGNvbnRlbnQsXG4gICAgfTtcbiAgfVxuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMuX2NhY2hlLnNldChub3JtYWxpemUoJy8nKSwgdGhpcy5fbmV3RGlyU3RhdHMoKSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgX3RvQWJzb2x1dGUocGF0aDogUGF0aCkge1xuICAgIHJldHVybiBpc0Fic29sdXRlKHBhdGgpID8gcGF0aCA6IG5vcm1hbGl6ZSgnLycgKyBwYXRoKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBfdXBkYXRlV2F0Y2hlcnMocGF0aDogUGF0aCwgdHlwZTogSG9zdFdhdGNoRXZlbnRUeXBlKSB7XG4gICAgY29uc3QgdGltZSA9IG5ldyBEYXRlKCk7XG4gICAgbGV0IGN1cnJlbnRQYXRoID0gcGF0aDtcbiAgICBsZXQgcGFyZW50OiBQYXRoIHwgbnVsbCA9IG51bGw7XG5cbiAgICBpZiAodGhpcy5fd2F0Y2hlcnMuc2l6ZSA9PSAwKSB7XG4gICAgICAvLyBOb3RoaW5nIHRvIGRvIGlmIHRoZXJlJ3Mgbm8gd2F0Y2hlcnMuXG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgbWF5YmVXYXRjaGVyID0gdGhpcy5fd2F0Y2hlcnMuZ2V0KGN1cnJlbnRQYXRoKTtcbiAgICBpZiAobWF5YmVXYXRjaGVyKSB7XG4gICAgICBtYXliZVdhdGNoZXIuZm9yRWFjaCgod2F0Y2hlcikgPT4ge1xuICAgICAgICBjb25zdCBbb3B0aW9ucywgc3ViamVjdF0gPSB3YXRjaGVyO1xuICAgICAgICBzdWJqZWN0Lm5leHQoeyBwYXRoLCB0aW1lLCB0eXBlIH0pO1xuXG4gICAgICAgIGlmICghb3B0aW9ucy5wZXJzaXN0ZW50ICYmIHR5cGUgPT0gSG9zdFdhdGNoRXZlbnRUeXBlLkRlbGV0ZWQpIHtcbiAgICAgICAgICBzdWJqZWN0LmNvbXBsZXRlKCk7XG4gICAgICAgICAgdGhpcy5fd2F0Y2hlcnMuZGVsZXRlKGN1cnJlbnRQYXRoKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgZG8ge1xuICAgICAgY3VycmVudFBhdGggPSBwYXJlbnQgIT09IG51bGwgPyBwYXJlbnQgOiBjdXJyZW50UGF0aDtcbiAgICAgIHBhcmVudCA9IGRpcm5hbWUoY3VycmVudFBhdGgpO1xuXG4gICAgICBjb25zdCBtYXliZVdhdGNoZXIgPSB0aGlzLl93YXRjaGVycy5nZXQoY3VycmVudFBhdGgpO1xuICAgICAgaWYgKG1heWJlV2F0Y2hlcikge1xuICAgICAgICBtYXliZVdhdGNoZXIuZm9yRWFjaCgod2F0Y2hlcikgPT4ge1xuICAgICAgICAgIGNvbnN0IFtvcHRpb25zLCBzdWJqZWN0XSA9IHdhdGNoZXI7XG4gICAgICAgICAgaWYgKCFvcHRpb25zLnJlY3Vyc2l2ZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgICBzdWJqZWN0Lm5leHQoeyBwYXRoLCB0aW1lLCB0eXBlIH0pO1xuXG4gICAgICAgICAgaWYgKCFvcHRpb25zLnBlcnNpc3RlbnQgJiYgdHlwZSA9PSBIb3N0V2F0Y2hFdmVudFR5cGUuRGVsZXRlZCkge1xuICAgICAgICAgICAgc3ViamVjdC5jb21wbGV0ZSgpO1xuICAgICAgICAgICAgdGhpcy5fd2F0Y2hlcnMuZGVsZXRlKGN1cnJlbnRQYXRoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0gd2hpbGUgKHBhcmVudCAhPSBjdXJyZW50UGF0aCk7XG4gIH1cblxuICBnZXQgY2FwYWJpbGl0aWVzKCk6IEhvc3RDYXBhYmlsaXRpZXMge1xuICAgIHJldHVybiB7IHN5bmNocm9ub3VzOiB0cnVlIH07XG4gIH1cblxuICAvKipcbiAgICogTGlzdCBvZiBwcm90ZWN0ZWQgbWV0aG9kcyB0aGF0IGdpdmUgZGlyZWN0IGFjY2VzcyBvdXRzaWRlIHRoZSBvYnNlcnZhYmxlcyB0byB0aGUgY2FjaGVcbiAgICogYW5kIGludGVybmFsIHN0YXRlcy5cbiAgICovXG4gIHByb3RlY3RlZCBfd3JpdGUocGF0aDogUGF0aCwgY29udGVudDogRmlsZUJ1ZmZlcik6IHZvaWQge1xuICAgIHBhdGggPSB0aGlzLl90b0Fic29sdXRlKHBhdGgpO1xuICAgIGNvbnN0IG9sZCA9IHRoaXMuX2NhY2hlLmdldChwYXRoKTtcbiAgICBpZiAob2xkICYmIG9sZC5pc0RpcmVjdG9yeSgpKSB7XG4gICAgICB0aHJvdyBuZXcgUGF0aElzRGlyZWN0b3J5RXhjZXB0aW9uKHBhdGgpO1xuICAgIH1cblxuICAgIC8vIFVwZGF0ZSBhbGwgZGlyZWN0b3JpZXMuIElmIHdlIGZpbmQgYSBmaWxlIHdlIGtub3cgaXQncyBhbiBpbnZhbGlkIHdyaXRlLlxuICAgIGNvbnN0IGZyYWdtZW50cyA9IHNwbGl0KHBhdGgpO1xuICAgIGxldCBjdXJyOiBQYXRoID0gbm9ybWFsaXplKCcvJyk7XG4gICAgZm9yIChjb25zdCBmciBvZiBmcmFnbWVudHMpIHtcbiAgICAgIGN1cnIgPSBqb2luKGN1cnIsIGZyKTtcbiAgICAgIGNvbnN0IG1heWJlU3RhdHMgPSB0aGlzLl9jYWNoZS5nZXQoZnIpO1xuICAgICAgaWYgKG1heWJlU3RhdHMpIHtcbiAgICAgICAgaWYgKG1heWJlU3RhdHMuaXNGaWxlKCkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGF0aElzRmlsZUV4Y2VwdGlvbihjdXJyKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5fY2FjaGUuc2V0KGN1cnIsIHRoaXMuX25ld0RpclN0YXRzKCkpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIENyZWF0ZSB0aGUgc3RhdHMuXG4gICAgY29uc3Qgc3RhdHM6IFN0YXRzPFNpbXBsZU1lbW9yeUhvc3RTdGF0cz4gPSB0aGlzLl9uZXdGaWxlU3RhdHMoY29udGVudCwgb2xkKTtcbiAgICB0aGlzLl9jYWNoZS5zZXQocGF0aCwgc3RhdHMpO1xuICAgIHRoaXMuX3VwZGF0ZVdhdGNoZXJzKHBhdGgsIG9sZCA/IEhvc3RXYXRjaEV2ZW50VHlwZS5DaGFuZ2VkIDogSG9zdFdhdGNoRXZlbnRUeXBlLkNyZWF0ZWQpO1xuICB9XG4gIHByb3RlY3RlZCBfcmVhZChwYXRoOiBQYXRoKTogRmlsZUJ1ZmZlciB7XG4gICAgcGF0aCA9IHRoaXMuX3RvQWJzb2x1dGUocGF0aCk7XG4gICAgY29uc3QgbWF5YmVTdGF0cyA9IHRoaXMuX2NhY2hlLmdldChwYXRoKTtcbiAgICBpZiAoIW1heWJlU3RhdHMpIHtcbiAgICAgIHRocm93IG5ldyBGaWxlRG9lc05vdEV4aXN0RXhjZXB0aW9uKHBhdGgpO1xuICAgIH0gZWxzZSBpZiAobWF5YmVTdGF0cy5pc0RpcmVjdG9yeSgpKSB7XG4gICAgICB0aHJvdyBuZXcgUGF0aElzRGlyZWN0b3J5RXhjZXB0aW9uKHBhdGgpO1xuICAgIH0gZWxzZSBpZiAoIW1heWJlU3RhdHMuY29udGVudCkge1xuICAgICAgdGhyb3cgbmV3IFBhdGhJc0RpcmVjdG9yeUV4Y2VwdGlvbihwYXRoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIG1heWJlU3RhdHMuY29udGVudDtcbiAgICB9XG4gIH1cbiAgcHJvdGVjdGVkIF9kZWxldGUocGF0aDogUGF0aCk6IHZvaWQge1xuICAgIHBhdGggPSB0aGlzLl90b0Fic29sdXRlKHBhdGgpO1xuICAgIGlmICh0aGlzLl9pc0RpcmVjdG9yeShwYXRoKSkge1xuICAgICAgZm9yIChjb25zdCBbY2FjaGVQYXRoXSBvZiB0aGlzLl9jYWNoZS5lbnRyaWVzKCkpIHtcbiAgICAgICAgaWYgKGNhY2hlUGF0aC5zdGFydHNXaXRoKHBhdGggKyBOb3JtYWxpemVkU2VwKSB8fCBjYWNoZVBhdGggPT09IHBhdGgpIHtcbiAgICAgICAgICB0aGlzLl9jYWNoZS5kZWxldGUoY2FjaGVQYXRoKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl9jYWNoZS5kZWxldGUocGF0aCk7XG4gICAgfVxuICAgIHRoaXMuX3VwZGF0ZVdhdGNoZXJzKHBhdGgsIEhvc3RXYXRjaEV2ZW50VHlwZS5EZWxldGVkKTtcbiAgfVxuICBwcm90ZWN0ZWQgX3JlbmFtZShmcm9tOiBQYXRoLCB0bzogUGF0aCk6IHZvaWQge1xuICAgIGZyb20gPSB0aGlzLl90b0Fic29sdXRlKGZyb20pO1xuICAgIHRvID0gdGhpcy5fdG9BYnNvbHV0ZSh0byk7XG4gICAgaWYgKCF0aGlzLl9jYWNoZS5oYXMoZnJvbSkpIHtcbiAgICAgIHRocm93IG5ldyBGaWxlRG9lc05vdEV4aXN0RXhjZXB0aW9uKGZyb20pO1xuICAgIH0gZWxzZSBpZiAodGhpcy5fY2FjaGUuaGFzKHRvKSkge1xuICAgICAgdGhyb3cgbmV3IEZpbGVBbHJlYWR5RXhpc3RFeGNlcHRpb24odG8pO1xuICAgIH1cblxuICAgIGlmICh0aGlzLl9pc0RpcmVjdG9yeShmcm9tKSkge1xuICAgICAgZm9yIChjb25zdCBwYXRoIG9mIHRoaXMuX2NhY2hlLmtleXMoKSkge1xuICAgICAgICBpZiAocGF0aC5zdGFydHNXaXRoKGZyb20gKyBOb3JtYWxpemVkU2VwKSkge1xuICAgICAgICAgIGNvbnN0IGNvbnRlbnQgPSB0aGlzLl9jYWNoZS5nZXQocGF0aCk7XG4gICAgICAgICAgaWYgKGNvbnRlbnQpIHtcbiAgICAgICAgICAgIC8vIFdlIGRvbid0IG5lZWQgdG8gY2xvbmUgb3IgZXh0cmFjdCB0aGUgY29udGVudCwgc2luY2Ugd2UncmUgbW92aW5nIGZpbGVzLlxuICAgICAgICAgICAgdGhpcy5fY2FjaGUuc2V0KGpvaW4odG8sIE5vcm1hbGl6ZWRTZXAsIHBhdGguc2xpY2UoZnJvbS5sZW5ndGgpKSwgY29udGVudCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGNvbnRlbnQgPSB0aGlzLl9jYWNoZS5nZXQoZnJvbSk7XG4gICAgICBpZiAoY29udGVudCkge1xuICAgICAgICBjb25zdCBmcmFnbWVudHMgPSBzcGxpdCh0byk7XG4gICAgICAgIGNvbnN0IG5ld0RpcmVjdG9yaWVzOiBQYXRoW10gPSBbXTtcbiAgICAgICAgbGV0IGN1cnI6IFBhdGggPSBub3JtYWxpemUoJy8nKTtcbiAgICAgICAgZm9yIChjb25zdCBmciBvZiBmcmFnbWVudHMpIHtcbiAgICAgICAgICBjdXJyID0gam9pbihjdXJyLCBmcik7XG4gICAgICAgICAgY29uc3QgbWF5YmVTdGF0cyA9IHRoaXMuX2NhY2hlLmdldChmcik7XG4gICAgICAgICAgaWYgKG1heWJlU3RhdHMpIHtcbiAgICAgICAgICAgIGlmIChtYXliZVN0YXRzLmlzRmlsZSgpKSB7XG4gICAgICAgICAgICAgIHRocm93IG5ldyBQYXRoSXNGaWxlRXhjZXB0aW9uKGN1cnIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBuZXdEaXJlY3Rvcmllcy5wdXNoKGN1cnIpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBmb3IgKGNvbnN0IG5ld0RpcmVjdG9yeSBvZiBuZXdEaXJlY3Rvcmllcykge1xuICAgICAgICAgIHRoaXMuX2NhY2hlLnNldChuZXdEaXJlY3RvcnksIHRoaXMuX25ld0RpclN0YXRzKCkpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX2NhY2hlLmRlbGV0ZShmcm9tKTtcbiAgICAgICAgdGhpcy5fY2FjaGUuc2V0KHRvLCBjb250ZW50KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLl91cGRhdGVXYXRjaGVycyhmcm9tLCBIb3N0V2F0Y2hFdmVudFR5cGUuUmVuYW1lZCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgX2xpc3QocGF0aDogUGF0aCk6IFBhdGhGcmFnbWVudFtdIHtcbiAgICBwYXRoID0gdGhpcy5fdG9BYnNvbHV0ZShwYXRoKTtcbiAgICBpZiAodGhpcy5faXNGaWxlKHBhdGgpKSB7XG4gICAgICB0aHJvdyBuZXcgUGF0aElzRmlsZUV4Y2VwdGlvbihwYXRoKTtcbiAgICB9XG5cbiAgICBjb25zdCBmcmFnbWVudHMgPSBzcGxpdChwYXRoKTtcbiAgICBjb25zdCByZXN1bHQgPSBuZXcgU2V0PFBhdGhGcmFnbWVudD4oKTtcbiAgICBpZiAocGF0aCAhPT0gTm9ybWFsaXplZFJvb3QpIHtcbiAgICAgIGZvciAoY29uc3QgcCBvZiB0aGlzLl9jYWNoZS5rZXlzKCkpIHtcbiAgICAgICAgaWYgKHAuc3RhcnRzV2l0aChwYXRoICsgTm9ybWFsaXplZFNlcCkpIHtcbiAgICAgICAgICByZXN1bHQuYWRkKHNwbGl0KHApW2ZyYWdtZW50cy5sZW5ndGhdKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBmb3IgKGNvbnN0IHAgb2YgdGhpcy5fY2FjaGUua2V5cygpKSB7XG4gICAgICAgIGlmIChwLnN0YXJ0c1dpdGgoTm9ybWFsaXplZFNlcCkgJiYgcCAhPT0gTm9ybWFsaXplZFJvb3QpIHtcbiAgICAgICAgICByZXN1bHQuYWRkKHNwbGl0KHApWzFdKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBbLi4ucmVzdWx0XTtcbiAgfVxuXG4gIHByb3RlY3RlZCBfZXhpc3RzKHBhdGg6IFBhdGgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gISF0aGlzLl9jYWNoZS5nZXQodGhpcy5fdG9BYnNvbHV0ZShwYXRoKSk7XG4gIH1cbiAgcHJvdGVjdGVkIF9pc0RpcmVjdG9yeShwYXRoOiBQYXRoKTogYm9vbGVhbiB7XG4gICAgY29uc3QgbWF5YmVTdGF0cyA9IHRoaXMuX2NhY2hlLmdldCh0aGlzLl90b0Fic29sdXRlKHBhdGgpKTtcblxuICAgIHJldHVybiBtYXliZVN0YXRzID8gbWF5YmVTdGF0cy5pc0RpcmVjdG9yeSgpIDogZmFsc2U7XG4gIH1cbiAgcHJvdGVjdGVkIF9pc0ZpbGUocGF0aDogUGF0aCk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IG1heWJlU3RhdHMgPSB0aGlzLl9jYWNoZS5nZXQodGhpcy5fdG9BYnNvbHV0ZShwYXRoKSk7XG5cbiAgICByZXR1cm4gbWF5YmVTdGF0cyA/IG1heWJlU3RhdHMuaXNGaWxlKCkgOiBmYWxzZTtcbiAgfVxuXG4gIHByb3RlY3RlZCBfc3RhdChwYXRoOiBQYXRoKTogU3RhdHM8U2ltcGxlTWVtb3J5SG9zdFN0YXRzPiB8IG51bGwge1xuICAgIGNvbnN0IG1heWJlU3RhdHMgPSB0aGlzLl9jYWNoZS5nZXQodGhpcy5fdG9BYnNvbHV0ZShwYXRoKSk7XG5cbiAgICBpZiAoIW1heWJlU3RhdHMpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gbWF5YmVTdGF0cztcbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgX3dhdGNoKHBhdGg6IFBhdGgsIG9wdGlvbnM/OiBIb3N0V2F0Y2hPcHRpb25zKTogT2JzZXJ2YWJsZTxIb3N0V2F0Y2hFdmVudD4ge1xuICAgIHBhdGggPSB0aGlzLl90b0Fic29sdXRlKHBhdGgpO1xuXG4gICAgY29uc3Qgc3ViamVjdCA9IG5ldyBTdWJqZWN0PEhvc3RXYXRjaEV2ZW50PigpO1xuICAgIGxldCBtYXliZVdhdGNoZXJBcnJheSA9IHRoaXMuX3dhdGNoZXJzLmdldChwYXRoKTtcbiAgICBpZiAoIW1heWJlV2F0Y2hlckFycmF5KSB7XG4gICAgICBtYXliZVdhdGNoZXJBcnJheSA9IFtdO1xuICAgICAgdGhpcy5fd2F0Y2hlcnMuc2V0KHBhdGgsIG1heWJlV2F0Y2hlckFycmF5KTtcbiAgICB9XG5cbiAgICBtYXliZVdhdGNoZXJBcnJheS5wdXNoKFtvcHRpb25zIHx8IHt9LCBzdWJqZWN0XSk7XG5cbiAgICByZXR1cm4gc3ViamVjdC5hc09ic2VydmFibGUoKTtcbiAgfVxuXG4gIHdyaXRlKHBhdGg6IFBhdGgsIGNvbnRlbnQ6IEZpbGVCdWZmZXIpOiBPYnNlcnZhYmxlPHZvaWQ+IHtcbiAgICByZXR1cm4gbmV3IE9ic2VydmFibGU8dm9pZD4oKG9icykgPT4ge1xuICAgICAgdGhpcy5fd3JpdGUocGF0aCwgY29udGVudCk7XG4gICAgICBvYnMubmV4dCgpO1xuICAgICAgb2JzLmNvbXBsZXRlKCk7XG4gICAgfSk7XG4gIH1cblxuICByZWFkKHBhdGg6IFBhdGgpOiBPYnNlcnZhYmxlPEZpbGVCdWZmZXI+IHtcbiAgICByZXR1cm4gbmV3IE9ic2VydmFibGU8RmlsZUJ1ZmZlcj4oKG9icykgPT4ge1xuICAgICAgY29uc3QgY29udGVudCA9IHRoaXMuX3JlYWQocGF0aCk7XG4gICAgICBvYnMubmV4dChjb250ZW50KTtcbiAgICAgIG9icy5jb21wbGV0ZSgpO1xuICAgIH0pO1xuICB9XG5cbiAgZGVsZXRlKHBhdGg6IFBhdGgpOiBPYnNlcnZhYmxlPHZvaWQ+IHtcbiAgICByZXR1cm4gbmV3IE9ic2VydmFibGU8dm9pZD4oKG9icykgPT4ge1xuICAgICAgdGhpcy5fZGVsZXRlKHBhdGgpO1xuICAgICAgb2JzLm5leHQoKTtcbiAgICAgIG9icy5jb21wbGV0ZSgpO1xuICAgIH0pO1xuICB9XG5cbiAgcmVuYW1lKGZyb206IFBhdGgsIHRvOiBQYXRoKTogT2JzZXJ2YWJsZTx2b2lkPiB7XG4gICAgcmV0dXJuIG5ldyBPYnNlcnZhYmxlPHZvaWQ+KChvYnMpID0+IHtcbiAgICAgIHRoaXMuX3JlbmFtZShmcm9tLCB0byk7XG4gICAgICBvYnMubmV4dCgpO1xuICAgICAgb2JzLmNvbXBsZXRlKCk7XG4gICAgfSk7XG4gIH1cblxuICBsaXN0KHBhdGg6IFBhdGgpOiBPYnNlcnZhYmxlPFBhdGhGcmFnbWVudFtdPiB7XG4gICAgcmV0dXJuIG5ldyBPYnNlcnZhYmxlPFBhdGhGcmFnbWVudFtdPigob2JzKSA9PiB7XG4gICAgICBvYnMubmV4dCh0aGlzLl9saXN0KHBhdGgpKTtcbiAgICAgIG9icy5jb21wbGV0ZSgpO1xuICAgIH0pO1xuICB9XG5cbiAgZXhpc3RzKHBhdGg6IFBhdGgpOiBPYnNlcnZhYmxlPGJvb2xlYW4+IHtcbiAgICByZXR1cm4gbmV3IE9ic2VydmFibGU8Ym9vbGVhbj4oKG9icykgPT4ge1xuICAgICAgb2JzLm5leHQodGhpcy5fZXhpc3RzKHBhdGgpKTtcbiAgICAgIG9icy5jb21wbGV0ZSgpO1xuICAgIH0pO1xuICB9XG5cbiAgaXNEaXJlY3RvcnkocGF0aDogUGF0aCk6IE9ic2VydmFibGU8Ym9vbGVhbj4ge1xuICAgIHJldHVybiBuZXcgT2JzZXJ2YWJsZTxib29sZWFuPigob2JzKSA9PiB7XG4gICAgICBvYnMubmV4dCh0aGlzLl9pc0RpcmVjdG9yeShwYXRoKSk7XG4gICAgICBvYnMuY29tcGxldGUoKTtcbiAgICB9KTtcbiAgfVxuXG4gIGlzRmlsZShwYXRoOiBQYXRoKTogT2JzZXJ2YWJsZTxib29sZWFuPiB7XG4gICAgcmV0dXJuIG5ldyBPYnNlcnZhYmxlPGJvb2xlYW4+KChvYnMpID0+IHtcbiAgICAgIG9icy5uZXh0KHRoaXMuX2lzRmlsZShwYXRoKSk7XG4gICAgICBvYnMuY29tcGxldGUoKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8vIFNvbWUgaG9zdHMgbWF5IG5vdCBzdXBwb3J0IHN0YXQuXG4gIHN0YXQocGF0aDogUGF0aCk6IE9ic2VydmFibGU8U3RhdHM8e30+IHwgbnVsbD4gfCBudWxsIHtcbiAgICByZXR1cm4gbmV3IE9ic2VydmFibGU8U3RhdHM8e30+IHwgbnVsbD4oKG9icykgPT4ge1xuICAgICAgb2JzLm5leHQodGhpcy5fc3RhdChwYXRoKSk7XG4gICAgICBvYnMuY29tcGxldGUoKTtcbiAgICB9KTtcbiAgfVxuXG4gIHdhdGNoKHBhdGg6IFBhdGgsIG9wdGlvbnM/OiBIb3N0V2F0Y2hPcHRpb25zKTogT2JzZXJ2YWJsZTxIb3N0V2F0Y2hFdmVudD4gfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy5fd2F0Y2gocGF0aCwgb3B0aW9ucyk7XG4gIH1cblxuICByZXNldCgpOiB2b2lkIHtcbiAgICB0aGlzLl9jYWNoZS5jbGVhcigpO1xuICAgIHRoaXMuX3dhdGNoZXJzLmNsZWFyKCk7XG4gIH1cbn1cbiJdfQ==
\No newline at end of file