Skip to content

Commit

Permalink
feat: add pattern-key-compare
Browse files Browse the repository at this point in the history
  • Loading branch information
unional committed Jan 1, 2023
1 parent 71f87b3 commit b137fa2
Show file tree
Hide file tree
Showing 25 changed files with 634 additions and 26 deletions.
6 changes: 6 additions & 0 deletions .changeset/nice-ladybugs-tickle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'pattern-key-compare': major
---

Initial release.
Extract from `resolve.imports`.
5 changes: 5 additions & 0 deletions .changeset/strong-mirrors-protect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'resolve.imports': patch
---

Extract `patternKeyCompare` to `pattern-key-compare` package.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@

[![Visual Studio Code][vscode-image]][vscode-url]

This is the repository of [resolve.imports](./packages/resolve.imports/README.md).
This is the repository of:

- [resolve.imports](./packages/resolve.imports/README.md).
- [pattern-key-compare](./packages/pattern-key-compare/README.md).

## Videos

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"lint": "cross-env TIMING=1 eslint --ext=ts,tsx,js,yaml,yml .",
"nuke": "pnpm --no-bail --filter=* nuke && pnpm --no-bail nuke:local",
"nuke:local": "rimraf node_modules",
"pkc": "pnpm --filter pattern-key-compare",
"imports": "pnpm --filter resolve.imports",
"release": "pnpm build && changeset publish",
"size": "turbo run size",
Expand Down
7 changes: 7 additions & 0 deletions packages/pattern-key-compare/.depcheckrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
ignores:
- '@repobuddy/jest'
- '@size-limit/preset-small-lib'
- '@types/node'
- jest
- jest-*
- ts-jest
4 changes: 4 additions & 0 deletions packages/pattern-key-compare/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
cjs
esm
tslib
*.tsbuildinfo
10 changes: 10 additions & 0 deletions packages/pattern-key-compare/.size-limit.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[
{
"path": "./cjs/index.js",
"limit": "2 KB"
},
{
"path": "./esm/index.js",
"limit": "2 KB"
}
]
21 changes: 21 additions & 0 deletions packages/pattern-key-compare/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
The MIT License (MIT)

Copyright © 2022 Homa Wong (unional) ([email protected])

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
64 changes: 64 additions & 0 deletions packages/pattern-key-compare/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# pattern-key-compare

[![NPM version][npm-image]][npm-url]
[![NPM downloads][downloads-image]][downloads-url]
[![Codecov][codecov-image]][codecov-url]

Implementation of `PATTERN_KEY_COMPARE` of [Node.js resolver algorithm][resolver-algorithm].

Here is a snapshot of the algorithm from Node.js v19.3.0:

`PATTERN_KEY_COMPARE(keyA, keyB)`

1. Assert: `keyA` ends with `"/"` or contains only a single `"*"`.
2. Assert: `keyB` ends with `"/"` or contains only a single `"*"`.
3. Let `baseLengthA` be the index of `"*"` in `keyA` plus one, if `keyA` contains `"*"`, or the length of `keyA` otherwise.
4. Let `baseLengthB` be the index of `"*"` in `keyB` plus one, if `keyB` contains `"*"`, or the length of `keyB` otherwise.
5. If `baseLengthA` is greater than `baseLengthB`, return `-1`.
6. If `baseLengthB` is greater than `baseLengthA`, return `1`.
7. If `keyA` does not contain "*", return `1`.
8. If `keyB` does not contain "*", return `-1`.
9. If the length of `keyA` is greater than the length of `keyB`, return `-1`.
10. If the length of `keyB` is greater than the length of `keyA`, return `1`.
11. Return `0`.

## Notes

> Assert: keyA/B ends with "/" or contains only a single "*"
Note that this is not correct as nowadays it supports file extensions. e.g.:

- `#a/b.js`
- `./foo/*.js`

## Install

```sh
# npm
npm install pattern-key-compare

# yarn
yarn add pattern-key-compare

# pnpm
pnpm add pattern-key-compare

# rush
rush add -p pattern-key-compare
```

## Usage

```ts
import { patternKeyCompare } from 'pattern-key-compare'

[...].sort(patternKeyCompare)
```

[codecov-image]: https://codecov.io/gh/cyberuni/resolve.imports/branch/main/graph/badge.svg
[codecov-url]: https://codecov.io/gh/cyberuni/resolve.imports
[downloads-image]: https://img.shields.io/npm/dm/pattern-key-compare.svg?style=flat
[downloads-url]: https://npmjs.org/package/pattern-key-compare
[npm-image]: https://img.shields.io/npm/v/pattern-key-compare.svg?style=flat
[npm-url]: https://npmjs.org/package/pattern-key-compare
[resolver-algorithm]: https://nodejs.org/api/esm.html#resolver-algorithm-specification
4 changes: 4 additions & 0 deletions packages/pattern-key-compare/jest.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/** @type {import('jest').Config} */
export default {
preset: '@repobuddy/jest/presets/ts-esm-watch'
}
1 change: 1 addition & 0 deletions packages/pattern-key-compare/package.cjs.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"type":"commonjs"}
79 changes: 79 additions & 0 deletions packages/pattern-key-compare/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
{
"name": "pattern-key-compare",
"version": "0.0.0",
"description": "PATTERN_KEY_COMPARE implementation",
"keywords": [
"resolve",
"esm",
"fields",
"nodejs"
],
"homepage": "https://github.com/cyberuni/resolve.imports",
"bugs": {
"url": "https://github.com/cyberuni/resolve.imports/issues"
},
"repository": {
"type": "git",
"url": "https://github.com/cyberuni/resolve.imports.git",
"directory": "packages/pattern-key-compare"
},
"license": "MIT",
"author": {
"name": "Homa Wong (unional)",
"email": "[email protected]"
},
"sideEffects": false,
"type": "module",
"exports": {
".": {
"types": "./esm/index.d.ts",
"import": "./esm/index.js",
"default": "./cjs/index.js"
},
"./package.json": "./package.json"
},
"main": "./cjs/index.js",
"types": "./esm/index.d.ts",
"files": [
"cjs",
"esm",
"ts",
"!cjs/**/*.d.ts",
"!**/*.test.*",
"!**/*.spec.*",
"!**/*.unit.*",
"!**/*.integrate.*",
"!**/*.system.*",
"!**/*.accept.*"
],
"scripts": {
"build": "run-p build:cjs build:esm",
"build:esm": "tsc --project tsconfig.esm.json",
"build:cjs": "tsc --project tsconfig.cjs.json && ncp package.cjs.json cjs/package.json",
"clean": "rimraf cjs esm tslib *.tsbuildinfo",
"coverage": "cross-env NODE_OPTIONS=--experimental-vm-modules NODE_OPTIONS=--experimental-import-meta-resolve NODE_NO_WARNINGS=1 jest --coverage",
"depcheck": "depcheck",
"size": "size-limit",
"test": "cross-env NODE_OPTIONS=--experimental-vm-modules NODE_OPTIONS=--experimental-import-meta-resolve jest",
"test:watch": "cross-env NODE_OPTIONS=--experimental-vm-modules NODE_OPTIONS=--experimental-import-meta-resolve jest --watch",
"verify": "npm-run-all -p build -p test depcheck size"
},
"devDependencies": {
"@jest/globals": "^29.3.1",
"@repobuddy/jest": "^2.3.0",
"@size-limit/preset-small-lib": "^8.1.0",
"@types/node": "^14",
"cross-env": "^7.0.3",
"depcheck": "^1.4.3",
"jest": "^29.3.1",
"jest-watch-suspend": "^1.1.2",
"jest-watch-toggle-config-2": "^2.1.0",
"jest-watch-typeahead": "^2.2.1",
"ncp": "^2.0.0",
"npm-run-all": "^4.1.5",
"rimraf": "^3.0.2",
"size-limit": "^8.1.0",
"ts-jest": "^29.0.3",
"typescript": "^4.9.4"
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { describe, expect, it } from '@jest/globals'
import { patternKeyCompare } from './resolve.js'
import { patternKeyCompare } from './index.js'

/**
* @see https://nodejs.org/api/esm.html#esm_resolver_algorithm_specification
Expand Down
16 changes: 16 additions & 0 deletions packages/pattern-key-compare/ts/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* Implementation of `PATTERN_KEY_COMPARE`
*
* @see https://nodejs.org/api/esm.html#esm_resolver_algorithm_specification
*/
export function patternKeyCompare(a: string, b: string) {
const iA = a.indexOf('*')
const iB = b.indexOf('*')
const baseLengthA = iA === -1 ? a.length : iA + 1
const baseLengthB = iB === -1 ? b.length : iB + 1
if (baseLengthA > baseLengthB) return -1
if (baseLengthA < baseLengthB) return 1
if (iA === -1) return 1
if (iB === -1) return -1
return a.length > b.length ? -1 : a.length < b.length ? 1 : 0
}
15 changes: 15 additions & 0 deletions packages/pattern-key-compare/tsconfig.base.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"compilerOptions": {
"composite": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "Node16",
"newLine": "LF",
"rootDir": "ts",
"strict": true,
"target": "ES2020"
},
"include": [
"ts",
"types"
]
}
8 changes: 8 additions & 0 deletions packages/pattern-key-compare/tsconfig.cjs.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"extends": "./tsconfig.base.json",
"compilerOptions": {
"esModuleInterop": true,
"module": "CommonJS",
"outDir": "cjs"
}
}
9 changes: 9 additions & 0 deletions packages/pattern-key-compare/tsconfig.esm.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"extends": "./tsconfig.base.json",
"compilerOptions": {
"declaration": true,
"declarationMap": true,
"module": "Node16",
"outDir": "esm"
}
}
6 changes: 6 additions & 0 deletions packages/pattern-key-compare/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"extends": "./tsconfig.esm.json",
"compilerOptions": {
"esModuleInterop": true
}
}
1 change: 1 addition & 0 deletions packages/resolve.imports/.depcheckrc.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
ignores:
- '@repobuddy/jest'
- '@size-limit/preset-small-lib'
- '@types/node'
- jest
- jest-*
Expand Down
4 changes: 2 additions & 2 deletions packages/resolve.imports/.size-limit.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
[
{
"path": "./cjs/index.js",
"limit": "10 KB"
"limit": "2 KB"
},
{
"path": "./esm/index.js",
"limit": "10 KB"
"limit": "2 KB"
}
]
6 changes: 0 additions & 6 deletions packages/resolve.imports/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,12 +198,6 @@ The phrase `target with every instance of "*" replaced by patternMatch` indicate
This module supports multiple `*`s in the replacer pattern as described,
but it is likely a bug in the spec, as the resulting string likely does not make sense.

### `PATTERN_KEY_COMPARE`

> Assert: keyA/B ends with "/" or contains only a single "*"

This is not correct as it supports file extensions (e.g. `#a/b.js`)

## References

- [NodeJS resolver algorithm][resolver-algorithm]
Expand Down
6 changes: 6 additions & 0 deletions packages/resolve.imports/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,18 @@
"clean": "rimraf cjs esm tslib *.tsbuildinfo",
"coverage": "cross-env NODE_OPTIONS=--experimental-vm-modules NODE_OPTIONS=--experimental-import-meta-resolve NODE_NO_WARNINGS=1 jest --coverage",
"depcheck": "depcheck",
"size": "size-limit",
"test": "cross-env NODE_OPTIONS=--experimental-vm-modules NODE_OPTIONS=--experimental-import-meta-resolve jest",
"test:watch": "cross-env NODE_OPTIONS=--experimental-vm-modules NODE_OPTIONS=--experimental-import-meta-resolve jest --watch",
"verify": "npm-run-all -p build -p test depcheck size"
},
"dependencies": {
"pattern-key-compare": "workspace:^"
},
"devDependencies": {
"@jest/globals": "^29.3.1",
"@repobuddy/jest": "^2.3.0",
"@size-limit/preset-small-lib": "^8.1.0",
"@types/node": "^14",
"cross-env": "^7.0.3",
"depcheck": "^1.4.3",
Expand All @@ -73,6 +78,7 @@
"ncp": "^2.0.0",
"npm-run-all": "^4.1.5",
"rimraf": "^3.0.2",
"size-limit": "^8.1.0",
"ts-jest": "^29.0.3",
"typescript": "^4.9.4"
}
Expand Down
18 changes: 2 additions & 16 deletions packages/resolve.imports/ts/resolve.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { patternKeyCompare } from 'pattern-key-compare'

export type ResolveOptions = {
/**
* Array of conditions to resolve.
Expand Down Expand Up @@ -65,19 +67,3 @@ function noRecursive(value: string | string[] | undefined): string | string[] |
function sortExpensionKeys(keys: string[]) {
return keys.sort(patternKeyCompare)
}

/**
* `PATTERN_KEY_COMPARE`
* @see https://nodejs.org/api/esm.html#esm_resolver_algorithm_specification
*/
export function patternKeyCompare(a: string, b: string) {
const iA = a.indexOf('*')
const iB = b.indexOf('*')
const baseLengthA = iA === -1 ? a.length : iA + 1
const baseLengthB = iB === -1 ? b.length : iB + 1
if (baseLengthA > baseLengthB) return -1
if (baseLengthA < baseLengthB) return 1
if (iA === -1) return 1
if (iB === -1) return -1
return a.length > b.length ? -1 : a.length < b.length ? 1 : 0
}
Loading

0 comments on commit b137fa2

Please sign in to comment.