Supported language
TypeScript
Analyze TypeScript projects by generating a dependency graph and optional complexity file with your own toolchain, then load coverage manually when you need it.
AtlasArc can analyze TypeScript projects when your project exports the structure that AtlasArc needs
to read. TypeScript analysis is artifact-backed: dependency-cruiser supplies the required graph,
while compatible SARIF and LCOV can add metrics. Your repository keeps control of the Node version, package manager, TypeScript compiler,
framework plugins, and test runner. AtlasArc does not install packages or run npm for you.
The usual flow is:
dependency graph JSON
+ optional ESLint/SonarJS SARIF
-> AtlasArc
-> source-folder graph, metrics, reports, and exports
LCOV coverage
-> selected manually in AtlasArc after the graph is loaded
What AtlasArc understands
AtlasArc understands TypeScript as a graph of source files and folders. It reads the files your project imports, re-exports, loads dynamically, or references as types, then rolls those file-level relationships up into source-folder architecture units.
At the architecture level, TypeScript provides:
- source-folder dependency graph;
- per-folder file internals in the Topology Graph: open a source folder to inspect its files and any import tangles inside it;
- the same source-folder evidence in Topology, Matrix, Composition, Subsystems, and Hotspots when the chosen view's required metrics are available.
The current TypeScript metric-family contract is complete below. The Metrics Matrix explains the metrics and their product-wide uses; this table owns the backend availability states.
| Metric family | TypeScript state | Evidence |
|---|---|---|
| Fan-in, fan-out, dependency references | Supported | Supplied dependency graph |
| Instability | Supported | Supplied dependency graph |
| Abstractness | Unsupported | JVM class/type evidence only |
| Distance from the main sequence | Unsupported | Requires Abstractness |
| Relative visibility | Unsupported | JVM visibility evidence only |
| Cyclomatic complexity maximum/average | Optional evidence | ESLint/SonarJS SARIF |
| Cognitive complexity maximum/average | Optional evidence | ESLint/SonarJS SARIF |
| Source-file count | Supported | TypeScript artifact model |
| Lines of code | Supported | TypeScript artifact model |
| Method count | Unsupported | JVM method evidence only |
| Line coverage | Optional evidence | Manually loaded LCOV |
| Branch coverage | Optional evidence | Manually loaded LCOV with branch records |
| Cycle status | Supported | Supplied dependency graph |
| Cycle-group count and largest cycle size | Supported | Supplied dependency graph |
| Source-folder architecture-unit count | Supported | TypeScript artifact model |
| Internal edges, boundary fan-in, boundary fan-out | Supported | Supplied dependency graph |
| Subsystem instability and cohesion | Supported | Supplied dependency graph |
| Recursive abstractness and recursive visibility | Unsupported | JVM public-surface evidence only |
| CCD, ACD, RACD, and NCCD dependency shape | Supported | Supplied dependency graph |
| ARV and GRV project visibility | Unsupported | JVM visibility evidence only |
TypeScript does not provide class/member-level dependency examples or source write-back for accepted dependencies. Missing optional data is shown as unavailable, not as zero. For example, if you load LCOV with line coverage but no branch records, line coverage can be shown while branch coverage stays unavailable.
Construct support
AtlasArc does not parse TypeScript syntax to discover architecture dependencies. It reads the resolved project-local file edges in the graph your project supplies, then rolls those edges up into source-folder architecture units. The graph generator decides which source constructs and aliases it can resolve; AtlasArc keeps the resulting file relationship and its available dependency kind.
The generated graph usually comes from the open source sverweij/dependency-cruiser project. In a supplied graph, AtlasArc handles these common relationship categories:
| Relationship present in the graph | AtlasArc treatment |
|---|---|
| Static imports, re-exports, and barrel edges | Project-local resolved files become source-folder dependency edges. |
| Dynamic imports | Resolved file edges remain source coupling; AtlasArc does not infer route or framework semantics. |
CommonJS require |
Included when the supplied graph resolves it to selected project source. |
| Type-only imports, exports, and import-type references | Included as source coupling when emitted, even though TypeScript may erase them at runtime. |
| JSDoc import references | Included when graph generation is configured to emit and resolve them. |
| Configured path or workspace aliases | Included when the supplied graph resolves the alias to selected project source. AtlasArc does not resolve aliases independently. |
| External packages and Node built-ins | Excluded from the project source-folder architecture. |
| Unresolved imports | Reported as artifact-quality evidence rather than guessed into the graph. |
Some TypeScript constructs matter to a reader, but AtlasArc recognizes them only as the imports or references they express:
| Construct | What AtlasArc can say |
|---|---|
extends and implements |
The imported base or interface file is a dependency. |
| Generic constraints and type aliases | The imported type source is a dependency. |
| Decorators | The decorator module is a dependency. |
| Function and constructor calls | The imported module is a dependency; member-level call evidence is not available. |
| Angular, React, NestJS, or similar framework imports | Imported source files are dependencies; framework runtime behavior is not inferred. |
Known boundaries
AtlasArc does not infer TypeScript dependencies from:
- Angular templates, Vue/Svelte component internals, or framework metadata that does not appear as a resolved source-file dependency;
- dependency injection container wiring, route strings, REST URLs, GraphQL endpoint strings, or plugin registry keys;
- generated clients, declaration files, mocks, stories, fixtures, or test sources unless your dependency graph intentionally includes them;
- external npm packages and Node built-ins as source folders;
- unresolved imports.
In a mixed Java/Kotlin and TypeScript repository, analyze server-side JVM code and TypeScript frontends as separate sources. Java and Kotlin can share one JVM graph when they compile together. TypeScript projects load from their generated files. Cross-language API contracts such as REST routes, GraphQL schemas, and generated clients are architectural agreements, but they are not ordinary Java method calls or TypeScript imports.
Files to generate
Create these files under the TypeScript project root you want to analyze:
| File | Required | What it adds |
|---|---|---|
.atlasarc/depgraph.json |
Yes | Source-file dependencies from dependency-cruiser. |
.atlasarc/eslint.sarif |
No | Cyclomatic complexity and cognitive complexity, when exported by ESLint and SonarJS. |
The dependency graph is required. SARIF enriches the graph with complexity metrics, but the project can still load without it.
Coverage is different. Do not place an LCOV file in .atlasarc expecting AtlasArc to find it. Run
your tests normally, let your coverage tool produce LCOV wherever it normally does, then choose that
file from the AtlasArc coverage action after the TypeScript graph is loaded.
In AtlasArc
- Generate `.atlasarc/depgraph.json` with your project toolchain.
- Rescan sources so AtlasArc sees the updated graph file.
- Select the TypeScript source from the analysis source picker.
- Load LCOV coverage manually when you want coverage overlays.
Generate the graph
Install dependency-cruiser in the TypeScript project and pin it with the rest of your dev dependencies:
npm install --save-dev dependency-cruiser
With pnpm:
pnpm add --save-dev dependency-cruiser
Create a dependency-cruiser config at the project root:
// .dependency-cruiser.cjs
module.exports = {
// AtlasArc reads the module graph and runs its own cycle detection, so no `forbidden`
// rules are needed here. Keep your team's own dependency-cruiser rules in a separate config.
options: {
tsConfig: { fileName: 'tsconfig.json' },
exclude: { path: ['\\.spec\\.tsx?$', '\\.test\\.tsx?$', '/dist/', '/coverage/', '/node_modules/'] },
doNotFollow: { path: 'node_modules' },
combinedDependencies: true,
},
};
Add scripts that write AtlasArc's default graph path:
{
"scripts": {
"atlasarc:prepare": "node -e \"require('fs').mkdirSync('.atlasarc', { recursive: true })\"",
"atlasarc:deps": "depcruise \"src\" --include-only \"^src\" --output-type json > .atlasarc/depgraph.json"
}
}
Run the graph script before loading or rescanning the TypeScript project in AtlasArc:
npm run atlasarc:prepare
npm run atlasarc:deps
Add complexity metrics
If you want cyclomatic and cognitive complexity, add ESLint, SonarJS, and the SARIF formatter:
npm install --save-dev eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-plugin-sonarjs @microsoft/eslint-formatter-sarif
With pnpm:
pnpm add --save-dev eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-plugin-sonarjs @microsoft/eslint-formatter-sarif
Use a dedicated ESLint config so your normal lint thresholds do not change:
// eslint-atlasarc.config.mjs
import tsParser from '@typescript-eslint/parser';
import tsPlugin from '@typescript-eslint/eslint-plugin';
import sonarjs from 'eslint-plugin-sonarjs';
export default [
{
ignores: ['dist/**', 'coverage/**', 'node_modules/**', '.atlasarc/**', '**/*.spec.*', '**/*.test.*'],
},
{
files: ['src/**/*.{ts,tsx}'],
languageOptions: {
parser: tsParser,
parserOptions: {
project: './tsconfig.json',
tsconfigRootDir: process.cwd(),
ecmaVersion: 2020,
sourceType: 'module',
},
},
plugins: { '@typescript-eslint': tsPlugin, sonarjs },
rules: {
// Threshold 0 makes ESLint emit a finding for *every* function, so the SARIF carries a
// score for each one. AtlasArc reads those scores; it does not treat them as violations.
complexity: ['warn', 0],
'sonarjs/cognitive-complexity': ['warn', 0],
},
},
];
Then add the SARIF export:
{
"scripts": {
"atlasarc:sarif": "eslint \"src/**/*.{ts,tsx}\" --config eslint-atlasarc.config.mjs --format @microsoft/eslint-formatter-sarif --output-file .atlasarc/eslint.sarif"
}
}
Run it before rescanning when you want updated complexity metrics:
npm run atlasarc:sarif
Workspaces
For npm, pnpm, Angular, or Nx workspaces, choose the source root you want AtlasArc to analyze and generate one dependency graph for that root. Avoid one accidental all-repository graph unless the whole repository is genuinely the architecture unit you want to inspect.
Examples:
| Project shape | Dependency-cruiser input |
|---|---|
| Single app | src |
| npm/pnpm workspace app | apps/web/src |
| Angular CLI project | projects/admin/src |
| Nx app | apps/web/src |
| Nx library | libs/design-system/src |
Give each analyzed root its own .atlasarc/ directory. AtlasArc infers the project root from where
.atlasarc/depgraph.json lives, so the graph for apps/web must sit at
apps/web/.atlasarc/depgraph.json — not in a shared folder at the repo root. Example root-level
scripts:
{
"scripts": {
"atlasarc:web:prepare": "node -e \"require('fs').mkdirSync('apps/web/.atlasarc', { recursive: true })\"",
"atlasarc:web:deps": "depcruise \"apps/web/src\" --include-only \"^apps/web/src\" --output-type json > apps/web/.atlasarc/depgraph.json",
"atlasarc:web:sarif": "eslint \"apps/web/src/**/*.{ts,tsx}\" --config eslint-atlasarc.config.mjs --format @microsoft/eslint-formatter-sarif --output-file apps/web/.atlasarc/eslint.sarif"
}
}
For Angular or Nx, use the project sourceRoot as the dependency-cruiser input unless your team has
a better source boundary.
Load coverage
TypeScript coverage uses LCOV. It is not tied to Babel; Vitest, Jest, nyc, c8, Playwright, Angular, and other tools can write LCOV.
Generate coverage with your normal test command. For example:
vitest run --coverage --coverage.reporter=lcov
After the TypeScript graph is loaded in AtlasArc, use the coverage action and select the generated
lcov.info or .lcov file. AtlasArc does not auto-detect LCOV files and does not reload them on
rescan; coverage is a manually loaded, session-scoped overlay.
The important part is path alignment. SF: entries in lcov.info should point at the same original
TypeScript files that appear in depgraph.json. If coverage points at compiled JavaScript, generated
files, or paths outside the selected source root, AtlasArc cannot attach coverage to the right source
folders reliably.
Check before loading
Before loading or rescanning the TypeScript project, check:
.atlasarc/depgraph.jsonexists and contains a top-levelmodulesarray;modules[].sourcepaths point at original TypeScript files, not generated JavaScript;- imports through aliases are resolved the way your team expects;
- optional SARIF paths match the same source files as dependency-cruiser;
- monorepo apps and libraries are split into the analysis roots your team actually wants to review.
Before loading coverage, check:
- the LCOV file exists where your coverage tool wrote it;
SF:paths point at original.tsor.tsxfiles;- the LCOV paths match the TypeScript graph that is currently loaded in AtlasArc;
- branch records exist if you expect Branch Coverage to be available.
Missing SARIF does not block analysis. Missing LCOV does not affect source readiness. Missing or invalid dependency graph JSON does.