As a side product LiTScript can produce a JSON file that represents the module dependency graph. It contains all the modules in the project and their dependencies. A dependency arises when a module imports or exports another.
This information can be used to generate diagrams or dictionaries that help understanding the project structure. LiTScript by itself does not use the dependency file, but there is a web component in the extras folder that serves as an example how it can be utilized.
The main data element of the dependency graph is the module, which is defined below.
export interface Module {
The url
property refers to the documentation file generated from the
module. This property can also be missing, if the module is defined
outside the project or is omitted from the documentation.
url: string
Dependencies to other modules are listed here. The following array contains names of the modules that are imported in this module.
dependencies: string[]
}
The graph itself is just an object which properties are module names. Module name is its source file name including the relative folder path. The root of the path is the project base directory. The module name must be unique, it serves also as a key that identifies the module.
export interface DependencyGraph {
[name: string]: Module
}
Both data structures are stored in global variables. The dependency graph can be retrieved using the getter function.
var dependencyGraph: DependencyGraph = {}
export function getDependencyGraph() {
return dependencyGraph
}
To unify the module names we change backslash characters in the module path to forward slashes and remove the file extension.
function normalizeName(name: string) {
return name.replace(/\\/g, "/",).replace(/\.[j|t]s$/, "")
}
Before adding a new module to the graph we check if the module is already there. If so, we only update the url property, if it is given.
export function addModule(name: string, url?: string): Module {
name = normalizeName(name)
let res = dependencyGraph[name]
if (!res) {
res = { url, dependencies: [] }
dependencyGraph[name] = res
}
if (url)
res.url = url
return res
}
We do duplicate checking also before adding a dependency.
export function addDependency(module: Module, dependency: string) {
let name = normalizeName(dependency)
if (!module.dependencies.includes(name))
module.dependencies.push(name)
}
We can obtain the transitive dependencies of a module by recursively traversing the dependency graph. The method returns a subgraph of modules that depend on the given module.
export function allDependencies(moduleName: string): DependencyGraph {
let res: DependencyGraph = {}
let mod = dependencyGraph[moduleName]
if (mod)
addDeps(mod)
return res
function addDeps(module: Module) {
for (let i = 0; i < module.dependencies.length; ++i) {
let depName = module.dependencies[i]
if (!res[depName]) {
let dep = dependencyGraph[depName]
res[depName] = dep
addDeps(dep)
}
}
}
}