GithubHelp home page GithubHelp logo

daangn / stackgraph Goto Github PK

View Code? Open in Web Editor NEW
21.0 4.0 2.0 105 KB

변수 의존성 관계도와 메타데이터를 정적 분석 및 시각화

Home Page: https://daangn.github.io/stackgraph/

License: MIT License

TypeScript 97.55% HTML 2.45%
deno dependency-graph ts-morph

stackgraph's Introduction

StackGraph

image

StackGraph타입스크립트 AST 정적 분석을 통해 변수 단위의 의존성을 분석하고 시각화하는 툴킷을 제공해요.

  • 컴포넌트 사이의 의존성을 관계도로 시각화해요.
  • Stackflowpush를 추적해 화면간 관계도를 시각화해요.
  • 이벤트 로깅 함수를 추적해 페이지에서 발생하는 모든 이벤트를 보여줘요.

StackGraph는 기존 의존성 정적 분석 솔루션과 대비해서 어떤 장점이 있을까요?

  • 기존 솔루션은 파일 단위로만 의존성 분석을 했어요.
    • 파일 하나에 여러 export가 있다면 어떤 export가 어디에서 사용되는지 알 수 없어요.
  • StackGraph는 타입스크립트 LSP를 사용해 변수 단위로 의존성을 분석해요.
    • export 수에 관계없이 개별 export가 어디에서 사용되는지 알 수 있어요.
  • 의존성 분석과 시각화 단계가 분리되어 있어 분석 결과가 프레임워크에 종속되지 않아요.

StackGraph는 아직 알파 버전으로, 모든 릴리즈에서 breaking change가 발생할 수 있어요.

시작하기

StackGraph는 Deno로 작성되었어요. 다음 명령어로 Deno를 설치해요.

$ brew install deno

프로젝트에 TypeScript 파일을 하나 생성하고, StackGraph 인스턴스를 초기화해요.

import { StackGraph } from "https://raw.githubusercontent.com/daangn/stackgraph/main/graph/fluent.ts"

const graph = new StackGraph()
VSCode에서 Deno Extension 사용하기

VSCode에서 타입스크립트 LSP와 Deno Extension이 충돌하는 것을 막기 위해 .vscode/settings.json에 다음과 같이 설정을 추가해주세요.

{
    "deno.enable": false,
    "deno.enablePaths": ["./deno_scripts", "./some_deno_file.ts"] // 파일 또는 디렉터리 경로
}

더 자세한 내용은 Deno 공식 문서의 설치법VSCode에서 사용법을 참고해주세요.

데이터 준비하기

다음 형태의 JSON 파일을 준비해주세요.

export type LabelOption = {
	flows: Record<string, {
		type: "push" | "replace"
		to: string
	}[]>
	clicks: Record<string, string[]>
	shows: Record<string, string[]>
}

렌더링하기

$ deno run -A https://raw.githubusercontent.com/daangn/stackgraph/main/render/build.ts <data.json 파일 경로>

$ deno task serve

stackgraph's People

Contributors

scarf005 avatar

Stargazers

jang hyun bong avatar polee avatar Junho Yoon avatar Kiwon Kim avatar Seunghyun Cho avatar John (Kanary Hong) avatar studyqrr12 avatar Hyunjoon-Kim avatar Hyojeong Choi avatar flow avatar Ben avatar Iha Shin (Cosmo, 신의하) avatar hyunjoon park avatar Xvezda avatar Chanhee Lee avatar Junhea Hong avatar Jeongjin Oh avatar 김석진(poki) avatar Chung-il Jung avatar Lee HyunJae (whale) avatar Jonghyeon Ko avatar

Watchers

JaePil Jung avatar  avatar GeunSam2 (Gray) avatar  avatar

Forkers

2-now scarf005

stackgraph's Issues

utility function to resolve `React.lazy` imports

Example implementation

const resolveDynamicImportPath = (path: string) =>
  resolve(import.meta.dirname!) + path.replace('@src', '/src') + '.tsx'

const projectCache = new Project({
  useInMemoryFileSystem: true,
})

export const getRouteMappings =
  (resolveDynamicImport: (path: string) => string) =>
  (sourceFile: SourceFile): Record<string, string> => {
    const nodes = query(
      sourceFile.getText(),
      'Identifier[name=routes] ~ ObjectLiteralExpression > PropertyAssignment'
    ).flatMap((x) => {
      const container = query(x, 'Identifier[name=component] ~ Identifier')[0]
      if (container === undefined) return []

      const topDecl = sourceFile.getVariableDeclarationOrThrow(container?.getText())

      // HACK: assumes all components are of format React.lazy(() => import('<path>/componentName'))
      const path = topDecl.getFirstDescendantByKindOrThrow(SyntaxKind.StringLiteral)
      const resolvedPath = resolveDynamicImport(path.getLiteralText())
      const resolvedText = Deno.readTextFileSync(resolvedPath)

      const srcfile = projectCache.createSourceFile(resolvedPath, resolvedText)
      // https://ts-morph.com/details/exports#getting-exported-declarations
      const uri = encodeVSCodeURI(srcfile.getExportedDeclarations().get('default')![0])
      projectCache.removeSourceFile(srcfile)

      const name = query(x, 'PropertyAccessExpression Identifier[name=Route] ~ Identifier')[0]?.getText()

      return [[name, uri]] as const
    })

    return Object.fromEntries(nodes)
  }

metadata inconsistency between initial nodes and queried nodes

Status Quo

export type Metadata<A, B> = {
/**
* Dependency not originated from module imports.
* For example, `Redirect` in `<Redirect to="ComponentName" />`.
*/
links: A
/** All other data to query from given link */
metas: B
}
export type LinkedDecl<A, B> = Metadata<A, B> & { node: Declaration }
/**
* Filter and map links, metadatas, and declaration
*/
export type GetLink<A, B> = (node: Declaration) => LinkedDecl<A, B> | undefined

data between nodes in metadata vs dependency graph, namely

  • StackGraph.metadata = Record<string, Metadata<A, B>>
  • StackGraph.depsMap = Map<Declaration, Declaration[]>

Problem

  • complicates API design
  • StackGraph.metadata less useful on querying metadata from graph and flatGraph

Solution

only filter initial nodes, query metadata later

☂️ project roadmap

Short-Term Goals

  • testing

    • test individual steps
    • test multi-file project
    • #7
  • documentation

    • project architecture
    • integration guide with stackflow
  • demo page

    • import data.json
    • use react components in demo page
  • integration

    • stackflow
    • #4
  • use a better encoding format other than VSCodeURI (verbose, only works in absolute path)

Medium-Term Goals

  • interactive editor with real-time visualization, like in e.g
  • integration
    • react-dom-router
    • typescript types
  • testing
    • use graphviz for snapshot testing
    • display snapshot diff using lsix

Long-Term Goals

  • analyze 3rd party dependencies
    • node_modules
    • URL imports
    • remote repository URL
  • create github app
    • generate dependency diff animation (e.g react components)
  • integration with graph database (e.g neo4j)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.