Skip to content

Commit

Permalink
feat: expose rendering module to provide terminal and web visualizati…
Browse files Browse the repository at this point in the history
…ons through the API (#157)

* refactor: move inmemory file-writer to fake namespace

* Temp

* refactor: expose webapp api

* refactor: move everything related to terminal ui into src as an API

* refactor: introduce Terminal API

* refactor: unify terminal runners from cli or api

* fix: tests

* refactor: expose variants of the web application renderer

* fix: tests

* changeset: 0.34.0

* docs: document rendering module

* ci

* ignore benchmarks

* fix: tests

* fix: allow proper watch mode process interruption
  • Loading branch information
antoine-coulon committed Jun 11, 2024
1 parent 5ab375c commit 0871131
Show file tree
Hide file tree
Showing 48 changed files with 1,441 additions and 751 deletions.
39 changes: 39 additions & 0 deletions .changeset/thick-ties-hang.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
"skott": minor
---

Expose a new rendering module providing a programmatic access to terminal and web visualizations through skott's API.

This is equivalent to use the CLI such as `skott --displayMode=webapp` but offers more flexibility for the runtime configuration which suffers from limitations when only using the CLI (some configurations are nearly impossible to represent using strings e.g. providing custom functions), this is why often authors tend to introduce runtime configuration files that CLIs can pick up automatically, thing that we want to avoid with skott, by unifying it's usage either coming from the API or CLI.

**Using the rendering module**

```js
import { defaultConfig } from "skott";
import { Web, Terminal } from "skott/rendering";

await Web.renderWebApplication(
// skott runtime config
defaultConfig,
// application config
{
visualization: {
granularity: "module",
},
watch: true,
port: 1111,
onListen: (port) => console.log(`Listening on port ${port}`),
open: true,
onOpenError: () => console.log(`Error when opening the browser`),
}
);

await Terminal.renderTerminalApplication(defaultConfig, {
displayMode: "graph",
exitCodeOnCircularDependencies: 1,
showCircularDependencies: true,
showUnusedDependencies: true,
watch: true,
});
```

53 changes: 27 additions & 26 deletions .github/workflows/skott.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,33 +54,34 @@ jobs:
env:
CI: true

- name: Run benchmarks
if: matrix.os == 'ubuntu-latest' && !contains(github.ref, 'main') && !contains(github.ref, 'release')
run: |
git config --local user.name "skott_bot"
git config --local user.email "skott.devtool@gmail.com"
git fetch origin
git pull origin ${{ github.head_ref }} --rebase
pnpm -r benchmark
# - name: Run benchmarks
# if: matrix.os == 'ubuntu-latest' && !contains(github.ref, 'main') && !contains(github.ref, 'release')
# run: |
# git stash
# git config --local user.name "skott_bot"
# git config --local user.email "skott.devtool@gmail.com"
# git fetch origin
# git pull origin ${{ github.head_ref }} --rebase

# pnpm -r benchmark

git status
git add .
git commit -m "benchmark: publish benchmark results from node_${{ matrix.node-version }}"
git pull origin ${{ github.head_ref }} --rebase
if git diff --quiet; then
echo "No conflicts, proceeding with the push."
else
git checkout --theirs .
git add .
git rebase --continue
fi
git push origin HEAD:${{ github.head_ref }}
env:
CI: true
NODE_VERSION: ${{ matrix.node-version }}
# git status
# git add .
# git commit -m "benchmark: publish benchmark results from node_${{ matrix.node-version }}"
# git pull origin ${{ github.head_ref }} --rebase

# if git diff --quiet; then
# echo "No conflicts, proceeding with the push."
# else
# git checkout --theirs .
# git add .
# git rebase --continue
# fi

# git push origin HEAD:${{ github.head_ref }}
# env:
# CI: true
# NODE_VERSION: ${{ matrix.node-version }}



3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
node_modules
.pnpm-debug.log
.pnpm-store
.pnpm-store
.DS_Store
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

✅ Deeply detects **circular dependencies** in an efficient way, with the ability to provide a max depth for the search

✅ Many **builtin visualization modes** including a web application or terminal-based outputs such as file-tree or graph views.
✅ Many **builtin visualization modes** including a web application or terminal-based outputs such as file-tree or graph views. Visualization modes can be rendered using both the CLI and API.

✅ Builtin **watch mode** updating the graph when file changes are detected. It works with all display modes (webapp and all CLIs visualization modes). Support all options of file ignoring/filtering from skott.

Expand Down
93 changes: 93 additions & 0 deletions packages/skott/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,12 +118,18 @@ const { getStructure, getWorkspace, useGraph, findUnusedDependencies } = await s
});
```

> [!NOTE]
> Starting from 0.34.0, skott visualization modes can be programatically registered using the API through the `rendering module` accessible through (`"skott/rendering"`) export. It allows all options to be provided (some options aren't accessible through the CLI) while having the ability to visualize the result of the API. An **[example of the rendering module can be found there](https://github.com/antoine-coulon/skott/blob/main/packages/skott/examples/api-rendering.ts)**.
More API **[examples can be found there](https://github.com/antoine-coulon/skott/blob/main/packages/skott/examples/api.ts)**.

## **Command line interface**

skott exposes a CLI directly using features from the core library. All the options shown from the API can be used from the CLI, please use `skott --help` to see how to express them via the command line.

> [!NOTE]
> All skott's runtime configuration options might not be available through the CLI, especially options that expect non serializable values such as functions (`groupBy` option for instance) as skott does not support any runtime configuration file (such as `.skottrc`). However, skott provides everything through its API, including capabilities to programmatically render all the available display modes, more [can be found there](https://github.com/antoine-coulon/skott/blob/main/packages/skott/examples/api-rendering.ts).
When the library installed locally you can run:

**Providing an entrypoint:**
Expand Down Expand Up @@ -481,6 +487,93 @@ console.log(getWorkspace());

This feature could help creating a dependency graph only using manifests instead of parsing and traversing the whole source code graph using static analysis.

### Explore all the information through the Rendering module

skott's API can be used to have a programmatic access to the project's graph and
all the information collected through the project analysis.

However when it comes to visualizing that information, skott provides many display
modes that were mostly accessible through the CLI only.

Since 0.34.0, skott provides a way to render these display modes while being
in the API context, allowing to have a better control over the configuration,
if it's depending on any other context (environment, output of other functions, etc).

**Terminal application rendering**

```js
import skott, { defaultConfig } from "skott";
import { Web, Terminal } from "skott/rendering";

await Terminal.renderTerminalApplication(defaultConfig, {
displayMode: "graph",
exitCodeOnCircularDependencies: 1,
showCircularDependencies: true,
showUnusedDependencies: true,
watch: true
});
```

**Web application rendering**

When it comes to web application, two options are available:

1. using `renderWebApplication` that just requires the runtime configuration, and
manages the lifecycle of skott internally.

```js
await Web.renderWebApplication(
// skott runtime config
defaultConfig,
// application config
{
visualization: {
granularity: "module"
},
watch: true,
port: 1111,
onListen: (port) => console.log(`Listening on port ${port}`),
open: true,
onOpenError: () => console.log(`Error when opening the browser`)
}
);
```

2. using `renderStandaloneWebApplication` that takes a factory function that
provides the skott instance, allowing to have a better control over
what is injected into the skott instance. That can become especially handy
when using plugins for external tools that need to alter the structure of the
graph before rendering it. As there is no plugin system in skott (yet), this
is a way to achieve a similar result. This is what we're using to build the
[Rush](https//rushjs.io) monorepo tool [skott plugin](https://github.com/antoine-coulon/krush).

```js
// In that case it's just using skott, but could be anything mapping the graph
// to a different structure, as long as it respects the expected contract.
const factory = () => skott(defaultConfig);

await Web.renderStandaloneWebApplication(
// factory function
factory,
// application config
{
visualization: {
granularity: "module"
},
watch: {
cwd: process.cwd(),
ignorePattern: "tests/**/*",
fileExtensions: [".ts"],
verbose: true
},
port: 1111,
onListen: (port) => console.log(`Listening on port ${port}`),
open: true,
onOpenError: () => console.log(`Error when opening the browser`)
}
);
```

## Contributors

<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
Expand Down
89 changes: 0 additions & 89 deletions packages/skott/bin/cli-config.ts

This file was deleted.

7 changes: 4 additions & 3 deletions packages/skott/bin/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ import { fileURLToPath } from "node:url";
import { Command } from "commander";

import { kExpectedModuleExtensions } from "../src/modules/resolvers/base-resolver.js";

import { main } from "./main.js";
import { runTerminalApplicationFromCLI } from "../src/rendering/terminal/internal.js";

function readManifestVersion(): string {
try {
Expand Down Expand Up @@ -169,6 +168,8 @@ cli
| ./node_modules/.bin/skott --showCircularDependencies --displayMode=raw --watch\n
`)
)
.action((name, commandAndOptions) => main(name, commandAndOptions));
.action((name, commandAndOptions) =>
runTerminalApplicationFromCLI(name, commandAndOptions)
);

cli.parse(process.argv);

0 comments on commit 0871131

Please sign in to comment.