UNPKG

cdk8s-cli

Version:

This is the command line tool for Cloud Development Kit (CDK) for Kubernetes (cdk8s).

316 lines • 48.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.generateHelmConstruct = exports.emitHelmHeader = exports.generateConstruct = exports.getPropsTypeName = exports.getConstructTypeName = exports.getTypeName = exports.emitHeader = void 0; const codemaker_1 = require("codemaker"); const json2jsii_1 = require("json2jsii"); const MANIFEST_STATIC_METHOD = 'manifest'; const GVK_STATIC = 'GVK'; /** * Emits the header for a generated imports file. * * @param custom - whether the header is being emitted for a custom resource * (imported from a CRD) or a core API object */ function emitHeader(code, custom) { code.line('// generated by cdk8s'); if (custom) { code.line('import { ApiObject, ApiObjectMetadata, GroupVersionKind } from \'cdk8s\';'); } else { code.line('import { ApiObject, GroupVersionKind } from \'cdk8s\';'); } code.line('import { Construct } from \'constructs\';'); code.line(); } exports.emitHeader = emitHeader; function getTypeName(custom, kind, version) { // add an API version postfix only if this is core API (`import k8s`). // TODO = what about the rest of the namespace? the same resource can exist in multiple // api groups (Ingress for example exists in 'extensions' and 'networking') const postfix = (custom || version === 'v1') ? '' : (0, codemaker_1.toPascalCase)(version); return `${kind}${postfix}`; } exports.getTypeName = getTypeName; function getConstructTypeName(def) { const prefix = def.prefix ?? ''; const suffix = def.suffix ?? ''; return json2jsii_1.TypeGenerator.normalizeTypeName(`${prefix}${getTypeName(def.custom, def.kind, def.version)}${suffix}`); } exports.getConstructTypeName = getConstructTypeName; function getPropsTypeName(def) { const constructName = getConstructTypeName(def); return json2jsii_1.TypeGenerator.normalizeTypeName(`${constructName}Props`); } exports.getPropsTypeName = getPropsTypeName; function generateConstruct(typegen, def) { const constructName = getConstructTypeName(def); if (def.custom) { typegen.emitCustomType('ApiObjectMetadata', () => { }); } typegen.emitCustomType(constructName, code => { const schema = def.schema; // `propsTypeName` could also be "any" if we can't parse the schema for some reason const propsTypeName = emitPropsStruct(); const groupPrefix = def.group ? `${def.group}/` : ''; const hasRequired = hasRequiredProps(schema); const defaultProps = hasRequired ? '' : ' = {}'; emitConstruct(); function emitPropsStruct() { const propsSchema = createPropsStructSchema(); const propsStructName = getPropsTypeName(def); return typegen.emitType(propsStructName, propsSchema, def.fqn); } function createPropsStructSchema() { const copy = { ...def.schema || {} }; const props = copy.properties = copy.properties || {}; delete props.apiVersion; delete props.kind; delete props.status; delete copy['x-kubernetes-group-version-kind']; copy.required = copy.required || []; if (Array.isArray(copy.required)) { copy.required = copy.required.filter(x => x !== 'apiVersion' && x !== 'kind' && x !== 'status'); } if (def.custom) { // add "metadata" field for all CRDs, overriding any existing typings copy.properties.metadata = { $ref: '#/definitions/ApiObjectMetadata' }; } // reorder top-level keys so that we have "metadata" first and then all the rest // This matches the behavior in the ApiObject's toJson function (https://github.com/cdk8s-team/cdk8s-core/blob/58fb8c0882ddd95a9b9dedb4107e12f601443cf4/src/api-object.ts#L185) const result = {}; for (const k of ['metadata', ...Object.keys(copy.properties)]) { if (k in copy.properties) { result[k] = copy.properties[k]; } } copy.properties = result; return copy; } function emitConstruct() { code.line('/**'); code.line(` * ${def.schema?.description ?? ''}`); code.line(' *'); code.line(` * @schema ${def.fqn}`); code.line(' */'); code.openBlock(`export class ${constructName} extends ApiObject`); emitGVK(); code.line(''); emitManifestFactory(); code.line(''); emitInitializer(); code.line(''); emitToJson(); code.closeBlock(); } function emitGVK() { code.line('/**'); code.line(` * Returns the apiVersion and kind for "${def.fqn}"`); code.line(' */'); code.openBlock(`public static readonly ${GVK_STATIC}: GroupVersionKind =`); code.line(`apiVersion: '${groupPrefix}${def.version}',`); code.line(`kind: '${def.kind}',`); code.closeBlock(); } function emitInitializer() { code.line('/**'); code.line(` * Defines a "${def.fqn}" API object`); code.line(' * @param scope the scope in which to define this object'); code.line(' * @param id a scope-local name for the object'); code.line(' * @param props initialization props'); code.line(' */'); code.openBlock(`public constructor(scope: Construct, id: string, props: ${propsTypeName}${defaultProps})`); code.open('super(scope, id, {'); code.line(`...${constructName}.${GVK_STATIC},`); code.line('...props,'); code.close('});'); code.closeBlock(); } function emitManifestFactory() { code.line('/**'); code.line(` * Renders a Kubernetes manifest for "${def.fqn}".`); code.line(' *'); code.line(' * This can be used to inline resource manifests inside other objects (e.g. as templates).'); code.line(' *'); code.line(' * @param props initialization props'); code.line(' */'); code.openBlock(`public static ${MANIFEST_STATIC_METHOD}(props: ${propsTypeName}${defaultProps}): any`); code.open('return {'); code.line(`...${constructName}.${GVK_STATIC},`); code.line(`...toJson_${propsTypeName}(props),`); code.close('};'); code.closeBlock(); } function emitToJson() { code.line('/**'); code.line(' * Renders the object to Kubernetes JSON.'); code.line(' */'); code.openBlock('public override toJson(): any'); code.line('const resolved = super.toJson();'); code.line(); code.open('return {'); code.line(`...${constructName}.${GVK_STATIC},`); code.line(`...toJson_${propsTypeName}(resolved),`); code.close('};'); code.closeBlock(); } }); } exports.generateConstruct = generateConstruct; /** * Emit imports for generated helm construct * @param code CodeMaker istance */ function emitHelmHeader(code) { code.line('// generated by cdk8s'); code.line('import { Helm, HelmProps } from \'cdk8s\';'); code.line('import { Construct } from \'constructs\';'); code.line(); } exports.emitHelmHeader = emitHelmHeader; function generateHelmConstruct(typegen, def) { const noSpecialChars = def.chartName.replace(/([^\w ]|_)/g, ''); const chartName = json2jsii_1.TypeGenerator.normalizeTypeName(noSpecialChars); const schema = def.schema; const repoUrl = def.chartUrl; const chartVersion = def.chartVersion; // Create custom type typegen.emitCustomType(chartName, code => { let valuesInterface = `${chartName}Values`; if (schema !== undefined) { // Creating values interface valuesInterface = emitValuesInterface(); function emitValuesInterface() { const copyOfSchema = schema ? addAdditionalValuesToProps(schema) : undefined; if (copyOfSchema && copyOfSchema.properties) { // Sub charts or dependencies for (const dependency of def.chartDependencies) { copyOfSchema.properties[dependency] = { type: 'object', additionalProperties: { type: 'object' } }; } copyOfSchema.properties.global = { type: 'object', additionalProperties: { type: 'object' } }; copyOfSchema.properties.additionalValues = { type: 'object', description: 'Values that are not available in values.schema.json will not be code generated. You can add such values to this property.', additionalProperties: { type: 'object' }, }; } return typegen.emitType(valuesInterface, copyOfSchema, def.fqn); } function addAdditionalValuesToProps(schma) { const tempSchema = schma; if (!tempSchema.properties) { return tempSchema; } Object.values(tempSchema.properties).forEach((prop) => { if (prop.type !== 'object') { return; } if (prop.properties) { prop.properties.additionalValues = { type: 'object', description: 'Values that are not available in values.schema.json will not be code generated. You can add such values to this property.', additionalProperties: { type: 'object' }, }; addAdditionalValuesToProps(prop); } }); return tempSchema; } } // Creating construct properties emitPropsInterface(); code.line(); // Creating construct for helm chart emitConstruct(); function emitPropsInterface() { code.openBlock(`export interface ${chartName}Props`); code.line('readonly namespace?: string;'); code.line('readonly releaseName?: string;'); code.line('readonly helmExecutable?: string;'); code.line('readonly helmFlags?: string[];'); if (schema === undefined) { code.line('readonly values?: { [key: string]: any };'); } else { const doValuesHaveReqProps = hasRequiredProps(schema) ? '' : '?'; code.line(`readonly values${doValuesHaveReqProps}: ${valuesInterface};`); } code.closeBlock(); } function emitConstruct() { code.openBlock(`export class ${chartName} extends Construct`); emitInitializer(); code.line(); emitAdditionalValuesFlattenFunc(); code.closeBlock(); } function emitInitializer() { const propsDefinition = schema && hasRequiredProps(schema) ? `${chartName}Props` : `${chartName}Props = {}`; code.openBlock(`public constructor(scope: Construct, id: string, props: ${propsDefinition})`); code.line('super(scope, id);'); code.line('let updatedProps = {};'); code.line(); code.openBlock('if (props.values)'); if (schema) { code.line(`const values = toJson_${valuesInterface}(props.values);`); } else { code.line('const values = props.values;'); } code.openBlock('if (values)'); code.line('const { additionalValues, ...valuesWithoutAdditionalValues } = values;'); code.open('updatedProps = {'); code.line('...props,'); code.open('values: {'); code.line('...this.flattenAdditionalValues(valuesWithoutAdditionalValues),'); code.line('...additionalValues,'); code.close('},'); code.close('};'); code.closeBlock(); code.closeBlock(); code.line(); code.open('const finalProps: HelmProps = {'); if (repoUrl.startsWith('oci://')) { code.line(`chart: \'${repoUrl}\',`); } else { code.line(`chart: \'${def.chartName}\',`); code.line(`repo: \'${repoUrl}\',`); } code.line(`version: \'${chartVersion}\',`); code.line('...(Object.keys(updatedProps).length !== 0 ? updatedProps : props),'); code.close('};'); code.line(); code.line('new Helm(this, \'Helm\', finalProps);'); code.closeBlock(); } function emitAdditionalValuesFlattenFunc() { code.openBlock('private flattenAdditionalValues(props: { [key: string]: any }): { [key: string]: any }'); code.open('for (let prop in props) {'); code.open('if (Array.isArray(props[prop])) {'); code.open('props[prop].map((item: any) => {'); code.open('if (typeof item === \'object\' && prop !== \'additionalValues\') {'); code.line('return this.flattenAdditionalValues(item);'); code.close('}'); code.line('return item;'); code.close('});'); code.close('}'); code.open('else if (typeof props[prop] === \'object\' && prop !== \'additionalValues\') {'); code.line('props[prop] = this.flattenAdditionalValues(props[prop]);'); code.close('}'); code.close('}'); code.line(); code.line('const { additionalValues, ...valuesWithoutAdditionalValues } = props;'); code.line(); code.open('return {'); code.line('...valuesWithoutAdditionalValues,'); code.line('...additionalValues,'); code.close('};'); code.closeBlock(); } }); } exports.generateHelmConstruct = generateHelmConstruct; function hasRequiredProps(schema) { return schema?.required && Array.isArray(schema.required) && schema.required.length > 0; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29kZWdlbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9pbXBvcnQvY29kZWdlbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSx5Q0FBb0Q7QUFJcEQseUNBQTBDO0FBRTFDLE1BQU0sc0JBQXNCLEdBQUcsVUFBVSxDQUFDO0FBQzFDLE1BQU0sVUFBVSxHQUFHLEtBQUssQ0FBQztBQStCekI7Ozs7O0dBS0c7QUFDSCxTQUFnQixVQUFVLENBQUMsSUFBZSxFQUFFLE1BQWU7SUFDekQsSUFBSSxDQUFDLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDO0lBQ25DLElBQUksTUFBTSxFQUFFO1FBQ1YsSUFBSSxDQUFDLElBQUksQ0FBQywyRUFBMkUsQ0FBQyxDQUFDO0tBQ3hGO1NBQU07UUFDTCxJQUFJLENBQUMsSUFBSSxDQUFDLHdEQUF3RCxDQUFDLENBQUM7S0FDckU7SUFDRCxJQUFJLENBQUMsSUFBSSxDQUFDLDJDQUEyQyxDQUFDLENBQUM7SUFDdkQsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO0FBQ2QsQ0FBQztBQVRELGdDQVNDO0FBRUQsU0FBZ0IsV0FBVyxDQUFDLE1BQWUsRUFBRSxJQUFZLEVBQUUsT0FBZTtJQUN4RSxzRUFBc0U7SUFDdEUsdUZBQXVGO0lBQ3ZGLDJFQUEyRTtJQUMzRSxNQUFNLE9BQU8sR0FBRyxDQUFDLE1BQU0sSUFBSSxPQUFPLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBQSx3QkFBWSxFQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQzFFLE9BQU8sR0FBRyxJQUFJLEdBQUcsT0FBTyxFQUFFLENBQUM7QUFDN0IsQ0FBQztBQU5ELGtDQU1DO0FBRUQsU0FBZ0Isb0JBQW9CLENBQUMsR0FBd0I7SUFDM0QsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLE1BQU0sSUFBSSxFQUFFLENBQUM7SUFDaEMsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLE1B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LENBQUMsQ0FBQztZQUNqQixJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDcEIsQ0FBQztJQUNILENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQztBQXpLRCxzREF5S0M7QUFFRCxTQUFTLGdCQUFnQixDQUFDLE1BQW1CO0lBQzNDLE9BQU8sTUFBTSxFQUFFLFFBQVEsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsSUFBSSxNQUFNLENBQUMsUUFBUSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7QUFDMUYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvZGVNYWtlciwgdG9QYXNjYWxDYXNlIH0gZnJvbSAnY29kZW1ha2VyJztcbi8vIHdlIGp1c3QgbmVlZCB0aGUgdHlwZXMgZnJvbSBqc29uLXNjaGVtYVxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgSlNPTlNjaGVtYTQgfSBmcm9tICdqc29uLXNjaGVtYSc7XG5pbXBvcnQgeyBUeXBlR2VuZXJhdG9yIH0gZnJvbSAnanNvbjJqc2lpJztcblxuY29uc3QgTUFOSUZFU1RfU1RBVElDX01FVEhPRCA9ICdtYW5pZmVzdCc7XG5jb25zdCBHVktfU1RBVElDID0gJ0dWSyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgQXBpT2JqZWN0RGVmaW5pdGlvbiB7XG4gIHJlYWRvbmx5IGZxbjogc3RyaW5nO1xuICByZWFkb25seSBncm91cDogc3RyaW5nO1xuICByZWFkb25seSB2ZXJzaW9uOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGtpbmQ6IHN0cmluZztcbiAgcmVhZG9ubHkgc2NoZW1hOiBKU09OU2NoZW1hNDtcblxuICAvKipcbiAgICogSXMgdGhpcyBpcyBhIGN1c3RvbSByZXNvdXJjZSAoaW1wb3J0ZWQgZnJvbSBhIENSRCkgb3IgYSBjb3JlIEFQSSBvYmplY3Q/XG4gICAqL1xuICByZWFkb25seSBjdXN0b206IGJvb2xlYW47XG5cbiAgLypcbiAgICogSW5kaWNhdGVzIGlmIGEgcHJlZml4IHNob3VsZCBiZSBhZGRlZCB0byB0aGUgY29uc3RydWN0IGNsYXNzIG5hbWUuIEZvclxuICAgKiBleGFtcGxlLCBmb3IgbmF0aXZlIGs4cyBhcGkgb2JqZWN0cywgd2UgYWRkIGBLdWJlYCBieSBkZWZhdWx0LlxuICAgKlxuICAgKiBAZGVmYXVsdCBcIlwiXG4gICAqL1xuICByZWFkb25seSBwcmVmaXg/OiBzdHJpbmc7XG5cbiAgLypcbiAgICogSW5kaWNhdGVzIGlmIGEgc3VmZml4IHNob3VsZCBiZSBhZGRlZCB0byB0aGUgY29uc3RydWN0IGNsYXNzIG5hbWUuIEZvclxuICAgKiBleGFtcGxlLCBmb3IgbXVsdGktdmVyc2lvbmVkIGNyZHMsIHdlIGFkZCB0aGUgdmVyc2lvbiBhcyB0aGUgc3VmZml4LlxuICAgKlxuICAgKiBAZGVmYXVsdCBcIlwiXG4gICAqL1xuICByZWFkb25seSBzdWZmaXg/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogRW1pdHMgdGhlIGhlYWRlciBmb3IgYSBnZW5lcmF0ZWQgaW1wb3J0cyBmaWxlLlxuICpcbiAqIEBwYXJhbSBjdXN0b20gLSB3aGV0aGVyIHRoZSBoZWFkZXIgaXMgYmVpbmcgZW1pdHRlZCBmb3IgYSBjdXN0b20gcmVzb3VyY2VcbiAqIChpbXBvcnRlZCBmcm9tIGEgQ1JEKSBvciBhIGNvcmUgQVBJIG9iamVjdFxuICovXG5leHBvcnQgZnVuY3Rpb24gZW1pdEhlYWRlcihjb2RlOiBDb2RlTWFrZXIsIGN1c3RvbTogYm9vbGVhbikge1xuICBjb2RlLmxpbmUoJy8vIGdlbmVyYXRlZCBieSBjZGs4cycpO1xuICBpZiAoY3VzdG9tKSB7XG4gICAgY29kZS5saW5lKCdpbXBvcnQgeyBBcGlPYmplY3QsIEFwaU9iamVjdE1ldGFkYXRhLCBHcm91cFZlcnNpb25LaW5kIH0gZnJvbSBcXCdjZGs4c1xcJzsnKTtcbiAgfSBlbHNlIHtcbiAgICBjb2RlLmxpbmUoJ2ltcG9ydCB7IEFwaU9iamVjdCwgR3JvdXBWZXJzaW9uS2luZCB9IGZyb20gXFwnY2RrOHNcXCc7Jyk7XG4gIH1cbiAgY29kZS5saW5lKCdpbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tIFxcJ2NvbnN0cnVjdHNcXCc7Jyk7XG4gIGNvZGUubGluZSgpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0VHlwZU5hbWUoY3VzdG9tOiBib29sZWFuLCBraW5kOiBzdHJpbmcsIHZlcnNpb246IHN0cmluZykge1xuICAvLyBhZGQgYW4gQVBJIHZlcnNpb24gcG9zdGZpeCBvbmx5IGlmIHRoaXMgaXMgY29yZSBBUEkgKGBpbXBvcnQgazhzYCkuXG4gIC8vIFRPRE8gPSB3aGF0IGFib3V0IHRoZSByZXN0IG9mIHRoZSBuYW1lc3BhY2U/IHRoZSBzYW1lIHJlc291cmNlIGNhbiBleGlzdCBpbiBtdWx0aXBsZVxuICAvLyBhcGkgZ3JvdXBzIChJbmdyZXNzIGZvciBleGFtcGxlIGV4aXN0cyBpbiAnZXh0ZW5zaW9ucycgYW5kICduZXR3b3JraW5nJylcbiAgY29uc3QgcG9zdGZpeCA9IChjdXN0b20gfHwgdmVyc2lvbiA9PT0gJ3YxJykgPyAnJyA6IHRvUGFzY2FsQ2FzZSh2ZXJzaW9uKTtcbiAgcmV0dXJuIGAke2tpbmR9JHtwb3N0Zml4fWA7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRDb25zdHJ1Y3RUeXBlTmFtZShkZWY6IEFwaU9iamVjdERlZmluaXRpb24pIHtcbiAgY29uc3QgcHJlZml4ID0gZGVmLnByZWZpeCA/PyAnJztcbiAgY29uc3Qgc3VmZml4ID0gZGVmLnN1ZmZpeCA/PyAnJztcbiAgcmV0dXJuIFR5cGVHZW5lcmF0b3Iubm9ybWFsaXplVHlwZU5hbWUoYCR7cHJlZml4fSR7Z2V0VHlwZU5hbWUoZGVmLmN1c3RvbSwgZGVmLmtpbmQsIGRlZi52ZXJzaW9uKX0ke3N1ZmZpeH1gKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFByb3BzVHlwZU5hbWUoZGVmOiBBcGlPYmplY3REZWZpbml0aW9uKSB7XG4gIGNvbnN0IGNvbnN0cnVjdE5hbWUgPSBnZXRDb25zdHJ1Y3RUeXBlTmFtZShkZWYpO1xuICByZXR1cm4gVHlwZUdlbmVyYXRvci5ub3JtYWxpemVUeXBlTmFtZShgJHtjb25zdHJ1Y3ROYW1lfVByb3BzYCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZW5lcmF0ZUNvbnN0cnVjdCh0eXBlZ2VuOiBUeXBlR2VuZXJhdG9yLCBkZWY6IEFwaU9iamVjdERlZmluaXRpb24pIHtcbiAgY29uc3QgY29uc3RydWN0TmFtZSA9IGdldENvbnN0cnVjdFR5cGVOYW1lKGRlZik7XG5cbiAgaWYgKGRlZi5jdXN0b20pIHtcbiAgICB0eXBlZ2VuLmVtaXRDdXN0b21UeXBlKCdBcGlPYmplY3RNZXRhZGF0YScsICgpID0+IHt9KTtcbiAgfVxuXG4gIHR5cGVnZW4uZW1pdEN1c3RvbVR5cGUoY29uc3RydWN0TmFtZSwgY29kZSA9PiB7XG4gICAgY29uc3Qgc2NoZW1hID0gZGVmLnNjaGVtYTtcblxuICAgIC8vIGBwcm9wc1R5cGVOYW1lYCBjb3VsZCBhbHNvIGJlIFwiYW55XCIgaWYgd2UgY2FuJ3QgcGFyc2UgdGhlIHNjaGVtYSBmb3Igc29tZSByZWFzb25cbiAgICBjb25zdCBwcm9wc1R5cGVOYW1lID0gZW1pdFByb3BzU3RydWN0KCk7XG4gICAgY29uc3QgZ3JvdXBQcmVmaXggPSBkZWYuZ3JvdXAgPyBgJHtkZWYuZ3JvdXB9L2AgOiAnJztcbiAgICBjb25zdCBoYXNSZXF1aXJlZCA9IGhhc1JlcXVpcmVkUHJvcHMoc2NoZW1hKTtcbiAgICBjb25zdCBkZWZhdWx0UHJvcHMgPSBoYXNSZXF1aXJlZCA/ICcnIDogJyA9IHt9JztcbiAgICBlbWl0Q29uc3RydWN0KCk7XG5cbiAgICBmdW5jdGlvbiBlbWl0UHJvcHNTdHJ1Y3QoKSB7XG4gICAgICBjb25zdCBwcm9wc1NjaGVtYSA9IGNyZWF0ZVByb3BzU3RydWN0U2NoZW1hKCk7XG4gICAgICBjb25zdCBwcm9wc1N0cnVjdE5hbWUgPSBnZXRQcm9wc1R5cGVOYW1lKGRlZik7XG4gICAgICByZXR1cm4gdHlwZWdlbi5lbWl0VHlwZShwcm9wc1N0cnVjdE5hbWUsIHByb3BzU2NoZW1hLCBkZWYuZnFuKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjcmVhdGVQcm9wc1N0cnVjdFNjaGVtYSgpIHtcbiAgICAgIGNvbnN0IGNvcHk6IEpTT05TY2hlbWE0ID0geyAuLi5kZWYuc2NoZW1hIHx8IHt9IH07XG4gICAgICBjb25zdCBwcm9wcyA9IGNvcHkucHJvcGVydGllcyA9IGNvcHkucHJvcGVydGllcyB8fCB7fTtcbiAgICAgIGRlbGV0ZSBwcm9wcy5hcGlWZXJzaW9uO1xuICAgICAgZGVsZXRlIHByb3BzLmtpbmQ7XG4gICAgICBkZWxldGUgcHJvcHMuc3RhdHVzO1xuICAgICAgZGVsZXRlIGNvcHlbJ3gta3ViZXJuZXRlcy1ncm91cC12ZXJzaW9uLWtpbmQnXTtcblxuICAgICAgY29weS5yZXF1aXJlZCA9IGNvcHkucmVxdWlyZWQgfHwgW107XG5cbiAgICAgIGlmIChBcnJheS5pc0FycmF5KGNvcHkucmVxdWlyZWQpKSB7XG4gICAgICAgIGNvcHkucmVxdWlyZWQgPSBjb3B5LnJlcXVpcmVkLmZpbHRlcih4ID0+IHggIT09ICdhcGlWZXJzaW9uJyAmJiB4ICE9PSAna2luZCcgJiYgeCAhPT0gJ3N0YXR1cycpO1xuICAgICAgfVxuXG4gICAgICBpZiAoZGVmLmN1c3RvbSkge1xuICAgICAgICAvLyBhZGQgXCJtZXRhZGF0YVwiIGZpZWxkIGZvciBhbGwgQ1JEcywgb3ZlcnJpZGluZyBhbnkgZXhpc3RpbmcgdHlwaW5nc1xuICAgICAgICBjb3B5LnByb3BlcnRpZXMubWV0YWRhdGEgPSB7ICRyZWY6ICcjL2RlZmluaXRpb25zL0FwaU9iamVjdE1ldGFkYXRhJyB9O1xuICAgICAgfVxuXG4gICAgICAvLyByZW9yZGVyIHRvcC1sZXZlbCBrZXlzIHNvIHRoYXQgd2UgaGF2ZSBcIm1ldGFkYXRhXCIgZmlyc3QgYW5kIHRoZW4gYWxsIHRoZSByZXN0XG4gICAgICAvLyBUaGlzIG1hdGNoZXMgdGhlIGJlaGF2aW9yIGluIHRoZSBBcGlPYmplY3QncyB0b0pzb24gZnVuY3Rpb24gKGh0dHBzOi8vZ2l0aHViLmNvbS9jZGs4cy10ZWFtL2NkazhzLWNvcmUvYmxvYi81OGZiOGMwODgyZGRkOTVhOWI5ZGVkYjQxMDdlMTJmNjAxNDQzY2Y0L3NyYy9hcGktb2JqZWN0LnRzI0wxODUpXG4gICAgICBjb25zdCByZXN1bHQ6IGFueSA9IHt9O1xuICAgICAgZm9yIChjb25zdCBrIG9mIFsnbWV0YWRhdGEnLCAuLi5PYmplY3Qua2V5cyhjb3B5LnByb3BlcnRpZXMpXSkge1xuICAgICAgICBpZiAoayBpbiBjb3B5LnByb3BlcnRpZXMpIHtcbiAgICAgICAgICByZXN1bHRba10gPSBjb3B5LnByb3BlcnRpZXNba107XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY29weS5wcm9wZXJ0aWVzID0gcmVzdWx0O1xuICAgICAgcmV0dXJuIGNvcHk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZW1pdENvbnN0cnVjdCgpIHtcbiAgICAgIGNvZGUubGluZSgnLyoqJyk7XG4gICAgICBjb2RlLmxpbmUoYCAqICR7ZGVmLnNjaGVtYT8uZGVzY3JpcHRpb24gPz8gJyd9YCk7XG4gICAgICBjb2RlLmxpbmUoJyAqJyk7XG4gICAgICBjb2RlLmxpbmUoYCAqIEBzY2hlbWEgJHtkZWYuZnFufWApO1xuICAgICAgY29kZS5saW5lKCcgKi8nKTtcbiAgICAgIGNvZGUub3BlbkJsb2NrKGBleHBvcnQgY2xhc3MgJHtjb25zdHJ1Y3ROYW1lfSBleHRlbmRzIEFwaU9iamVjdGApO1xuXG4gICAgICBlbWl0R1ZLKCk7XG5cbiAgICAgIGNvZGUubGluZSgnJyk7XG5cbiAgICAgIGVtaXRNYW5pZmVzdEZhY3RvcnkoKTtcblxuICAgICAgY29kZS5saW5lKCcnKTtcblxuICAgICAgZW1pdEluaXRpYWxpemVyKCk7XG5cbiAgICAgIGNvZGUubGluZSgnJyk7XG5cbiAgICAgIGVtaXRUb0pzb24oKTtcblxuICAgICAgY29kZS5jbG9zZUJsb2NrKCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZW1pdEdWSygpIHtcbiAgICAgIGNvZGUubGluZSgnLyoqJyk7XG4gICAgICBjb2RlLmxpbmUoYCAqIFJldHVybnMgdGhlIGFwaVZlcnNpb24gYW5kIGtpbmQgZm9yIFwiJHtkZWYuZnFufVwiYCk7XG4gICAgICBjb2RlLmxpbmUoJyAqLycpO1xuICAgICAgY29kZS5vcGVuQmxvY2soYHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgJHtHVktfU1RBVElDfTogR3JvdXBWZXJzaW9uS2luZCA9YCk7XG4gICAgICBjb2RlLmxpbmUoYGFwaVZlcnNpb246ICcke2dyb3VwUHJlZml4fSR7ZGVmLnZlcnNpb259JyxgKTtcbiAgICAgIGNvZGUubGluZShga2luZDogJyR7ZGVmLmtpbmR9JyxgKTtcbiAgICAgIGNvZGUuY2xvc2VCbG9jaygpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGVtaXRJbml0aWFsaXplcigpIHtcblxuICAgICAgY29kZS5saW5lKCcvKionKTtcbiAgICAgIGNvZGUubGluZShgICogRGVmaW5lcyBhIFwiJHtkZWYuZnFufVwiIEFQSSBvYmplY3RgKTtcbiAgICAgIGNvZGUubGluZSgnICogQHBhcmFtIHNjb3BlIHRoZSBzY29wZSBpbiB3aGljaCB0byBkZWZpbmUgdGhpcyBvYmplY3QnKTtcbiAgICAgIGNvZGUubGluZSgnICogQHBhcmFtIGlkIGEgc2NvcGUtbG9jYWwgbmFtZSBmb3IgdGhlIG9iamVjdCcpO1xuICAgICAgY29kZS5saW5lKCcgKiBAcGFyYW0gcHJvcHMgaW5pdGlhbGl6YXRpb24gcHJvcHMnKTtcbiAgICAgIGNvZGUubGluZSgnICovJyk7XG5cbiAgICAgIGNvZGUub3BlbkJsb2NrKGBwdWJsaWMgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6ICR7cHJvcHNUeXBlTmFtZX0ke2RlZmF1bHRQcm9wc30pYCk7XG5cbiAgICAgIGNvZGUub3Blbignc3VwZXIoc2NvcGUsIGlkLCB7Jyk7XG4gICAgICBjb2RlLmxpbmUoYC4uLiR7Y29uc3RydWN0TmFtZX0uJHtHVktfU1RBVElDfSxgKTtcbiAgICAgIGNvZGUubGluZSgnLi4ucHJvcHMsJyk7XG4gICAgICBjb2RlLmNsb3NlKCd9KTsnKTtcblxuICAgICAgY29kZS5jbG9zZUJsb2NrKCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZW1pdE1hbmlmZXN0RmFjdG9yeSgpIHtcbiAgICAgIGNvZGUubGluZSgnLyoqJyk7XG4gICAgICBjb2RlLmxpbmUoYCAqIFJlbmRlcnMgYSBLdWJlcm5ldGVzIG1hbmlmZXN0IGZvciBcIiR7ZGVmLmZxbn1cIi5gKTtcbiAgICAgIGNvZGUubGluZSgnIConKTtcbiAgICAgIGNvZGUubGluZSgnICogVGhpcyBjYW4gYmUgdXNlZCB0byBpbmxpbmUgcmVzb3VyY2UgbWFuaWZlc3RzIGluc2lkZSBvdGhlciBvYmplY3RzIChlLmcuIGFzIHRlbXBsYXRlcykuJyk7XG4gICAgICBjb2RlLmxpbmUoJyAqJyk7XG4gICAgICBjb2RlLmxpbmUoJyAqIEBwYXJhbSBwcm9wcyBpbml0aWFsaXphdGlvbiBwcm9wcycpO1xuICAgICAgY29kZS5saW5lKCcgKi8nKTtcblxuICAgICAgY29kZS5vcGVuQmxvY2soYHB1YmxpYyBzdGF0aWMgJHtNQU5JRkVTVF9TVEFUSUNfTUVUSE9EfShwcm9wczogJHtwcm9wc1R5cGVOYW1lfSR7ZGVmYXVsdFByb3BzfSk6IGFueWApO1xuICAgICAgY29kZS5vcGVuKCdyZXR1cm4geycpO1xuICAgICAgY29kZS5saW5lKGAuLi4ke2NvbnN0cnVjdE5hbWV9LiR7R1ZLX1NUQVRJQ30sYCk7XG4gICAgICBjb2RlLmxpbmUoYC4uLnRvSnNvbl8ke3Byb3BzVHlwZU5hbWV9KHByb3BzKSxgKTtcbiAgICAgIGNvZGUuY2xvc2UoJ307Jyk7XG4gICAgICBjb2RlLmNsb3NlQmxvY2soKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBlbWl0VG9Kc29uKCkge1xuICAgICAgY29kZS5saW5lKCcvKionKTtcbiAgICAgIGNvZGUubGluZSgnICogUmVuZGVycyB0aGUgb2JqZWN0IHRvIEt1YmVybmV0ZXMgSlNPTi4nKTtcbiAgICAgIGNvZGUubGluZSgnICovJyk7XG4gICAgICBjb2RlLm9wZW5CbG9jaygncHVibGljIG92ZXJyaWRlIHRvSnNvbigpOiBhbnknKTtcbiAgICAgIGNvZGUubGluZSgnY29uc3QgcmVzb2x2ZWQgPSBzdXBlci50b0pzb24oKTsnKTtcbiAgICAgIGNvZGUubGluZSgpO1xuICAgICAgY29kZS5vcGVuKCdyZXR1cm4geycpO1xuICAgICAgY29kZS5saW5lKGAuLi4ke2NvbnN0cnVjdE5hbWV9LiR7R1ZLX1NUQVRJQ30sYCk7XG4gICAgICBjb2RlLmxpbmUoYC4uLnRvSnNvbl8ke3Byb3BzVHlwZU5hbWV9KHJlc29sdmVkKSxgKTtcbiAgICAgIGNvZGUuY2xvc2UoJ307Jyk7XG4gICAgICBjb2RlLmNsb3NlQmxvY2soKTtcbiAgICB9XG4gIH0pO1xufVxuXG4vKipcbiAqIEVtaXQgaW1wb3J0cyBmb3IgZ2VuZXJhdGVkIGhlbG0gY29uc3RydWN0XG4gKiBAcGFyYW0gY29kZSBDb2RlTWFrZXIgaXN0YW5jZVxuICovXG5leHBvcnQgZnVuY3Rpb24gZW1pdEhlbG1IZWFkZXIoY29kZTogQ29kZU1ha2VyKSB7XG4gIGNvZGUubGluZSgnLy8gZ2VuZXJhdGVkIGJ5IGNkazhzJyk7XG4gIGNvZGUubGluZSgnaW1wb3J0IHsgSGVsbSwgSGVsbVByb3BzIH0gZnJvbSBcXCdjZGs4c1xcJzsnKTtcbiAgY29kZS5saW5lKCdpbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tIFxcJ2NvbnN0cnVjdHNcXCc7Jyk7XG4gIGNvZGUubGluZSgpO1xufVxuXG4vKipcbiAqIEhlbG0gT2JqZWN0IERlZmluaXRpb25cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBIZWxtT2JqZWN0RGVmaW5pdGlvbiB7XG4gIC8qKlxuICAgKiBgdmFsdWVzLnNjaGVtYS5qc29uYCBmb3IgdGhlIGhlbG0gY2hhcnRcbiAgICovXG4gIHJlYWRvbmx5IHNjaGVtYTogSlNPTlNjaGVtYTQgfCB1bmRlZmluZWQ7XG4gIC8qKlxuICAgKiBDaGFydCBuYW1lXG4gICAqL1xuICByZWFkb25seSBjaGFydE5hbWU6IHN0cmluZztcbiAgLyoqXG4gICAqIENoYXJ0IHVybFxuICAgKi9cbiAgcmVhZG9ubHkgY2hhcnRVcmw6IHN0cmluZztcbiAgLyoqXG4gICAqIENoYXJ0IHZlcnNpb25cbiAgICovXG4gIHJlYWRvbmx5IGNoYXJ0VmVyc2lvbjogc3RyaW5nO1xuICAvKipcbiAgICogQ2hhcnQgZGVwZW5kZW5jaWVzXG4gICAqL1xuICByZWFkb25seSBjaGFydERlcGVuZGVuY2llczogc3RyaW5nW107XG4gIC8qKlxuICAgKiBGdWxseSBxdWFsaWZpZWQgbmFtZSBmb3IgdGhlIGNvbnN0cnVjdFxuICAgKi9cbiAgcmVhZG9ubHkgZnFuPzogc3RyaW5nO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2VuZXJhdGVIZWxtQ29uc3RydWN0KHR5cGVnZW46IFR5cGVHZW5lcmF0b3IsIGRlZjogSGVsbU9iamVjdERlZmluaXRpb24pIHtcbiAgY29uc3Qgbm9TcGVjaWFsQ2hhcnMgPSBkZWYuY2hhcnROYW1lLnJlcGxhY2UoLyhbXlxcdyBdfF8pL2csICcnKTtcbiAgY29uc3QgY2hhcnROYW1lID0gVHlwZUdlbmVyYXRvci5ub3JtYWxpemVUeXBlTmFtZShub1NwZWNpYWxDaGFycyk7XG4gIGNvbnN0IHNjaGVtYSA9IGRlZi5zY2hlbWE7XG4gIGNvbnN0IHJlcG9VcmwgPSBkZWYuY2hhcnRVcmw7XG4gIGNvbnN0IGNoYXJ0VmVyc2lvbiA9IGRlZi5jaGFydFZlcnNpb247XG5cbiAgLy8gQ3JlYXRlIGN1c3RvbSB0eXBlXG4gIHR5cGVnZW4uZW1pdEN1c3RvbVR5cGUoY2hhcnROYW1lLCBjb2RlID0+IHtcblxuICAgIGxldCB2YWx1ZXNJbnRlcmZhY2UgPSBgJHtjaGFydE5hbWV9VmFsdWVzYDtcbiAgICBpZiAoc2NoZW1hICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIC8vIENyZWF0aW5nIHZhbHVlcyBpbnRlcmZhY2VcbiAgICAgIHZhbHVlc0ludGVyZmFjZSA9IGVtaXRWYWx1ZXNJbnRlcmZhY2UoKTtcblxuICAgICAgZnVuY3Rpb24gZW1pdFZhbHVlc0ludGVyZmFjZSgpIHtcblxuICAgICAgICBjb25zdCBjb3B5T2ZTY2hlbWEgPSBzY2hlbWEgPyBhZGRBZGRpdGlvbmFsVmFsdWVzVG9Qcm9wcyhzY2hlbWEpIDogdW5kZWZpbmVkO1xuXG4gICAgICAgIGlmIChjb3B5T2ZTY2hlbWEgJiYgY29weU9mU2NoZW1hLnByb3BlcnRpZXMpIHtcbiAgICAgICAgICAvLyBTdWIgY2hhcnRzIG9yIGRlcGVuZGVuY2llc1xuICAgICAgICAgIGZvciAoY29uc3QgZGVwZW5kZW5jeSBvZiBkZWYuY2hhcnREZXBlbmRlbmNpZXMpIHtcbiAgICAgICAgICAgIGNvcHlPZlNjaGVtYS5wcm9wZXJ0aWVzW2RlcGVuZGVuY3ldID0geyB0eXBlOiAnb2JqZWN0JywgYWRkaXRpb25hbFByb3BlcnRpZXM6IHsgdHlwZTogJ29iamVjdCcgfSB9O1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvcHlPZlNjaGVtYS5wcm9wZXJ0aWVzLmdsb2JhbCA9IHsgdHlwZTogJ29iamVjdCcsIGFkZGl0aW9uYWxQcm9wZXJ0aWVzOiB7IHR5cGU6ICdvYmplY3QnIH0gfTtcbiAgICAgICAgICBjb3B5T2ZTY2hlbWEucHJvcGVydGllcy5hZGRpdGlvbmFsVmFsdWVzID0ge1xuICAgICAgICAgICAgdHlwZTogJ29iamVjdCcsXG4gICAgICAgICAgICBkZXNjcmlwdGlvbjogJ1ZhbHVlcyB0aGF0IGFyZSBub3QgYXZhaWxhYmxlIGluIHZhbHVlcy5zY2hlbWEuanNvbiB3aWxsIG5vdCBiZSBjb2RlIGdlbmVyYXRlZC4gWW91IGNhbiBhZGQgc3VjaCB2YWx1ZXMgdG8gdGhpcyBwcm9wZXJ0eS4nLFxuICAgICAgICAgICAgYWRkaXRpb25hbFByb3BlcnRpZXM6IHsgdHlwZTogJ29iamVjdCcgfSxcbiAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHR5cGVnZW4uZW1pdFR5cGUodmFsdWVzSW50ZXJmYWNlLCBjb3B5T2ZTY2hlbWEsIGRlZi5mcW4pO1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBhZGRBZGRpdGlvbmFsVmFsdWVzVG9Qcm9wcyhzY2htYTogSlNPTlNjaGVtYTQpOiBKU09OU2NoZW1hNCB7XG4gICAgICAgIGNvbnN0IHRlbXBTY2hlbWEgPSBzY2htYTtcblxuICAgICAgICBpZiAoIXRlbXBTY2hlbWEucHJvcGVydGllcykge1xuICAgICAgICAgIHJldHVybiB0ZW1wU2NoZW1hO1xuICAgICAgICB9XG5cbiAgICAgICAgT2JqZWN0LnZhbHVlcyh0ZW1wU2NoZW1hLnByb3BlcnRpZXMpLmZvckVhY2goKHByb3ApID0+IHtcbiAgICAgICAgICBpZiAocHJvcC50eXBlICE9PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChwcm9wLnByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgIHByb3AucHJvcGVydGllcy5hZGRpdGlvbmFsVmFsdWVzID0ge1xuICAgICAgICAgICAgICB0eXBlOiAnb2JqZWN0JyxcbiAgICAgICAgICAgICAgZGVzY3JpcHRpb246ICdWYWx1ZXMgdGhhdCBhcmUgbm90IGF2YWlsYWJsZSBpbiB2YWx1ZXMuc2NoZW1hLmpzb24gd2lsbCBub3QgYmUgY29kZSBnZW5lcmF0ZWQuIFlvdSBjYW4gYWRkIHN1Y2ggdmFsdWVzIHRvIHRoaXMgcHJvcGVydHkuJyxcbiAgICAgICAgICAgICAgYWRkaXRpb25hbFByb3BlcnRpZXM6IHsgdHlwZTogJ29iamVjdCcgfSxcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGFkZEFkZGl0aW9uYWxWYWx1ZXNUb1Byb3BzKHByb3ApO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIHRlbXBTY2hlbWE7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ3JlYXRpbmcgY29uc3RydWN0IHByb3BlcnRpZXNcbiAgICBlbWl0UHJvcHNJbnRlcmZhY2UoKTtcblxuICAgIGNvZGUubGluZSgpO1xuXG4gICAgLy8gQ3JlYXRpbmcgY29uc3RydWN0IGZvciBoZWxtIGNoYXJ0XG4gICAgZW1pdENvbnN0cnVjdCgpO1xuXG4gICAgZnVuY3Rpb24gZW1pdFByb3BzSW50ZXJmYWNlKCkge1xuICAgICAgY29kZS5vcGVuQmxvY2soYGV4cG9ydCBpbnRlcmZhY2UgJHtjaGFydE5hbWV9UHJvcHNgKTtcblxuICAgICAgY29kZS5saW5lKCdyZWFkb25seSBuYW1lc3BhY2U/OiBzdHJpbmc7Jyk7XG4gICAgICBjb2RlLmxpbmUoJ3JlYWRvbmx5IHJlbGVhc2VOYW1lPzogc3RyaW5nOycpO1xuICAgICAgY29kZS5saW5lKCdyZWFkb25seSBoZWxtRXhlY3V0YWJsZT86IHN0cmluZzsnKTtcbiAgICAgIGNvZGUubGluZSgncmVhZG9ubHkgaGVsbUZsYWdzPzogc3RyaW5nW107Jyk7XG5cbiAgICAgIGlmIChzY2hlbWEgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBjb2RlLmxpbmUoJ3JlYWRvbmx5IHZhbHVlcz86IHsgW2tleTogc3RyaW5nXTogYW55IH07Jyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBkb1ZhbHVlc0hhdmVSZXFQcm9wcyA9IGhhc1JlcXVpcmVkUHJvcHMoc2NoZW1hKSA/ICcnIDogJz8nO1xuICAgICAgICBjb2RlLmxpbmUoYHJlYWRvbmx5IHZhbHVlcyR7ZG9WYWx1ZXNIYXZlUmVxUHJvcHN9OiAke3ZhbHVlc0ludGVyZmFjZX07YCk7XG4gICAgICB9XG5cbiAgICAgIGNvZGUuY2xvc2VCbG9jaygpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGVtaXRDb25zdHJ1Y3QoKSB7XG4gICAgICBjb2RlLm9wZW5CbG9jayhgZXhwb3J0IGNsYXNzICR7Y2hhcnROYW1lfSBleHRlbmRzIENvbnN0cnVjdGApO1xuXG4gICAgICBlbWl0SW5pdGlhbGl6ZXIoKTtcblxuICAgICAgY29kZS5saW5lKCk7XG5cbiAgICAgIGVtaXRBZGRpdGlvbmFsVmFsdWVzRmxhdHRlbkZ1bmMoKTtcblxuICAgICAgY29kZS5jbG9zZUJsb2NrKCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZW1pdEluaXRpYWxpemVyKCkge1xuICAgICAgY29uc3QgcHJvcHNEZWZpbml0aW9uID0gc2NoZW1hICYmIGhhc1JlcXVpcmVkUHJvcHMoc2NoZW1hKSA/IGAke2NoYXJ0TmFtZX1Qcm9wc2AgOiBgJHtjaGFydE5hbWV9UHJvcHMgPSB7fWA7XG5cbiAgICAgIGNvZGUub3BlbkJsb2NrKGBwdWJsaWMgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6ICR7cHJvcHNEZWZpbml0aW9ufSlgKTtcbiAgICAgIGNvZGUubGluZSgnc3VwZXIoc2NvcGUsIGlkKTsnKTtcblxuICAgICAgY29kZS5saW5lKCdsZXQgdXBkYXRlZFByb3BzID0ge307Jyk7XG4gICAgICBjb2RlLmxpbmUoKTtcbiAgICAgIGNvZGUub3BlbkJsb2NrKCdpZiAocHJvcHMudmFsdWVzKScpO1xuICAgICAgaWYgKHNjaGVtYSkge1xuICAgICAgICBjb2RlLmxpbmUoYGNvbnN0IHZhbHVlcyA9IHRvSnNvbl8ke3ZhbHVlc0ludGVyZmFjZX0ocHJvcHMudmFsdWVzKTtgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvZGUubGluZSgnY29uc3QgdmFsdWVzID0gcHJvcHMudmFsdWVzOycpO1xuICAgICAgfVxuICAgICAgY29kZS5vcGVuQmxvY2soJ2lmICh2YWx1ZXMpJyk7XG4gICAgICBjb2RlLmxpbmUoJ2NvbnN0IHsgYWRkaXRpb25hbFZhbHVlcywgLi4udmFsdWVzV2l0aG91dEFkZGl0aW9uYWxWYWx1ZXMgfSA9IHZhbHVlczsnKTtcbiAgICAgIGNvZGUub3BlbigndXBkYXRlZFByb3BzID0geycpO1xuICAgICAgY29kZS5saW5lKCcuLi5wcm9wcywnKTtcbiAgICAgIGNvZGUub3BlbigndmFsdWVzOiB7Jyk7XG4gICAgICBjb2RlLmxpbmUoJy4uLnRoaXMuZmxhdHRlbkFkZGl0aW9uYWxWYWx1ZXModmFsdWVzV2l0aG91dEFkZGl0aW9uYWxWYWx1ZXMpLCcpO1xuICAgICAgY29kZS5saW5lKCcuLi5hZGRpdGlvbmFsVmFsdWVzLCcpO1xuICAgICAgY29kZS5jbG9zZSgnfSwnKTtcbiAgICAgIGNvZGUuY2xvc2UoJ307Jyk7XG4gICAgICBjb2RlLmNsb3NlQmxvY2soKTtcbiAgICAgIGNvZGUuY2xvc2VCbG9jaygpO1xuICAgICAgY29kZS5saW5lKCk7XG5cbiAgICAgIGNvZGUub3BlbignY29uc3QgZmluYWxQcm9wczogSGVsbVByb3BzID0geycpO1xuICAgICAgaWYgKHJlcG9Vcmwuc3RhcnRzV2l0aCgnb2NpOi8vJykpIHtcbiAgICAgICAgY29kZS5saW5lKGBjaGFydDogXFwnJHtyZXBvVXJsfVxcJyxgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvZGUubGluZShgY2hhcnQ6IFxcJyR7ZGVmLmNoYXJ0TmFtZX1cXCcsYCk7XG4gICAgICAgIGNvZGUubGluZShgcmVwbzogXFwnJHtyZXBvVXJsfVxcJyxgKTtcbiAgICAgIH1cbiAgICAgIGNvZGUubGluZShgdmVyc2lvbjogXFwnJHtjaGFydFZlcnNpb259XFwnLGApO1xuICAgICAgY29kZS5saW5lKCcuLi4oT2JqZWN0LmtleXModXBkYXRlZFByb3BzKS5sZW5ndGggIT09IDAgPyB1cGRhdGVkUHJvcHMgOiBwcm9wcyksJyk7XG4gICAgICBjb2RlLmNsb3NlKCd9OycpO1xuXG4gICAgICBjb2RlLmxpbmUoKTtcbiAgICAgIGNvZGUubGluZSgnbmV3IEhlbG0odGhpcywgXFwnSGVsbVxcJywgZmluYWxQcm9wcyk7Jyk7XG4gICAgICBjb2RlLmNsb3NlQmxvY2soKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBlbWl0QWRkaXRpb25hbFZhbHVlc0ZsYXR0ZW5GdW5jKCkge1xuICAgICAgY29kZS5vcGVuQmxvY2soJ3ByaXZhdGUgZmxhdHRlbkFkZGl0aW9uYWxWYWx1ZXMocHJvcHM6IHsgW2tleTogc3RyaW5nXTogYW55IH0pOiB7IFtrZXk6IHN0cmluZ106IGFueSB9Jyk7XG4gICAgICBjb2RlLm9wZW4oJ2ZvciAobGV0IHByb3AgaW4gcHJvcHMpIHsnKTtcbiAgICAgIGNvZGUub3BlbignaWYgKEFycmF5LmlzQXJyYXkocHJvcHNbcHJvcF0pKSB7Jyk7XG4gICAgICBjb2RlLm9wZW4oJ3Byb3BzW3Byb3BdLm1hcCgoaXRlbTogYW55KSA9PiB7Jyk7XG4gICAgICBjb2RlLm9wZW4oJ2lmICh0eXBlb2YgaXRlbSA9PT0gXFwnb2JqZWN0XFwnICYmIHByb3AgIT09IFxcJ2FkZGl0aW9uYWxWYWx1ZXNcXCcpIHsnKTtcbiAgICAgIGNvZGUubGluZSgncmV0dXJuIHRoaXMuZmxhdHRlbkFkZGl0aW9uYWxWYWx1ZXMoaXRlbSk7Jyk7XG4gICAgICBjb2RlLmNsb3NlKCd9Jyk7XG4gICAgICBjb2RlLmxpbmUoJ3JldHVybiBpdGVtOycpO1xuICAgICAgY29kZS5jbG9zZSgnfSk7Jyk7XG4gICAgICBjb2RlLmNsb3NlKCd9Jyk7XG4gICAgICBjb2RlLm9wZW4oJ2Vsc2UgaWYgKHR5cGVvZiBwcm9wc1twcm9wXSA9PT0gXFwnb2JqZWN0XFwnICYmIHByb3AgIT09IFxcJ2FkZGl0aW9uYWxWYWx1ZXNcXCcpIHsnKTtcbiAgICAgIGNvZGUubGluZSgncHJvcHNbcHJvcF0gPSB0aGlzLmZsYXR0ZW5BZGRpdGlvbmFsVmFsdWVzKHByb3BzW3Byb3BdKTsnKTtcbiAgICAgIGNvZGUuY2xvc2UoJ30nKTtcbiAgICAgIGNvZGUuY2xvc2UoJ30nKTtcbiAgICAgIGNvZGUubGluZSgpO1xuICAgICAgY29kZS5saW5lKCdjb25zdCB7IGFkZGl0aW9uYWxWYWx1ZXMsIC4uLnZhbHVlc1dpdGhvdXRBZGRpdGlvbmFsVmFsdWVzIH0gPSBwcm9wczsnKTtcbiAgICAgIGNvZGUubGluZSgpO1xuICAgICAgY29kZS5vcGVuKCdyZXR1cm4geycpO1xuICAgICAgY29kZS5saW5lKCcuLi52YWx1ZXNXaXRob3V0QWRkaXRpb25hbFZhbHVlcywnKTtcbiAgICAgIGNvZGUubGluZSgnLi4uYWRkaXRpb25hbFZhbHVlcywnKTtcbiAgICAgIGNvZGUuY2xvc2UoJ307Jyk7XG4gICAgICBjb2RlLmNsb3NlQmxvY2soKTtcbiAgICB9XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBoYXNSZXF1aXJlZFByb3BzKHNjaGVtYTogSlNPTlNjaGVtYTQpOmJvb2xlYW4gfCB1bmRlZmluZWQge1xuICByZXR1cm4gc2NoZW1hPy5yZXF1aXJlZCAmJiBBcnJheS5pc0FycmF5KHNjaGVtYS5yZXF1aXJlZCkgJiYgc2NoZW1hLnJlcXVpcmVkLmxlbmd0aCA+IDA7XG59Il19