Neo4J Browser Internals

The Neo4J Browser is logically composed of 2 parts:

  1. The neo4j-arc, which is the current part we are discussing

    1. The neo4j-arc is based on D3 and implements its own layout, coloring, and link drawing. For example, the calculation of arrow, i.e. links, between nodes uses some very complicated math along with very prelimiary MDN standard basic shap specification.

  2. A user-interface that combines the graph rendering (supported by the graphing module), database, and user interaction together

Although we see <id> property for every node or relationship in the node inspection panel of Neo4J Browser, those ID’s are NOT generated by neo4j-arc, but instead by Neo4J database. This pattern should be honored by all client using neo4j-arc library. All nodes or relationships, at the moment of being fed into the module for graph viauzliation, MUST all have defined ID’s.

neo4j-arc does NOT generate or manage node/rel ID’s

Note: the displayed <id> is the value of NodeMode.id

We will not have any TypeDoc documentation, because the TypeScript version used in Neo4J Browser is not supprted by the TypeDoc

Component Diagram (WIP)

neo4j browser

  • The orange triangle labled with "On Canvas Interaction" is discussed in detail in graph interactions section

  • Sentry.io is initialized in the top index.tsx

  • AppInit.tsx is responsible for several initializations:

    • Redux

    • Suber (discussed below)

    • Apollo GraphQL Client

    • Drag & Drop Plugin

    The initialization assumes provider pattern around regular App component:

<Provider store={store as any}>
  <BusProvider bus={bus}>
    <ApolloProvider client={client}>
      <DndProvider backend={HTML5Backend}>
        <App />
      </DndProvider>
    </ApolloProvider>
  </BusProvider>
</Provider>
  • Neo4J Browser styling is implemented via styled-components and is initialized in App.tsx

What is Suber?

Looking at suber-related code (bus), we feel that it is very similar to Redux. It’s true that both Suber and Redux are designed to decouple React components.

Redux decouples components via "state", which makes it great for shared application state handling. Essentially, if one component A depends on component B via a state S; when S is updated in B, A gets re-rendered accordingly. Redux is our choice in this case

But what if component A depends on B via a prop that is not a state? For example, if component B is a database client and component A is a user registration form, then there is no concept of state S between A and B, because between A and B is just a one-time username/password message. Application state that is not shared should not go into Redux, it should go directly into the component that needs it.

This is where suber comes in.

redux vs suber

How is Suber Used in neo4j-browser?

This is how all those Epics from redux-observable come into play

The "sender" of Suber bus is a graphing component who wants to persists some data into Neo4j database. For example, when we add a new node onto canvas, the graphing component initiates a Cypher query and feeds it into the Suber bus.

We now know who the "sender" is at one end of Suber bus. Who is the receiver them? In its simplest form, our receiver can simply be regular TypeScript class. We also notice that Suber works with Redux. So how about having Redux as our "reciver"?

If we do that, we will need to wire up some logic that sends the Cypher query against Neo4j database. Redux middleware combined with redux-observable is able to perform that logic for us.

In neo4j-browser, the cypherRequestEpic in cypherDuck implements the "receiver". It takes a Cypher query and use the Neo4j’s Bolt Protocol to write the data int Neo4j database.

In summary:

suber epic