Skip to content

Commit 41a35ab

Browse files
committed
first pass on new, simpler routing
1 parent c2c2623 commit 41a35ab

29 files changed

+356
-462
lines changed

example/ts/package-lock.json

+5-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

example/ts/src/client.ts

+8-9
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,31 @@
11
/**
22
* client.ts
3-
* Copyright(c) 2021 Aaron Hedges <[email protected]>
3+
* Copyright(c) 2025 Aaron Hedges <[email protected]>
44
* MIT Licensed
55
*
66
* This file is an example of using roads router in the client
77
*/
88

9-
import { Road, RoadsPJAX, ParseBodyMiddleware, RouterMiddleware, CookieMiddleware, Request } from 'roads';
10-
import applyPublicRotues from './routes/applyPublicRoutes';
9+
import { Road, RoadsPJAX, ParseBodyMiddleware, CookieMiddleware, Request } from 'roads';
10+
import applyPublicRoutes from './routes/applyPublicRoutes';
1111
import emptyTo404 from './middleware/emptyTo404';
1212

1313
const road = new Road();
1414

15-
road.use(function (method, url, body, headers, next) {
15+
road.beforeRoute(function (method, url, body, headers, next) {
1616
console.log(`fake ${ method } request to...`, url);
1717
return next();
1818
});
1919

2020
const pjax = new RoadsPJAX(road, document.getElementById('container') as HTMLAnchorElement, window);
2121
pjax.addTitleMiddleware('roads-title');
22-
road.use(emptyTo404);
23-
road.use(ParseBodyMiddleware.middleware);
22+
road.beforeRoute(emptyTo404);
23+
road.beforeRoute(ParseBodyMiddleware.middleware);
2424
// Todo: get this set up properly, then check cokie and stor val on the server
25-
road.use(CookieMiddleware.buildClientMiddleware(document));
25+
road.beforeRoute(CookieMiddleware.buildClientMiddleware(document));
2626
pjax.register();
2727
pjax.registerAdditionalElement(document.getElementById('home') as HTMLAnchorElement);
28-
const router = new RouterMiddleware.Router(road);
29-
applyPublicRotues(router);
28+
applyPublicRoutes(road);
3029

3130
const testRequest = new Request(false, 'localhost', 8081);
3231
testRequest.request('GET', '/').then(response => {

example/ts/src/middleware/addLayout.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
/**
22
* addLayout.ts
3-
* Copyright(c) 2018 Aaron Hedges <[email protected]>
3+
* Copyright(c) 2025 Aaron Hedges <[email protected]>
44
* MIT Licensed
55
*
66
* This file is an example of how to apply HTML layouts via a middleware system
77
*/
88

9-
import { Middleware } from 'roads/types/core/road';
109
import { Response } from 'roads';
1110
const TITLE_KEY = 'page-title';
1211
import { StoreValsContext } from 'roads/types/middleware/storeVals';
12+
import { Route } from '../../../../types/core/router';
1313

1414
/**
1515
* Example function to wrap an HTML body in the required surrounding HTML tags (commonly called a layout)
@@ -50,7 +50,7 @@ function wrapLayout(body: string | Buffer, vals: {
5050
* @param {object} headers - HTTP request headers
5151
* @param {function} next - When called, this function will execute the next step in the roads method chain
5252
*/
53-
const addLayoutMiddleware: Middleware<StoreValsContext> = function addLayoutMiddleware (method, url, body, headers, next) {
53+
const addLayoutMiddleware: Route<StoreValsContext> = function addLayoutMiddleware (method, url, body, headers, next) {
5454
return next()
5555
.then((response) => {
5656
if (!(response instanceof Response)) {

example/ts/src/middleware/emptyTo404.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
/**
22
* emptyTo404.ts
3-
* Copyright(c) 2021 Aaron Hedges <[email protected]>
3+
* Copyright(c) 2025 Aaron Hedges <[email protected]>
44
* MIT Licensed
55
*
66
* This file is an example of how to apply HTML layouts via a middleware system
77
*/
88

9-
import { Middleware, Context } from 'roads/types/core/road';
9+
import { Context } from 'roads/types/core/road';
1010
import { Response } from 'roads';
11+
import { Route } from '../../../../types/core/router';
1112

1213
/**
1314
* This middleware translates missing responses into 404s
@@ -18,7 +19,7 @@ import { Response } from 'roads';
1819
* @param {object} headers - HTTP request headers
1920
* @param {function} next - When called, this function will execute the next step in the roads method chain
2021
*/
21-
const emptyTo404: Middleware<Context> = function (method, url, body, headers, next) {
22+
const emptyTo404: Route<Context> = function (method, url, body, headers, next) {
2223
return next()
2324
.then((response) => {
2425
if (!response) {

example/ts/src/routes/applyPrivateRoutes.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
* applyPrivateRoutes.ts
3-
* Copyright(c) 2018 Aaron Hedges <[email protected]>
3+
* Copyright(c) 2025 Aaron Hedges <[email protected]>
44
* MIT Licensed
55
*
66
* This file is an example of how to assign some private routes to a road server
@@ -9,7 +9,7 @@
99
import * as fs from 'fs';
1010
import { CookieContext } from 'roads/types/middleware/cookieMiddleware';
1111
import { StoreValsContext } from 'roads/types/middleware/storeVals';
12-
import { RouterMiddleware, Response } from 'roads';
12+
import { Response, Road } from 'roads';
1313
const TITLE_KEY = 'page-title';
1414

1515
/**
@@ -19,8 +19,8 @@ const TITLE_KEY = 'page-title';
1919
*
2020
* @param {SimpleRouter} router - The router that the routes will be added to
2121
*/
22-
export default function applyPrivateRotues(router: RouterMiddleware.Router<StoreValsContext>): void {
23-
router.addRoute<CookieContext>('GET', '/private', async function () {
22+
export default function applyPrivateRotues(road: Road<StoreValsContext>): void {
23+
road.addRoute<CookieContext & StoreValsContext>('GET', '/private', async function () {
2424
this.storeVal(TITLE_KEY, 'Private Resource');
2525
this.setCookie('private_cookie', 'foo', {
2626
httpOnly: true
@@ -36,13 +36,13 @@ export default function applyPrivateRotues(router: RouterMiddleware.Router<Store
3636
<a href="/" data-roads="link">home</a>!<br />`);
3737
});
3838

39-
router.addRoute('GET', '/privateJSON', async function () {
39+
road.addRoute('GET', '/privateJSON', async function () {
4040
this.storeVal('ignoreLayout', true);
4141
return new Response(JSON.stringify({'private-success': true}));
4242
});
4343

4444
// eslint-disable-next-line @typescript-eslint/no-unused-vars
45-
router.addRoute('GET', 'client.js', async function (url, body, headers) {
45+
road.addRoute('GET', 'client.js', async function (url, body, headers) {
4646
this.storeVal('ignoreLayout', true);
4747
// In the real world the body of the response should be created from a template engine.
4848
return new Response(fs.readFileSync(`${__dirname }/../../../public/client.js`).toString('utf-8'), 200, {

example/ts/src/routes/applyPublicRoutes.ts

+8-6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
/**
22
* applyPublicRoutes.ts
3-
* Copyright(c) 2018 Aaron Hedges <[email protected]>
3+
* Copyright(c) 2025 Aaron Hedges <[email protected]>
44
* MIT Licensed
55
*
66
* This file is an example of how to assign some public routes to a roads server
77
*/
88

9-
import { Response, RouterMiddleware } from 'roads';
9+
import { Response, Road } from 'roads';
1010
const TITLE_KEY = 'page-title';
1111

1212
import { ParseBodyContext } from 'roads/types/middleware/parseBody';
@@ -24,8 +24,8 @@ interface ExampleRequestBody {
2424
*
2525
* @param {SimpleRouter} router - The router that the routes will be added to
2626
*/
27-
export default function applyPublicRotues(router: RouterMiddleware.Router<StoreValsContext>): void {
28-
router.addRoute('GET', '/', async function () {
27+
export default function applyPublicRoutes(road: Road<StoreValsContext>): void {
28+
road.addRoute('GET', '/', async function () {
2929
this.storeVal(TITLE_KEY, 'Root Resource');
3030

3131
// In the real world the body of the response should be created from a template engine.
@@ -39,7 +39,7 @@ export default function applyPublicRotues(router: RouterMiddleware.Router<StoreV
3939
});
4040
});
4141

42-
router.addRoute<CookieContext>('GET', '/public', async function () {
42+
road.addRoute<CookieContext & StoreValsContext>('GET', '/public', async function () {
4343
this.storeVal(TITLE_KEY, 'Public Resource');
4444
console.log('Here are all cookies accessible to this code: ', this.getCookies());
4545
console.log('Cookies are not set until you access the private route.');
@@ -59,7 +59,9 @@ export default function applyPublicRotues(router: RouterMiddleware.Router<StoreV
5959
});
6060

6161
// eslint-disable-next-line @typescript-eslint/no-unused-vars
62-
router.addRoute<ParseBodyContext<ExampleRequestBody>>('POST', '/postdata', async function (url, body, headers) {
62+
road.addRoute<
63+
StoreValsContext & ParseBodyContext<ExampleRequestBody>
64+
>('POST', '/postdata', async function (url, body, headers) {
6365
console.log(`You sent the message:${this.body?.message}`);
6466
this.ignore_layout = true;
6567
return new Response('', 302, { location: '/public' });

example/ts/src/server.ts

+7-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
* server.ts
3-
* Copyright(c) 2021 Aaron Hedges <[email protected]>
3+
* Copyright(c) 2025 Aaron Hedges <[email protected]>
44
* MIT Licensed
55
*
66
* This file starts up the HTTP roads server
@@ -17,19 +17,18 @@ import emptyTo404 from './middleware/emptyTo404';
1717

1818
const road = new Road();
1919

20-
road.use(function (method, url, body, headers, next) {
20+
road.beforeRoute(function (method, url, body, headers, next) {
2121
console.log(`${method} ${url}`);
2222
return next();
2323
});
2424

2525
attachCommonMiddleware(road);
26-
road.use(CookieMiddleware.serverMiddleware);
27-
road.use(addLayout);
26+
road.beforeRoute(CookieMiddleware.serverMiddleware);
27+
road.beforeRoute(addLayout);
2828

29-
const router = new RouterMiddleware.Router(road);
30-
applyPublicRotues(router);
31-
applyPrivateRoutes(router);
32-
road.use(emptyTo404);
29+
applyPublicRotues(road);
30+
applyPrivateRoutes(road);
31+
road.afterRoute(emptyTo404);
3332

3433
const server = new Server(road, function (err: Error) {
3534
console.log(err.stack);

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "roads",
3-
"version": "8.0.0-alpha.3",
3+
"version": "8.0.0-alpha.4",
44
"author": {
55
"name": "Aaron Hedges",
66
"email": "[email protected]",

src/client/pjax.ts

+10-9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
* pjax.ts
3-
* Copyright(c) 2021 Aaron Hedges <[email protected]>
3+
* Copyright(c) 2025 Aaron Hedges <[email protected]>
44
* MIT Licensed
55
*
66
* PJAX is a technique for speeding up webpages by automatically replacing links or
@@ -15,16 +15,17 @@
1515
*
1616
*/
1717

18-
import Road, { Middleware } from '../core/road';
18+
import Road, { Context } from '../core/road';
1919
import Response from '../core/response';
2020
import { StoreValsContext, middleware as storeValsMiddleware} from '../middleware/storeVals';
21+
import { Route } from '../core/router';
2122

2223
/**
2324
* This is a helper class to make PJAX easier. PJAX is a clean way of improving the performance of webpages
2425
* by progressively turning standard HTML links into AJAX requests for portions of a web page.
2526
*/
26-
export default class RoadsPjax {
27-
protected _road: Road;
27+
export default class RoadsPjax<PjaxContext extends Context & StoreValsContext> {
28+
protected _road: Road<PjaxContext>;
2829
protected _page_title?: string;
2930
protected _window: Window;
3031
protected _container_element: HTMLElement;
@@ -38,7 +39,7 @@ export default class RoadsPjax {
3839
* @param {HTMLElement} containerElement - The element that will be filled with your roads output
3940
* @param {Window} window - The page's window object to help set page title url
4041
*/
41-
constructor(road: Road, containerElement: HTMLElement, window: Window) {
42+
constructor(road: Road<PjaxContext>, containerElement: HTMLElement, window: Window) {
4243
this._road = road;
4344
this._page_title = undefined;
4445
this._window = window;
@@ -62,11 +63,11 @@ export default class RoadsPjax {
6263
* @param {titleKey} string - The key of the title as stored in the "storeVals" middleware.
6364
* @returns {RoadsPjax} Returns the PJAX object. This is provided to allow for easy function chaining.
6465
*/
65-
addTitleMiddleware (titleKey: string): RoadsPjax {
66+
addTitleMiddleware (titleKey: string): RoadsPjax<PjaxContext> {
6667
// eslint-disable-next-line @typescript-eslint/no-this-alias
6768
const pjaxObj = this;
6869

69-
const titleMiddleware: Middleware<StoreValsContext> = function (method, url, body, headers, next) {
70+
const titleMiddleware: Route<StoreValsContext> = function (method, url, body, headers, next) {
7071

7172
return next().then((response) => {
7273
if (this.getVal) {
@@ -77,8 +78,8 @@ export default class RoadsPjax {
7778
});
7879
};
7980

80-
this._road.use(storeValsMiddleware);
81-
this._road.use(titleMiddleware);
81+
this._road.beforeRoute(storeValsMiddleware);
82+
this._road.beforeRoute(titleMiddleware);
8283

8384
return this;
8485
}

src/client/request.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
* request.ts
3-
* Copyright(c) 2021 Aaron Hedges <[email protected]>
3+
* Copyright(c) 2025 Aaron Hedges <[email protected]>
44
* MIT Licensed
55
*
66
* This file exposes a Request object to offer an HTTP request library with a method signature that matches

src/core/requestChain.ts

-61
This file was deleted.

0 commit comments

Comments
 (0)