diff --git a/.github/workflows/on-commit.yml b/.github/workflows/on-commit.yml index caf130a..79572a3 100644 --- a/.github/workflows/on-commit.yml +++ b/.github/workflows/on-commit.yml @@ -8,14 +8,12 @@ jobs: runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v2.0.0 - - name: Read .nvmrc - id: nvm - run: echo ::set-output name=NVMRC::$(cat .nvmrc) - name: Setup node uses: actions/setup-node@v2 with: - node-version: '${{ steps.nvm.outputs.NVMRC }}' + # https://github.com/actions/setup-node/issues/32#issuecomment-1003854758 + node-version-file: '.nvmrc' - name: prepare dependencies run: npm install - name: test - run: npm run precommit \ No newline at end of file + run: npm run precommit diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 2f9f050..03e9173 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -11,13 +11,11 @@ jobs: runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v2.0.0 - - name: Read .nvmrc - id: nvm - run: echo ::set-output name=NVMRC::$(cat .nvmrc) - name: Setup node uses: actions/setup-node@v2 with: - node-version: '${{ steps.nvm.outputs.NVMRC }}' + # https://github.com/actions/setup-node/issues/32#issuecomment-1003854758 + node-version-file: '.nvmrc' - name: prepare dependencies run: npm install - name: test diff --git a/.nvmrc b/.nvmrc index d72f808..bf79505 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v12.12.0 +v16.14.0 diff --git a/package.json b/package.json index a02f539..76fc6d7 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,6 @@ { "name": "@bessonovs/node-http-router", + "version": "0.0.7", "description": "Extensible http router for node and micro", "keywords": [ "router", @@ -16,7 +17,6 @@ "http", "server" ], - "version": "0.0.6", "author": "Anton Bessonov", "license": "MIT", "repository": "bessonov/node-http-router", @@ -33,26 +33,26 @@ "precommit": "$_ run test && $_ run lint && $_ run build" }, "dependencies": { - "fast-url-parser": "1.1.3" + "urlite": "3.0.0" }, "devDependencies": { "@bessonovs/eslint-config": "0.0.7", - "@types/express": "4.17.12", - "@types/jest": "25.2.2", - "@types/node": "14.0.1", - "@typescript-eslint/eslint-plugin": "4.28.1", - "@typescript-eslint/parser": "4.28.1", - "eslint": "7.29.0", - "eslint-config-airbnb": "18.2.1", - "eslint-plugin-import": "2.23.4", - "eslint-plugin-jsx-a11y": "6.4.1", - "eslint-plugin-react": "7.24.0", - "jest": "27.0.6", + "@types/express": "4.17.13", + "@types/jest": "27.4.1", + "@types/node": "16.11.7", + "@typescript-eslint/eslint-plugin": "5.13.0", + "@typescript-eslint/parser": "5.13.0", + "eslint": "8.10.0", + "eslint-config-airbnb": "19.0.4", + "eslint-plugin-import": "2.25.4", + "eslint-plugin-jsx-a11y": "6.5.1", + "eslint-plugin-react": "7.29.3", + "jest": "27.5.1", "micro": "9.3.5-canary.3", - "node-mocks-http": "1.10.1", + "node-mocks-http": "1.11.0", "path-to-regexp": "6.2.0", - "ts-jest": "27.0.3", - "typescript": "4.3.4" + "ts-jest": "27.1.3", + "typescript": "4.6.2" }, "publishConfig": { "access": "public" diff --git a/src/@types/fast-url-parser/index.d.ts b/src/@types/fast-url-parser/index.d.ts deleted file mode 100644 index 60ec84c..0000000 --- a/src/@types/fast-url-parser/index.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -declare module 'fast-url-parser' { - // eslint-disable-next-line import/no-named-default - import { default as nativeUrl } from 'url' - - const Url: typeof nativeUrl - // eslint-disable-next-line import/no-default-export - export default Url -} diff --git a/src/@types/urlite/index.d.ts b/src/@types/urlite/index.d.ts new file mode 100644 index 0000000..3a252bb --- /dev/null +++ b/src/@types/urlite/index.d.ts @@ -0,0 +1,10 @@ +declare module 'urlite' { + const Url: { + parse: (url: string) => { + pathname: string | undefined + search: string | undefined + } + } + // eslint-disable-next-line import/no-default-export + export default Url +} diff --git a/src/index.ts b/src/index.ts index c5bcf0b..ad54485 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,2 +1,2 @@ export * from './matchers' -export { Route, Router, MatchedHandler } from './router' +export type { Route, Router, MatchedHandler } from './router' diff --git a/src/matchers/ExactQueryMatcher.ts b/src/matchers/ExactQueryMatcher.ts index d59732e..70597ad 100644 --- a/src/matchers/ExactQueryMatcher.ts +++ b/src/matchers/ExactQueryMatcher.ts @@ -1,5 +1,5 @@ import { IncomingMessage } from 'http' -import Url from 'fast-url-parser' +import Url from 'urlite' import { Matcher } from './Matcher' import { MatchResult } from './MatchResult' @@ -29,19 +29,20 @@ export type ExactQueryMatchResult = MatchResult<{ export class ExactQueryMatcher implements Matcher> { private readonly listConfig: [string, string | true | false | undefined][] - constructor(private readonly config: U) { + constructor(config: U) { this.listConfig = Object.entries(config) } match(req: IncomingMessage): ExactQueryMatchResult { /* istanbul ignore else */ if (req.url !== undefined) { - const { query } = Url.parse(req.url) + // original URL returns '' if search is empty + const search = Url.parse(req.url).search ?? '' // parse query string into dict let params = {} as QueryResult - if (query !== null) { - params = query.split(/&/).reduce((acc, parts) => { + if (search !== '') { + params = search.substring(1).split(/&/).reduce((acc, parts) => { const part = parts.split(/=/) const [key, value] = part // @ts-ignore diff --git a/src/matchers/ExactUrlPathnameMatcher.ts b/src/matchers/ExactUrlPathnameMatcher.ts index 4ccd3cd..fdbe847 100644 --- a/src/matchers/ExactUrlPathnameMatcher.ts +++ b/src/matchers/ExactUrlPathnameMatcher.ts @@ -1,5 +1,5 @@ import { IncomingMessage } from 'http' -import Url from 'fast-url-parser' +import Url from 'urlite' import { Matcher } from './Matcher' import { MatchResult } from './MatchResult' @@ -18,8 +18,9 @@ implements Matcher> { match(req: IncomingMessage): ExactUrlPathnameMatchResult { /* istanbul ignore else */ if (req.url !== undefined) { - const { pathname } = Url.parse(req.url) - if (pathname !== null && this.urls.indexOf(pathname) >= 0) { + // original URL returns '/' if pathname is empty + const pathname = Url.parse(req.url).pathname ?? '/' + if (this.urls.indexOf(pathname) >= 0) { return { matched: true, pathname, diff --git a/src/matchers/__tests__/ExactUrlPathnameMatcher.test.ts b/src/matchers/__tests__/ExactUrlPathnameMatcher.test.ts index b320827..f5925e8 100644 --- a/src/matchers/__tests__/ExactUrlPathnameMatcher.test.ts +++ b/src/matchers/__tests__/ExactUrlPathnameMatcher.test.ts @@ -1,16 +1,29 @@ import * as httpMocks from 'node-mocks-http' import { ExactUrlPathnameMatcher } from '..' -it('not match', () => { +it('not match empty', () => { const result = new ExactUrlPathnameMatcher(['/test']) .match(httpMocks.createRequest()) expect(result).toStrictEqual({ matched: false, }) }) -it('not match', () => { + +it('not match with postfix', () => { const result = new ExactUrlPathnameMatcher(['/test']) - .match(httpMocks.createRequest()) + .match(httpMocks.createRequest({ + url: '/test2', + })) + expect(result).toStrictEqual({ + matched: false, + }) +}) + +it('not match prefix', () => { + const result = new ExactUrlPathnameMatcher(['/test']) + .match(httpMocks.createRequest({ + url: '/tes', + })) expect(result).toStrictEqual({ matched: false, })