diff --git a/.eslintrc b/.eslintrc index ca2f535..9281326 100644 --- a/.eslintrc +++ b/.eslintrc @@ -38,6 +38,7 @@ "message": "Use `globalThis` instead" } ], + "prefer-rest-params": 0, "require-yield": 0, "eqeqeq": ["error", "smart"], "spaced-comment": [ diff --git a/README.md b/README.md index 72b2307..6789029 100644 --- a/README.md +++ b/README.md @@ -471,7 +471,7 @@ npm install # build the dist npm run build # run the repl (this allows you to import from ./src) -npm run ts-node +npm run tsx # run the tests npm run test # lint the source code diff --git a/benches/index.ts b/benches/index.ts index 858f216..3cf25b3 100644 --- a/benches/index.ts +++ b/benches/index.ts @@ -2,22 +2,25 @@ import fs from 'fs'; import path from 'path'; +import url from 'url'; import si from 'systeminformation'; +const dirname = url.fileURLToPath(new URL('.', import.meta.url)); + async function main(): Promise { - await fs.promises.mkdir(path.join(__dirname, 'results'), { recursive: true }); + await fs.promises.mkdir(path.join(dirname, 'results'), { recursive: true }); const resultFilenames = await fs.promises.readdir( - path.join(__dirname, 'results'), + path.join(dirname, 'results'), ); const metricsFile = await fs.promises.open( - path.join(__dirname, 'results', 'metrics.txt'), + path.join(dirname, 'results', 'metrics.txt'), 'w', ); let concatenating = false; for (const resultFilename of resultFilenames) { if (/.+_metrics\.txt$/.test(resultFilename)) { const metricsData = await fs.promises.readFile( - path.join(__dirname, 'results', resultFilename), + path.join(dirname, 'results', resultFilename), ); if (concatenating) { await metricsFile.write('\n'); @@ -33,7 +36,7 @@ async function main(): Promise { system: 'model, manufacturer', }); await fs.promises.writeFile( - path.join(__dirname, 'results', 'system.json'), + path.join(dirname, 'results', 'system.json'), JSON.stringify(systemData, null, 2), ); } diff --git a/benches/utils/index.ts b/benches/utils/index.ts index 04bca77..9be8099 100644 --- a/benches/utils/index.ts +++ b/benches/utils/index.ts @@ -1 +1 @@ -export * from './utils'; +export * from './utils.js'; diff --git a/benches/utils/utils.ts b/benches/utils/utils.ts index 71c4d10..0e46cef 100644 --- a/benches/utils/utils.ts +++ b/benches/utils/utils.ts @@ -1,27 +1,30 @@ import fs from 'fs'; import path from 'path'; +import url from 'url'; import b from 'benny'; import { codeBlock } from 'common-tags'; import packageJson from '../../package.json'; +const dirname = url.fileURLToPath(new URL('.', import.meta.url)); + const suiteCommon = [ b.cycle(), b.complete(), b.save({ file: (summary) => summary.name, - folder: path.join(__dirname, '../results'), + folder: path.join(dirname, '../results'), version: packageJson.version, details: true, }), b.save({ file: (summary) => summary.name, - folder: path.join(__dirname, '../results'), + folder: path.join(dirname, '../results'), version: packageJson.version, format: 'chart.html', }), b.complete((summary) => { const filePath = path.join( - __dirname, + dirname, '../results', summary.name + '_metrics.txt', ); diff --git a/jest.config.js b/jest.config.mjs similarity index 78% rename from jest.config.js rename to jest.config.mjs index 58d32f3..b3e3b3f 100644 --- a/jest.config.js +++ b/jest.config.mjs @@ -1,18 +1,16 @@ -const path = require('path'); -const { pathsToModuleNameMapper } = require('ts-jest'); -const { compilerOptions } = require('./tsconfig'); +import path from 'node:path'; +import url from 'node:url'; +import tsconfigJSON from './tsconfig.json' assert { type: "json" }; -const moduleNameMapper = pathsToModuleNameMapper(compilerOptions.paths, { - prefix: '/src/', -}); +const projectPath = path.dirname(url.fileURLToPath(import.meta.url)); // Global variables that are shared across the jest worker pool // These variables must be static and serializable const globals = { // Absolute directory to the project root - projectDir: __dirname, + projectDir: projectPath, // Absolute directory to the test root - testDir: path.join(__dirname, 'tests'), + testDir: path.join(projectPath, 'tests'), // Default asynchronous test timeout defaultTimeout: 20000, // Timeouts rely on setTimeout which takes 32 bit numbers @@ -24,7 +22,7 @@ const globals = { // They can however receive the process environment // Use `process.env` to set variables -module.exports = { +const config = { testEnvironment: 'node', verbose: true, collectCoverage: false, @@ -40,10 +38,10 @@ module.exports = { parser: { syntax: "typescript", tsx: true, - decorators: compilerOptions.experimentalDecorators, + decorators: tsconfigJSON.compilerOptions.experimentalDecorators, dynamicImport: true, }, - target: compilerOptions.target.toLowerCase(), + target: tsconfigJSON.compilerOptions.target.toLowerCase(), keepClassNames: true, }, } @@ -77,5 +75,10 @@ module.exports = { 'jest-extended/all', '/tests/setupAfterEnv.ts' ], - moduleNameMapper: moduleNameMapper, + moduleNameMapper: { + "^(\\.{1,2}/.*)\\.js$": "$1", + }, + extensionsToTreatAsEsm: ['.ts', '.tsx', '.mts'], }; + +export default config; diff --git a/package-lock.json b/package-lock.json index 8d0d1c8..f3638f6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,15 +9,15 @@ "version": "0.6.4", "license": "Apache-2.0", "dependencies": { - "@matrixai/async-init": "^1.10.0", - "@matrixai/contexts": "^1.2.0", - "@matrixai/errors": "^1.2.0", - "@matrixai/events": "^3.2.3", - "@matrixai/logger": "^3.1.2", + "@matrixai/async-init": "^2.1.2", + "@matrixai/contexts": "^2.0.2", + "@matrixai/errors": "^2.1.3", + "@matrixai/events": "^4.0.1", + "@matrixai/logger": "^4.0.3", "@streamparser/json": "^0.0.17" }, "devDependencies": { - "@fast-check/jest": "^1.1.0", + "@fast-check/jest": "^2.1.0", "@swc/core": "1.3.82", "@swc/jest": "^0.2.29", "@types/jest": "^29.5.2", @@ -30,16 +30,15 @@ "eslint-config-prettier": "^8.8.0", "eslint-plugin-import": "^2.27.5", "eslint-plugin-prettier": "^5.0.0-alpha.2", - "ix": "^5.0.0", + "fast-check": "^4.0.0", "jest": "^29.6.2", "jest-extended": "^4.0.0", "jest-junit": "^16.0.0", "prettier": "^3.0.0", "shx": "^0.3.4", "systeminformation": "^5.18.5", - "ts-jest": "^29.1.1", "ts-node": "^10.9.1", - "tsconfig-paths": "^3.9.0", + "tsx": "^3.12.7", "typedoc": "^0.24.8", "typescript": "^5.1.6" } @@ -779,6 +778,380 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@esbuild/android-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", + "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", + "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", + "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", + "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", + "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", + "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", + "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", + "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", + "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", + "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", + "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", + "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", + "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", + "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", + "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", + "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", + "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", + "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", + "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", + "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", + "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", + "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -836,9 +1209,9 @@ } }, "node_modules/@fast-check/jest": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@fast-check/jest/-/jest-1.7.3.tgz", - "integrity": "sha512-6NcpYIIUnLwEdEfPhijYT5mnFPiQNP/isC+os+P+rV8qHRzUxRNx8WyPTOx+oVkBMm1+XSn00ZqfD3ANfciTZQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@fast-check/jest/-/jest-2.1.0.tgz", + "integrity": "sha512-9ZVvFnngR0EpfxWoGrq/e9ERrDv3qqE4RXVnn/mGv5Rn33LoDcIfg7xjqVREsyhGcwegEKeL0KJlrWzWiOBV8A==", "dev": true, "funding": [ { @@ -850,11 +1223,12 @@ "url": "https://opencollective.com/fast-check" } ], + "license": "MIT", "dependencies": { - "fast-check": "^3.0.0" + "fast-check": "^3.0.0 || ^4.0.0" }, "peerDependencies": { - "@fast-check/worker": "~0.0.7", + "@fast-check/worker": ">=0.0.7 <0.5.0", "@jest/expect": ">=28.0.0", "@jest/globals": ">=25.5.2" }, @@ -1394,73 +1768,82 @@ } }, "node_modules/@matrixai/async-cancellable": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@matrixai/async-cancellable/-/async-cancellable-1.1.1.tgz", - "integrity": "sha512-f0yxu7dHwvffZ++7aCm2WIcCJn18uLcOTdCCwEA3R3KVHYE3TG/JNoTWD9/mqBkAV1AI5vBfJzg27WnF9rOUXQ==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@matrixai/async-cancellable/-/async-cancellable-2.0.1.tgz", + "integrity": "sha512-4oZC7RMehzZCfyVLk33fOZpW1Nz4WFxuHzznrjFDBre6FmGb63jc2uWjwn+BKplqyby1J/sdJbjO0iqNcweWHg==", + "license": "Apache-2.0" }, "node_modules/@matrixai/async-init": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@matrixai/async-init/-/async-init-1.10.0.tgz", - "integrity": "sha512-JjUFu6rqd+dtTHFJ6z8bjbceuFGBj/APWfJByVsfbEH1DJsOgWERFcW3DBUrS0mgTph4Vl518tsNcsSwKT5Y+g==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@matrixai/async-init/-/async-init-2.1.2.tgz", + "integrity": "sha512-i8Hj9Q/FGM725/LpsUyXk2APHn6y7yV9VmPoayAMkzM54+7p9ylmyxIwpYzw1A2zslrgUUvszg++uSM4a+5REw==", + "license": "Apache-2.0", "dependencies": { - "@matrixai/async-locks": "^4.0.0", - "@matrixai/errors": "^1.2.0", - "@matrixai/events": "^3.2.0" + "@matrixai/async-locks": "^5.0.1", + "@matrixai/errors": "^2.1.0", + "@matrixai/events": "^4.0.0" } }, "node_modules/@matrixai/async-locks": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@matrixai/async-locks/-/async-locks-4.0.0.tgz", - "integrity": "sha512-u/3fOdtjOKcDYF8dDoPR1/+7nmOkhxo42eBpXTEgfI0hLPGI37PoW7tjLvwy+O51Quy1HGOwhsR/Dgr4x+euug==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@matrixai/async-locks/-/async-locks-5.0.2.tgz", + "integrity": "sha512-YX3LUt4okyXPnDpx78PgPQybn8duh/FvWKx0t3UTaJW/0HL0/ZOQEEOsX1qefV1fQps1nKUHfjK1VeqZciCvXQ==", + "license": "Apache-2.0", "dependencies": { - "@matrixai/async-cancellable": "^1.1.1", - "@matrixai/errors": "^1.1.7", - "@matrixai/resources": "^1.1.5", - "@matrixai/timer": "^1.1.1" + "@matrixai/async-cancellable": "^2.0.0", + "@matrixai/errors": "^2.0.1", + "@matrixai/resources": "^2.0.0", + "@matrixai/timer": "^2.0.0" } }, "node_modules/@matrixai/contexts": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@matrixai/contexts/-/contexts-1.2.0.tgz", - "integrity": "sha512-MR/B02Kf4UoliP9b/gMMKsvWV6QM4JSPKTIqrhQP2tbOl3FwLI+AIhL3vgYEj1Xw+PP8bY5cr8ontJ8x6AJyMg==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@matrixai/contexts/-/contexts-2.0.2.tgz", + "integrity": "sha512-nI29nv2UP43s+hO+N8SDNxlDHHfj0Evypg5IxZ/Y04o6/InDhCQmZErxMu4ZAOTtt21yuI4zssPRcBQdhtQygA==", + "license": "Apache-2.0", "dependencies": { - "@matrixai/async-cancellable": "^1.1.1", - "@matrixai/async-locks": "^4.0.0", - "@matrixai/errors": "^1.1.7", - "@matrixai/resources": "^1.1.5", - "@matrixai/timer": "^1.1.1" + "@matrixai/async-cancellable": "^2.0.0", + "@matrixai/async-locks": "^5.0.1", + "@matrixai/errors": "^2.1.2", + "@matrixai/resources": "^2.0.0", + "@matrixai/timer": "^2.1.0" } }, "node_modules/@matrixai/errors": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@matrixai/errors/-/errors-1.2.0.tgz", - "integrity": "sha512-eZHPHFla5GFmi0O0yGgbtkca+ZjwpDbMz+60NC3y+DzQq6BMoe4gHmPjDalAHTxyxv0+Q+AWJTuV8Ows+IqBfQ==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@matrixai/errors/-/errors-2.1.3.tgz", + "integrity": "sha512-uPH09OHLykjCdX17Piyc1P0kw3pkJC8l2ydr6LzcWUPmP8i38oO9oq2AqX21UeyeBhGvDcBzQk890GUMb6iOIA==", + "license": "Apache-2.0", "dependencies": { "ts-custom-error": "3.2.2" } }, "node_modules/@matrixai/events": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/@matrixai/events/-/events-3.2.3.tgz", - "integrity": "sha512-bZrNCwzYeFalGQpn8qa/jgD10mUAwLRbv6xGMI7gGz1f+vE65d3GPoJ6JoFOJSg9iCmRSayQJ+IipH3LMATvDA==" + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@matrixai/events/-/events-4.0.1.tgz", + "integrity": "sha512-75hH7ZTmhM/VXeICXCPiVr/ZxQSoBwXh2HOI3AhD8AGYDDsEJsm4tnDSr/6vT3vS0ryZb3kb9mpAmCeibdrF3w==", + "license": "Apache-2.0" }, "node_modules/@matrixai/logger": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@matrixai/logger/-/logger-3.1.2.tgz", - "integrity": "sha512-nNliLCnbg6hGS2+gGtQfeeyVNJzOmvqz90AbrQsHPNiE08l3YsENL2JQt9d454SorD1Ud51ymZdDCkeMLWY93A==" + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@matrixai/logger/-/logger-4.0.3.tgz", + "integrity": "sha512-cu7e82iwN32H+K8HxsrvrWEYSEj7+RP/iVFhJ4RuacC8/BSOLFOYxry3EchVjrx4FP5G7QP1HnKYXAGpZN/46w==", + "license": "Apache-2.0" }, "node_modules/@matrixai/resources": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@matrixai/resources/-/resources-1.1.5.tgz", - "integrity": "sha512-m/DEZEe3wHqWEPTyoBtzFF6U9vWYhEnQtGgwvqiAlTxTM0rk96UBpWjDZCTF/vYG11ZlmlQFtg5H+zGgbjaB3Q==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@matrixai/resources/-/resources-2.0.1.tgz", + "integrity": "sha512-qP7wDz1HnQY7wV4NxybAE+A+488D7bGkkdgk2TIRaw8/fTWENi9Y/AFvOJrdKt3q5rDybB4OeTJIkN5qULE35A==", + "license": "Apache-2.0" }, "node_modules/@matrixai/timer": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@matrixai/timer/-/timer-1.1.1.tgz", - "integrity": "sha512-8UKDoGuwKC6BvrY/yANJVH29v71wgQKH/tJlxMPohGxmzVUQO5+JeI4lUYVHTs2vq1AyKAWloF5fOig+I1dyGA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@matrixai/timer/-/timer-2.1.1.tgz", + "integrity": "sha512-8N4t3eISASJttKIuQKitVfCNxfaUp1Tritg9/92biGDxVwoP+Err8FVrjG30yWz56K/H+T9xUcZ58AH/mk15Sw==", + "license": "Apache-2.0", "dependencies": { - "@matrixai/async-cancellable": "^1.1.1", - "@matrixai/errors": "^1.1.7" + "@matrixai/async-cancellable": "^2.0.0", + "@matrixai/errors": "^2.0.1" } }, "node_modules/@nodelib/fs.scandir": { @@ -2586,18 +2969,6 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/bs-logger": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", - "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", - "dev": true, - "dependencies": { - "fast-json-stable-stringify": "2.x" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/bser": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", @@ -3251,6 +3622,44 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/esbuild": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", + "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.18.20", + "@esbuild/android-arm64": "0.18.20", + "@esbuild/android-x64": "0.18.20", + "@esbuild/darwin-arm64": "0.18.20", + "@esbuild/darwin-x64": "0.18.20", + "@esbuild/freebsd-arm64": "0.18.20", + "@esbuild/freebsd-x64": "0.18.20", + "@esbuild/linux-arm": "0.18.20", + "@esbuild/linux-arm64": "0.18.20", + "@esbuild/linux-ia32": "0.18.20", + "@esbuild/linux-loong64": "0.18.20", + "@esbuild/linux-mips64el": "0.18.20", + "@esbuild/linux-ppc64": "0.18.20", + "@esbuild/linux-riscv64": "0.18.20", + "@esbuild/linux-s390x": "0.18.20", + "@esbuild/linux-x64": "0.18.20", + "@esbuild/netbsd-x64": "0.18.20", + "@esbuild/openbsd-x64": "0.18.20", + "@esbuild/sunos-x64": "0.18.20", + "@esbuild/win32-arm64": "0.18.20", + "@esbuild/win32-ia32": "0.18.20", + "@esbuild/win32-x64": "0.18.20" + } + }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -3663,9 +4072,9 @@ } }, "node_modules/fast-check": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-3.13.0.tgz", - "integrity": "sha512-m6+3gZ/yTiCWTuV/1e/UuPPjyyyHdQ5gu0pMd84C6705VTDjAgAE6nqFT5jhgegFllCJ95yOzBpqvJSs2DZAxQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-4.0.0.tgz", + "integrity": "sha512-aXLyLemZ7qhLNn2oq+YpjT2Xed21+i29WGAYuyrGbU4r8oinB3i4XR4e62O3NY6qmm5qHEDoc/7d+gMsri3AfA==", "dev": true, "funding": [ { @@ -3677,13 +4086,31 @@ "url": "https://opencollective.com/fast-check" } ], + "license": "MIT", "dependencies": { - "pure-rand": "^6.0.0" + "pure-rand": "^7.0.0" }, "engines": { - "node": ">=8.0.0" + "node": ">=12.17.0" } }, + "node_modules/fast-check/node_modules/pure-rand": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-7.0.1.tgz", + "integrity": "sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -3960,6 +4387,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-tsconfig": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.0.tgz", + "integrity": "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -4669,22 +5109,6 @@ "node": ">=8" } }, - "node_modules/ix": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ix/-/ix-5.0.0.tgz", - "integrity": "sha512-6LyyrHnvNrSy5pKtW/KA+KKusHrB223aBJCJlIGPN7QBfDkEEtNrAkAz9lLLShIcdJntq6BiPCHuKaCM/9wwXw==", - "dev": true, - "dependencies": { - "@types/node": "^13.7.4", - "tslib": "^2.3.0" - } - }, - "node_modules/ix/node_modules/@types/node": { - "version": "13.13.52", - "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.52.tgz", - "integrity": "sha512-s3nugnZumCC//n4moGGe6tkNMyYEdaDBitVjwPxXmR5lnMG5dHePinH2EdxkG3Rh1ghFHHixAG4NJhpJW1rthQ==", - "dev": true - }, "node_modules/jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", @@ -5461,12 +5885,6 @@ "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", "dev": true }, - "node_modules/lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", - "dev": true - }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -6243,6 +6661,16 @@ "node": ">=4" } }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, "node_modules/resolve.exports": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", @@ -6800,53 +7228,11 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/ts-custom-error/-/ts-custom-error-3.2.2.tgz", "integrity": "sha512-u0YCNf2lf6T/vHm+POKZK1yFKWpSpJitcUN3HxqyEcFuNnHIDbyuIQC7QDy/PsBX3giFyk9rt6BFqBAh2lsDZQ==", + "license": "MIT", "engines": { "node": ">=14.0.0" } }, - "node_modules/ts-jest": { - "version": "29.1.1", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", - "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==", - "dev": true, - "dependencies": { - "bs-logger": "0.x", - "fast-json-stable-stringify": "2.x", - "jest-util": "^29.0.0", - "json5": "^2.2.3", - "lodash.memoize": "4.x", - "make-error": "1.x", - "semver": "^7.5.3", - "yargs-parser": "^21.0.1" - }, - "bin": { - "ts-jest": "cli.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": ">=7.0.0-beta.0 <8", - "@jest/types": "^29.0.0", - "babel-jest": "^29.0.0", - "jest": "^29.0.0", - "typescript": ">=4.3 <6" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "@jest/types": { - "optional": true - }, - "babel-jest": { - "optional": true - }, - "esbuild": { - "optional": true - } - } - }, "node_modules/ts-node": { "version": "10.9.1", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", @@ -6950,6 +7336,35 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true }, + "node_modules/tsx": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-3.14.0.tgz", + "integrity": "sha512-xHtFaKtHxM9LOklMmJdI3BEnQq/D5F73Of2E1GDrITi9sgoVkvIsrQUTY1G8FlmGtA+awCI4EBlTRRYxkL2sRg==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "~0.18.20", + "get-tsconfig": "^4.7.2", + "source-map-support": "^0.5.21" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/tsx/node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", diff --git a/package.json b/package.json index e80f820..6b81015 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,9 @@ }, { "name": "Amy Yan" + }, + { + "name": "Brian Botha" } ], "description": "RPC for TypeScript/JavaScript Applications", @@ -19,30 +22,44 @@ "type": "git", "url": "https://github.com/MatrixAI/js-rpc.git" }, - "main": "dist/index.js", - "types": "dist/index.d.ts", + "type": "module", + "exports": { + "./package.json": "./package.json", + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js" + }, + "./*.js": { + "types": "./dist/*.d.ts", + "import": "./dist/*.js" + }, + "./*": "./dist/*" + }, + "imports": { + "#*": "./dist/*" + }, "scripts": { "prepare": "tsc -p ./tsconfig.build.json", "build": "shx rm -rf ./dist && tsc -p ./tsconfig.build.json", "postversion": "npm install --package-lock-only --ignore-scripts --silent", - "ts-node": "ts-node", - "test": "jest", - "lint": "eslint '{src,tests,scripts,benches}/**/*.{js,ts}'", - "lintfix": "eslint '{src,tests,scripts,benches}/**/*.{js,ts}' --fix", + "tsx": "tsx", + "test": "node ./scripts/test.mjs", + "lint": "eslint '{src,tests,scripts,benches}/**/*.{js,mjs,ts,mts,jsx,tsx}'", + "lintfix": "eslint '{src,tests,scripts,benches}/**/*.{js,mjs,ts,mts,jsx,tsx}' --fix", "lint-shell": "find ./src ./tests ./scripts -type f -regextype posix-extended -regex '.*\\.(sh)' -exec shellcheck {} +", "docs": "shx rm -rf ./docs && typedoc --gitRevision master --tsconfig ./tsconfig.build.json --out ./docs src", - "bench": "shx rm -rf ./benches/results && ts-node ./benches" + "bench": "tsc -p ./tsconfig.build.json && shx rm -rf ./benches/results && tsx ./benches/index.ts" }, "dependencies": { - "@matrixai/async-init": "^1.10.0", - "@matrixai/contexts": "^1.2.0", - "@matrixai/errors": "^1.2.0", - "@matrixai/events": "^3.2.3", - "@matrixai/logger": "^3.1.2", + "@matrixai/async-init": "^2.1.2", + "@matrixai/contexts": "^2.0.2", + "@matrixai/errors": "^2.1.3", + "@matrixai/events": "^4.0.1", + "@matrixai/logger": "^4.0.3", "@streamparser/json": "^0.0.17" }, "devDependencies": { - "@fast-check/jest": "^1.1.0", + "@fast-check/jest": "^2.1.0", "@swc/core": "1.3.82", "@swc/jest": "^0.2.29", "@types/jest": "^29.5.2", @@ -55,16 +72,15 @@ "eslint-config-prettier": "^8.8.0", "eslint-plugin-import": "^2.27.5", "eslint-plugin-prettier": "^5.0.0-alpha.2", - "ix": "^5.0.0", + "fast-check": "^4.0.0", "jest": "^29.6.2", "jest-extended": "^4.0.0", "jest-junit": "^16.0.0", "prettier": "^3.0.0", "shx": "^0.3.4", "systeminformation": "^5.18.5", - "ts-jest": "^29.1.1", "ts-node": "^10.9.1", - "tsconfig-paths": "^3.9.0", + "tsx": "^3.12.7", "typedoc": "^0.24.8", "typescript": "^5.1.6" } diff --git a/scripts/test.mjs b/scripts/test.mjs new file mode 100644 index 0000000..35db564 --- /dev/null +++ b/scripts/test.mjs @@ -0,0 +1,48 @@ +#!/usr/bin/env node + +import os from 'node:os'; +import path from 'node:path'; +import url from 'node:url'; +import process from 'node:process'; +import childProcess from 'node:child_process'; + +const projectPath = path.dirname( + path.dirname(url.fileURLToPath(import.meta.url)), +); + +const platform = os.platform(); + +/* eslint-disable no-console */ +async function main(argv = process.argv) { + argv = argv.slice(2); + const tscArgs = [`-p`, path.join(projectPath, 'tsconfig.build.json')]; + console.error('Running tsc:'); + console.error(['tsc', ...tscArgs].join(' ')); + childProcess.execFileSync('tsc', tscArgs, { + stdio: ['inherit', 'inherit', 'inherit'], + windowsHide: true, + encoding: 'utf-8', + shell: platform === 'win32' ? true : false, + }); + const jestArgs = [...argv]; + console.error('Running jest:'); + console.error(['jest', ...jestArgs].join(' ')); + childProcess.execFileSync('jest', jestArgs, { + env: { + ...process.env, + NODE_OPTIONS: '--experimental-vm-modules', + }, + stdio: ['inherit', 'inherit', 'inherit'], + windowsHide: true, + encoding: 'utf-8', + shell: platform === 'win32' ? true : false, + }); +} +/* eslint-enable no-console */ + +if (import.meta.url.startsWith('file:')) { + const modulePath = url.fileURLToPath(import.meta.url); + if (process.argv[1] === modulePath) { + void main(); + } +} diff --git a/src/RPCClient.ts b/src/RPCClient.ts index 3aa6bdf..0179b81 100644 --- a/src/RPCClient.ts +++ b/src/RPCClient.ts @@ -15,12 +15,12 @@ import type { RPCStream, StreamFactory, ToError, -} from './types'; +} from './types.js'; import Logger from '@matrixai/logger'; import { Timer } from '@matrixai/timer'; -import * as middleware from './middleware'; -import * as errors from './errors'; -import * as utils from './utils'; +import * as middleware from './middleware.js'; +import * as errors from './errors.js'; +import * as utils from './utils.js'; const timerCleanupReasonSymbol = Symbol('timerCleanUpReasonSymbol'); @@ -491,7 +491,9 @@ class RPCClient { try { const message = await Promise.race([tempReader.read(), abortProm.p]); const messageValue = message.value as JSONRPCResponse; - if (message.done) utils.never(); + if (message.done) { + utils.never('a message was expected, received done instead'); + } if ('error' in messageValue) { const metadata = { ...(rpcStream.meta ?? {}), diff --git a/src/RPCServer.ts b/src/RPCServer.ts index cd51901..db74afc 100644 --- a/src/RPCServer.ts +++ b/src/RPCServer.ts @@ -16,24 +16,21 @@ import type { MiddlewareFactory, FromError, JSONObject, -} from './types'; +} from './types.js'; import { ReadableStream, TransformStream } from 'stream/web'; import Logger from '@matrixai/logger'; import { PromiseCancellable } from '@matrixai/async-cancellable'; import { Timer } from '@matrixai/timer'; import { startStop } from '@matrixai/async-init'; -import { StartStop } from '@matrixai/async-init/dist/StartStop'; -import { RawHandler } from './handlers'; -import { - DuplexHandler, - ServerHandler, - UnaryHandler, - ClientHandler, -} from './handlers'; -import * as utils from './utils'; -import * as errors from './errors'; -import * as middleware from './middleware'; -import * as events from './events'; +import RawHandler from './handlers/RawHandler.js'; +import DuplexHandler from './handlers/DuplexHandler.js'; +import ServerHandler from './handlers/ServerHandler.js'; +import UnaryHandler from './handlers/UnaryHandler.js'; +import ClientHandler from './handlers/ClientHandler.js'; +import * as utils from './utils.js'; +import * as errors from './errors.js'; +import * as middleware from './middleware.js'; +import * as events from './events.js'; const cleanupReason = Symbol('CleanupReason'); @@ -79,7 +76,7 @@ function composeErrorMessage(error: unknown): string { */ interface RPCServer extends startStop.StartStop {} -@StartStop({ +@startStop.StartStop({ eventStart: events.EventRPCServerStart, eventStarted: events.EventRPCServerStarted, eventStop: events.EventRPCServerStopping, @@ -197,14 +194,6 @@ class RPCServer { ); continue; } - if (manifestItem instanceof ClientHandler) { - this.registerClientStreamHandler( - key, - manifestItem.handle, - manifestItem.timeout, - ); - continue; - } if (manifestItem instanceof UnaryHandler) { this.registerUnaryHandler( key, @@ -213,7 +202,7 @@ class RPCServer { ); continue; } - utils.never(); + utils.never(`manifestItem must be an instance of a Handler`); } } catch (e) { // No need to clean up streams, as streams can only be handled after RPCServer has been started. diff --git a/src/callers/Caller.ts b/src/callers/Caller.ts index 094e2a4..19af4b5 100644 --- a/src/callers/Caller.ts +++ b/src/callers/Caller.ts @@ -2,7 +2,7 @@ import type { HandlerType, JSONRPCRequestParams, JSONRPCResponseResult, -} from '../types'; +} from '../types.js'; abstract class Caller< Input extends JSONRPCRequestParams = JSONRPCRequestParams, diff --git a/src/callers/ClientCaller.ts b/src/callers/ClientCaller.ts index 66b47d7..cdffaed 100644 --- a/src/callers/ClientCaller.ts +++ b/src/callers/ClientCaller.ts @@ -1,5 +1,5 @@ -import type { JSONRPCRequestParams, JSONRPCResponseResult } from '../types'; -import Caller from './Caller'; +import type { JSONRPCRequestParams, JSONRPCResponseResult } from '../types.js'; +import Caller from './Caller.js'; class ClientCaller< Input extends JSONRPCRequestParams = JSONRPCRequestParams, diff --git a/src/callers/DuplexCaller.ts b/src/callers/DuplexCaller.ts index 98ddb54..b31ae0e 100644 --- a/src/callers/DuplexCaller.ts +++ b/src/callers/DuplexCaller.ts @@ -1,5 +1,5 @@ -import type { JSONRPCRequestParams, JSONRPCResponseResult } from '../types'; -import Caller from './Caller'; +import type { JSONRPCRequestParams, JSONRPCResponseResult } from '../types.js'; +import Caller from './Caller.js'; class DuplexCaller< Input extends JSONRPCRequestParams = JSONRPCRequestParams, diff --git a/src/callers/RawCaller.ts b/src/callers/RawCaller.ts index a5e3522..49acef5 100644 --- a/src/callers/RawCaller.ts +++ b/src/callers/RawCaller.ts @@ -1,4 +1,4 @@ -import Caller from './Caller'; +import Caller from './Caller.js'; class RawCaller extends Caller { public type: 'RAW' = 'RAW' as const; } diff --git a/src/callers/ServerCaller.ts b/src/callers/ServerCaller.ts index b281464..745c703 100644 --- a/src/callers/ServerCaller.ts +++ b/src/callers/ServerCaller.ts @@ -1,5 +1,5 @@ -import type { JSONRPCRequestParams, JSONRPCResponseResult } from '../types'; -import Caller from './Caller'; +import type { JSONRPCRequestParams, JSONRPCResponseResult } from '../types.js'; +import Caller from './Caller.js'; class ServerCaller< Input extends JSONRPCRequestParams = JSONRPCRequestParams, diff --git a/src/callers/UnaryCaller.ts b/src/callers/UnaryCaller.ts index fd76df8..51c2576 100644 --- a/src/callers/UnaryCaller.ts +++ b/src/callers/UnaryCaller.ts @@ -1,5 +1,5 @@ -import type { JSONRPCRequestParams, JSONRPCResponseResult } from '../types'; -import Caller from './Caller'; +import type { JSONRPCRequestParams, JSONRPCResponseResult } from '../types.js'; +import Caller from './Caller.js'; class UnaryCaller< Input extends JSONRPCRequestParams = JSONRPCRequestParams, diff --git a/src/callers/index.ts b/src/callers/index.ts index 17e8c87..1955bd0 100644 --- a/src/callers/index.ts +++ b/src/callers/index.ts @@ -1,6 +1,6 @@ -export { default as Caller } from './Caller'; -export { default as ClientCaller } from './ClientCaller'; -export { default as DuplexCaller } from './DuplexCaller'; -export { default as RawCaller } from './RawCaller'; -export { default as ServerCaller } from './ServerCaller'; -export { default as UnaryCaller } from './UnaryCaller'; +export { default as Caller } from './Caller.js'; +export { default as ClientCaller } from './ClientCaller.js'; +export { default as DuplexCaller } from './DuplexCaller.js'; +export { default as RawCaller } from './RawCaller.js'; +export { default as ServerCaller } from './ServerCaller.js'; +export { default as UnaryCaller } from './UnaryCaller.js'; diff --git a/src/errors.ts b/src/errors.ts index a9789df..bf7a8a7 100644 --- a/src/errors.ts +++ b/src/errors.ts @@ -1,11 +1,15 @@ import type { Class } from '@matrixai/errors'; -import type { JSONRPCResponseError, JSONValue, POJO } from './types'; +import type { JSONRPCResponseError, JSONValue, POJO } from './types.js'; import { AbstractError } from '@matrixai/errors'; class ErrorRPC extends AbstractError { static description = 'RPC Error'; } +class ErrorRPCUndefinedBehaviour extends ErrorRPC { + static description = 'You should never see this error'; +} + // Server Errors class ErrorRPCServer extends ErrorRPC { @@ -247,6 +251,7 @@ const rpcProtocolErrors = { export { ErrorRPC, + ErrorRPCUndefinedBehaviour, ErrorRPCServer, ErrorRPCServerNotRunning, ErrorRPCProtocol, diff --git a/src/events.ts b/src/events.ts index 565bfc7..0846b7c 100644 --- a/src/events.ts +++ b/src/events.ts @@ -3,7 +3,7 @@ import type { ErrorRPCConnectionPeer, ErrorRPCConnectionKeepAliveTimeOut, ErrorRPCConnectionInternal, -} from './errors'; +} from './errors.js'; import { AbstractEvent } from '@matrixai/events'; abstract class EventRPCClient extends AbstractEvent {} diff --git a/src/handlers/ClientHandler.ts b/src/handlers/ClientHandler.ts index 5478a71..798dbac 100644 --- a/src/handlers/ClientHandler.ts +++ b/src/handlers/ClientHandler.ts @@ -3,10 +3,10 @@ import type { JSONValue, JSONRPCRequestParams, JSONRPCResponseResult, -} from '../types'; +} from '../types.js'; import type { ContextTimed } from '@matrixai/contexts'; -import Handler from './Handler'; -import { ErrorRPCMethodNotImplemented } from '../errors'; +import Handler from './Handler.js'; +import { ErrorRPCMethodNotImplemented } from '../errors.js'; abstract class ClientHandler< Container extends ContainerType = ContainerType, diff --git a/src/handlers/DuplexHandler.ts b/src/handlers/DuplexHandler.ts index b62d672..5402793 100644 --- a/src/handlers/DuplexHandler.ts +++ b/src/handlers/DuplexHandler.ts @@ -3,10 +3,10 @@ import type { JSONValue, JSONRPCRequestParams, JSONRPCResponseResult, -} from '../types'; +} from '../types.js'; import type { ContextTimed } from '@matrixai/contexts'; -import Handler from './Handler'; -import { ErrorRPCMethodNotImplemented } from '../errors'; +import Handler from './Handler.js'; +import { ErrorRPCMethodNotImplemented } from '../errors.js'; abstract class DuplexHandler< Container extends ContainerType = ContainerType, diff --git a/src/handlers/Handler.ts b/src/handlers/Handler.ts index b4bd4c2..f0b2b0c 100644 --- a/src/handlers/Handler.ts +++ b/src/handlers/Handler.ts @@ -2,7 +2,7 @@ import type { ContainerType, JSONRPCRequestParams, JSONRPCResponseResult, -} from '../types'; +} from '../types.js'; abstract class Handler< Container extends ContainerType = ContainerType, Input extends JSONRPCRequestParams = JSONRPCRequestParams, diff --git a/src/handlers/RawHandler.ts b/src/handlers/RawHandler.ts index e5cab11..3772207 100644 --- a/src/handlers/RawHandler.ts +++ b/src/handlers/RawHandler.ts @@ -5,9 +5,9 @@ import type { JSONRPCRequest, JSONRPCResponseResult, JSONValue, -} from '../types'; -import Handler from './Handler'; -import { ErrorRPCMethodNotImplemented } from '../errors'; +} from '../types.js'; +import Handler from './Handler.js'; +import { ErrorRPCMethodNotImplemented } from '../errors.js'; abstract class RawHandler< Container extends ContainerType = ContainerType, diff --git a/src/handlers/ServerHandler.ts b/src/handlers/ServerHandler.ts index 912ea83..9add45a 100644 --- a/src/handlers/ServerHandler.ts +++ b/src/handlers/ServerHandler.ts @@ -4,9 +4,9 @@ import type { JSONValue, JSONRPCRequestParams, JSONRPCResponseResult, -} from '../types'; -import Handler from './Handler'; -import { ErrorRPCMethodNotImplemented } from '../errors'; +} from '../types.js'; +import Handler from './Handler.js'; +import { ErrorRPCMethodNotImplemented } from '../errors.js'; abstract class ServerHandler< Container extends ContainerType = ContainerType, diff --git a/src/handlers/UnaryHandler.ts b/src/handlers/UnaryHandler.ts index 23f8cd1..67c579b 100644 --- a/src/handlers/UnaryHandler.ts +++ b/src/handlers/UnaryHandler.ts @@ -4,9 +4,9 @@ import type { JSONValue, JSONRPCRequestParams, JSONRPCResponseResult, -} from '../types'; -import Handler from './Handler'; -import { ErrorRPCMethodNotImplemented } from '../errors'; +} from '../types.js'; +import Handler from './Handler.js'; +import { ErrorRPCMethodNotImplemented } from '../errors.js'; abstract class UnaryHandler< Container extends ContainerType = ContainerType, diff --git a/src/handlers/index.ts b/src/handlers/index.ts index 2df4ee2..eb89418 100644 --- a/src/handlers/index.ts +++ b/src/handlers/index.ts @@ -1,6 +1,6 @@ -export { default as Handler } from './Handler'; -export { default as ClientHandler } from './ClientHandler'; -export { default as DuplexHandler } from './DuplexHandler'; -export { default as RawHandler } from './RawHandler'; -export { default as ServerHandler } from './ServerHandler'; -export { default as UnaryHandler } from './UnaryHandler'; +export { default as Handler } from './Handler.js'; +export { default as ClientHandler } from './ClientHandler.js'; +export { default as DuplexHandler } from './DuplexHandler.js'; +export { default as RawHandler } from './RawHandler.js'; +export { default as ServerHandler } from './ServerHandler.js'; +export { default as UnaryHandler } from './UnaryHandler.js'; diff --git a/src/index.ts b/src/index.ts index 44e076d..b870aaa 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,9 +1,9 @@ -export { default as RPCClient } from './RPCClient'; -export { default as RPCServer } from './RPCServer'; -export * as utils from './utils'; -export * from './types'; -export * as errors from './errors'; -export * as events from './events'; -export * from './handlers'; -export * from './callers'; -export * as middleware from './middleware'; +export { default as RPCClient } from './RPCClient.js'; +export { default as RPCServer } from './RPCServer.js'; +export * as utils from './utils.js'; +export * from './types.js'; +export * as errors from './errors.js'; +export * as events from './events.js'; +export * from './handlers/index.js'; +export * from './callers/index.js'; +export * as middleware from './middleware.js'; diff --git a/src/middleware.ts b/src/middleware.ts index e415bc4..39411b9 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -5,12 +5,12 @@ import type { JSONRPCResponseSuccess, MiddlewareFactory, JSONValue, -} from './types'; +} from './types.js'; import type { ContextTimed } from '@matrixai/contexts'; import { TransformStream } from 'stream/web'; import { JSONParser } from '@streamparser/json'; -import * as utils from './utils'; -import * as rpcErrors from './errors'; +import * as utils from './utils.js'; +import * as rpcErrors from './errors.js'; /** * This function is a factory to create a TransformStream that will diff --git a/src/types.ts b/src/types.ts index b29c47e..ec1d88e 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,12 +1,12 @@ import type { ReadableStream, ReadableWritablePair } from 'stream/web'; import type { ContextTimed, ContextTimedInput } from '@matrixai/contexts'; -import type { Caller } from './callers'; -import type { RawCaller } from './callers'; -import type { DuplexCaller } from './callers'; -import type { ServerCaller } from './callers'; -import type { ClientCaller } from './callers'; -import type { UnaryCaller } from './callers'; -import type Handler from './handlers/Handler'; +import type Caller from './callers/Caller.js'; +import type RawCaller from './callers/RawCaller.js'; +import type DuplexCaller from './callers/DuplexCaller.js'; +import type ServerCaller from './callers/ServerCaller.js'; +import type ClientCaller from './callers/ClientCaller.js'; +import type UnaryCaller from './callers/UnaryCaller.js'; +import type Handler from './handlers/Handler.js'; /** * This is the type for the IdGenFunction. It is used to generate the request diff --git a/src/utils.ts b/src/utils.ts index edd2816..e314d87 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -14,11 +14,11 @@ import type { JSONValue, PromiseDeconstructed, ToError, -} from './types'; +} from './types.js'; import { TransformStream } from 'stream/web'; import { JSONParser } from '@streamparser/json'; import { AbstractError } from '@matrixai/errors'; -import * as errors from './errors'; +import * as errors from './errors.js'; const timeoutCancelledReason = Symbol('timeoutCancelledReason'); @@ -537,8 +537,8 @@ function parseHeadStream( ); } -function never(): never { - throw new errors.ErrorRPC('This function should never be called'); +function never(message: string): never { + throw new errors.ErrorRPCUndefinedBehaviour(message); } export { diff --git a/tests/RPC.test.ts b/tests/RPC.test.ts index bef466f..f395c0d 100644 --- a/tests/RPC.test.ts +++ b/tests/RPC.test.ts @@ -4,32 +4,32 @@ import type { JSONRPCRequestParams, JSONRPCRequest, JSONRPCResponseResult, -} from '@/types'; +} from '#types.js'; import type { ReadableStream } from 'stream/web'; -import type { JSONValue, IdGen } from '@/types'; +import type { JSONValue, IdGen } from '#types.js'; import type { ContextTimed } from '@matrixai/contexts'; import { TransformStream } from 'stream/web'; import { fc, test } from '@fast-check/jest'; import Logger, { LogLevel, StreamHandler } from '@matrixai/logger'; import { Timer } from '@matrixai/timer'; -import RawCaller from '@/callers/RawCaller'; -import DuplexCaller from '@/callers/DuplexCaller'; -import ServerCaller from '@/callers/ServerCaller'; -import ClientCaller from '@/callers/ClientCaller'; -import UnaryCaller from '@/callers/UnaryCaller'; -import * as rpcUtilsMiddleware from '@/middleware'; -import { ErrorRPCRemote } from '@/errors'; -import * as rpcErrors from '@/errors'; -import RPCClient from '@/RPCClient'; -import RPCServer from '@/RPCServer'; -import * as utils from '@/utils'; -import DuplexHandler from '@/handlers/DuplexHandler'; -import RawHandler from '@/handlers/RawHandler'; -import ServerHandler from '@/handlers/ServerHandler'; -import UnaryHandler from '@/handlers/UnaryHandler'; -import ClientHandler from '@/handlers/ClientHandler'; -import { filterSensitive } from '@/utils'; -import * as rpcTestUtils from './utils'; +import * as rpcTestUtils from './utils.js'; +import RawCaller from '#callers/RawCaller.js'; +import DuplexCaller from '#callers/DuplexCaller.js'; +import ServerCaller from '#callers/ServerCaller.js'; +import ClientCaller from '#callers/ClientCaller.js'; +import UnaryCaller from '#callers/UnaryCaller.js'; +import * as rpcUtilsMiddleware from '#middleware.js'; +import { ErrorRPCRemote } from '#errors.js'; +import * as rpcErrors from '#errors.js'; +import RPCClient from '#RPCClient.js'; +import RPCServer from '#RPCServer.js'; +import * as utils from '#utils.js'; +import DuplexHandler from '#handlers/DuplexHandler.js'; +import RawHandler from '#handlers/RawHandler.js'; +import ServerHandler from '#handlers/ServerHandler.js'; +import UnaryHandler from '#handlers/UnaryHandler.js'; +import ClientHandler from '#handlers/ClientHandler.js'; +import { filterSensitive } from '#utils.js'; describe('RPC tests', () => { const logger = new Logger(`RPC Test`, LogLevel.WARN, [new StreamHandler()]); @@ -240,9 +240,7 @@ describe('RPC tests', () => { }); test.prop( { - values: fc - .array(rpcTestUtils.safeJsonObjectArb, { minLength: 1 }) - .noShrink(), + values: fc.array(rpcTestUtils.safeJsonObjectArb, { minLength: 1 }), }, { numRuns: 1 }, )( @@ -370,7 +368,7 @@ describe('RPC tests', () => { await rpcServer.stop({ force: true }); }); test.prop({ - values: fc.array(fc.integer(), { minLength: 1 }).noShrink(), + values: fc.array(fc.integer(), { minLength: 1 }), })('the RPC should communicate using client streams', async ({ values }) => { const { clientPair, serverPair } = rpcTestUtils.createTapPairs< Uint8Array, diff --git a/tests/RPCClient.test.ts b/tests/RPCClient.test.ts index 7467178..ad356e3 100644 --- a/tests/RPCClient.test.ts +++ b/tests/RPCClient.test.ts @@ -3,30 +3,30 @@ import type { JSONRPCRequestParams, JSONRPCResponseResult, JSONValue, -} from '@/types'; +} from '#types.js'; import type { JSONRPCRequest, JSONRPCRequestMessage, JSONRPCResponse, JSONRPCResponseSuccess, RPCStream, -} from '@/types'; -import type { IdGen } from '@/types'; +} from '#types.js'; +import type { IdGen } from '#types.js'; import { TransformStream, ReadableStream } from 'stream/web'; import Logger, { LogLevel, StreamHandler } from '@matrixai/logger'; import { Timer } from '@matrixai/timer'; import { test, fc } from '@fast-check/jest'; -import RawCaller from '@/callers/RawCaller'; -import DuplexCaller from '@/callers/DuplexCaller'; -import ServerCaller from '@/callers/ServerCaller'; -import ClientCaller from '@/callers/ClientCaller'; -import UnaryCaller from '@/callers/UnaryCaller'; -import RPCClient from '@/RPCClient'; -import * as rpcErrors from '@/errors'; -import * as rpcUtilsMiddleware from '@/middleware'; -import { promise, timeoutCancelledReason } from '@/utils'; -import * as utils from '@/utils'; -import * as rpcTestUtils from './utils'; +import * as rpcTestUtils from './utils.js'; +import RawCaller from '#callers/RawCaller.js'; +import DuplexCaller from '#callers/DuplexCaller.js'; +import ServerCaller from '#callers/ServerCaller.js'; +import ClientCaller from '#callers/ClientCaller.js'; +import UnaryCaller from '#callers/UnaryCaller.js'; +import RPCClient from '#RPCClient.js'; +import * as rpcErrors from '#errors.js'; +import * as rpcUtilsMiddleware from '#middleware.js'; +import { promise, timeoutCancelledReason } from '#utils.js'; +import * as utils from '#utils.js'; describe('RPCClient tests', () => { const logger = new Logger('RPCClient Test', LogLevel.WARN, [ @@ -35,11 +35,12 @@ describe('RPCClient tests', () => { const idGen: IdGen = () => Promise.resolve(null); const methodName = 'testMethod'; - const specificMessageArb = fc - .array(rpcTestUtils.JSONRPCResponseSuccessArb(), { + const specificMessageArb = fc.array( + rpcTestUtils.JSONRPCResponseSuccessArb(), + { minLength: 5, - }) - .noShrink(); + }, + ); test.prop({ headerParams: rpcTestUtils.safeJsonObjectArb, diff --git a/tests/RPCServer.test.ts b/tests/RPCServer.test.ts index 60bb2f3..f00f5c9 100644 --- a/tests/RPCServer.test.ts +++ b/tests/RPCServer.test.ts @@ -8,24 +8,24 @@ import type { JSONRPCResponseResult, JSONValue, RPCStream, -} from '@/types'; -import type { IdGen } from '@/types'; +} from '#types.js'; +import type { IdGen } from '#types.js'; import type { PromiseCancellable } from '@matrixai/async-cancellable'; -import type * as rpcEvents from '@/events'; +import type * as rpcEvents from '#events.js'; import { ReadableStream, TransformStream, WritableStream } from 'stream/web'; import { fc, test } from '@fast-check/jest'; import Logger, { LogLevel, StreamHandler } from '@matrixai/logger'; -import RPCServer from '@/RPCServer'; -import * as rpcErrors from '@/errors'; -import * as rpcUtils from '@/utils'; -import { promise } from '@/utils'; -import * as rpcUtilsMiddleware from '@/middleware'; -import ServerHandler from '@/handlers/ServerHandler'; -import DuplexHandler from '@/handlers/DuplexHandler'; -import RawHandler from '@/handlers/RawHandler'; -import UnaryHandler from '@/handlers/UnaryHandler'; -import ClientHandler from '@/handlers/ClientHandler'; -import * as rpcTestUtils from './utils'; +import * as rpcTestUtils from './utils.js'; +import RPCServer from '#RPCServer.js'; +import * as rpcErrors from '#errors.js'; +import * as rpcUtils from '#utils.js'; +import { promise } from '#utils.js'; +import * as rpcUtilsMiddleware from '#middleware.js'; +import ServerHandler from '#handlers/ServerHandler.js'; +import DuplexHandler from '#handlers/DuplexHandler.js'; +import RawHandler from '#handlers/RawHandler.js'; +import UnaryHandler from '#handlers/UnaryHandler.js'; +import ClientHandler from '#handlers/ClientHandler.js'; describe('RPCServer', () => { const logger = new Logger('RPCServer Test', LogLevel.WARN, [ @@ -33,11 +33,12 @@ describe('RPCServer', () => { ]); const idGen: IdGen = () => Promise.resolve(null); const methodName = 'testMethod'; - const specificMessageArb = fc - .array(rpcTestUtils.jsonRpcRequestMessageArb(fc.constant(methodName)), { + const specificMessageArb = fc.array( + rpcTestUtils.jsonRpcRequestMessageArb(fc.constant(methodName)), + { minLength: 5, - }) - .noShrink(); + }, + ); const singleNumberMessageArb = fc.array( rpcTestUtils.jsonRpcRequestMessageArb( fc.constant(methodName), diff --git a/tests/middleware.test.ts b/tests/middleware.test.ts index 242d1e1..46b4354 100644 --- a/tests/middleware.test.ts +++ b/tests/middleware.test.ts @@ -1,19 +1,15 @@ -import 'ix/add/asynciterable-operators/toarray'; import { fc, test } from '@fast-check/jest'; -import { AsyncIterableX as AsyncIterable } from 'ix/asynciterable'; import { Timer } from '@matrixai/timer'; -import * as rpcUtils from '@/utils'; -import * as rpcErrors from '@/errors'; -import * as rpcUtilsMiddleware from '@/middleware'; -import * as rpcTestUtils from './utils'; +import * as rpcTestUtils from './utils.js'; +import * as rpcUtils from '#utils.js'; +import * as rpcErrors from '#errors.js'; +import * as rpcUtilsMiddleware from '#middleware.js'; describe('Middleware tests', () => { - const noiseArb = fc - .array( - fc.uint8Array({ minLength: 5 }).map((array) => Buffer.from(array)), - { minLength: 5 }, - ) - .noShrink(); + const noiseArb = fc.array( + fc.uint8Array({ minLength: 5 }).map((array) => Buffer.from(array)), + { minLength: 5 }, + ); test.prop({ messages: rpcTestUtils.jsonMessagesArb }, { numRuns: 1000 })( 'converting to raw and back to JSON', @@ -26,7 +22,7 @@ describe('Middleware tests', () => { ), ); // Converting back. - const messagesParsed = await AsyncIterable.as(parsedStream).toArray(); + const messagesParsed = await rpcTestUtils.toArray(parsedStream); expect(messagesParsed).toEqual(messages); }, ); @@ -84,7 +80,7 @@ describe('Middleware tests', () => { messages: rpcTestUtils.jsonMessagesArb, snipPattern: rpcTestUtils.snippingPatternArb, }, - { numRuns: 1000 }, + { numRuns: 1000, verbose: true }, )( 'can parse json stream with random chunk sizes', async ({ messages, snipPattern: snipPattern }) => { @@ -97,7 +93,7 @@ describe('Middleware tests', () => { ), ); // Converting back. - const messagesParsed = await AsyncIterable.as(parsedStream).toArray(); + const messagesParsed = await rpcTestUtils.toArray(parsedStream); expect(messagesParsed).toStrictEqual(messages); }, ); @@ -119,7 +115,7 @@ describe('Middleware tests', () => { ), ); // Converting back. - await expect(AsyncIterable.as(parsedStream).toArray()).rejects.toThrow( + await expect(rpcTestUtils.toArray(parsedStream)).rejects.toThrow( rpcErrors.ErrorRPCParse, ); }); @@ -151,7 +147,7 @@ describe('Middleware tests', () => { ) // Converting back. .pipeThrough(timeoutMiddleware.forward); - const messagesParsed = await AsyncIterable.as(parsedStream).toArray(); + const messagesParsed = await rpcTestUtils.toArray(parsedStream); expect(messagesParsed).toEqual(messages); expect(timer.delay).toBe(timeout); timer.cancel(); @@ -186,7 +182,7 @@ describe('Middleware tests', () => { ) // Converting back. .pipeThrough(timeoutMiddleware.forward); - const messagesParsed = await AsyncIterable.as(parsedStream).toArray(); + const messagesParsed = await rpcTestUtils.toArray(parsedStream); expect(messagesParsed).toEqual(messages); expect(timer.delay).toBe(0); timer.cancel(); @@ -227,7 +223,7 @@ describe('Middleware tests', () => { if (expectedMessages[0].params?.metadata != null) { expectedMessages[0].params.metadata.timeout = null; } - const messagesParsed = await AsyncIterable.as(parsedStream).toArray(); + const messagesParsed = await rpcTestUtils.toArray(parsedStream); expect(messagesParsed).toEqual(expectedMessages); expect(timer.delay).toBe(Infinity); timer.cancel(); @@ -266,7 +262,7 @@ describe('Middleware tests', () => { ...expectedMessages[0].params.metadata, timeout, }; - const messagesParsed = await AsyncIterable.as(parsedStream).toArray(); + const messagesParsed = await rpcTestUtils.toArray(parsedStream); expect(messagesParsed).toEqual(expectedMessages); expect(timer.delay).toBe(timeout); timer.cancel(); diff --git a/tests/setupAfterEnv.ts b/tests/setupAfterEnv.ts index 8ea8279..ec04822 100644 --- a/tests/setupAfterEnv.ts +++ b/tests/setupAfterEnv.ts @@ -1,3 +1,5 @@ +import { jest } from '@jest/globals'; + // Default timeout per test // some tests may take longer in which case you should specify the timeout // explicitly for each test by using the third parameter of test function diff --git a/tests/utils.test.ts b/tests/utils.test.ts index 0e812dc..446a9ed 100644 --- a/tests/utils.test.ts +++ b/tests/utils.test.ts @@ -1,7 +1,6 @@ import { test, fc } from '@fast-check/jest'; -import * as rpcUtils from '@/utils'; -import 'ix/add/asynciterable-operators/toarray'; -import * as rpcTestUtils from './utils'; +import * as rpcTestUtils from './utils.js'; +import * as rpcUtils from '#utils.js'; describe('utils tests', () => { test.prop( diff --git a/tests/utils.ts b/tests/utils.ts index fdcdd95..711943a 100644 --- a/tests/utils.ts +++ b/tests/utils.ts @@ -1,5 +1,5 @@ import type { ReadableWritablePair } from 'stream/web'; -import type { JSONObject, JSONValue } from '@/types'; +import type { JSONObject, JSONValue } from '#types.js'; import type { JSONRPCResponseError, JSONRPCMessage, @@ -9,14 +9,14 @@ import type { JSONRPCResponseSuccess, JSONRPCResponse, JSONRPCRequest, -} from '@/types'; -import type { ErrorRPC } from '@/errors'; +} from '#types.js'; +import type { ErrorRPC } from '#errors.js'; import { ReadableStream, WritableStream, TransformStream } from 'stream/web'; import { fc } from '@fast-check/jest'; import { AbstractError } from '@matrixai/errors'; -import * as utils from '@/utils'; -import { fromError } from '@/utils'; -import * as rpcErrors from '@/errors'; +import * as utils from '#utils.js'; +import { fromError } from '#utils.js'; +import * as rpcErrors from '#errors.js'; /** * This is used to convert regular chunks into randomly sized chunks based on @@ -85,12 +85,14 @@ const safeJsonValueArb = fc .json() .map( (value) => JSON.parse(value.replaceAll('__proto__', 'proto')) as JSONValue, - ) - .noShrink(); + ); const safeJsonObjectArb = fc.dictionary( fc.string().map((s) => s.replaceAll('__proto__', 'proto')), safeJsonValueArb, + { + noNullPrototype: true, + }, ) as fc.Arbitrary; const idArb = fc.oneof(fc.string(), fc.integer(), fc.constant(null)); @@ -99,106 +101,112 @@ const jsonRpcRequestMessageArb = ( method: fc.Arbitrary = fc.string(), params: fc.Arbitrary = safeJsonObjectArb, ) => - fc - .record( - { - jsonrpc: fc.constant('2.0'), - method: method, - params: params, - id: idArb, - }, - { - requiredKeys: ['jsonrpc', 'method', 'id'], - }, - ) - .noShrink() as fc.Arbitrary; + fc.record( + { + jsonrpc: fc.constant('2.0'), + method: method, + params: params, + id: idArb, + }, + { + requiredKeys: ['jsonrpc', 'method', 'id'], + noNullPrototype: true, + }, + ) as fc.Arbitrary; const jsonRpcRequestNotificationArb = ( method: fc.Arbitrary = fc.string(), params: fc.Arbitrary = safeJsonValueArb, ) => - fc - .record( - { - jsonrpc: fc.constant('2.0'), - method: method, - params: params, - }, - { - requiredKeys: ['jsonrpc', 'method'], - }, - ) - .noShrink() as fc.Arbitrary; + fc.record( + { + jsonrpc: fc.constant('2.0'), + method: method, + params: params, + }, + { + requiredKeys: ['jsonrpc', 'method'], + noNullPrototype: true, + }, + ) as fc.Arbitrary; const jsonRpcRequestArb = ( method: fc.Arbitrary = fc.string(), params: fc.Arbitrary = safeJsonObjectArb, ) => - fc - .oneof( - jsonRpcRequestMessageArb(method, params), - jsonRpcRequestNotificationArb(method, params), - ) - .noShrink() as fc.Arbitrary; + fc.oneof( + jsonRpcRequestMessageArb(method, params), + jsonRpcRequestNotificationArb(method, params), + ) as fc.Arbitrary; const JSONRPCResponseSuccessArb = ( result: fc.Arbitrary = safeJsonObjectArb, ) => - fc - .record({ + fc.record( + { jsonrpc: fc.constant('2.0'), result: result, id: idArb, - }) - .noShrink() as fc.Arbitrary; + }, + { + noNullPrototype: true, + }, + ) as fc.Arbitrary; const JSONRPCResponseErrorArb = ( error: fc.Arbitrary = fc.constant(new Error('test error')), ) => - fc - .record( - { - code: fc.constant(rpcErrors.JSONRPCResponseErrorCode.RPCRemote), - message: fc.string(), - data: error.map((e) => fromError(e)), - }, - { - requiredKeys: ['code', 'message', 'data'], - }, - ) - .noShrink() as fc.Arbitrary; + fc.record( + { + code: fc.constant(rpcErrors.JSONRPCResponseErrorCode.RPCRemote), + message: fc.string(), + data: error.map((e) => fromError(e)), + }, + { + requiredKeys: ['code', 'message', 'data'], + noNullPrototype: true, + }, + ) as fc.Arbitrary; const JSONRPCResponseFailedArb = (error?: fc.Arbitrary>) => - fc - .record({ + fc.record( + { jsonrpc: fc.constant('2.0'), error: JSONRPCResponseErrorArb(error), id: idArb, - }) - .noShrink() as fc.Arbitrary; + }, + { + noNullPrototype: true, + }, + ) as fc.Arbitrary; const jsonRpcResponseArb = ( result: fc.Arbitrary = safeJsonObjectArb, ) => - fc - .oneof(JSONRPCResponseSuccessArb(result), JSONRPCResponseFailedArb()) - .noShrink() as fc.Arbitrary; + fc.oneof( + JSONRPCResponseSuccessArb(result), + JSONRPCResponseFailedArb(), + ) as fc.Arbitrary; const jsonRpcMessageArb = ( method: fc.Arbitrary = fc.string(), params: fc.Arbitrary = safeJsonObjectArb, result: fc.Arbitrary = safeJsonObjectArb, ) => - fc - .oneof(jsonRpcRequestArb(method, params), jsonRpcResponseArb(result)) - .noShrink() as fc.Arbitrary; + fc.oneof( + jsonRpcRequestArb(method, params), + jsonRpcResponseArb(result), + ) as fc.Arbitrary; -const snippingPatternArb = fc - .array(fc.integer({ min: 1, max: 32 }), { minLength: 100, size: 'medium' }) - .noShrink(); +const snippingPatternArb = fc.noShrink( + fc.array(fc.integer({ min: 1, max: 32 }), { + minLength: 100, + size: 'medium', + }), +); -const jsonMessagesArb = fc - .array(jsonRpcRequestMessageArb(), { minLength: 2 }) - .noShrink(); +const jsonMessagesArb = fc.noShrink( + fc.array(jsonRpcRequestMessageArb(), { minLength: 2 }), +); const rawDataArb = fc.array(fc.uint8Array({ minLength: 1 }), { minLength: 1 }); @@ -286,6 +294,14 @@ const timeoutsArb = fc ), ); +async function toArray( + readabelStream: ReadableStream, +): Promise> { + const array: Array = []; + for await (const value of readabelStream) array.push(value); + return array; +} + export { binaryStreamToSnippedStream, binaryStreamToNoisyStream, @@ -308,4 +324,5 @@ export { createTapPairs, errorArb, timeoutsArb, + toArray, }; diff --git a/tsconfig.json b/tsconfig.json index a120436..2947129 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,14 +12,15 @@ "esModuleInterop": true, "allowSyntheticDefaultImports": true, "resolveJsonModule": true, - "moduleResolution": "node", - "module": "CommonJS", + "isolatedModules": true, + "moduleResolution": "NodeNext", + "module": "ESNext", "target": "ES2022", "baseUrl": "./src", "paths": { - "@": ["index"], - "@/*": ["*"] + "#*": ["*"] }, + "skipLibCheck": true, "noEmit": true }, "include": [ @@ -30,7 +31,7 @@ "./benches/**/*" ], "ts-node": { - "require": ["tsconfig-paths/register"], + "esm": true, "transpileOnly": true, "swc": true }