JSPM

  • Created
  • Published
  • Downloads 41711
  • Score
    100M100P100Q144116F
  • License MIT

Automatically construct and visualize Graphs generated from your JavaScript and TypeScript project

Package Exports

  • skott
  • skott/filesystem/file-reader
  • skott/filesystem/file-writer
  • skott/modules/resolvers/base-resolver
  • skott/modules/resolvers/ecmascript/resolver
  • skott/modules/walkers/common
  • skott/modules/walkers/ecmascript/index
  • skott/modules/walkers/ecmascript/javascript/cjs
  • skott/modules/walkers/ecmascript/javascript/walker
  • skott/modules/walkers/ecmascript/module-declaration
  • skott/modules/walkers/ecmascript/typescript/path-alias
  • skott/modules/walkers/ecmascript/typescript/walker

Readme

skott

How to use skott

Install

You can install skott either locally or globally

npm install skott 
// or
npm install skott -g

Embedded Web Application

skott now embeds a new display mode "skott --displayMode=webapp" allowing you to visualize more precisely dependencies and the links between them. Here is an overview of a subset from the graph generated for fastify:

skott-webapp-fastify

As shown above Third-party and Built-in dependencies can be toggled when they are tracked (by providing --trackThirdPartyDependencies and --trackBuiltinDependencies to the CLI).

When Circular dependencies are found in the graph, they can also be toggled via the Node visualization options as shown below:

skott-webapp-with-cycles

JavaScript API

import skott from "skott";

const { getStructure, findCircularDependencies, findParentsOf, findLeaves } = await skott({
  /**
   * (Optional) Entrypoint of the project. If not provided, `skott` will search for all
   * supported files starting from the current working directory.
   * Defaults to `""`
   */ 
  entrypoint: "src/index.ts",
  /**
   * (Optional) Whether to run Skott using the incremental pattern. By setting "true",
   * Skott will create a `.skott/cache.json` file to only detect and re-process what
   * changed since the last analysis.
   * Defaults to `true`;
   */ 
  incremental: true,
  /**
   * (Optional) restricts file discovering when building the graph. 
   * Defaults to `[".js", ".mjs", ".cjs", ".jsx", ".ts", ".tsx"]`
   */ 
  fileExtensions: [".ts", ".tsx"],
  /**
   * (Optional) Max depth search for circular dependencies. This can be useful for 
   * performance purposes. 
   * Defaults to `POSITIVE_INFINITY`.
   */
  circularMaxDepth: 20,
  /**
   * (Optional) Whether the base directory of the entrypoint should be included in relative 
   * file paths. For the specified `src/index.ts` above, it would consider the 
   * root path to be `./` consequently `src/` would never appear in any file paths.
   * Defaults to `false`.
   */
  includeBaseDir: false,
  /**
   * (Optional) Whether third-party dependencies (npm) and/or builtin (Node.js core modules)
   * should be added in the graph and/or Typescript type-only import should be followed. 
   * Defaults to `thirdParty=false`, `builtin=false`, and `typeOnly=true`.
   */
  dependencyTracking: {
    thirdParty: true,
    builtin: true,
    typeOnly: true
  };
  /**
   * (Optional) Provide a custom tsconfig file to help skott resolve path aliases.
   * When extending some other tsconfig files, skott will be able to parse
   * all the way up all the path aliases referenced. 
   * Defaults to `tsconfig.json`.
   */
  tsConfigPath: "./tsconfig.json",
  /**
   * (Optional) Provide a path to the package.json that should be used to detect
   * unused third-party dependencies.
   * Defaults to `package.json`.
   */
  manifestPath: "./package.json",
  /**
   * (Optional) Provide custom dependency resolvers to take full control over the
   * content that will be added to the graph nodes.
   * Defaults to `EcmaScriptModuleResolver` which is used a standard dependency
   * resolver for ECMAScript projects.
   */
  dependencyResolvers: [new TurborepoResolver()]
});

Command line interface

skott exposes a CLI directly using features from the core library.

When the library installed locally you can run:

Providing an entrypoint:

$ ./node_modules/.bin/skott src/index.js

When the library is installed globally:

$ skott src/index.js

Note: The CLI output might be massive, so don't hesitate to pipe the stdout into a file:

$ skott --displayMode=file-tree > skott.txt

Run a global analysis from the current working directory:

Using this command, skott will deeply search for all ".ts" and ".tsx" files starting from cwd

$ skott --fileExtensions=.ts,.tsx

Skott can be used to generate static files from the project graph structure (.svg, .png, .md, .json)

$ skott src/index.js --staticFile=svg

For Skott itself, the following .svg file is generated:

On the CLI side, here are some examples of output generated:

Example targetting Fastify using "graph" display mode:

Using "file-tree" display mode:

When asking for circular dependencies to be found (using the --showCircularDependencies option):

See all the options of the CLI running:

$ skott --help

Examples

To initialize the dependency graph, the default exported function must be used first. Once executed, the default function returns a set of functions to retrieve some information about the graph just built.

import skott from "skott";

const { getStructure } = await skott({
  entrypoint: "index.js",
  // ...rest of the config
});

const { graph, files } = getStructure();
console.log(graph); // logs { "index.js": { id: "index.js", adjacentTo: [], body: {...} } };
console.log(files); // logs [ "index.js" ]

Search for circular dependencies

import skott from "skott";

const { findCircularDependencies, hasCircularDependencies } = await skott({
  entrypoint: "index.js",
  // ...rest of the config
});

// Imagine that starting from "index.js" skott detects a circular dependency
// between "core.js" and "utils.js" files

console.log(findCircularDependencies()); // logs [ [ "core.js", "utils.js" ] ]
console.log(hasCircularDependencies()); // logs "true"

Search for unused dependencies using the graph generated

import skott from "skott";

const { findUnusedDependencies } = await skott({
  entrypoint: "index.tsx",
  // ...rest of the config
});

const { thirdParty } = await findUnusedDependencies();
console.log(thirdParty); // logs [ "rxjs", "lodash.difference" ]

Search for leaves (nodes with no children)

leaf.js

console.log("I'm a leaf because I have no dependency");

index.js

import skott from "skott";

const { findLeaves } = await skott({
  entrypoint: "leaf.js",
  // ...rest of the config
});

console.log(findLeaves()); // logs [ "leaf.js" ]

Deeply search for parent dependencies of a given node

children.js

export const childrenFunction = () => {};

parent.js

import { childrenFunction } from "./children.js";

childrenFunction();

index.js

import skott from "skott";

const { findParentsOf } = await skott({
  entrypoint: "parent.js",
  // ...rest of the config
});

console.log(findParentsOf("children.js")); // logs [ "parent.js" ]

Explore file node metadata

Take for instance lib.js with the following content:

lib.js

import * as fs from "node:fs";
import { parseScript } from "meriyah";

And given the entrypoint main.js module below:

main.js

import skott from "skott";

const { getStructure } = await skott({
  entrypoint: "lib.js",
  dependencyTracking: {
    builtin: true,
    thirdParty: true,
    typeOnly: true
  }
});

const { graph } = getStructure();
console.log(graph["lib.js"].body);

// Prints
{ 
  size: 70, 
  thirdPartyDependencies: ["meriyah"], 
  builtinDependencies: ["node:fs"] 
}