@angular-devkit/core 7.2.0-beta.0 → 7.2.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 (48) hide show
  1. package/node/_golden-api.d.ts +12 -0
  2. package/node/_golden-api.js +24 -0
  3. package/node/experimental/index.d.ts +9 -0
  4. package/node/experimental/index.js +12 -0
  5. package/node/experimental/job-registry.d.ts +22 -0
  6. package/node/experimental/job-registry.js +70 -0
  7. package/node/fs.d.ts +2 -4
  8. package/node/fs.js +25 -28
  9. package/node/index.d.ts +3 -1
  10. package/node/index.js +5 -2
  11. package/node/resolve.js +4 -4
  12. package/package.json +2 -2
  13. package/src/exception/exception.d.ts +1 -1
  14. package/src/exception/exception.js +2 -2
  15. package/src/experimental/jobs/README.md +495 -0
  16. package/src/experimental/jobs/api.d.ts +345 -0
  17. package/src/experimental/jobs/api.js +68 -0
  18. package/src/experimental/jobs/architecture.md +257 -0
  19. package/src/experimental/jobs/create-job-handler.d.ts +50 -0
  20. package/src/experimental/jobs/create-job-handler.js +145 -0
  21. package/src/experimental/jobs/dispatcher.d.ts +32 -0
  22. package/src/experimental/jobs/dispatcher.js +42 -0
  23. package/src/experimental/jobs/exception.d.ts +15 -0
  24. package/src/experimental/jobs/exception.js +23 -0
  25. package/src/experimental/jobs/index.d.ts +14 -0
  26. package/src/experimental/jobs/index.js +20 -0
  27. package/src/experimental/jobs/simple-registry.d.ts +44 -0
  28. package/src/experimental/jobs/simple-registry.js +74 -0
  29. package/src/experimental/jobs/simple-scheduler.d.ts +74 -0
  30. package/src/experimental/jobs/simple-scheduler.js +367 -0
  31. package/src/experimental/jobs/strategy.d.ts +15 -0
  32. package/src/experimental/jobs/strategy.js +55 -0
  33. package/src/experimental.d.ts +2 -1
  34. package/src/experimental.js +3 -1
  35. package/src/json/schema/index.d.ts +1 -0
  36. package/src/json/schema/index.js +2 -1
  37. package/src/json/schema/registry.d.ts +2 -1
  38. package/src/json/schema/registry.js +10 -1
  39. package/src/json/schema/schema.d.ts +15 -0
  40. package/src/json/schema/schema.js +52 -0
  41. package/src/json/schema/utility.d.ts +2 -9
  42. package/src/json/schema/utility.js +1 -1
  43. package/src/json/schema/visitor.d.ts +2 -1
  44. package/src/json/schema/visitor.js +5 -1
  45. package/src/logger/logger.d.ts +1 -0
  46. package/src/logger/logger.js +4 -1
  47. package/src/utils/index.d.ts +9 -0
  48. package/src/utils/index.js +1 -1
@@ -0,0 +1,44 @@
1
+ /**
2
+ * @license
3
+ * Copyright Google Inc. All Rights Reserved.
4
+ *
5
+ * Use of this source code is governed by an MIT-style license that can be
6
+ * found in the LICENSE file at https://angular.io/license
7
+ */
8
+ import { Observable } from 'rxjs';
9
+ import { JsonValue } from '../../json';
10
+ import { JobDescription, JobHandler, JobName, Registry } from './api';
11
+ /**
12
+ * SimpleJobRegistry job registration options.
13
+ */
14
+ export interface RegisterJobOptions extends Partial<JobDescription> {
15
+ }
16
+ /**
17
+ * A simple job registry that keep a map of JobName => JobHandler internally.
18
+ */
19
+ export declare class SimpleJobRegistry<MinimumArgumentValueT extends JsonValue = JsonValue, MinimumInputValueT extends JsonValue = JsonValue, MinimumOutputValueT extends JsonValue = JsonValue> implements Registry<MinimumArgumentValueT, MinimumInputValueT, MinimumOutputValueT> {
20
+ private _jobNames;
21
+ get<A extends MinimumArgumentValueT = MinimumArgumentValueT, I extends MinimumInputValueT = MinimumInputValueT, O extends MinimumOutputValueT = MinimumOutputValueT>(name: JobName): Observable<JobHandler<A, I, O> | null>;
22
+ /**
23
+ * Register a job handler. The name must be unique.
24
+ *
25
+ * @param name The name of the job.
26
+ * @param handler The function that will be called for the job.
27
+ * @param options An optional list of options to override the handler. {@see RegisterJobOptions}
28
+ */
29
+ register<A extends MinimumArgumentValueT, I extends MinimumInputValueT, O extends MinimumOutputValueT>(name: JobName, handler: JobHandler<A, I, O>, options?: RegisterJobOptions): void;
30
+ /**
31
+ * Register a job handler. The name must be unique.
32
+ *
33
+ * @param handler The function that will be called for the job.
34
+ * @param options An optional list of options to override the handler. {@see RegisterJobOptions}
35
+ */
36
+ register<ArgumentT extends JsonValue, InputT extends JsonValue, OutputT extends JsonValue>(handler: JobHandler<ArgumentT, InputT, OutputT>, options?: RegisterJobOptions & {
37
+ name: string;
38
+ }): void;
39
+ protected _register<ArgumentT extends JsonValue, InputT extends JsonValue, OutputT extends JsonValue>(name: JobName, handler: JobHandler<ArgumentT, InputT, OutputT>, options: RegisterJobOptions): void;
40
+ /**
41
+ * Returns the job names of all jobs.
42
+ */
43
+ getJobNames(): JobName[];
44
+ }
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ /**
4
+ * @license
5
+ * Copyright Google Inc. All Rights Reserved.
6
+ *
7
+ * Use of this source code is governed by an MIT-style license that can be
8
+ * found in the LICENSE file at https://angular.io/license
9
+ */
10
+ const rxjs_1 = require("rxjs");
11
+ const json_1 = require("../../json");
12
+ const api_1 = require("./api");
13
+ const exception_1 = require("./exception");
14
+ /**
15
+ * A simple job registry that keep a map of JobName => JobHandler internally.
16
+ */
17
+ class SimpleJobRegistry {
18
+ constructor() {
19
+ this._jobNames = new Map();
20
+ }
21
+ get(name) {
22
+ return rxjs_1.of(this._jobNames.get(name) || null);
23
+ }
24
+ register(nameOrHandler, handlerOrOptions = {}, options = {}) {
25
+ // Switch on the arguments.
26
+ if (typeof nameOrHandler == 'string') {
27
+ if (!api_1.isJobHandler(handlerOrOptions)) {
28
+ // This is an error.
29
+ throw new TypeError('Expected a JobHandler as second argument.');
30
+ }
31
+ this._register(nameOrHandler, handlerOrOptions, options);
32
+ }
33
+ else if (api_1.isJobHandler(nameOrHandler)) {
34
+ if (typeof handlerOrOptions !== 'object') {
35
+ // This is an error.
36
+ throw new TypeError('Expected an object options as second argument.');
37
+ }
38
+ const name = options.name || nameOrHandler.jobDescription.name || handlerOrOptions.name;
39
+ if (name === undefined) {
40
+ throw new TypeError('Expected name to be a string.');
41
+ }
42
+ this._register(name, nameOrHandler, options);
43
+ }
44
+ else {
45
+ throw new TypeError('Unrecognized arguments.');
46
+ }
47
+ }
48
+ _register(name, handler, options) {
49
+ if (this._jobNames.has(name)) {
50
+ // We shouldn't allow conflicts.
51
+ throw new exception_1.JobNameAlreadyRegisteredException(name);
52
+ }
53
+ // Merge all fields with the ones in the handler (to make sure we respect the handler).
54
+ const argument = json_1.schema.mergeSchemas(handler.jobDescription.argument, options.argument);
55
+ const input = json_1.schema.mergeSchemas(handler.jobDescription.input, options.input);
56
+ const output = json_1.schema.mergeSchemas(handler.jobDescription.output, options.output);
57
+ // Create the job description.
58
+ const jobDescription = {
59
+ name,
60
+ argument,
61
+ output,
62
+ input,
63
+ };
64
+ this._jobNames.set(name, Object.assign(handler.bind(undefined), { jobDescription }));
65
+ }
66
+ /**
67
+ * Returns the job names of all jobs.
68
+ */
69
+ getJobNames() {
70
+ return [...this._jobNames.keys()];
71
+ }
72
+ }
73
+ exports.SimpleJobRegistry = SimpleJobRegistry;
74
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2ltcGxlLXJlZ2lzdHJ5LmpzIiwic291cmNlUm9vdCI6Ii4vIiwic291cmNlcyI6WyJwYWNrYWdlcy9hbmd1bGFyX2RldmtpdC9jb3JlL3NyYy9leHBlcmltZW50YWwvam9icy9zaW1wbGUtcmVnaXN0cnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQTs7Ozs7O0dBTUc7QUFDSCwrQkFBc0M7QUFDdEMscUNBQStDO0FBQy9DLCtCQUFvRjtBQUNwRiwyQ0FBZ0U7QUFRaEU7O0dBRUc7QUFDSCxNQUFhLGlCQUFpQjtJQUE5QjtRQUtVLGNBQVMsR0FBRyxJQUFJLEdBQUcsRUFHeEIsQ0FBQztJQWtITixDQUFDO0lBaEhDLEdBQUcsQ0FJRCxJQUFhO1FBQ2IsT0FBTyxTQUFFLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFpQyxJQUFJLElBQUksQ0FBQyxDQUFDO0lBQzlFLENBQUM7SUErQkQsUUFBUSxDQUNOLGFBQStELEVBQy9ELG1CQUFnRixFQUFFLEVBQ2xGLFVBQThCLEVBQUU7UUFFaEMsMkJBQTJCO1FBQzNCLElBQUksT0FBTyxhQUFhLElBQUksUUFBUSxFQUFFO1lBQ3BDLElBQUksQ0FBQyxrQkFBWSxDQUFDLGdCQUFnQixDQUFDLEVBQUU7Z0JBQ25DLG9CQUFvQjtnQkFDcEIsTUFBTSxJQUFJLFNBQVMsQ0FBQywyQ0FBMkMsQ0FBQyxDQUFDO2FBQ2xFO1lBRUQsSUFBSSxDQUFDLFNBQVMsQ0FBQyxhQUFhLEVBQUUsZ0JBQWdCLEVBQUUsT0FBTyxDQUFDLENBQUM7U0FDMUQ7YUFBTSxJQUFJLGtCQUFZLENBQUMsYUFBYSxDQUFDLEVBQUU7WUFDdEMsSUFBSSxPQUFPLGdCQUFnQixLQUFLLFFBQVEsRUFBRTtnQkFDeEMsb0JBQW9CO2dCQUNwQixNQUFNLElBQUksU0FBUyxDQUFDLGdEQUFnRCxDQUFDLENBQUM7YUFDdkU7WUFFRCxNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsSUFBSSxJQUFJLGFBQWEsQ0FBQyxjQUFjLENBQUMsSUFBSSxJQUFJLGdCQUFnQixDQUFDLElBQUksQ0FBQztZQUN4RixJQUFJLElBQUksS0FBSyxTQUFTLEVBQUU7Z0JBQ3RCLE1BQU0sSUFBSSxTQUFTLENBQUMsK0JBQStCLENBQUMsQ0FBQzthQUN0RDtZQUVELElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLGFBQWEsRUFBRSxPQUFPLENBQUMsQ0FBQztTQUM5QzthQUFNO1lBQ0wsTUFBTSxJQUFJLFNBQVMsQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDO1NBQ2hEO0lBQ0gsQ0FBQztJQUVTLFNBQVMsQ0FLakIsSUFBYSxFQUNiLE9BQStDLEVBQy9DLE9BQTJCO1FBRTNCLElBQUksSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUU7WUFDNUIsZ0NBQWdDO1lBQ2hDLE1BQU0sSUFBSSw2Q0FBaUMsQ0FBQyxJQUFJLENBQUMsQ0FBQztTQUNuRDtRQUVELHVGQUF1RjtRQUN2RixNQUFNLFFBQVEsR0FBRyxhQUFNLENBQUMsWUFBWSxDQUNsQyxPQUFPLENBQUMsY0FBYyxDQUFDLFFBQVEsRUFDL0IsT0FBTyxDQUFDLFFBQVEsQ0FDakIsQ0FBQztRQUNGLE1BQU0sS0FBSyxHQUFHLGFBQU0sQ0FBQyxZQUFZLENBQy9CLE9BQU8sQ0FBQyxjQUFjLENBQUMsS0FBSyxFQUM1QixPQUFPLENBQUMsS0FBSyxDQUNkLENBQUM7UUFDRixNQUFNLE1BQU0sR0FBRyxhQUFNLENBQUMsWUFBWSxDQUNoQyxPQUFPLENBQUMsY0FBYyxDQUFDLE1BQU0sRUFDN0IsT0FBTyxDQUFDLE1BQU0sQ0FDZixDQUFDO1FBRUYsOEJBQThCO1FBQzlCLE1BQU0sY0FBYyxHQUFtQjtZQUNyQyxJQUFJO1lBQ0osUUFBUTtZQUNSLE1BQU07WUFDTixLQUFLO1NBQ04sQ0FBQztRQUVGLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxNQUFNLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsRUFBRSxjQUFjLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDdkYsQ0FBQztJQUVEOztPQUVHO0lBQ0gsV0FBVztRQUNULE9BQU8sQ0FBQyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUNwQyxDQUFDO0NBQ0Y7QUExSEQsOENBMEhDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IEdvb2dsZSBJbmMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbiAqIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgYXQgaHR0cHM6Ly9hbmd1bGFyLmlvL2xpY2Vuc2VcbiAqL1xuaW1wb3J0IHsgT2JzZXJ2YWJsZSwgb2YgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IEpzb25WYWx1ZSwgc2NoZW1hIH0gZnJvbSAnLi4vLi4vanNvbic7XG5pbXBvcnQgeyBKb2JEZXNjcmlwdGlvbiwgSm9iSGFuZGxlciwgSm9iTmFtZSwgUmVnaXN0cnksIGlzSm9iSGFuZGxlciB9IGZyb20gJy4vYXBpJztcbmltcG9ydCB7IEpvYk5hbWVBbHJlYWR5UmVnaXN0ZXJlZEV4Y2VwdGlvbiB9IGZyb20gJy4vZXhjZXB0aW9uJztcblxuXG4vKipcbiAqIFNpbXBsZUpvYlJlZ2lzdHJ5IGpvYiByZWdpc3RyYXRpb24gb3B0aW9ucy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZWdpc3RlckpvYk9wdGlvbnMgZXh0ZW5kcyBQYXJ0aWFsPEpvYkRlc2NyaXB0aW9uPiB7fVxuXG4vKipcbiAqIEEgc2ltcGxlIGpvYiByZWdpc3RyeSB0aGF0IGtlZXAgYSBtYXAgb2YgSm9iTmFtZSA9PiBKb2JIYW5kbGVyIGludGVybmFsbHkuXG4gKi9cbmV4cG9ydCBjbGFzcyBTaW1wbGVKb2JSZWdpc3RyeTxcbiAgTWluaW11bUFyZ3VtZW50VmFsdWVUIGV4dGVuZHMgSnNvblZhbHVlID0gSnNvblZhbHVlLFxuICBNaW5pbXVtSW5wdXRWYWx1ZVQgZXh0ZW5kcyBKc29uVmFsdWUgPSBKc29uVmFsdWUsXG4gIE1pbmltdW1PdXRwdXRWYWx1ZVQgZXh0ZW5kcyBKc29uVmFsdWUgPSBKc29uVmFsdWUsXG4+IGltcGxlbWVudHMgUmVnaXN0cnk8TWluaW11bUFyZ3VtZW50VmFsdWVULCBNaW5pbXVtSW5wdXRWYWx1ZVQsIE1pbmltdW1PdXRwdXRWYWx1ZVQ+IHtcbiAgcHJpdmF0ZSBfam9iTmFtZXMgPSBuZXcgTWFwPFxuICAgIEpvYk5hbWUsXG4gICAgSm9iSGFuZGxlcjxNaW5pbXVtQXJndW1lbnRWYWx1ZVQsIE1pbmltdW1JbnB1dFZhbHVlVCwgTWluaW11bU91dHB1dFZhbHVlVD5cbiAgPigpO1xuXG4gIGdldDxcbiAgICBBIGV4dGVuZHMgTWluaW11bUFyZ3VtZW50VmFsdWVUID0gTWluaW11bUFyZ3VtZW50VmFsdWVULFxuICAgIEkgZXh0ZW5kcyBNaW5pbXVtSW5wdXRWYWx1ZVQgPSBNaW5pbXVtSW5wdXRWYWx1ZVQsXG4gICAgTyBleHRlbmRzIE1pbmltdW1PdXRwdXRWYWx1ZVQgPSBNaW5pbXVtT3V0cHV0VmFsdWVULFxuICA+KG5hbWU6IEpvYk5hbWUpOiBPYnNlcnZhYmxlPEpvYkhhbmRsZXI8QSwgSSwgTz4gfCBudWxsPiB7XG4gICAgcmV0dXJuIG9mKHRoaXMuX2pvYk5hbWVzLmdldChuYW1lKSBhcyAoSm9iSGFuZGxlcjxBLCBJLCBPPiB8IG51bGwpIHx8IG51bGwpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlZ2lzdGVyIGEgam9iIGhhbmRsZXIuIFRoZSBuYW1lIG11c3QgYmUgdW5pcXVlLlxuICAgKlxuICAgKiBAcGFyYW0gbmFtZSBUaGUgbmFtZSBvZiB0aGUgam9iLlxuICAgKiBAcGFyYW0gaGFuZGxlciBUaGUgZnVuY3Rpb24gdGhhdCB3aWxsIGJlIGNhbGxlZCBmb3IgdGhlIGpvYi5cbiAgICogQHBhcmFtIG9wdGlvbnMgQW4gb3B0aW9uYWwgbGlzdCBvZiBvcHRpb25zIHRvIG92ZXJyaWRlIHRoZSBoYW5kbGVyLiB7QHNlZSBSZWdpc3RlckpvYk9wdGlvbnN9XG4gICAqL1xuICByZWdpc3RlcjxcbiAgICBBIGV4dGVuZHMgTWluaW11bUFyZ3VtZW50VmFsdWVULFxuICAgIEkgZXh0ZW5kcyBNaW5pbXVtSW5wdXRWYWx1ZVQsXG4gICAgTyBleHRlbmRzIE1pbmltdW1PdXRwdXRWYWx1ZVQsXG4gID4oXG4gICAgbmFtZTogSm9iTmFtZSxcbiAgICBoYW5kbGVyOiBKb2JIYW5kbGVyPEEsIEksIE8+LFxuICAgIG9wdGlvbnM/OiBSZWdpc3RlckpvYk9wdGlvbnMsXG4gICk6IHZvaWQ7XG5cbiAgLyoqXG4gICAqIFJlZ2lzdGVyIGEgam9iIGhhbmRsZXIuIFRoZSBuYW1lIG11c3QgYmUgdW5pcXVlLlxuICAgKlxuICAgKiBAcGFyYW0gaGFuZGxlciBUaGUgZnVuY3Rpb24gdGhhdCB3aWxsIGJlIGNhbGxlZCBmb3IgdGhlIGpvYi5cbiAgICogQHBhcmFtIG9wdGlvbnMgQW4gb3B0aW9uYWwgbGlzdCBvZiBvcHRpb25zIHRvIG92ZXJyaWRlIHRoZSBoYW5kbGVyLiB7QHNlZSBSZWdpc3RlckpvYk9wdGlvbnN9XG4gICAqL1xuICByZWdpc3RlcjxBcmd1bWVudFQgZXh0ZW5kcyBKc29uVmFsdWUsIElucHV0VCBleHRlbmRzIEpzb25WYWx1ZSwgT3V0cHV0VCBleHRlbmRzIEpzb25WYWx1ZT4oXG4gICAgaGFuZGxlcjogSm9iSGFuZGxlcjxBcmd1bWVudFQsIElucHV0VCwgT3V0cHV0VD4sXG4gICAgLy8gVGhpcyB2ZXJzaW9uIE1VU1QgY29udGFpbiBhIG5hbWUuXG4gICAgb3B0aW9ucz86IFJlZ2lzdGVySm9iT3B0aW9ucyAmIHsgbmFtZTogc3RyaW5nIH0sXG4gICk6IHZvaWQ7XG5cbiAgcmVnaXN0ZXI8QXJndW1lbnRUIGV4dGVuZHMgSnNvblZhbHVlLCBJbnB1dFQgZXh0ZW5kcyBKc29uVmFsdWUsIE91dHB1dFQgZXh0ZW5kcyBKc29uVmFsdWU+KFxuICAgIG5hbWVPckhhbmRsZXI6IEpvYk5hbWUgfCBKb2JIYW5kbGVyPEFyZ3VtZW50VCwgSW5wdXRULCBPdXRwdXRUPixcbiAgICBoYW5kbGVyT3JPcHRpb25zOiBKb2JIYW5kbGVyPEFyZ3VtZW50VCwgSW5wdXRULCBPdXRwdXRUPiB8IFJlZ2lzdGVySm9iT3B0aW9ucyA9IHt9LFxuICAgIG9wdGlvbnM6IFJlZ2lzdGVySm9iT3B0aW9ucyA9IHt9LFxuICApOiB2b2lkIHtcbiAgICAvLyBTd2l0Y2ggb24gdGhlIGFyZ3VtZW50cy5cbiAgICBpZiAodHlwZW9mIG5hbWVPckhhbmRsZXIgPT0gJ3N0cmluZycpIHtcbiAgICAgIGlmICghaXNKb2JIYW5kbGVyKGhhbmRsZXJPck9wdGlvbnMpKSB7XG4gICAgICAgIC8vIFRoaXMgaXMgYW4gZXJyb3IuXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0V4cGVjdGVkIGEgSm9iSGFuZGxlciBhcyBzZWNvbmQgYXJndW1lbnQuJyk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX3JlZ2lzdGVyKG5hbWVPckhhbmRsZXIsIGhhbmRsZXJPck9wdGlvbnMsIG9wdGlvbnMpO1xuICAgIH0gZWxzZSBpZiAoaXNKb2JIYW5kbGVyKG5hbWVPckhhbmRsZXIpKSB7XG4gICAgICBpZiAodHlwZW9mIGhhbmRsZXJPck9wdGlvbnMgIT09ICdvYmplY3QnKSB7XG4gICAgICAgIC8vIFRoaXMgaXMgYW4gZXJyb3IuXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0V4cGVjdGVkIGFuIG9iamVjdCBvcHRpb25zIGFzIHNlY29uZCBhcmd1bWVudC4nKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgbmFtZSA9IG9wdGlvbnMubmFtZSB8fCBuYW1lT3JIYW5kbGVyLmpvYkRlc2NyaXB0aW9uLm5hbWUgfHwgaGFuZGxlck9yT3B0aW9ucy5uYW1lO1xuICAgICAgaWYgKG5hbWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdFeHBlY3RlZCBuYW1lIHRvIGJlIGEgc3RyaW5nLicpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9yZWdpc3RlcihuYW1lLCBuYW1lT3JIYW5kbGVyLCBvcHRpb25zKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignVW5yZWNvZ25pemVkIGFyZ3VtZW50cy4nKTtcbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgX3JlZ2lzdGVyPFxuICAgIEFyZ3VtZW50VCBleHRlbmRzIEpzb25WYWx1ZSxcbiAgICBJbnB1dFQgZXh0ZW5kcyBKc29uVmFsdWUsXG4gICAgT3V0cHV0VCBleHRlbmRzIEpzb25WYWx1ZSxcbiAgPihcbiAgICBuYW1lOiBKb2JOYW1lLFxuICAgIGhhbmRsZXI6IEpvYkhhbmRsZXI8QXJndW1lbnRULCBJbnB1dFQsIE91dHB1dFQ+LFxuICAgIG9wdGlvbnM6IFJlZ2lzdGVySm9iT3B0aW9ucyxcbiAgKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuX2pvYk5hbWVzLmhhcyhuYW1lKSkge1xuICAgICAgLy8gV2Ugc2hvdWxkbid0IGFsbG93IGNvbmZsaWN0cy5cbiAgICAgIHRocm93IG5ldyBKb2JOYW1lQWxyZWFkeVJlZ2lzdGVyZWRFeGNlcHRpb24obmFtZSk7XG4gICAgfVxuXG4gICAgLy8gTWVyZ2UgYWxsIGZpZWxkcyB3aXRoIHRoZSBvbmVzIGluIHRoZSBoYW5kbGVyICh0byBtYWtlIHN1cmUgd2UgcmVzcGVjdCB0aGUgaGFuZGxlcikuXG4gICAgY29uc3QgYXJndW1lbnQgPSBzY2hlbWEubWVyZ2VTY2hlbWFzKFxuICAgICAgaGFuZGxlci5qb2JEZXNjcmlwdGlvbi5hcmd1bWVudCxcbiAgICAgIG9wdGlvbnMuYXJndW1lbnQsXG4gICAgKTtcbiAgICBjb25zdCBpbnB1dCA9IHNjaGVtYS5tZXJnZVNjaGVtYXMoXG4gICAgICBoYW5kbGVyLmpvYkRlc2NyaXB0aW9uLmlucHV0LFxuICAgICAgb3B0aW9ucy5pbnB1dCxcbiAgICApO1xuICAgIGNvbnN0IG91dHB1dCA9IHNjaGVtYS5tZXJnZVNjaGVtYXMoXG4gICAgICBoYW5kbGVyLmpvYkRlc2NyaXB0aW9uLm91dHB1dCxcbiAgICAgIG9wdGlvbnMub3V0cHV0LFxuICAgICk7XG5cbiAgICAvLyBDcmVhdGUgdGhlIGpvYiBkZXNjcmlwdGlvbi5cbiAgICBjb25zdCBqb2JEZXNjcmlwdGlvbjogSm9iRGVzY3JpcHRpb24gPSB7XG4gICAgICBuYW1lLFxuICAgICAgYXJndW1lbnQsXG4gICAgICBvdXRwdXQsXG4gICAgICBpbnB1dCxcbiAgICB9O1xuXG4gICAgdGhpcy5fam9iTmFtZXMuc2V0KG5hbWUsIE9iamVjdC5hc3NpZ24oaGFuZGxlci5iaW5kKHVuZGVmaW5lZCksIHsgam9iRGVzY3JpcHRpb24gfSkpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGpvYiBuYW1lcyBvZiBhbGwgam9icy5cbiAgICovXG4gIGdldEpvYk5hbWVzKCk6IEpvYk5hbWVbXSB7XG4gICAgcmV0dXJuIFsuLi50aGlzLl9qb2JOYW1lcy5rZXlzKCldO1xuICB9XG59XG4iXX0=
@@ -0,0 +1,74 @@
1
+ /**
2
+ * @license
3
+ * Copyright Google Inc. All Rights Reserved.
4
+ *
5
+ * Use of this source code is governed by an MIT-style license that can be
6
+ * found in the LICENSE file at https://angular.io/license
7
+ */
8
+ import { Observable } from 'rxjs';
9
+ import { JsonValue, schema } from '../../json';
10
+ import { Job, JobDescription, JobName, Registry, ScheduleJobOptions, Scheduler } from './api';
11
+ export declare class JobInboundMessageSchemaValidationError extends schema.SchemaValidationException {
12
+ constructor(errors?: schema.SchemaValidatorError[]);
13
+ }
14
+ export declare class JobOutputSchemaValidationError extends schema.SchemaValidationException {
15
+ constructor(errors?: schema.SchemaValidatorError[]);
16
+ }
17
+ /**
18
+ * Simple scheduler. Should be the base of all registries and schedulers.
19
+ */
20
+ export declare class SimpleScheduler<MinimumArgumentT extends JsonValue = JsonValue, MinimumInputT extends JsonValue = JsonValue, MinimumOutputT extends JsonValue = JsonValue> implements Scheduler<MinimumArgumentT, MinimumInputT, MinimumOutputT> {
21
+ protected _jobRegistry: Registry<MinimumArgumentT, MinimumInputT, MinimumOutputT>;
22
+ protected _schemaRegistry: schema.SchemaRegistry;
23
+ private _internalJobDescriptionMap;
24
+ private _queue;
25
+ private _pauseCounter;
26
+ constructor(_jobRegistry: Registry<MinimumArgumentT, MinimumInputT, MinimumOutputT>, _schemaRegistry?: schema.SchemaRegistry);
27
+ private _getInternalDescription;
28
+ /**
29
+ * Get a job description for a named job.
30
+ *
31
+ * @param name The name of the job.
32
+ * @returns A description, or null if the job is not registered.
33
+ */
34
+ getDescription(name: JobName): Observable<JobDescription | null>;
35
+ /**
36
+ * Returns true if the job name has been registered.
37
+ * @param name The name of the job.
38
+ * @returns True if the job exists, false otherwise.
39
+ */
40
+ has(name: JobName): Observable<boolean>;
41
+ /**
42
+ * Pause the scheduler, temporary queueing _new_ jobs. Returns a resume function that should be
43
+ * used to resume execution. If multiple `pause()` were called, all their resume functions must
44
+ * be called before the Scheduler actually starts new jobs. Additional calls to the same resume
45
+ * function will have no effect.
46
+ *
47
+ * Jobs already running are NOT paused. This is pausing the scheduler only.
48
+ */
49
+ pause(): () => void;
50
+ /**
51
+ * Schedule a job to be run, using its name.
52
+ * @param name The name of job to be run.
53
+ * @param argument The argument to send to the job when starting it.
54
+ * @param options Scheduling options.
55
+ * @returns The Job being run.
56
+ */
57
+ schedule<A extends MinimumArgumentT, I extends MinimumInputT, O extends MinimumOutputT>(name: JobName, argument: A, options?: ScheduleJobOptions): Job<A, I, O>;
58
+ /**
59
+ * Filter messages.
60
+ * @private
61
+ */
62
+ private _filterJobOutboundMessages;
63
+ /**
64
+ * Return a new state. This is just to simplify the reading of the _createJob method.
65
+ * @private
66
+ */
67
+ private _updateState;
68
+ /**
69
+ * Create the job.
70
+ * @private
71
+ */
72
+ private _createJob;
73
+ protected _scheduleJob<A extends MinimumArgumentT, I extends MinimumInputT, O extends MinimumOutputT>(name: JobName, argument: A, options: ScheduleJobOptions, waitable: Observable<never>): Job<A, I, O>;
74
+ }
@@ -0,0 +1,367 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ /**
4
+ * @license
5
+ * Copyright Google Inc. All Rights Reserved.
6
+ *
7
+ * Use of this source code is governed by an MIT-style license that can be
8
+ * found in the LICENSE file at https://angular.io/license
9
+ */
10
+ const rxjs_1 = require("rxjs");
11
+ const operators_1 = require("rxjs/operators");
12
+ const json_1 = require("../../json");
13
+ const logger_1 = require("../../logger");
14
+ const api_1 = require("./api");
15
+ const exception_1 = require("./exception");
16
+ class JobInboundMessageSchemaValidationError extends json_1.schema.SchemaValidationException {
17
+ constructor(errors) {
18
+ super(errors, 'Job Inbound Message failed to validate. Errors: ');
19
+ }
20
+ }
21
+ exports.JobInboundMessageSchemaValidationError = JobInboundMessageSchemaValidationError;
22
+ class JobOutputSchemaValidationError extends json_1.schema.SchemaValidationException {
23
+ constructor(errors) {
24
+ super(errors, 'Job Output failed to validate. Errors: ');
25
+ }
26
+ }
27
+ exports.JobOutputSchemaValidationError = JobOutputSchemaValidationError;
28
+ function _jobShare() {
29
+ // This is the same code as a `shareReplay()` operator, but uses a dumber Subject rather than a
30
+ // ReplaySubject.
31
+ return (source) => {
32
+ let refCount = 0;
33
+ let subject;
34
+ let hasError = false;
35
+ let isComplete = false;
36
+ let subscription;
37
+ return new rxjs_1.Observable(subscriber => {
38
+ let innerSub;
39
+ refCount++;
40
+ if (!subject) {
41
+ subject = new rxjs_1.Subject();
42
+ innerSub = subject.subscribe(subscriber);
43
+ subscription = source.subscribe({
44
+ next(value) { subject.next(value); },
45
+ error(err) {
46
+ hasError = true;
47
+ subject.error(err);
48
+ },
49
+ complete() {
50
+ isComplete = true;
51
+ subject.complete();
52
+ },
53
+ });
54
+ }
55
+ else {
56
+ innerSub = subject.subscribe(subscriber);
57
+ }
58
+ return () => {
59
+ refCount--;
60
+ innerSub.unsubscribe();
61
+ if (subscription && refCount === 0 && (isComplete || hasError)) {
62
+ subscription.unsubscribe();
63
+ }
64
+ };
65
+ });
66
+ };
67
+ }
68
+ /**
69
+ * Simple scheduler. Should be the base of all registries and schedulers.
70
+ */
71
+ class SimpleScheduler {
72
+ constructor(_jobRegistry, _schemaRegistry = new json_1.schema.CoreSchemaRegistry()) {
73
+ this._jobRegistry = _jobRegistry;
74
+ this._schemaRegistry = _schemaRegistry;
75
+ this._internalJobDescriptionMap = new Map();
76
+ this._queue = [];
77
+ this._pauseCounter = 0;
78
+ }
79
+ _getInternalDescription(name) {
80
+ const maybeHandler = this._internalJobDescriptionMap.get(name);
81
+ if (maybeHandler !== undefined) {
82
+ return rxjs_1.of(maybeHandler);
83
+ }
84
+ const handler = this._jobRegistry.get(name);
85
+ return handler.pipe(operators_1.switchMap(handler => {
86
+ if (handler === null) {
87
+ return rxjs_1.of(null);
88
+ }
89
+ const description = {
90
+ name,
91
+ argument: handler.jobDescription.argument || true,
92
+ input: handler.jobDescription.input || true,
93
+ output: handler.jobDescription.output || true,
94
+ channels: handler.jobDescription.channels || {},
95
+ };
96
+ const handlerWithExtra = Object.assign(handler.bind(undefined), {
97
+ jobDescription: description,
98
+ argumentV: this._schemaRegistry.compile(description.argument).pipe(operators_1.shareReplay(1)),
99
+ inputV: this._schemaRegistry.compile(description.input).pipe(operators_1.shareReplay(1)),
100
+ outputV: this._schemaRegistry.compile(description.output).pipe(operators_1.shareReplay(1)),
101
+ });
102
+ this._internalJobDescriptionMap.set(name, handlerWithExtra);
103
+ return rxjs_1.of(handlerWithExtra);
104
+ }));
105
+ }
106
+ /**
107
+ * Get a job description for a named job.
108
+ *
109
+ * @param name The name of the job.
110
+ * @returns A description, or null if the job is not registered.
111
+ */
112
+ getDescription(name) {
113
+ return rxjs_1.concat(this._getInternalDescription(name).pipe(operators_1.map(x => x && x.jobDescription)), rxjs_1.of(null)).pipe(operators_1.first());
114
+ }
115
+ /**
116
+ * Returns true if the job name has been registered.
117
+ * @param name The name of the job.
118
+ * @returns True if the job exists, false otherwise.
119
+ */
120
+ has(name) {
121
+ return this.getDescription(name).pipe(operators_1.map(x => x !== null));
122
+ }
123
+ /**
124
+ * Pause the scheduler, temporary queueing _new_ jobs. Returns a resume function that should be
125
+ * used to resume execution. If multiple `pause()` were called, all their resume functions must
126
+ * be called before the Scheduler actually starts new jobs. Additional calls to the same resume
127
+ * function will have no effect.
128
+ *
129
+ * Jobs already running are NOT paused. This is pausing the scheduler only.
130
+ */
131
+ pause() {
132
+ let called = false;
133
+ this._pauseCounter++;
134
+ return () => {
135
+ if (!called) {
136
+ called = true;
137
+ if (--this._pauseCounter == 0) {
138
+ // Resume the queue.
139
+ const q = this._queue;
140
+ this._queue = [];
141
+ q.forEach(fn => fn());
142
+ }
143
+ }
144
+ };
145
+ }
146
+ /**
147
+ * Schedule a job to be run, using its name.
148
+ * @param name The name of job to be run.
149
+ * @param argument The argument to send to the job when starting it.
150
+ * @param options Scheduling options.
151
+ * @returns The Job being run.
152
+ */
153
+ schedule(name, argument, options) {
154
+ if (this._pauseCounter > 0) {
155
+ const waitable = new rxjs_1.Subject();
156
+ this._queue.push(() => waitable.complete());
157
+ return this._scheduleJob(name, argument, options || {}, waitable);
158
+ }
159
+ return this._scheduleJob(name, argument, options || {}, rxjs_1.EMPTY);
160
+ }
161
+ /**
162
+ * Filter messages.
163
+ * @private
164
+ */
165
+ _filterJobOutboundMessages(message, state) {
166
+ switch (message.kind) {
167
+ case api_1.JobOutboundMessageKind.OnReady:
168
+ return state == api_1.JobState.Queued;
169
+ case api_1.JobOutboundMessageKind.Start:
170
+ return state == api_1.JobState.Ready;
171
+ case api_1.JobOutboundMessageKind.End:
172
+ return state == api_1.JobState.Started || state == api_1.JobState.Ready;
173
+ }
174
+ return true;
175
+ }
176
+ /**
177
+ * Return a new state. This is just to simplify the reading of the _createJob method.
178
+ * @private
179
+ */
180
+ _updateState(message, state) {
181
+ switch (message.kind) {
182
+ case api_1.JobOutboundMessageKind.OnReady:
183
+ return api_1.JobState.Ready;
184
+ case api_1.JobOutboundMessageKind.Start:
185
+ return api_1.JobState.Started;
186
+ case api_1.JobOutboundMessageKind.End:
187
+ return api_1.JobState.Ended;
188
+ }
189
+ return state;
190
+ }
191
+ /**
192
+ * Create the job.
193
+ * @private
194
+ */
195
+ _createJob(name, argument, handler, inboundBus, outboundBus, options) {
196
+ const schemaRegistry = this._schemaRegistry;
197
+ const channelsSubject = new Map();
198
+ const channels = new Map();
199
+ let state = api_1.JobState.Queued;
200
+ let pingId = 0;
201
+ const logger = options.logger ? options.logger.createChild('job') : new logger_1.NullLogger();
202
+ // Create the input channel by having a filter.
203
+ const input = new rxjs_1.Subject();
204
+ input.pipe(operators_1.switchMap(message => handler.pipe(operators_1.switchMap(handler => {
205
+ if (handler === null) {
206
+ throw new exception_1.JobDoesNotExistException(name);
207
+ }
208
+ else {
209
+ return handler.inputV.pipe(operators_1.switchMap(validate => validate(message)));
210
+ }
211
+ }))), operators_1.filter(result => result.success), operators_1.map(result => result.data)).subscribe(value => inboundBus.next({ kind: api_1.JobInboundMessageKind.Input, value }));
212
+ outboundBus = rxjs_1.concat(outboundBus,
213
+ // Add an End message at completion. This will be filtered out if the job actually send an
214
+ // End.
215
+ handler.pipe(operators_1.switchMap(handler => {
216
+ if (handler) {
217
+ return rxjs_1.of({
218
+ kind: api_1.JobOutboundMessageKind.End, description: handler.jobDescription,
219
+ });
220
+ }
221
+ else {
222
+ return rxjs_1.EMPTY;
223
+ }
224
+ }))).pipe(operators_1.filter(message => this._filterJobOutboundMessages(message, state)),
225
+ // Update internal logic and Job<> members.
226
+ operators_1.tap(message => {
227
+ // Update the state.
228
+ state = this._updateState(message, state);
229
+ switch (message.kind) {
230
+ case api_1.JobOutboundMessageKind.Log:
231
+ logger.next(message.entry);
232
+ break;
233
+ case api_1.JobOutboundMessageKind.ChannelCreate: {
234
+ const maybeSubject = channelsSubject.get(message.name);
235
+ // If it doesn't exist or it's closed on the other end.
236
+ if (!maybeSubject) {
237
+ const s = new rxjs_1.Subject();
238
+ channelsSubject.set(message.name, s);
239
+ channels.set(message.name, s.asObservable());
240
+ }
241
+ break;
242
+ }
243
+ case api_1.JobOutboundMessageKind.ChannelMessage: {
244
+ const maybeSubject = channelsSubject.get(message.name);
245
+ if (maybeSubject) {
246
+ maybeSubject.next(message.message);
247
+ }
248
+ break;
249
+ }
250
+ case api_1.JobOutboundMessageKind.ChannelComplete: {
251
+ const maybeSubject = channelsSubject.get(message.name);
252
+ if (maybeSubject) {
253
+ maybeSubject.complete();
254
+ channelsSubject.delete(message.name);
255
+ }
256
+ break;
257
+ }
258
+ case api_1.JobOutboundMessageKind.ChannelError: {
259
+ const maybeSubject = channelsSubject.get(message.name);
260
+ if (maybeSubject) {
261
+ maybeSubject.error(message.error);
262
+ channelsSubject.delete(message.name);
263
+ }
264
+ break;
265
+ }
266
+ }
267
+ }, () => {
268
+ state = api_1.JobState.Errored;
269
+ }),
270
+ // Do output validation (might include default values so this might have side
271
+ // effects). We keep all messages in order.
272
+ operators_1.concatMap(message => {
273
+ if (message.kind !== api_1.JobOutboundMessageKind.Output) {
274
+ return rxjs_1.of(message);
275
+ }
276
+ return handler.pipe(operators_1.switchMap(handler => {
277
+ if (handler === null) {
278
+ throw new exception_1.JobDoesNotExistException(name);
279
+ }
280
+ else {
281
+ return handler.outputV.pipe(operators_1.switchMap(validate => validate(message.value)), operators_1.switchMap(output => {
282
+ if (!output.success) {
283
+ throw new JobOutputSchemaValidationError(output.errors);
284
+ }
285
+ return rxjs_1.of(Object.assign({}, message, { output: output.data }));
286
+ }));
287
+ }
288
+ }));
289
+ }), _jobShare());
290
+ const output = outboundBus.pipe(operators_1.filter(x => x.kind == api_1.JobOutboundMessageKind.Output), operators_1.map((x) => x.value), operators_1.shareReplay(1));
291
+ // Return the Job.
292
+ return {
293
+ get state() { return state; },
294
+ argument,
295
+ description: handler.pipe(operators_1.switchMap(handler => {
296
+ if (handler === null) {
297
+ throw new exception_1.JobDoesNotExistException(name);
298
+ }
299
+ else {
300
+ return rxjs_1.of(handler.jobDescription);
301
+ }
302
+ })),
303
+ output,
304
+ getChannel(name, schema = true) {
305
+ let maybeObservable = channels.get(name);
306
+ if (!maybeObservable) {
307
+ const s = new rxjs_1.Subject();
308
+ channelsSubject.set(name, s);
309
+ channels.set(name, s.asObservable());
310
+ maybeObservable = s.asObservable();
311
+ }
312
+ return maybeObservable.pipe(
313
+ // Keep the order of messages.
314
+ operators_1.concatMap(message => {
315
+ return schemaRegistry.compile(schema).pipe(operators_1.switchMap(validate => validate(message)), operators_1.filter(x => x.success), operators_1.map(x => x.data));
316
+ }));
317
+ },
318
+ ping() {
319
+ const id = pingId++;
320
+ inboundBus.next({ kind: api_1.JobInboundMessageKind.Ping, id });
321
+ return outboundBus.pipe(operators_1.filter(x => x.kind === api_1.JobOutboundMessageKind.Pong && x.id == id), operators_1.first(), operators_1.ignoreElements());
322
+ },
323
+ stop() {
324
+ inboundBus.next({ kind: api_1.JobInboundMessageKind.Stop });
325
+ },
326
+ input,
327
+ inboundBus,
328
+ outboundBus,
329
+ };
330
+ }
331
+ _scheduleJob(name, argument, options, waitable) {
332
+ // Get handler first, since this can error out if there's no handler for the job name.
333
+ const handler = this._getInternalDescription(name);
334
+ const optionsDeps = (options && options.dependencies) || [];
335
+ const dependencies = Array.isArray(optionsDeps) ? optionsDeps : [optionsDeps];
336
+ const inboundBus = new rxjs_1.Subject();
337
+ const outboundBus = rxjs_1.concat(
338
+ // Wait for dependencies, make sure to not report messages from dependencies. Subscribe to
339
+ // all dependencies at the same time so they run concurrently.
340
+ rxjs_1.merge(...dependencies.map(x => x.outboundBus)).pipe(operators_1.ignoreElements()),
341
+ // Wait for pause() to clear (if necessary).
342
+ waitable, rxjs_1.from(handler).pipe(operators_1.switchMap(handler => new rxjs_1.Observable((subscriber) => {
343
+ if (!handler) {
344
+ throw new exception_1.JobDoesNotExistException(name);
345
+ }
346
+ // Validate the argument.
347
+ return handler.argumentV.pipe(operators_1.switchMap(validate => validate(argument)), operators_1.switchMap(output => {
348
+ if (!output.success) {
349
+ throw new JobInboundMessageSchemaValidationError(output.errors);
350
+ }
351
+ const argument = output.data;
352
+ const description = handler.jobDescription;
353
+ subscriber.next({ kind: api_1.JobOutboundMessageKind.OnReady, description });
354
+ const context = {
355
+ description,
356
+ dependencies: [...dependencies],
357
+ inboundBus: inboundBus.asObservable(),
358
+ scheduler: this,
359
+ };
360
+ return handler(argument, context);
361
+ })).subscribe(subscriber);
362
+ }))));
363
+ return this._createJob(name, argument, handler, inboundBus, outboundBus, options);
364
+ }
365
+ }
366
+ exports.SimpleScheduler = SimpleScheduler;
367
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2ltcGxlLXNjaGVkdWxlci5qcyIsInNvdXJjZVJvb3QiOiIuLyIsInNvdXJjZXMiOlsicGFja2FnZXMvYW5ndWxhcl9kZXZraXQvY29yZS9zcmMvZXhwZXJpbWVudGFsL2pvYnMvc2ltcGxlLXNjaGVkdWxlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBOzs7Ozs7R0FNRztBQUNILCtCQVdjO0FBQ2QsOENBU3dCO0FBQ3hCLHFDQUErQztBQUMvQyx5Q0FBMEM7QUFDMUMsK0JBY2U7QUFDZiwyQ0FBdUQ7QUFHdkQsTUFBYSxzQ0FBdUMsU0FBUSxhQUFNLENBQUMseUJBQXlCO0lBQzFGLFlBQVksTUFBc0M7UUFDaEQsS0FBSyxDQUFDLE1BQU0sRUFBRSxrREFBa0QsQ0FBQyxDQUFDO0lBQ3BFLENBQUM7Q0FDRjtBQUpELHdGQUlDO0FBQ0QsTUFBYSw4QkFBK0IsU0FBUSxhQUFNLENBQUMseUJBQXlCO0lBQ2xGLFlBQVksTUFBc0M7UUFDaEQsS0FBSyxDQUFDLE1BQU0sRUFBRSx5Q0FBeUMsQ0FBQyxDQUFDO0lBQzNELENBQUM7Q0FDRjtBQUpELHdFQUlDO0FBWUQsU0FBUyxTQUFTO0lBQ2hCLCtGQUErRjtJQUMvRixpQkFBaUI7SUFDakIsT0FBTyxDQUFDLE1BQXFCLEVBQWlCLEVBQUU7UUFDOUMsSUFBSSxRQUFRLEdBQUcsQ0FBQyxDQUFDO1FBQ2pCLElBQUksT0FBbUIsQ0FBQztRQUN4QixJQUFJLFFBQVEsR0FBRyxLQUFLLENBQUM7UUFDckIsSUFBSSxVQUFVLEdBQUcsS0FBSyxDQUFDO1FBQ3ZCLElBQUksWUFBMEIsQ0FBQztRQUUvQixPQUFPLElBQUksaUJBQVUsQ0FBSSxVQUFVLENBQUMsRUFBRTtZQUNwQyxJQUFJLFFBQXNCLENBQUM7WUFDM0IsUUFBUSxFQUFFLENBQUM7WUFDWCxJQUFJLENBQUMsT0FBTyxFQUFFO2dCQUNaLE9BQU8sR0FBRyxJQUFJLGNBQU8sRUFBSyxDQUFDO2dCQUUzQixRQUFRLEdBQUcsT0FBTyxDQUFDLFNBQVMs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QUFRLENBQUMsUUFBUSxDQUFDLENBQUMsRUFDekMscUJBQVMsQ0FBQyxNQUFNLENBQUMsRUFBRTtnQkFDakIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUU7b0JBQ25CLE1BQU0sSUFBSSxzQ0FBc0MsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7aUJBQ2pFO2dCQUVELE1BQU0sUUFBUSxHQUFNLE1BQU0sQ0FBQyxJQUFTLENBQUM7Z0JBQ3JDLE1BQU0sV0FBVyxHQUFHLE9BQU8sQ0FBQyxjQUFjLENBQUM7Z0JBQzNDLFVBQVUsQ0FBQyxJQUFJLENBQUMsRUFBRSxJQUFJLEVBQUUsNEJBQXNCLENBQUMsT0FBTyxFQUFFLFdBQVcsRUFBRSxDQUFDLENBQUM7Z0JBRXZFLE1BQU0sT0FBTyxHQUFHO29CQUNkLFdBQVc7b0JBQ1gsWUFBWSxFQUFFLENBQUMsR0FBRyxZQUFZLENBQUM7b0JBQy9CLFVBQVUsRUFBRSxVQUFVLENBQUMsWUFBWSxFQUFFO29CQUNyQyxTQUFTLEVBQUUsSUFBa0U7aUJBQzlFLENBQUM7Z0JBRUYsT0FBTyxPQUFPLENBQUMsUUFBUSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQ3BDLENBQUMsQ0FBQyxDQUNILENBQUMsU0FBUyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQzFCLENBQUMsQ0FBQyxDQUFDLENBQ0osQ0FDRixDQUFDO1FBRUYsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxXQUFXLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDcEYsQ0FBQztDQUNGO0FBM2FELDBDQTJhQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCBHb29nbGUgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG4gKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vYW5ndWxhci5pby9saWNlbnNlXG4gKi9cbmltcG9ydCB7XG4gIEVNUFRZLFxuICBNb25vVHlwZU9wZXJhdG9yRnVuY3Rpb24sXG4gIE9ic2VydmFibGUsXG4gIE9ic2VydmVyLFxuICBTdWJqZWN0LFxuICBTdWJzY3JpcHRpb24sXG4gIGNvbmNhdCxcbiAgZnJvbSxcbiAgbWVyZ2UsXG4gIG9mLFxufSBmcm9tICdyeGpzJztcbmltcG9ydCB7XG4gIGNvbmNhdE1hcCxcbiAgZmlsdGVyLFxuICBmaXJzdCxcbiAgaWdub3JlRWxlbWVudHMsXG4gIG1hcCxcbiAgc2hhcmVSZXBsYXksXG4gIHN3aXRjaE1hcCxcbiAgdGFwLFxufSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBKc29uVmFsdWUsIHNjaGVtYSB9IGZyb20gJy4uLy4uL2pzb24nO1xuaW1wb3J0IHsgTnVsbExvZ2dlciB9IGZyb20gJy4uLy4uL2xvZ2dlcic7XG5pbXBvcnQge1xuICBKb2IsXG4gIEpvYkRlc2NyaXB0aW9uLFxuICBKb2JIYW5kbGVyLFxuICBKb2JJbmJvdW5kTWVzc2FnZSxcbiAgSm9iSW5ib3VuZE1lc3NhZ2VLaW5kLFxuICBKb2JOYW1lLFxuICBKb2JPdXRib3VuZE1lc3NhZ2UsXG4gIEpvYk91dGJvdW5kTWVzc2FnZUtpbmQsXG4gIEpvYk91dGJvdW5kTWVzc2FnZU91dHB1dCxcbiAgSm9iU3RhdGUsXG4gIFJlZ2lzdHJ5LFxuICBTY2hlZHVsZUpvYk9wdGlvbnMsXG4gIFNjaGVkdWxlcixcbn0gZnJvbSAnLi9hcGknO1xuaW1wb3J0IHsgSm9iRG9lc05vdEV4aXN0RXhjZXB0aW9uIH0gZnJvbSAnLi9leGNlcHRpb24nO1xuXG5cbmV4cG9ydCBjbGFzcyBKb2JJbmJvdW5kTWVzc2FnZVNjaGVtYVZhbGlkYXRpb25FcnJvciBleHRlbmRzIHNjaGVtYS5TY2hlbWFWYWxpZGF0aW9uRXhjZXB0aW9uIHtcbiAgY29uc3RydWN0b3IoZXJyb3JzPzogc2NoZW1hLlNjaGVtYVZhbGlkYXRvckVycm9yW10pIHtcbiAgICBzdXBlcihlcnJvcnMsICdKb2IgSW5ib3VuZCBNZXNzYWdlIGZhaWxlZCB0byB2YWxpZGF0ZS4gRXJyb3JzOiAnKTtcbiAgfVxufVxuZXhwb3J0IGNsYXNzIEpvYk91dHB1dFNjaGVtYVZhbGlkYXRpb25FcnJvciBleHRlbmRzIHNjaGVtYS5TY2hlbWFWYWxpZGF0aW9uRXhjZXB0aW9uIHtcbiAgY29uc3RydWN0b3IoZXJyb3JzPzogc2NoZW1hLlNjaGVtYVZhbGlkYXRvckVycm9yW10pIHtcbiAgICBzdXBlcihlcnJvcnMsICdKb2IgT3V0cHV0IGZhaWxlZCB0byB2YWxpZGF0ZS4gRXJyb3JzOiAnKTtcbiAgfVxufVxuXG5cbmludGVyZmFjZSBKb2JIYW5kbGVyV2l0aEV4dHJhIGV4dGVuZHMgSm9iSGFuZGxlcjxKc29uVmFsdWUsIEpzb25WYWx1ZSwgSnNvblZhbHVlPiB7XG4gIGpvYkRlc2NyaXB0aW9uOiBKb2JEZXNjcmlwdGlvbjtcblxuICBhcmd1bWVudFY6IE9ic2VydmFibGU8c2NoZW1hLlNjaGVtYVZhbGlkYXRvcj47XG4gIG91dHB1dFY6IE9ic2VydmFibGU8c2NoZW1hLlNjaGVtYVZhbGlkYXRvcj47XG4gIGlucHV0VjogT2JzZXJ2YWJsZTxzY2hlbWEuU2NoZW1hVmFsaWRhdG9yPjtcbn1cblxuXG5mdW5jdGlvbiBfam9iU2hhcmU8VD4oKTogTW9ub1R5cGVPcGVyYXRvckZ1bmN0aW9uPFQ+IHtcbiAgLy8gVGhpcyBpcyB0aGUgc2FtZSBjb2RlIGFzIGEgYHNoYXJlUmVwbGF5KClgIG9wZXJhdG9yLCBidXQgdXNlcyBhIGR1bWJlciBTdWJqZWN0IHJhdGhlciB0aGFuIGFcbiAgLy8gUmVwbGF5U3ViamVjdC5cbiAgcmV0dXJuIChzb3VyY2U6IE9ic2VydmFibGU8VD4pOiBPYnNlcnZhYmxlPFQ+ID0+IHtcbiAgICBsZXQgcmVmQ291bnQgPSAwO1xuICAgIGxldCBzdWJqZWN0OiBTdWJqZWN0PFQ+O1xuICAgIGxldCBoYXNFcnJvciA9IGZhbHNlO1xuICAgIGxldCBpc0NvbXBsZXRlID0gZmFsc2U7XG4gICAgbGV0IHN1YnNjcmlwdGlvbjogU3Vic2NyaXB0aW9uO1xuXG4gICAgcmV0dXJuIG5ldyBPYnNlcnZhYmxlPFQ+KHN1YnNjcmliZXIgPT4ge1xuICAgICAgbGV0IGlubmVyU3ViOiBTdWJzY3JpcHRpb247XG4gICAgICByZWZDb3VudCsrO1xuICAgICAgaWYgKCFzdWJqZWN0KSB7XG4gICAgICAgIHN1YmplY3QgPSBuZXcgU3ViamVjdDxUPigpO1xuXG4gICAgICAgIGlubmVyU3ViID0gc3ViamVjdC5zdWJzY3JpYmUoc3Vic2NyaWJlcik7XG4gICAgICAgIHN1YnNjcmlwdGlvbiA9IHNvdXJjZS5zdWJzY3JpYmUoe1xuICAgICAgICAgIG5leHQodmFsdWUpIHsgc3ViamVjdC5uZXh0KHZhbHVlKTsgfSxcbiAgICAgICAgICBlcnJvcihlcnIpIHtcbiAgICAgICAgICAgIGhhc0Vycm9yID0gdHJ1ZTtcbiAgICAgICAgICAgIHN1YmplY3QuZXJyb3IoZXJyKTtcbiAgICAgICAgICB9LFxuICAgICAgICAgIGNvbXBsZXRlKCkge1xuICAgICAgICAgICAgaXNDb21wbGV0ZSA9IHRydWU7XG4gICAgICAgICAgICBzdWJqZWN0LmNvbXBsZXRlKCk7XG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpbm5lclN1YiA9IHN1YmplY3Quc3Vic2NyaWJlKHN1YnNjcmliZXIpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gKCkgPT4ge1xuICAgICAgICByZWZDb3VudC0tO1xuICAgICAgICBpbm5lclN1Yi51bnN1YnNjcmliZSgpO1xuICAgICAgICBpZiAoc3Vic2NyaXB0aW9uICYmIHJlZkNvdW50ID09PSAwICYmIChpc0NvbXBsZXRlIHx8IGhhc0Vycm9yKSkge1xuICAgICAgICAgIHN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgIH0pO1xuICB9O1xufVxuXG5cbi8qKlxuICogU2ltcGxlIHNjaGVkdWxlci4gU2hvdWxkIGJlIHRoZSBiYXNlIG9mIGFsbCByZWdpc3RyaWVzIGFuZCBzY2hlZHVsZXJzLlxuICovXG5leHBvcnQgY2xhc3MgU2ltcGxlU2NoZWR1bGVyPFxuICBNaW5pbXVtQXJndW1lbnRUIGV4dGVuZHMgSnNvblZhbHVlID0gSnNvblZhbHVlLFxuICBNaW5pbXVtSW5wdXRUIGV4dGVuZHMgSnNvblZhbHVlID0gSnNvblZhbHVlLFxuICBNaW5pbXVtT3V0cHV0VCBleHRlbmRzIEpzb25WYWx1ZSA9IEpzb25WYWx1ZSxcbj4gaW1wbGVtZW50cyBTY2hlZHVsZXI8TWluaW11bUFyZ3VtZW50VCwgTWluaW11bUlucHV0VCwgTWluaW11bU91dHB1dFQ+IHtcbiAgcHJpdmF0ZSBfaW50ZXJuYWxKb2JEZXNjcmlwdGlvbk1hcCA9IG5ldyBNYXA8Sm9iTmFtZSwgSm9iSGFuZGxlcldpdGhFeHRyYT4oKTtcbiAgcHJpdmF0ZSBfcXVldWU6ICgoKSA9PiB2b2lkKVtdID0gW107XG4gIHByaXZhdGUgX3BhdXNlQ291bnRlciA9IDA7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJvdGVjdGVkIF9qb2JSZWdpc3RyeTogUmVnaXN0cnk8TWluaW11bUFyZ3VtZW50VCwgTWluaW11bUlucHV0VCwgTWluaW11bU91dHB1dFQ+LFxuICAgIHByb3RlY3RlZCBfc2NoZW1hUmVnaXN0cnk6IHNjaGVtYS5TY2hlbWFSZWdpc3RyeSA9IG5ldyBzY2hlbWEuQ29yZVNjaGVtYVJlZ2lzdHJ5KCksXG4gICkge31cblxuICBwcml2YXRlIF9nZXRJbnRlcm5hbERlc2NyaXB0aW9uKG5hbWU6IEpvYk5hbWUpOiBPYnNlcnZhYmxlPEpvYkhhbmRsZXJXaXRoRXh0cmEgfCBudWxsPiB7XG4gICAgY29uc3QgbWF5YmVIYW5kbGVyID0gdGhpcy5faW50ZXJuYWxKb2JEZXNjcmlwdGlvbk1hcC5nZXQobmFtZSk7XG4gICAgaWYgKG1heWJlSGFuZGxlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gb2YobWF5YmVIYW5kbGVyKTtcbiAgICB9XG5cbiAgICBjb25zdCBoYW5kbGVyID0gdGhpcy5fam9iUmVnaXN0cnkuZ2V0PE1pbmltdW1Bcmd1bWVudFQsIE1pbmltdW1JbnB1dFQsIE1pbmltdW1PdXRwdXRUPihuYW1lKTtcblxuICAgIHJldHVybiBoYW5kbGVyLnBpcGUoXG4gICAgICBzd2l0Y2hNYXAoaGFuZGxlciA9PiB7XG4gICAgICAgIGlmIChoYW5kbGVyID09PSBudWxsKSB7XG4gICAgICAgICAgcmV0dXJuIG9mKG51bGwpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZGVzY3JpcHRpb246IEpvYkRlc2NyaXB0aW9uID0ge1xuICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgYXJndW1lbnQ6IGhhbmRsZXIuam9iRGVzY3JpcHRpb24uYXJndW1lbnQgfHwgdHJ1ZSxcbiAgICAgICAgICBpbnB1dDogaGFuZGxlci5qb2JEZXNjcmlwdGlvbi5pbnB1dCB8fCB0cnVlLFxuICAgICAgICAgIG91dHB1dDogaGFuZGxlci5qb2JEZXNjcmlwdGlvbi5vdXRwdXQgfHwgdHJ1ZSxcbiAgICAgICAgICBjaGFubmVsczogaGFuZGxlci5qb2JEZXNjcmlwdGlvbi5jaGFubmVscyB8fCB7fSxcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCBoYW5kbGVyV2l0aEV4dHJhID0gT2JqZWN0LmFzc2lnbihoYW5kbGVyLmJpbmQodW5kZWZpbmVkKSwge1xuICAgICAgICAgIGpvYkRlc2NyaXB0aW9uOiBkZXNjcmlwdGlvbixcbiAgICAgICAgICBhcmd1bWVudFY6IHRoaXMuX3NjaGVtYVJlZ2lzdHJ5LmNvbXBpbGUoZGVzY3JpcHRpb24uYXJndW1lbnQpLnBpcGUoc2hhcmVSZXBsYXkoMSkpLFxuICAgICAgICAgIGlucHV0VjogdGhpcy5fc2NoZW1hUmVnaXN0cnkuY29tcGlsZShkZXNjcmlwdGlvbi5pbnB1dCkucGlwZShzaGFyZVJlcGxheSgxKSksXG4gICAgICAgICAgb3V0cHV0VjogdGhpcy5fc2NoZW1hUmVnaXN0cnkuY29tcGlsZShkZXNjcmlwdGlvbi5vdXRwdXQpLnBpcGUoc2hhcmVSZXBsYXkoMSkpLFxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5faW50ZXJuYWxKb2JEZXNjcmlwdGlvbk1hcC5zZXQobmFtZSwgaGFuZGxlcldpdGhFeHRyYSk7XG5cbiAgICAgICAgcmV0dXJuIG9mKGhhbmRsZXJXaXRoRXh0cmEpO1xuICAgICAgfSksXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgYSBqb2IgZGVzY3JpcHRpb24gZm9yIGEgbmFtZWQgam9iLlxuICAgKlxuICAgKiBAcGFyYW0gbmFtZSBUaGUgbmFtZSBvZiB0aGUgam9iLlxuICAgKiBAcmV0dXJucyBBIGRlc2NyaXB0aW9uLCBvciBudWxsIGlmIHRoZSBqb2IgaXMgbm90IHJlZ2lzdGVyZWQuXG4gICAqL1xuICBnZXREZXNjcmlwdGlvbihuYW1lOiBKb2JOYW1lKSB7XG4gICAgcmV0dXJuIGNvbmNhdChcbiAgICAgIHRoaXMuX2dldEludGVybmFsRGVzY3JpcHRpb24obmFtZSkucGlwZShtYXAoeCA9PiB4ICYmIHguam9iRGVzY3JpcHRpb24pKSxcbiAgICAgIG9mKG51bGwpLFxuICAgICkucGlwZShcbiAgICAgIGZpcnN0KCksXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRydWUgaWYgdGhlIGpvYiBuYW1lIGhhcyBiZWVuIHJlZ2lzdGVyZWQuXG4gICAqIEBwYXJhbSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBqb2IuXG4gICAqIEByZXR1cm5zIFRydWUgaWYgdGhlIGpvYiBleGlzdHMsIGZhbHNlIG90aGVyd2lzZS5cbiAgICovXG4gIGhhcyhuYW1lOiBKb2JOYW1lKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0RGVzY3JpcHRpb24obmFtZSkucGlwZShcbiAgICAgIG1hcCh4ID0+IHggIT09IG51bGwpLFxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogUGF1c2UgdGhlIHNjaGVkdWxlciwgdGVtcG9yYXJ5IHF1ZXVlaW5nIF9uZXdfIGpvYnMuIFJldHVybnMgYSByZXN1bWUgZnVuY3Rpb24gdGhhdCBzaG91bGQgYmVcbiAgICogdXNlZCB0byByZXN1bWUgZXhlY3V0aW9uLiBJZiBtdWx0aXBsZSBgcGF1c2UoKWAgd2VyZSBjYWxsZWQsIGFsbCB0aGVpciByZXN1bWUgZnVuY3Rpb25zIG11c3RcbiAgICogYmUgY2FsbGVkIGJlZm9yZSB0aGUgU2NoZWR1bGVyIGFjdHVhbGx5IHN0YXJ0cyBuZXcgam9icy4gQWRkaXRpb25hbCBjYWxscyB0byB0aGUgc2FtZSByZXN1bWVcbiAgICogZnVuY3Rpb24gd2lsbCBoYXZlIG5vIGVmZmVjdC5cbiAgICpcbiAgICogSm9icyBhbHJlYWR5IHJ1bm5pbmcgYXJlIE5PVCBwYXVzZWQuIFRoaXMgaXMgcGF1c2luZyB0aGUgc2NoZWR1bGVyIG9ubHkuXG4gICAqL1xuICBwYXVzZSgpIHtcbiAgICBsZXQgY2FsbGVkID0gZmFsc2U7XG4gICAgdGhpcy5fcGF1c2VDb3VudGVyKys7XG5cbiAgICByZXR1cm4gKCkgPT4ge1xuICAgICAgaWYgKCFjYWxsZWQpIHtcbiAgICAgICAgY2FsbGVkID0gdHJ1ZTtcbiAgICAgICAgaWYgKC0tdGhpcy5fcGF1c2VDb3VudGVyID09IDApIHtcbiAgICAgICAgICAvLyBSZXN1bWUgdGhlIHF1ZXVlLlxuICAgICAgICAgIGNvbnN0IHEgPSB0aGlzLl9xdWV1ZTtcbiAgICAgICAgICB0aGlzLl9xdWV1ZSA9IFtdO1xuICAgICAgICAgIHEuZm9yRWFjaChmbiA9PiBmbigpKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogU2NoZWR1bGUgYSBqb2IgdG8gYmUgcnVuLCB1c2luZyBpdHMgbmFtZS5cbiAgICogQHBhcmFtIG5hbWUgVGhlIG5hbWUgb2Ygam9iIHRvIGJlIHJ1bi5cbiAgICogQHBhcmFtIGFyZ3VtZW50IFRoZSBhcmd1bWVudCB0byBzZW5kIHRvIHRoZSBqb2Igd2hlbiBzdGFydGluZyBpdC5cbiAgICogQHBhcmFtIG9wdGlvbnMgU2NoZWR1bGluZyBvcHRpb25zLlxuICAgKiBAcmV0dXJucyBUaGUgSm9iIGJlaW5nIHJ1bi5cbiAgICovXG4gIHNjaGVkdWxlPEEgZXh0ZW5kcyBNaW5pbXVtQXJndW1lbnRULCBJIGV4dGVuZHMgTWluaW11bUlucHV0VCwgTyBleHRlbmRzIE1pbmltdW1PdXRwdXRUPihcbiAgICBuYW1lOiBKb2JOYW1lLFxuICAgIGFyZ3VtZW50OiBBLFxuICAgIG9wdGlvbnM/OiBTY2hlZHVsZUpvYk9wdGlvbnMsXG4gICk6IEpvYjxBLCBJLCBPPiB7XG4gICAgaWYgKHRoaXMuX3BhdXNlQ291bnRlciA+IDApIHtcbiAgICAgIGNvbnN0IHdhaXRhYmxlID0gbmV3IFN1YmplY3Q8bmV2ZXI+KCk7XG4gICAgICB0aGlzLl9xdWV1ZS5wdXNoKCgpID0+IHdhaXRhYmxlLmNvbXBsZXRlKCkpO1xuXG4gICAgICByZXR1cm4gdGhpcy5fc2NoZWR1bGVKb2I8QSwgSSwgTz4obmFtZSwgYXJndW1lbnQsIG9wdGlvbnMgfHwge30sIHdhaXRhYmxlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5fc2NoZWR1bGVKb2I8QSwgSSwgTz4obmFtZSwgYXJndW1lbnQsIG9wdGlvbnMgfHwge30sIEVNUFRZKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGaWx0ZXIgbWVzc2FnZXMuXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBwcml2YXRlIF9maWx0ZXJKb2JPdXRib3VuZE1lc3NhZ2VzPE8gZXh0ZW5kcyBNaW5pbXVtT3V0cHV0VD4oXG4gICAgbWVzc2FnZTogSm9iT3V0Ym91bmRNZXNzYWdlPE8+LFxuICAgIHN0YXRlOiBKb2JTdGF0ZSxcbiAgKSB7XG4gICAgc3dpdGNoIChtZXNzYWdlLmtpbmQpIHtcbiAgICAgIGNhc2UgSm9iT3V0Ym91bmRNZXNzYWdlS2luZC5PblJlYWR5OlxuICAgICAgICByZXR1cm4gc3RhdGUgPT0gSm9iU3RhdGUuUXVldWVkO1xuICAgICAgY2FzZSBKb2JPdXRib3VuZE1lc3NhZ2VLaW5kLlN0YXJ0OlxuICAgICAgICByZXR1cm4gc3RhdGUgPT0gSm9iU3RhdGUuUmVhZHk7XG5cbiAgICAgIGNhc2UgSm9iT3V0Ym91bmRNZXNzYWdlS2luZC5FbmQ6XG4gICAgICAgIHJldHVybiBzdGF0ZSA9PSBKb2JTdGF0ZS5TdGFydGVkIHx8IHN0YXRlID09IEpvYlN0YXRlLlJlYWR5O1xuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybiBhIG5ldyBzdGF0ZS4gVGhpcyBpcyBqdXN0IHRvIHNpbXBsaWZ5IHRoZSByZWFkaW5nIG9mIHRoZSBfY3JlYXRlSm9iIG1ldGhvZC5cbiAgICogQHByaXZhdGVcbiAgICovXG4gIHByaXZhdGUgX3VwZGF0ZVN0YXRlPE8gZXh0ZW5kcyBNaW5pbXVtT3V0cHV0VD4oXG4gICAgbWVzc2FnZTogSm9iT3V0Ym91bmRNZXNzYWdlPE8+LFxuICAgIHN0YXRlOiBKb2JTdGF0ZSxcbiAgKTogSm9iU3RhdGUge1xuICAgIHN3aXRjaCAobWVzc2FnZS5raW5kKSB7XG4gICAgICBjYXNlIEpvYk91dGJvdW5kTWVzc2FnZUtpbmQuT25SZWFkeTpcbiAgICAgICAgcmV0dXJuIEpvYlN0YXRlLlJlYWR5O1xuICAgICAgY2FzZSBKb2JPdXRib3VuZE1lc3NhZ2VLaW5kLlN0YXJ0OlxuICAgICAgICByZXR1cm4gSm9iU3RhdGUuU3RhcnRlZDtcbiAgICAgIGNhc2UgSm9iT3V0Ym91bmRNZXNzYWdlS2luZC5FbmQ6XG4gICAgICAgIHJldHVybiBKb2JTdGF0ZS5FbmRlZDtcbiAgICB9XG5cbiAgICByZXR1cm4gc3RhdGU7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIHRoZSBqb2IuXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBwcml2YXRlIF9jcmVhdGVKb2I8QSBleHRlbmRzIE1pbmltdW1Bcmd1bWVudFQsIEkgZXh0ZW5kcyBNaW5pbXVtSW5wdXRULCBPIGV4dGVuZHMgTWluaW11bU91dHB1dFQ+KFxuICAgIG5hbWU6IEpvYk5hbWUsXG4gICAgYXJndW1lbnQ6IEEsXG4gICAgaGFuZGxlcjogT2JzZXJ2YWJsZTxKb2JIYW5kbGVyV2l0aEV4dHJhIHwgbnVsbD4sXG4gICAgaW5ib3VuZEJ1czogT2JzZXJ2ZXI8Sm9iSW5ib3VuZE1lc3NhZ2U8ST4+LFxuICAgIG91dGJvdW5kQnVzOiBPYnNlcnZhYmxlPEpvYk91dGJvdW5kTWVzc2FnZTxPPj4sXG4gICAgb3B0aW9uczogU2NoZWR1bGVKb2JPcHRpb25zLFxuICApOiBKb2I8QSwgSSwgTz4ge1xuICAgIGNvbnN0IHNjaGVtYVJlZ2lzdHJ5ID0gdGhpcy5fc2NoZW1hUmVnaXN0cnk7XG5cbiAgICBjb25zdCBjaGFubmVsc1N1YmplY3QgPSBuZXcgTWFwPHN0cmluZywgU3ViamVjdDxKc29uVmFsdWU+PigpO1xuICAgIGNvbnN0IGNoYW5uZWxzID0gbmV3IE1hcDxzdHJpbmcsIE9ic2VydmFibGU8SnNvblZhbHVlPj4oKTtcblxuICAgIGxldCBzdGF0ZSA9IEpvYlN0YXRlLlF1ZXVlZDtcbiAgICBsZXQgcGluZ0lkID0gMDtcblxuICAgIGNvbnN0IGxvZ2dlciA9IG9wdGlvbnMubG9nZ2VyID8gb3B0aW9ucy5sb2dnZXIuY3JlYXRlQ2hpbGQoJ2pvYicpIDogbmV3IE51bGxMb2dnZXIoKTtcblxuICAgIC8vIENyZWF0ZSB0aGUgaW5wdXQgY2hhbm5lbCBieSBoYXZpbmcgYSBmaWx0ZXIuXG4gICAgY29uc3QgaW5wdXQgPSBuZXcgU3ViamVjdDxKc29uVmFsdWU+KCk7XG4gICAgaW5wdXQucGlwZShcbiAgICAgIHN3aXRjaE1hcChtZXNzYWdlID0+IGhhbmRsZXIucGlwZShcbiAgICAgICAgc3dpdGNoTWFwKGhhbmRsZXIgPT4ge1xuICAgICAgICAgIGlmIChoYW5kbGVyID09PSBudWxsKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgSm9iRG9lc05vdEV4aXN0RXhjZXB0aW9uKG5hbWUpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gaGFuZGxlci5pbnB1dFYucGlwZShcbiAgICAgICAgICAgICAgc3dpdGNoTWFwKHZhbGlkYXRlID0+IHZhbGlkYXRlKG1lc3NhZ2UpKSxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICB9KSxcbiAgICAgICkpLFxuICAgICAgZmlsdGVyKHJlc3VsdCA9PiByZXN1bHQuc3VjY2VzcyksXG4gICAgICBtYXAocmVzdWx0ID0+IHJlc3VsdC5kYXRhIGFzIEkpLFxuICAgICkuc3Vic2NyaWJlKFxuICAgICAgdmFsdWUgPT4gaW5ib3VuZEJ1cy5uZXh0KHsga2luZDogSm9iSW5ib3VuZE1lc3NhZ2VLaW5kLklucHV0LCB2YWx1ZSB9KSxcbiAgICApO1xuXG4gICAgb3V0Ym91bmRCdXMgPSBjb25jYXQoXG4gICAgICBvdXRib3VuZEJ1cyxcbiAgICAgIC8vIEFkZCBhbiBFbmQgbWVzc2FnZSBhdCBjb21wbGV0aW9uLiBUaGlzIHdpbGwgYmUgZmlsdGVyZWQgb3V0IGlmIHRoZSBqb2IgYWN0dWFsbHkgc2VuZCBhblxuICAgICAgLy8gRW5kLlxuICAgICAgaGFuZGxlci5waXBlKHN3aXRjaE1hcChoYW5kbGVyID0+IHtcbiAgICAgICAgaWYgKGhhbmRsZXIpIHtcbiAgICAgICAgICByZXR1cm4gb2Y8Sm9iT3V0Ym91bmRNZXNzYWdlPE8+Pih7XG4gICAgICAgICAgICBraW5kOiBKb2JPdXRib3VuZE1lc3NhZ2VLaW5kLkVuZCwgZGVzY3JpcHRpb246IGhhbmRsZXIuam9iRGVzY3JpcHRpb24sXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuIEVNUFRZIGFzIE9ic2VydmFibGU8Sm9iT3V0Ym91bmRNZXNzYWdlPE8+PjtcbiAgICAgICAgfVxuICAgICAgfSkpLFxuICAgICkucGlwZShcbiAgICAgIGZpbHRlcihtZXNzYWdlID0+IHRoaXMuX2ZpbHRlckpvYk91dGJvdW5kTWVzc2FnZXMobWVzc2FnZSwgc3RhdGUpKSxcbiAgICAgIC8vIFVwZGF0ZSBpbnRlcm5hbCBsb2dpYyBhbmQgSm9iPD4gbWVtYmVycy5cbiAgICAgIHRhcChtZXNzYWdlID0+IHtcbiAgICAgICAgLy8gVXBkYXRlIHRoZSBzdGF0ZS5cbiAgICAgICAgc3RhdGUgPSB0aGlzLl91cGRhdGVTdGF0ZShtZXNzYWdlLCBzdGF0ZSk7XG5cbiAgICAgICAgc3dpdGNoIChtZXNzYWdlLmtpbmQpIHtcbiAgICAgICAgICBjYXNlIEpvYk91dGJvdW5kTWVzc2FnZUtpbmQuTG9nOlxuICAgICAgICAgICAgbG9nZ2VyLm5leHQobWVzc2FnZS5lbnRyeSk7XG4gICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgIGNhc2UgSm9iT3V0Ym91bmRNZXNzYWdlS2luZC5DaGFubmVsQ3JlYXRlOiB7XG4gICAgICAgICAgICBjb25zdCBtYXliZVN1YmplY3QgPSBjaGFubmVsc1N1YmplY3QuZ2V0KG1lc3NhZ2UubmFtZSk7XG4gICAgICAgICAgICAvLyBJZiBpdCBkb2Vzbid0IGV4aXN0IG9yIGl0J3MgY2xvc2VkIG9uIHRoZSBvdGhlciBlbmQuXG4gICAgICAgICAgICBpZiAoIW1heWJlU3ViamVjdCkge1xuICAgICAgICAgICAgICBjb25zdCBzID0gbmV3IFN1YmplY3Q8SnNvblZhbHVlPigpO1xuICAgICAgICAgICAgICBjaGFubmVsc1N1YmplY3Quc2V0KG1lc3NhZ2UubmFtZSwgcyk7XG4gICAgICAgICAgICAgIGNoYW5uZWxzLnNldChtZXNzYWdlLm5hbWUsIHMuYXNPYnNlcnZhYmxlKCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY2FzZSBKb2JPdXRib3VuZE1lc3NhZ2VLaW5kLkNoYW5uZWxNZXNzYWdlOiB7XG4gICAgICAgICAgICBjb25zdCBtYXliZVN1YmplY3QgPSBjaGFubmVsc1N1YmplY3QuZ2V0KG1lc3NhZ2UubmFtZSk7XG4gICAgICAgICAgICBpZiAobWF5YmVTdWJqZWN0KSB7XG4gICAgICAgICAgICAgIG1heWJlU3ViamVjdC5uZXh0KG1lc3NhZ2UubWVzc2FnZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjYXNlIEpvYk91dGJvdW5kTWVzc2FnZUtpbmQuQ2hhbm5lbENvbXBsZXRlOiB7XG4gICAgICAgICAgICBjb25zdCBtYXliZVN1YmplY3QgPSBjaGFubmVsc1N1YmplY3QuZ2V0KG1lc3NhZ2UubmFtZSk7XG4gICAgICAgICAgICBpZiAobWF5YmVTdWJqZWN0KSB7XG4gICAgICAgICAgICAgIG1heWJlU3ViamVjdC5jb21wbGV0ZSgpO1xuICAgICAgICAgICAgICBjaGFubmVsc1N1YmplY3QuZGVsZXRlKG1lc3NhZ2UubmFtZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjYXNlIEpvYk91dGJvdW5kTWVzc2FnZUtpbmQuQ2hhbm5lbEVycm9yOiB7XG4gICAgICAgICAgICBjb25zdCBtYXliZVN1YmplY3QgPSBjaGFubmVsc1N1YmplY3QuZ2V0KG1lc3NhZ2UubmFtZSk7XG4gICAgICAgICAgICBpZiAobWF5YmVTdWJqZWN0KSB7XG4gICAgICAgICAgICAgIG1heWJlU3ViamVjdC5lcnJvcihtZXNzYWdlLmVycm9yKTtcbiAgICAgICAgICAgICAgY2hhbm5lbHNTdWJqZWN0LmRlbGV0ZShtZXNzYWdlLm5hbWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9LCAoKSA9PiB7XG4gICAgICAgIHN0YXRlID0gSm9iU3RhdGUuRXJyb3JlZDtcbiAgICAgIH0pLFxuXG4gICAgICAvLyBEbyBvdXRwdXQgdmFsaWRhdGlvbiAobWlnaHQgaW5jbHVkZSBkZWZhdWx0IHZhbHVlcyBzbyB0aGlzIG1pZ2h0IGhhdmUgc2lkZVxuICAgICAgLy8gZWZmZWN0cykuIFdlIGtlZXAgYWxsIG1lc3NhZ2VzIGluIG9yZGVyLlxuICAgICAgY29uY2F0TWFwKG1lc3NhZ2UgPT4ge1xuICAgICAgICBpZiAobWVzc2FnZS5raW5kICE9PSBKb2JPdXRib3VuZE1lc3NhZ2VLaW5kLk91dHB1dCkge1xuICAgICAgICAgIHJldHVybiBvZihtZXNzYWdlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBoYW5kbGVyLnBpcGUoXG4gICAgICAgICAgc3dpdGNoTWFwKGhhbmRsZXIgPT4ge1xuICAgICAgICAgICAgaWYgKGhhbmRsZXIgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IEpvYkRvZXNOb3RFeGlzdEV4Y2VwdGlvbihuYW1lKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHJldHVybiBoYW5kbGVyLm91dHB1dFYucGlwZShcbiAgICAgICAgICAgICAgICBzd2l0Y2hNYXAodmFsaWRhdGUgPT4gdmFsaWRhdGUobWVzc2FnZS52YWx1ZSkpLFxuICAgICAgICAgICAgICAgIHN3aXRjaE1hcChvdXRwdXQgPT4ge1xuICAgICAgICAgICAgICAgICAgaWYgKCFvdXRwdXQuc3VjY2Vzcykge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSm9iT3V0cHV0U2NoZW1hVmFsaWRhdGlvbkVycm9yKG91dHB1dC5lcnJvcnMpO1xuICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICByZXR1cm4gb2Yoe1xuICAgICAgICAgICAgICAgICAgICAuLi5tZXNzYWdlLFxuICAgICAgICAgICAgICAgICAgICBvdXRwdXQ6IG91dHB1dC5kYXRhIGFzIE8sXG4gICAgICAgICAgICAgICAgICB9IGFzIEpvYk91dGJvdW5kTWVzc2FnZU91dHB1dDxPPik7XG4gICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSksXG4gICAgICAgICkgYXMgT2JzZXJ2YWJsZTxKb2JPdXRib3VuZE1lc3NhZ2U8Tz4+O1xuICAgICAgfSksXG4gICAgICBfam9iU2hhcmUoKSxcbiAgICApO1xuXG4gICAgY29uc3Qgb3V0cHV0ID0gb3V0Ym91bmRCdXMucGlwZShcbiAgICAgIGZpbHRlcih4ID0+IHgua2luZCA9PSBKb2JPdXRib3VuZE1lc3NhZ2VLaW5kLk91dHB1dCksXG4gICAgICBtYXAoKHg6IEpvYk91dGJvdW5kTWVzc2FnZU91dHB1dDxPPikgPT4geC52YWx1ZSksXG4gICAgICBzaGFyZVJlcGxheSgxKSxcbiAgICApO1xuXG4gICAgLy8gUmV0dXJuIHRoZSBKb2IuXG4gICAgcmV0dXJuIHtcbiAgICAgIGdldCBzdGF0ZSgpIHsgcmV0dXJuIHN0YXRlOyB9LFxuICAgICAgYXJndW1lbnQsXG4gICAgICBkZXNjcmlwdGlvbjogaGFuZGxlci5waXBlKFxuICAgICAgICBzd2l0Y2hNYXAoaGFuZGxlciA9PiB7XG4gICAgICAgICAgaWYgKGhhbmRsZXIgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBKb2JEb2VzTm90RXhpc3RFeGNlcHRpb24obmFtZSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBvZihoYW5kbGVyLmpvYkRlc2NyaXB0aW9uKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pLFxuICAgICAgKSxcbiAgICAgIG91dHB1dCxcbiAgICAgIGdldENoYW5uZWw8VCBleHRlbmRzIEpzb25WYWx1ZT4oXG4gICAgICAgIG5hbWU6IEpvYk5hbWUsXG4gICAgICAgIHNjaGVtYTogc2NoZW1hLkpzb25TY2hlbWEgPSB0cnVlLFxuICAgICAgKTogT2JzZXJ2YWJsZTxUPiB7XG4gICAgICAgIGxldCBtYXliZU9ic2VydmFibGUgPSBjaGFubmVscy5nZXQobmFtZSk7XG4gICAgICAgIGlmICghbWF5YmVPYnNlcnZhYmxlKSB7XG4gICAgICAgICAgY29uc3QgcyA9IG5ldyBTdWJqZWN0PFQ+KCk7XG4gICAgICAgICAgY2hhbm5lbHNTdWJqZWN0LnNldChuYW1lLCBzKTtcbiAgICAgICAgICBjaGFubmVscy5zZXQobmFtZSwgcy5hc09ic2VydmFibGUoKSk7XG5cbiAgICAgICAgICBtYXliZU9ic2VydmFibGUgPSBzLmFzT2JzZXJ2YWJsZSgpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG1heWJlT2JzZXJ2YWJsZS5waXBlKFxuICAgICAgICAgIC8vIEtlZXAgdGhlIG9yZGVyIG9mIG1lc3NhZ2VzLlxuICAgICAgICAgIGNvbmNhdE1hcChcbiAgICAgICAgICAgIG1lc3NhZ2UgPT4ge1xuICAgICAgICAgICAgICByZXR1cm4gc2NoZW1hUmVnaXN0cnkuY29tcGlsZShzY2hlbWEpLnBpcGUoXG4gICAgICAgICAgICAgICAgc3dpdGNoTWFwKHZhbGlkYXRlID0+IHZhbGlkYXRlKG1lc3NhZ2UpKSxcbiAgICAgICAgICAgICAgICBmaWx0ZXIoeCA9PiB4LnN1Y2Nlc3MpLFxuICAgICAgICAgICAgICAgIG1hcCh4ID0+IHguZGF0YSBhcyBUKSxcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgKSxcbiAgICAgICAgKTtcbiAgICAgIH0sXG4gICAgICBwaW5nKCkge1xuICAgICAgICBjb25zdCBpZCA9IHBpbmdJZCsrO1xuICAgICAgICBpbmJvdW5kQnVzLm5leHQoeyBraW5kOiBKb2JJbmJvdW5kTWVzc2FnZUtpbmQuUGluZywgaWQgfSk7XG5cbiAgICAgICAgcmV0dXJuIG91dGJvdW5kQnVzLnBpcGUoXG4gICAgICAgICAgZmlsdGVyKHggPT4geC5raW5kID09PSBKb2JPdXRib3VuZE1lc3NhZ2VLaW5kLlBvbmcgJiYgeC5pZCA9PSBpZCksXG4gICAgICAgICAgZmlyc3QoKSxcbiAgICAgICAgICBpZ25vcmVFbGVtZW50cygpLFxuICAgICAgICApO1xuICAgICAgfSxcbiAgICAgIHN0b3AoKSB7XG4gICAgICAgIGluYm91bmRCdXMubmV4dCh7IGtpbmQ6IEpvYkluYm91bmRNZXNzYWdlS2luZC5TdG9wIH0pO1xuICAgICAgfSxcbiAgICAgIGlucHV0LFxuICAgICAgaW5ib3VuZEJ1cyxcbiAgICAgIG91dGJvdW5kQnVzLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgX3NjaGVkdWxlSm9iPFxuICAgIEEgZXh0ZW5kcyBNaW5pbXVtQXJndW1lbnRULFxuICAgIEkgZXh0ZW5kcyBNaW5pbXVtSW5wdXRULFxuICAgIE8gZXh0ZW5kcyBNaW5pbXVtT3V0cHV0VCxcbiAgPihcbiAgICBuYW1lOiBKb2JOYW1lLFxuICAgIGFyZ3VtZW50OiBBLFxuICAgIG9wdGlvbnM6IFNjaGVkdWxlSm9iT3B0aW9ucyxcbiAgICB3YWl0YWJsZTogT2JzZXJ2YWJsZTxuZXZlcj4sXG4gICk6IEpvYjxBLCBJLCBPPiB7XG4gICAgLy8gR2V0IGhhbmRsZXIgZmlyc3QsIHNpbmNlIHRoaXMgY2FuIGVycm9yIG91dCBpZiB0aGVyZSdzIG5vIGhhbmRsZXIgZm9yIHRoZSBqb2IgbmFtZS5cbiAgICBjb25zdCBoYW5kbGVyID0gdGhpcy5fZ2V0SW50ZXJuYWxEZXNjcmlwdGlvbihuYW1lKTtcblxuICAgIGNvbnN0IG9wdGlvbnNEZXBzID0gKG9wdGlvbnMgJiYgb3B0aW9ucy5kZXBlbmRlbmNpZXMpIHx8IFtdO1xuICAgIGNvbnN0IGRlcGVuZGVuY2llcyA9IEFycmF5LmlzQXJyYXkob3B0aW9uc0RlcHMpID8gb3B0aW9uc0RlcHMgOiBbb3B0aW9uc0RlcHNdO1xuXG4gICAgY29uc3QgaW5ib3VuZEJ1cyA9IG5ldyBTdWJqZWN0PEpvYkluYm91bmRNZXNzYWdlPEk+PigpO1xuICAgIGNvbnN0IG91dGJvdW5kQnVzID0gY29uY2F0KFxuICAgICAgLy8gV2FpdCBmb3IgZGVwZW5kZW5jaWVzLCBtYWtlIHN1cmUgdG8gbm90IHJlcG9ydCBtZXNzYWdlcyBmcm9tIGRlcGVuZGVuY2llcy4gU3Vic2NyaWJlIHRvXG4gICAgICAvLyBhbGwgZGVwZW5kZW5jaWVzIGF0IHRoZSBzYW1lIHRpbWUgc28gdGhleSBydW4gY29uY3VycmVudGx5LlxuICAgICAgbWVyZ2UoLi4uZGVwZW5kZW5jaWVzLm1hcCh4ID0+IHgub3V0Ym91bmRCdXMpKS5waXBlKGlnbm9yZUVsZW1lbnRzKCkpLFxuXG4gICAgICAvLyBXYWl0IGZvciBwYXVzZSgpIHRvIGNsZWFyIChpZiBuZWNlc3NhcnkpLlxuICAgICAgd2FpdGFibGUsXG5cbiAgICAgIGZyb20oaGFuZGxlcikucGlwZShcbiAgICAgICAgc3dpdGNoTWFwKGhhbmRsZXIgPT4gbmV3IE9ic2VydmFibGUoKHN1YnNjcmliZXI6IE9ic2VydmVyPEpvYk91dGJvdW5kTWVzc2FnZTxPPj4pID0+IHtcbiAgICAgICAgICBpZiAoIWhhbmRsZXIpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBKb2JEb2VzTm90RXhpc3RFeGNlcHRpb24obmFtZSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gVmFsaWRhdGUgdGhlIGFyZ3VtZW50LlxuICAgICAgICAgIHJldHVybiBoYW5kbGVyLmFyZ3VtZW50Vi5waXBlKFxuICAgICAgICAgICAgc3dpdGNoTWFwKHZhbGlkYXRlID0+IHZhbGlkYXRlKGFyZ3VtZW50KSksXG4gICAgICAgICAgICBzd2l0Y2hNYXAob3V0cHV0ID0+IHtcbiAgICAgICAgICAgICAgaWYgKCFvdXRwdXQuc3VjY2Vzcykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBKb2JJbmJvdW5kTWVzc2FnZVNjaGVtYVZhbGlkYXRpb25FcnJvcihvdXRwdXQuZXJyb3JzKTtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIGNvbnN0IGFyZ3VtZW50OiBBID0gb3V0cHV0LmRhdGEgYXMgQTtcbiAgICAgICAgICAgICAgY29uc3QgZGVzY3JpcHRpb24gPSBoYW5kbGVyLmpvYkRlc2NyaXB0aW9uO1xuICAgICAgICAgICAgICBzdWJzY3JpYmVyLm5leHQoeyBraW5kOiBKb2JPdXRib3VuZE1lc3NhZ2VLaW5kLk9uUmVhZHksIGRlc2NyaXB0aW9uIH0pO1xuXG4gICAgICAgICAgICAgIGNvbnN0IGNvbnRleHQgPSB7XG4gICAgICAgICAgICAgICAgZGVzY3JpcHRpb24sXG4gICAgICAgICAgICAgICAgZGVwZW5kZW5jaWVzOiBbLi4uZGVwZW5kZW5jaWVzXSxcbiAgICAgICAgICAgICAgICBpbmJvdW5kQnVzOiBpbmJvdW5kQnVzLmFzT2JzZXJ2YWJsZSgpLFxuICAgICAgICAgICAgICAgIHNjaGVkdWxlcjogdGhpcyBhcyBTY2hlZHVsZXI8TWluaW11bUFyZ3VtZW50VCwgTWluaW11bUlucHV0VCwgTWluaW11bU91dHB1dFQ+LFxuICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgIHJldHVybiBoYW5kbGVyKGFyZ3VtZW50LCBjb250ZXh0KTtcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgICkuc3Vic2NyaWJlKHN1YnNjcmliZXIpO1xuICAgICAgICB9KSksXG4gICAgICApLFxuICAgICk7XG5cbiAgICByZXR1cm4gdGhpcy5fY3JlYXRlSm9iKG5hbWUsIGFyZ3VtZW50LCBoYW5kbGVyLCBpbmJvdW5kQnVzLCBvdXRib3VuZEJ1cywgb3B0aW9ucyk7XG4gIH1cbn1cbiJdfQ==