mirror of https://github.com/186526/handlers.js
Add Deno test supported & RegExp construction at route creation time
This commit is contained in:
parent
6559a3f134
commit
87744a2b25
|
@ -1,14 +1,20 @@
|
||||||
# [Choice] Node.js version (use -bullseye variants on local arm64/Apple Silicon): 18, 16, 14, 18-bullseye, 16-bullseye, 14-bullseye, 18-buster, 16-buster, 14-buster
|
FROM debian:bullseye as tjs
|
||||||
ARG VARIANT=16-bullseye
|
|
||||||
FROM mcr.microsoft.com/vscode/devcontainers/typescript-node:0-${VARIANT}
|
|
||||||
|
|
||||||
# [Optional] Uncomment this section to install additional OS packages.
|
RUN apt-get update -y && apt install cmake build-essential curl libcurl4-openssl-dev git -y
|
||||||
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
|
|
||||||
# && apt-get -y install --no-install-recommends <your-package-list-here>
|
|
||||||
|
|
||||||
# [Optional] Uncomment if you want to install an additional version of node using nvm
|
WORKDIR /
|
||||||
# ARG EXTRA_NODE_VERSION=10
|
|
||||||
# RUN su node -c "source /usr/local/share/nvm/nvm.sh && nvm install ${EXTRA_NODE_VERSION}"
|
|
||||||
|
|
||||||
# [Optional] Uncomment if you want to install more global node packages
|
RUN git clone --recursive https://github.com/saghul/txiki.js --shallow-submodules && cd txiki.js && \
|
||||||
# RUN su node -c "npm install -g <your-package-list -here>"
|
make
|
||||||
|
|
||||||
|
FROM denoland/deno:bin AS deno
|
||||||
|
|
||||||
|
FROM mcr.microsoft.com/vscode/devcontainers/typescript-node:16-bullseye
|
||||||
|
|
||||||
|
COPY --from=deno /deno /usr/local/bin/deno
|
||||||
|
COPY --from=tjs /txiki.js/build/tjs /usr/local/bin/tjs
|
||||||
|
|
||||||
|
RUN su node -c "npm install -g esbuild webpack jest ts-node"
|
||||||
|
|
||||||
|
ARG EXTRA_NODE_VERSION=14
|
||||||
|
RUN su node -c "source /usr/local/share/nvm/nvm.sh && nvm install ${EXTRA_NODE_VERSION}"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# [Choice] Node.js version (use -bullseye variants on local arm64/Apple Silicon): 18, 16, 14, 18-bullseye, 16-bullseye, 14-bullseye, 18-buster, 16-buster, 14-buster
|
# [Choice] Node.js version (use -bullseye variants on local arm64/Apple Silicon): 18, 16, 14, 18-bullseye, 16-bullseye, 14-bullseye, 18-buster, 16-buster, 14-buster
|
||||||
ARG VARIANT=16-bullseye
|
ARG VARIANT=16-bullseye
|
||||||
FROM mcr.microsoft.com/vscode/devcontainers/javascript-node:0-${VARIANT}
|
FROM mcr.microsoft.com/vscode/devcontainers/javascript-node:${VARIANT}
|
||||||
|
|
||||||
# Install tslint, typescript. eslint is installed by javascript image
|
# Install tslint, typescript. eslint is installed by javascript image
|
||||||
ARG NODE_MODULES="tslint-to-eslint-config typescript"
|
ARG NODE_MODULES="tslint-to-eslint-config typescript"
|
||||||
|
|
|
@ -1,17 +1,11 @@
|
||||||
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
|
|
||||||
// https://github.com/microsoft/vscode-dev-containers/tree/v0.238.1/containers/typescript-node
|
|
||||||
{
|
{
|
||||||
"name": "Node.js & TypeScript",
|
"name": "Handlers.js Devlopment Container",
|
||||||
"build": {
|
"build": {
|
||||||
"dockerfile": "Dockerfile",
|
"dockerfile": "Dockerfile",
|
||||||
// Update 'VARIANT' to pick a Node version: 18, 16, 14.
|
|
||||||
// Append -bullseye or -buster to pin to an OS version.
|
|
||||||
// Use -bullseye variants on local on arm64/Apple Silicon.
|
|
||||||
"args": {
|
"args": {
|
||||||
"VARIANT": "16-bullseye"
|
"VARIANT": "16-bullseye"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// Configure tool-specific properties.
|
// Configure tool-specific properties.
|
||||||
"customizations": {
|
"customizations": {
|
||||||
// Configure properties specific to VS Code.
|
// Configure properties specific to VS Code.
|
||||||
|
@ -21,19 +15,28 @@
|
||||||
"dbaeumer.vscode-eslint",
|
"dbaeumer.vscode-eslint",
|
||||||
"ms-vscode.vscode-typescript-next",
|
"ms-vscode.vscode-typescript-next",
|
||||||
"oderwat.indent-rainbow",
|
"oderwat.indent-rainbow",
|
||||||
|
"GitHub.copilot",
|
||||||
|
"redhat.vscode-yaml",
|
||||||
|
"ms-azuretools.vscode-docker"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||||
// "forwardPorts": [],
|
// "forwardPorts": [],
|
||||||
|
|
||||||
// Use 'postCreateCommand' to run commands after the container is created.
|
// Use 'postCreateCommand' to run commands after the container is created.
|
||||||
"postCreateCommand": "yarn install",
|
"postCreateCommand": "yarn install",
|
||||||
|
|
||||||
// Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
|
// Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
|
||||||
"remoteUser": "node",
|
"remoteUser": "node",
|
||||||
"features": {
|
"features": {
|
||||||
"git": "latest"
|
"git": "latest",
|
||||||
|
"docker-in-docker": {
|
||||||
|
"version": "latest",
|
||||||
|
"moby": true,
|
||||||
|
"dockerDashComposeVersion": "v1"
|
||||||
|
},
|
||||||
|
"rust": {
|
||||||
|
"version": "latest",
|
||||||
|
"profile": "minimal"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,7 +3,7 @@ name: CI
|
||||||
on: push
|
on: push
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
node:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
|
@ -12,11 +12,35 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Use Node.js ${{ matrix.node-version }}
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: yarn install
|
run: yarn install
|
||||||
|
|
||||||
- name: Test handlers.js
|
- name: Test handlers.js
|
||||||
run: yarn test
|
run: yarn test:node
|
||||||
|
|
||||||
|
deno:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Use Node.js Latest
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: vx.x.x
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: yarn install
|
||||||
|
|
||||||
|
- uses: denoland/setup-deno@v1
|
||||||
|
with:
|
||||||
|
deno-version: vx.x.x
|
||||||
|
|
||||||
|
- name: Test handlers.js
|
||||||
|
run: yarn test:deno
|
||||||
|
|
|
@ -46,7 +46,8 @@
|
||||||
"clean": "rm -rf ./dist",
|
"clean": "rm -rf ./dist",
|
||||||
"demo": "env NODE_ENV=development yarn build:node && node ./dist/main.node.js",
|
"demo": "env NODE_ENV=development yarn build:node && node ./dist/main.node.js",
|
||||||
"tsc": "tsc",
|
"tsc": "tsc",
|
||||||
"test": "jest",
|
"test:node": "jest ./test/node.test.ts",
|
||||||
|
"test:deno": "BUILD_TARGET=deno:test webpack && jest ./test/deno.test.ts",
|
||||||
"coverage": "jest --collectCoverage --"
|
"coverage": "jest --collectCoverage --"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|
|
@ -35,6 +35,7 @@ export class SWPlatformAdapter<T = any, K = any> implements platformAdapater {
|
||||||
}
|
}
|
||||||
|
|
||||||
async handleResponse(response: response<K>): Promise<Response> {
|
async handleResponse(response: response<K>): Promise<Response> {
|
||||||
|
if (response.status === 204) { response.body = null; }
|
||||||
const nativResponse = new Response(response.body, {
|
const nativResponse = new Response(response.body, {
|
||||||
status: response.status,
|
status: response.status,
|
||||||
headers: response.headers.headers,
|
headers: response.headers.headers,
|
||||||
|
|
31
src/route.ts
31
src/route.ts
|
@ -10,26 +10,33 @@ interface matchedStatus {
|
||||||
}[];
|
}[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface regExpKey {
|
||||||
|
name: string;
|
||||||
|
prefix: string;
|
||||||
|
suffix: string;
|
||||||
|
pattern: string;
|
||||||
|
modifier: string;
|
||||||
|
};
|
||||||
|
|
||||||
export class route {
|
export class route {
|
||||||
public paths: path[];
|
private paths: path[];
|
||||||
public handlers: handler<any, any>[];
|
public handlers: handler<any, any>[];
|
||||||
|
private regExps: { regExp: RegExp, keys: regExpKey[] }[] = [];
|
||||||
|
|
||||||
constructor(paths: path[], handlers: handler<any, any>[]) {
|
constructor(paths: path[], handlers: handler<any, any>[]) {
|
||||||
this.paths = paths;
|
this.paths = paths;
|
||||||
this.handlers = handlers;
|
this.handlers = handlers;
|
||||||
|
|
||||||
|
this.paths.forEach(path => {
|
||||||
|
const keys: regExpKey[] = [];
|
||||||
|
this.regExps.push({ regExp: pathToRegexp(path, keys), keys });
|
||||||
|
})
|
||||||
}
|
}
|
||||||
async exec(path: string): Promise<matchedStatus> {
|
async exec(path: string): Promise<matchedStatus> {
|
||||||
let Answer = await Promise.all<Promise<matchedStatus>>(
|
let Answer = await Promise.all<Promise<matchedStatus>>(
|
||||||
this.paths.map(async (it) => {
|
this.regExps.map(async (it) => {
|
||||||
const keys: {
|
|
||||||
name: string;
|
const answer = it.regExp.exec(path);
|
||||||
prefix: string;
|
|
||||||
suffix: string;
|
|
||||||
pattern: string;
|
|
||||||
modifier: string;
|
|
||||||
}[] = [];
|
|
||||||
const regExp = pathToRegexp(it, keys);
|
|
||||||
const answer = regExp.exec(path);
|
|
||||||
if (answer === null)
|
if (answer === null)
|
||||||
return {
|
return {
|
||||||
matched: false,
|
matched: false,
|
||||||
|
@ -38,7 +45,7 @@ export class route {
|
||||||
|
|
||||||
let attributes: matchedStatus["attributes"] = [];
|
let attributes: matchedStatus["attributes"] = [];
|
||||||
|
|
||||||
keys.forEach((key, index) => {
|
it.keys.forEach((key, index) => {
|
||||||
attributes.push({
|
attributes.push({
|
||||||
name: key.name,
|
name: key.name,
|
||||||
value: answer[index + 1],
|
value: answer[index + 1],
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
import { spawn } from "child_process";
|
||||||
|
|
||||||
|
import Axios from "axios";
|
||||||
|
|
||||||
|
const Instance = Axios.create({
|
||||||
|
baseURL: "http://localhost:3000"
|
||||||
|
})
|
||||||
|
|
||||||
|
spawn(`deno`, [
|
||||||
|
"run", "--allow-net", `${__dirname}/../dist/test.deno.js`
|
||||||
|
]);
|
||||||
|
|
||||||
|
const randomString = () => Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
|
||||||
|
|
||||||
|
describe("Test server", () => {
|
||||||
|
test("normal 200 response", async () => {
|
||||||
|
expect.assertions(2);
|
||||||
|
|
||||||
|
await new Promise((r) => setTimeout(r, 200));
|
||||||
|
|
||||||
|
const { data, status } = await Instance.get("/");
|
||||||
|
expect(status).toEqual(200);
|
||||||
|
expect(data).toEqual("200 OK");
|
||||||
|
})
|
||||||
|
|
||||||
|
test("post response", async () => {
|
||||||
|
expect.assertions(2);
|
||||||
|
const string = randomString();
|
||||||
|
|
||||||
|
const { data, status } = await Instance.post("/post", string);
|
||||||
|
|
||||||
|
expect(status).toEqual(200);
|
||||||
|
expect(data).toEqual(string);
|
||||||
|
})
|
||||||
|
|
||||||
|
test("change header and status code", async () => {
|
||||||
|
expect.assertions(3);
|
||||||
|
|
||||||
|
const { data, status, headers } = await Instance.get("/header");
|
||||||
|
|
||||||
|
expect(status).toEqual(204);
|
||||||
|
expect(headers["itis"]).toEqual("work");
|
||||||
|
expect(data).toEqual("");
|
||||||
|
})
|
||||||
|
|
||||||
|
test("get param", async () => {
|
||||||
|
expect.assertions(2);
|
||||||
|
|
||||||
|
const string = randomString();
|
||||||
|
const { data, status } = await Instance.get(`/info/${string}`);
|
||||||
|
|
||||||
|
expect(status).toEqual(200);
|
||||||
|
expect(data).toEqual(string);
|
||||||
|
})
|
||||||
|
|
||||||
|
test("chain interrupted", async () => {
|
||||||
|
expect.assertions(2);
|
||||||
|
|
||||||
|
const { data, status } = await Instance.get(`/info/foo`);
|
||||||
|
|
||||||
|
expect(status).toEqual(200);
|
||||||
|
expect(data).toEqual("hit");
|
||||||
|
})
|
||||||
|
})
|
|
@ -0,0 +1,3 @@
|
||||||
|
import App from "./test-server";
|
||||||
|
|
||||||
|
App.listen(3000);
|
|
@ -81,6 +81,10 @@ export default () => {
|
||||||
'Promise': 'bluebird'
|
'Promise': 'bluebird'
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
case "deno:test":
|
||||||
|
config.target = "webworker";
|
||||||
|
config.output.filename = "test.deno.js";
|
||||||
|
config.entry = "./test/test-server.deno.ts";
|
||||||
default:
|
default:
|
||||||
config.target = "es6";
|
config.target = "es6";
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue