@tripsnek/tmf
Version:
TypeScript Modeling Framework - A TypeScript port of the Eclipse Modeling Framework (EMF)
152 lines (142 loc) • 20.6 kB
JavaScript
import { EClassImpl } from '../metamodel/impl/eclass-impl.js';
import { TGenUtils as DU } from './tgen-utils.js';
import { Environment, safeDynamicImport } from '../utils/environment.js';
/**
* Source code generation for .ts file that exports external facing
* APIs for a TMF EPackage.
*
*/
export class TGeneratorBarrelIndexTs {
outDir = '';
async generate(ePackage, outDir) {
if (outDir) {
this.outDir = outDir;
await this.ensureCustomDirectory();
}
const packageContents = this.generatePackageContents('', ePackage);
const customExports = await this.generateCustomExports();
return packageContents + customExports;
}
generatePackageContents(pkgFolderPath, ePackage) {
const path = pkgFolderPath + ePackage.getName();
let toReturn = ``;
for (const sub of ePackage.getESubPackages()) {
toReturn += this.generatePackageContents(path + '/', sub);
}
toReturn +=
`export * from './${path}/${DU.genUtilsFileName(ePackage)}.js';
export * from './${path}/${DU.genPackageFileName(ePackage)}.js';
export * from './${path}/${DU.genFactoryFileName(ePackage)}.js';
${this.generateEClassifierExports(ePackage, path)}`;
return toReturn;
}
generateEClassifierExports(ePackage, pkgFolderPath) {
let exports = ``;
for (const eclassifier of ePackage.getEClassifiers()) {
exports += `export * from './${pkgFolderPath}/api/${DU.genClassApiName(eclassifier)}.js';\n`;
if (eclassifier instanceof EClassImpl) {
exports += `export * from './${pkgFolderPath}/impl/${DU.genClassImplName(eclassifier)}.js';\n`;
exports += `export * from './${pkgFolderPath}/gen/${DU.genClassGenName(eclassifier)}.js';\n`;
}
}
return exports;
}
async ensureCustomDirectory() {
if (!this.outDir)
return;
Environment.requireNodeEnvironment('Custom directory creation');
try {
const fs = await safeDynamicImport('fs');
const path = await safeDynamicImport('path');
const customDir = path.join(this.outDir, 'custom');
if (!fs.existsSync(customDir)) {
fs.mkdirSync(customDir, { recursive: true });
const readmeContent = `# Custom Directory
This directory is automatically created by the TMF code generator to store your custom TypeScript files.
## Purpose
Files placed in this directory (and its subdirectories) are automatically exported in the barrel file (index.ts)
alongside the generated model code. This allows you to:
- Add custom utility functions related to your model
- Create custom business logic that works with your model
- Add helper types and interfaces
## Usage
- Place any \`.ts\` files in this directory or its subdirectories
- **GENERATE YOUR MODEL AGAIN**: All \`.ts\` files will be automatically included in the barrel exports
- Files are exported using relative paths from the project root
- The directory structure is preserved in the export paths
## Examples
\`\`\`typescript
// custom/utilities.ts
export function customModelHelper() {
// Your custom code here
}
// custom/types/custom-types.ts
export interface CustomModelExtension {
// Your custom types here
}
\`\`\`
These will automatically be exported as:
\`\`\`typescript
export * from './custom/utilities.js';
export * from './custom/types/custom-types.js';
\`\`\`
`;
const readmePath = path.join(customDir, 'README.md');
fs.writeFileSync(readmePath, readmeContent, 'utf8');
}
}
catch (error) {
throw new Error(`Custom directory creation failed: ${error.message}. This operation requires Node.js environment.`);
}
}
async generateCustomExports() {
if (!this.outDir)
return '';
Environment.requireNodeEnvironment('Custom exports generation');
try {
const fs = await safeDynamicImport('fs');
const path = await safeDynamicImport('path');
const customDir = path.join(this.outDir, 'custom');
if (!fs.existsSync(customDir))
return '';
const customFiles = await this.findTypeScriptFiles(customDir);
if (customFiles.length === 0)
return '';
let exports = '\n// Custom exports from /custom directory\n';
for (const file of customFiles) {
const relativePath = path.relative(this.outDir, file);
const exportPath = relativePath.replace(/\.ts$/, '').replace(/\\/g, '/');
exports += `export * from './${exportPath}.js';\n`;
}
return exports;
}
catch (error) {
throw new Error(`Custom exports generation failed: ${error.message}. This operation requires Node.js environment.`);
}
}
async findTypeScriptFiles(dir) {
Environment.requireNodeEnvironment('TypeScript file discovery');
try {
const fs = await safeDynamicImport('fs');
const path = await safeDynamicImport('path');
const files = [];
if (!fs.existsSync(dir))
return files;
const items = fs.readdirSync(dir, { withFileTypes: true });
for (const item of items) {
const fullPath = path.join(dir, item.name);
if (item.isDirectory()) {
files.push(...await this.findTypeScriptFiles(fullPath));
}
else if (item.isFile() && item.name.endsWith('.ts') && item.name !== 'README.md') {
files.push(fullPath);
}
}
return files;
}
catch (error) {
throw new Error(`TypeScript file discovery failed: ${error.message}. This operation requires Node.js environment.`);
}
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGdlbmVyYXRvci1iYXJyZWwtaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL3NvdXJjZS1nZW5lcmF0b3JzL3RnZW5lcmF0b3ItYmFycmVsLWluZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQztBQUU5RCxPQUFPLEVBQUUsU0FBUyxJQUFJLEVBQUUsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ2xELE9BQU8sRUFBRSxXQUFXLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUV6RTs7OztHQUlHO0FBQ0gsTUFBTSxPQUFPLHVCQUF1QjtJQUMxQixNQUFNLEdBQVcsRUFBRSxDQUFDO0lBRXJCLEtBQUssQ0FBQyxRQUFRLENBQUMsUUFBa0IsRUFBRSxNQUFlO1FBQ3ZELElBQUksTUFBTSxFQUFFLENBQUM7WUFDWCxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztZQUNyQixNQUFNLElBQUksQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO1FBQ3JDLENBQUM7UUFDRCxNQUFNLGVBQWUsR0FBRyxJQUFJLENBQUMsdUJBQXVCLENBQUMsRUFBRSxFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBQ25FLE1BQU0sYUFBYSxHQUFHLE1BQU0sSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQUM7UUFDekQsT0FBTyxlQUFlLEdBQUcsYUFBYSxDQUFDO0lBQ3pDLENBQUM7SUFFTyx1QkFBdUIsQ0FDN0IsYUFBcUIsRUFDckIsUUFBa0I7UUFFbEIsTUFBTSxJQUFJLEdBQUcsYUFBYSxHQUFHLFFBQVEsQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNoRCxJQUFJLFFBQVEsR0FBRyxFQUFFLENBQUM7UUFDbEIsS0FBSyxNQUFNLEdBQUcsSUFBSSxRQUFRLENBQUMsZUFBZSxFQUFFLEVBQUUsQ0FBQztZQUM3QyxRQUFRLElBQUksSUFBSSxDQUFDLHVCQUF1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QUFDLFVBQVUsQ0FBQyxHQUFHLENBQUM7Z0JBQUUsT0FBTyxLQUFLLENBQUM7WUFFdEMsTUFBTSxLQUFLLEdBQUcsRUFBRSxDQUFDLFdBQVcsQ0FBQyxHQUFHLEVBQUUsRUFBRSxhQUFhLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztZQUUzRCxLQUFLLE1BQU0sSUFBSSxJQUFJLEtBQUssRUFBRSxDQUFDO2dCQUN6QixNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBRTNDLElBQUksSUFBSSxDQUFDLFdBQVcsRUFBRSxFQUFFLENBQUM7b0JBQ3ZCLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxNQUFNLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO2dCQUMxRCxDQUFDO3FCQUFNLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRSxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxJQUFJLElBQUksQ0FBQyxJQUFJLEtBQUssV0FBVyxFQUFFLENBQUM7b0JBQ25GLEtBQUssQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7Z0JBQ3ZCLENBQUM7WUFDSCxDQUFDO1lBRUQsT0FBTyxLQUFLLENBQUM7UUFDZixDQUFDO1FBQUMsT0FBTyxLQUFVLEVBQUUsQ0FBQztZQUNwQixNQUFNLElBQUksS0FBSyxDQUFDLHFDQUFxQyxLQUFLLENBQUMsT0FBTyxnREFBZ0QsQ0FBQyxDQUFDO1FBQ3RILENBQUM7SUFDSCxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBFQ2xhc3MgfSBmcm9tICcuLi9tZXRhbW9kZWwvYXBpL2VjbGFzcy5qcyc7XHJcbmltcG9ydCB7IEVDbGFzc0ltcGwgfSBmcm9tICcuLi9tZXRhbW9kZWwvaW1wbC9lY2xhc3MtaW1wbC5qcyc7XHJcbmltcG9ydCB7IEVQYWNrYWdlIH0gZnJvbSAnLi4vbWV0YW1vZGVsL2FwaS9lcGFja2FnZS5qcyc7XHJcbmltcG9ydCB7IFRHZW5VdGlscyBhcyBEVSB9IGZyb20gJy4vdGdlbi11dGlscy5qcyc7XHJcbmltcG9ydCB7IEVudmlyb25tZW50LCBzYWZlRHluYW1pY0ltcG9ydCB9IGZyb20gJy4uL3V0aWxzL2Vudmlyb25tZW50LmpzJztcclxuXHJcbi8qKlxyXG4gKiBTb3VyY2UgY29kZSBnZW5lcmF0aW9uIGZvciAudHMgZmlsZSB0aGF0IGV4cG9ydHMgZXh0ZXJuYWwgZmFjaW5nXHJcbiAqIEFQSXMgZm9yIGEgVE1GIEVQYWNrYWdlLlxyXG4gKlxyXG4gKi9cclxuZXhwb3J0IGNsYXNzIFRHZW5lcmF0b3JCYXJyZWxJbmRleFRzIHtcclxuICBwcml2YXRlIG91dERpcjogc3RyaW5nID0gJyc7XHJcblxyXG4gIHB1YmxpYyBhc3luYyBnZW5lcmF0ZShlUGFja2FnZTogRVBhY2thZ2UsIG91dERpcj86IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XHJcbiAgICBpZiAob3V0RGlyKSB7XHJcbiAgICAgIHRoaXMub3V0RGlyID0gb3V0RGlyO1xyXG4gICAgICBhd2FpdCB0aGlzLmVuc3VyZUN1c3RvbURpcmVjdG9yeSgpO1xyXG4gICAgfVxyXG4gICAgY29uc3QgcGFja2FnZUNvbnRlbnRzID0gdGhpcy5nZW5lcmF0ZVBhY2thZ2VDb250ZW50cygnJywgZVBhY2thZ2UpO1xyXG4gICAgY29uc3QgY3VzdG9tRXhwb3J0cyA9IGF3YWl0IHRoaXMuZ2VuZXJhdGVDdXN0b21FeHBvcnRzKCk7XHJcbiAgICByZXR1cm4gcGFja2FnZUNvbnRlbnRzICsgY3VzdG9tRXhwb3J0cztcclxuICB9XHJcblxyXG4gIHByaXZhdGUgZ2VuZXJhdGVQYWNrYWdlQ29udGVudHMoXHJcbiAgICBwa2dGb2xkZXJQYXRoOiBzdHJpbmcsXHJcbiAgICBlUGFja2FnZTogRVBhY2thZ2VcclxuICApOiBzdHJpbmcge1xyXG4gICAgY29uc3QgcGF0aCA9IHBrZ0ZvbGRlclBhdGggKyBlUGFja2FnZS5nZXROYW1lKCk7XHJcbiAgICBsZXQgdG9SZXR1cm4gPSBgYDtcclxuICAgIGZvciAoY29uc3Qgc3ViIG9mIGVQYWNrYWdlLmdldEVTdWJQYWNrYWdlcygpKSB7XHJcbiAgICAgIHRvUmV0dXJuICs9IHRoaXMuZ2VuZXJhdGVQYWNrYWdlQ29udGVudHMocGF0aCArICcvJywgc3ViKTtcclxuICAgIH1cclxuICAgIHRvUmV0dXJuICs9IFxyXG4gICAgYGV4cG9ydCAqIGZyb20gJy4vJHtwYXRofS8ke0RVLmdlblV0aWxzRmlsZU5hbWUoZVBhY2thZ2UpfS5qcyc7XHJcbmV4cG9ydCAqIGZyb20gJy4vJHtwYXRofS8ke0RVLmdlblBhY2thZ2VGaWxlTmFtZShlUGFja2FnZSl9LmpzJztcclxuZXhwb3J0ICogZnJvbSAnLi8ke3BhdGh9LyR7RFUuZ2VuRmFjdG9yeUZpbGVOYW1lKGVQYWNrYWdlKX0uanMnO1xyXG4ke3RoaXMuZ2VuZXJhdGVFQ2xhc3NpZmllckV4cG9ydHMoZVBhY2thZ2UsIHBhdGgpfWA7XHJcbiAgICByZXR1cm4gdG9SZXR1cm47XHJcbiAgfVxyXG5cclxuICBnZW5lcmF0ZUVDbGFzc2lmaWVyRXhwb3J0cyhlUGFja2FnZTogRVBhY2thZ2UsIHBrZ0ZvbGRlclBhdGg6IHN0cmluZykge1xyXG4gICAgbGV0IGV4cG9ydHMgPSBgYDtcclxuICAgIGZvciAoY29uc3QgZWNsYXNzaWZpZXIgb2YgZVBhY2thZ2UuZ2V0RUNsYXNzaWZpZXJzKCkpIHtcclxuICAgICAgZXhwb3J0cyArPSBgZXhwb3J0ICogZnJvbSAnLi8ke3BrZ0ZvbGRlclBhdGh9L2FwaS8ke0RVLmdlbkNsYXNzQXBpTmFtZShcclxuICAgICAgICBlY2xhc3NpZmllclxyXG4gICAgICApfS5qcyc7XFxuYDtcclxuICAgICAgaWYgKGVjbGFzc2lmaWVyIGluc3RhbmNlb2YgRUNsYXNzSW1wbCkge1xyXG4gICAgICAgIGV4cG9ydHMgKz0gYGV4cG9ydCAqIGZyb20gJy4vJHtwa2dGb2xkZXJQYXRofS9pbXBsLyR7RFUuZ2VuQ2xhc3NJbXBsTmFtZShcclxuICAgICAgICAgIGVjbGFzc2lmaWVyXHJcbiAgICAgICAgKX0uanMnO1xcbmA7XHJcbiAgICAgICAgZXhwb3J0cyArPSBgZXhwb3J0ICogZnJvbSAnLi8ke3BrZ0ZvbGRlclBhdGh9L2dlbi8ke0RVLmdlbkNsYXNzR2VuTmFtZShcclxuICAgICAgICAgIGVjbGFzc2lmaWVyXHJcbiAgICAgICAgKX0uanMnO1xcbmA7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIHJldHVybiBleHBvcnRzO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBhc3luYyBlbnN1cmVDdXN0b21EaXJlY3RvcnkoKTogUHJvbWlzZTx2b2lkPiB7XHJcbiAgICBpZiAoIXRoaXMub3V0RGlyKSByZXR1cm47XHJcbiAgICBcclxuICAgIEVudmlyb25tZW50LnJlcXVpcmVOb2RlRW52aXJvbm1lbnQoJ0N1c3RvbSBkaXJlY3RvcnkgY3JlYXRpb24nKTtcclxuICAgIFxyXG4gICAgdHJ5IHtcclxuICAgICAgY29uc3QgZnMgPSBhd2FpdCBzYWZlRHluYW1pY0ltcG9ydCgnZnMnKTtcclxuICAgICAgY29uc3QgcGF0aCA9IGF3YWl0IHNhZmVEeW5hbWljSW1wb3J0KCdwYXRoJyk7XHJcbiAgICAgIFxyXG4gICAgICBjb25zdCBjdXN0b21EaXIgPSBwYXRoLmpvaW4odGhpcy5vdXREaXIsICdjdXN0b20nKTtcclxuICAgICAgXHJcbiAgICAgIGlmICghZnMuZXhpc3RzU3luYyhjdXN0b21EaXIpKSB7XHJcbiAgICAgICAgZnMubWtkaXJTeW5jKGN1c3RvbURpciwgeyByZWN1cnNpdmU6IHRydWUgfSk7XHJcbiAgICAgICAgXHJcbiAgICAgICAgY29uc3QgcmVhZG1lQ29udGVudCA9IGAjIEN1c3RvbSBEaXJlY3RvcnlcclxuXHJcblRoaXMgZGlyZWN0b3J5IGlzIGF1dG9tYXRpY2FsbHkgY3JlYXRlZCBieSB0aGUgVE1GIGNvZGUgZ2VuZXJhdG9yIHRvIHN0b3JlIHlvdXIgY3VzdG9tIFR5cGVTY3JpcHQgZmlsZXMuXHJcblxyXG4jIyBQdXJwb3NlXHJcblxyXG5GaWxlcyBwbGFjZWQgaW4gdGhpcyBkaXJlY3RvcnkgKGFuZCBpdHMgc3ViZGlyZWN0b3JpZXMpIGFyZSBhdXRvbWF0aWNhbGx5IGV4cG9ydGVkIGluIHRoZSBiYXJyZWwgZmlsZSAoaW5kZXgudHMpIFxyXG5hbG9uZ3NpZGUgdGhlIGdlbmVyYXRlZCBtb2RlbCBjb2RlLiBUaGlzIGFsbG93cyB5b3UgdG86XHJcblxyXG4tIEFkZCBjdXN0b20gdXRpbGl0eSBmdW5jdGlvbnMgcmVsYXRlZCB0byB5b3VyIG1vZGVsXHJcbi0gQ3JlYXRlIGN1c3RvbSBidXNpbmVzcyBsb2dpYyB0aGF0IHdvcmtzIHdpdGggeW91ciBtb2RlbFxyXG4tIEFkZCBoZWxwZXIgdHlwZXMgYW5kIGludGVyZmFjZXNcclxuXHJcbiMjIFVzYWdlXHJcblxyXG4tIFBsYWNlIGFueSBcXGAudHNcXGAgZmlsZXMgaW4gdGhpcyBkaXJlY3Rvcnkgb3IgaXRzIHN1YmRpcmVjdG9yaWVzXHJcbi0gKipHRU5FUkFURSBZT1VSIE1PREVMIEFHQUlOKio6IEFsbCBcXGAudHNcXGAgZmlsZXMgd2lsbCBiZSBhdXRvbWF0aWNhbGx5IGluY2x1ZGVkIGluIHRoZSBiYXJyZWwgZXhwb3J0c1xyXG4tIEZpbGVzIGFyZSBleHBvcnRlZCB1c2luZyByZWxhdGl2ZSBwYXRocyBmcm9tIHRoZSBwcm9qZWN0IHJvb3RcclxuLSBUaGUgZGlyZWN0b3J5IHN0cnVjdHVyZSBpcyBwcmVzZXJ2ZWQgaW4gdGhlIGV4cG9ydCBwYXRoc1xyXG5cclxuIyMgRXhhbXBsZXNcclxuXHJcblxcYFxcYFxcYHR5cGVzY3JpcHRcclxuLy8gY3VzdG9tL3V0aWxpdGllcy50c1xyXG5leHBvcnQgZnVuY3Rpb24gY3VzdG9tTW9kZWxIZWxwZXIoKSB7XHJcbiAgLy8gWW91ciBjdXN0b20gY29kZSBoZXJlXHJcbn1cclxuXHJcbi8vIGN1c3RvbS90eXBlcy9jdXN0b20tdHlwZXMudHMgIFxyXG5leHBvcnQgaW50ZXJmYWNlIEN1c3RvbU1vZGVsRXh0ZW5zaW9uIHtcclxuICAvLyBZb3VyIGN1c3RvbSB0eXBlcyBoZXJlXHJcbn1cclxuXFxgXFxgXFxgXHJcblxyXG5UaGVzZSB3aWxsIGF1dG9tYXRpY2FsbHkgYmUgZXhwb3J0ZWQgYXM6XHJcblxcYFxcYFxcYHR5cGVzY3JpcHRcclxuZXhwb3J0ICogZnJvbSAnLi9jdXN0b20vdXRpbGl0aWVzLmpzJztcclxuZXhwb3J0ICogZnJvbSAnLi9jdXN0b20vdHlwZXMvY3VzdG9tLXR5cGVzLmpzJztcclxuXFxgXFxgXFxgXHJcbmA7XHJcbiAgICAgICAgXHJcbiAgICAgICAgY29uc3QgcmVhZG1lUGF0aCA9IHBhdGguam9pbihjdXN0b21EaXIsICdSRUFETUUubWQnKTtcclxuICAgICAgICBmcy53cml0ZUZpbGVTeW5jKHJlYWRtZVBhdGgsIHJlYWRtZUNvbnRlbnQsICd1dGY4Jyk7XHJcbiAgICAgIH1cclxuICAgIH0gY2F0Y2ggKGVycm9yOiBhbnkpIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBDdXN0b20gZGlyZWN0b3J5IGNyZWF0aW9uIGZhaWxlZDogJHtlcnJvci5tZXNzYWdlfS4gVGhpcyBvcGVyYXRpb24gcmVxdWlyZXMgTm9kZS5qcyBlbnZpcm9ubWVudC5gKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgYXN5bmMgZ2VuZXJhdGVDdXN0b21FeHBvcnRzKCk6IFByb21pc2U8c3RyaW5nPiB7XHJcbiAgICBpZiAoIXRoaXMub3V0RGlyKSByZXR1cm4gJyc7XHJcbiAgICBcclxuICAgIEVudmlyb25tZW50LnJlcXVpcmVOb2RlRW52aXJvbm1lbnQoJ0N1c3RvbSBleHBvcnRzIGdlbmVyYXRpb24nKTtcclxuICAgIFxyXG4gICAgdHJ5IHtcclxuICAgICAgY29uc3QgZnMgPSBhd2FpdCBzYWZlRHluYW1pY0ltcG9ydCgnZnMnKTtcclxuICAgICAgY29uc3QgcGF0aCA9IGF3YWl0IHNhZmVEeW5hbWljSW1wb3J0KCdwYXRoJyk7XHJcbiAgICAgIFxyXG4gICAgICBjb25zdCBjdXN0b21EaXIgPSBwYXRoLmpvaW4odGhpcy5vdXREaXIsICdjdXN0b20nKTtcclxuICAgICAgXHJcbiAgICAgIGlmICghZnMuZXhpc3RzU3luYyhjdXN0b21EaXIpKSByZXR1cm4gJyc7XHJcbiAgICAgIFxyXG4gICAgICBjb25zdCBjdXN0b21GaWxlcyA9IGF3YWl0IHRoaXMuZmluZFR5cGVTY3JpcHRGaWxlcyhjdXN0b21EaXIpO1xyXG4gICAgICBcclxuICAgICAgaWYgKGN1c3RvbUZpbGVzLmxlbmd0aCA9PT0gMCkgcmV0dXJuICcnO1xyXG4gICAgICBcclxuICAgICAgbGV0IGV4cG9ydHMgPSAnXFxuLy8gQ3VzdG9tIGV4cG9ydHMgZnJvbSAvY3VzdG9tIGRpcmVjdG9yeVxcbic7XHJcbiAgICAgIFxyXG4gICAgICBmb3IgKGNvbnN0IGZpbGUgb2YgY3VzdG9tRmlsZXMpIHtcclxuICAgICAgICBjb25zdCByZWxhdGl2ZVBhdGggPSBwYXRoLnJlbGF0aXZlKHRoaXMub3V0RGlyLCBmaWxlKTtcclxuICAgICAgICBjb25zdCBleHBvcnRQYXRoID0gcmVsYXRpdmVQYXRoLnJlcGxhY2UoL1xcLnRzJC8sICcnKS5yZXBsYWNlKC9cXFxcL2csICcvJyk7XHJcbiAgICAgICAgZXhwb3J0cyArPSBgZXhwb3J0ICogZnJvbSAnLi8ke2V4cG9ydFBhdGh9LmpzJztcXG5gO1xyXG4gICAgICB9XHJcbiAgICAgIFxyXG4gICAgICByZXR1cm4gZXhwb3J0cztcclxuICAgIH0gY2F0Y2ggKGVycm9yOiBhbnkpIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBDdXN0b20gZXhwb3J0cyBnZW5lcmF0aW9uIGZhaWxlZDogJHtlcnJvci5tZXNzYWdlfS4gVGhpcyBvcGVyYXRpb24gcmVxdWlyZXMgTm9kZS5qcyBlbnZpcm9ubWVudC5gKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgYXN5bmMgZmluZFR5cGVTY3JpcHRGaWxlcyhkaXI6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nW10+IHtcclxuICAgIEVudmlyb25tZW50LnJlcXVpcmVOb2RlRW52aXJvbm1lbnQoJ1R5cGVTY3JpcHQgZmlsZSBkaXNjb3ZlcnknKTtcclxuICAgIFxyXG4gICAgdHJ5IHtcclxuICAgICAgY29uc3QgZnMgPSBhd2FpdCBzYWZlRHluYW1pY0ltcG9ydCgnZnMnKTtcclxuICAgICAgY29uc3QgcGF0aCA9IGF3YWl0IHNhZmVEeW5hbWljSW1wb3J0KCdwYXRoJyk7XHJcbiAgICAgIFxyXG4gICAgICBjb25zdCBmaWxlczogc3RyaW5nW10gPSBbXTtcclxuICAgICAgXHJcbiAgICAgIGlmICghZnMuZXhpc3RzU3luYyhkaXIpKSByZXR1cm4gZmlsZXM7XHJcbiAgICAgIFxyXG4gICAgICBjb25zdCBpdGVtcyA9IGZzLnJlYWRkaXJTeW5jKGRpciwgeyB3aXRoRmlsZVR5cGVzOiB0cnVlIH0pO1xyXG4gICAgICBcclxuICAgICAgZm9yIChjb25zdCBpdGVtIG9mIGl0ZW1zKSB7XHJcbiAgICAgICAgY29uc3QgZnVsbFBhdGggPSBwYXRoLmpvaW4oZGlyLCBpdGVtLm5hbWUpO1xyXG4gICAgICAgIFxyXG4gICAgICAgIGlmIChpdGVtLmlzRGlyZWN0b3J5KCkpIHtcclxuICAgICAgICAgIGZpbGVzLnB1c2goLi4uYXdhaXQgdGhpcy5maW5kVHlwZVNjcmlwdEZpbGVzKGZ1bGxQYXRoKSk7XHJcbiAgICAgICAgfSBlbHNlIGlmIChpdGVtLmlzRmlsZSgpICYmIGl0ZW0ubmFtZS5lbmRzV2l0aCgnLnRzJykgJiYgaXRlbS5uYW1lICE9PSAnUkVBRE1FLm1kJykge1xyXG4gICAgICAgICAgZmlsZXMucHVzaChmdWxsUGF0aCk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICAgIFxyXG4gICAgICByZXR1cm4gZmlsZXM7XHJcbiAgICB9IGNhdGNoIChlcnJvcjogYW55KSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVHlwZVNjcmlwdCBmaWxlIGRpc2NvdmVyeSBmYWlsZWQ6ICR7ZXJyb3IubWVzc2FnZX0uIFRoaXMgb3BlcmF0aW9uIHJlcXVpcmVzIE5vZGUuanMgZW52aXJvbm1lbnQuYCk7XHJcbiAgICB9XHJcbiAgfVxyXG59Il19