func (g *Graph) AddNode(n *Node) error {
	if n.Canonical == "" {
		return errcode.ErrGraphRequiredNodeCanonical
	}
	if n.ID == "" {
		return errcode.ErrGraphRequiredNodeID
	}
	if _, ok := g.nodesCans[n.Canonical]; ok {
		return fmt.Errorf("with canonical %q: %w", n.Canonical, errcode.ErrGraphAlreadyExistsNode)
	}
	if _, ok := g.nodesIDs[n.ID]; ok {
		return errcode.ErrGraphAlreadyExistsNodeID
	}
	g.nodesCans[n.Canonical] = n
	g.nodesIDs[n.ID] = n
	g.Nodes = append(g.Nodes, n)
	return nil
}
AddNode adds an Node to the Graph
package graph
import (
	"fmt"
	"github.com/cycloidio/inframap/errcode"
)
type Graph struct {
	Edges []*Edge
	Nodes []*Node
	nodesCans map[string]*Node
	nodesIDs map[string]*Node
	nodesWithEdge map[string][]*Edge
	edgesSourceTarget map[string]*Edge
	edgesIDs map[string]*Edge
}
func New() *Graph {
	return &Graph{
		nodesCans:         make(map[string]*Node),
		nodesIDs:          make(map[string]*Node),
		edgesSourceTarget: make(map[string]*Edge),
		edgesIDs:          make(map[string]*Edge),
		nodesWithEdge: make(map[string][]*Edge),
	}
}
func (g *Graph) AddEdge(e *Edge) error {
	if e.ID == "" {
		return errcode.ErrGraphRequiredEdgeID
	}
	if e.Target == "" {
		return errcode.ErrGraphRequiredEdgeTarget
	}
	if e.Source == "" {
		return errcode.ErrGraphRequiredEdgeSource
	}
	if _, ok := g.nodesIDs[e.Target]; !ok {
		return errcode.ErrGraphNotFoundEdgeTarget
	}
	if _, ok := g.nodesIDs[e.Source]; !ok {
		return errcode.ErrGraphNotFoundEdgeSource
	}
	check := e.Source + e.Target
	if _, ok := g.edgesSourceTarget[check]; ok {
		return errcode.ErrGraphAlreadyExistsEdge
	}
	if _, ok := g.edgesIDs[e.ID]; ok {
		return errcode.ErrGraphAlreadyExistsEdgeID
	}
	g.edgesSourceTarget[check] = e
	g.edgesIDs[e.ID] = e
	g.nodesWithEdge[e.Source] = append(g.nodesWithEdge[e.Source], e)
	g.nodesWithEdge[e.Target] = append(g.nodesWithEdge[e.Target], e)
	g.Edges = append(g.Edges, e)
	return nil
}