Skip to content
Open
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
38 changes: 37 additions & 1 deletion src/router.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { describe, expect, it } from "vitest";
import { describe, expect, it, assert } from "vitest";
import { createEndpoint, type Endpoint } from "./endpoint";
import { createRouter } from "./router";
import { z } from "zod";
Expand Down Expand Up @@ -397,3 +397,39 @@ describe("error handling", () => {
expect(body.message).toBe("Resource not found");
});
});

describe("extend", () => {
it("should extend the router with new endpoints", async () => {
const initialEndpoint = createEndpoint("/initial", { method: "GET" }, async () => ({}));
const router = createRouter({ initialEndpoint });
assert.ok(router.endpoints.initialEndpoint.path === "/initial");

const dynamicEndpoint = createEndpoint(
"/dynamic_added",
{
method: "POST",
},
async (c) => {
return { message: "dynamically added", body: c.body };
},
);

const extendedRouter = router.extend({ dynamicEndpoint });
assert.ok(extendedRouter.endpoints.initialEndpoint.path === "/initial");
assert.ok(extendedRouter.endpoints.dynamicEndpoint.path === "/dynamic_added");

const dynamicRequest = new Request("http://localhost/dynamic_added", {
method: "POST",
body: JSON.stringify({ test: "data" }),
headers: {
"Content-Type": "application/json",
},
});
const dynamicResponse = await extendedRouter.handler(dynamicRequest);
expect(dynamicResponse.status).toBe(200);
const jsonResponse = await dynamicResponse.json();
expect(jsonResponse.message).toBe("dynamically added");
expect(jsonResponse.body).toEqual({ test: "data" });
});

});
13 changes: 10 additions & 3 deletions src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,9 @@ export const createRouter = <E extends Record<string, Endpoint>, Config extends
const middlewareRouter = createRou3Router();

for (const endpoint of Object.values(endpoints)) {
if (!endpoint.options) {
if (!endpoint.options || endpoint.options?.metadata?.SERVER_ONLY) {
continue;
}
if (endpoint.options?.metadata?.SERVER_ONLY) continue;

const methods = Array.isArray(endpoint.options?.method)
? endpoint.options.method
: [endpoint.options?.method];
Expand Down Expand Up @@ -240,6 +238,15 @@ export const createRouter = <E extends Record<string, Endpoint>, Config extends
return res;
},
endpoints,

/**
* Extend the router with new endpoints
* @param newEndpoints new endpoints to extend the router with
* @returns new router with additional endpoints
*/
extend: <NE extends Record<string, Endpoint>>(newEndpoints: NE) => {
return createRouter({ ...endpoints, ...newEndpoints } as E & NE, config);
},
};
};

Expand Down