Skip to content

Commit

Permalink
Store and restore the router from json (#6)
Browse files Browse the repository at this point in the history
The routes in the router usually never change during runtime. We could
construct the router during compile time in some cases. This feature
allows us to save and restore the configuration of the router so we can
initialize the router faster and more convenient!

Also the typescript configuration was fixed, it was not generating types
and sourcemaps, that had quite a few consequences!
  • Loading branch information
Elmer Bulthuis authored Nov 8, 2023
1 parent 1a78f66 commit 28d161c
Show file tree
Hide file tree
Showing 9 changed files with 103 additions and 13 deletions.
7 changes: 4 additions & 3 deletions goodrouter-ts/.vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@
"name": "run file",
"program": "${file}",
"args": [],
"cwd": "${workspaceRoot}",
"cwd": "${workspaceFolder}",
"sourceMaps": true,
"outFiles": ["${workspaceRoot}/out/**/*.js"],
"preLaunchTask": "watch"
"outFiles": ["${workspaceFolder}/out/**/*.js"],
"preLaunchTask": "watch",
"outputCapture": "std"
}
]
}
6 changes: 3 additions & 3 deletions goodrouter-ts/.vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
"version": "2.0.0",
"tasks": [
{
"type": "typescript",
"type": "npm",
"label": "watch",
"tsconfig": "tsconfig.json",
"option": "watch",
"script": "watch",
"isBackground": true,
"problemMatcher": ["$tsc-watch"],
"group": {
"kind": "build",
Expand Down
1 change: 1 addition & 0 deletions goodrouter-ts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
],
"scripts": {
"build": "tsc",
"watch": "tsc --watch",
"clean": "rm -rf out",
"test": "npm run spec-all",
"lint": "prettier --check *",
Expand Down
1 change: 1 addition & 0 deletions goodrouter-ts/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from "./route-node-json.js";
export * from "./router-options.js";
export * from "./router.js";
6 changes: 6 additions & 0 deletions goodrouter-ts/src/route-node-json.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export interface RouteNodeJson<K extends string | number> {
anchor: string;
hasParameter: boolean;
routeKey: K | null;
children: RouteNodeJson<K>[];
}
45 changes: 45 additions & 0 deletions goodrouter-ts/src/route-node.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { permutations } from "itertools";
import assert from "node:assert/strict";
import test from "node:test";
import { RouteNodeJson } from "./route-node-json.js";
import { RouteNode } from "./route-node.js";
import { defaultRouterOptions } from "./router-options.js";
import { parseTemplatePairs } from "./template.js";
Expand Down Expand Up @@ -60,3 +61,47 @@ test("route-node-sort", () => {

assert.deepEqual(nodesActual, nodesExpected);
});

test("route-node-json", () => {
const node = new RouteNode();
node.insert(1, [
...parseTemplatePairs(
"x/y",
defaultRouterOptions.parameterPlaceholderRE,
),
]);
node.insert(2, [
...parseTemplatePairs(
"x/z",
defaultRouterOptions.parameterPlaceholderRE,
),
]);
const actual = node.toJSON();
const expected: RouteNodeJson<number> = {
anchor: "",
hasParameter: false,
routeKey: null,
children: [
{
anchor: "x/",
hasParameter: false,
routeKey: null,
children: [
{
anchor: "y",
hasParameter: false,
routeKey: 1,
children: [],
},
{
anchor: "z",
hasParameter: false,
routeKey: 2,
children: [],
},
],
},
],
};
assert.deepEqual(actual, expected);
});
34 changes: 28 additions & 6 deletions goodrouter-ts/src/route-node.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { RouteNodeJson } from "./route-node-json.js";
import { findCommonPrefixLength } from "./utils/string.js";

/**
Expand All @@ -22,14 +23,13 @@ export class RouteNode<K extends string | number> {
* key that identifies the route, if this is a leaf node for the route
*/
public routeKey: K | null = null,
/**
* @description
* children that represent the rest of the path that needs to be matched
*/
private readonly children = new Array<RouteNode<K>>(),
) {}

/**
* @description
* children that represent the rest of the path that needs to be matched
*/
private readonly children = new Array<RouteNode<K>>();

private addChild(childNode: RouteNode<K>) {
this.children.push(childNode);
}
Expand Down Expand Up @@ -323,4 +323,26 @@ export class RouteNode<K extends string | number> {

return 0;
}

public toJSON(): RouteNodeJson<K> {
const json = {
anchor: this.anchor,
hasParameter: this.hasParameter,
routeKey: this.routeKey,
children: this.children.map((child) => child.toJSON()),
};
return json;
}

public static fromJSON<K extends string | number>(
json: RouteNodeJson<K>,
): RouteNode<K> {
const node = new RouteNode(
json.anchor,
json.hasParameter,
json.routeKey,
json.children.map((child) => RouteNode.fromJSON(child)),
);
return node;
}
}
12 changes: 12 additions & 0 deletions goodrouter-ts/src/router.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { RouteNodeJson } from "./route-node-json.js";
import { RouteNode } from "./route-node.js";
import { defaultRouterOptions, RouterOptions } from "./router-options.js";
import { parseTemplatePairs } from "./template.js";
Expand Down Expand Up @@ -154,4 +155,15 @@ export class Router<K extends string | number> {
}
return result;
}

public saveToJSON(): RouteNodeJson<K> {
const json = this.rootNode.toJSON();
return json;
}

public loadFromJSON(json: RouteNodeJson<K>) {
const node = RouteNode.fromJSON(json);
this.rootNode = node;
return this;
}
}
4 changes: 3 additions & 1 deletion goodrouter-ts/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
"extends": "@tsconfig/node20",
"compilerOptions": {
"outDir": "./out",
"rootDir": "./src"
"rootDir": "./src",
"sourceMap": true,
"declaration": true
},
"include": ["src/**/*"]
}

0 comments on commit 28d161c

Please sign in to comment.