ernestognw / solidity-mermaid

A Solidity AST processor for transpiling Solidity smart contracts into Github's Mermaid.js language for diagramming.
https://www.npmjs.com/package/solidity-mermaid
MIT License
26 stars 0 forks source link

node app #22

Open devtooligan opened 12 months ago

devtooligan commented 12 months ago

this looks really cool, i ♥️ mermaid

i'd love to create a js file that i can run from the command line and have it produce a chart for me. i'm sure it's not much harder than copying in that example you've provided and adding some extra logic to handle the clargs. my js skills are so rusty and i'm quite busy atm so will have to try that some other time. anyways kudos on the project

ernestognw commented 11 months ago

Thanks for the comments @devtooligan. You can easily set up a project with the following:

mkdir my-custom-cli
cd my-custom-cli
node init -y
npm install solc solidity-mermaid solidity-ast

Then copy this file:

// index.js
const solc = require("solc");
const { Class } = require("solidity-mermaid");
const { readFileSync } = require("fs");
const { findAll } = require("solidity-ast/utils");

// Usage: node index.js <solidityFile>
const [_, __, path] = process.argv;

const input = {
  language: "Solidity",
  sources: {
    [path]: {
      content: readFileSync(path, "utf8"),
    },
  },
  settings: {
    outputSelection: {
      "*": {
        "*": ["*"],
        "": ["ast"],
      },
    },
  },
};

const output = JSON.parse(solc.compile(JSON.stringify(input)));

for (const [, { ast }] of Object.entries(output.sources)) {
  for (const typeDef of findAll(["ContractDefinition"], ast)) {
    const classDiagram = new Class(output, "ContractDefinition", typeDef.id);

    // Mermaid diagram
    console.log(classDiagram.processed);
  }
}

Copy some contract anywhere (eg. contracts/ERC721.sol), and run:

node index <path>

For example:

node index contracts/SimpleStorage.sol
> classDiagram
  %% 25:219:0
  class SimpleStorage {
    <<Contract>>
    +set(uint256 value)
    +get(): (uint256)
  }

I thought about a CLI at some point, which should be kind of straightforward since I focused on making the library agnostic to any usage (so it can be plugged in Hardhat/Foundry). I'll keep considering it 😄