Skip to content
This repository has been archived by the owner on Jul 28, 2024. It is now read-only.

Commit

Permalink
chore: QoL changes and fixes for 1.0.0 release (#39)
Browse files Browse the repository at this point in the history
* chore: bundle and route correctly

* chore: decrease log timeout and remove log formatting

* chore: prep 1.0.0 release
  • Loading branch information
jeroenptrs authored Jul 25, 2020
1 parent 3b64489 commit c25591b
Show file tree
Hide file tree
Showing 35 changed files with 310 additions and 145 deletions.
15 changes: 11 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,19 @@ This will map in `registry` to
### index.ts

```ts
import { createHandler } from "https://cdn.jsdelivr.net/gh/jeroenptrs/[email protected]/packages/micro/mod.ts";

export default createHandler(async (_) => "Hello, world");
import {
createHandler,
createResponse,
} from "https://cdn.jsdelivr.net/gh/jeroenptrs/[email protected]/packages/micro/functions/mod.ts";

export default createHandler(async (req, res) => {
return createResponse({
body: "Hello, World",
});
});
```

`createHandler` gives you a Request object and requires a string or Response object. See typings in `packages/micro/mod.ts`. Handlers must _always_ be async.
`createHandler` gives you a server Request and an empty Response object that you can populate with your data. A Handler always returns a Response and _must always be async_.

### registry.json

Expand Down
2 changes: 1 addition & 1 deletion fixtures/dfn_reg/packages/micro/deps.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export * as server from "https://deno.land/std@0.61.0/http/server.ts";
export * as server from "https://deno.land/std@0.62.0/http/server.ts";
5 changes: 5 additions & 0 deletions fixtures/dfn_reg/packages/micro/functions/mod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export { createHandler } from "../src/createHandler.ts";
export { createResponse } from "../src/createResponse.ts";
export { createResponseFromError } from "../src/createResponseFromError.ts";
export { NetworkError } from "../src/networkError.ts";
export { Request, Response, Handler, Methods } from "../src/types.ts";
24 changes: 12 additions & 12 deletions fixtures/dfn_reg/packages/micro/lock.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
{
"https://deno.land/std@0.61.0/_util/assert.ts": "e1f76e77c5ccb5a8e0dbbbe6cce3a56d2556c8cb5a9a8802fc9565af72462149",
"https://deno.land/std@0.61.0/async/deferred.ts": "ac95025f46580cf5197928ba90995d87f26e202c19ad961bc4e3177310894cdc",
"https://deno.land/std@0.61.0/async/delay.ts": "35957d585a6e3dd87706858fb1d6b551cb278271b03f52c5a2cb70e65e00c26a",
"https://deno.land/std@0.61.0/async/mod.ts": "bf46766747775d0fc4070940d20d45fb311c814989485861cdc8a8ef0e3bbbab",
"https://deno.land/std@0.61.0/async/mux_async_iterator.ts": "f6ca1b70f05e3cb676956d70a3230c99925288cf67e4e0b0bbaf34759b41945b",
"https://deno.land/std@0.61.0/bytes/mod.ts": "b1a149ac741728db00bda9ce1a2d044f248edd5ac95e708a6cc501bfd3adb4a7",
"https://deno.land/std@0.61.0/encoding/utf8.ts": "8654fa820aa69a37ec5eb11908e20b39d056c9bf1c23ab294303ff467f3d50a1",
"https://deno.land/std@0.61.0/http/_io.ts": "7a31bf7d0167685d8d0ff4eca93b558cd26539695d1ddbd715ee28bf1dc7db17",
"https://deno.land/std@0.61.0/http/http_status.ts": "0ecc0799a208f49452023b1b927106ba5a2c13cc6cf6666345db028239d554ab",
"https://deno.land/std@0.61.0/http/server.ts": "3bae933acb2645d863f0f87a91070d2478ad24b828ce27936711377426896b29",
"https://deno.land/std@0.61.0/io/bufio.ts": "dd1fc575524fe8b44e128091ba0e6833be7d0966336ef12a407544440b762e17",
"https://deno.land/std@0.61.0/textproto/mod.ts": "ee6bad9818d3fb44ecb2e0bbf9fc5b6a871fb332145800c54f732bf805dddff2"
"https://deno.land/std@0.62.0/_util/assert.ts": "e1f76e77c5ccb5a8e0dbbbe6cce3a56d2556c8cb5a9a8802fc9565af72462149",
"https://deno.land/std@0.62.0/async/deferred.ts": "ac95025f46580cf5197928ba90995d87f26e202c19ad961bc4e3177310894cdc",
"https://deno.land/std@0.62.0/async/delay.ts": "35957d585a6e3dd87706858fb1d6b551cb278271b03f52c5a2cb70e65e00c26a",
"https://deno.land/std@0.62.0/async/mod.ts": "bf46766747775d0fc4070940d20d45fb311c814989485861cdc8a8ef0e3bbbab",
"https://deno.land/std@0.62.0/async/mux_async_iterator.ts": "1352b10a5cee1821a963eb8f4f05603bd7e25f8886eaf8d1888f4b416ddccdf5",
"https://deno.land/std@0.62.0/bytes/mod.ts": "b1a149ac741728db00bda9ce1a2d044f248edd5ac95e708a6cc501bfd3adb4a7",
"https://deno.land/std@0.62.0/encoding/utf8.ts": "8654fa820aa69a37ec5eb11908e20b39d056c9bf1c23ab294303ff467f3d50a1",
"https://deno.land/std@0.62.0/http/_io.ts": "a6108623563611e901b1128ca91aca02982af552aa7c4f39f2240cf6e6cd9ac7",
"https://deno.land/std@0.62.0/http/http_status.ts": "0ecc0799a208f49452023b1b927106ba5a2c13cc6cf6666345db028239d554ab",
"https://deno.land/std@0.62.0/http/server.ts": "9f39d814950c741e0dcf0dfb9a046515f5fb342a62fbc28607c44ac5692e8a7e",
"https://deno.land/std@0.62.0/io/bufio.ts": "e76c5b7bf978a638aae6f62b87efde3ab7203b85902ce9b84ac8388c8c2bb104",
"https://deno.land/std@0.62.0/textproto/mod.ts": "ebd84342f62216af1850279d32581c51d0958e36d477c6c26c961987e6240356"
}
16 changes: 3 additions & 13 deletions fixtures/dfn_reg/packages/micro/src/createHandler.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,7 @@
import { server } from "../deps.ts";
import { createResponse } from "./createResponse.ts";
import { NetworkError } from "./networkError.ts";
import { returnNetworkErrorOnCatch } from "./createResponseFromError.ts";
import * as T from "./types.ts";

export const createHandler = (h: T.Handler): T.LibHandler => async (req: server.ServerRequest) => {
try {
const response = createResponse(await h(req, createResponse({})));
return response;
} catch (e) {
const E: NetworkError = e;
return createResponse({
status: E.statusCode ?? 500,
body: E.message ?? `Internal Server Error`,
});
}
};
export const createHandler = (h: T.Handler): T.LibHandler => async (req: server.ServerRequest) =>
returnNetworkErrorOnCatch(async () => createResponse(await h(req, createResponse({}))));
12 changes: 12 additions & 0 deletions fixtures/dfn_reg/packages/micro/src/createHandler_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,15 @@ Deno.test("should return error response", async () => {
assertEquals(response.status, 404);
assertEquals(response.body, "Not found");
});

Deno.test("should return generic error response", async () => {
const libHandler = createHandler(
mockHandler(() => {
throw new Error();
})
);

const response = await libHandler(mockRequest);
assertEquals(response.status, 500);
assertEquals(response.body, "Internal Server Error");
});
21 changes: 19 additions & 2 deletions fixtures/dfn_reg/packages/micro/src/createResponseFromError.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,26 @@
import { createResponse } from "./createResponse.ts";
import { NetworkError } from "./networkError.ts";
import { Response } from "./types.ts";

export const createResponseFromError = (e: NetworkError) => {
return createResponse({
status: e.statusCode ?? 500,
body: e.message ?? `Internal Server Error`,
status: e.statusCode,
body: e.message,
});
};

export async function returnNetworkErrorOnCatch(
fn: (...args: any[]) => Promise<Response>
): Promise<Response> {
try {
const response = await fn();
return response;
} catch (e) {
let error: NetworkError;
if (e instanceof NetworkError) error = e;
else if (e instanceof Error)
error = new NetworkError(500, e.message || "Internal Server Error");
else error = new NetworkError();
return createResponseFromError(error);
}
}
2 changes: 1 addition & 1 deletion fixtures/dfn_reg/packages/micro/src/networkError.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export class NetworkError extends Error {
statusCode: number;
constructor(statusCode: number = 500, message: string = "Internal server error") {
constructor(statusCode: number = 500, message: string = "Internal Server Error") {
super(message);
this.statusCode = statusCode;
}
Expand Down
2 changes: 1 addition & 1 deletion fixtures/dfn_reg/packages/micro/src/networkError_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { NetworkError } from "./networkError.ts";
Deno.test("NetworkError", () => {
const defaultNetworkError = new NetworkError();
assertEquals(defaultNetworkError.statusCode, 500);
assertEquals(defaultNetworkError.message, "Internal server error");
assertEquals(defaultNetworkError.message, "Internal Server Error");

let newNetworkError = new NetworkError(404, "Not found");
assertEquals(newNetworkError.statusCode, 404);
Expand Down
61 changes: 61 additions & 0 deletions fixtures/dfn_reg/packages/micro/src/router.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { assertEquals, ServerRequest } from "../../testing/mod.ts";
import { createResponse } from "./createResponse.ts";
import { Router } from "./router.ts";

const req1 = () => Object.assign({}, new ServerRequest(), { method: "get", url: "/" });
const req2 = () => Object.assign({}, new ServerRequest(), { method: "get", url: "/test" });
const req3 = () => Object.assign({}, new ServerRequest(), { method: "get", url: "/test?abc" });
const req4 = () => Object.assign({}, new ServerRequest(), { method: "get", url: "/test/abc" });
const req5 = () => Object.assign({}, new ServerRequest(), { method: "get", url: "/testt" });

const body1 = "Hello, World!";
const body2 = "Hello, Test!";

const app = new Router();
app.use("/", async () => createResponse({ body: body1 }));
app.use("/test", async () => createResponse({ body: body2 }));

Deno.test("should respond with data on request", async () => {
const response = await app.handle(req1(), createResponse({}));
assertEquals(response.body, body1);
});

Deno.test("should respond with different data on different routes", async () => {
const response1 = await app.handle(req1(), createResponse({}));
const response2 = await app.handle(req2(), createResponse({}));
assertEquals(response1.body, body1);
assertEquals(response2.body, body2);
});

Deno.test("should still route subroutes and queries to parent route", async () => {
const response3 = await app.handle(req3(), createResponse({}));
const response4 = await app.handle(req4(), createResponse({}));
assertEquals(response3.body, body2);
assertEquals(response4.body, body2);
});

Deno.test("should properly resolve routes and fallback to 404", async () => {
const response5 = await app.handle(req5(), createResponse({}));
assertEquals(response5.body, `Cannot find ${req5().url}`);
});

Deno.test(
"should properly resolve routes and fallback to default route when provided",
async () => {
const _app = new Router();
_app.use(async (_, res) => ({ ...res, body: body1 }));
_app.use("/test", async (_, res) => ({ ...res, body: body2 }));
const response5 = await _app.handle(req5(), createResponse({}));
assertEquals(response5.body, body1);
}
);

Deno.test("should make clear distinction between app.use with or without route", async () => {
const _app = new Router();
_app.use(async () => createResponse({ body: "1" }));
_app.use("", async () => createResponse({ body: "2" }));
const responseA = await _app.handle(req1(), createResponse({}));
const responseB = await _app.handle(req2(), createResponse({}));
assertEquals(responseA.body, "2");
assertEquals(responseB.body, "1");
});
12 changes: 9 additions & 3 deletions fixtures/dfn_reg/packages/micro/src/router.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { createHandler } from "./createHandler.ts";
import { createResponseFromError } from "./createResponseFromError.ts";
import { filterOutQuery } from "./filters.ts";
import { NetworkError } from "./networkError.ts";
import { serve } from "./serve.ts";
Expand All @@ -14,6 +15,9 @@ export class Router {
private _stack: [[string] | [string, T.Methods], T.Handler][];
constructor() {
this._stack = [];
this.use(async (req) =>
createResponseFromError(new NetworkError(404, `Cannot find ${req.url}`))
);
}

use(middleware: T.Handler): void;
Expand All @@ -22,7 +26,7 @@ export class Router {
if (typeof pathOrMiddleware !== "string") {
this._stack.push([[""], pathOrMiddleware]);
} else if (typeof pathOrMiddleware === "string" && !!middleware) {
this._stack.push([[pathOrMiddleware], middleware]);
this._stack.push([[shouldStartWithSlash(pathOrMiddleware)], middleware]);
} else {
throw new NetworkError();
}
Expand All @@ -45,9 +49,11 @@ export class Router {
req.url = reqUrl;

if (!method || method === req.method.toLowerCase()) {
if (filterOutQuery(reqUrl) === "/" && originalPath === "/") {
if (originalPath === "") {
return next(req, await layer(req, res));
} else if (filterOutQuery(reqUrl) === "/" && originalPath === "/") {
return next(req, await layer(req, res));
} else if (reqUrl.startsWith(path)) {
} else if (filterOutQuery(reqUrl).split("/")[1] === path.split("/")[1]) {
const strippedReq = assignUrl(req, shouldStartWithSlash(reqUrl.substring(path.length)));
return next(req, await layer(strippedReq, res));
} else {
Expand Down
2 changes: 1 addition & 1 deletion fixtures/dfn_reg/packages/templates/bundle.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { serve } from "./packages/micro/mod.ts";
import { serve } from "./packages/micro/src/serve.ts";
import fn from "./registry_in/%SCRIPT_NAME%/index.ts";

console.log("%SCRIPT_NAME%");
Expand Down
5 changes: 5 additions & 0 deletions packages/micro/functions/mod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export { createHandler } from "../src/createHandler.ts";
export { createResponse } from "../src/createResponse.ts";
export { createResponseFromError } from "../src/createResponseFromError.ts";
export { NetworkError } from "../src/networkError.ts";
export { Request, Response, Handler, Methods } from "../src/types.ts";
16 changes: 3 additions & 13 deletions packages/micro/src/createHandler.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,7 @@
import { server } from "../deps.ts";
import { createResponse } from "./createResponse.ts";
import { NetworkError } from "./networkError.ts";
import { returnNetworkErrorOnCatch } from "./createResponseFromError.ts";
import * as T from "./types.ts";

export const createHandler = (h: T.Handler): T.LibHandler => async (req: server.ServerRequest) => {
try {
const response = createResponse(await h(req, createResponse({})));
return response;
} catch (e) {
const E: NetworkError = e;
return createResponse({
status: E.statusCode ?? 500,
body: E.message ?? `Internal Server Error`,
});
}
};
export const createHandler = (h: T.Handler): T.LibHandler => async (req: server.ServerRequest) =>
returnNetworkErrorOnCatch(async () => createResponse(await h(req, createResponse({}))));
12 changes: 12 additions & 0 deletions packages/micro/src/createHandler_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,15 @@ Deno.test("should return error response", async () => {
assertEquals(response.status, 404);
assertEquals(response.body, "Not found");
});

Deno.test("should return generic error response", async () => {
const libHandler = createHandler(
mockHandler(() => {
throw new Error();
})
);

const response = await libHandler(mockRequest);
assertEquals(response.status, 500);
assertEquals(response.body, "Internal Server Error");
});
21 changes: 19 additions & 2 deletions packages/micro/src/createResponseFromError.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,26 @@
import { createResponse } from "./createResponse.ts";
import { NetworkError } from "./networkError.ts";
import { Response } from "./types.ts";

export const createResponseFromError = (e: NetworkError) => {
return createResponse({
status: e.statusCode ?? 500,
body: e.message ?? `Internal Server Error`,
status: e.statusCode,
body: e.message,
});
};

export async function returnNetworkErrorOnCatch(
fn: (...args: any[]) => Promise<Response>
): Promise<Response> {
try {
const response = await fn();
return response;
} catch (e) {
let error: NetworkError;
if (e instanceof NetworkError) error = e;
else if (e instanceof Error)
error = new NetworkError(500, e.message || "Internal Server Error");
else error = new NetworkError();
return createResponseFromError(error);
}
}
2 changes: 1 addition & 1 deletion packages/micro/src/networkError.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export class NetworkError extends Error {
statusCode: number;
constructor(statusCode: number = 500, message: string = "Internal server error") {
constructor(statusCode: number = 500, message: string = "Internal Server Error") {
super(message);
this.statusCode = statusCode;
}
Expand Down
2 changes: 1 addition & 1 deletion packages/micro/src/networkError_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { NetworkError } from "./networkError.ts";
Deno.test("NetworkError", () => {
const defaultNetworkError = new NetworkError();
assertEquals(defaultNetworkError.statusCode, 500);
assertEquals(defaultNetworkError.message, "Internal server error");
assertEquals(defaultNetworkError.message, "Internal Server Error");

let newNetworkError = new NetworkError(404, "Not found");
assertEquals(newNetworkError.statusCode, 404);
Expand Down
Loading

0 comments on commit c25591b

Please sign in to comment.