<|start_filename|>bin/uml-builder.js<|end_filename|>
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var graphviz = require("graphviz");
var ts_elements_1 = require("./ts-elements");
var extensions_1 = require("./extensions");
function buildUml(modules, outputFilename, dependenciesOnly, svgOutput) {
    var g = graphviz.digraph("G");
    var FontSizeKey = "fontsize";
    var FontSize = 12;
    var FontNameKey = "fontname";
    var FontName = "Verdana";
    g.set(FontSizeKey, FontSize);
    g.set(FontNameKey, FontName);
    g.setEdgeAttribut(FontSizeKey, FontSize);
    g.setEdgeAttribut(FontNameKey, FontName);
    g.setNodeAttribut(FontSizeKey, FontSize);
    g.setNodeAttribut(FontNameKey, FontName);
    g.setNodeAttribut("shape", "record");
    modules.forEach(function (module) {
        buildModule(module, g, module.path, 0, dependenciesOnly);
    });
    if (process.platform === "win32") {
        var pathVariable = process.env["PATH"];
        if (pathVariable.indexOf("Graphviz") === -1) {
            console.warn("Could not find Graphviz in PATH.");
        }
    }
    g.output(svgOutput ? "svg" : "png", outputFilename);
}
exports.buildUml = buildUml;
function buildModule(module, g, path, level, dependenciesOnly) {
    var ModulePrefix = "cluster_";
    var moduleId = getGraphNodeId(path, module.name);
    var cluster = g.addCluster("\"" + ModulePrefix + moduleId + "\"");
    cluster.set("label", (module.visibility !== ts_elements_1.Visibility.Public ? visibilityToString(module.visibility) + " " : "") + module.name);
    cluster.set("style", "filled");
    cluster.set("color", "gray" + Math.max(40, (95 - (level * 6))));
    if (dependenciesOnly) {
        extensions_1.Collections.distinct(module.dependencies, function (d) { return d.name; }).forEach(function (d) {
            g.addEdge(module.name, getGraphNodeId("", d.name));
        });
    }
    else {
        var moduleMethods = combineSignatures(module.methods, getMethodSignature);
        if (moduleMethods) {
            cluster.addNode(getGraphNodeId(path, module.name), {
                "label": moduleMethods,
                "shape": "none"
            });
        }
        module.modules.forEach(function (childModule) {
            buildModule(childModule, cluster, moduleId, level + 1, false);
        });
        module.classes.forEach(function (childClass) {
            buildClass(childClass, cluster, moduleId);
        });
    }
}
function buildClass(classDef, g, path) {
    var methodsSignatures = combineSignatures(classDef.methods, getMethodSignature);
    var propertiesSignatures = combineSignatures(classDef.properties, getPropertySignature);
    var classNode = g.addNode(getGraphNodeId(path, classDef.name), {
        "label": "{" + [classDef.name, methodsSignatures, propertiesSignatures].filter(function (e) { return e.length > 0; }).join("|") + "}"
    });
    if (classDef.extends) {
        g.addEdge(classNode, classDef.extends.parts.reduce(function (path, name) { return getGraphNodeId(path, name); }, ""), { "arrowhead": "onormal" });
    }
}
function combineSignatures(elements, map) {
    return elements.filter(function (e) { return e.visibility == ts_elements_1.Visibility.Public; })
        .map(function (e) { return map(e) + "\\l"; })
        .join("");
}
function getMethodSignature(method) {
    return [
        visibilityToString(method.visibility),
        lifetimeToString(method.lifetime),
        getName(method) + "()"
    ].join(" ");
}
function getPropertySignature(property) {
    return [
        visibilityToString(property.visibility),
        lifetimeToString(property.lifetime),
        [
            (property.hasGetter ? "get" : null),
            (property.hasSetter ? "set" : null)
        ].filter(function (v) { return v !== null; }).join("/"),
        getName(property)
    ].join(" ");
}
function visibilityToString(visibility) {
    switch (visibility) {
        case ts_elements_1.Visibility.Public:
            return "+";
        case ts_elements_1.Visibility.Protected:
            return "~";
        case ts_elements_1.Visibility.Private:
            return "-";
    }
}
function lifetimeToString(lifetime) {
    return lifetime === ts_elements_1.Lifetime.Static ? "\\<static\\>" : "";
}
function getName(element) {
    return element.name;
}
function getGraphNodeId(path, name) {
    var result = ((path ? path + "/" : "") + name).replace(/\//g, "|");
    return result;
}


<|start_filename|>bin/tsviz-app.js<|end_filename|>
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var tsviz = require("./tsviz");
function main(args) {
    var switches = args.filter(function (a) { return a.indexOf("-") === 0; });
    var nonSwitches = args.filter(function (a) { return a.indexOf("-") !== 0; });
    if (nonSwitches.length < 1) {
        console.error("Invalid number of arguments. Usage:\n" +
            "  <switches> <sources filename/directory> <output.png>\n" +
            "Available switches:\n" +
            "  -d, dependencies: produces the modules' dependencies diagram\n" +
            "  -r, recursive: include files in subdirectories (must be non-cyclic)" +
            "  -svg: output an svg file");
        return;
    }
    var targetPath = nonSwitches.length > 0 ? nonSwitches[0] : "";
    var outputFilename = nonSwitches.length > 1 ? nonSwitches[1] : "diagram.png";
    var dependenciesOnly = switches.indexOf("-d") >= 0 || switches.indexOf("-dependencies") >= 0;
    var recursive = switches.indexOf("-r") >= 0 || switches.indexOf("-recursive") >= 0;
    var svgOutput = switches.indexOf("-svg") >= 0;
    tsviz.createGraph(targetPath, outputFilename, dependenciesOnly, recursive, svgOutput);
    console.log("Done");
}
function run() {
    main(process.argv.slice(2));
}
exports.run = run;


<|start_filename|>bin/tsviz.js<|end_filename|>
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var fs_1 = require("fs");
var ts = require("typescript");
var analyser = require("./ts-analyser");
var umlBuilder = require("./uml-builder");
function walk(dir, recursive) {
    var results = [];
    var list = fs_1.readdirSync(dir);
    var i = 0;
    (function next() {
        var file = list[i++];
        if (!file) {
            return results;
        }
        file = dir + '/' + file;
        var stat = fs_1.statSync(file);
        if (stat && stat.isDirectory()) {
            if (recursive) {
                results = results.concat(walk(file, recursive));
                next();
            }
        }
        else {
            results.push(file);
            next();
        }
    })();
    return results;
}
function getFiles(targetPath, recursive) {
    if (!fs_1.existsSync(targetPath)) {
        console.error("'" + targetPath + "' does not exist");
        return [];
    }
    var fileNames;
    if (fs_1.lstatSync(targetPath).isDirectory()) {
        fileNames = walk(targetPath, recursive);
    }
    else {
        fileNames = [targetPath];
    }
    return fileNames;
}
function getModules(targetPath, recursive) {
    var originalDir = process.cwd();
    var fileNames = getFiles(targetPath, recursive);
    var compilerOptions = {
        noEmitOnError: true,
        noImplicitAny: true,
        target: 1,
        module: 2
    };
    var compilerHost = ts.createCompilerHost(compilerOptions, true);
    var program = ts.createProgram(fileNames, compilerOptions, compilerHost);
    var modules = program.getSourceFiles()
        .filter(function (f) { return f.fileName.lastIndexOf(".d.ts") !== f.fileName.length - ".d.ts".length; })
        .map(function (sourceFile) { return analyser.collectInformation(program, sourceFile); });
    process.chdir(originalDir);
    console.log("Found " + modules.length + " module(s)");
    return modules;
}
function createGraph(targetPath, outputFilename, dependenciesOnly, recursive, svgOutput) {
    var modules = getModules(targetPath, recursive);
    umlBuilder.buildUml(modules, outputFilename, dependenciesOnly, svgOutput);
}
exports.createGraph = createGraph;
function getModulesDependencies(targetPath, recursive) {
    var modules = getModules(targetPath, recursive);
    var outputModules = [];
    modules.sort(function (a, b) { return a.name.localeCompare(b.name); }).forEach(function (module) {
        var uniqueDependencies = {};
        module.dependencies.forEach(function (dependency) {
            uniqueDependencies[dependency.name] = null;
        });
        outputModules.push({
            name: module.name,
            dependencies: Object.keys(uniqueDependencies).sort()
        });
    });
    return outputModules;
}
exports.getModulesDependencies = getModulesDependencies;
