Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 28 additions & 13 deletions packages/ingest/src/Router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import EventRouter from '@stackpress/lib/EventRouter';
//common
import type {
RouterAction,
RouterActions,
RouterEmitter,
RouterImport,
RouterQueueArgs
} from './types';
import Request from './Request';
Expand Down Expand Up @@ -52,7 +54,7 @@ export default class Router<
*/
public all(
path: string,
action: RouterAction<R, S, X>,
action: RouterActions<R, S, X>,
priority?: number
) {
return this.route('[A-Z]+', path, action, priority);
Expand All @@ -63,7 +65,7 @@ export default class Router<
*/
public connect(
path: string,
action: RouterAction<R, S, X>,
action: RouterActions<R, S, X>,
priority?: number
) {
return this.route('CONNECT', path, action, priority);
Expand All @@ -74,7 +76,7 @@ export default class Router<
*/
public delete(
path: string,
action: RouterAction<R, S, X>,
action: RouterActions<R, S, X>,
priority?: number
) {
return this.route('DELETE', path, action, priority);
Expand All @@ -85,7 +87,7 @@ export default class Router<
*/
public get(
path: string,
action: RouterAction<R, S, X>,
action: RouterActions<R, S, X>,
priority?: number
) {
return this.route('GET', path, action, priority);
Expand All @@ -96,7 +98,7 @@ export default class Router<
*/
public head(
path: string,
action: RouterAction<R, S, X>,
action: RouterActions<R, S, X>,
priority?: number
) {
return this.route('HEAD', path, action, priority);
Expand All @@ -107,7 +109,7 @@ export default class Router<
*/
public options(
path: string,
action: RouterAction<R, S, X>,
action: RouterActions<R, S, X>,
priority?: number
) {
return this.route('OPTIONS', path, action, priority);
Expand All @@ -118,7 +120,7 @@ export default class Router<
*/
public patch(
path: string,
action: RouterAction<R, S, X>,
action: RouterActions<R, S, X>,
priority?: number
) {
return this.route('PATCH', path, action, priority);
Expand All @@ -129,7 +131,7 @@ export default class Router<
*/
public post(
path: string,
action: RouterAction<R, S, X>,
action: RouterActions<R, S, X>,
priority?: number
) {
return this.route('POST', path, action, priority);
Expand All @@ -140,7 +142,7 @@ export default class Router<
*/
public put(
path: string,
action: RouterAction<R, S, X>,
action: RouterActions<R, S, X>,
priority?: number
) {
return this.route('PUT', path, action, priority);
Expand All @@ -151,7 +153,7 @@ export default class Router<
*/
public trace(
path: string,
action: RouterAction<R, S, X>,
action: RouterActions<R, S, X>,
priority?: number
) {
return this.route('TRACE', path, action, priority);
Expand All @@ -163,7 +165,7 @@ export default class Router<
public route(
method: Method|'[A-Z]+',
path: string,
action: RouterAction<R, S, X>,
action: RouterActions<R, S, X>,
priority?: number
) {
//convert path to a regex pattern
Expand All @@ -175,14 +177,27 @@ export default class Router<
.replaceAll('*', '([^/]+)')
//** -> ([^/]+)([^/]+) -> (.*)
.replaceAll('([^/]+)([^/]+)', '(.*)');

//now form the event pattern
const event = new RegExp(`^${method}\\s${pattern}/*$`, 'ig');
this.routes.set(event.toString(), {
method: method === '[A-Z]+' ? 'ALL' : method,
path: path
});
//add to tasks
return this.on(event, action, priority);

//delegate to appropriate router based on action type
if (typeof action === 'string') {
//view router for string paths
this.view.on(event, action, priority);
} else if (typeof action === 'function' && action.length === 0) {
//import router for parameterless functions
this.imports.on(event, action as RouterImport, priority);
} else {
//default router for request/response handlers
this.on(event, action as RouterAction<R, S, X>, priority);
}

return this;
}

/**
Expand Down
6 changes: 6 additions & 0 deletions packages/ingest/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,12 @@ export type RouterImport = () => Promise<{
default: RouterAction<any, any, any>
}>;

export type RouterActions<
R = unknown,
S = unknown,
X = unknown
> = string | RouterAction<R, S, X> | RouterImport;

export type RouterQueueArgs<
R = unknown,
S = unknown,
Expand Down
42 changes: 42 additions & 0 deletions packages/ingest/tests/Router.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type { RouterImport } from '../src/types';
import Router from '../src/Router';
import Request from '../src/Request';
import Response from '../src/Response';
import ViewRouter from '../src/router/ViewRouter';

type method = 'all'
| 'connect' | 'delete' | 'get'
Expand Down Expand Up @@ -267,4 +268,45 @@ describe('Router Tests', () => {

expect(res.body).to.equal('router1');
});

it('Should handle flexible routing types', async () => {
const router = new Router();
expect(router).to.be.instanceOf(Router);
router.view.engine = function (filePath, req, res) {
res.setBody('text/plain', filePath);
}
// Set up routes with different action types
router.get('/view/path', './templates/view.html');
router.get('/import/path', () => import('./fixtures/get'));
router.get('/standard/path', (req, res) => {
res.setBody('text/plain', 'standard response');
});

// Test view routing
const viewRequest = new Request({
method: 'GET',
url: new URL('http://localhost/view/path')
});
const viewResponse = new Response();
await router.emit('GET /view/path', viewRequest, viewResponse);
expect(viewResponse.body).to.equal('./templates/view.html');

// Test import routing
const importRequest = new Request({
method: 'GET',
url: new URL('http://localhost/import/path')
});
const importResponse = new Response();
await router.emit('GET /import/path', importRequest, importResponse);
expect(importResponse.body).to.equal('/import/path');

// Test standard routing
const standardRequest = new Request({
method: 'GET',
url: new URL('http://localhost/standard/path')
});
const standardResponse = new Response();
await router.emit('GET /standard/path', standardRequest, standardResponse);
expect(standardResponse.body).to.equal('standard response');
});
})