Home > other >  NodeJS: Creating a tree from a string for http routing
NodeJS: Creating a tree from a string for http routing

Time:01-23

I am trying to create a tree like radix tree for http routing

My code:

interface Node {
  nodes?: Record<string, Node>
  methods?: Record<string, () => unknown>
}

class Tree {
  root: Node

  constructor() {
    this.root = {}
  }

  insert(path: string, method: string, handler: () => unknown): void {
    let node = this.root

    path.split('/').forEach((path: string): void => {
      path = path === '' ? '/' : path

      node.nodes = node.nodes ?? {}

      const child = node.nodes[path] ?? {}

      node.nodes[path] = child

      node = child
    })

    node.methods = node.methods ?? {}

    if (!node.methods[method]) {
      node.methods[method] = handler
    }
  }
}

const tree = new Tree()

tree.insert('/users', 'GET', (): string => {
  return 'users get handler'
})
tree.insert('/posts', 'GET', (): string => {
  return 'posts get handler'
})
tree.insert('/profile', 'GET', (): string => {
  return 'profile get handler'
})
tree.insert('/profile/posts', 'GET', (): string => {
  return 'profile posts get handler'
})
tree.insert('/profile/friends', 'GET', (): string => {
  return 'profile friends get handler'
})

console.log(
  JSON.stringify(tree),
)

Expected result:

{
  root: {
    nodes: {
      "/": {
        nodes: {
          users: {
            methods: {
              GET: handler,
            },
          },
          posts: {
            methods: {
              GET: handler,
            },
          },
          profile: {
            methods: {
              GET: handler,
            },
            nodes: {
              posts: {
                methods: {
                  GET: handler,
                },
              },
              friends: {
                methods: {
                  GET: handler,
                },
              },
            },
          },
        },
      },
    },
  },
}

I would like to replace the root variable with nodes in the Tree class:

class Tree {
  nodes: Record<string, Node>
}

To get the desired result:

{
  nodes: {
    "/": {
      nodes: {
        users: {
          methods: {
            GET: handler,
          },
        },
        posts: {
          methods: {
            GET: handler,
          },
        },
        profile: {
          methods: {
            GET: handler,
          },
          nodes: {
            posts: {
              methods: {
                GET: handler,
              },
            },
            friends: {
              methods: {
                GET: handler,
              },
            },
          },
        },
      },
    },
  },
}

I tried several times to implement what I wanted, but in the end I got confused with my own code...

PS: Thank you all in advance for your answers :)

CodePudding user response:

To achieve that your class works with a nodes member instead of root, you only need to change the first statement in your insert method.

Replace:

    let node = this.root

with:

    let node = { nodes: this.nodes };
  • Related