Compare commits
16 Commits
0fd0e3bada
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
d0164640a1
|
|||
|
ae5305f3c6
|
|||
|
31c0757780
|
|||
|
696729d2c2
|
|||
|
bdea643256
|
|||
|
4e5dfd7134
|
|||
|
955acc6c96
|
|||
|
c7a6d6880c
|
|||
|
400644e079
|
|||
|
f6a9dd97ed
|
|||
|
806d735c35
|
|||
|
637991c394
|
|||
|
afa4c8a684
|
|||
|
75219bc716
|
|||
|
c98e462142
|
|||
|
9af08e71fc
|
275
package-lock.json
generated
275
package-lock.json
generated
@@ -9,16 +9,15 @@
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.14.15",
|
||||
"esbuild": "^0.23.0",
|
||||
"tsx": "^4.17.0",
|
||||
"typescript": "^5.5.4"
|
||||
"@types/node": "^25.5.0",
|
||||
"tsx": "^4.19.4",
|
||||
"typescript": "^6.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/aix-ppc64": {
|
||||
"version": "0.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.0.tgz",
|
||||
"integrity": "sha512-3sG8Zwa5fMcA9bgqB8AfWPQ+HFke6uD3h1s3RIwUNK8EG7a4buxvuFTs3j1IMs2NXAk9F30C/FF4vxRgQCcmoQ==",
|
||||
"version": "0.27.7",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz",
|
||||
"integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
@@ -33,9 +32,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-arm": {
|
||||
"version": "0.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.0.tgz",
|
||||
"integrity": "sha512-+KuOHTKKyIKgEEqKbGTK8W7mPp+hKinbMBeEnNzjJGyFcWsfrXjSTNluJHCY1RqhxFurdD8uNXQDei7qDlR6+g==",
|
||||
"version": "0.27.7",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.7.tgz",
|
||||
"integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@@ -50,9 +49,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-arm64": {
|
||||
"version": "0.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.0.tgz",
|
||||
"integrity": "sha512-EuHFUYkAVfU4qBdyivULuu03FhJO4IJN9PGuABGrFy4vUuzk91P2d+npxHcFdpUnfYKy0PuV+n6bKIpHOB3prQ==",
|
||||
"version": "0.27.7",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz",
|
||||
"integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -67,9 +66,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-x64": {
|
||||
"version": "0.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.0.tgz",
|
||||
"integrity": "sha512-WRrmKidLoKDl56LsbBMhzTTBxrsVwTKdNbKDalbEZr0tcsBgCLbEtoNthOW6PX942YiYq8HzEnb4yWQMLQuipQ==",
|
||||
"version": "0.27.7",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.7.tgz",
|
||||
"integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -84,9 +83,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/darwin-arm64": {
|
||||
"version": "0.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.0.tgz",
|
||||
"integrity": "sha512-YLntie/IdS31H54Ogdn+v50NuoWF5BDkEUFpiOChVa9UnKpftgwzZRrI4J132ETIi+D8n6xh9IviFV3eXdxfow==",
|
||||
"version": "0.27.7",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz",
|
||||
"integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -101,9 +100,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/darwin-x64": {
|
||||
"version": "0.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.0.tgz",
|
||||
"integrity": "sha512-IMQ6eme4AfznElesHUPDZ+teuGwoRmVuuixu7sv92ZkdQcPbsNHzutd+rAfaBKo8YK3IrBEi9SLLKWJdEvJniQ==",
|
||||
"version": "0.27.7",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz",
|
||||
"integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -118,9 +117,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/freebsd-arm64": {
|
||||
"version": "0.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.0.tgz",
|
||||
"integrity": "sha512-0muYWCng5vqaxobq6LB3YNtevDFSAZGlgtLoAc81PjUfiFz36n4KMpwhtAd4he8ToSI3TGyuhyx5xmiWNYZFyw==",
|
||||
"version": "0.27.7",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz",
|
||||
"integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -135,9 +134,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/freebsd-x64": {
|
||||
"version": "0.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.0.tgz",
|
||||
"integrity": "sha512-XKDVu8IsD0/q3foBzsXGt/KjD/yTKBCIwOHE1XwiXmrRwrX6Hbnd5Eqn/WvDekddK21tfszBSrE/WMaZh+1buQ==",
|
||||
"version": "0.27.7",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz",
|
||||
"integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -152,9 +151,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-arm": {
|
||||
"version": "0.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.0.tgz",
|
||||
"integrity": "sha512-SEELSTEtOFu5LPykzA395Mc+54RMg1EUgXP+iw2SJ72+ooMwVsgfuwXo5Fn0wXNgWZsTVHwY2cg4Vi/bOD88qw==",
|
||||
"version": "0.27.7",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz",
|
||||
"integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@@ -169,9 +168,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-arm64": {
|
||||
"version": "0.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.0.tgz",
|
||||
"integrity": "sha512-j1t5iG8jE7BhonbsEg5d9qOYcVZv/Rv6tghaXM/Ug9xahM0nX/H2gfu6X6z11QRTMT6+aywOMA8TDkhPo8aCGw==",
|
||||
"version": "0.27.7",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz",
|
||||
"integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -186,9 +185,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-ia32": {
|
||||
"version": "0.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.0.tgz",
|
||||
"integrity": "sha512-P7O5Tkh2NbgIm2R6x1zGJJsnacDzTFcRWZyTTMgFdVit6E98LTxO+v8LCCLWRvPrjdzXHx9FEOA8oAZPyApWUA==",
|
||||
"version": "0.27.7",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz",
|
||||
"integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
@@ -203,9 +202,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-loong64": {
|
||||
"version": "0.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.0.tgz",
|
||||
"integrity": "sha512-InQwepswq6urikQiIC/kkx412fqUZudBO4SYKu0N+tGhXRWUqAx+Q+341tFV6QdBifpjYgUndV1hhMq3WeJi7A==",
|
||||
"version": "0.27.7",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz",
|
||||
"integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==",
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
@@ -220,9 +219,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-mips64el": {
|
||||
"version": "0.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.0.tgz",
|
||||
"integrity": "sha512-J9rflLtqdYrxHv2FqXE2i1ELgNjT+JFURt/uDMoPQLcjWQA5wDKgQA4t/dTqGa88ZVECKaD0TctwsUfHbVoi4w==",
|
||||
"version": "0.27.7",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz",
|
||||
"integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==",
|
||||
"cpu": [
|
||||
"mips64el"
|
||||
],
|
||||
@@ -237,9 +236,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-ppc64": {
|
||||
"version": "0.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.0.tgz",
|
||||
"integrity": "sha512-cShCXtEOVc5GxU0fM+dsFD10qZ5UpcQ8AM22bYj0u/yaAykWnqXJDpd77ublcX6vdDsWLuweeuSNZk4yUxZwtw==",
|
||||
"version": "0.27.7",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz",
|
||||
"integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
@@ -254,9 +253,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-riscv64": {
|
||||
"version": "0.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.0.tgz",
|
||||
"integrity": "sha512-HEtaN7Y5UB4tZPeQmgz/UhzoEyYftbMXrBCUjINGjh3uil+rB/QzzpMshz3cNUxqXN7Vr93zzVtpIDL99t9aRw==",
|
||||
"version": "0.27.7",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz",
|
||||
"integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
@@ -271,9 +270,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-s390x": {
|
||||
"version": "0.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.0.tgz",
|
||||
"integrity": "sha512-WDi3+NVAuyjg/Wxi+o5KPqRbZY0QhI9TjrEEm+8dmpY9Xir8+HE/HNx2JoLckhKbFopW0RdO2D72w8trZOV+Wg==",
|
||||
"version": "0.27.7",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz",
|
||||
"integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
@@ -288,9 +287,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-x64": {
|
||||
"version": "0.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.0.tgz",
|
||||
"integrity": "sha512-a3pMQhUEJkITgAw6e0bWA+F+vFtCciMjW/LPtoj99MhVt+Mfb6bbL9hu2wmTZgNd994qTAEw+U/r6k3qHWWaOQ==",
|
||||
"version": "0.27.7",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz",
|
||||
"integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -304,10 +303,27 @@
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/netbsd-arm64": {
|
||||
"version": "0.27.7",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz",
|
||||
"integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"netbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/netbsd-x64": {
|
||||
"version": "0.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.0.tgz",
|
||||
"integrity": "sha512-cRK+YDem7lFTs2Q5nEv/HHc4LnrfBCbH5+JHu6wm2eP+d8OZNoSMYgPZJq78vqQ9g+9+nMuIsAO7skzphRXHyw==",
|
||||
"version": "0.27.7",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz",
|
||||
"integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -322,9 +338,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/openbsd-arm64": {
|
||||
"version": "0.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.0.tgz",
|
||||
"integrity": "sha512-suXjq53gERueVWu0OKxzWqk7NxiUWSUlrxoZK7usiF50C6ipColGR5qie2496iKGYNLhDZkPxBI3erbnYkU0rQ==",
|
||||
"version": "0.27.7",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz",
|
||||
"integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -339,9 +355,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/openbsd-x64": {
|
||||
"version": "0.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.0.tgz",
|
||||
"integrity": "sha512-6p3nHpby0DM/v15IFKMjAaayFhqnXV52aEmv1whZHX56pdkK+MEaLoQWj+H42ssFarP1PcomVhbsR4pkz09qBg==",
|
||||
"version": "0.27.7",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz",
|
||||
"integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -355,10 +371,27 @@
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/openharmony-arm64": {
|
||||
"version": "0.27.7",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz",
|
||||
"integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openharmony"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/sunos-x64": {
|
||||
"version": "0.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.0.tgz",
|
||||
"integrity": "sha512-BFelBGfrBwk6LVrmFzCq1u1dZbG4zy/Kp93w2+y83Q5UGYF1d8sCzeLI9NXjKyujjBBniQa8R8PzLFAUrSM9OA==",
|
||||
"version": "0.27.7",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz",
|
||||
"integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -373,9 +406,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-arm64": {
|
||||
"version": "0.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.0.tgz",
|
||||
"integrity": "sha512-lY6AC8p4Cnb7xYHuIxQ6iYPe6MfO2CC43XXKo9nBXDb35krYt7KGhQnOkRGar5psxYkircpCqfbNDB4uJbS2jQ==",
|
||||
"version": "0.27.7",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz",
|
||||
"integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -390,9 +423,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-ia32": {
|
||||
"version": "0.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.0.tgz",
|
||||
"integrity": "sha512-7L1bHlOTcO4ByvI7OXVI5pNN6HSu6pUQq9yodga8izeuB1KcT2UkHaH6118QJwopExPn0rMHIseCTx1CRo/uNA==",
|
||||
"version": "0.27.7",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz",
|
||||
"integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
@@ -407,9 +440,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-x64": {
|
||||
"version": "0.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.0.tgz",
|
||||
"integrity": "sha512-Arm+WgUFLUATuoxCJcahGuk6Yj9Pzxd6l11Zb/2aAuv5kWWvvfhLFo2fni4uSK5vzlUdCGZ/BdV5tH8klj8p8g==",
|
||||
"version": "0.27.7",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz",
|
||||
"integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -424,19 +457,19 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "20.14.15",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.15.tgz",
|
||||
"integrity": "sha512-Fz1xDMCF/B00/tYSVMlmK7hVeLh7jE5f3B7X1/hmV0MJBwE27KlS7EvD/Yp+z1lm8mVhwV5w+n8jOZG8AfTlKw==",
|
||||
"version": "25.5.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.5.2.tgz",
|
||||
"integrity": "sha512-tO4ZIRKNC+MDWV4qKVZe3Ql/woTnmHDr5JD8UI5hn2pwBrHEwOEMZK7WlNb5RKB6EoJ02gwmQS9OrjuFnZYdpg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~5.26.4"
|
||||
"undici-types": "~7.18.0"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.23.0",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.0.tgz",
|
||||
"integrity": "sha512-1lvV17H2bMYda/WaFb2jLPeHU3zml2k4/yagNMG8Q/YtfMjCwEUZa2eXXMgZTVSL5q1n4H7sQ0X6CdJDqqeCFA==",
|
||||
"version": "0.27.7",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz",
|
||||
"integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
@@ -447,30 +480,32 @@
|
||||
"node": ">=18"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@esbuild/aix-ppc64": "0.23.0",
|
||||
"@esbuild/android-arm": "0.23.0",
|
||||
"@esbuild/android-arm64": "0.23.0",
|
||||
"@esbuild/android-x64": "0.23.0",
|
||||
"@esbuild/darwin-arm64": "0.23.0",
|
||||
"@esbuild/darwin-x64": "0.23.0",
|
||||
"@esbuild/freebsd-arm64": "0.23.0",
|
||||
"@esbuild/freebsd-x64": "0.23.0",
|
||||
"@esbuild/linux-arm": "0.23.0",
|
||||
"@esbuild/linux-arm64": "0.23.0",
|
||||
"@esbuild/linux-ia32": "0.23.0",
|
||||
"@esbuild/linux-loong64": "0.23.0",
|
||||
"@esbuild/linux-mips64el": "0.23.0",
|
||||
"@esbuild/linux-ppc64": "0.23.0",
|
||||
"@esbuild/linux-riscv64": "0.23.0",
|
||||
"@esbuild/linux-s390x": "0.23.0",
|
||||
"@esbuild/linux-x64": "0.23.0",
|
||||
"@esbuild/netbsd-x64": "0.23.0",
|
||||
"@esbuild/openbsd-arm64": "0.23.0",
|
||||
"@esbuild/openbsd-x64": "0.23.0",
|
||||
"@esbuild/sunos-x64": "0.23.0",
|
||||
"@esbuild/win32-arm64": "0.23.0",
|
||||
"@esbuild/win32-ia32": "0.23.0",
|
||||
"@esbuild/win32-x64": "0.23.0"
|
||||
"@esbuild/aix-ppc64": "0.27.7",
|
||||
"@esbuild/android-arm": "0.27.7",
|
||||
"@esbuild/android-arm64": "0.27.7",
|
||||
"@esbuild/android-x64": "0.27.7",
|
||||
"@esbuild/darwin-arm64": "0.27.7",
|
||||
"@esbuild/darwin-x64": "0.27.7",
|
||||
"@esbuild/freebsd-arm64": "0.27.7",
|
||||
"@esbuild/freebsd-x64": "0.27.7",
|
||||
"@esbuild/linux-arm": "0.27.7",
|
||||
"@esbuild/linux-arm64": "0.27.7",
|
||||
"@esbuild/linux-ia32": "0.27.7",
|
||||
"@esbuild/linux-loong64": "0.27.7",
|
||||
"@esbuild/linux-mips64el": "0.27.7",
|
||||
"@esbuild/linux-ppc64": "0.27.7",
|
||||
"@esbuild/linux-riscv64": "0.27.7",
|
||||
"@esbuild/linux-s390x": "0.27.7",
|
||||
"@esbuild/linux-x64": "0.27.7",
|
||||
"@esbuild/netbsd-arm64": "0.27.7",
|
||||
"@esbuild/netbsd-x64": "0.27.7",
|
||||
"@esbuild/openbsd-arm64": "0.27.7",
|
||||
"@esbuild/openbsd-x64": "0.27.7",
|
||||
"@esbuild/openharmony-arm64": "0.27.7",
|
||||
"@esbuild/sunos-x64": "0.27.7",
|
||||
"@esbuild/win32-arm64": "0.27.7",
|
||||
"@esbuild/win32-ia32": "0.27.7",
|
||||
"@esbuild/win32-x64": "0.27.7"
|
||||
}
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
@@ -489,9 +524,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/get-tsconfig": {
|
||||
"version": "4.7.6",
|
||||
"resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.6.tgz",
|
||||
"integrity": "sha512-ZAqrLlu18NbDdRaHq+AKXzAmqIUPswPWKUchfytdAjiRFnCe5ojG2bstg6mRiZabkKfCoL/e98pbBELIV/YCeA==",
|
||||
"version": "4.13.7",
|
||||
"resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.7.tgz",
|
||||
"integrity": "sha512-7tN6rFgBlMgpBML5j8typ92BKFi2sFQvIdpAqLA2beia5avZDrMs0FLZiM5etShWq5irVyGcGMEA1jcDaK7A/Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -512,13 +547,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/tsx": {
|
||||
"version": "4.17.0",
|
||||
"resolved": "https://registry.npmjs.org/tsx/-/tsx-4.17.0.tgz",
|
||||
"integrity": "sha512-eN4mnDA5UMKDt4YZixo9tBioibaMBpoxBkD+rIPAjVmYERSG0/dWEY1CEFuV89CgASlKL499q8AhmkMnnjtOJg==",
|
||||
"version": "4.21.0",
|
||||
"resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz",
|
||||
"integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"esbuild": "~0.23.0",
|
||||
"esbuild": "~0.27.0",
|
||||
"get-tsconfig": "^4.7.5"
|
||||
},
|
||||
"bin": {
|
||||
@@ -532,9 +567,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.5.4",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz",
|
||||
"integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==",
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.2.tgz",
|
||||
"integrity": "sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
@@ -546,9 +581,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "5.26.5",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
||||
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
|
||||
"version": "7.18.2",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz",
|
||||
"integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
}
|
||||
|
||||
20
package.json
20
package.json
@@ -6,15 +6,23 @@
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"start": "tsx src/index.ts",
|
||||
"test": "tsx src/test.ts",
|
||||
"build": "tsc && esbuild --bundle --minify --sourcemap --platform=node --target=node20 --outdir=build src/index.ts"
|
||||
"test": "tsx src/test.ts"
|
||||
},
|
||||
"author": "Hervé BECHER",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.14.15",
|
||||
"esbuild": "^0.23.0",
|
||||
"tsx": "^4.17.0",
|
||||
"typescript": "^5.5.4"
|
||||
"@types/node": "^25.5.0",
|
||||
"tsx": "^4.19.4",
|
||||
"typescript": "^6.0.2"
|
||||
},
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./src/index.ts",
|
||||
"types": "./src/index.ts"
|
||||
},
|
||||
"./*": {
|
||||
"import": "./src/*.ts",
|
||||
"types": "./src/*.ts"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,13 +2,17 @@ import { wrap as wrapSync } from "../sync/index.js";
|
||||
import { Sequence } from "../sync/types.js";
|
||||
import { MaybeAsyncGenerator, MaybeAsyncIterable, MaybePromiseLike } from "../types.js";
|
||||
import { isAsyncIterable } from "../utils.js";
|
||||
import { WrappedSequence, WrappedAsyncIterable, WrappedObjectAsync, WrappedArrayAsync, WrappedArrayLikeAsync, FunctionAsyncSequence, GeneratorAsyncSequence, RangeAsyncSequence, RepeatForeverAsyncSequence, RepeatAsyncSequence, AsyncSequenceMarker, EMPTY, ConcatAsyncSequence } from "./impl.js";
|
||||
import { WrappedSequence, WrappedAsyncIterable, WrappedObjectAsync, WrappedArrayAsync, WrappedArrayLikeAsync, FunctionAsyncSequence, GeneratorAsyncSequence, RangeAsyncSequence, RepeatForeverAsyncSequence, RepeatAsyncSequence, AsyncSequenceMarker, EMPTY, ConcatAsyncSequence, WrappedPromise } from "./impl.js";
|
||||
import { AsyncSequence } from "./types.js";
|
||||
|
||||
export function asAsync<T>(sequence: Sequence<MaybePromiseLike<T>>): AsyncSequence<T> {
|
||||
return new WrappedSequence(sequence);
|
||||
}
|
||||
|
||||
export function wrapPromise<T>(promise: Promise<MaybeAsyncIterable<T>>): AsyncSequence<T> {
|
||||
return new WrappedPromise(promise);
|
||||
}
|
||||
|
||||
export function wrap<T>(iterable: MaybeAsyncIterable<MaybePromiseLike<T>>): AsyncSequence<T> {
|
||||
if (isAsyncSequence<T>(iterable)) {
|
||||
return iterable;
|
||||
@@ -33,7 +37,7 @@ export function single<T>(obj: MaybePromiseLike<T>): AsyncSequence<T> {
|
||||
return new WrappedObjectAsync(obj);
|
||||
}
|
||||
|
||||
export function array<T>(array: MaybePromiseLike<T>[]): AsyncSequence<T> {
|
||||
export function array<T>(array: ReadonlyArray<MaybePromiseLike<T>>): AsyncSequence<T> {
|
||||
return new WrappedArrayAsync(array);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
import { Collector } from "../collector/types.js";
|
||||
import { MaybeAsyncComparisonOrComparer, AsyncComparer } from "../comparer/types.js";
|
||||
import { MaybeAsyncEqualityComparisonOrComparer } from "../equality-comparer/types.js";
|
||||
import { AsyncRandomOptions } from "../random/types.js";
|
||||
import { MaybeAsyncAnyPredicate, MaybeAsyncConverter, MaybeAsyncEquater, MaybeAsyncBiConverter, MaybeAsyncAccumulator, MaybeAsyncComparer, MaybeAsyncAction, MaybeAsyncSequence } from "../types.js";
|
||||
import { MaybeAsyncAnyPredicate, MaybeAsyncConverter, MaybeAsyncBiConverter, MaybeAsyncAccumulator, MaybeAsyncAction, MaybeAsyncFunction, MaybePromise, MaybeAsyncIterable } from "../types.js";
|
||||
|
||||
export type AsyncSequencePipeline<TElement, TResult> = MaybeAsyncFunction<(sequence: AsyncSequence<TElement>) => TResult>;
|
||||
export type AsyncSequenceElement<TAsyncSequence extends AsyncSequence<any>> = TAsyncSequence extends AsyncSequence<infer TElement> ? TElement : never;
|
||||
|
||||
export interface AsyncSequence<TElement> extends AsyncIterable<TElement> {
|
||||
iterator(): AsyncIterator<TElement>;
|
||||
|
||||
apply<TResult>(pipeline: (sequence: AsyncSequence<TElement>) => TResult): TResult;
|
||||
apply<TResult>(pipeline: AsyncSequencePipeline<TElement, TResult>): MaybePromise<TResult>;
|
||||
|
||||
count(predicate?: MaybeAsyncAnyPredicate<TElement>): Promise<number>;
|
||||
nonEnumeratedCount(): Promise<number>;
|
||||
@@ -13,30 +18,31 @@ export interface AsyncSequence<TElement> extends AsyncIterable<TElement> {
|
||||
maxCount(): Promise<number>;
|
||||
|
||||
select<TResult>(selector: MaybeAsyncConverter<TElement, TResult>): AsyncSequence<TResult>;
|
||||
selectMany<TResult>(selector: MaybeAsyncConverter<TElement, MaybeAsyncSequence<TResult>>): AsyncSequence<TResult>;
|
||||
selectMany<TResult>(selector: MaybeAsyncConverter<TElement, MaybeAsyncIterable<TResult>>): AsyncSequence<TResult>;
|
||||
|
||||
where<TFiltered extends TElement>(predicate: MaybeAsyncAnyPredicate<TElement>): AsyncSequence<TFiltered>;
|
||||
where(predicate: MaybeAsyncAnyPredicate<TElement>): AsyncSequence<TElement>;
|
||||
|
||||
groupBy<TKey>(keySelector: MaybeAsyncConverter<TElement, TKey>, elementSelector?: undefined, keyComparer?: MaybeAsyncEquater<TKey>): AsyncSequence<GroupedAsyncSequence<TKey, TElement>>;
|
||||
groupBy<TKey, TResult>(keySelector: MaybeAsyncConverter<TElement, TKey>, elementSelector: MaybeAsyncConverter<TElement, TResult>, keyComparer?: MaybeAsyncEquater<TKey>): AsyncSequence<GroupedAsyncSequence<TKey, TResult>>;
|
||||
groupBy<TKey>(keySelector: MaybeAsyncConverter<TElement, TKey>, elementSelector?: undefined, keyComparer?: MaybeAsyncEqualityComparisonOrComparer<TKey>): AsyncSequence<GroupedAsyncSequence<TKey, TElement>>;
|
||||
groupBy<TKey, TResult>(keySelector: MaybeAsyncConverter<TElement, TKey>, elementSelector: MaybeAsyncConverter<TElement, TResult>, keyComparer?: MaybeAsyncEqualityComparisonOrComparer<TKey>): AsyncSequence<GroupedAsyncSequence<TKey, TResult>>;
|
||||
|
||||
join<TOther, TKey>(sequence: MaybeAsyncSequence<TOther>, firstKeySelector: MaybeAsyncConverter<TElement, TKey>, secondKeySelector: MaybeAsyncConverter<TOther, TKey>, resultSelector?: undefined, keyComparer?: MaybeAsyncEquater<TKey>): AsyncSequence<[TElement, TOther]>;
|
||||
join<TOther, TKey, TResult>(sequence: MaybeAsyncSequence<TOther>, firstKeySelector: MaybeAsyncConverter<TElement, TKey>, secondKeySelector: MaybeAsyncConverter<TOther, TKey>, resultSelector: MaybeAsyncBiConverter<TElement, TOther, TResult>, keyComparer?: MaybeAsyncEquater<TKey>): AsyncSequence<TResult>;
|
||||
join<TOther, TKey>(sequence: MaybeAsyncIterable<TOther>, firstKeySelector: MaybeAsyncConverter<TElement, TKey>, secondKeySelector: MaybeAsyncConverter<TOther, TKey>, resultSelector?: undefined, keyComparer?: MaybeAsyncEqualityComparisonOrComparer<TKey>): AsyncSequence<[TElement, TOther]>;
|
||||
join<TOther, TKey, TResult>(sequence: MaybeAsyncIterable<TOther>, firstKeySelector: MaybeAsyncConverter<TElement, TKey>, secondKeySelector: MaybeAsyncConverter<TOther, TKey>, resultSelector: MaybeAsyncBiConverter<TElement, TOther, TResult>, keyComparer?: MaybeAsyncEqualityComparisonOrComparer<TKey>): AsyncSequence<TResult>;
|
||||
|
||||
groupJoin<TOther, TKey>(sequence: MaybeAsyncSequence<TOther>, firstKeySelector: MaybeAsyncConverter<TElement, TKey>, secondKeySelector: MaybeAsyncConverter<TOther, TKey>, resultSelector?: undefined, keyComparer?: MaybeAsyncEquater<TKey>): AsyncSequence<GroupedAsyncSequence<TElement, TOther>>;
|
||||
groupJoin<TOther, TKey, TResult>(sequence: MaybeAsyncSequence<TOther>, firstKeySelector: MaybeAsyncConverter<TElement, TKey>, secondKeySelector: MaybeAsyncConverter<TOther, TKey>, resultSelector: MaybeAsyncBiConverter<TElement, AsyncSequence<TOther>, TResult>, keyComparer?: MaybeAsyncEquater<TKey>): AsyncSequence<TResult>;
|
||||
groupJoin<TOther, TKey>(sequence: MaybeAsyncIterable<TOther>, firstKeySelector: MaybeAsyncConverter<TElement, TKey>, secondKeySelector: MaybeAsyncConverter<TOther, TKey>, resultSelector?: undefined, keyComparer?: MaybeAsyncEqualityComparisonOrComparer<TKey>): AsyncSequence<GroupedAsyncSequence<TElement, TOther>>;
|
||||
groupJoin<TOther, TKey, TResult>(sequence: MaybeAsyncIterable<TOther>, firstKeySelector: MaybeAsyncConverter<TElement, TKey>, secondKeySelector: MaybeAsyncConverter<TOther, TKey>, resultSelector: MaybeAsyncBiConverter<TElement, MaybeAsyncIterable<TOther>, TResult>, keyComparer?: MaybeAsyncEqualityComparisonOrComparer<TKey>): AsyncSequence<TResult>;
|
||||
|
||||
contains(obj: TElement, equater?: MaybeAsyncEquater<TElement>): Promise<boolean>;
|
||||
contains(obj: TElement, equater?: MaybeAsyncEqualityComparisonOrComparer<TElement>): Promise<boolean>;
|
||||
|
||||
sequenceEquals(sequence: MaybeAsyncSequence<TElement>, equater?: MaybeAsyncEquater<TElement>): Promise<boolean>;
|
||||
sequenceEquals(sequence: MaybeAsyncIterable<TElement>, equater?: MaybeAsyncEqualityComparisonOrComparer<TElement>): Promise<boolean>;
|
||||
|
||||
append(obj: TElement): AsyncSequence<TElement>;
|
||||
|
||||
prepend(obj: TElement): AsyncSequence<TElement>;
|
||||
|
||||
remove(obj: TElement, all?: boolean, equater?: MaybeAsyncEquater<TElement>): AsyncSequence<TElement>;
|
||||
remove(obj: TElement, all?: boolean, equater?: MaybeAsyncEqualityComparisonOrComparer<TElement>): AsyncSequence<TElement>;
|
||||
|
||||
concat(...sequences: MaybeAsyncSequence<TElement>[]): AsyncSequence<TElement>;
|
||||
concat(...sequences: MaybeAsyncIterable<TElement>[]): AsyncSequence<TElement>;
|
||||
|
||||
first(predicate?: MaybeAsyncAnyPredicate<TElement>): Promise<TElement>;
|
||||
firstOrDefault(predicate?: MaybeAsyncAnyPredicate<TElement>, def?: TElement): Promise<TElement | undefined>;
|
||||
@@ -60,26 +66,29 @@ export interface AsyncSequence<TElement> extends AsyncIterable<TElement> {
|
||||
max(): Promise<TElement>;
|
||||
maxBy<TBy>(selector: MaybeAsyncConverter<TElement, TBy>): Promise<TElement>;
|
||||
|
||||
order(comparer?: MaybeAsyncComparer<TElement>): AsyncSequence<TElement>;
|
||||
orderBy<TBy>(selector: MaybeAsyncConverter<TElement, TBy>, comparer?: MaybeAsyncComparer<TBy>): AsyncSequence<TElement>;
|
||||
bounds(comparer?: MaybeAsyncComparisonOrComparer<TElement>): Promise<[min: TElement, max: TElement]>;
|
||||
boundsBy<TBy>(selector: MaybeAsyncConverter<TElement, TBy>, comparer?: MaybeAsyncComparisonOrComparer<TBy>): Promise<[min: TElement, max: TElement]>;
|
||||
|
||||
orderDescending(comparer?: MaybeAsyncComparer<TElement>): AsyncSequence<TElement>;
|
||||
orderByDescending<TBy>(selector: MaybeAsyncConverter<TElement, TBy>, comparer?: MaybeAsyncComparer<TBy>): AsyncSequence<TElement>;
|
||||
order(comparer?: MaybeAsyncComparisonOrComparer<TElement>): OrderedAsyncSequence<TElement>;
|
||||
orderBy<TBy>(selector: MaybeAsyncConverter<TElement, TBy>, comparer?: MaybeAsyncComparisonOrComparer<TBy>): OrderedAsyncSequence<TElement>;
|
||||
|
||||
partition(equater?: MaybeAsyncEquater<TElement>): AsyncSequence<AsyncSequence<TElement>>;
|
||||
partitionBy<TBy>(selector: MaybeAsyncConverter<TElement, TBy>, equater?: MaybeAsyncEquater<TBy>): AsyncSequence<AsyncSequence<TElement>>;
|
||||
orderDescending(comparer?: MaybeAsyncComparisonOrComparer<TElement>): OrderedAsyncSequence<TElement>;
|
||||
orderByDescending<TBy>(selector: MaybeAsyncConverter<TElement, TBy>, comparer?: MaybeAsyncComparisonOrComparer<TBy>): OrderedAsyncSequence<TElement>;
|
||||
|
||||
distinct(equater?: MaybeAsyncEquater<TElement>): AsyncSequence<TElement>;
|
||||
distinctBy<TBy>(selector: MaybeAsyncConverter<TElement, TBy>, equater?: MaybeAsyncEquater<TBy>): AsyncSequence<TElement>;
|
||||
partition(equater?: MaybeAsyncEqualityComparisonOrComparer<TElement>): AsyncSequence<AsyncSequence<TElement>>;
|
||||
partitionBy<TBy>(selector: MaybeAsyncConverter<TElement, TBy>, equater?: MaybeAsyncEqualityComparisonOrComparer<TBy>): AsyncSequence<AsyncSequence<TElement>>;
|
||||
|
||||
union(sequence: MaybeAsyncSequence<TElement>, equater?: MaybeAsyncEquater<TElement>): AsyncSequence<TElement>;
|
||||
unionBy<TBy>(sequence: MaybeAsyncSequence<TElement>, selector: MaybeAsyncConverter<TElement, TBy>, equater?: MaybeAsyncEquater<TBy>): AsyncSequence<TElement>;
|
||||
distinct(equater?: MaybeAsyncEqualityComparisonOrComparer<TElement>): AsyncSequence<TElement>;
|
||||
distinctBy<TBy>(selector: MaybeAsyncConverter<TElement, TBy>, equater?: MaybeAsyncEqualityComparisonOrComparer<TBy>): AsyncSequence<TElement>;
|
||||
|
||||
except(sequence: MaybeAsyncSequence<TElement>, equater?: MaybeAsyncEquater<TElement>): AsyncSequence<TElement>;
|
||||
exceptBy<TBy>(sequence: MaybeAsyncSequence<TElement>, selector: MaybeAsyncConverter<TElement, TBy>, equater?: MaybeAsyncEquater<TBy>): AsyncSequence<TElement>;
|
||||
union(sequence: MaybeAsyncIterable<TElement>, equater?: MaybeAsyncEqualityComparisonOrComparer<TElement>): AsyncSequence<TElement>;
|
||||
unionBy<TBy>(sequence: MaybeAsyncIterable<TElement>, selector: MaybeAsyncConverter<TElement, TBy>, equater?: MaybeAsyncEqualityComparisonOrComparer<TBy>): AsyncSequence<TElement>;
|
||||
|
||||
intersect(sequence: MaybeAsyncSequence<TElement>, equater?: MaybeAsyncEquater<TElement>): AsyncSequence<TElement>;
|
||||
intersectBy<TBy>(sequence: MaybeAsyncSequence<TElement>, selector: MaybeAsyncConverter<TElement, TBy>, equater?: MaybeAsyncEquater<TBy>): AsyncSequence<TElement>;
|
||||
except(sequence: MaybeAsyncIterable<TElement>, equater?: MaybeAsyncEqualityComparisonOrComparer<TElement>): AsyncSequence<TElement>;
|
||||
exceptBy<TBy>(sequence: MaybeAsyncIterable<TElement>, selector: MaybeAsyncConverter<TElement, TBy>, equater?: MaybeAsyncEqualityComparisonOrComparer<TBy>): AsyncSequence<TElement>;
|
||||
|
||||
intersect(sequence: MaybeAsyncIterable<TElement>, equater?: MaybeAsyncEqualityComparisonOrComparer<TElement>): AsyncSequence<TElement>;
|
||||
intersectBy<TBy>(sequence: MaybeAsyncIterable<TElement>, selector: MaybeAsyncConverter<TElement, TBy>, equater?: MaybeAsyncEqualityComparisonOrComparer<TBy>): AsyncSequence<TElement>;
|
||||
|
||||
all(predicate: MaybeAsyncAnyPredicate<TElement>): Promise<boolean>;
|
||||
any(predicate: MaybeAsyncAnyPredicate<TElement>): Promise<boolean>;
|
||||
@@ -99,14 +108,15 @@ export interface AsyncSequence<TElement> extends AsyncIterable<TElement> {
|
||||
|
||||
forEach(action: MaybeAsyncAction<TElement>): Promise<void>;
|
||||
|
||||
zip<TOther>(sequence: MaybeAsyncSequence<TOther>): AsyncSequence<[TElement, TOther]>;
|
||||
zip<TOther>(sequence: MaybeAsyncIterable<TOther>): AsyncSequence<[TElement, TOther]>;
|
||||
cartesianProduct<TOther>(sequence: MaybeAsyncIterable<TOther>): AsyncSequence<[TElement, TOther]>;
|
||||
|
||||
indexed(): AsyncSequence<[number, TElement]>;
|
||||
|
||||
reversed(): AsyncSequence<TElement>;
|
||||
|
||||
chunked(size: number, asArray?: false): AsyncSequence<AsyncSequence<TElement>>;
|
||||
chunked(size: number, asArray: true): AsyncSequence<TElement[]>;
|
||||
chunked(size: number): AsyncSequence<AsyncSequence<TElement>>;
|
||||
chunked<TResult>(size: number, transformer: AsyncSequencePipeline<TElement, TResult>): AsyncSequence<TResult>;
|
||||
|
||||
random(options?: AsyncRandomOptions<TElement>): Promise<TElement | undefined>;
|
||||
|
||||
@@ -129,13 +139,13 @@ export interface GroupedAsyncSequence<TKey, TElement> extends AsyncSequence<TEle
|
||||
}
|
||||
|
||||
export interface OrderedAsyncSequence<TElement> extends AsyncSequence<TElement> {
|
||||
get comparer(): MaybeAsyncComparer<TElement>;
|
||||
get comparer(): AsyncComparer<TElement>;
|
||||
|
||||
thenSelf(comparer?: MaybeAsyncComparer<TElement>): OrderedAsyncSequence<TElement>;
|
||||
thenSelf(comparer?: MaybeAsyncComparisonOrComparer<TElement>): OrderedAsyncSequence<TElement>;
|
||||
|
||||
thenBy<TBy>(selector: MaybeAsyncConverter<TElement, TBy>, comparer?: MaybeAsyncComparer<TBy>): OrderedAsyncSequence<TElement>;
|
||||
thenBy<TBy>(selector: MaybeAsyncConverter<TElement, TBy>, comparer?: MaybeAsyncComparisonOrComparer<TBy>): OrderedAsyncSequence<TElement>;
|
||||
|
||||
thenSelfDescending(comparer?: MaybeAsyncComparer<TElement>): OrderedAsyncSequence<TElement>;
|
||||
thenSelfDescending(comparer?: MaybeAsyncComparisonOrComparer<TElement>): OrderedAsyncSequence<TElement>;
|
||||
|
||||
thenByDescending<TBy>(selector: MaybeAsyncConverter<TElement, TBy>, comparer?: MaybeAsyncComparer<TBy>): OrderedAsyncSequence<TElement>;
|
||||
thenByDescending<TBy>(selector: MaybeAsyncConverter<TElement, TBy>, comparer?: MaybeAsyncComparisonOrComparer<TBy>): OrderedAsyncSequence<TElement>;
|
||||
}
|
||||
|
||||
@@ -2,27 +2,47 @@ import { asArray } from "../utils.js";
|
||||
import { EmptyBitArray, BitArrayImpl } from "./impl.js";
|
||||
import { BitArray } from "./types.js";
|
||||
|
||||
export const EMPTY = new EmptyBitArray();
|
||||
namespace BitArray {
|
||||
export const EMPTY: BitArray = new EmptyBitArray();
|
||||
|
||||
export function create(length: number): BitArray {
|
||||
if (length < 0) {
|
||||
throw new Error("length < 0");
|
||||
export function create(length: number): BitArray {
|
||||
if (length < 0) {
|
||||
throw new Error("length < 0");
|
||||
}
|
||||
|
||||
return length === 0 ? EMPTY : new BitArrayImpl(length);
|
||||
}
|
||||
|
||||
return length === 0 ? EMPTY : new BitArrayImpl(length);
|
||||
}
|
||||
export function from(bits: Iterable<boolean>) {
|
||||
const arr = asArray(bits);
|
||||
const result = create(arr.length);
|
||||
|
||||
export function from(bits: Iterable<boolean>): BitArray {
|
||||
const arr = asArray(bits);
|
||||
const result = create(arr.length);
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
result.set(i, arr[i]);
|
||||
}
|
||||
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
result.set(i, arr[i]);
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
export function of(...bits: boolean[]) {
|
||||
return from(bits);
|
||||
}
|
||||
|
||||
export function and(a: BitArray, b: BitArray) {
|
||||
return a.copy().and(b);
|
||||
}
|
||||
|
||||
export function or(a: BitArray, b: BitArray) {
|
||||
return a.copy().or(b);
|
||||
}
|
||||
|
||||
export function xor(a: BitArray, b: BitArray) {
|
||||
return a.copy().xor(b);
|
||||
}
|
||||
|
||||
export function not(a: BitArray) {
|
||||
return a.copy().not();
|
||||
}
|
||||
}
|
||||
|
||||
export function of(...bits: boolean[]): BitArray {
|
||||
return from(bits);
|
||||
}
|
||||
export { BitArray };
|
||||
|
||||
@@ -65,6 +65,37 @@ export class ToObjectCollector<TElement, TKey extends PropertyKey, TValue> imple
|
||||
}
|
||||
}
|
||||
|
||||
export class ToObjectListCollector<TElement, TKey extends PropertyKey, TValue> implements Collector<TElement, Record<TKey, TValue[]>, Record<TKey, TValue[]>> {
|
||||
readonly #keySelector: Converter<TElement, TKey>;
|
||||
readonly #valueSelector: Converter<TElement, TValue>;
|
||||
|
||||
constructor(keySelector: Converter<TElement, TKey>, valueSelector: Converter<TElement, TValue>) {
|
||||
this.#keySelector = keySelector;
|
||||
this.#valueSelector = valueSelector;
|
||||
}
|
||||
|
||||
initialize() {
|
||||
return {} as Record<TKey, TValue[]>;
|
||||
}
|
||||
|
||||
accumulate(accumulator: Record<TKey, TValue[]>, element: TElement) {
|
||||
const key = this.#keySelector(element);
|
||||
const value = this.#valueSelector(element);
|
||||
|
||||
const l = accumulator[key];
|
||||
|
||||
if (l) {
|
||||
l.push(value);
|
||||
} else {
|
||||
accumulator[key] = [value];
|
||||
}
|
||||
}
|
||||
|
||||
finalize(accumulator: Record<TKey, TValue[]>) {
|
||||
return accumulator;
|
||||
}
|
||||
}
|
||||
|
||||
export class ToMapCollector<TElement, TKey, TValue> implements Collector<TElement, Map<TKey, TValue>, Map<TKey, TValue>> {
|
||||
readonly #keySelector: Converter<TElement, TKey>;
|
||||
readonly #valueSelector: Converter<TElement, TValue>;
|
||||
@@ -90,6 +121,37 @@ export class ToMapCollector<TElement, TKey, TValue> implements Collector<TElemen
|
||||
}
|
||||
}
|
||||
|
||||
export class ToMapListCollector<TElement, TKey, TValue> implements Collector<TElement, Map<TKey, TValue[]>, Map<TKey, TValue[]>> {
|
||||
readonly #keySelector: Converter<TElement, TKey>;
|
||||
readonly #valueSelector: Converter<TElement, TValue>;
|
||||
|
||||
constructor(keySelector: Converter<TElement, TKey>, valueSelector: Converter<TElement, TValue>) {
|
||||
this.#keySelector = keySelector;
|
||||
this.#valueSelector = valueSelector;
|
||||
}
|
||||
|
||||
initialize() {
|
||||
return new Map<TKey, TValue[]>();
|
||||
}
|
||||
|
||||
accumulate(accumulator: Map<TKey, TValue[]>, element: TElement) {
|
||||
const key = this.#keySelector(element);
|
||||
const value = this.#valueSelector(element);
|
||||
|
||||
const l = accumulator.get(key);
|
||||
|
||||
if (l) {
|
||||
l.push(value);
|
||||
} else {
|
||||
accumulator.set(key, [value]);
|
||||
}
|
||||
}
|
||||
|
||||
finalize(accumulator: Map<TKey, TValue[]>) {
|
||||
return accumulator;
|
||||
}
|
||||
}
|
||||
|
||||
export class ToSetCollector<TElement> implements Collector<TElement, Set<TElement>, Set<TElement>> {
|
||||
initialize() {
|
||||
return new Set<TElement>();
|
||||
@@ -128,60 +190,60 @@ export class JoinCollector implements Collector<any, any[], string> {
|
||||
}
|
||||
}
|
||||
|
||||
export class SumCollector implements Collector<number, { sum: number }, number> {
|
||||
export class SumCollector implements Collector<number, { sum: number; }, number> {
|
||||
initialize() {
|
||||
return { sum: 0 };
|
||||
}
|
||||
|
||||
accumulate(accumulator: { sum: number }, element: number) {
|
||||
accumulate(accumulator: { sum: number; }, element: number) {
|
||||
accumulator.sum += element;
|
||||
}
|
||||
|
||||
finalize(accumulator: { sum: number }) {
|
||||
finalize(accumulator: { sum: number; }) {
|
||||
return accumulator.sum;
|
||||
}
|
||||
}
|
||||
|
||||
export class BigIntSumCollector implements Collector<bigint, { sum: bigint }, bigint> {
|
||||
export class BigIntSumCollector implements Collector<bigint, { sum: bigint; }, bigint> {
|
||||
initialize() {
|
||||
return { sum: 0n, };
|
||||
}
|
||||
|
||||
accumulate(accumulator: { sum: bigint }, element: bigint) {
|
||||
accumulate(accumulator: { sum: bigint; }, element: bigint) {
|
||||
accumulator.sum += element;
|
||||
}
|
||||
|
||||
finalize(accumulator: { sum: bigint }) {
|
||||
finalize(accumulator: { sum: bigint; }) {
|
||||
return accumulator.sum;
|
||||
}
|
||||
}
|
||||
|
||||
export class AverageCollector implements Collector<number, { count: number, sum: number }, number> {
|
||||
export class AverageCollector implements Collector<number, { count: number, sum: number; }, number> {
|
||||
initialize() {
|
||||
return { count: 0, sum: 0 };
|
||||
}
|
||||
|
||||
accumulate(accumulator: { count: number, sum: number }, element: number) {
|
||||
accumulate(accumulator: { count: number, sum: number; }, element: number) {
|
||||
accumulator.count++;
|
||||
accumulator.sum += element;
|
||||
}
|
||||
|
||||
finalize(accumulator: { count: number, sum: number }) {
|
||||
finalize(accumulator: { count: number, sum: number; }) {
|
||||
return accumulator.count === 0 ? 0 : accumulator.sum / accumulator.count;
|
||||
}
|
||||
}
|
||||
|
||||
export class BigIntAverageCollector implements Collector<bigint, { count: number, sum: bigint }, bigint> {
|
||||
export class BigIntAverageCollector implements Collector<bigint, { count: number, sum: bigint; }, bigint> {
|
||||
initialize() {
|
||||
return { count: 0, sum: 0n };
|
||||
}
|
||||
|
||||
accumulate(accumulator: { count: number, sum: bigint }, element: bigint) {
|
||||
accumulate(accumulator: { count: number, sum: bigint; }, element: bigint) {
|
||||
accumulator.count++;
|
||||
accumulator.sum += element;
|
||||
}
|
||||
|
||||
finalize(accumulator: { count: number, sum: bigint }) {
|
||||
finalize(accumulator: { count: number, sum: bigint; }) {
|
||||
return accumulator.count === 0 ? 0n : accumulator.sum / BigInt(accumulator.count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Converter } from "../types.js";
|
||||
import { SimpleCollector, ToArrayCollector, ToObjectCollector, ToMapCollector, ToSetCollector, JoinCollector, SumCollector, BigIntSumCollector, AverageCollector, BigIntAverageCollector } from "./impl.js";
|
||||
import { SimpleCollector, ToArrayCollector, ToObjectCollector, ToMapCollector, ToSetCollector, JoinCollector, SumCollector, BigIntSumCollector, AverageCollector, BigIntAverageCollector, ToObjectListCollector, ToMapListCollector } from "./impl.js";
|
||||
import { Collector } from "./types.js";
|
||||
|
||||
export function create<TElement, TAccumulator, TResult>(initialize: () => TAccumulator, accumulate: (accumulator: TAccumulator, element: TElement) => void,
|
||||
@@ -17,10 +17,18 @@ export function toObject<TElement, TKey extends PropertyKey, TValue>(keySelector
|
||||
return new ToObjectCollector<TElement, TKey, TValue>(keySelector, valueSelector);
|
||||
}
|
||||
|
||||
export function toObjectList<TElement, TKey extends PropertyKey, TValue>(keySelector: Converter<TElement, TKey>, valueSelector: Converter<TElement, TValue>): Collector<TElement, any, Record<TKey, TValue[]>> {
|
||||
return new ToObjectListCollector<TElement, TKey, TValue>(keySelector, valueSelector);
|
||||
}
|
||||
|
||||
export function toMap<TElement, TKey, TValue>(keySelector: Converter<TElement, TKey>, valueSelector: Converter<TElement, TValue>): Collector<TElement, any, Map<TKey, TValue>> {
|
||||
return new ToMapCollector<TElement, TKey, TValue>(keySelector, valueSelector);
|
||||
}
|
||||
|
||||
export function toMapList<TElement, TKey, TValue>(keySelector: Converter<TElement, TKey>, valueSelector: Converter<TElement, TValue>): Collector<TElement, any, Map<TKey, TValue[]>> {
|
||||
return new ToMapListCollector<TElement, TKey, TValue>(keySelector, valueSelector);
|
||||
}
|
||||
|
||||
const toSetCollector = new ToSetCollector<any>();
|
||||
|
||||
export function toSet<TElement>(): Collector<TElement, any, Set<TElement>> {
|
||||
|
||||
219
src/collector/v2/impl.ts
Normal file
219
src/collector/v2/impl.ts
Normal file
@@ -0,0 +1,219 @@
|
||||
// import { Converter } from "../../types.js";
|
||||
// import { CollectorFactory, CollectorInstance } from "./types.js";
|
||||
|
||||
// export class ToArrayCollectorFactory<TElement> implements CollectorFactory<TElement, TElement[]> {
|
||||
// initialize() {
|
||||
// return new ToArrayCollectorInstance<TElement>();
|
||||
// }
|
||||
// };
|
||||
|
||||
// class ToArrayCollectorInstance<TElement> implements CollectorInstance<TElement, TElement[]> {
|
||||
// readonly #accumulator: TElement[];
|
||||
|
||||
// constructor() {
|
||||
// this.#accumulator = [];
|
||||
// }
|
||||
|
||||
// accumulate(element: TElement) {
|
||||
// this.#accumulator.push(element);
|
||||
// }
|
||||
|
||||
// finalize() {
|
||||
// return this.#accumulator;
|
||||
// }
|
||||
// }
|
||||
|
||||
// export class ToObjectCollectorFactory<TElement, TKey extends PropertyKey, TValue> implements CollectorFactory<TElement, Record<TKey, TValue>> {
|
||||
// readonly #keySelector: Converter<TElement, TKey>;
|
||||
// readonly #valueSelector: Converter<TElement, TValue>;
|
||||
|
||||
// constructor(keySelector: Converter<TElement, TKey>, valueSelector: Converter<TElement, TValue>) {
|
||||
// this.#keySelector = keySelector;
|
||||
// this.#valueSelector = valueSelector;
|
||||
// }
|
||||
|
||||
// get keySelector() {
|
||||
// return this.#keySelector;
|
||||
// }
|
||||
|
||||
// get valueSelector() {
|
||||
// return this.#valueSelector;
|
||||
// }
|
||||
|
||||
// initialize() {
|
||||
// return new ToObjectCollectorInstance<TElement, TKey, TValue>(this);
|
||||
// }
|
||||
// }
|
||||
|
||||
// class ToObjectCollectorInstance<TElement, TKey extends PropertyKey, TValue> implements CollectorInstance<TElement, Record<TKey, TValue>> {
|
||||
// readonly #factory: ToObjectCollectorFactory<TElement, TKey, TValue>;
|
||||
// readonly #accumulator = <Record<TKey, TValue>>{};
|
||||
|
||||
// constructor(factory: ToObjectCollectorFactory<TElement, TKey, TValue>) {
|
||||
// this.#factory = factory;
|
||||
// }
|
||||
|
||||
// accumulate(element: TElement) {
|
||||
// const key = this.#factory.keySelector(element);
|
||||
// const value = this.#factory.valueSelector(element);
|
||||
|
||||
// this.#accumulator[key] = value;
|
||||
// }
|
||||
|
||||
// finalize() {
|
||||
// return this.#accumulator;
|
||||
// }
|
||||
// }
|
||||
|
||||
// export class ToMapCollectorFactory<TElement, TKey extends PropertyKey, TValue> implements CollectorFactory<TElement, Map<TKey, TValue>> {
|
||||
// readonly #keySelector: Converter<TElement, TKey>;
|
||||
// readonly #valueSelector: Converter<TElement, TValue>;
|
||||
|
||||
// constructor(keySelector: Converter<TElement, TKey>, valueSelector: Converter<TElement, TValue>) {
|
||||
// this.#keySelector = keySelector;
|
||||
// this.#valueSelector = valueSelector;
|
||||
// }
|
||||
|
||||
// get keySelector() {
|
||||
// return this.#keySelector;
|
||||
// }
|
||||
|
||||
// get valueSelector() {
|
||||
// return this.#valueSelector;
|
||||
// }
|
||||
|
||||
// initialize() {
|
||||
// return new ToMapCollectorInstance<TElement, TKey, TValue>(this);
|
||||
// }
|
||||
// }
|
||||
|
||||
// class ToMapCollectorInstance<TElement, TKey extends PropertyKey, TValue> implements CollectorInstance<TElement, Map<TKey, TValue>> {
|
||||
// readonly #factory: ToMapCollectorFactory<TElement, TKey, TValue>;
|
||||
// readonly #accumulator = new Map<TKey, TValue>();
|
||||
|
||||
// constructor(factory: ToMapCollectorFactory<TElement, TKey, TValue>) {
|
||||
// this.#factory = factory;
|
||||
// }
|
||||
|
||||
// accumulate(element: TElement) {
|
||||
// const key = this.#factory.keySelector(element);
|
||||
// const value = this.#factory.valueSelector(element);
|
||||
|
||||
// this.#accumulator.set(key, value);
|
||||
// }
|
||||
|
||||
// finalize() {
|
||||
// return this.#accumulator;
|
||||
// }
|
||||
// }
|
||||
|
||||
// export class ToSetCollectorFactory<TElement> implements CollectorFactory<TElement, Set<TElement>> {
|
||||
// initialize() {
|
||||
// return new ToSetCollectorInstance<TElement>();
|
||||
// }
|
||||
// }
|
||||
|
||||
// class ToSetCollectorInstance<TElement> implements CollectorInstance<TElement, Set<TElement>> {
|
||||
// readonly #accumulator = new Set<TElement>();
|
||||
|
||||
// accumulate(element: TElement) {
|
||||
// this.#accumulator.add(element);
|
||||
// }
|
||||
|
||||
// finalize() {
|
||||
// return this.#accumulator;
|
||||
// }
|
||||
// }
|
||||
|
||||
// export class JoinCollectorFactory implements CollectorFactory<any, string> {
|
||||
// readonly #delimiter: string;
|
||||
// readonly #prefix: string;
|
||||
// readonly #suffix: string;
|
||||
|
||||
// constructor(delimiter?: string, prefix?: string, suffix?: string) {
|
||||
// this.#delimiter = delimiter ?? "";
|
||||
// this.#prefix = prefix ?? "";
|
||||
// this.#suffix = suffix ?? "";
|
||||
// }
|
||||
|
||||
// accumulate(element: string) {
|
||||
// this.#accumulator.push(element);
|
||||
// }
|
||||
|
||||
// finalize() {
|
||||
// return this.#prefix + this.#accumulator.join(this.#delimiter) + this.#suffix;
|
||||
// }
|
||||
// }
|
||||
|
||||
// class JoinCollectorInstance implements CollectorInstance<any, string> {
|
||||
// readonly #delimiter: string;
|
||||
// readonly #prefix: string;
|
||||
// readonly #suffix: string;
|
||||
// readonly #accumulator: any[] = [];
|
||||
|
||||
// constructor(delimiter: string, prefix: string, suffix: string) {
|
||||
// this.#delimiter = delimiter ?? "";
|
||||
// this.#prefix = prefix ?? "";
|
||||
// this.#suffix = suffix ?? "";
|
||||
// }
|
||||
|
||||
// accumulate(element: string) {
|
||||
// this.#accumulator.push(element);
|
||||
// }
|
||||
|
||||
// finalize() {
|
||||
// return this.#prefix + this.#accumulator.join(this.#delimiter) + this.#suffix;
|
||||
// }
|
||||
// }
|
||||
|
||||
// export class SumCollectorInstance implements CollectorInstance<number, number> {
|
||||
// #accumulator = 0;
|
||||
|
||||
// accumulate(element: number) {
|
||||
// this.#accumulator += element;
|
||||
// }
|
||||
|
||||
// finalize() {
|
||||
// return this.#accumulator;
|
||||
// }
|
||||
// }
|
||||
|
||||
// export class BigIntSumCollectorInstance implements CollectorInstance<bigint, bigint> {
|
||||
// #accumulator = 0n;
|
||||
|
||||
// accumulate(element: bigint) {
|
||||
// this.#accumulator += element;
|
||||
// }
|
||||
|
||||
// finalize() {
|
||||
// return this.#accumulator;
|
||||
// }
|
||||
// }
|
||||
|
||||
// export class AverageCollectorInstance implements CollectorInstance<number, number> {
|
||||
// #count = 0;
|
||||
// #sum = 0;
|
||||
|
||||
// accumulate(element: number) {
|
||||
// this.#count++;
|
||||
// this.#sum += element;
|
||||
// }
|
||||
|
||||
// finalize() {
|
||||
// return this.#count === 0 ? 0 : this.#sum / this.#count;
|
||||
// }
|
||||
// }
|
||||
|
||||
// export class BigIntAverageCollectorInstance implements CollectorInstance<bigint, bigint> {
|
||||
// #count = 0n;
|
||||
// #sum = 0n;
|
||||
|
||||
// accumulate(element: bigint) {
|
||||
// this.#count++;
|
||||
// this.#sum += element;
|
||||
// }
|
||||
|
||||
// finalize() {
|
||||
// return this.#count === 0n ? 0n : this.#sum / this.#count;
|
||||
// }
|
||||
// }
|
||||
57
src/collector/v2/index.ts
Normal file
57
src/collector/v2/index.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
// import { Converter } from "../../types.js";
|
||||
// import { ToArrayCollectorInstance, ToObjectCollectorInstance, ToMapCollectorInstance, ToSetCollectorInstance, JoinCollectorInstance, SumCollectorInstance, BigIntSumCollectorInstance, AverageCollectorInstance, BigIntAverageCollectorInstance, ToArrayCollectorFactory } from "./impl.js";
|
||||
// import { CollectorFactory } from "./types.js";
|
||||
|
||||
// const toArrayCollectorFactory = new ToArrayCollectorFactory<any>();
|
||||
|
||||
// export function toArray<TElement>(): CollectorFactory<TElement, TElement[]> {
|
||||
// return toArrayCollectorFactory;
|
||||
// }
|
||||
|
||||
// export function toObject<TElement, TKey extends PropertyKey, TValue>(keySelector: Converter<TElement, TKey>, valueSelector: Converter<TElement, TValue>): CollectorFactory<TElement, Record<TKey, TValue>> {
|
||||
// return () => toObjectCollectorFactory<TElement, TKey, TValue>(keySelector, valueSelector);
|
||||
// }
|
||||
|
||||
// export function toMap<TElement, TKey, TValue>(keySelector: Converter<TElement, TKey>, valueSelector: Converter<TElement, TValue>): CollectorFactory<TElement, Map<TKey, TValue>> {
|
||||
// return () => new ToMapCollectorInstance<TElement, TKey, TValue>(keySelector, valueSelector);
|
||||
// }
|
||||
|
||||
// export function toSet<TElement>(): CollectorFactory<TElement, Set<TElement>> {
|
||||
// return () => new ToSetCollectorInstance<TElement>();
|
||||
// }
|
||||
|
||||
// export function join(delimiter?: string, prefix?: string, suffix?: string): CollectorFactory<any, string> {
|
||||
// return () => new JoinCollectorInstance(delimiter, prefix, suffix);
|
||||
// }
|
||||
|
||||
// function sumCollectorFactory() {
|
||||
// return new SumCollectorInstance();
|
||||
// }
|
||||
|
||||
// export function sum(): CollectorFactory<number, number> {
|
||||
// return sumCollectorFactory;
|
||||
// }
|
||||
|
||||
// function bigintSumCollectorFactory() {
|
||||
// return new BigIntSumCollectorInstance();
|
||||
// }
|
||||
|
||||
// export function bigintSum(): CollectorFactory<bigint | number, bigint> {
|
||||
// return bigintSumCollectorFactory;
|
||||
// }
|
||||
|
||||
// function averageCollectorFactory() {
|
||||
// return new AverageCollectorInstance();
|
||||
// }
|
||||
|
||||
// export function average(): CollectorFactory<number, number> {
|
||||
// return averageCollectorFactory;
|
||||
// }
|
||||
|
||||
// function bigintAverageCollectorFactory() {
|
||||
// return new BigIntAverageCollectorInstance();
|
||||
// }
|
||||
|
||||
// export function bigintAverage(): CollectorFactory<bigint, bigint> {
|
||||
// return bigintAverageCollectorFactory;
|
||||
// }
|
||||
8
src/collector/v2/types.ts
Normal file
8
src/collector/v2/types.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
// export interface CollectorFactory<TElement, TResult> {
|
||||
// initialize(): CollectorInstance<TElement, TResult>;
|
||||
// }
|
||||
|
||||
// export interface CollectorInstance<TElement, TResult> {
|
||||
// accumulate(element: TElement): void;
|
||||
// finalize(): TResult;
|
||||
// }
|
||||
263
src/comparer/async.ts
Normal file
263
src/comparer/async.ts
Normal file
@@ -0,0 +1,263 @@
|
||||
import { MaybeAsyncConverter } from "../types.js";
|
||||
import { Nullable } from "../utils.js";
|
||||
import { AsyncComparer, AsyncComparison, Comparer, MaybeAsyncComparison, MaybeAsyncComparisonOrComparer } from "./types.js";
|
||||
|
||||
export function isAsyncComparer<T>(obj: any): obj is AsyncComparer<T> {
|
||||
return obj instanceof BaseAsyncComparer;
|
||||
}
|
||||
|
||||
export function asAsyncComparer<T>(comparer: MaybeAsyncComparisonOrComparer<T>): AsyncComparer<T> {
|
||||
return typeof comparer === "function" ? createAsyncComparer(comparer) : isAsyncComparer<T>(comparer) ? comparer : fromSyncComparer(comparer);
|
||||
}
|
||||
|
||||
export function fromSyncComparer<T>(comparer: Comparer<T>): AsyncComparer<T> {
|
||||
return new WrappedAsyncComparer(comparer);
|
||||
}
|
||||
|
||||
export function createAsyncComparer<T>(comparison: MaybeAsyncComparison<T>): AsyncComparer<T> {
|
||||
return new SimpleAsyncComparer(comparison);
|
||||
}
|
||||
|
||||
export function createAsyncComparerUsing<T, U>(projection: MaybeAsyncConverter<T, U>, comparison?: MaybeAsyncComparisonOrComparer<U>): AsyncComparer<T> {
|
||||
return new MappedAsyncComparer(projection, comparison);
|
||||
}
|
||||
|
||||
export function combineAsyncComparers<T>(comparers: Iterable<Nullable<MaybeAsyncComparisonOrComparer<T>>>): AsyncComparer<T> | undefined {
|
||||
let result: AsyncComparer<T> = dummyAsyncComparer;
|
||||
|
||||
for (const comparer of comparers) {
|
||||
if (!comparer) {
|
||||
continue;
|
||||
}
|
||||
|
||||
result = result.then(asAsyncComparer(comparer));
|
||||
}
|
||||
|
||||
return result === dummyAsyncComparer ? undefined : result;
|
||||
}
|
||||
|
||||
export abstract class BaseAsyncComparer<T> implements AsyncComparer<T> {
|
||||
#cachedBoundComparison: AsyncComparison<T> | undefined;
|
||||
|
||||
public abstract compare(a: T, b: T): Promise<number>;
|
||||
|
||||
public comparison(): AsyncComparison<T> {
|
||||
return this.#cachedBoundComparison ??= this.compare.bind(this);
|
||||
}
|
||||
|
||||
public reverse(): AsyncComparer<T> {
|
||||
return new ReversedAsyncComparer(this);
|
||||
}
|
||||
|
||||
public then(comparer: AsyncComparer<T>): AsyncComparer<T> {
|
||||
return new ThenAsyncComparer(this, comparer);
|
||||
}
|
||||
|
||||
public thenCompare(comparison: MaybeAsyncComparison<T>): AsyncComparer<T> {
|
||||
return this.then(createAsyncComparer(comparison));
|
||||
}
|
||||
|
||||
public thenCompareUsing<U>(projection: MaybeAsyncConverter<T, U>, comparer?: MaybeAsyncComparisonOrComparer<U>): AsyncComparer<T> {
|
||||
return this.then(createAsyncComparerUsing(projection, comparer));
|
||||
}
|
||||
|
||||
public nullAwareComparer(): AsyncComparer<Nullable<T>> {
|
||||
return new NullAwareAsyncComparer(this);
|
||||
}
|
||||
}
|
||||
|
||||
class WrappedAsyncComparer<T> extends BaseAsyncComparer<T> {
|
||||
readonly #base: Comparer<T>;
|
||||
|
||||
constructor(base: Comparer<T>) {
|
||||
super();
|
||||
|
||||
this.#base = base;
|
||||
}
|
||||
|
||||
public override async compare(a: T, b: T) {
|
||||
return this.#base.compare(a, b);
|
||||
}
|
||||
}
|
||||
|
||||
class SimpleAsyncComparer<T> extends BaseAsyncComparer<T> {
|
||||
readonly #comparison: MaybeAsyncComparison<T>;
|
||||
|
||||
public constructor(comparison: MaybeAsyncComparison<T>) {
|
||||
super();
|
||||
|
||||
this.#comparison = comparison;
|
||||
}
|
||||
|
||||
public async compare(a: T, b: T) {
|
||||
return await this.#comparison(a, b);
|
||||
}
|
||||
}
|
||||
|
||||
class MappedAsyncComparer<T, U> extends BaseAsyncComparer<T> {
|
||||
readonly #projection: MaybeAsyncConverter<T, U>;
|
||||
readonly #comparer: AsyncComparer<U>;
|
||||
|
||||
public constructor(projection: MaybeAsyncConverter<T, U>, comparer?: MaybeAsyncComparisonOrComparer<U>) {
|
||||
super();
|
||||
|
||||
this.#projection = projection;
|
||||
this.#comparer = comparer ? asAsyncComparer(comparer) : defaultAsyncComparer;
|
||||
}
|
||||
|
||||
public async compare(a: T, b: T) {
|
||||
return await this.#comparer.compare(await this.#projection(a), await this.#projection(b));
|
||||
}
|
||||
}
|
||||
|
||||
class ReversedAsyncComparer<T> extends BaseAsyncComparer<T> {
|
||||
readonly #base: AsyncComparer<T>;
|
||||
|
||||
public constructor(base: AsyncComparer<T>) {
|
||||
super();
|
||||
|
||||
this.#base = base;
|
||||
}
|
||||
|
||||
public async compare(a: T, b: T) {
|
||||
return await this.#base.compare(b, a);
|
||||
}
|
||||
|
||||
public override reverse() {
|
||||
return this.#base;
|
||||
}
|
||||
}
|
||||
|
||||
class ThenAsyncComparer<T> extends BaseAsyncComparer<T> {
|
||||
readonly #base: AsyncComparer<T>;
|
||||
readonly #comparer: AsyncComparer<T>;
|
||||
|
||||
public constructor(base: AsyncComparer<T>, comparer: AsyncComparer<T>) {
|
||||
super();
|
||||
|
||||
this.#base = base;
|
||||
this.#comparer = comparer;
|
||||
}
|
||||
|
||||
public async compare(a: T, b: T) {
|
||||
return await this.#base.compare(a, b) || await this.#comparer.compare(a, b);
|
||||
}
|
||||
}
|
||||
|
||||
const dummyAsyncComparer = new class DummyAsyncComparer extends BaseAsyncComparer<any> {
|
||||
public override async compare(_a: any, _b: any): Promise<number> {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public override then(comparer: AsyncComparer<any>): AsyncComparer<any> {
|
||||
return comparer;
|
||||
}
|
||||
|
||||
public override thenCompare(comparison: MaybeAsyncComparison<any>): AsyncComparer<any> {
|
||||
return createAsyncComparer(comparison);
|
||||
}
|
||||
|
||||
public override thenCompareUsing<U>(projection: MaybeAsyncConverter<any, U>, comparison?: MaybeAsyncComparisonOrComparer<U> | undefined): AsyncComparer<any> {
|
||||
return createAsyncComparerUsing(projection, comparison);
|
||||
}
|
||||
}
|
||||
|
||||
export const defaultAsyncComparer: AsyncComparer<any> = new class DefaultAsyncComparer extends BaseAsyncComparer<any> {
|
||||
public override async compare(a: any, b: any): Promise<number> {
|
||||
if (a === undefined) {
|
||||
if (b === undefined) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (b === undefined) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const aStr = `${a}`, bStr = `${b}`;
|
||||
|
||||
return aStr > bStr ? 1 : aStr < bStr ? -1 : 0;
|
||||
}
|
||||
};
|
||||
|
||||
export function getDefaultAsyncComparer<T>(): AsyncComparer<T> {
|
||||
return defaultAsyncComparer;
|
||||
}
|
||||
|
||||
class NullAwareAsyncComparer<T> extends BaseAsyncComparer<Nullable<T>> {
|
||||
readonly #base: AsyncComparer<T>;
|
||||
|
||||
constructor(baseComparer: AsyncComparer<T>) {
|
||||
super();
|
||||
|
||||
this.#base = baseComparer;
|
||||
}
|
||||
|
||||
public override async compare(a: Nullable<T>, b: Nullable<T>): Promise<number> {
|
||||
if (a === undefined) {
|
||||
if (b === undefined) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (b === undefined) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (a === null) {
|
||||
if (b === null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (b === null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return await this.#base.compare(a, b);
|
||||
}
|
||||
|
||||
public override nullAwareComparer(): AsyncComparer<Nullable<T>> {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
export function nullAwareComparer<T>(baseComparer: AsyncComparer<T>): AsyncComparer<Nullable<T>> {
|
||||
return new NullAwareAsyncComparer(baseComparer);
|
||||
}
|
||||
|
||||
export const stringAsyncComparer: AsyncComparer<string> = new class StringAsyncComparer extends BaseAsyncComparer<string> {
|
||||
public override async compare(a: string, b: string): Promise<number> {
|
||||
return a.localeCompare(b);
|
||||
}
|
||||
};
|
||||
|
||||
export const numberAsyncComparer: AsyncComparer<number> = new class NumberAsyncComparer extends BaseAsyncComparer<number> {
|
||||
public override async compare(a: number, b: number): Promise<number> {
|
||||
return a - b;
|
||||
}
|
||||
};
|
||||
|
||||
export const bigintAsyncComparer: AsyncComparer<bigint> = new class BigIntAsyncComparer extends BaseAsyncComparer<bigint> {
|
||||
public override async compare(a: bigint, b: bigint): Promise<number> {
|
||||
return Number(a - b);
|
||||
}
|
||||
};
|
||||
|
||||
export const booleanAsyncComparer: AsyncComparer<boolean> = new class BooleanAsyncComparer extends BaseAsyncComparer<boolean> {
|
||||
public override async compare(a: boolean, b: boolean): Promise<number> {
|
||||
return Number(a) - Number(b);
|
||||
}
|
||||
};
|
||||
|
||||
export const dateAsyncComparer: AsyncComparer<Date> = new class DateAsyncComparer extends BaseAsyncComparer<Date> {
|
||||
public override async compare(a: Date, b: Date): Promise<number> {
|
||||
return a.getTime() - b.getTime();
|
||||
}
|
||||
};
|
||||
262
src/comparer/sync.ts
Normal file
262
src/comparer/sync.ts
Normal file
@@ -0,0 +1,262 @@
|
||||
import { Converter } from "../types.js";
|
||||
import { Nullable } from "../utils.js";
|
||||
import { fromSyncComparer } from "./async.js";
|
||||
import { Comparer, ComparisonOrComparer, Comparison, AsyncComparer } from "./types.js";
|
||||
|
||||
export function isComparer<T>(obj: any): obj is Comparer<T> {
|
||||
return obj instanceof BaseComparer;
|
||||
}
|
||||
|
||||
export function asComparer<T>(comparer: ComparisonOrComparer<T>) {
|
||||
return typeof comparer === "function" ? createComparer(comparer) : comparer;
|
||||
}
|
||||
|
||||
export function asComparison<T>(comparer: ComparisonOrComparer<T>) {
|
||||
return typeof comparer === "function" ? comparer : comparer.comparison();
|
||||
}
|
||||
|
||||
export function createComparer<T = any>(comparison: Comparison<T>): Comparer<T> {
|
||||
return new SimpleComparer(comparison);
|
||||
}
|
||||
|
||||
export function createComparerUsing<T = any, U = any>(projection: Converter<T, U>, comparison?: ComparisonOrComparer<U>): Comparer<T> {
|
||||
return new MappedComparer(projection, comparison);
|
||||
}
|
||||
|
||||
export function reverseComparison<T>(comparison: Comparison<T>): Comparison<T> {
|
||||
return (a, b) => comparison(b, a);
|
||||
}
|
||||
|
||||
export function combineComparers<T>(comparers: Iterable<Nullable<ComparisonOrComparer<T>>>) {
|
||||
let result: Comparer<T> = dummyComparer;
|
||||
|
||||
for (const comparer of comparers) {
|
||||
if (!comparer) {
|
||||
continue;
|
||||
}
|
||||
|
||||
result = result.then(asComparer(comparer));
|
||||
}
|
||||
|
||||
return result === dummyComparer ? undefined : result;
|
||||
}
|
||||
|
||||
export abstract class BaseComparer<T> implements Comparer<T> {
|
||||
#cachedBoundComparison: Comparison<T> | undefined;
|
||||
|
||||
public abstract compare(a: T, b: T): number;
|
||||
|
||||
public comparison(): Comparison<T> {
|
||||
return this.#cachedBoundComparison ??= this.compare.bind(this);
|
||||
}
|
||||
|
||||
public reverse(): Comparer<T> {
|
||||
return new ReversedComparer(this);
|
||||
}
|
||||
|
||||
public then(comparer: Comparer<T>): Comparer<T> {
|
||||
return new ThenComparer(this, comparer);
|
||||
}
|
||||
|
||||
public thenCompare(comparison: Comparison<T>): Comparer<T> {
|
||||
return this.then(createComparer(comparison));
|
||||
}
|
||||
|
||||
public thenCompareUsing<U>(projection: Converter<T, U>, comparison?: ComparisonOrComparer<U>): Comparer<T> {
|
||||
return this.then(createComparerUsing(projection, comparison));
|
||||
}
|
||||
|
||||
public toAsync(): AsyncComparer<T> {
|
||||
return fromSyncComparer<T>(this);
|
||||
}
|
||||
|
||||
public nullAwareComparer(): Comparer<Nullable<T>> {
|
||||
return new NullAwareComparer(this);
|
||||
}
|
||||
}
|
||||
|
||||
const dummyComparer = new class DummyComparer extends BaseComparer<any> {
|
||||
public override compare(_a: any, _b: any): number {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public override then(comparer: Comparer<any>): Comparer<any> {
|
||||
return comparer;
|
||||
}
|
||||
|
||||
public override thenCompare(comparison: Comparison<any>): Comparer<any> {
|
||||
return createComparer(comparison);
|
||||
}
|
||||
|
||||
public override thenCompareUsing<U>(projection: Converter<any, U>, comparison?: ComparisonOrComparer<U> | undefined): Comparer<any> {
|
||||
return createComparerUsing(projection, comparison);
|
||||
}
|
||||
};
|
||||
|
||||
class SimpleComparer<T> extends BaseComparer<T> {
|
||||
readonly #comparison: Comparison<T>;
|
||||
|
||||
public constructor(comparison: Comparison<T>) {
|
||||
super();
|
||||
|
||||
this.#comparison = comparison;
|
||||
}
|
||||
|
||||
public override compare(a: T, b: T) {
|
||||
return this.#comparison(a, b);
|
||||
}
|
||||
|
||||
public override comparison() {
|
||||
return this.#comparison;
|
||||
}
|
||||
}
|
||||
|
||||
class MappedComparer<T, U> extends BaseComparer<T> {
|
||||
readonly #projection: Converter<T, U>;
|
||||
readonly #comparison: Comparer<U>;
|
||||
|
||||
public constructor(projection: Converter<T, U>, comparison?: ComparisonOrComparer<U>) {
|
||||
super();
|
||||
|
||||
this.#projection = projection;
|
||||
this.#comparison = comparison ? asComparer(comparison) : defaultComparer;
|
||||
}
|
||||
|
||||
public override compare(a: T, b: T) {
|
||||
return this.#comparison.compare(this.#projection(a), this.#projection(b));
|
||||
}
|
||||
}
|
||||
|
||||
class ReversedComparer<T> extends BaseComparer<T> {
|
||||
readonly #base: Comparer<T>;
|
||||
|
||||
public constructor(base: Comparer<T>) {
|
||||
super();
|
||||
|
||||
this.#base = base;
|
||||
}
|
||||
|
||||
public override compare(a: T, b: T): number {
|
||||
return this.#base.compare(b, a);
|
||||
}
|
||||
|
||||
public override reverse(): Comparer<T> {
|
||||
return this.#base;
|
||||
}
|
||||
}
|
||||
|
||||
class ThenComparer<T> extends BaseComparer<T> {
|
||||
readonly #base: Comparer<T>;
|
||||
readonly #comparer: Comparer<T>;
|
||||
|
||||
public constructor(base: Comparer<T>, comparer: Comparer<T>) {
|
||||
super();
|
||||
|
||||
this.#base = base;
|
||||
this.#comparer = comparer;
|
||||
}
|
||||
|
||||
public override compare(a: T, b: T) {
|
||||
return this.#base.compare(a, b) || this.#comparer.compare(a, b);
|
||||
}
|
||||
}
|
||||
|
||||
export const defaultComparer: Comparer<any> = new class DefaultComparer extends BaseComparer<any> {
|
||||
public override compare(a: any, b: any): number {
|
||||
if (a === undefined) {
|
||||
if (b === undefined) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (b === undefined) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const aStr = `${a}`, bStr = `${b}`;
|
||||
|
||||
return aStr > bStr ? 1 : aStr < bStr ? -1 : 0;
|
||||
}
|
||||
};
|
||||
|
||||
export function getDefaultComparer<T>(): Comparer<T> {
|
||||
return defaultComparer;
|
||||
}
|
||||
|
||||
class NullAwareComparer<T> extends BaseComparer<Nullable<T>> {
|
||||
readonly #base: Comparer<T>;
|
||||
|
||||
constructor(baseComparer: Comparer<T>) {
|
||||
super();
|
||||
|
||||
this.#base = baseComparer;
|
||||
}
|
||||
|
||||
public override compare(a: Nullable<T>, b: Nullable<T>): number {
|
||||
if (a === undefined) {
|
||||
if (b === undefined) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (b === undefined) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (a === null) {
|
||||
if (b === null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (b === null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return this.#base.compare(a, b);
|
||||
}
|
||||
|
||||
public override nullAwareComparer(): Comparer<Nullable<T>> {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
export function nullAwareComparer<T>(baseComparer: Comparer<T>): Comparer<Nullable<T>> {
|
||||
return new NullAwareComparer(baseComparer);
|
||||
}
|
||||
|
||||
export const stringComparer: Comparer<string> = new class StringComparer extends BaseComparer<string> {
|
||||
public override compare(a: string, b: string): number {
|
||||
return a.localeCompare(b);
|
||||
}
|
||||
};
|
||||
|
||||
export const numberComparer: Comparer<number> = new class NumberComparer extends BaseComparer<number> {
|
||||
public override compare(a: number, b: number): number {
|
||||
return a - b;
|
||||
}
|
||||
};
|
||||
|
||||
export const bigintComparer: Comparer<bigint> = new class BigIntComparer extends BaseComparer<bigint> {
|
||||
public override compare(a: bigint, b: bigint): number {
|
||||
return Number(a - b);
|
||||
}
|
||||
};
|
||||
|
||||
export const booleanComparer: Comparer<boolean> = new class BooleanComparer extends BaseComparer<boolean> {
|
||||
public override compare(a: boolean, b: boolean): number {
|
||||
return Number(a) - Number(b);
|
||||
}
|
||||
};
|
||||
|
||||
export const dateComparer: Comparer<Date> = new class DateComparer extends BaseComparer<Date> {
|
||||
public override compare(a: Date, b: Date): number {
|
||||
return a.getTime() - b.getTime();
|
||||
}
|
||||
};
|
||||
32
src/comparer/types.ts
Normal file
32
src/comparer/types.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { AsyncFunction, Converter, MaybeAsyncConverter, MaybeAsyncFunction } from "../types.js";
|
||||
import { Nullable } from "../utils.js";
|
||||
|
||||
export interface Comparer<T> {
|
||||
compare(a: T, b: T): number;
|
||||
comparison(): Comparison<T>;
|
||||
reverse(): Comparer<T>;
|
||||
then(comparer: Comparer<T>): Comparer<T>;
|
||||
thenCompare(comparison: Comparison<T>): Comparer<T>;
|
||||
thenCompareUsing<U>(projection: Converter<T, U>, comparison?: ComparisonOrComparer<U>): Comparer<T>;
|
||||
toAsync(): AsyncComparer<T>;
|
||||
nullAwareComparer(): Comparer<Nullable<T>>;
|
||||
}
|
||||
|
||||
export interface AsyncComparer<T> {
|
||||
compare(a: T, b: T): Promise<number>;
|
||||
comparison(): AsyncComparison<T>;
|
||||
reverse(): AsyncComparer<T>;
|
||||
then(comparer: AsyncComparer<T>): AsyncComparer<T>;
|
||||
thenCompare(comparison: AsyncComparison<T>): AsyncComparer<T>;
|
||||
thenCompareUsing<U>(projection: MaybeAsyncConverter<T, U>, comparison?: AsyncComparisonOrComparer<U>): AsyncComparer<T>;
|
||||
nullAwareComparer(): AsyncComparer<Nullable<T>>;
|
||||
}
|
||||
|
||||
export type Comparison<T> = (first: T, second: T) => number;
|
||||
export type ComparisonOrComparer<T> = Comparison<T> | Comparer<T>;
|
||||
|
||||
export type AsyncComparison<T> = AsyncFunction<Comparison<T>>;
|
||||
export type MaybeAsyncComparison<T> = MaybeAsyncFunction<Comparison<T>>;
|
||||
export type AsyncComparisonOrComparer<T> = AsyncComparison<T> | AsyncComparer<T>;
|
||||
export type MaybeAsyncComparisonOrComparer<T> = MaybeAsyncComparison<T> | Comparer<T> | AsyncComparer<T>;
|
||||
|
||||
217
src/equality-comparer/async.ts
Normal file
217
src/equality-comparer/async.ts
Normal file
@@ -0,0 +1,217 @@
|
||||
import { MaybeAsyncConverter } from "../types.js";
|
||||
import { Nullable } from "../utils.js";
|
||||
import { AsyncEqualityComparer, AsyncEqualityComparison, EqualityComparer, MaybeAsyncEqualityComparison, MaybeAsyncEqualityComparisonOrComparer } from "./types.js";
|
||||
|
||||
export function isAsyncEqualityComparer<T>(obj: any): obj is AsyncEqualityComparer<T> {
|
||||
return obj instanceof BaseAsyncEqualityComparer;
|
||||
}
|
||||
|
||||
export function asAsyncEqualityComparer<T>(equalityComparer: MaybeAsyncEqualityComparisonOrComparer<T>): AsyncEqualityComparer<T> {
|
||||
return typeof equalityComparer === "function" ? createAsyncEqualityComparer(equalityComparer) : isAsyncEqualityComparer<T>(equalityComparer) ? equalityComparer : fromSyncEqualityComparer(equalityComparer);
|
||||
}
|
||||
|
||||
export function fromSyncEqualityComparer<T>(equalityComparer: EqualityComparer<T>): AsyncEqualityComparer<T> {
|
||||
return new WrappedAsyncEqualityComparer(equalityComparer);
|
||||
}
|
||||
|
||||
export function createAsyncEqualityComparer<T = any>(equalityComparison: MaybeAsyncEqualityComparison<T>): AsyncEqualityComparer<T> {
|
||||
return new SimpleAsyncEqualityComparer(equalityComparison);
|
||||
}
|
||||
|
||||
export function createAsyncEqualityComparerUsing<T = any, U = any>(projection: MaybeAsyncConverter<T, U>, equalityComparison?: MaybeAsyncEqualityComparisonOrComparer<U>): AsyncEqualityComparer<T> {
|
||||
return new MappedAsyncEqualityComparer(projection, equalityComparison);
|
||||
}
|
||||
|
||||
export function combineAsyncEqualityComparers<T>(equalityComparers: Iterable<Nullable<MaybeAsyncEqualityComparisonOrComparer<T>>>) {
|
||||
let result: AsyncEqualityComparer<T> = alwaysTrueAsyncEqualityComparer;
|
||||
|
||||
for (const equalityComparer of equalityComparers) {
|
||||
if (!equalityComparer) {
|
||||
continue;
|
||||
}
|
||||
|
||||
result = result.then(asAsyncEqualityComparer(equalityComparer));
|
||||
}
|
||||
|
||||
return result === alwaysTrueAsyncEqualityComparer ? undefined : result;
|
||||
}
|
||||
|
||||
export abstract class BaseAsyncEqualityComparer<T> implements AsyncEqualityComparer<T> {
|
||||
#cachedBoundEqualityComparison: AsyncEqualityComparison<T> | undefined;
|
||||
|
||||
public abstract equals(a: T, b: T): Promise<boolean>;
|
||||
|
||||
public equalityComparison(): AsyncEqualityComparison<T> {
|
||||
return this.#cachedBoundEqualityComparison ??= this.equals.bind(this);
|
||||
}
|
||||
|
||||
public opposite(): AsyncEqualityComparer<T> {
|
||||
return new OppositeAsyncEqualityComparer(this);
|
||||
}
|
||||
|
||||
public then(equalityComparer: AsyncEqualityComparer<T>): AsyncEqualityComparer<T> {
|
||||
return new ThenAsyncEqualityComparer(this, equalityComparer);
|
||||
}
|
||||
|
||||
public thenEquals(equalityComparison: MaybeAsyncEqualityComparison<T>): AsyncEqualityComparer<T> {
|
||||
return this.then(createAsyncEqualityComparer(equalityComparison));
|
||||
}
|
||||
|
||||
public thenEqualsUsing<U>(projection: MaybeAsyncConverter<T, U>, equalityComparison?: MaybeAsyncEqualityComparisonOrComparer<U>): AsyncEqualityComparer<T> {
|
||||
return this.then(createAsyncEqualityComparerUsing(projection, equalityComparison));
|
||||
}
|
||||
}
|
||||
|
||||
class WrappedAsyncEqualityComparer<T> extends BaseAsyncEqualityComparer<T> {
|
||||
readonly #base: EqualityComparer<T>;
|
||||
|
||||
constructor(base: EqualityComparer<T>) {
|
||||
super();
|
||||
|
||||
this.#base = base;
|
||||
}
|
||||
|
||||
public override async equals(a: T, b: T) {
|
||||
return this.#base.equals(a, b);
|
||||
}
|
||||
}
|
||||
|
||||
class SimpleAsyncEqualityComparer<T> extends BaseAsyncEqualityComparer<T> {
|
||||
readonly #equalityComparison: MaybeAsyncEqualityComparison<T>;
|
||||
|
||||
public constructor(equalityComparison: MaybeAsyncEqualityComparison<T>) {
|
||||
super();
|
||||
|
||||
this.#equalityComparison = equalityComparison;
|
||||
}
|
||||
|
||||
public override async equals(a: T, b: T): Promise<boolean> {
|
||||
return await this.#equalityComparison(a, b);
|
||||
}
|
||||
}
|
||||
|
||||
class MappedAsyncEqualityComparer<T, U> extends BaseAsyncEqualityComparer<T> {
|
||||
readonly #projection: MaybeAsyncConverter<T, U>;
|
||||
readonly #equalityComparison: AsyncEqualityComparer<U>;
|
||||
|
||||
public constructor(projection: MaybeAsyncConverter<T, U>, equalityComparison?: MaybeAsyncEqualityComparisonOrComparer<U>) {
|
||||
super();
|
||||
|
||||
this.#projection = projection;
|
||||
this.#equalityComparison = equalityComparison ? asAsyncEqualityComparer(equalityComparison) : defaultAsyncEqualityComparer;
|
||||
}
|
||||
|
||||
public override async equals(a: T, b: T): Promise<boolean> {
|
||||
return await this.#equalityComparison.equals(await this.#projection(a), await this.#projection(b));
|
||||
}
|
||||
}
|
||||
|
||||
class OppositeAsyncEqualityComparer<T> extends BaseAsyncEqualityComparer<T> {
|
||||
readonly #base: AsyncEqualityComparer<T>;
|
||||
|
||||
public constructor(base: AsyncEqualityComparer<T>) {
|
||||
super();
|
||||
|
||||
this.#base = base;
|
||||
}
|
||||
|
||||
public override async equals(a: T, b: T): Promise<boolean> {
|
||||
return !(await this.#base.equals(a, b));
|
||||
}
|
||||
|
||||
public override opposite(): AsyncEqualityComparer<T> {
|
||||
return this.#base;
|
||||
}
|
||||
}
|
||||
|
||||
class ThenAsyncEqualityComparer<T> extends BaseAsyncEqualityComparer<T> {
|
||||
readonly #base: AsyncEqualityComparer<T>;
|
||||
readonly #equalityComparer: AsyncEqualityComparer<T>;
|
||||
|
||||
public constructor(base: AsyncEqualityComparer<T>, equalityComparer: AsyncEqualityComparer<T>) {
|
||||
super();
|
||||
|
||||
this.#base = base;
|
||||
this.#equalityComparer = equalityComparer;
|
||||
}
|
||||
|
||||
public override async equals(a: T, b: T) {
|
||||
return await this.#base.equals(a, b) && await this.#equalityComparer.equals(a, b);
|
||||
}
|
||||
}
|
||||
|
||||
export const alwaysAsyncFalseEqualityComparer = new class AlwaysFalseAsyncEqualityComparer extends BaseAsyncEqualityComparer<any> {
|
||||
public override async equals(_a: any, _b: any): Promise<boolean> {
|
||||
return false;
|
||||
}
|
||||
|
||||
public override opposite(): AsyncEqualityComparer<any> {
|
||||
return alwaysTrueAsyncEqualityComparer;
|
||||
}
|
||||
|
||||
public override then(_equalityComparer: AsyncEqualityComparer<any>): AsyncEqualityComparer<any> {
|
||||
return this;
|
||||
}
|
||||
|
||||
public override thenEquals(_equalityComparison: MaybeAsyncEqualityComparison<any>): AsyncEqualityComparer<any> {
|
||||
return this;
|
||||
}
|
||||
|
||||
public override thenEqualsUsing<U>(_projection: MaybeAsyncConverter<any, U>, _equalityComparison?: MaybeAsyncEqualityComparisonOrComparer<U> | undefined): AsyncEqualityComparer<any> {
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
export const alwaysTrueAsyncEqualityComparer = new class AlwaysTrueAsyncEqualityComparer extends BaseAsyncEqualityComparer<any> {
|
||||
public override async equals(_a: any, _b: any): Promise<boolean> {
|
||||
return true;
|
||||
}
|
||||
|
||||
public override opposite(): AsyncEqualityComparer<any> {
|
||||
return alwaysAsyncFalseEqualityComparer;
|
||||
}
|
||||
|
||||
public override then(equalityComparer: AsyncEqualityComparer<any>): AsyncEqualityComparer<any> {
|
||||
return equalityComparer;
|
||||
}
|
||||
|
||||
public override thenEquals(equalityComparison: MaybeAsyncEqualityComparison<any>): AsyncEqualityComparer<any> {
|
||||
return createAsyncEqualityComparer(equalityComparison);
|
||||
}
|
||||
|
||||
public override thenEqualsUsing<U>(projection: MaybeAsyncConverter<any, U>, equalityComparison?: MaybeAsyncEqualityComparisonOrComparer<U> | undefined): AsyncEqualityComparer<any> {
|
||||
return createAsyncEqualityComparerUsing(projection, equalityComparison);
|
||||
}
|
||||
};
|
||||
|
||||
export const looseAsyncEqualityComparer: AsyncEqualityComparer<any> = new class LooseAsyncEqualityComparer extends BaseAsyncEqualityComparer<any> {
|
||||
public override async equals(a: any, b: any): Promise<boolean> {
|
||||
return a == b;
|
||||
}
|
||||
};
|
||||
export const strictAsyncEqualityComparer: AsyncEqualityComparer<any> = new class StrictAsyncEqualityComparer extends BaseAsyncEqualityComparer<any> {
|
||||
public override async equals(a: any, b: any): Promise<boolean> {
|
||||
return a === b;
|
||||
}
|
||||
};
|
||||
export const sameValueAsyncEqualityComparer: AsyncEqualityComparer<any> = new class SameValueAsyncEqualityComparer extends BaseAsyncEqualityComparer<any> {
|
||||
public override async equals(a: any, b: any): Promise<boolean> {
|
||||
return Object.is(a, b);
|
||||
}
|
||||
};
|
||||
|
||||
export const defaultAsyncEqualityComparer: AsyncEqualityComparer<any> = new class DefaultAsyncEqualityComparer extends BaseAsyncEqualityComparer<any> {
|
||||
public override async equals(a: any, b: any): Promise<boolean> {
|
||||
return a === b;
|
||||
}
|
||||
};
|
||||
|
||||
export function getDefaultAsyncEqualityComparer<T>(): AsyncEqualityComparer<T> {
|
||||
return defaultAsyncEqualityComparer;
|
||||
}
|
||||
|
||||
export const dateAsyncEqualityComparer: AsyncEqualityComparer<Date> = new class DateAsyncEqualityComparer extends BaseAsyncEqualityComparer<Date> {
|
||||
public override async equals(a: Date, b: Date): Promise<boolean> {
|
||||
return a.getTime() === b.getTime();
|
||||
}
|
||||
};
|
||||
203
src/equality-comparer/sync.ts
Normal file
203
src/equality-comparer/sync.ts
Normal file
@@ -0,0 +1,203 @@
|
||||
import { Converter } from "../types.js";
|
||||
import { Nullable } from "../utils.js";
|
||||
import { EqualityComparer, EqualityComparison, EqualityComparisonOrComparer } from "./types.js";
|
||||
|
||||
export function isEqualityComparer<T>(obj: any): obj is EqualityComparer<T> {
|
||||
return obj instanceof BaseEqualityComparer;
|
||||
}
|
||||
|
||||
export function asEqualityComparer<T>(equalityComparer: EqualityComparisonOrComparer<T>): EqualityComparer<T> {
|
||||
return typeof equalityComparer === "function" ? createEqualityComparer(equalityComparer) : equalityComparer;
|
||||
}
|
||||
|
||||
export function createEqualityComparer<T = any>(equalityComparison: EqualityComparison<T>): EqualityComparer<T> {
|
||||
return new SimpleEqualityComparer(equalityComparison);
|
||||
}
|
||||
|
||||
export function createEqualityComparerUsing<T = any, U = any>(projection: Converter<T, U>, equalityComparison?: EqualityComparisonOrComparer<U>): EqualityComparer<T> {
|
||||
return new MappedEqualityComparer(projection, equalityComparison);
|
||||
}
|
||||
|
||||
export function combineEqualityComparers<T>(equalityComparers: Iterable<Nullable<EqualityComparisonOrComparer<T>>>) {
|
||||
let result: EqualityComparer<T> = alwaysTrueEqualityComparer;
|
||||
|
||||
for (const equalityComparer of equalityComparers) {
|
||||
if (!equalityComparer) {
|
||||
continue;
|
||||
}
|
||||
|
||||
result = result.then(asEqualityComparer(equalityComparer));
|
||||
}
|
||||
|
||||
return result === alwaysTrueEqualityComparer ? undefined : result;
|
||||
}
|
||||
|
||||
export abstract class BaseEqualityComparer<T> implements EqualityComparer<T> {
|
||||
#cachedBoundEqualityComparison: EqualityComparison<T> | undefined;
|
||||
|
||||
public abstract equals(a: T, b: T): boolean;
|
||||
|
||||
public equalityComparison(): EqualityComparison<T> {
|
||||
return this.#cachedBoundEqualityComparison ??= this.equals.bind(this);
|
||||
}
|
||||
|
||||
public opposite(): EqualityComparer<T> {
|
||||
return new OppositeEqualityComparer(this);
|
||||
}
|
||||
|
||||
public then(equalityComparer: EqualityComparer<T>): EqualityComparer<T> {
|
||||
return new ThenEqualityComparer(this, equalityComparer);
|
||||
}
|
||||
|
||||
public thenEquals(equalityComparison: EqualityComparison<T>): EqualityComparer<T> {
|
||||
return this.then(createEqualityComparer(equalityComparison));
|
||||
}
|
||||
|
||||
public thenEqualsUsing<U>(projection: Converter<T, U>, equalityComparison?: EqualityComparisonOrComparer<U>): EqualityComparer<T> {
|
||||
return this.then(createEqualityComparerUsing(projection, equalityComparison));
|
||||
}
|
||||
}
|
||||
|
||||
class SimpleEqualityComparer<T> extends BaseEqualityComparer<T> {
|
||||
readonly #equalityComparison: EqualityComparison<T>;
|
||||
|
||||
public constructor(equalityComparison: EqualityComparison<T>) {
|
||||
super();
|
||||
|
||||
this.#equalityComparison = equalityComparison;
|
||||
}
|
||||
|
||||
public override equals(a: T, b: T): boolean {
|
||||
return this.#equalityComparison(a, b);
|
||||
}
|
||||
|
||||
public override equalityComparison() {
|
||||
return this.#equalityComparison;
|
||||
}
|
||||
}
|
||||
|
||||
class MappedEqualityComparer<T, U> extends BaseEqualityComparer<T> {
|
||||
readonly #projection: Converter<T, U>;
|
||||
readonly #equalityComparison: EqualityComparer<U>;
|
||||
|
||||
public constructor(projection: Converter<T, U>, equalityComparison?: EqualityComparisonOrComparer<U>) {
|
||||
super();
|
||||
|
||||
this.#projection = projection;
|
||||
this.#equalityComparison = equalityComparison ? asEqualityComparer(equalityComparison) : defaultEqualityComparer;
|
||||
}
|
||||
|
||||
public override equals(a: T, b: T): boolean {
|
||||
return this.#equalityComparison.equals(this.#projection(a), this.#projection(b));
|
||||
}
|
||||
}
|
||||
|
||||
class OppositeEqualityComparer<T> extends BaseEqualityComparer<T> {
|
||||
readonly #base: EqualityComparer<T>;
|
||||
|
||||
public constructor(base: EqualityComparer<T>) {
|
||||
super();
|
||||
|
||||
this.#base = base;
|
||||
}
|
||||
|
||||
public override equals(a: T, b: T): boolean {
|
||||
return !this.#base.equals(a, b);
|
||||
}
|
||||
|
||||
public override opposite(): EqualityComparer<T> {
|
||||
return this.#base;
|
||||
}
|
||||
}
|
||||
|
||||
class ThenEqualityComparer<T> extends BaseEqualityComparer<T> {
|
||||
readonly #base: EqualityComparer<T>;
|
||||
readonly #equalityComparer: EqualityComparer<T>;
|
||||
|
||||
public constructor(base: EqualityComparer<T>, equalityComparer: EqualityComparer<T>) {
|
||||
super();
|
||||
|
||||
this.#base = base;
|
||||
this.#equalityComparer = equalityComparer;
|
||||
}
|
||||
|
||||
public override equals(a: T, b: T) {
|
||||
return this.#base.equals(a, b) && this.#equalityComparer.equals(a, b);
|
||||
}
|
||||
}
|
||||
|
||||
export const alwaysFalseEqualityComparer = new class AlwaysFalseEqualityComparer extends BaseEqualityComparer<any> {
|
||||
public override equals(_a: any, _b: any): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
public override opposite(): EqualityComparer<any> {
|
||||
return alwaysTrueEqualityComparer;
|
||||
}
|
||||
|
||||
public override then(_equalityComparer: EqualityComparer<any>): EqualityComparer<any> {
|
||||
return this;
|
||||
}
|
||||
|
||||
public override thenEquals(_equalityComparison: EqualityComparison<any>): EqualityComparer<any> {
|
||||
return this;
|
||||
}
|
||||
|
||||
public override thenEqualsUsing<U>(_projection: Converter<any, U>, _equalityComparison?: EqualityComparisonOrComparer<U> | undefined): EqualityComparer<any> {
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
export const alwaysTrueEqualityComparer = new class AlwaysTrueEqualityComparer extends BaseEqualityComparer<any> {
|
||||
public override equals(_a: any, _b: any): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
public override opposite(): EqualityComparer<any> {
|
||||
return alwaysFalseEqualityComparer;
|
||||
}
|
||||
|
||||
public override then(equalityComparer: EqualityComparer<any>): EqualityComparer<any> {
|
||||
return equalityComparer;
|
||||
}
|
||||
|
||||
public override thenEquals(equalityComparison: EqualityComparison<any>): EqualityComparer<any> {
|
||||
return createEqualityComparer(equalityComparison);
|
||||
}
|
||||
|
||||
public override thenEqualsUsing<U>(projection: Converter<any, U>, equalityComparison?: EqualityComparisonOrComparer<U> | undefined): EqualityComparer<any> {
|
||||
return createEqualityComparerUsing(projection, equalityComparison);
|
||||
}
|
||||
};
|
||||
|
||||
export const looseEqualityComparer: EqualityComparer<any> = new class LooseEqualityComparer extends BaseEqualityComparer<any> {
|
||||
public override equals(a: any, b: any): boolean {
|
||||
return a == b;
|
||||
}
|
||||
};
|
||||
export const strictEqualityComparer: EqualityComparer<any> = new class StrictEqualityComparer extends BaseEqualityComparer<any> {
|
||||
public override equals(a: any, b: any): boolean {
|
||||
return a === b;
|
||||
}
|
||||
};
|
||||
export const sameValueEqualityComparer: EqualityComparer<any> = new class SameValueEqualityComparer extends BaseEqualityComparer<any> {
|
||||
public override equals(a: any, b: any): boolean {
|
||||
return Object.is(a, b);
|
||||
}
|
||||
};
|
||||
|
||||
export const defaultEqualityComparer: EqualityComparer<any> = new class DefaultEqualityComparer extends BaseEqualityComparer<any> {
|
||||
public override equals(a: any, b: any): boolean {
|
||||
return a === b;
|
||||
}
|
||||
};
|
||||
|
||||
export function getDefaultEqualityComparer<T>(): EqualityComparer<T> {
|
||||
return defaultEqualityComparer;
|
||||
}
|
||||
|
||||
export const dateEqualityComparer: EqualityComparer<Date> = new class DateEqualityComparer extends BaseEqualityComparer<Date> {
|
||||
public override equals(a: Date, b: Date): boolean {
|
||||
return a.getTime() === b.getTime();
|
||||
}
|
||||
};
|
||||
28
src/equality-comparer/types.ts
Normal file
28
src/equality-comparer/types.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { AsyncFunction, Converter, MaybeAsyncConverter, MaybeAsyncFunction } from "../types.js";
|
||||
|
||||
export interface EqualityComparer<T> {
|
||||
equals(a: T, b: T): boolean;
|
||||
equalityComparison(): EqualityComparison<T>;
|
||||
opposite(): EqualityComparer<T>;
|
||||
then(equalityComparer: EqualityComparer<T>): EqualityComparer<T>;
|
||||
thenEquals(equalityComparison: EqualityComparison<T>): EqualityComparer<T>;
|
||||
thenEqualsUsing<U>(projection: Converter<T, U>, equalityComparison?: EqualityComparisonOrComparer<U>): EqualityComparer<T>;
|
||||
}
|
||||
|
||||
export interface AsyncEqualityComparer<T> {
|
||||
equals(a: T, b: T): Promise<boolean>;
|
||||
equalityComparison(): AsyncEqualityComparison<T>;
|
||||
opposite(): AsyncEqualityComparer<T>;
|
||||
then(equalityComparer: AsyncEqualityComparer<T>): AsyncEqualityComparer<T>;
|
||||
thenEquals(equalityComparison: AsyncEqualityComparison<T>): AsyncEqualityComparer<T>;
|
||||
thenEqualsUsing<U>(projection: MaybeAsyncConverter<T, U>, equalityComparison?: AsyncEqualityComparisonOrComparer<U>): AsyncEqualityComparer<T>;
|
||||
}
|
||||
|
||||
export type EqualityComparison<T> = (first: T, second: T) => boolean;
|
||||
export type EqualityComparisonOrComparer<T> = EqualityComparison<T> | EqualityComparer<T>;
|
||||
|
||||
export type AsyncEqualityComparison<T> = AsyncFunction<EqualityComparison<T>>;
|
||||
export type MaybeAsyncEqualityComparison<T> = MaybeAsyncFunction<EqualityComparison<T>>;
|
||||
export type AsyncEqualityComparisonOrComparer<T> = AsyncEqualityComparison<T> | AsyncEqualityComparer<T>;
|
||||
export type MaybeAsyncEqualityComparisonOrComparer<T> = MaybeAsyncEqualityComparison<T> | EqualityComparer<T> | AsyncEqualityComparer<T>;
|
||||
|
||||
@@ -1,18 +1,10 @@
|
||||
import { Equater, MaybeAsyncEquater } from "./types.js";
|
||||
import { asAsyncEqualityComparer } from "../equality-comparer/async.js";
|
||||
import { asEqualityComparer } from "../equality-comparer/sync.js";
|
||||
import { AsyncEqualityComparer, EqualityComparer, EqualityComparisonOrComparer, MaybeAsyncEqualityComparisonOrComparer } from "../equality-comparer/types.js";
|
||||
import { MaybeAsyncIterable } from "../types.js";
|
||||
import { AsyncEqualityMap, EqualityMap, EqualityMapEntry } from "./types.js";
|
||||
|
||||
export interface EqualityMap<K, V> extends Iterable<[K, V]> {
|
||||
readonly size: number;
|
||||
get(key: K): V | undefined;
|
||||
set(key: K, value: V): V | undefined;
|
||||
contains(key: K): boolean;
|
||||
remove(key: K): V | undefined;
|
||||
clear(): void;
|
||||
keys(): IterableIterator<K>;
|
||||
values(): IterableIterator<V>;
|
||||
entries(): IterableIterator<[K, V]>;
|
||||
}
|
||||
|
||||
class NativeEqualityMap<K, V> implements EqualityMap<K, V> {
|
||||
export class NativeEqualityMap<K, V> implements EqualityMap<K, V> {
|
||||
readonly #map = new Map<K, V>();
|
||||
|
||||
get size() {
|
||||
@@ -29,6 +21,12 @@ class NativeEqualityMap<K, V> implements EqualityMap<K, V> {
|
||||
return existing;
|
||||
}
|
||||
|
||||
setAll(entries: Iterable<EqualityMapEntry<K, V>>) {
|
||||
for (const [key, value] of entries) {
|
||||
this.set(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
contains(key: K) {
|
||||
return this.#map.has(key);
|
||||
}
|
||||
@@ -60,12 +58,12 @@ class NativeEqualityMap<K, V> implements EqualityMap<K, V> {
|
||||
}
|
||||
}
|
||||
|
||||
class CustomEqualityMap<K, V> implements EqualityMap<K, V> {
|
||||
readonly #list: [K, V][] = [];
|
||||
readonly #keyComparer: Equater<K>;
|
||||
export class CustomEqualityMap<K, V> implements EqualityMap<K, V> {
|
||||
readonly #list: EqualityMapEntry<K, V>[] = [];
|
||||
readonly #keyComparer: EqualityComparer<K>;
|
||||
|
||||
constructor(keyComparer: Equater<K>) {
|
||||
this.#keyComparer = keyComparer;
|
||||
constructor(keyComparer: EqualityComparisonOrComparer<K>) {
|
||||
this.#keyComparer = asEqualityComparer(keyComparer);
|
||||
}
|
||||
|
||||
get size() {
|
||||
@@ -74,7 +72,7 @@ class CustomEqualityMap<K, V> implements EqualityMap<K, V> {
|
||||
|
||||
get(key: K) {
|
||||
for (const entry of this.#list) {
|
||||
if (this.#keyComparer(key, entry[0])) {
|
||||
if (this.#keyComparer.equals(key, entry[0])) {
|
||||
return entry[1];
|
||||
}
|
||||
}
|
||||
@@ -84,7 +82,7 @@ class CustomEqualityMap<K, V> implements EqualityMap<K, V> {
|
||||
|
||||
set(key: K, value: V) {
|
||||
for (const entry of this.#list) {
|
||||
if (this.#keyComparer(key, entry[0])) {
|
||||
if (this.#keyComparer.equals(key, entry[0])) {
|
||||
const previous = entry[1];
|
||||
entry[1] = value;
|
||||
return previous;
|
||||
@@ -96,9 +94,15 @@ class CustomEqualityMap<K, V> implements EqualityMap<K, V> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
setAll(entries: Iterable<EqualityMapEntry<K, V>>) {
|
||||
for (const [key, value] of entries) {
|
||||
this.set(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
contains(key: K) {
|
||||
for (const entry of this.#list) {
|
||||
if (this.#keyComparer(key, entry[0])) {
|
||||
if (this.#keyComparer.equals(key, entry[0])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -108,7 +112,7 @@ class CustomEqualityMap<K, V> implements EqualityMap<K, V> {
|
||||
|
||||
remove(key: K) {
|
||||
for (let i = 0; i < this.#list.length; i++) {
|
||||
if (this.#keyComparer(key, this.#list[i][0])) {
|
||||
if (this.#keyComparer.equals(key, this.#list[i][0])) {
|
||||
const removed = this.#list.splice(i, 1);
|
||||
return removed[0][1];
|
||||
}
|
||||
@@ -139,28 +143,12 @@ class CustomEqualityMap<K, V> implements EqualityMap<K, V> {
|
||||
|
||||
*[Symbol.iterator]() {
|
||||
for (const entry of this.#list) {
|
||||
yield entry.slice() as [K, V]; // no entry mutation allowed!
|
||||
yield entry.slice() as EqualityMapEntry<K, V>; // no entry mutation allowed!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function createEqualityMap<K, V>(keyComparer?: Equater<K>): EqualityMap<K, V> {
|
||||
return keyComparer ? new CustomEqualityMap<K, V>(keyComparer) : new NativeEqualityMap<K, V>();
|
||||
}
|
||||
|
||||
export interface AsyncEqualityMap<K, V> extends Iterable<[K, V]> {
|
||||
readonly size: number;
|
||||
get(key: K): Promise<V | undefined>;
|
||||
set(key: K, value: V): Promise<V | undefined>;
|
||||
contains(key: K): Promise<boolean>;
|
||||
remove(key: K): Promise<V | undefined>;
|
||||
clear(): void;
|
||||
keys(): IterableIterator<K>;
|
||||
values(): IterableIterator<V>;
|
||||
entries(): IterableIterator<[K, V]>;
|
||||
}
|
||||
|
||||
class NativeAsyncEqualityMap<K, V> implements AsyncEqualityMap<K, V> {
|
||||
export class NativeAsyncEqualityMap<K, V> implements AsyncEqualityMap<K, V> {
|
||||
readonly #map = new Map<K, V>();
|
||||
|
||||
get size() {
|
||||
@@ -177,6 +165,12 @@ class NativeAsyncEqualityMap<K, V> implements AsyncEqualityMap<K, V> {
|
||||
return existing;
|
||||
}
|
||||
|
||||
async setAll(entries: MaybeAsyncIterable<EqualityMapEntry<K, V>>) {
|
||||
for await (const [key, value] of entries) {
|
||||
await this.set(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
async contains(key: K) {
|
||||
return this.#map.has(key);
|
||||
}
|
||||
@@ -208,12 +202,12 @@ class NativeAsyncEqualityMap<K, V> implements AsyncEqualityMap<K, V> {
|
||||
}
|
||||
}
|
||||
|
||||
class CustomAsyncEqualityMap<K, V> implements AsyncEqualityMap<K, V> {
|
||||
readonly #list: [K, V][] = [];
|
||||
readonly #keyComparer: MaybeAsyncEquater<K>;
|
||||
export class CustomAsyncEqualityMap<K, V> implements AsyncEqualityMap<K, V> {
|
||||
readonly #list: EqualityMapEntry<K, V>[] = [];
|
||||
readonly #keyComparer: AsyncEqualityComparer<K>;
|
||||
|
||||
constructor(keyComparer: MaybeAsyncEquater<K>) {
|
||||
this.#keyComparer = keyComparer;
|
||||
constructor(keyComparer: MaybeAsyncEqualityComparisonOrComparer<K>) {
|
||||
this.#keyComparer = asAsyncEqualityComparer(keyComparer);
|
||||
}
|
||||
|
||||
get size() {
|
||||
@@ -222,7 +216,7 @@ class CustomAsyncEqualityMap<K, V> implements AsyncEqualityMap<K, V> {
|
||||
|
||||
async get(key: K) {
|
||||
for (const entry of this.#list) {
|
||||
if (await this.#keyComparer(key, entry[0])) {
|
||||
if (await this.#keyComparer.equals(key, entry[0])) {
|
||||
return entry[1];
|
||||
}
|
||||
}
|
||||
@@ -232,7 +226,7 @@ class CustomAsyncEqualityMap<K, V> implements AsyncEqualityMap<K, V> {
|
||||
|
||||
async set(key: K, value: V) {
|
||||
for (const entry of this.#list) {
|
||||
if (await this.#keyComparer(key, entry[0])) {
|
||||
if (await this.#keyComparer.equals(key, entry[0])) {
|
||||
const previous = entry[1];
|
||||
entry[1] = value;
|
||||
return previous;
|
||||
@@ -244,9 +238,15 @@ class CustomAsyncEqualityMap<K, V> implements AsyncEqualityMap<K, V> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
async setAll(entries: MaybeAsyncIterable<EqualityMapEntry<K, V>>) {
|
||||
for await (const [key, value] of entries) {
|
||||
await this.set(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
async contains(key: K) {
|
||||
for (const entry of this.#list) {
|
||||
if (await this.#keyComparer(key, entry[0])) {
|
||||
if (await this.#keyComparer.equals(key, entry[0])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -256,7 +256,7 @@ class CustomAsyncEqualityMap<K, V> implements AsyncEqualityMap<K, V> {
|
||||
|
||||
async remove(key: K) {
|
||||
for (let i = 0; i < this.#list.length; i++) {
|
||||
if (await this.#keyComparer(key, this.#list[i][0])) {
|
||||
if (await this.#keyComparer.equals(key, this.#list[i][0])) {
|
||||
const removed = this.#list.splice(i, 1);
|
||||
return removed[0][1];
|
||||
}
|
||||
@@ -287,11 +287,7 @@ class CustomAsyncEqualityMap<K, V> implements AsyncEqualityMap<K, V> {
|
||||
|
||||
*[Symbol.iterator]() {
|
||||
for (const entry of this.#list) {
|
||||
yield entry.slice() as [K, V]; // no entry mutation allowed!
|
||||
yield entry.slice() as EqualityMapEntry<K, V>; // no entry mutation allowed!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function createAsyncEqualityMap<K, V>(keyComparer?: MaybeAsyncEquater<K>): AsyncEqualityMap<K, V> {
|
||||
return keyComparer ? new CustomAsyncEqualityMap<K, V>(keyComparer) : new NativeAsyncEqualityMap<K, V>();
|
||||
}
|
||||
11
src/equality-map/index.ts
Normal file
11
src/equality-map/index.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { EqualityComparisonOrComparer, MaybeAsyncEqualityComparisonOrComparer } from "../equality-comparer/types.js";
|
||||
import { CustomAsyncEqualityMap, CustomEqualityMap, NativeAsyncEqualityMap, NativeEqualityMap } from "./impl.js";
|
||||
import { AsyncEqualityMap, EqualityMap } from "./types.js";
|
||||
|
||||
export function createEqualityMap<K, V>(keyComparer?: EqualityComparisonOrComparer<K>): EqualityMap<K, V> {
|
||||
return keyComparer ? new CustomEqualityMap<K, V>(keyComparer) : new NativeEqualityMap<K, V>();
|
||||
}
|
||||
|
||||
export function createAsyncEqualityMap<K, V>(keyComparer?: MaybeAsyncEqualityComparisonOrComparer<K>): AsyncEqualityMap<K, V> {
|
||||
return keyComparer ? new CustomAsyncEqualityMap<K, V>(keyComparer) : new NativeAsyncEqualityMap<K, V>();
|
||||
}
|
||||
29
src/equality-map/types.ts
Normal file
29
src/equality-map/types.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { MaybeAsyncIterable } from "../types.js";
|
||||
|
||||
export type EqualityMapEntry<K, V> = [key: K, value: V];
|
||||
|
||||
export interface EqualityMap<K, V> extends Iterable<EqualityMapEntry<K, V>> {
|
||||
readonly size: number;
|
||||
get(key: K): V | undefined;
|
||||
set(key: K, value: V): V | undefined;
|
||||
setAll(entries: Iterable<EqualityMapEntry<K, V>>): void;
|
||||
contains(key: K): boolean;
|
||||
remove(key: K): V | undefined;
|
||||
clear(): void;
|
||||
keys(): IterableIterator<K>;
|
||||
values(): IterableIterator<V>;
|
||||
entries(): IterableIterator<EqualityMapEntry<K, V>>;
|
||||
}
|
||||
|
||||
export interface AsyncEqualityMap<K, V> extends Iterable<EqualityMapEntry<K, V>> {
|
||||
readonly size: number;
|
||||
get(key: K): Promise<V | undefined>;
|
||||
set(key: K, value: V): Promise<V | undefined>;
|
||||
setAll(entries: MaybeAsyncIterable<EqualityMapEntry<K, V>>): Promise<void>;
|
||||
contains(key: K): Promise<boolean>;
|
||||
remove(key: K): Promise<V | undefined>;
|
||||
clear(): void;
|
||||
keys(): IterableIterator<K>;
|
||||
values(): IterableIterator<V>;
|
||||
entries(): IterableIterator<EqualityMapEntry<K, V>>;
|
||||
}
|
||||
@@ -1,211 +0,0 @@
|
||||
import { Equater, MaybeAsyncEquater } from "./types.js";
|
||||
|
||||
export interface EqualitySet<T> extends Iterable<T> {
|
||||
readonly size: number;
|
||||
add(obj: T): boolean;
|
||||
contains(obj: T): boolean;
|
||||
remove(obj: T): boolean;
|
||||
clear(): void;
|
||||
values(): IterableIterator<T>;
|
||||
}
|
||||
|
||||
class NativeEqualitySet<T> implements EqualitySet<T> {
|
||||
readonly #set = new Set<T>();
|
||||
|
||||
get size() {
|
||||
return this.#set.size;
|
||||
}
|
||||
|
||||
add(obj: T) {
|
||||
const exists = this.contains(obj);
|
||||
this.#set.add(obj);
|
||||
return !exists;
|
||||
}
|
||||
|
||||
contains(obj: T) {
|
||||
return this.#set.has(obj);
|
||||
}
|
||||
|
||||
remove(obj: T) {
|
||||
return this.#set.delete(obj);
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.#set.clear();
|
||||
}
|
||||
|
||||
values() {
|
||||
return this.#set.values();
|
||||
}
|
||||
|
||||
[Symbol.iterator]() {
|
||||
return this.#set[Symbol.iterator]();
|
||||
}
|
||||
}
|
||||
|
||||
class CustomEqualitySet<T> implements EqualitySet<T> {
|
||||
readonly #list: T[] = [];
|
||||
readonly #equater: Equater<T>;
|
||||
|
||||
constructor(equater: Equater<T>) {
|
||||
this.#equater = equater;
|
||||
}
|
||||
|
||||
get size() {
|
||||
return this.#list.length;
|
||||
}
|
||||
|
||||
add(obj: T) {
|
||||
if (this.contains(obj)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.#list.push(obj);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
contains(obj: T) {
|
||||
for (const val of this.#list) {
|
||||
if (this.#equater(obj, val)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
remove(obj: T) {
|
||||
const length = this.#list.length;
|
||||
|
||||
for (let i = 0; i < length; i++) {
|
||||
if (this.#equater(obj, this.#list[i])) {
|
||||
this.#list.splice(i, 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.#list.length = 0;
|
||||
}
|
||||
|
||||
values() {
|
||||
return this[Symbol.iterator]();
|
||||
}
|
||||
|
||||
[Symbol.iterator]() {
|
||||
return this.#list[Symbol.iterator]();
|
||||
}
|
||||
}
|
||||
|
||||
export function createEqualitySet<T>(equater?: Equater<T>): EqualitySet<T> {
|
||||
return equater ? new CustomEqualitySet(equater) : new NativeEqualitySet<T>();
|
||||
}
|
||||
|
||||
export interface AsyncEqualitySet<T> extends Iterable<T> {
|
||||
readonly size: number;
|
||||
add(obj: T): Promise<boolean>;
|
||||
contains(obj: T): Promise<boolean>;
|
||||
remove(obj: T): Promise<boolean>;
|
||||
clear(): void;
|
||||
values(): IterableIterator<T>;
|
||||
}
|
||||
|
||||
class NativeAsyncEqualitySet<T> implements AsyncEqualitySet<T> {
|
||||
readonly #set = new Set<T>();
|
||||
|
||||
get size() {
|
||||
return this.#set.size;
|
||||
}
|
||||
|
||||
async add(obj: T) {
|
||||
const exists = await this.contains(obj);
|
||||
this.#set.add(obj);
|
||||
return !exists;
|
||||
}
|
||||
|
||||
async contains(obj: T) {
|
||||
return this.#set.has(obj);
|
||||
}
|
||||
|
||||
async remove(obj: T) {
|
||||
return this.#set.delete(obj);
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.#set.clear();
|
||||
}
|
||||
|
||||
values() {
|
||||
return this.#set.values();
|
||||
}
|
||||
|
||||
[Symbol.iterator]() {
|
||||
return this.#set[Symbol.iterator]();
|
||||
}
|
||||
}
|
||||
|
||||
class CustomAsyncEqualitySet<T> implements AsyncEqualitySet<T> {
|
||||
readonly #list: T[] = [];
|
||||
readonly #equater: MaybeAsyncEquater<T>;
|
||||
|
||||
constructor(equater: MaybeAsyncEquater<T>) {
|
||||
this.#equater = equater;
|
||||
}
|
||||
|
||||
get size() {
|
||||
return this.#list.length;
|
||||
}
|
||||
|
||||
async add(obj: T) {
|
||||
if (await this.contains(obj)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.#list.push(obj);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
async contains(obj: T) {
|
||||
for (const val of this.#list) {
|
||||
if (await this.#equater(obj, val)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
async remove(obj: T) {
|
||||
const length = this.#list.length;
|
||||
|
||||
for (let i = 0; i < length; i++) {
|
||||
if (await this.#equater(obj, this.#list[i])) {
|
||||
this.#list.splice(i, 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.#list.length = 0;
|
||||
}
|
||||
|
||||
values() {
|
||||
return this[Symbol.iterator]();
|
||||
}
|
||||
|
||||
[Symbol.iterator]() {
|
||||
return this.#list[Symbol.iterator]();
|
||||
}
|
||||
}
|
||||
|
||||
export function createAsyncEqualitySet<T>(equater?: MaybeAsyncEquater<T>): AsyncEqualitySet<T> {
|
||||
return equater ? new CustomAsyncEqualitySet(equater) : new NativeAsyncEqualitySet<T>();
|
||||
}
|
||||
237
src/equality-set/impl.ts
Normal file
237
src/equality-set/impl.ts
Normal file
@@ -0,0 +1,237 @@
|
||||
import { asAsyncEqualityComparer } from "../equality-comparer/async.js";
|
||||
import { asEqualityComparer } from "../equality-comparer/sync.js";
|
||||
import { AsyncEqualityComparer, EqualityComparer, EqualityComparisonOrComparer, MaybeAsyncEqualityComparisonOrComparer } from "../equality-comparer/types.js";
|
||||
import { MaybeAsyncIterable } from "../types.js";
|
||||
import { AsyncEqualitySet, EqualitySet } from "./types.js";
|
||||
|
||||
export class NativeEqualitySet<T> implements EqualitySet<T> {
|
||||
readonly #set = new Set<T>();
|
||||
|
||||
get size() {
|
||||
return this.#set.size;
|
||||
}
|
||||
|
||||
add(value: T) {
|
||||
const exists = this.contains(value);
|
||||
this.#set.add(value);
|
||||
return !exists;
|
||||
}
|
||||
|
||||
addAll(values: Iterable<T>) {
|
||||
let result = 0;
|
||||
|
||||
for (const value of values) {
|
||||
if (this.add(value)) {
|
||||
result++;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
contains(value: T) {
|
||||
return this.#set.has(value);
|
||||
}
|
||||
|
||||
remove(value: T) {
|
||||
return this.#set.delete(value);
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.#set.clear();
|
||||
}
|
||||
|
||||
values() {
|
||||
return this.#set.values();
|
||||
}
|
||||
|
||||
[Symbol.iterator]() {
|
||||
return this.#set[Symbol.iterator]();
|
||||
}
|
||||
}
|
||||
|
||||
export class CustomEqualitySet<T> implements EqualitySet<T> {
|
||||
readonly #list: T[] = [];
|
||||
readonly #equater: EqualityComparer<T>;
|
||||
|
||||
constructor(equater: EqualityComparisonOrComparer<T>) {
|
||||
this.#equater = asEqualityComparer(equater);
|
||||
}
|
||||
|
||||
get size() {
|
||||
return this.#list.length;
|
||||
}
|
||||
|
||||
add(value: T) {
|
||||
if (this.contains(value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.#list.push(value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
addAll(values: Iterable<T>) {
|
||||
let result = 0;
|
||||
|
||||
for (const value of values) {
|
||||
if (this.add(value)) {
|
||||
result++;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
contains(value: T) {
|
||||
for (const val of this.#list) {
|
||||
if (this.#equater.equals(value, val)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
remove(value: T) {
|
||||
const length = this.#list.length;
|
||||
|
||||
for (let i = 0; i < length; i++) {
|
||||
if (this.#equater.equals(value, this.#list[i])) {
|
||||
this.#list.splice(i, 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.#list.length = 0;
|
||||
}
|
||||
|
||||
values() {
|
||||
return this.#list.values();
|
||||
}
|
||||
|
||||
[Symbol.iterator]() {
|
||||
return this.#list[Symbol.iterator]();
|
||||
}
|
||||
}
|
||||
|
||||
export class NativeAsyncEqualitySet<T> implements AsyncEqualitySet<T> {
|
||||
readonly #set = new Set<T>();
|
||||
|
||||
get size() {
|
||||
return this.#set.size;
|
||||
}
|
||||
|
||||
async add(value: T) {
|
||||
const exists = await this.contains(value);
|
||||
this.#set.add(value);
|
||||
return !exists;
|
||||
}
|
||||
|
||||
async addAll(values: MaybeAsyncIterable<T>) {
|
||||
let result = 0;
|
||||
|
||||
for await (const value of values) {
|
||||
if (await this.add(value)) {
|
||||
result++;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
async contains(value: T) {
|
||||
return this.#set.has(value);
|
||||
}
|
||||
|
||||
async remove(value: T) {
|
||||
return this.#set.delete(value);
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.#set.clear();
|
||||
}
|
||||
|
||||
values() {
|
||||
return this.#set.values();
|
||||
}
|
||||
|
||||
[Symbol.iterator]() {
|
||||
return this.#set[Symbol.iterator]();
|
||||
}
|
||||
}
|
||||
|
||||
export class CustomAsyncEqualitySet<T> implements AsyncEqualitySet<T> {
|
||||
readonly #list: T[] = [];
|
||||
readonly #equater: AsyncEqualityComparer<T>;
|
||||
|
||||
constructor(equater: MaybeAsyncEqualityComparisonOrComparer<T>) {
|
||||
this.#equater = asAsyncEqualityComparer(equater);
|
||||
}
|
||||
|
||||
get size() {
|
||||
return this.#list.length;
|
||||
}
|
||||
|
||||
async add(value: T) {
|
||||
if (await this.contains(value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.#list.push(value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
async addAll(values: MaybeAsyncIterable<T>) {
|
||||
let result = 0;
|
||||
|
||||
for await (const value of values) {
|
||||
if (await this.add(value)) {
|
||||
result++;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
async contains(value: T) {
|
||||
for (const val of this.#list) {
|
||||
if (await this.#equater.equals(value, val)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
async remove(value: T) {
|
||||
const length = this.#list.length;
|
||||
|
||||
for (let i = 0; i < length; i++) {
|
||||
if (await this.#equater.equals(value, this.#list[i])) {
|
||||
this.#list.splice(i, 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.#list.length = 0;
|
||||
}
|
||||
|
||||
values() {
|
||||
return this[Symbol.iterator]();
|
||||
}
|
||||
|
||||
[Symbol.iterator]() {
|
||||
return this.#list[Symbol.iterator]();
|
||||
}
|
||||
}
|
||||
11
src/equality-set/index.ts
Normal file
11
src/equality-set/index.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { EqualityComparisonOrComparer, MaybeAsyncEqualityComparisonOrComparer } from "../equality-comparer/types.js";
|
||||
import { CustomAsyncEqualitySet, CustomEqualitySet, NativeAsyncEqualitySet, NativeEqualitySet } from "./impl.js";
|
||||
import { AsyncEqualitySet, EqualitySet } from "./types.js";
|
||||
|
||||
export function createEqualitySet<T>(equater?: EqualityComparisonOrComparer<T>): EqualitySet<T> {
|
||||
return equater ? new CustomEqualitySet(equater) : new NativeEqualitySet<T>();
|
||||
}
|
||||
|
||||
export function createAsyncEqualitySet<T>(equater?: MaybeAsyncEqualityComparisonOrComparer<T>): AsyncEqualitySet<T> {
|
||||
return equater ? new CustomAsyncEqualitySet(equater) : new NativeAsyncEqualitySet<T>();
|
||||
}
|
||||
21
src/equality-set/types.ts
Normal file
21
src/equality-set/types.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { MaybeAsyncIterable } from "../types.js";
|
||||
|
||||
export interface EqualitySet<T> extends Iterable<T> {
|
||||
readonly size: number;
|
||||
add(value: T): boolean;
|
||||
addAll(values: Iterable<T>): number;
|
||||
contains(value: T): boolean;
|
||||
remove(value: T): boolean;
|
||||
clear(): void;
|
||||
values(): IterableIterator<T>;
|
||||
}
|
||||
|
||||
export interface AsyncEqualitySet<T> extends Iterable<T> {
|
||||
readonly size: number;
|
||||
add(value: T): Promise<boolean>;
|
||||
addAll(values: MaybeAsyncIterable<T>): Promise<number>;
|
||||
contains(value: T): Promise<boolean>;
|
||||
remove(value: T): Promise<boolean>;
|
||||
clear(): void;
|
||||
values(): IterableIterator<T>;
|
||||
}
|
||||
18
src/index.ts
18
src/index.ts
@@ -1,7 +1,7 @@
|
||||
export { BaseSequence, DelegatedSequence } from "./sync/impl.js";
|
||||
export { BaseSequence } from "./sync/impl.js";
|
||||
export * as Sequences from "./sync/index.js";
|
||||
export * from "./sync/types.js";
|
||||
export { BaseAsyncSequence, DelegatedAsyncSequence } from "./async/impl.js";
|
||||
export { BaseAsyncSequence } from "./async/impl.js";
|
||||
export * as AsyncSequences from "./async/index.js";
|
||||
export * from "./async/types.js";
|
||||
export * as Collectors from "./collector/index.js";
|
||||
@@ -10,3 +10,17 @@ export * as BitArrays from "./bitarray/index.js";
|
||||
export * from "./bitarray/types.js";
|
||||
export * as Random from "./random/index.js";
|
||||
export * from "./random/types.js";
|
||||
export { BaseComparer } from "./comparer/sync.js";
|
||||
export * as Comparers from "./comparer/sync.js";
|
||||
export { BaseAsyncComparer } from "./comparer/async.js";
|
||||
export * as AsyncComparers from "./comparer/async.js";
|
||||
export * from "./comparer/types.js";
|
||||
export { BaseEqualityComparer } from "./equality-comparer/sync.js";
|
||||
export * as EqualityComparers from "./equality-comparer/sync.js";
|
||||
export { BaseAsyncEqualityComparer } from "./equality-comparer/async.js";
|
||||
export * as AsyncEqualityComparers from "./equality-comparer/async.js";
|
||||
export * from "./equality-comparer/types.js";
|
||||
export * as EqualityMaps from "./equality-map/index.js";
|
||||
export * from "./equality-map/types.js";
|
||||
export * as EqualitySets from "./equality-set/index.js";
|
||||
export * from "./equality-set/types.js";
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { create as createBitArray } from "../bitarray/index.js";
|
||||
import { BitArray } from "../bitarray/types.js";
|
||||
import { BitArray } from "../bitarray/index.js";
|
||||
import { asArray } from "../utils.js";
|
||||
import { AsyncRandomOptions, ElementPredicate, ElementWeight, RandomGenerator, RandomOptions } from "./types.js";
|
||||
import { AsyncRandomOptions, ElementPredicate, ElementWeight, RandomElement, RandomGenerator, RandomOptions } from "./types.js";
|
||||
|
||||
export const alwaysTrue: ElementPredicate = () => true;
|
||||
export const weightOfOne: ElementWeight = () => 1.0;
|
||||
@@ -46,9 +45,10 @@ function withDefaultOptions<T>(options: RandomOptions<T> | AsyncRandomOptions<T>
|
||||
};
|
||||
}
|
||||
|
||||
function _getRandomElement<T>(sequence: Iterable<T>, options: Required<RandomOptions<T>>) {
|
||||
function _getRandomElement<T>(sequence: Iterable<T>, options: Required<RandomOptions<T>>): RandomElement<T> {
|
||||
const { predicate, weight, random } = options;
|
||||
|
||||
let found = false;
|
||||
let result: T | undefined = undefined;
|
||||
let resultIndex = -1;
|
||||
let index = 0;
|
||||
@@ -67,22 +67,24 @@ function _getRandomElement<T>(sequence: Iterable<T>, options: Required<RandomOpt
|
||||
weightAcc += w;
|
||||
|
||||
if (random() * weightAcc < w) {
|
||||
found = true;
|
||||
result = element;
|
||||
resultIndex = currentIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return { element: result, index: resultIndex };
|
||||
return { found, element: result, index: resultIndex } as RandomElement<T>;
|
||||
}
|
||||
|
||||
export function getRandomElement<T>(sequence: Iterable<T>, options?: RandomOptions<T>) {
|
||||
return _getRandomElement(sequence, withDefaultOptions(options));
|
||||
}
|
||||
|
||||
async function _getRandomElementAsync<T>(sequence: AsyncIterable<T>, options: Required<AsyncRandomOptions<T>>) {
|
||||
async function _getRandomElementAsync<T>(sequence: AsyncIterable<T>, options: Required<AsyncRandomOptions<T>>): Promise<RandomElement<T>> {
|
||||
const { predicate, weight, random } = options;
|
||||
|
||||
let found = false;
|
||||
let result: T | undefined = undefined;
|
||||
let resultIndex = -1;
|
||||
let index = 0;
|
||||
@@ -101,13 +103,14 @@ async function _getRandomElementAsync<T>(sequence: AsyncIterable<T>, options: Re
|
||||
weightAcc += w;
|
||||
|
||||
if (random() * weightAcc < w) {
|
||||
found = true;
|
||||
result = element;
|
||||
resultIndex = currentIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return { element: result, index: resultIndex };
|
||||
return { found, element: result, index: resultIndex } as RandomElement<T>;
|
||||
}
|
||||
|
||||
export async function getRandomElementAsync<T>(sequence: AsyncIterable<T>, options?: AsyncRandomOptions<T>) {
|
||||
@@ -121,7 +124,7 @@ export class RandomPicker<T> {
|
||||
|
||||
public constructor(elements: Iterable<T>, length: number, options?: RandomOptions<T>) {
|
||||
this.#elements = elements;
|
||||
this.#flags = createBitArray(length);
|
||||
this.#flags = BitArray.create(length);
|
||||
this.#options = withDefaultOptions(mergeOptions({ predicate: i => this.#flags.get(i) }, options));
|
||||
|
||||
this.reset();
|
||||
|
||||
@@ -4,7 +4,7 @@ export type ElementPredicate<T = any> = (index: number, obj: T) => boolean;
|
||||
export type ElementWeight<T = any> = (index: number, obj: T) => number;
|
||||
export type RandomGenerator = () => number;
|
||||
|
||||
export interface RandomOptions<T = any> {
|
||||
export type RandomOptions<T = any> = {
|
||||
predicate?: ElementPredicate<T>;
|
||||
weight?: ElementWeight<T>;
|
||||
random?: RandomGenerator;
|
||||
@@ -13,8 +13,20 @@ export interface RandomOptions<T = any> {
|
||||
export type MaybeAsyncElementPredicate<T = any> = MaybeAsyncFunction<ElementPredicate<T>>;
|
||||
export type MaybeAsyncElementWeight<T = any> = MaybeAsyncFunction<ElementWeight<T>>;
|
||||
|
||||
export interface AsyncRandomOptions<T = any> {
|
||||
export type AsyncRandomOptions<T = any> = {
|
||||
predicate?: MaybeAsyncElementPredicate<T>;
|
||||
weight?: MaybeAsyncElementWeight<T>;
|
||||
random?: RandomGenerator;
|
||||
};
|
||||
|
||||
type RandomElementFound<T> = {
|
||||
found: true;
|
||||
element: T;
|
||||
index: number;
|
||||
};
|
||||
type RandomElementNotFound = {
|
||||
found: false;
|
||||
element: undefined;
|
||||
index: -1;
|
||||
};
|
||||
export type RandomElement<T> = RandomElementFound<T> | RandomElementNotFound;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { MaybeAsyncComparer } from "./types.js";
|
||||
import { reverseAsyncComparer } from "./utils.js";
|
||||
import { asAsyncComparer } from "./comparer/async.js";
|
||||
import { MaybeAsyncComparisonOrComparer, AsyncComparer } from "./comparer/types.js";
|
||||
|
||||
export interface AsyncSorter {
|
||||
sort<T>(array: T[], descending: boolean, comparer: MaybeAsyncComparer<T>): Promise<void>;
|
||||
sort<T>(array: T[], descending: boolean, comparer: MaybeAsyncComparisonOrComparer<T>): Promise<void>;
|
||||
}
|
||||
|
||||
function swap(array: any[], i: number, j: number) {
|
||||
@@ -12,20 +12,26 @@ function swap(array: any[], i: number, j: number) {
|
||||
}
|
||||
|
||||
abstract class BaseAsyncSorter implements AsyncSorter {
|
||||
async sort<T>(array: T[], descending: boolean, comparer: MaybeAsyncComparer<T>) {
|
||||
await this._sort(array, descending ? reverseAsyncComparer(comparer) : comparer);
|
||||
async sort<T>(array: T[], descending: boolean, comparer: MaybeAsyncComparisonOrComparer<T>) {
|
||||
comparer = asAsyncComparer(comparer);
|
||||
|
||||
if (descending) {
|
||||
comparer = comparer.reverse();
|
||||
}
|
||||
|
||||
await this._sort(array, comparer);
|
||||
}
|
||||
|
||||
protected abstract _sort<T>(array: T[], comparer: MaybeAsyncComparer<T>): Promise<void>;
|
||||
protected abstract _sort<T>(array: T[], comparer: AsyncComparer<T>): Promise<void>;
|
||||
}
|
||||
|
||||
class InsertionSorter extends BaseAsyncSorter {
|
||||
protected override async _sort<T>(array: T[], comparer: MaybeAsyncComparer<T>) {
|
||||
export const insertionSorter: AsyncSorter = new class InsertionSorter extends BaseAsyncSorter {
|
||||
protected override async _sort<T>(array: T[], comparer: AsyncComparer<T>) {
|
||||
for (let i = 1; i < array.length; i++) {
|
||||
const obj = array[i];
|
||||
|
||||
for (let j = i - 1; j >= 0; j--) {
|
||||
if (await comparer(obj, array[j]) < 0) {
|
||||
if (await comparer.compare(obj, array[j]) < 0) {
|
||||
for (let k = i; k > j; k--) {
|
||||
swap(array, k - 1, k);
|
||||
}
|
||||
@@ -35,10 +41,10 @@ class InsertionSorter extends BaseAsyncSorter {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class SelectionSorter extends BaseAsyncSorter {
|
||||
protected async _sort<T>(array: T[], comparer: MaybeAsyncComparer<T>) {
|
||||
export const selectionSorter: AsyncSorter = new class SelectionSorter extends BaseAsyncSorter {
|
||||
protected async _sort<T>(array: T[], comparer: AsyncComparer<T>) {
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
let smallest = array[i];
|
||||
let smallestIndex = i;
|
||||
@@ -46,7 +52,7 @@ class SelectionSorter extends BaseAsyncSorter {
|
||||
for (let j = i; j < array.length; j++) {
|
||||
const current = array[j];
|
||||
|
||||
if (await comparer(current, smallest) < 0) {
|
||||
if (await comparer.compare(current, smallest) < 0) {
|
||||
smallest = current;
|
||||
smallestIndex = j;
|
||||
}
|
||||
@@ -57,10 +63,10 @@ class SelectionSorter extends BaseAsyncSorter {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class BubbleSorter extends BaseAsyncSorter {
|
||||
protected async _sort<T>(array: T[], comparer: MaybeAsyncComparer<T>) {
|
||||
export const bubbleSorter: AsyncSorter = new class BubbleSorter extends BaseAsyncSorter {
|
||||
protected async _sort<T>(array: T[], comparer: AsyncComparer<T>) {
|
||||
const length = array.length;
|
||||
|
||||
for (let k = length - 2; k >= 0; k--) {
|
||||
@@ -70,7 +76,7 @@ class BubbleSorter extends BaseAsyncSorter {
|
||||
const j = i + 1;
|
||||
const a = array[i], b = array[j];
|
||||
|
||||
if (await comparer(a, b) > 0) {
|
||||
if (await comparer.compare(a, b) > 0) {
|
||||
swap(array, i, j);
|
||||
hasSwaped = true;
|
||||
}
|
||||
@@ -81,8 +87,4 @@ class BubbleSorter extends BaseAsyncSorter {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const insertionSorter: AsyncSorter = new InsertionSorter();
|
||||
export const selectionSorter: AsyncSorter = new SelectionSorter();
|
||||
export const bubbleSorter: AsyncSorter = new BubbleSorter();
|
||||
};
|
||||
|
||||
859
src/sync/impl.ts
859
src/sync/impl.ts
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
import { mathRandom } from "../random/index.js";
|
||||
import { RandomGenerator } from "../random/types.js";
|
||||
import { BigIntRangeSequence, ConcatSequence, SequenceMarker, FunctionSequence, GeneratorSequence, RangeSequence, RepeatSequence, RepeatForeverSequence, WrappedArrayLike, WrappedIterable, WrappedMap, WrappedObject, WrappedSet, WrappedReadonlyArray, EMPTY } from "./impl.js";
|
||||
import { BigIntRangeSequence, ConcatSequence, SequenceMarker, FunctionSequence, GeneratorSequence, RangeSequence, RepeatSequence, RepeatForeverSequence, WrappedArrayLike, WrappedIterable, WrappedMap, WrappedObject, WrappedSet, WrappedArray, EMPTY, ZippedSequence } from "./impl.js";
|
||||
import { Sequence } from "./types.js";
|
||||
|
||||
export function wrap<T = any>(iterable: Iterable<T>): Sequence<T> {
|
||||
@@ -9,7 +9,7 @@ export function wrap<T = any>(iterable: Iterable<T>): Sequence<T> {
|
||||
}
|
||||
|
||||
if (Array.isArray(iterable)) {
|
||||
return array(iterable);
|
||||
return array<T>(iterable);
|
||||
}
|
||||
|
||||
if (iterable instanceof Set) {
|
||||
@@ -20,7 +20,7 @@ export function wrap<T = any>(iterable: Iterable<T>): Sequence<T> {
|
||||
return map(iterable) as unknown as Sequence<T>;
|
||||
}
|
||||
|
||||
return sequence(iterable);
|
||||
return sequence<T>(iterable);
|
||||
}
|
||||
|
||||
export function sequence<T = any>(iterable: Iterable<T>): Sequence<T> {
|
||||
@@ -36,7 +36,7 @@ export function single<T>(obj: T): Sequence<T> {
|
||||
}
|
||||
|
||||
export function array<T = any>(array: ReadonlyArray<T>): Sequence<T> {
|
||||
return new WrappedReadonlyArray(array);
|
||||
return new WrappedArray(array);
|
||||
}
|
||||
|
||||
export function arrayLike<T = any>(arrayLike: ArrayLike<T>): Sequence<T> {
|
||||
@@ -62,10 +62,6 @@ export function of<T>(...elements: T[]): Sequence<T> {
|
||||
}
|
||||
}
|
||||
|
||||
export function ofPropertyKeys<T extends PropertyKey>(...elements: T[]): Sequence<T> {
|
||||
return of(...elements);
|
||||
}
|
||||
|
||||
export function entries<T>(o: Record<string, T> | ArrayLike<T>): Sequence<[string, T]> {
|
||||
return array(Object.entries(o));
|
||||
}
|
||||
@@ -74,6 +70,12 @@ export function keys(o: object): Sequence<string> {
|
||||
return array(Object.keys(o));
|
||||
}
|
||||
|
||||
export function values(o: object): Sequence<any>;
|
||||
export function values<T>(o: Record<any, T> | ArrayLike<T>): Sequence<T>;
|
||||
export function values(o: object) {
|
||||
return array(Object.values(o));
|
||||
}
|
||||
|
||||
export function func<T>(f: () => T): Sequence<T> {
|
||||
return new FunctionSequence(f);
|
||||
}
|
||||
@@ -82,9 +84,9 @@ export function generator<T>(generator: () => Iterable<T>): Sequence<T> {
|
||||
return new GeneratorSequence(generator);
|
||||
}
|
||||
|
||||
export function range(max: number): Sequence<number>
|
||||
export function range(min: number, max: number): Sequence<number>
|
||||
export function range(min: number, max: number, step: number): Sequence<number>
|
||||
export function range(max: number): Sequence<number>;
|
||||
export function range(min: number, max: number): Sequence<number>;
|
||||
export function range(min: number, max: number, step: number): Sequence<number>;
|
||||
export function range(a: number, b?: number, c?: number): Sequence<number> {
|
||||
if (b === undefined) {
|
||||
b = a;
|
||||
@@ -98,9 +100,9 @@ export function range(a: number, b?: number, c?: number): Sequence<number> {
|
||||
return new RangeSequence(a, b, c);
|
||||
}
|
||||
|
||||
export function bigintRange(max: bigint): Sequence<bigint>
|
||||
export function bigintRange(min: bigint, max: bigint): Sequence<bigint>
|
||||
export function bigintRange(min: bigint, max: bigint, step: bigint): Sequence<bigint>
|
||||
export function bigintRange(max: bigint): Sequence<bigint>;
|
||||
export function bigintRange(min: bigint, max: bigint): Sequence<bigint>;
|
||||
export function bigintRange(min: bigint, max: bigint, step: bigint): Sequence<bigint>;
|
||||
export function bigintRange(a: bigint, b?: bigint, c?: bigint): Sequence<bigint> {
|
||||
if (b === undefined) {
|
||||
b = a;
|
||||
@@ -138,8 +140,12 @@ export function randomSequence(random?: RandomGenerator): Sequence<number> {
|
||||
return new FunctionSequence(random ?? mathRandom);
|
||||
}
|
||||
|
||||
export function concat<T>(...sequences: Sequence<T>[]): Sequence<T> {
|
||||
return new ConcatSequence(sequences);
|
||||
export function concat<T>(...sequences: Iterable<T>[]): Sequence<T> {
|
||||
return new ConcatSequence(sequences.map(wrap));
|
||||
}
|
||||
|
||||
export function zip<T>(first: Sequence<T>, second: Sequence<T>): Sequence<[T, T]> {
|
||||
return new ZippedSequence(first, second);
|
||||
}
|
||||
|
||||
export function isSequence<T = any>(obj: any): obj is Sequence<T> {
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import { AsyncSequence } from "../async/types.js";
|
||||
import { Collector } from "../collector/types.js";
|
||||
import { ComparisonOrComparer, Comparer } from "../comparer/types.js";
|
||||
import { EqualityComparisonOrComparer } from "../equality-comparer/types.js";
|
||||
import { RandomOptions } from "../random/types.js";
|
||||
import { AnyPredicate, Converter, FilterPredicate, Equater, BiConverter, Accumulator, Comparer, Action } from "../types.js";
|
||||
import { AnyPredicate, Converter, TypePredicate, BiConverter, Accumulator, Action } from "../types.js";
|
||||
|
||||
export type SequencePipeline<TElement, TResult> = (sequence: Sequence<TElement>) => TResult;
|
||||
export type SequenceElement<TSequence extends Sequence<any>> = TSequence extends Sequence<infer TElement> ? TElement : never;
|
||||
|
||||
export interface Sequence<TElement> extends Iterable<TElement> {
|
||||
iterator(): Iterator<TElement>;
|
||||
@@ -18,31 +21,31 @@ export interface Sequence<TElement> extends Iterable<TElement> {
|
||||
maxCount(): number;
|
||||
|
||||
select<TResult>(selector: Converter<TElement, TResult>): Sequence<TResult>;
|
||||
selectMany<TResult>(selector: Converter<TElement, Sequence<TResult>>): Sequence<TResult>;
|
||||
selectMany<TResult>(selector: Converter<TElement, Iterable<TResult>>): Sequence<TResult>;
|
||||
|
||||
where<TFiltered extends TElement>(predicate: FilterPredicate<TElement, TFiltered>): Sequence<TFiltered>;
|
||||
where<TFiltered extends TElement>(predicate: TypePredicate<TElement, TFiltered>): Sequence<TFiltered>;
|
||||
where(predicate: AnyPredicate<TElement>): Sequence<TElement>;
|
||||
|
||||
groupBy<TKey>(keySelector: Converter<TElement, TKey>, elementSelector?: undefined, keyComparer?: Equater<TKey>): Sequence<GroupedSequence<TKey, TElement>>;
|
||||
groupBy<TKey, TResult>(keySelector: Converter<TElement, TKey>, elementSelector: Converter<TElement, TResult>, keyComparer?: Equater<TKey>): Sequence<GroupedSequence<TKey, TResult>>;
|
||||
groupBy<TKey>(keySelector: Converter<TElement, TKey>, elementSelector?: undefined, keyComparer?: EqualityComparisonOrComparer<TKey>): Sequence<GroupedSequence<TKey, TElement>>;
|
||||
groupBy<TKey, TResult>(keySelector: Converter<TElement, TKey>, elementSelector: Converter<TElement, TResult>, keyComparer?: EqualityComparisonOrComparer<TKey>): Sequence<GroupedSequence<TKey, TResult>>;
|
||||
|
||||
join<TOther, TKey>(sequence: Sequence<TOther>, firstKeySelector: Converter<TElement, TKey>, secondKeySelector: Converter<TOther, TKey>, resultSelector?: undefined, keyComparer?: Equater<TKey>): Sequence<[TElement, TOther]>;
|
||||
join<TOther, TKey, TResult>(sequence: Sequence<TOther>, firstKeySelector: Converter<TElement, TKey>, secondKeySelector: Converter<TOther, TKey>, resultSelector: BiConverter<TElement, TOther, TResult>, keyComparer?: Equater<TKey>): Sequence<TResult>;
|
||||
join<TOther, TKey>(sequence: Iterable<TOther>, firstKeySelector: Converter<TElement, TKey>, secondKeySelector: Converter<TOther, TKey>, resultSelector?: undefined, keyComparer?: EqualityComparisonOrComparer<TKey>): Sequence<[TElement, TOther]>;
|
||||
join<TOther, TKey, TResult>(sequence: Iterable<TOther>, firstKeySelector: Converter<TElement, TKey>, secondKeySelector: Converter<TOther, TKey>, resultSelector: BiConverter<TElement, TOther, TResult>, keyComparer?: EqualityComparisonOrComparer<TKey>): Sequence<TResult>;
|
||||
|
||||
groupJoin<TOther, TKey>(sequence: Sequence<TOther>, firstKeySelector: Converter<TElement, TKey>, secondKeySelector: Converter<TOther, TKey>, resultSelector?: undefined, keyComparer?: Equater<TKey>): Sequence<GroupedSequence<TElement, TOther>>;
|
||||
groupJoin<TOther, TKey, TResult>(sequence: Sequence<TOther>, firstKeySelector: Converter<TElement, TKey>, secondKeySelector: Converter<TOther, TKey>, resultSelector: BiConverter<TElement, Sequence<TOther>, TResult>, keyComparer?: Equater<TKey>): Sequence<TResult>;
|
||||
groupJoin<TOther, TKey>(sequence: Iterable<TOther>, firstKeySelector: Converter<TElement, TKey>, secondKeySelector: Converter<TOther, TKey>, resultSelector?: undefined, keyComparer?: EqualityComparisonOrComparer<TKey>): Sequence<GroupedSequence<TElement, TOther>>;
|
||||
groupJoin<TOther, TKey, TResult>(sequence: Iterable<TOther>, firstKeySelector: Converter<TElement, TKey>, secondKeySelector: Converter<TOther, TKey>, resultSelector: BiConverter<TElement, Iterable<TOther>, TResult>, keyComparer?: EqualityComparisonOrComparer<TKey>): Sequence<TResult>;
|
||||
|
||||
contains(obj: TElement, equater?: Equater<TElement>): boolean;
|
||||
contains(obj: TElement, equater?: EqualityComparisonOrComparer<TElement>): boolean;
|
||||
|
||||
sequenceEquals(sequence: Sequence<TElement>, equater?: Equater<TElement>): boolean;
|
||||
sequenceEquals(sequence: Iterable<TElement>, equater?: EqualityComparisonOrComparer<TElement>): boolean;
|
||||
|
||||
append(obj: TElement): Sequence<TElement>;
|
||||
|
||||
prepend(obj: TElement): Sequence<TElement>;
|
||||
|
||||
remove(obj: TElement, all?: boolean, equater?: Equater<TElement>): Sequence<TElement>;
|
||||
remove(obj: TElement, all?: boolean, equater?: EqualityComparisonOrComparer<TElement>): Sequence<TElement>;
|
||||
|
||||
concat(...sequences: Sequence<TElement>[]): Sequence<TElement>;
|
||||
concat(...sequences: Iterable<TElement>[]): Sequence<TElement>;
|
||||
|
||||
first(predicate?: AnyPredicate<TElement>): TElement;
|
||||
firstOrDefault(predicate?: AnyPredicate<TElement>, def?: TElement): TElement | undefined;
|
||||
@@ -60,32 +63,35 @@ export interface Sequence<TElement> extends Iterable<TElement> {
|
||||
aggregate<TAccumulator>(accumulator: Accumulator<TElement, TAccumulator>, seed?: TAccumulator): TAccumulator;
|
||||
aggregate<TAccumulator, TResult>(accumulator: Accumulator<TElement, TAccumulator>, seed?: TAccumulator, resultSelector?: Converter<TAccumulator, TResult>): TResult;
|
||||
|
||||
min(comparer?: Comparer<TElement>): TElement;
|
||||
minBy<TBy>(selector: Converter<TElement, TBy>, comparer?: Comparer<TBy>): TElement;
|
||||
min(comparer?: ComparisonOrComparer<TElement>): TElement;
|
||||
minBy<TBy>(selector: Converter<TElement, TBy>, comparer?: ComparisonOrComparer<TBy>): TElement;
|
||||
|
||||
max(comparer?: Comparer<TElement>): TElement;
|
||||
maxBy<TBy>(selector: Converter<TElement, TBy>, comparer?: Comparer<TBy>): TElement;
|
||||
max(comparer?: ComparisonOrComparer<TElement>): TElement;
|
||||
maxBy<TBy>(selector: Converter<TElement, TBy>, comparer?: ComparisonOrComparer<TBy>): TElement;
|
||||
|
||||
order(comparer?: Comparer<TElement>): OrderedSequence<TElement>;
|
||||
orderBy<TBy>(selector: Converter<TElement, TBy>, comparer?: Comparer<TBy>): OrderedSequence<TElement>;
|
||||
bounds(comparer?: ComparisonOrComparer<TElement>): [min: TElement, max: TElement];
|
||||
boundsBy<TBy>(selector: Converter<TElement, TBy>, comparer?: ComparisonOrComparer<TBy>): [min: TElement, max: TElement];
|
||||
|
||||
orderDescending(comparer?: Comparer<TElement>): OrderedSequence<TElement>;
|
||||
orderByDescending<TBy>(selector: Converter<TElement, TBy>, comparer?: Comparer<TBy>): OrderedSequence<TElement>;
|
||||
order(comparer?: ComparisonOrComparer<TElement>): OrderedSequence<TElement>;
|
||||
orderBy<TBy>(selector: Converter<TElement, TBy>, comparer?: ComparisonOrComparer<TBy>): OrderedSequence<TElement>;
|
||||
|
||||
partition(equater?: Equater<TElement>): Sequence<Sequence<TElement>>;
|
||||
partitionBy<TBy>(selector: Converter<TElement, TBy>, equater?: Equater<TBy>): Sequence<Sequence<TElement>>;
|
||||
orderDescending(comparer?: ComparisonOrComparer<TElement>): OrderedSequence<TElement>;
|
||||
orderByDescending<TBy>(selector: Converter<TElement, TBy>, comparer?: ComparisonOrComparer<TBy>): OrderedSequence<TElement>;
|
||||
|
||||
distinct(equater?: Equater<TElement>): Sequence<TElement>;
|
||||
distinctBy<TBy>(selector: Converter<TElement, TBy>, equater?: Equater<TBy>): Sequence<TElement>;
|
||||
partition(equater?: EqualityComparisonOrComparer<TElement>): Sequence<Sequence<TElement>>;
|
||||
partitionBy<TBy>(selector: Converter<TElement, TBy>, equater?: EqualityComparisonOrComparer<TBy>): Sequence<Sequence<TElement>>;
|
||||
|
||||
union(sequence: Sequence<TElement>, equater?: Equater<TElement>): Sequence<TElement>;
|
||||
unionBy<TBy>(sequence: Sequence<TElement>, selector: Converter<TElement, TBy>, equater?: Equater<TBy>): Sequence<TElement>;
|
||||
distinct(equater?: EqualityComparisonOrComparer<TElement>): Sequence<TElement>;
|
||||
distinctBy<TBy>(selector: Converter<TElement, TBy>, equater?: EqualityComparisonOrComparer<TBy>): Sequence<TElement>;
|
||||
|
||||
except(sequence: Sequence<TElement>, equater?: Equater<TElement>): Sequence<TElement>;
|
||||
exceptBy<TBy>(sequence: Sequence<TElement>, selector: Converter<TElement, TBy>, equater?: Equater<TBy>): Sequence<TElement>;
|
||||
union(sequence: Iterable<TElement>, equater?: EqualityComparisonOrComparer<TElement>): Sequence<TElement>;
|
||||
unionBy<TBy>(sequence: Iterable<TElement>, selector: Converter<TElement, TBy>, equater?: EqualityComparisonOrComparer<TBy>): Sequence<TElement>;
|
||||
|
||||
intersect(sequence: Sequence<TElement>, equater?: Equater<TElement>): Sequence<TElement>;
|
||||
intersectBy<TBy>(sequence: Sequence<TElement>, selector: Converter<TElement, TBy>, equater?: Equater<TBy>): Sequence<TElement>;
|
||||
except(sequence: Iterable<TElement>, equater?: EqualityComparisonOrComparer<TElement>): Sequence<TElement>;
|
||||
exceptBy<TBy>(sequence: Iterable<TElement>, selector: Converter<TElement, TBy>, equater?: EqualityComparisonOrComparer<TBy>): Sequence<TElement>;
|
||||
|
||||
intersect(sequence: Iterable<TElement>, equater?: EqualityComparisonOrComparer<TElement>): Sequence<TElement>;
|
||||
intersectBy<TBy>(sequence: Iterable<TElement>, selector: Converter<TElement, TBy>, equater?: EqualityComparisonOrComparer<TBy>): Sequence<TElement>;
|
||||
|
||||
all(predicate: AnyPredicate<TElement>): boolean;
|
||||
any(predicate: AnyPredicate<TElement>): boolean;
|
||||
@@ -105,14 +111,16 @@ export interface Sequence<TElement> extends Iterable<TElement> {
|
||||
|
||||
forEach(action: Action<TElement>): void;
|
||||
|
||||
zip<TOther>(sequence: Sequence<TOther>): Sequence<[TElement, TOther]>;
|
||||
zip<TOther>(sequence: Iterable<TOther>): Sequence<[TElement, TOther]>;
|
||||
cartesianProduct<TOther>(sequence: Iterable<TOther>): Sequence<[TElement, TOther]>;
|
||||
|
||||
indexed(): Sequence<[number, TElement]>;
|
||||
|
||||
reversed(): Sequence<TElement>;
|
||||
|
||||
chunked(size: number, asArray?: false): Sequence<Sequence<TElement>>;
|
||||
chunked(size: number): Sequence<Sequence<TElement>>;
|
||||
chunked(size: number, asArray: true): Sequence<TElement[]>;
|
||||
chunked<TResult>(size: number, transformer: SequencePipeline<TElement, TResult>): Sequence<TResult>;
|
||||
|
||||
random(options?: RandomOptions<TElement>): TElement | undefined;
|
||||
|
||||
@@ -136,13 +144,13 @@ export interface GroupedSequence<TKey, TElement> extends Sequence<TElement> {
|
||||
}
|
||||
|
||||
export interface OrderedSequence<TElement> extends Sequence<TElement> {
|
||||
get comparer(): Comparer<TElement> | undefined;
|
||||
get comparer(): Comparer<TElement>;
|
||||
|
||||
thenSelf(comparer?: Comparer<TElement>): OrderedSequence<TElement>;
|
||||
thenSelf(comparer?: ComparisonOrComparer<TElement>): OrderedSequence<TElement>;
|
||||
|
||||
thenBy<TBy>(selector: Converter<TElement, TBy>, comparer?: Comparer<TBy>): OrderedSequence<TElement>;
|
||||
thenBy<TBy>(selector: Converter<TElement, TBy>, comparer?: ComparisonOrComparer<TBy>): OrderedSequence<TElement>;
|
||||
|
||||
thenSelfDescending(comparer?: Comparer<TElement>): OrderedSequence<TElement>;
|
||||
thenSelfDescending(comparer?: ComparisonOrComparer<TElement>): OrderedSequence<TElement>;
|
||||
|
||||
thenByDescending<TBy>(selector: Converter<TElement, TBy>, comparer?: Comparer<TBy>): OrderedSequence<TElement>;
|
||||
thenByDescending<TBy>(selector: Converter<TElement, TBy>, comparer?: ComparisonOrComparer<TBy>): OrderedSequence<TElement>;
|
||||
}
|
||||
|
||||
17
src/types.ts
17
src/types.ts
@@ -1,15 +1,10 @@
|
||||
import { AsyncSequence } from "./async/types.js";
|
||||
import { Sequence } from "./sync/types.js";
|
||||
|
||||
export type Predicate<T> = (obj: T) => boolean;
|
||||
export type AnyPredicate<T> = (obj: T) => unknown;
|
||||
export type FilterPredicate<TElement, TFiltered extends TElement> = (obj: TElement) => obj is TFiltered;
|
||||
export type TypePredicate<TElement, TType extends TElement> = (obj: TElement) => obj is TType;
|
||||
export type Converter<TFrom, TTo> = (obj: TFrom) => TTo;
|
||||
export type BiConverter<TFromFirst, TFromSecond, TTo> = (first: TFromFirst, second: TFromSecond) => TTo;
|
||||
export type Action<T> = (obj: T) => void;
|
||||
export type Action<T> = (obj: T) => unknown;
|
||||
export type Accumulator<TElement, TAccumulator> = (acc: TAccumulator, obj: TElement) => TAccumulator;
|
||||
export type Comparer<T> = (first: T, second: T) => number;
|
||||
export type Equater<T> = (first: T, second: T) => boolean;
|
||||
|
||||
export type MaybeAsyncIterable<T> = Iterable<T> | AsyncIterable<T>;
|
||||
export type MaybeAsyncIterator<T> = Iterator<T> | AsyncIterator<T>;
|
||||
@@ -18,12 +13,13 @@ export type AsyncFunction<TFunc extends (...args: any) => any> = TFunc extends (
|
||||
export type MaybePromise<T> = T | Promise<T>;
|
||||
export type MaybePromiseLike<T> = T | PromiseLike<T>;
|
||||
export type MaybeAsyncFunction<TFunc extends (...args: any) => any> = TFunc extends (...args: infer P) => infer R ? (...args: P) => MaybePromise<R> : never;
|
||||
export type MaybeAsyncSequence<T> = Sequence<T> | AsyncSequence<T>;
|
||||
|
||||
export type AsyncPredicate<T> = AsyncFunction<Predicate<T>>;
|
||||
export type AsyncAnyPredicate<T> = AsyncFunction<AnyPredicate<T>>;
|
||||
export type AsyncTypePredicate<TElement, TType extends TElement> = AsyncFunction<TypePredicate<TElement, TType>>;
|
||||
export type MaybeAsyncPredicate<T> = MaybeAsyncFunction<Predicate<T>>;
|
||||
export type MaybeAsyncAnyPredicate<T> = MaybeAsyncFunction<AnyPredicate<T>>;
|
||||
export type MaybeAsyncTypePredicate<TElement, TType extends TElement> = MaybeAsyncFunction<TypePredicate<TElement, TType>>;
|
||||
export type AsyncConverter<TFrom, TTo> = AsyncFunction<Converter<TFrom, TTo>>;
|
||||
export type MaybeAsyncConverter<TFrom, TTo> = MaybeAsyncFunction<Converter<TFrom, TTo>>;
|
||||
export type AsyncBiConverter<TFromFirst, TFromSecond, TTo> = AsyncFunction<BiConverter<TFromFirst, TFromSecond, TTo>>;
|
||||
@@ -32,7 +28,4 @@ export type AsyncAction<T> = AsyncFunction<Action<T>>;
|
||||
export type MaybeAsyncAction<T> = MaybeAsyncFunction<Action<T>>;
|
||||
export type AsyncAccumulator<TElement, TAccumulator> = AsyncFunction<Accumulator<TElement, TAccumulator>>;
|
||||
export type MaybeAsyncAccumulator<T, U> = MaybeAsyncFunction<Accumulator<T, U>>;
|
||||
export type AsyncComparer<T> = AsyncFunction<Comparer<T>>;
|
||||
export type MaybeAsyncComparer<T> = MaybeAsyncFunction<Comparer<T>>;
|
||||
export type AsyncEquater<T> = AsyncFunction<Equater<T>>;
|
||||
export type MaybeAsyncEquater<T> = MaybeAsyncFunction<Equater<T>>;
|
||||
|
||||
|
||||
96
src/utils.ts
96
src/utils.ts
@@ -1,93 +1,19 @@
|
||||
import { Comparer, MaybeAsyncComparer, AsyncComparer, MaybeAsyncIterator } from "./types.js";
|
||||
export type Nullable<T> = T | null | undefined;
|
||||
|
||||
export function isDefined<T = any>(obj: T): obj is NonNullable<T> {
|
||||
return obj !== undefined && obj !== null;
|
||||
}
|
||||
|
||||
export function isIterable<T = any>(obj: any): obj is Iterable<T> {
|
||||
return isDefined(obj) && typeof obj[Symbol.iterator] === "function";
|
||||
}
|
||||
|
||||
export function isAsyncIterable<T = any>(obj: any): obj is AsyncIterable<T> {
|
||||
return isDefined(obj) && typeof obj[Symbol.asyncIterator] === "function";
|
||||
}
|
||||
|
||||
export function identity<T>(obj: T) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
export function looseEquals<T>(a: T, b: T) {
|
||||
return a == b;
|
||||
}
|
||||
|
||||
export function strictEquals<T>(a: T, b: T) {
|
||||
return a === b;
|
||||
}
|
||||
|
||||
export function referenceEquals<T>(a: T, b: T) {
|
||||
return Object.is(a, b);
|
||||
}
|
||||
|
||||
export function numberCompare<T extends number | bigint>(a: T, b: T) {
|
||||
return a - b;
|
||||
}
|
||||
|
||||
export function operatorCompare(a: any, b: any) {
|
||||
return a < b ? -1 : a > b ? 1 : 0;
|
||||
}
|
||||
|
||||
export function defaultArrayComparer<T>(a: T, b: T) {
|
||||
if (a === undefined) {
|
||||
if (b === undefined) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (b === undefined) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const aStr = `${a}`, bStr = `${b}`;
|
||||
|
||||
return aStr > bStr ? 1 : aStr < bStr ? -1 : 0;
|
||||
}
|
||||
|
||||
export function combineComparers<T>(first: Comparer<T>, second: Comparer<T>): Comparer<T> {
|
||||
return (a, b) => first(a, b) || second(a, b);
|
||||
}
|
||||
|
||||
export function combineAsyncComparers<T>(first: MaybeAsyncComparer<T>, second: MaybeAsyncComparer<T>): AsyncComparer<T> {
|
||||
return async (a, b) => await first(a, b) || await second(a, b);
|
||||
}
|
||||
|
||||
export function reverseComparer<T>(comparer: Comparer<T>): Comparer<T> {
|
||||
return (a, b) => comparer(b, a);
|
||||
}
|
||||
|
||||
export function reverseAsyncComparer<T>(comparer: MaybeAsyncComparer<T>): AsyncComparer<T> {
|
||||
return async (a, b) => await comparer(b, a);
|
||||
}
|
||||
|
||||
export function asArray<T>(iterable: Iterable<T>) {
|
||||
return Array.isArray(iterable) ? <T[]>iterable : Array.from(iterable);
|
||||
}
|
||||
|
||||
class WrappedIterator<T> implements Iterable<T> {
|
||||
readonly #iterator: Iterator<T>;
|
||||
|
||||
constructor(iterator: Iterator<T>) {
|
||||
this.#iterator = iterator;
|
||||
}
|
||||
|
||||
[Symbol.iterator]() {
|
||||
return this.#iterator;
|
||||
}
|
||||
}
|
||||
|
||||
export function asIterable<T>(iterator: Iterator<T>): Iterable<T> {
|
||||
return isIterable<T>(iterator) ? iterator : new WrappedIterator(iterator);
|
||||
export function identity<T>(obj: T) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
class WrappedAsyncIterator<T> implements AsyncIterable<T> {
|
||||
@@ -115,15 +41,25 @@ const _emptyIterableIterator = new class EmptyIterableIterator implements Iterab
|
||||
return { done: true, value: undefined };
|
||||
}
|
||||
|
||||
return(value?: any): IteratorResult<any, any> {
|
||||
return(_value?: any): IteratorResult<any, any> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
throw(e?: any): IteratorResult<any, any> {
|
||||
throw(_e?: any): IteratorResult<any, any> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export function emptyIterableIterator<T>(): IterableIterator<T> {
|
||||
return _emptyIterableIterator;
|
||||
}
|
||||
|
||||
type FindElementSuccess<T> = {
|
||||
found: true;
|
||||
element: T;
|
||||
};
|
||||
type FindElementFail = {
|
||||
found: false;
|
||||
reason?: number;
|
||||
};
|
||||
export type FindElementResult<T> = FindElementSuccess<T> | FindElementFail;
|
||||
|
||||
@@ -1,21 +1,17 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "Node16",
|
||||
"target": "ES2023",
|
||||
"moduleResolution": "Node16",
|
||||
"rootDir": "src",
|
||||
"outDir": "build",
|
||||
"outFile": "build/index.ts",
|
||||
"esModuleInterop": true,
|
||||
"module": "nodenext",
|
||||
"target": "esnext",
|
||||
"moduleResolution": "nodenext",
|
||||
"lib": [
|
||||
"ESNext"
|
||||
],
|
||||
"types": ["node"],
|
||||
"alwaysStrict": true,
|
||||
"strict": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"allowUnreachableCode": true,
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"emitDeclarationOnly": true
|
||||
"rootDir": "./src"
|
||||
},
|
||||
"include": [
|
||||
"src"
|
||||
"./src"
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user