Skip to content

Commit 2b3fab3

Browse files
committed
update index
1 parent 99a0a5f commit 2b3fab3

6 files changed

+410
-388
lines changed

Readme.md

Lines changed: 51 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ To master a new concept, it's often best to begin from the ground up. This isn't
2020

2121
You won't just learn how Node.js works, but also why it operates in a particular way. The guide also includes discussions on relevant data structures and design patterns.
2222

23-
The book also includes a wide range of exercises specifically created to challenge you, that may require commitment and consistent effort on your part. The first exercises start from [chapter 7](/chapters/ch07-ex-implementing-a-trie.md)
23+
The book also includes a wide range of exercises specifically created to challenge you, that may require commitment and consistent effort on your part. The first exercises start from [chapter 7](/chapters/ch06.5-ex-implementing-a-trie.md)
2424

2525
This guide goes beyond the basics. We're focused on delivering a modular, optimized backend framework that is close to being production-ready. Topics like performance optimization, security measures, and various testing approaches will be covered to ensure the framework is both reliable and extendable.
2626

@@ -261,29 +261,53 @@ The repo for our backend framework- [Velocy](https://github.com/ishtms/velocy).
261261
- [Improving the `Router` API](/chapters/ch06.3-improving-the-router-api.md)
262262
- [The need for a `trie`](/chapters/ch06.4-the-need-for-a-trie.md)
263263
- [What is a `Trie` anyway?](/chapters/ch06.4-the-need-for-a-trie.md#what-is-a-trie-anyway)
264-
- [Exercise 1 - Implementing a `Trie`](/chapters/ch07-ex-implementing-a-trie.md#exercise-1---implementing-a-trie)
265-
- [Root Node](/chapters/ch07-ex-implementing-a-trie.md#root-node)
266-
- [End of the word](/chapters/ch07-ex-implementing-a-trie.md#end-of-the-word)
267-
- [Challenge 1: Basic Trie with `insert` Method](/chapters/ch07-ex-implementing-a-trie.md#challenge-1-basic-trie-with-insert-method)
268-
- [Requirements](/chapters/ch07-ex-implementing-a-trie.md#requirements)
269-
- [More details](/chapters/ch07-ex-implementing-a-trie.md#more-details)
270-
- [Solution](/chapters/ch07-ex-implementing-a-trie.md#solution)
271-
- [Challenge 2: Implement `search` method](/chapters/ch07-ex-implementing-a-trie.md#challenge-2-implement-search-method)
272-
- [Requirements](/chapters/ch07-ex-implementing-a-trie.md#requirements-1)
273-
- [More details](/chapters/ch07-ex-implementing-a-trie.md#more-details-1)
274-
- [Hints](/chapters/ch07-ex-implementing-a-trie.md#hints)
275-
- [Solution](#solution-1)
276-
- [Exercise 2 - Implementing our Trie based `Router`](/chapters/ch08-ex-implementing-router.md#exercise-2---implementing-our-trie-based-router)
277-
- [Challenge 1: Implementing the `addRoute` method](/chapters/ch08-ex-implementing-router.md#challenge-1-implementing-the-addroute-method)
278-
- [Requirements](/chapters/ch08-ex-implementing-router.md#requirements)
279-
- [More details](/chapters/ch08-ex-implementing-router.md#more-details)
280-
- [Hints](/chapters/ch08-ex-implementing-router.md#hints)
281-
- [Solution](/chapters/ch08-ex-implementing-router.md#solution)
282-
- [Explanation](/chapters/ch08-ex-implementing-router.md#explanation)
283-
- [Challenge 2: Implementing the `findRoute` method](/chapters/ch08-ex-implementing-router.md#challenge-2-implementing-the-findroute-method)
284-
- [Requirements](/chapters/ch08-ex-implementing-router.md#requirements-1)
285-
- [More details](/chapters/ch08-ex-implementing-router.md#more-details-1)
286-
- [Starting Boilerplate](/chapters/ch08-ex-implementing-router.md#starting-boilerplate)
287-
- [Hints](/chapters/ch08-ex-implementing-router.md#hints-1)
288-
- [Solution](/chapters/ch08-ex-implementing-router.md#solution-1)
289-
- [Explanation](/chapters/ch08-ex-implementing-router.md#explanation-1)
264+
- [Exercise 1 - Implementing a `Trie`](/chapters/ch06.5-ex-implementing-a-trie.md#exercise-1---implementing-a-trie)
265+
- [Root Node](/chapters/ch06.5-ex-implementing-a-trie.md#root-node)
266+
- [End of the word](/chapters/ch06.5-ex-implementing-a-trie.md#end-of-the-word)
267+
- [Challenge 1: Basic Trie with `insert` Method](/chapters/ch06.5-ex-implementing-a-trie.md#challenge-1-basic-trie-with-insert-method)
268+
- [Requirements](/chapters/ch06.5-ex-implementing-a-trie.md#requirements)
269+
- [More details](/chapters/ch06.5-ex-implementing-a-trie.md#more-details)
270+
- [Solution](/chapters/ch06.5-ex-implementing-a-trie.md#solution)
271+
- [Challenge 2: Implement `search` method](/chapters/ch06.5-ex-implementing-a-trie.md#challenge-2-implement-search-method)
272+
- [Requirements](/chapters/ch06.5-ex-implementing-a-trie.md#requirements-1)
273+
- [More details](/chapters/ch06.5-ex-implementing-a-trie.md#more-details-1)
274+
- [Hints](/chapters/ch06.5-ex-implementing-a-trie.md#hints)
275+
- [Solution](/chapters/ch06.5-ex-implementing-a-trie.md#solution-1)
276+
- [Exercise 2 - Implementing our Trie based `Router`](/chapters/ch06.6-ex-implementing-router.md#exercise-2---implementing-our-trie-based-router)
277+
- [Challenge 1: Implementing the `addRoute` method](/chapters/ch06.6-ex-implementing-router.md#challenge-1-implementing-the-addroute-method)
278+
- [Requirements](/chapters/ch06.6-ex-implementing-router.md#requirements)
279+
- [More details](/chapters/ch06.6-ex-implementing-router.md#more-details)
280+
- [Hints](/chapters/ch06.6-ex-implementing-router.md#hints)
281+
- [Solution](/chapters/ch06.6-ex-implementing-router.md#solution)
282+
- [Explanation](/chapters/ch06.6-ex-implementing-router.md#explanation)
283+
- [Challenge 2: Implementing the `findRoute` method](/chapters/ch06.6-ex-implementing-router.md#challenge-2-implementing-the-findroute-method)
284+
- [Requirements](/chapters/ch06.6-ex-implementing-router.md#requirements-1)
285+
- [More details](/chapters/ch06.6-ex-implementing-router.md#more-details-1)
286+
- [Starting Boilerplate](/chapters/ch06.6-ex-implementing-router.md#starting-boilerplate)
287+
- [Hints](/chapters/ch06.6-ex-implementing-router.md#hints-1)
288+
- [Solution](/chapters/ch06.6-ex-implementing-router.md#solution-1)
289+
- [Explanation](/chapters/ch06.6-ex-implementing-router.md#explanation-1)
290+
- [Exercise 3 - Adding `HTTP` method support](/chapters/ch06.6-ex-implementing-router.md#explanation-1#exercise-3-adding-http-method-support)
291+
- [Requirements](/chapters/ch06.7-ex-adding-http-methods#requirements)
292+
- [More details](/chapters/ch06.7-ex-adding-http-methods#more-details)
293+
- [Example](/chapters/ch06.7-ex-adding-http-methods#example)
294+
- [Hints](/chapters/ch06.7-ex-adding-http-methods#hints)
295+
- [Solution](/chapters/ch06.7-ex-adding-http-methods#solution)
296+
- [Exercise 4 - Implementing Dynamic Routing](/chapters/ch06.8-ex-dynamic-routing#exercise-4-implementing-dynamic-routing)
297+
- [Why Dynamic Routing?](/chapters/ch06.8-ex-dynamic-routing#why-dynamic-routing)
298+
- [Flexibility](/chapters/ch06.8-ex-dynamic-routing#flexibility)
299+
- [Better User Experience](/chapters/ch06.8-ex-dynamic-routing#better-user-experience)
300+
- [Better Developer Experience](/chapters/ch06.8-ex-dynamic-routing#better-developer-experience)
301+
- [Better SEO](/chapters/ch06.8-ex-dynamic-routing#better-seo)
302+
- [Anatomy of a dynamic route](/chapters/ch06.8-ex-dynamic-routing#anatomy-of-a-dynamic-route)
303+
- [Challenge 1: Update the `getRouteParts()` function](/chapters/ch06.8-ex-dynamic-routing#challenge-1-update-the-getrouteparts-function)
304+
- [Requirement](/chapters/ch06.8-ex-dynamic-routing#requirement)
305+
- [More Details:](/chapters/ch06.8-ex-dynamic-routing#more-details)
306+
- [Solution](/chapters/ch06.8-ex-dynamic-routing#solution)
307+
- [Challenge 2: Add the dynamic routing functionality in `Router` class](/chapters/ch06.8-ex-dynamic-routing#challenge-2-add-the-dynamic-routing-functionality-in-router-class)
308+
- [Requirements](/chapters/ch06.8-ex-dynamic-routing#requirements)
309+
- [More Details](/chapters/ch06.8-ex-dynamic-routing#more-details-1)
310+
- [Steps](/chapters/ch06.8-ex-dynamic-routing#steps)
311+
- [Solution](/chapters/ch06.8-ex-dynamic-routing#solution-1)
312+
- [Challenge 3: Adding Wildcard (Catch-All) Route Support](/chapters/ch06.8-ex-dynamic-routing#challenge-3-adding-wildcard-catch-all-route-support) - [More Details](/chapters/ch06.8-ex-dynamic-routing#more-details-2) - [Steps](/chapters/ch06.8-ex-dynamic-routing#steps-1)
313+
- [Solution](/chapters/ch06.8-ex-dynamic-routing#solution-2)

chapters/ch06.4-the-need-for-a-trie.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,4 +105,4 @@ Every node, including `root` will be an object that contain some necessary infor
105105

106106
Enough with the theory. In the next chapter, we'll dive into our very first exercise for this book: **implementing a Trie**.
107107

108-
[![Read Next](/assets/imgs/next.png)](/chapters/ch07-ex-implementing-a-trie.md)
108+
[![Read Next](/assets/imgs/next.png)](/chapters/ch06.5-ex-implementing-a-trie.md)

chapters/ch07-ex-implementing-a-trie.md renamed to chapters/ch06.5-ex-implementing-a-trie.md

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[![Read Prev](/assets/imgs/prev.png)](/chapters/ch06.4-the-need-for-a-trie.md)
22

3-
# Exercise 1 - Implementing a `Trie`
3+
## Exercise 1 - Implementing a `Trie`
44

55
> This exercise will motivate you to work on implementing your solution independently. Once you have completed the exercise, you can move on to the next challenge or read the solution to find a different approach.
66
>
@@ -14,7 +14,7 @@ Here's an illustration that shows how does a `Trie` look like in theory:
1414

1515
Here's how you can visualize the Trie above based on the words "OK", "TO", "CAR", "CAT", and "CUP":
1616

17-
## Root Node
17+
### Root Node
1818

1919
The Trie starts with a root node that doesn't hold any character. It serves as the starting point of the Trie.
2020

@@ -32,7 +32,7 @@ The Trie starts with a root node that doesn't hold any character. It serves as t
3232
- "A" further branches to "R" for "CAR" and "T" for "CAT".
3333
- "U" further branches to "P", completing the word "CUP".
3434

35-
## End of the word
35+
### End of the word
3636

3737
The "end of the word" is often represented by a boolean flag at a node to signify that the path from the root of the Trie to that node corresponds to a complete word. This flag helps distinguish between a string that is merely a prefix and one that is a full word in the Trie.
3838

@@ -44,16 +44,16 @@ Here's an another illustration to explain the "end-of-word" (EOW):
4444

4545
![](/assets/imgs/trie-eow.png)
4646

47-
## Challenge 1: Basic Trie with `insert` Method
47+
### Challenge 1: Basic Trie with `insert` Method
4848

4949
In this first challenge, your task is to implement a Trie data structure with only one functionality: inserting a word into the Trie.
5050

51-
### Requirements
51+
#### Requirements
5252

5353
1. Create a class called `Trie`.
5454
2. Implement an `insert(word)` method that takes a string `word` and inserts it into the Trie.
5555

56-
### More details
56+
#### More details
5757

5858
1. **Initialization**: You'll begin with a root node. This node will be the starting point for all word insertions, and it won't store any character itself.
5959

@@ -104,7 +104,7 @@ Great. You just implemented a `Trie` which is a Tree data structure. You've also
104104

105105
> In case you were not able to figure out what to do, I would still like you to scrap the code you've written and start again from scratch. Get a pen and paper, and visualize it. That way you can convert hard problems into easier ones.
106106
107-
### Solution
107+
#### Solution
108108

109109
```js
110110
class Trie {
@@ -219,7 +219,7 @@ The previous code looks fine. However, as our backend library/framework prioriti
219219

220220
The code above is acceptable, and not a bad implementation. But we can do better.
221221

222-
### Using a `for` loop instead of recursion
222+
#### Using a `for` loop instead of recursion
223223

224224
I am not a big fan of recursion, and I prefer using loops over recursion most of the time. For loop is much easier to reason about and as someone who's reading the code, it's easier to understand what's going on.
225225

@@ -259,16 +259,16 @@ class Trie {
259259
}
260260
```
261261

262-
## Challenge 2: Implement `search` method
262+
### Challenge 2: Implement `search` method
263263

264264
Now that we have a Trie with insertion capabilities, let's add a `search` method.
265265

266-
### Requirements
266+
#### Requirements
267267

268268
1. Add a `search(word)` method to the `Trie` class.
269269
2. The method should return `true` if the word exists in the Trie and `false` otherwise.
270270

271-
### More details
271+
#### More details
272272

273273
1. **Start at the Root**: Begin your search at the root node.
274274
2. **Traversal**: For each character in the word, traverse down the Trie, going from one node to its child that corresponds to the next character.
@@ -292,7 +292,7 @@ Go ahead and implement the `Trie.search` method. Don't read anything below befor
292292

293293
If you are having trouble or are stuck, here are some hints to help you with the implementation -
294294

295-
### Hints
295+
#### Hints
296296

297297
1. **Starting Point**: Similar to the `insert` method, you'll start at the root node and traverse the Trie based on the characters in the word you're searching for.
298298

@@ -312,7 +312,7 @@ If you are having trouble or are stuck, here are some hints to help you with the
312312

313313
Good luck!
314314

315-
### Solution
315+
#### Solution
316316

317317
Again, I chose to implement tree traversal using a for loop instead of recursion.
318318

@@ -345,4 +345,4 @@ search(word) {
345345

346346
Awesome work. Now you know the basics of the `Trie` data structure and how to implement it. In the next exercise, we'll implement our `Router` from scratch! The next exercise will be more challenging and exhaustive.
347347

348-
[![Read Next](/assets/imgs/next.png)](/chapters/ch08-ex-implementing-router.md)
348+
[![Read Next](/assets/imgs/next.png)](/chapters/ch06.6-ex-implementing-router.md)

chapters/ch08-ex-implementing-router.md renamed to chapters/ch06.6-ex-implementing-router.md

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
1-
[![Read Prev](/assets/imgs/prev.png)](/chapters/ch07-ex-implementing-a-trie.md)
1+
[![Read Prev](/assets/imgs/prev.png)](/chapters/ch06.5-ex-implementing-a-trie.md)
22

3-
# Exercise 2 - Implementing our Trie based `Router`
3+
## Exercise 2 - Implementing our Trie based `Router`
44

55
> This challenge is designed to push your boundaries and is considered to be more advanced than usual. It's completely okay if you don't crack it on your first attempt. The key is to persist, revisit your logic, and don't hesitate to iterate on your solutions.
66
77
Since we just built a Trie data structure that can efficiently insert and search words, we can further enhance its capabilities by extending it to implement a Trie-based router for matching URL patterns. This powerful application of `Trie` data structure is commonly utilized in web frameworks, where it plays a crucial role in efficiently routing incoming HTTP requests to their respective handler functions.
88

99
By building a `Trie`-based router, our framework can achieve optimal performance and scalability, ensuring that each request is efficiently directed to the appropriate handler for processing.
1010

11-
## Challenge 1: Implementing the `addRoute` method
11+
### Challenge 1: Implementing the `addRoute` method
1212

13-
### Requirements
13+
#### Requirements
1414

1515
Create a new class, `TrieRouter`, similar to what we had earlier - `Trie`. Add a method, `addRoute`, that takes in a URL pattern (like `/home` or `/user/status/play`) as a first parameter and a handler function as second parameter. Then insert the URL pattern into the `TrieRouter`, associating the handler function with the last node of that pattern.
1616

17-
### More details
17+
#### More details
1818

1919
1. **Class Definition**: Define a class named `TrieRouter`. This class should contain:
2020

@@ -110,7 +110,7 @@ class RouteNode {
110110
}
111111
```
112112

113-
### Hints
113+
#### Hints
114114

115115
1. Remember that a Trie is a tree-like structure where each node represents a piece/segment of a URL. Understanding the hierarchy can simplify the process.
116116

@@ -125,7 +125,7 @@ class RouteNode {
125125
6. To deal with trailing slashes, and repeated slashes, you could write utility functions that normalize the path before processing it.
126126
7. You should throw an error if the path contains any whitespace.
127127

128-
### Solution
128+
#### Solution
129129

130130
Kudos to those who successfully implemented the `addRoute` function in the `TrieRouter` class. You've just completed the first difficult exercise in this book, showcasing not only your coding abilities but also your problem-solving skills.
131131

@@ -213,7 +213,7 @@ Output:
213213
```bash
214214
$node trie_router.js
215215

216-
# OUTPUT
216+
## OUTPUT
217217
-home
218218
-user
219219
--status
@@ -222,7 +222,7 @@ $node trie_router.js
222222

223223
Looks perfect. Let's go through the code and understand what's going on.
224224

225-
### Explanation
225+
#### Explanation
226226

227227
```js
228228
class RouteNode {
@@ -319,13 +319,13 @@ After the loop completes, the handler function is associated with the last node
319319
320320
That's it. We now have a working implementation of our router that supports adding routes. The next challenge involves finding a route and returning the handler associated with it.
321321
322-
## Challenge 2: Implementing the `findRoute` method
322+
### Challenge 2: Implementing the `findRoute` method
323323
324-
### Requirements
324+
#### Requirements
325325
326326
You've successfully implemented the `addRoute` method to build our `Trie`-based router. Now, lets extend our `TrieRouter` class by adding another method, `findRoute`. This method should take a URL pattern (e.g., `/home` or `/user/status/play`) as its parameter. Search the `TrieRouter` and find the handler function associated with the last node that matches the pattern.
327327
328-
### More details
328+
#### More details
329329
330330
1. **Method - `findRoute`**: Add a method to your `TrieRouter` class called `findRoute`.
331331
@@ -361,7 +361,7 @@ console.log(trieRouter.findRoute("/user/status/play")); // Should return null
361361
362362
Feel free to share your implementation or ask for feedback in the [Github discussions](https://github.com/ishtms/learn-nodejs-hard-way/discussions) section. I'll try to review all code submissions and provide feedback if required.
363363
364-
### Starting Boilerplate
364+
#### Starting Boilerplate
365365
366366
Feel free to use the starting boilerplate below. If you are comfortable, you may proceed without it.
367367
@@ -381,13 +381,13 @@ class TrieRouter {
381381
}
382382
```
383383
384-
### Hints
384+
#### Hints
385385
386386
1. When traversing the Trie, you may find it beneficial to break down the URL pattern into segments just like you did while inserting the route.
387387
388388
2. Be careful about the return values. Ensure you return the handler function if a match is found and a suitable indicator (like `null`) if no match exists.
389389
390-
### Solution
390+
#### Solution
391391
392392
Here's the solution that I came up with:
393393
@@ -433,7 +433,7 @@ class RouteNode {
433433
}
434434
```
435435
436-
### Explanation
436+
#### Explanation
437437
438438
```js
439439
findRoute(path) {

0 commit comments

Comments
 (0)