@angular-devkit/core
Version:
Angular DevKit - Core Utility Library
133 lines • 15.5 kB
JavaScript
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.writeWorkspace = exports.readWorkspace = exports._test_removeWorkspaceFile = exports._test_addWorkspaceFile = exports.WorkspaceFormat = void 0;
const virtual_fs_1 = require("../virtual-fs");
const reader_1 = require("./json/reader");
const writer_1 = require("./json/writer");
const formatLookup = new WeakMap();
/**
* Supported workspace formats
*/
var WorkspaceFormat;
(function (WorkspaceFormat) {
WorkspaceFormat[WorkspaceFormat["JSON"] = 0] = "JSON";
})(WorkspaceFormat || (exports.WorkspaceFormat = WorkspaceFormat = {}));
/**
* @private
*/
function _test_addWorkspaceFile(name, format) {
workspaceFiles[name] = format;
}
exports._test_addWorkspaceFile = _test_addWorkspaceFile;
/**
* @private
*/
function _test_removeWorkspaceFile(name) {
delete workspaceFiles[name];
}
exports._test_removeWorkspaceFile = _test_removeWorkspaceFile;
// NOTE: future additions could also perform content analysis to determine format/version
const workspaceFiles = {
'angular.json': WorkspaceFormat.JSON,
'.angular.json': WorkspaceFormat.JSON,
};
/**
* Reads and constructs a `WorkspaceDefinition`. If the function is provided with a path to a
* directory instead of a file, a search of the directory's files will commence to attempt to
* locate a known workspace file. Currently the following are considered known workspace files:
* - `angular.json`
* - `.angular.json`
*
* @param path The path to either a workspace file or a directory containing a workspace file.
* @param host The `WorkspaceHost` to use to access the file and directory data.
* @param format An optional `WorkspaceFormat` value. Used if the path specifies a non-standard
* file name that would prevent automatically discovering the format.
*
*
* @return An `Promise` of the read result object with the `WorkspaceDefinition` contained within
* the `workspace` property.
*/
async function readWorkspace(path, host, format) {
if (await host.isDirectory(path)) {
// TODO: Warn if multiple found (requires diagnostics support)
const directory = (0, virtual_fs_1.normalize)(path);
let found = false;
for (const [name, nameFormat] of Object.entries(workspaceFiles)) {
if (format !== undefined && format !== nameFormat) {
continue;
}
const potential = (0, virtual_fs_1.getSystemPath)((0, virtual_fs_1.join)(directory, name));
if (await host.isFile(potential)) {
path = potential;
format = nameFormat;
found = true;
break;
}
}
if (!found) {
throw new Error('Unable to locate a workspace file for workspace path. Are you missing an `angular.json`' +
' or `.angular.json` file?');
}
}
else if (format === undefined) {
const filename = (0, virtual_fs_1.basename)((0, virtual_fs_1.normalize)(path));
if (filename in workspaceFiles) {
format = workspaceFiles[filename];
}
}
if (format === undefined) {
throw new Error('Unable to determine format for workspace path.');
}
let workspace;
switch (format) {
case WorkspaceFormat.JSON:
workspace = await (0, reader_1.readJsonWorkspace)(path, host);
break;
default:
throw new Error('Unsupported workspace format.');
}
formatLookup.set(workspace, WorkspaceFormat.JSON);
return { workspace };
}
exports.readWorkspace = readWorkspace;
/**
* Writes a `WorkspaceDefinition` to the underlying storage via the provided `WorkspaceHost`.
* If the `WorkspaceDefinition` was created via the `readWorkspace` function, metadata will be
* used to determine the path and format of the Workspace. In all other cases, the `path` and
* `format` options must be specified as they would be otherwise unknown.
*
* @param workspace The `WorkspaceDefinition` that will be written.
* @param host The `WorkspaceHost` to use to access/write the file and directory data.
* @param path The path to a file location for the output. Required if `readWorkspace` was not
* used to create the `WorkspaceDefinition`. Optional otherwise; will override the
* `WorkspaceDefinition` metadata if provided.
* @param format The `WorkspaceFormat` to use for output. Required if `readWorkspace` was not
* used to create the `WorkspaceDefinition`. Optional otherwise; will override the
* `WorkspaceDefinition` metadata if provided.
*
*
* @return An `Promise` of type `void`.
*/
async function writeWorkspace(workspace, host, path, format) {
if (format === undefined) {
format = formatLookup.get(workspace);
if (format === undefined) {
throw new Error('A format is required for custom workspace objects.');
}
}
switch (format) {
case WorkspaceFormat.JSON:
return (0, writer_1.writeJsonWorkspace)(workspace, host, path);
default:
throw new Error('Unsupported workspace format.');
}
}
exports.writeWorkspace = writeWorkspace;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29yZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL2FuZ3VsYXJfZGV2a2l0L2NvcmUvc3JjL3dvcmtzcGFjZS9jb3JlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7O0dBTUc7OztBQUVILDhDQUF5RTtBQUd6RSwwQ0FBa0Q7QUFDbEQsMENBQW1EO0FBRW5ELE1BQU0sWUFBWSxHQUFHLElBQUksT0FBTyxFQUF3QyxDQUFDO0FBRXpFOztHQUVHO0FBQ0gsSUFBWSxlQUVYO0FBRkQsV0FBWSxlQUFlO0lBQ3pCLHFEQUFJLENBQUE7QUFDTixDQUFDLEVBRlcsZUFBZSwrQkFBZixlQUFlLFFBRTFCO0FBRUQ7O0dBRUc7QUFDSCxTQUFnQixzQkFBc0IsQ0FBQyxJQUFZLEVBQUUsTUFBdUI7SUFDMUUsY0FBYyxDQUFDLElBQUksQ0FBQyxHQUFHLE1BQU0sQ0FBQztBQUNoQyxDQUFDO0FBRkQsd0RBRUM7QUFFRDs7R0FFRztBQUNILFNBQWdCLHlCQUF5QixDQUFDLElBQVk7SUFDcEQsT0FBTyxjQUFjLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDOUIsQ0FBQztBQUZELDhEQUVDO0FBRUQseUZBQXlGO0FBQ3pGLE1BQU0sY0FBYyxHQUFvQztJQUN0RCxjQUFjLEVBQUUsZUFBZSxDQUFDLElBQUk7SUFDcEMsZUFBZSxFQUFFLGVBQWUsQ0FBQyxJQUFJO0NBQ3RDLENBQUM7QUFFRjs7Ozs7Ozs7Ozs7Ozs7O0dBZUc7QUFDSSxLQUFLLFVBQVUsYUFBYSxDQUNqQyxJQUFZLEVBQ1osSUFBbUIsRUFDbkIsTUFBd0I7SUFHeEIsSUFBSSxNQUFNLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLEVBQUU7UUFDaEMsOERBQThEO1FBQzlELE1BQU0sU0FBUyxHQUFHLElBQUEsc0JBQVMsRUFBQyxJQUFJLENBQUMsQ0FBQztRQUNsQyxJQUFJLEtBQUssR0FBRyxLQUFLLENBQUM7UUFDbEIsS0FBSyxNQUFNLENBQUMsSUFBSSxFQUFFLFVBQVUsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDLEVBQUU7WUFDL0QsSUFBSSxNQUFNLEtBQUssU0FBUyxJQUFJLE1BQU0sS0FBSyxVQUFVLEVBQUU7Z0JBQ2pELFNBQVM7YUFDVjtZQUVELE1BQU0sU0FBUyxHQUFHLElBQUEsMEJBQWEsRUFBQyxJQUFBLGlCQUFJLEVBQUMsU0FBUyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUM7WUFDdkQsSUFBSSxNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLEVBQUU7Z0JBQ2hDLElBQUksR0FBRyxTQUFTLENBQUM7Z0JBQ2pCLE1BQU0sR0FBRyxVQUFVLENBQUM7Z0JBQ3BCLEtBQUssR0FBRyxJQUFJLENBQUM7Z0JBQ2IsTUFBTTthQUNQO1NBQ0Y7UUFDRCxJQUFJLENBQUMsS0FBSyxFQUFFO1lBQ1YsTUFBTSxJQUFJLEtBQUssQ0FDYix5RkFBeUY7Z0JBQ3ZGLDJCQUEyQixDQUM5QixDQUFDO1NBQ0g7S0FDRjtTQUFNLElBQUksTUFBTSxLQUFLLFNBQVMsRUFBRTtRQUMvQixNQUFNLFFBQVEsR0FBRyxJQUFBLHFCQUFRLEVBQUMsSUFBQSxzQkFBUyxFQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDM0MsSUFBSSxRQUFRLElBQUksY0FBYyxFQUFFO1lBQzlCLE1BQU0sR0FBRyxjQUFjLENBQUMsUUFBUSxDQUFDLENBQUM7U0FDbkM7S0FDRjtJQUVELElBQUksTUFBTSxLQUFLLFNBQVMsRUFBRTtRQUN4QixNQUFNLElBQUksS0FBSyxDQUFDLGdEQUFnRCxDQUFDLENBQUM7S0FDbkU7SUFFRCxJQUFJLFNBQVMsQ0FBQztJQUNkLFFBQVEsTUFBTSxFQUFFO1FBQ2QsS0FBSyxlQUFlLENBQUMsSUFBSTtZQUN2QixTQUFTLEdBQUcsTUFBTSxJQUFBLDBCQUFpQixFQUFDLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQztZQUNoRCxNQUFNO1FBQ1I7WUFDRSxNQUFNLElBQUksS0FBSyxDQUFDLCtCQUErQixDQUFDLENBQUM7S0FDcEQ7SUFFRCxZQUFZLENBQUMsR0FBRyxDQUFDLFNBQVMsRUFBRSxlQUFlLENBQUMsSUFBSSxDQUFDLENBQUM7SUFFbEQsT0FBTyxFQUFFLFNBQVMsRUFBRSxDQUFDO0FBQ3ZCLENBQUM7QUFwREQsc0NBb0RDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBaUJHO0FBQ0ksS0FBSyxVQUFVLGNBQWMsQ0FDbEMsU0FBOEIsRUFDOUIsSUFBbUIsRUFDbkIsSUFBYSxFQUNiLE1BQXdCO0lBRXhCLElBQUksTUFBTSxLQUFLLFNBQVMsRUFBRTtRQUN4QixNQUFNLEdBQUcsWUFBWSxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUNyQyxJQUFJLE1BQU0sS0FBSyxTQUFTLEVBQUU7WUFDeEIsTUFBTSxJQUFJLEtBQUssQ0FBQyxvREFBb0QsQ0FBQyxDQUFDO1NBQ3ZFO0tBQ0Y7SUFFRCxRQUFRLE1BQU0sRUFBRTtRQUNkLEtBQUssZUFBZSxDQUFDLElBQUk7WUFDdkIsT0FBTyxJQUFBLDJCQUFrQixFQUFDLFNBQVMsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDbkQ7WUFDRSxNQUFNLElBQUksS0FBSyxDQUFDLCtCQUErQixDQUFDLENBQUM7S0FDcEQ7QUFDSCxDQUFDO0FBbkJELHdDQW1CQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCBHb29nbGUgTExDIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbiAqIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgYXQgaHR0cHM6Ly9hbmd1bGFyLmlvL2xpY2Vuc2VcbiAqL1xuXG5pbXBvcnQgeyBiYXNlbmFtZSwgZ2V0U3lzdGVtUGF0aCwgam9pbiwgbm9ybWFsaXplIH0gZnJvbSAnLi4vdmlydHVhbC1mcyc7XG5pbXBvcnQgeyBXb3Jrc3BhY2VEZWZpbml0aW9uIH0gZnJvbSAnLi9kZWZpbml0aW9ucyc7XG5pbXBvcnQgeyBXb3Jrc3BhY2VIb3N0IH0gZnJvbSAnLi9ob3N0JztcbmltcG9ydCB7IHJlYWRKc29uV29ya3NwYWNlIH0gZnJvbSAnLi9qc29uL3JlYWRlcic7XG5pbXBvcnQgeyB3cml0ZUpzb25Xb3Jrc3BhY2UgfSBmcm9tICcuL2pzb24vd3JpdGVyJztcblxuY29uc3QgZm9ybWF0TG9va3VwID0gbmV3IFdlYWtNYXA8V29ya3NwYWNlRGVmaW5pdGlvbiwgV29ya3NwYWNlRm9ybWF0PigpO1xuXG4vKipcbiAqIFN1cHBvcnRlZCB3b3Jrc3BhY2UgZm9ybWF0c1xuICovXG5leHBvcnQgZW51bSBXb3Jrc3BhY2VGb3JtYXQge1xuICBKU09OLFxufVxuXG4vKipcbiAqIEBwcml2YXRlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBfdGVzdF9hZGRXb3Jrc3BhY2VGaWxlKG5hbWU6IHN0cmluZywgZm9ybWF0OiBXb3Jrc3BhY2VGb3JtYXQpOiB2b2lkIHtcbiAgd29ya3NwYWNlRmlsZXNbbmFtZV0gPSBmb3JtYXQ7XG59XG5cbi8qKlxuICogQHByaXZhdGVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIF90ZXN0X3JlbW92ZVdvcmtzcGFjZUZpbGUobmFtZTogc3RyaW5nKTogdm9pZCB7XG4gIGRlbGV0ZSB3b3Jrc3BhY2VGaWxlc1tuYW1lXTtcbn1cblxuLy8gTk9URTogZnV0dXJlIGFkZGl0aW9ucyBjb3VsZCBhbHNvIHBlcmZvcm0gY29udGVudCBhbmFseXNpcyB0byBkZXRlcm1pbmUgZm9ybWF0L3ZlcnNpb25cbmNvbnN0IHdvcmtzcGFjZUZpbGVzOiBSZWNvcmQ8c3RyaW5nLCBXb3Jrc3BhY2VGb3JtYXQ+ID0ge1xuICAnYW5ndWxhci5qc29uJzogV29ya3NwYWNlRm9ybWF0LkpTT04sXG4gICcuYW5ndWxhci5qc29uJzogV29ya3NwYWNlRm9ybWF0LkpTT04sXG59O1xuXG4vKipcbiAqIFJlYWRzIGFuZCBjb25zdHJ1Y3RzIGEgYFdvcmtzcGFjZURlZmluaXRpb25gLiAgSWYgdGhlIGZ1bmN0aW9uIGlzIHByb3ZpZGVkIHdpdGggYSBwYXRoIHRvIGFcbiAqIGRpcmVjdG9yeSBpbnN0ZWFkIG9mIGEgZmlsZSwgYSBzZWFyY2ggb2YgdGhlIGRpcmVjdG9yeSdzIGZpbGVzIHdpbGwgY29tbWVuY2UgdG8gYXR0ZW1wdCB0b1xuICogbG9jYXRlIGEga25vd24gd29ya3NwYWNlIGZpbGUuICBDdXJyZW50bHkgdGhlIGZvbGxvd2luZyBhcmUgY29uc2lkZXJlZCBrbm93biB3b3Jrc3BhY2UgZmlsZXM6XG4gKiAtIGBhbmd1bGFyLmpzb25gXG4gKiAtIGAuYW5ndWxhci5qc29uYFxuICpcbiAqIEBwYXJhbSBwYXRoIFRoZSBwYXRoIHRvIGVpdGhlciBhIHdvcmtzcGFjZSBmaWxlIG9yIGEgZGlyZWN0b3J5IGNvbnRhaW5pbmcgYSB3b3Jrc3BhY2UgZmlsZS5cbiAqIEBwYXJhbSBob3N0IFRoZSBgV29ya3NwYWNlSG9zdGAgdG8gdXNlIHRvIGFjY2VzcyB0aGUgZmlsZSBhbmQgZGlyZWN0b3J5IGRhdGEuXG4gKiBAcGFyYW0gZm9ybWF0IEFuIG9wdGlvbmFsIGBXb3Jrc3BhY2VGb3JtYXRgIHZhbHVlLiBVc2VkIGlmIHRoZSBwYXRoIHNwZWNpZmllcyBhIG5vbi1zdGFuZGFyZFxuICogZmlsZSBuYW1lIHRoYXQgd291bGQgcHJldmVudCBhdXRvbWF0aWNhbGx5IGRpc2NvdmVyaW5nIHRoZSBmb3JtYXQuXG4gKlxuICpcbiAqIEByZXR1cm4gQW4gYFByb21pc2VgIG9mIHRoZSByZWFkIHJlc3VsdCBvYmplY3Qgd2l0aCB0aGUgYFdvcmtzcGFjZURlZmluaXRpb25gIGNvbnRhaW5lZCB3aXRoaW5cbiAqIHRoZSBgd29ya3NwYWNlYCBwcm9wZXJ0eS5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlYWRXb3Jrc3BhY2UoXG4gIHBhdGg6IHN0cmluZyxcbiAgaG9zdDogV29ya3NwYWNlSG9zdCxcbiAgZm9ybWF0PzogV29ya3NwYWNlRm9ybWF0LFxuICAvLyByZXR1cm4gdHlwZSB3aWxsIGV2ZW50dWFsbHkgaGF2ZSBhIGBkaWFnbm9zdGljc2AgcHJvcGVydHkgYXMgd2VsbFxuKTogUHJvbWlzZTx7IHdvcmtzcGFjZTogV29ya3NwYWNlRGVmaW5pdGlvbiB9PiB7XG4gIGlmIChhd2FpdCBob3N0LmlzRGlyZWN0b3J5KHBhdGgpKSB7XG4gICAgLy8gVE9ETzogV2FybiBpZiBtdWx0aXBsZSBmb3VuZCAocmVxdWlyZXMgZGlhZ25vc3RpY3Mgc3VwcG9ydClcbiAgICBjb25zdCBkaXJlY3RvcnkgPSBub3JtYWxpemUocGF0aCk7XG4gICAgbGV0IGZvdW5kID0gZmFsc2U7XG4gICAgZm9yIChjb25zdCBbbmFtZSwgbmFtZUZvcm1hdF0gb2YgT2JqZWN0LmVudHJpZXMod29ya3NwYWNlRmlsZXMpKSB7XG4gICAgICBpZiAoZm9ybWF0ICE9PSB1bmRlZmluZWQgJiYgZm9ybWF0ICE9PSBuYW1lRm9ybWF0KSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBwb3RlbnRpYWwgPSBnZXRTeXN0ZW1QYXRoKGpvaW4oZGlyZWN0b3J5LCBuYW1lKSk7XG4gICAgICBpZiAoYXdhaXQgaG9zdC5pc0ZpbGUocG90ZW50aWFsKSkge1xuICAgICAgICBwYXRoID0gcG90ZW50aWFsO1xuICAgICAgICBmb3JtYXQgPSBuYW1lRm9ybWF0O1xuICAgICAgICBmb3VuZCA9IHRydWU7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAoIWZvdW5kKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICdVbmFibGUgdG8gbG9jYXRlIGEgd29ya3NwYWNlIGZpbGUgZm9yIHdvcmtzcGFjZSBwYXRoLiBBcmUgeW91IG1pc3NpbmcgYW4gYGFuZ3VsYXIuanNvbmAnICtcbiAgICAgICAgICAnIG9yIGAuYW5ndWxhci5qc29uYCBmaWxlPycsXG4gICAgICApO1xuICAgIH1cbiAgfSBlbHNlIGlmIChmb3JtYXQgPT09IHVuZGVmaW5lZCkge1xuICAgIGNvbnN0IGZpbGVuYW1lID0gYmFzZW5hbWUobm9ybWFsaXplKHBhdGgpKTtcbiAgICBpZiAoZmlsZW5hbWUgaW4gd29ya3NwYWNlRmlsZXMpIHtcbiAgICAgIGZvcm1hdCA9IHdvcmtzcGFjZUZpbGVzW2ZpbGVuYW1lXTtcbiAgICB9XG4gIH1cblxuICBpZiAoZm9ybWF0ID09PSB1bmRlZmluZWQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1VuYWJsZSB0byBkZXRlcm1pbmUgZm9ybWF0IGZvciB3b3Jrc3BhY2UgcGF0aC4nKTtcbiAgfVxuXG4gIGxldCB3b3Jrc3BhY2U7XG4gIHN3aXRjaCAoZm9ybWF0KSB7XG4gICAgY2FzZSBXb3Jrc3BhY2VGb3JtYXQuSlNPTjpcbiAgICAgIHdvcmtzcGFjZSA9IGF3YWl0IHJlYWRKc29uV29ya3NwYWNlKHBhdGgsIGhvc3QpO1xuICAgICAgYnJlYWs7XG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcignVW5zdXBwb3J0ZWQgd29ya3NwYWNlIGZvcm1hdC4nKTtcbiAgfVxuXG4gIGZvcm1hdExvb2t1cC5zZXQod29ya3NwYWNlLCBXb3Jrc3BhY2VGb3JtYXQuSlNPTik7XG5cbiAgcmV0dXJuIHsgd29ya3NwYWNlIH07XG59XG5cbi8qKlxuICogV3JpdGVzIGEgYFdvcmtzcGFjZURlZmluaXRpb25gIHRvIHRoZSB1bmRlcmx5aW5nIHN0b3JhZ2UgdmlhIHRoZSBwcm92aWRlZCBgV29ya3NwYWNlSG9zdGAuXG4gKiBJZiB0aGUgYFdvcmtzcGFjZURlZmluaXRpb25gIHdhcyBjcmVhdGVkIHZpYSB0aGUgYHJlYWRXb3Jrc3BhY2VgIGZ1bmN0aW9uLCBtZXRhZGF0YSB3aWxsIGJlXG4gKiB1c2VkIHRvIGRldGVybWluZSB0aGUgcGF0aCBhbmQgZm9ybWF0IG9mIHRoZSBXb3Jrc3BhY2UuICBJbiBhbGwgb3RoZXIgY2FzZXMsIHRoZSBgcGF0aGAgYW5kXG4gKiBgZm9ybWF0YCBvcHRpb25zIG11c3QgYmUgc3BlY2lmaWVkIGFzIHRoZXkgd291bGQgYmUgb3RoZXJ3aXNlIHVua25vd24uXG4gKlxuICogQHBhcmFtIHdvcmtzcGFjZSBUaGUgYFdvcmtzcGFjZURlZmluaXRpb25gIHRoYXQgd2lsbCBiZSB3cml0dGVuLlxuICogQHBhcmFtIGhvc3QgVGhlIGBXb3Jrc3BhY2VIb3N0YCB0byB1c2UgdG8gYWNjZXNzL3dyaXRlIHRoZSBmaWxlIGFuZCBkaXJlY3RvcnkgZGF0YS5cbiAqIEBwYXJhbSBwYXRoIFRoZSBwYXRoIHRvIGEgZmlsZSBsb2NhdGlvbiBmb3IgdGhlIG91dHB1dC4gUmVxdWlyZWQgaWYgYHJlYWRXb3Jrc3BhY2VgIHdhcyBub3RcbiAqIHVzZWQgdG8gY3JlYXRlIHRoZSBgV29ya3NwYWNlRGVmaW5pdGlvbmAuICBPcHRpb25hbCBvdGhlcndpc2U7IHdpbGwgb3ZlcnJpZGUgdGhlXG4gKiBgV29ya3NwYWNlRGVmaW5pdGlvbmAgbWV0YWRhdGEgaWYgcHJvdmlkZWQuXG4gKiBAcGFyYW0gZm9ybWF0IFRoZSBgV29ya3NwYWNlRm9ybWF0YCB0byB1c2UgZm9yIG91dHB1dC4gUmVxdWlyZWQgaWYgYHJlYWRXb3Jrc3BhY2VgIHdhcyBub3RcbiAqIHVzZWQgdG8gY3JlYXRlIHRoZSBgV29ya3NwYWNlRGVmaW5pdGlvbmAuICBPcHRpb25hbCBvdGhlcndpc2U7IHdpbGwgb3ZlcnJpZGUgdGhlXG4gKiBgV29ya3NwYWNlRGVmaW5pdGlvbmAgbWV0YWRhdGEgaWYgcHJvdmlkZWQuXG4gKlxuICpcbiAqIEByZXR1cm4gQW4gYFByb21pc2VgIG9mIHR5cGUgYHZvaWRgLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gd3JpdGVXb3Jrc3BhY2UoXG4gIHdvcmtzcGFjZTogV29ya3NwYWNlRGVmaW5pdGlvbixcbiAgaG9zdDogV29ya3NwYWNlSG9zdCxcbiAgcGF0aD86IHN0cmluZyxcbiAgZm9ybWF0PzogV29ya3NwYWNlRm9ybWF0LFxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGlmIChmb3JtYXQgPT09IHVuZGVmaW5lZCkge1xuICAgIGZvcm1hdCA9IGZvcm1hdExvb2t1cC5nZXQod29ya3NwYWNlKTtcbiAgICBpZiAoZm9ybWF0ID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQSBmb3JtYXQgaXMgcmVxdWlyZWQgZm9yIGN1c3RvbSB3b3Jrc3BhY2Ugb2JqZWN0cy4nKTtcbiAgICB9XG4gIH1cblxuICBzd2l0Y2ggKGZvcm1hdCkge1xuICAgIGNhc2UgV29ya3NwYWNlRm9ybWF0LkpTT046XG4gICAgICByZXR1cm4gd3JpdGVKc29uV29ya3NwYWNlKHdvcmtzcGFjZSwgaG9zdCwgcGF0aCk7XG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcignVW5zdXBwb3J0ZWQgd29ya3NwYWNlIGZvcm1hdC4nKTtcbiAgfVxufVxuIl19
;