292 lines
26 KiB
JavaScript
292 lines
26 KiB
JavaScript
"use strict";
|
|
var __defProp = Object.defineProperty;
|
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
var __export = (target, all) => {
|
|
for (var name in all)
|
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
};
|
|
var __copyProps = (to, from, except, desc) => {
|
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
for (let key of __getOwnPropNames(from))
|
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
}
|
|
return to;
|
|
};
|
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
|
|
// src/index.ts
|
|
var src_exports = {};
|
|
__export(src_exports, {
|
|
FFmpeg: () => FFmpeg,
|
|
changeFFmpegFlags: () => changeFFmpegFlags,
|
|
createFFmpegArgs: () => createFFmpegArgs,
|
|
version: () => version
|
|
});
|
|
module.exports = __toCommonJS(src_exports);
|
|
|
|
// src/FFmpeg.ts
|
|
var import_node_child_process = require("child_process");
|
|
var import_node_stream = require("stream");
|
|
var VERSION_REGEX = /version (.+) Copyright/im;
|
|
var validatePathParam = /* @__PURE__ */ __name((path, displayName) => {
|
|
if (!path) throw new Error(`Failed to resolve ${displayName}`);
|
|
return path;
|
|
}, "validatePathParam");
|
|
var _FFmpeg = class _FFmpeg extends import_node_stream.Duplex {
|
|
/**
|
|
* Create FFmpeg duplex stream
|
|
* @param options Options to initialize ffmpeg
|
|
* @example ```typescript
|
|
* const ffmpeg = new FFmpeg({
|
|
* args: [
|
|
* '-analyzeduration', '0',
|
|
* '-loglevel', '0',
|
|
* '-f', 's16le',
|
|
* '-ar', '48000',
|
|
* '-ac', '2',
|
|
* '-af', 'bass=g=10,acompressor'
|
|
* ]
|
|
* });
|
|
*
|
|
* const pcm = input.pipe(ffmpeg);
|
|
*
|
|
* pcm.pipe(fs.createWriteStream('./audio.pcm'));
|
|
* ```
|
|
*/
|
|
constructor(options = {}) {
|
|
super(options);
|
|
/**
|
|
* Current FFmpeg process
|
|
*/
|
|
__publicField(this, "process");
|
|
this.process = _FFmpeg.spawn(options);
|
|
const EVENTS = {
|
|
readable: this._reader,
|
|
data: this._reader,
|
|
end: this._reader,
|
|
unpipe: this._reader,
|
|
finish: this._writer,
|
|
drain: this._writer
|
|
};
|
|
this._readableState = this._reader._readableState;
|
|
this._writableState = this._writer._writableState;
|
|
this._copy(["write", "end"], this._writer);
|
|
this._copy(["read", "setEncoding", "pipe", "unpipe"], this._reader);
|
|
for (const method of [
|
|
"on",
|
|
"once",
|
|
"removeListener",
|
|
"removeAllListeners",
|
|
"listeners"
|
|
]) {
|
|
this[method] = (ev, fn) => (
|
|
// @ts-expect-error
|
|
EVENTS[ev] ? (
|
|
// @ts-expect-error
|
|
EVENTS[ev][method](ev, fn)
|
|
) : (
|
|
// @ts-expect-error
|
|
import_node_stream.Duplex.prototype[method].call(this, ev, fn)
|
|
)
|
|
);
|
|
}
|
|
const processError = /* @__PURE__ */ __name((error) => this.emit("error", error), "processError");
|
|
this._reader.on("error", processError);
|
|
this._writer.on("error", processError);
|
|
}
|
|
/**
|
|
* Checks if FFmpeg is loaded.
|
|
*/
|
|
static isLoaded() {
|
|
return _FFmpeg.cached != null;
|
|
}
|
|
/**
|
|
* Adds a new FFmpeg source.
|
|
* @param source FFmpeg source
|
|
*/
|
|
static addSource(source) {
|
|
if (_FFmpeg.sources.some((s) => s.name === source.name)) return false;
|
|
_FFmpeg.sources.push(source);
|
|
return true;
|
|
}
|
|
/**
|
|
* Removes a FFmpeg source.
|
|
* @param source FFmpeg source
|
|
*/
|
|
static removeSource(source) {
|
|
const index = _FFmpeg.sources.findIndex((s) => s.name === source.name);
|
|
if (index === -1) return false;
|
|
_FFmpeg.sources.splice(index, 1);
|
|
return true;
|
|
}
|
|
/**
|
|
* Resolves FFmpeg path. Throws an error if it fails to resolve.
|
|
* @param force if it should relocate the command
|
|
*/
|
|
static resolve(force = false) {
|
|
if (!force && _FFmpeg.cached) return _FFmpeg.cached;
|
|
const errors = [];
|
|
for (const source of _FFmpeg.sources) {
|
|
try {
|
|
let path;
|
|
if (source.module) {
|
|
const mod = require(source.name);
|
|
path = validatePathParam(
|
|
mod.default?.path || mod.path || mod,
|
|
source.name
|
|
);
|
|
} else {
|
|
path = source.name;
|
|
}
|
|
const result = (0, import_node_child_process.spawnSync)(path, ["-v"], { windowsHide: true });
|
|
const resolved = {
|
|
result: result.stdout.toString(),
|
|
command: path,
|
|
module: source.module,
|
|
name: source.name,
|
|
path,
|
|
version: VERSION_REGEX.exec(result.stderr.toString())?.[1] ?? "unknown"
|
|
};
|
|
_FFmpeg.cached = resolved;
|
|
errors.length = 0;
|
|
return resolved;
|
|
} catch (e) {
|
|
const err = e && e instanceof Error ? e.message : `${e}`;
|
|
const msg = `Failed to load ffmpeg using ${source.module ? `require('${source.name}')` : `spawn('${source.name}')`}. Error: ${err}`;
|
|
errors.push(msg);
|
|
}
|
|
}
|
|
throw new Error(`Could not load ffmpeg. Errors:
|
|
${errors.join("\n")}`);
|
|
}
|
|
/**
|
|
* Resolves FFmpeg path safely. Returns null if it fails to resolve.
|
|
* @param force if it should relocate the command
|
|
*/
|
|
static resolveSafe(force = false) {
|
|
try {
|
|
return _FFmpeg.resolve(force);
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
/**
|
|
* Spawns ffmpeg process
|
|
* @param options Spawn options
|
|
*/
|
|
static spawn({ args = [], shell = false } = {}) {
|
|
if (!args.includes("-i")) args.unshift("-i", "-");
|
|
return (0, import_node_child_process.spawn)(_FFmpeg.resolve().command, args.concat(["pipe:1"]), {
|
|
windowsHide: true,
|
|
shell
|
|
});
|
|
}
|
|
get _reader() {
|
|
return this.process.stdout;
|
|
}
|
|
get _writer() {
|
|
return this.process.stdin;
|
|
}
|
|
_copy(methods, target) {
|
|
for (const method of methods) {
|
|
this[method] = target[method].bind(target);
|
|
}
|
|
}
|
|
_destroy(err, cb) {
|
|
this._cleanup();
|
|
if (cb) return cb(err);
|
|
}
|
|
_final(cb) {
|
|
this._cleanup();
|
|
cb();
|
|
}
|
|
_cleanup() {
|
|
if (this.process) {
|
|
this.once("error", () => {
|
|
});
|
|
this.process.kill("SIGKILL");
|
|
this.process = null;
|
|
}
|
|
}
|
|
};
|
|
__name(_FFmpeg, "FFmpeg");
|
|
/**
|
|
* Cached FFmpeg source.
|
|
*/
|
|
__publicField(_FFmpeg, "cached", null);
|
|
/**
|
|
* Supported FFmpeg sources.
|
|
*/
|
|
__publicField(_FFmpeg, "sources", [
|
|
// paths
|
|
{ name: "ffmpeg", module: false },
|
|
{ name: "./ffmpeg", module: false },
|
|
{ name: "avconv", module: false },
|
|
{ name: "./avconv", module: false },
|
|
// modules
|
|
{ name: "ffmpeg-static", module: true },
|
|
{ name: "@ffmpeg-installer/ffmpeg", module: true },
|
|
{ name: "@node-ffmpeg/node-ffmpeg-installer", module: true },
|
|
{ name: "ffmpeg-binaries", module: true }
|
|
]);
|
|
var FFmpeg = _FFmpeg;
|
|
|
|
// src/common.ts
|
|
function changeFFmpegFlags(oldFlags, newFlags) {
|
|
const updatedFlags = [...oldFlags];
|
|
for (let i = 0; i < newFlags.length; i++) {
|
|
const key = newFlags[i];
|
|
const value = newFlags[i + 1];
|
|
const oldIndex = updatedFlags.indexOf(key);
|
|
if (oldIndex !== -1) {
|
|
if (value && !value.startsWith("-")) {
|
|
updatedFlags[oldIndex + 1] = value;
|
|
i++;
|
|
} else {
|
|
updatedFlags.splice(oldIndex, 1);
|
|
}
|
|
} else {
|
|
if (value && !value.startsWith("-")) {
|
|
updatedFlags.push(key, value);
|
|
i++;
|
|
} else {
|
|
updatedFlags.push(key);
|
|
}
|
|
}
|
|
}
|
|
return updatedFlags;
|
|
}
|
|
__name(changeFFmpegFlags, "changeFFmpegFlags");
|
|
|
|
// src/version.ts
|
|
var version = (
|
|
/* @__MACRO__ getVersion */
|
|
"7.2.0"
|
|
);
|
|
|
|
// src/index.ts
|
|
var createFFmpegArgs = /* @__PURE__ */ __name((input, post) => {
|
|
const args = [];
|
|
for (const [key, value] of Object.entries(input)) {
|
|
if (value == null) continue;
|
|
args.push(`-${key}`, String(value));
|
|
}
|
|
if (post) {
|
|
Array.isArray(post) ? args.push(...post) : args.push(post);
|
|
}
|
|
return args;
|
|
}, "createFFmpegArgs");
|
|
// Annotate the CommonJS export names for ESM import in node:
|
|
0 && (module.exports = {
|
|
FFmpeg,
|
|
changeFFmpegFlags,
|
|
createFFmpegArgs,
|
|
version
|
|
});
|
|
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL2luZGV4LnRzIiwgIi4uL3NyYy9GRm1wZWcudHMiLCAiLi4vc3JjL2NvbW1vbi50cyIsICIuLi9zcmMvdmVyc2lvbi50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiZXhwb3J0ICogZnJvbSAnLi9GRm1wZWcnO1xuXG5leHBvcnQgdHlwZSBBcmdQcmltaXRpdmUgPSBzdHJpbmcgfCBudW1iZXIgfCBudWxsO1xuXG4vKipcbiAqIENyZWF0ZSBGRm1wZWcgYXJndW1lbnRzIGZyb20gYW4gb2JqZWN0LlxuICogQHBhcmFtIGlucHV0IFRoZSBpbnB1dCBvYmplY3QuXG4gKiBAcGFyYW0gcG9zdCBBZGRpdGlvbmFsIGFyZ3VtZW50cyB0byBhcHBlbmQuXG4gKiBAcmV0dXJucyBUaGUgRkZtcGVnIGFyZ3VtZW50cy5cbiAqIEBleGFtcGxlIGNyZWF0ZUZGbXBlZ0FyZ3MoeyBpOiAnaW5wdXQubXAzJywgYWY6IFsnYmFzcz1nPTEwJywnYWNvbXByZXNzb3InXSB9LCAnLi9vdXQubXAzJyk7XG4gKiAvLyA9PiBbJy1pJywgJ2lucHV0Lm1wMycsICctYWYnLCAnYmFzcz1nPTEwLGFjb21wcmVzc29yJywgJy4vb3V0Lm1wMyddXG4gKi9cbmV4cG9ydCBjb25zdCBjcmVhdGVGRm1wZWdBcmdzID0gKFxuaW5wdXQ6IFJlY29yZDxzdHJpbmcsIEFyZ1ByaW1pdGl2ZSB8IEFyZ1ByaW1pdGl2ZVtdPixcbnBvc3Q/OiBzdHJpbmcgfCBzdHJpbmdbXSlcbjogc3RyaW5nW10gPT4ge1xuICBjb25zdCBhcmdzID0gW107XG5cbiAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgT2JqZWN0LmVudHJpZXMoaW5wdXQpKSB7XG4gICAgaWYgKHZhbHVlID09IG51bGwpIGNvbnRpbnVlO1xuICAgIGFyZ3MucHVzaChgLSR7a2V5fWAsIFN0cmluZyh2YWx1ZSkpO1xuICB9XG5cbiAgaWYgKHBvc3QpIHtcbiAgICBBcnJheS5pc0FycmF5KHBvc3QpID8gYXJncy5wdXNoKC4uLnBvc3QpIDogYXJncy5wdXNoKHBvc3QpO1xuICB9XG5cbiAgcmV0dXJuIGFyZ3M7XG59O1xuXG5leHBvcnQgKiBmcm9tICcuL2NvbW1vbic7XG5leHBvcnQgeyB2ZXJzaW9uIH0gZnJvbSAnLi92ZXJzaW9uJzsiLCAiaW1wb3J0IHtcbiAgQ2hpbGRQcm9jZXNzV2l0aG91dE51bGxTdHJlYW1zLFxuICBzcGF3bixcbiAgc3Bhd25TeW5jIH0gZnJvbVxuJ25vZGU6Y2hpbGRfcHJvY2Vzcyc7XG5pbXBvcnQgeyBEdXBsZXgsIER1cGxleE9wdGlvbnMgfSBmcm9tICdub2RlOnN0cmVhbSc7XG5pbXBvcnQgeyBGRm1wZWdDYWxsYmFjaywgRkZtcGVnU291cmNlLCBSZXNvbHZlZEZGbXBlZ1NvdXJjZSB9IGZyb20gJy4vY29tbW9uJztcblxuZXhwb3J0IGludGVyZmFjZSBGRm1wZWdPcHRpb25zIGV4dGVuZHMgRHVwbGV4T3B0aW9ucyB7XG4gIGFyZ3M/OiBzdHJpbmdbXTtcbiAgc2hlbGw/OiBib29sZWFuO1xufVxuXG5jb25zdCBWRVJTSU9OX1JFR0VYID0gL3ZlcnNpb24gKC4rKSBDb3B5cmlnaHQvaW07XG5cbmNvbnN0IHZhbGlkYXRlUGF0aFBhcmFtID0gKHBhdGg6IHN0cmluZywgZGlzcGxheU5hbWU6IHN0cmluZykgPT4ge1xuICBpZiAoIXBhdGgpIHRocm93IG5ldyBFcnJvcihgRmFpbGVkIHRvIHJlc29sdmUgJHtkaXNwbGF5TmFtZX1gKTtcbiAgcmV0dXJuIHBhdGg7XG59O1xuXG5leHBvcnQgY2xhc3MgRkZtcGVnIGV4dGVuZHMgRHVwbGV4IHtcbiAgLyoqXG4gICAqIENhY2hlZCBGRm1wZWcgc291cmNlLlxuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgY2FjaGVkOiBSZXNvbHZlZEZGbXBlZ1NvdXJjZSB8IG51bGwgPSBudWxsO1xuICAvKipcbiAgICogU3VwcG9ydGVkIEZGbXBlZyBzb3VyY2VzLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBzb3VyY2VzOiBGRm1wZWdTb3VyY2VbXSA9IFtcbiAgLy8gcGF0aHNcbiAgeyBuYW1lOiAnZmZtcGVnJywgbW9kdWxlOiBmYWxzZSB9LFxuICB7IG5hbWU6ICcuL2ZmbXBlZycsIG1vZHVsZTogZmFsc2UgfSxcbiAgeyBuYW1lOiAnYXZjb252JywgbW9kdWxlOiBmYWxzZSB9LFxuICB7IG5hbWU6ICcuL2F2Y29udicsIG1vZHVsZTogZmFsc2UgfSxcbiAgLy8gbW9kdWxlc1xuICB7IG5hbWU6ICdmZm1wZWctc3RhdGljJywgbW9kdWxlOiB0cnVlIH0sXG4gIHsgbmFtZTogJ0BmZm1wZWctaW5zdGFsbGVyL2ZmbXBlZycsIG1vZHVsZTogdHJ1ZSB9LFxuICB7IG5hbWU6ICdAbm9kZS1mZm1wZWcvbm9kZS1mZm1wZWctaW5zdGFsbGVyJywgbW9kdWxlOiB0cnVlIH0sXG4gIHsgbmFtZTogJ2ZmbXBlZy1iaW5hcmllcycsIG1vZHVsZTogdHJ1ZSB9XTtcblxuXG4gIC8qKlxuICAgKiBDaGVja3MgaWYgRkZtcGVnIGlzIGxvYWRlZC5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgaXNMb2FkZWQoKSB7XG4gICAgcmV0dXJuIEZGbXBlZy5jYWNoZWQgIT0gbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIGEgbmV3IEZGbXBlZyBzb3VyY2UuXG4gICAqIEBwYXJhbSBzb3VyY2UgRkZtcGVnIHNvdXJjZVxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBhZGRTb3VyY2Uoc291cmNlOiBGRm1wZWdTb3VyY2UpIHtcbiAgICBpZiAoRkZtcGVnLnNvdXJjZXMuc29tZSgocykgPT4gcy5uYW1lID09PSBzb3VyY2UubmFtZSkpIHJldHVybiBmYWxzZTtcbiAgICBGRm1wZWcuc291cmNlcy5wdXNoKHNvdXJjZSk7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKipcbiAgICogUmVtb3ZlcyBhIEZGbXBlZyBzb3VyY2UuXG4gICAqIEBwYXJhbSBzb3VyY2UgRkZtcGVnIHNvdXJjZVxuICAgKi9cbiAgcHVibGljIHN0YXRpYyByZW1vdmVTb3VyY2Uoc291cmNlOiBGRm1wZWdTb3VyY2UpIHtcbiAgICBjb25zdCBpbmRleCA9IEZGbXBlZy5zb3VyY2VzLmZpbmRJbmRleCgocykgPT4gcy5uYW1lID09PSBzb3VyY2UubmFtZSk7XG4gICAgaWYgKGluZGV4ID09PSAtMSkgcmV0dXJuIGZhbHNlO1xuICAgIEZGbXBlZy5zb3VyY2VzLnNwbGljZShpbmRleCwgMSk7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKipcbiAgICogUmVzb2x2ZXMgRkZtcGVnIHBhdGguIFRocm93cyBhbiBlcnJvciBpZiBpdCBmYWlscyB0byByZXNvbHZlLlxuICAgKiBAcGFyYW0gZm9yY2UgaWYgaXQgc2hvdWxkIHJlbG9jYXRlIHRoZSBjb21tYW5kXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHJlc29sdmUoZm9yY2UgPSBmYWxzZSkge1xuICAgIGlmICghZm9yY2UgJiYgRkZtcGVnLmNhY2hlZCkgcmV0dXJuIEZGbXBlZy5jYWNoZWQ7XG5cbiAgICBjb25zdCBlcnJvcnM6IHN0cmluZ1tdID0gW107XG5cbiAgICBmb3IgKGNvbnN0IHNvdXJjZSBvZiBGRm1wZWcuc291cmNlcykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgbGV0IHBhdGg6IHN0cmluZztcblxuICAgICAgICBpZiAoc291cmNlLm1vZHVsZSkge1xuICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdmFyLXJlcXVpcmVzXG4gICAgICAgICAgY29uc3QgbW9kID0gcmVxdWlyZShzb3VyY2UubmFtZSk7XG4gICAgICAgICAgcGF0aCA9IHZhbGlkYXRlUGF0aFBhcmFtKFxuICAgICAgICAgICAgbW9kLmRlZmF1bHQ/LnBhdGggfHwgbW9kLnBhdGggfHwgbW9kLFxuICAgICAgICAgICAgc291cmNlLm5hbWVcbiAgICAgICAgICApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHBhdGggPSBzb3VyY2UubmFtZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IHNwYXduU3luYyhwYXRoLCBbJy12J10sIHsgd2luZG93c0hpZGU6IHRydWUgfSk7XG5cbiAgICAgICAgY29uc3QgcmVzb2x2ZWQ6IFJlc29sdmVkRkZtcGVnU291cmNlID0ge1xuICAgICAgICAgIHJlc3VsdDogcmVzdWx0LnN0ZG91dC50b1N0cmluZygpLFxuICAgICAgICAgIGNvbW1hbmQ6IHBhdGgsXG4gICAgICAgICAgbW9kdWxlOiBzb3VyY2UubW9kdWxlLFxuICAgICAgICAgIG5hbWU6IHNvdXJjZS5uYW1lLFxuICAgICAgICAgIHBhdGgsXG4gICAgICAgICAgdmVyc2lvbjpcbiAgICAgICAgICBWRVJTSU9OX1JFR0VYLmV4ZWMocmVzdWx0LnN0ZGVyci50b1N0cmluZygpKT8uWzFdID8/ICd1bmtub3duJ1xuICAgICAgICB9O1xuXG4gICAgICAgIEZGbXBlZy5jYWNoZWQgPSByZXNvbHZlZDtcblxuICAgICAgICBlcnJvcnMubGVuZ3RoID0gMDtcblxuICAgICAgICByZXR1cm4gcmVzb2x2ZWQ7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGNvbnN0IGVyciA9IGUgJiYgZSBpbnN0YW5jZW9mIEVycm9yID8gZS5tZXNzYWdlIDogYCR7ZX1gO1xuICAgICAgICBjb25zdCBtc2cgPSBgRmFpbGVkIHRvIGxvYWQgZmZtcGVnIHVzaW5nICR7XG4gICAgICAgIHNvdXJjZS5tb2R1bGUgP1xuICAgICAgICBgcmVxdWlyZSgnJHtzb3VyY2UubmFtZX0nKWAgOlxuICAgICAgICBgc3Bhd24oJyR7c291cmNlLm5hbWV9JylgfS4gRXJyb3I6ICR7XG4gICAgICAgIGVycn1gO1xuXG4gICAgICAgIGVycm9ycy5wdXNoKG1zZyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKGBDb3VsZCBub3QgbG9hZCBmZm1wZWcuIEVycm9yczpcXG4ke2Vycm9ycy5qb2luKCdcXG4nKX1gKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXNvbHZlcyBGRm1wZWcgcGF0aCBzYWZlbHkuIFJldHVybnMgbnVsbCBpZiBpdCBmYWlscyB0byByZXNvbHZlLlxuICAgKiBAcGFyYW0gZm9yY2UgaWYgaXQgc2hvdWxkIHJlbG9jYXRlIHRoZSBjb21tYW5kXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHJlc29sdmVTYWZlKGZvcmNlID0gZmFsc2UpIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIEZGbXBlZy5yZXNvbHZlKGZvcmNlKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTcGF3bnMgZmZtcGVnIHByb2Nlc3NcbiAgICogQHBhcmFtIG9wdGlvbnMgU3Bhd24gb3B0aW9uc1xuICAgKi9cbiAgcHVibGljIHN0YXRpYyBzcGF3bih7IGFyZ3MgPSBbXSBhcyBzdHJpbmdbXSwgc2hlbGwgPSBmYWxzZSB9ID0ge30pIHtcbiAgICBpZiAoIWFyZ3MuaW5jbHVkZXMoJy1pJykpIGFyZ3MudW5zaGlmdCgnLWknLCAnLScpO1xuICAgIHJldHVybiBzcGF3bihGRm1wZWcucmVzb2x2ZSgpLmNvbW1hbmQsIGFyZ3MuY29uY2F0KFsncGlwZToxJ10pLCB7XG4gICAgICB3aW5kb3dzSGlkZTogdHJ1ZSxcbiAgICAgIHNoZWxsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQ3VycmVudCBGRm1wZWcgcHJvY2Vzc1xuICAgKi9cbiAgcHVibGljIHByb2Nlc3M6IENoaWxkUHJvY2Vzc1dpdGhvdXROdWxsU3RyZWFtcztcblxuICAvKipcbiAgICogQ3JlYXRlIEZGbXBlZyBkdXBsZXggc3RyZWFtXG4gICAqIEBwYXJhbSBvcHRpb25zIE9wdGlvbnMgdG8gaW5pdGlhbGl6ZSBmZm1wZWdcbiAgICogQGV4YW1wbGUgYGBgdHlwZXNjcmlwdFxuICAgKiBjb25zdCBmZm1wZWcgPSBuZXcgRkZtcGVnKHtcbiAgICogICBhcmdzOiBbXG4gICAqICAgICAnLWFuYWx5emVkdXJhdGlvbicsICcwJyxcbiAgICogICAgICctbG9nbGV2ZWwnLCAnMCcsXG4gICAqICAgICAnLWYnLCAnczE2bGUnLFxuICAgKiAgICAgJy1hcicsICc0ODAwMCcsXG4gICAqICAgICAnLWFjJywgJzInLFxuICAgKiAgICAgJy1hZicsICdiYXNzPWc9MTAsYWNvbXByZXNzb3InXG4gICAqICAgXVxuICAgKiB9KTtcbiAgICpcbiAgICogY29uc3QgcGNtID0gaW5wdXQucGlwZShmZm1wZWcpO1xuICAgKlxuICAgKiBwY20ucGlwZShmcy5jcmVhdGVXcml0ZVN0cmVhbSgnLi9hdWRpby5wY20nKSk7XG4gICAqIGBgYFxuICAgKi9cbiAgcHVibGljIGNvbnN0cnVjdG9yKG9wdGlvbnM6IEZGbXBlZ09wdGlvbnMgPSB7fSkge1xuICAgIHN1cGVyKG9wdGlvbnMpO1xuXG4gICAgdGhpcy5wcm9jZXNzID0gRkZtcGVnLnNwYXduKG9wdGlvbnMpO1xuXG4gICAgY29uc3QgRVZFTlRTID0ge1xuICAgICAgcmVhZGFibGU6IHRoaXMuX3JlYWRlcixcbiAgICAgIGRhdGE6IHRoaXMuX3JlYWRlcixcbiAgICAgIGVuZDogdGhpcy5fcmVhZGVyLFxuICAgICAgdW5waXBlOiB0aGlzLl9yZWFkZXIsXG4gICAgICBmaW5pc2g6IHRoaXMuX3dyaXRlcixcbiAgICAgIGRyYWluOiB0aGlzLl93cml0ZXJcbiAgICB9IGFzIGNvbnN0O1xuXG4gICAgLy8gQHRzLWV4cGVjdC1lcnJvclxuICAgIHRoaXMuX3JlYWRhYmxlU3RhdGUgPSB0aGlzLl9yZWFkZXIuX3JlYWRhYmxlU3RhdGU7XG4gICAgLy8gQHRzLWV4cGVjdC1lcnJvclxuICAgIHRoaXMuX3dyaXRhYmxlU3RhdGUgPSB0aGlzLl93cml0ZXIuX3dyaXRhYmxlU3RhdGU7XG5cbiAgICB0aGlzLl9jb3B5KFsnd3JpdGUnLCAnZW5kJ10sIHRoaXMuX3dyaXRlcik7XG4gICAgdGhpcy5fY29weShbJ3JlYWQnLCAnc2V0RW5jb2RpbmcnLCAncGlwZScsICd1bnBpcGUnXSwgdGhpcy5fcmVhZGVyKTtcblxuICAgIGZvciAoY29uc3QgbWV0aG9kIG9mIFtcbiAgICAnb24nLFxuICAgICdvbmNlJyxcbiAgICAncmVtb3ZlTGlzdGVuZXInLFxuICAgICdyZW1vdmVBbGxMaXN0ZW5lcnMnLFxuICAgICdsaXN0ZW5lcnMnXSBhc1xuICAgIGNvbnN0KSB7XG4gICAgICAvLyBAdHMtZXhwZWN0LWVycm9yXG4gICAgICB0aGlzW21ldGhvZF0gPSAoZXYsIGZuKSA9PlxuICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvclxuICAgICAgRVZFTlRTW2V2XSA/XG4gICAgICAvLyBAdHMtZXhwZWN0LWVycm9yXG4gICAgICBFVkVOVFNbZXZdW21ldGhvZF0oZXYsIGZuKSA6XG4gICAgICAvLyBAdHMtZXhwZWN0LWVycm9yXG4gICAgICBEdXBsZXgucHJvdG90eXBlW21ldGhvZF0uY2FsbCh0aGlzLCBldiwgZm4pO1xuICAgIH1cblxuICAgIGNvbnN0IHByb2Nlc3NFcnJvciA9IChlcnJvcjogRXJyb3IpID0+IHRoaXMuZW1pdCgnZXJyb3InLCBlcnJvcik7XG5cbiAgICB0aGlzLl9yZWFkZXIub24oJ2Vycm9yJywgcHJvY2Vzc0Vycm9yKTtcbiAgICB0aGlzLl93cml0ZXIub24oJ2Vycm9yJywgcHJvY2Vzc0Vycm9yKTtcbiAgfVxuXG4gIGdldCBfcmVhZGVyKCkge1xuICAgIHJldHVybiB0aGlzLnByb2Nlc3MhLnN0ZG91dDtcbiAgfVxuICBnZXQgX3dyaXRlcigpIHtcbiAgICByZXR1cm4gdGhpcy5wcm9jZXNzIS5zdGRpbjtcbiAgfVxuXG4gIHByaXZhdGUgX2NvcHkobWV0aG9kczogc3RyaW5nW10sIHRhcmdldDogdW5rbm93bikge1xuICAgIGZvciAoY29uc3QgbWV0aG9kIG9mIG1ldGhvZHMpIHtcbiAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgICAgIHRoaXNbbWV0aG9kXSA9IHRhcmdldFttZXRob2RdLmJpbmQodGFyZ2V0KTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgX2Rlc3Ryb3koZXJyOiBFcnJvciB8IG51bGwsIGNiOiBGRm1wZWdDYWxsYmFjazxbRXJyb3IgfCBudWxsXT4pIHtcbiAgICB0aGlzLl9jbGVhbnVwKCk7XG4gICAgaWYgKGNiKSByZXR1cm4gY2IoZXJyKTtcbiAgfVxuXG4gIHB1YmxpYyBfZmluYWwoY2I6IEZGbXBlZ0NhbGxiYWNrPFtdPikge1xuICAgIHRoaXMuX2NsZWFudXAoKTtcbiAgICBjYigpO1xuICB9XG5cbiAgcHJpdmF0ZSBfY2xlYW51cCgpIHtcbiAgICBpZiAodGhpcy5wcm9jZXNzKSB7XG4gICAgICB0aGlzLm9uY2UoJ2Vycm9yJywgKCkgPT4ge1xuXG4gICAgICAgIC8vXG4gICAgICB9KTt0aGlzLnByb2Nlc3Mua2lsbCgnU0lHS0lMTCcpO1xuICAgICAgdGhpcy5wcm9jZXNzID0gbnVsbCBhcyB1bmtub3duIGFzIENoaWxkUHJvY2Vzc1dpdGhvdXROdWxsU3RyZWFtcztcbiAgICB9XG4gIH1cbn0iLCAiZXhwb3J0IHR5cGUgRkZtcGVnTGliID1cbidmZm1wZWcnIHxcbicuL2ZmbXBlZycgfFxuJ2F2Y29udicgfFxuJy4vYXZjb252JyB8XG4nZmZtcGVnLXN0YXRpYycgfFxuJ0BmZm1wZWctaW5zdGFsbGVyL2ZmbXBlZycgfFxuJ0Bub2RlLWZmbXBlZy9ub2RlLWZmbXBlZy1pbnN0YWxsZXInIHxcbidmZm1wZWctYmluYXJpZXMnO1xuXG5leHBvcnQgdHlwZSBGRm1wZWdDYWxsYmFjazxBcmdzIGV4dGVuZHMgQXJyYXk8dW5rbm93bj4+ID0gKFxuLi4uYXJnczogQXJncylcbj0+IHVua25vd247XG5cbi8qKlxuICogRkZtcGVnIHNvdXJjZSBjb25maWd1cmF0aW9uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRkZtcGVnU291cmNlIHtcbiAgLyoqIE5hbWUgb3IgcGF0aCBvZiB0aGUgRkZtcGVnIGV4ZWN1dGFibGUgKi9cbiAgbmFtZTogRkZtcGVnTGliO1xuICAvKiogV2hldGhlciB0aGlzIHNvdXJjZSBpcyBhIE5vZGUuanMgbW9kdWxlICovXG4gIG1vZHVsZTogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZXNvbHZlZEZGbXBlZ1NvdXJjZSBleHRlbmRzIEZGbXBlZ1NvdXJjZSB7XG4gIHBhdGg6IHN0cmluZztcbiAgdmVyc2lvbjogc3RyaW5nO1xuICBjb21tYW5kOiBzdHJpbmc7XG4gIHJlc3VsdDogc3RyaW5nO1xufVxuXG4vKipcbiAqIENvbXBhcmVzIGFuZCB1cGRhdGVzIEZGbXBlZyBmbGFncyBhcyBuZWVkZWRcbiAqIEBwYXJhbSBvbGRGbGFncyBUaGUgb2xkIGZsYWdzXG4gKiBAcGFyYW0gbmV3RmxhZ3MgVGhlIG5ldyBmbGFnc1xuICogQHJldHVybnMgVGhlIHVwZGF0ZWQgZmxhZ3NcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNoYW5nZUZGbXBlZ0ZsYWdzKG9sZEZsYWdzOiBzdHJpbmdbXSwgbmV3RmxhZ3M6IHN0cmluZ1tdKSB7XG4gIGNvbnN0IHVwZGF0ZWRGbGFncyA9IFsuLi5vbGRGbGFnc107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBuZXdGbGFncy5sZW5ndGg7IGkrKykge1xuICAgIGNvbnN0IGtleSA9IG5ld0ZsYWdzW2ldO1xuICAgIGNvbnN0IHZhbHVlID0gbmV3RmxhZ3NbaSArIDFdO1xuXG4gICAgY29uc3Qgb2xkSW5kZXggPSB1cGRhdGVkRmxhZ3MuaW5kZXhPZihrZXkpO1xuXG4gICAgaWYgKG9sZEluZGV4ICE9PSAtMSkge1xuICAgICAgaWYgKHZhbHVlICYmICF2YWx1ZS5zdGFydHNXaXRoKCctJykpIHtcbiAgICAgICAgdXBkYXRlZEZsYWdzW29sZEluZGV4ICsgMV0gPSB2YWx1ZTtcbiAgICAgICAgaSsrO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdXBkYXRlZEZsYWdzLnNwbGljZShvbGRJbmRleCwgMSk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmICh2YWx1ZSAmJiAhdmFsdWUuc3RhcnRzV2l0aCgnLScpKSB7XG4gICAgICAgIHVwZGF0ZWRGbGFncy5wdXNoKGtleSwgdmFsdWUpO1xuICAgICAgICBpKys7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1cGRhdGVkRmxhZ3MucHVzaChrZXkpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiB1cGRhdGVkRmxhZ3M7XG59IiwgIlxuXG5cblxuXG5cbmV4cG9ydCBjb25zdCB2ZXJzaW9uID0gLyogQF9fTUFDUk9fXyBnZXRWZXJzaW9uICovXCI3LjIuMFwiOyJdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTs7O0FDQUEsZ0NBSUE7QUFDQSx5QkFBc0M7QUFRdEMsSUFBTSxnQkFBZ0I7QUFFdEIsSUFBTSxvQkFBb0Isd0JBQUMsTUFBYyxnQkFBd0I7QUFDL0QsTUFBSSxDQUFDLEtBQU0sT0FBTSxJQUFJLE1BQU0scUJBQXFCLFdBQVcsRUFBRTtBQUM3RCxTQUFPO0FBQ1QsR0FIMEI7QUFLbkIsSUFBTSxVQUFOLE1BQU0sZ0JBQWUsMEJBQU87QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUEwSjFCLFlBQVksVUFBeUIsQ0FBQyxHQUFHO0FBQzlDLFVBQU0sT0FBTztBQXZCZjtBQUFBO0FBQUE7QUFBQSx3QkFBTztBQXlCTCxTQUFLLFVBQVUsUUFBTyxNQUFNLE9BQU87QUFFbkMsVUFBTSxTQUFTO0FBQUEsTUFDYixVQUFVLEtBQUs7QUFBQSxNQUNmLE1BQU0sS0FBSztBQUFBLE1BQ1gsS0FBSyxLQUFLO0FBQUEsTUFDVixRQUFRLEtBQUs7QUFBQSxNQUNiLFFBQVEsS0FBSztBQUFBLE1BQ2IsT0FBTyxLQUFLO0FBQUEsSUFDZDtBQUdBLFNBQUssaUJBQWlCLEtBQUssUUFBUTtBQUVuQyxTQUFLLGlCQUFpQixLQUFLLFFBQVE7QUFFbkMsU0FBSyxNQUFNLENBQUMsU0FBUyxLQUFLLEdBQUcsS0FBSyxPQUFPO0FBQ3pD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
|